Release 4.76
[org-mode/org-tableheadings.git] / org.el
blob62a605ad079935aa39dd80d0c8d2001e45092bfd
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: 4.76
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 "4.76"
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 ;;; The custom variables
102 (defgroup org nil
103 "Outline-based notes management and organizer."
104 :tag "Org"
105 :group 'outlines
106 :group 'hypermedia
107 :group 'calendar)
109 (defgroup org-startup nil
110 "Options concerning startup of Org-mode."
111 :tag "Org Startup"
112 :group 'org)
114 (defcustom org-startup-folded t
115 "Non-nil means, entering Org-mode will switch to OVERVIEW.
116 This can also be configured on a per-file basis by adding one of
117 the following lines anywhere in the buffer:
119 #+STARTUP: fold
120 #+STARTUP: nofold
121 #+STARTUP: content"
122 :group 'org-startup
123 :type '(choice
124 (const :tag "nofold: show all" nil)
125 (const :tag "fold: overview" t)
126 (const :tag "content: all headlines" content)))
128 (defcustom org-startup-truncated t
129 "Non-nil means, entering Org-mode will set `truncate-lines'.
130 This is useful since some lines containing links can be very long and
131 uninteresting. Also tables look terrible when wrapped."
132 :group 'org-startup
133 :type 'boolean)
135 (defcustom org-startup-align-all-tables nil
136 "Non-nil means, align all tables when visiting a file.
137 This is useful when the column width in tables is forced with <N> cookies
138 in table fields. Such tables will look correct only after the first re-align.
139 This can also be configured on a per-file basis by adding one of
140 the following lines anywhere in the buffer:
141 #+STARTUP: align
142 #+STARTUP: noalign"
143 :group 'org-startup
144 :type 'boolean)
146 (defcustom org-insert-mode-line-in-empty-file nil
147 "Non-nil means insert the first line setting Org-mode in empty files.
148 When the function `org-mode' is called interactively in an empty file, this
149 normally means that the file name does not automatically trigger Org-mode.
150 To ensure that the file will always be in Org-mode in the future, a
151 line enforcing Org-mode will be inserted into the buffer, if this option
152 has been set."
153 :group 'org-startup
154 :type 'boolean)
156 (defcustom org-replace-disputed-keys nil
157 "Non-nil means use alternative key bindings for some keys.
158 Org-mode uses S-<cursor> keys for changing timestamps and priorities.
159 These keys are also used by other packages like `CUA-mode' or `windmove.el'.
160 If you want to use Org-mode together with one of these other modes,
161 or more generally if you would like to move some Org-mode commands to
162 other keys, set this variable and configure the keys with the variable
163 `org-disputed-keys'.
165 This option is only relevant at load-time of Org-mode, and must be set
166 *before* org.el is loaded. Changing it requires a restart of Emacs to
167 become effective."
168 :group 'org-startup
169 :type 'boolean)
171 (if (fboundp 'defvaralias)
172 (defvaralias 'org-CUA-compatible 'org-replace-disputed-keys))
174 (defcustom org-disputed-keys
175 '(([(shift up)] . [(meta p)])
176 ([(shift down)] . [(meta n)])
177 ([(shift left)] . [(meta -)])
178 ([(shift right)] . [(meta +)])
179 ([(control shift right)] . [(meta shift +)])
180 ([(control shift left)] . [(meta shift -)]))
181 "Keys for which Org-mode and other modes compete.
182 This is an alist, cars are the default keys, second element specifies
183 the alternative to use when `org-replace-disputed-keys' is t.
185 Keys can be specified in any syntax supported by `define-key'.
186 The value of this option takes effect only at Org-mode's startup,
187 therefore you'll have to restart Emacs to apply it after changing."
188 :group 'org-startup
189 :type 'alist)
191 (defun org-key (key)
192 "Select key according to `org-replace-disputed-keys' and `org-disputed-keys'.
193 Or return the original if not disputed."
194 (if org-replace-disputed-keys
195 (let* ((nkey (key-description key))
196 (x (org-find-if (lambda (x)
197 (equal (key-description (car x)) nkey))
198 org-disputed-keys)))
199 (if x (cdr x) key))
200 key))
202 (defun org-find-if (predicate seq)
203 (catch 'exit
204 (while seq
205 (if (funcall predicate (car seq))
206 (throw 'exit (car seq))
207 (pop seq)))))
209 (defun org-defkey (keymap key def)
210 "Define a key, possibly translated, as returned by `org-key'."
211 (define-key keymap (org-key key) def))
213 (defcustom org-ellipsis nil
214 "The ellipsis to use in the Org-mode outline.
215 When nil, just use the standard three dots. When a string, use that instead,
216 and just in Org-mode (which will then use its own display table).
217 Changing this requires executing `M-x org-mode' in a buffer to become
218 effective."
219 :group 'org-startup
220 :type '(choice (const :tag "Default" nil)
221 (string :tag "String" :value "...#")))
223 (defvar org-display-table nil
224 "The display table for org-mode, in case `org-ellipsis' is non-nil.")
226 (defgroup org-keywords nil
227 "Keywords in Org-mode."
228 :tag "Org Keywords"
229 :group 'org)
231 (defcustom org-deadline-string "DEADLINE:"
232 "String to mark deadline entries.
233 A deadline is this string, followed by a time stamp. Should be a word,
234 terminated by a colon. You can insert a schedule keyword and
235 a timestamp with \\[org-deadline].
236 Changes become only effective after restarting Emacs."
237 :group 'org-keywords
238 :type 'string)
240 (defcustom org-scheduled-string "SCHEDULED:"
241 "String to mark scheduled TODO entries.
242 A schedule is this string, followed by a time stamp. Should be a word,
243 terminated by a colon. You can insert a schedule keyword and
244 a timestamp with \\[org-schedule].
245 Changes become only effective after restarting Emacs."
246 :group 'org-keywords
247 :type 'string)
249 (defcustom org-closed-string "CLOSED:"
250 "String used as the prefix for timestamps logging closing a TODO entry."
251 :group 'org-keywords
252 :type 'string)
254 (defcustom org-clock-string "CLOCK:"
255 "String used as prefix for timestamps clocking work hours on an item."
256 :group 'org-keywords
257 :type 'string)
259 (defcustom org-comment-string "COMMENT"
260 "Entries starting with this keyword will never be exported.
261 An entry can be toggled between COMMENT and normal with
262 \\[org-toggle-comment].
263 Changes become only effective after restarting Emacs."
264 :group 'org-keywords
265 :type 'string)
267 (defcustom org-quote-string "QUOTE"
268 "Entries starting with this keyword will be exported in fixed-width font.
269 Quoting applies only to the text in the entry following the headline, and does
270 not extend beyond the next headline, even if that is lower level.
271 An entry can be toggled between QUOTE and normal with
272 \\[org-toggle-fixed-width-section]."
273 :group 'org-keywords
274 :type 'string)
276 (defconst org-repeat-re
277 (concat "\\(?:\\<\\(?:" org-scheduled-string "\\|" org-deadline-string "\\)"
278 " +<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [^>\n]*\\)\\(\\+[0-9]+[dwmy]\\)")
279 "Regular expression for specifying repeated events.
280 After a match, group 1 contains the repeat expression.")
282 (defgroup org-structure nil
283 "Options concerning the general structure of Org-mode files."
284 :tag "Org Structure"
285 :group 'org)
287 (defgroup org-reveal-location nil
288 "Options about how to make context of a location visible."
289 :tag "Org Reveal Location"
290 :group 'org-structure)
292 (defcustom org-show-hierarchy-above '((default . t))
293 "Non-nil means, show full hierarchy when revealing a location.
294 Org-mode often shows locations in an org-mode file which might have
295 been invisible before. When this is set, the hierarchy of headings
296 above the exposed location is shown.
297 Turning this off for example for sparse trees makes them very compact.
298 Instead of t, this can also be an alist specifying this option for different
299 contexts. Valid contexts are
300 agenda when exposing an entry from the agenda
301 org-goto when using the command `org-goto' on key C-c C-j
302 occur-tree when using the command `org-occur' on key C-c /
303 tags-tree when constructing a sparse tree based on tags matches
304 link-search when exposing search matches associated with a link
305 mark-goto when exposing the jump goal of a mark
306 bookmark-jump when exposing a bookmark location
307 isearch when exiting from an incremental search
308 default default for all contexts not set explicitly"
309 :group 'org-reveal-location
310 :type '(choice
311 (const :tag "Always" t)
312 (const :tag "Never" nil)
313 (repeat :greedy t :tag "Individual contexts"
314 (cons
315 (choice :tag "Context"
316 (const agenda)
317 (const org-goto)
318 (const occur-tree)
319 (const tags-tree)
320 (const link-search)
321 (const mark-goto)
322 (const bookmark-jump)
323 (const isearch)
324 (const default))
325 (boolean)))))
327 (defcustom org-show-following-heading '((default . t))
328 "Non-nil means, show following heading when revealing a location.
329 Org-mode often shows locations in an org-mode file which might have
330 been invisible before. When this is set, the heading following the
331 match is shown.
332 Turning this off for example for sparse trees makes them very compact,
333 but makes it harder to edit the location of the match. In such a case,
334 use the command \\[org-reveal] to show more context.
335 Instead of t, this can also be an alist specifying this option for different
336 contexts. See `org-show-hierarchy-above' for valid contexts."
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-siblings '((default . nil) (isearch t))
356 "Non-nil means, show all sibling 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 sibling of the current entry
359 heading are all made visible. If `org-show-hierarchy-above' is t,
360 the same happens on each level of the hierarchy above the current entry.
362 By default this is on for the isearch context, off for all other contexts.
363 Turning this off for example for sparse trees makes them very compact,
364 but makes it harder to edit the location of the match. In such a case,
365 use the command \\[org-reveal] to show more context.
366 Instead of t, this can also be an alist specifying this option for different
367 contexts. See `org-show-hierarchy-above' for valid contexts."
368 :group 'org-reveal-location
369 :type '(choice
370 (const :tag "Always" t)
371 (const :tag "Never" nil)
372 (repeat :greedy t :tag "Individual contexts"
373 (cons
374 (choice :tag "Context"
375 (const agenda)
376 (const org-goto)
377 (const occur-tree)
378 (const tags-tree)
379 (const link-search)
380 (const mark-goto)
381 (const bookmark-jump)
382 (const isearch)
383 (const default))
384 (boolean)))))
386 (defgroup org-cycle nil
387 "Options concerning visibility cycling in Org-mode."
388 :tag "Org Cycle"
389 :group 'org-structure)
391 (defcustom org-cycle-global-at-bob t
392 "Cycle globally if cursor is at beginning of buffer and not at a headline.
393 This makes it possible to do global cycling without having to use S-TAB or
394 C-u TAB. For this special case to work, the first line of the buffer
395 must not be a headline - it may be empty ot some other text. When used in
396 this way, `org-cycle-hook' is disables temporarily, to make sure the
397 cursor stays at the beginning of the buffer.
398 When this option is nil, don't do anything special at the beginning
399 of the buffer."
400 :group 'org-cycle
401 :type 'boolean)
403 (defcustom org-cycle-emulate-tab t
404 "Where should `org-cycle' emulate TAB.
405 nil Never
406 white Only in completely white lines
407 whitestart Only at the beginning of lines, before the first non-white char.
408 t Everywhere except in headlines
409 exc-hl-bol Everywhere except at the start of a headline
410 If TAB is used in a place where it does not emulate TAB, the current subtree
411 visibility is cycled."
412 :group 'org-cycle
413 :type '(choice (const :tag "Never" nil)
414 (const :tag "Only in completely white lines" white)
415 (const :tag "Before first char in a line" whitestart)
416 (const :tag "Everywhere except in headlines" t)
417 (const :tag "Everywhere except at bol in headlines" exc-hl-bol)
420 (defcustom org-cycle-separator-lines 2
421 "Number of empty lines needed to keep an empty line between collapsed trees.
422 If you leave an empty line between the end of a subtree and the following
423 headline, this empty line is hidden when the subtree is folded.
424 Org-mode will leave (exactly) one empty line visible if the number of
425 empty lines is equal or larger to the number given in this variable.
426 So the default 2 means, at least 2 empty lines after the end of a subtree
427 are needed to produce free space between a collapsed subtree and the
428 following headline.
430 Special case: when 0, never leave empty lines in collapsed view."
431 :group 'org-cycle
432 :type 'integer)
434 (defcustom org-cycle-hook '(org-cycle-hide-archived-subtrees
435 org-cycle-show-empty-lines
436 org-optimize-window-after-visibility-change)
437 "Hook that is run after `org-cycle' has changed the buffer visibility.
438 The function(s) in this hook must accept a single argument which indicates
439 the new state that was set by the most recent `org-cycle' command. The
440 argument is a symbol. After a global state change, it can have the values
441 `overview', `content', or `all'. After a local state change, it can have
442 the values `folded', `children', or `subtree'."
443 :group 'org-cycle
444 :type 'hook)
446 (defgroup org-edit-structure nil
447 "Options concerning structure editing in Org-mode."
448 :tag "Org Edit Structure"
449 :group 'org-structure)
451 (defcustom org-special-ctrl-a nil
452 "Non-nil means `C-a' behaves specially in headlines.
453 When set, `C-a' will bring back the cursor to the beginning of the
454 headline text, i.e. after the stars and after a possible TODO keyword.
455 When the cursor is already at that position, another `C-a' will bring
456 it to the beginning of the line."
457 :group 'org-edit-structure
458 :type 'boolean)
460 (defcustom org-odd-levels-only nil
461 "Non-nil means, skip even levels and only use odd levels for the outline.
462 This has the effect that two stars are being added/taken away in
463 promotion/demotion commands. It also influences how levels are
464 handled by the exporters.
465 Changing it requires restart of `font-lock-mode' to become effective
466 for fontification also in regions already fontified.
467 You may also set this on a per-file basis by adding one of the following
468 lines to the buffer:
470 #+STARTUP: odd
471 #+STARTUP: oddeven"
472 :group 'org-edit-structure
473 :group 'org-font-lock
474 :type 'boolean)
476 (defcustom org-adapt-indentation t
477 "Non-nil means, adapt indentation when promoting and demoting.
478 When this is set and the *entire* text in an entry is indented, the
479 indentation is increased by one space in a demotion command, and
480 decreased by one in a promotion command. If any line in the entry
481 body starts at column 0, indentation is not changed at all."
482 :group 'org-edit-structure
483 :type 'boolean)
485 (defcustom org-blank-before-new-entry '((heading . nil)
486 (plain-list-item . nil))
487 "Should `org-insert-heading' leave a blank line before new heading/item?
488 The value is an alist, with `heading' and `plain-list-item' as car,
489 and a boolean flag as cdr."
490 :group 'org-edit-structure
491 :type '(list
492 (cons (const heading) (boolean))
493 (cons (const plain-list-item) (boolean))))
495 (defcustom org-insert-heading-hook nil
496 "Hook being run after inserting a new heading."
497 :group 'org-edit-structure
498 :type 'boolean)
500 (defcustom org-enable-fixed-width-editor t
501 "Non-nil means, lines starting with \":\" are treated as fixed-width.
502 This currently only means, they are never auto-wrapped.
503 When nil, such lines will be treated like ordinary lines.
504 See also the QUOTE keyword."
505 :group 'org-edit-structure
506 :type 'boolean)
508 (defgroup org-sparse-trees nil
509 "Options concerning sparse trees in Org-mode."
510 :tag "Org Sparse Trees"
511 :group 'org-structure)
513 (defcustom org-highlight-sparse-tree-matches t
514 "Non-nil means, highlight all matches that define a sparse tree.
515 The highlights will automatically disappear the next time the buffer is
516 changed by an edit command."
517 :group 'org-sparse-trees
518 :type 'boolean)
520 (defcustom org-remove-highlights-with-change t
521 "Non-nil means, any change to the buffer will remove temporary highlights.
522 Such highlights are created by `org-occur' and `org-clock-display'.
523 When nil, `C-c C-c needs to be used to get rid of the highlights.
524 The highlights created by `org-preview-latex-fragment' always need
525 `C-c C-c' to be removed."
526 :group 'org-sparse-trees
527 :group 'org-time
528 :type 'boolean)
531 (defcustom org-occur-hook '(org-first-headline-recenter)
532 "Hook that is run after `org-occur' has constructed a sparse tree.
533 This can be used to recenter the window to show as much of the structure
534 as possible."
535 :group 'org-sparse-trees
536 :type 'hook)
538 (defgroup org-plain-lists nil
539 "Options concerning plain lists in Org-mode."
540 :tag "Org Plain lists"
541 :group 'org-structure)
543 (defcustom org-cycle-include-plain-lists nil
544 "Non-nil means, include plain lists into visibility cycling.
545 This means that during cycling, plain list items will *temporarily* be
546 interpreted as outline headlines with a level given by 1000+i where i is the
547 indentation of the bullet. In all other operations, plain list items are
548 not seen as headlines. For example, you cannot assign a TODO keyword to
549 such an item."
550 :group 'org-plain-lists
551 :type 'boolean)
553 (defcustom org-plain-list-ordered-item-terminator t
554 "The character that makes a line with leading number an ordered list item.
555 Valid values are ?. and ?\). To get both terminators, use t. While
556 ?. may look nicer, it creates the danger that a line with leading
557 number may be incorrectly interpreted as an item. ?\) therefore is
558 the safe choice."
559 :group 'org-plain-lists
560 :type '(choice (const :tag "dot like in \"2.\"" ?.)
561 (const :tag "paren like in \"2)\"" ?\))
562 (const :tab "both" t)))
564 (defcustom org-auto-renumber-ordered-lists t
565 "Non-nil means, automatically renumber ordered plain lists.
566 Renumbering happens when the sequence have been changed with
567 \\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands,
568 use \\[org-ctrl-c-ctrl-c] to trigger renumbering."
569 :group 'org-plain-lists
570 :type 'boolean)
572 (defcustom org-provide-checkbox-statistics t
573 "Non-nil means, update checkbox statistics after insert and toggle.
574 When this is set, checkbox statistics is updated each time you either insert
575 a new checkbox with \\[org-insert-todo-heading] or toggle a checkbox
576 with \\[org-ctrl-c-ctrl-c\\]."
577 :group 'org-plain-lists
578 :type 'boolean)
580 (defgroup org-archive nil
581 "Options concerning archiving in Org-mode."
582 :tag "Org Archive"
583 :group 'org-structure)
585 (defcustom org-archive-tag "ARCHIVE"
586 "The tag that marks a subtree as archived.
587 An archived subtree does not open during visibility cycling, and does
588 not contribute to the agenda listings."
589 :group 'org-archive
590 :group 'org-keywords
591 :type 'string)
593 (defcustom org-agenda-skip-archived-trees t
594 "Non-nil means, the agenda will skip any items located in archived trees.
595 An archived tree is a tree marked with the tag ARCHIVE."
596 :group 'org-archive
597 :group 'org-agenda-skip
598 :type 'boolean)
600 (defcustom org-cycle-open-archived-trees nil
601 "Non-nil means, `org-cycle' will open archived trees.
602 An archived tree is a tree marked with the tag ARCHIVE.
603 When nil, archived trees will stay folded. You can still open them with
604 normal outline commands like `show-all', but not with the cycling commands."
605 :group 'org-archive
606 :group 'org-cycle
607 :type 'boolean)
609 (defcustom org-sparse-tree-open-archived-trees nil
610 "Non-nil means sparse tree construction shows matches in archived trees.
611 When nil, matches in these trees are highlighted, but the trees are kept in
612 collapsed state."
613 :group 'org-archive
614 :group 'org-sparse-trees
615 :type 'boolean)
617 (defcustom org-archive-location "%s_archive::"
618 "The location where subtrees should be archived.
619 This string consists of two parts, separated by a double-colon.
621 The first part is a file name - when omitted, archiving happens in the same
622 file. %s will be replaced by the current file name (without directory part).
623 Archiving to a different file is useful to keep archived entries from
624 contributing to the Org-mode Agenda.
626 The part after the double colon is a headline. The archived entries will be
627 filed under that headline. When omitted, the subtrees are simply filed away
628 at the end of the file, as top-level entries.
630 Here are a few examples:
631 \"%s_archive::\"
632 If the current file is Projects.org, archive in file
633 Projects.org_archive, as top-level trees. This is the default.
635 \"::* Archived Tasks\"
636 Archive in the current file, under the top-level headline
637 \"* Archived Tasks\".
639 \"~/org/archive.org::\"
640 Archive in file ~/org/archive.org (absolute path), as top-level trees.
642 \"basement::** Finished Tasks\"
643 Archive in file ./basement (relative path), as level 3 trees
644 below the level 2 heading \"** Finished Tasks\".
646 You may set this option on a per-file basis by adding to the buffer a
647 line like
649 #+ARCHIVE: basement::** Finished Tasks"
650 :group 'org-archive
651 :type 'string)
653 (defcustom org-archive-mark-done t
654 "Non-nil means, mark entries as DONE when they are moved to the archive file."
655 :group 'org-archive
656 :type 'boolean)
658 (defcustom org-archive-stamp-time t
659 "Non-nil means, add a time stamp to entries moved to an archive file.
660 The time stamp will be added directly after the TODO state keyword in the
661 first line, so it is probably best to use this in combinations with
662 `org-archive-mark-done'."
663 :group 'org-archive
664 :type 'boolean)
666 (defgroup org-table nil
667 "Options concerning tables in Org-mode."
668 :tag "Org Table"
669 :group 'org)
671 (defcustom org-enable-table-editor 'optimized
672 "Non-nil means, lines starting with \"|\" are handled by the table editor.
673 When nil, such lines will be treated like ordinary lines.
675 When equal to the symbol `optimized', the table editor will be optimized to
676 do the following:
677 - Automatic overwrite mode in front of whitespace in table fields.
678 This makes the structure of the table stay in tact as long as the edited
679 field does not exceed the column width.
680 - Minimize the number of realigns. Normally, the table is aligned each time
681 TAB or RET are pressed to move to another field. With optimization this
682 happens only if changes to a field might have changed the column width.
683 Optimization requires replacing the functions `self-insert-command',
684 `delete-char', and `backward-delete-char' in Org-mode buffers, with a
685 slight (in fact: unnoticeable) speed impact for normal typing. Org-mode is
686 very good at guessing when a re-align will be necessary, but you can always
687 force one with \\[org-ctrl-c-ctrl-c].
689 If you would like to use the optimized version in Org-mode, but the
690 un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'.
692 This variable can be used to turn on and off the table editor during a session,
693 but in order to toggle optimization, a restart is required.
695 See also the variable `org-table-auto-blank-field'."
696 :group 'org-table
697 :type '(choice
698 (const :tag "off" nil)
699 (const :tag "on" t)
700 (const :tag "on, optimized" optimized)))
702 (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized)
703 "Non-nil means, use the optimized table editor version for `orgtbl-mode'.
704 In the optimized version, the table editor takes over all simple keys that
705 normally just insert a character. In tables, the characters are inserted
706 in a way to minimize disturbing the table structure (i.e. in overwrite mode
707 for empty fields). Outside tables, the correct binding of the keys is
708 restored.
710 The default for this option is t if the optimized version is also used in
711 Org-mode. See the variable `org-enable-table-editor' for details. Changing
712 this variable requires a restart of Emacs to become effective."
713 :group 'org-table
714 :type 'boolean)
716 (defcustom orgtbl-radio-table-templates
717 '((latex-mode "% BEGIN RECEIVE ORGTBL %n
718 % END RECEIVE ORGTBL %n
719 \\begin{comment}
720 #+ORGTBL: SEND %n orgtbl-to-latex :splice nil :skip 0
721 | | |
722 \\end{comment}\n")
723 (texinfo-mode "@c BEGIN RECEIVE ORGTBL %n
724 @c END RECEIVE ORGTBL %n
725 @ignore
726 #+ORGTBL: SEND %n orgtbl-to-html :splice nil :skip 0
727 | | |
728 @end ignore\n")
729 (html-mode "<!-- BEGIN RECEIVE ORGTBL %n -->
730 <!-- END RECEIVE ORGTBL %n -->
731 <!--
732 #+ORGTBL: SEND %n orgtbl-to-html :splice nil :skip 0
733 | | |
734 -->\n"))
735 "Templates for radio tables in different major modes.
736 All occurrences of %n in a template will be replaced with the name of the
737 table, obtained by prompting the user."
738 :group 'org-table
739 :type '(repeat
740 (list (symbol :tag "Major mode")
741 (string :tag "Format"))))
743 (defgroup org-table-settings nil
744 "Settings for tables in Org-mode."
745 :tag "Org Table Settings"
746 :group 'org-table)
748 (defcustom org-table-default-size "5x2"
749 "The default size for newly created tables, Columns x Rows."
750 :group 'org-table-settings
751 :type 'string)
753 (defcustom org-table-number-regexp
754 "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%:]*\\|\\(0[xX]\\)[0-9a-fA-F]+\\)$"
755 "Regular expression for recognizing numbers in table columns.
756 If a table column contains mostly numbers, it will be aligned to the
757 right. If not, it will be aligned to the left.
759 The default value of this option is a regular expression which allows
760 anything which looks remotely like a number as used in scientific
761 context. For example, all of the following will be considered a
762 number:
763 12 12.2 2.4e-08 2x10^12 4.034+-0.02 2.7(10) >3.5
765 Other options offered by the customize interface are more restrictive."
766 :group 'org-table-settings
767 :type '(choice
768 (const :tag "Positive Integers"
769 "^[0-9]+$")
770 (const :tag "Integers"
771 "^[-+]?[0-9]+$")
772 (const :tag "Floating Point Numbers"
773 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.[0-9]*\\)$")
774 (const :tag "Floating Point Number or Integer"
775 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.?[0-9]*\\)$")
776 (const :tag "Exponential, Floating point, Integer"
777 "^[-+]?[0-9.]+\\([eEdD][-+0-9]+\\)?$")
778 (const :tag "Very General Number-Like, including hex"
779 "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*\\|\\(0[xX]\\)[0-9a-fA-F]+\\)$")
780 (string :tag "Regexp:")))
782 (defcustom org-table-number-fraction 0.5
783 "Fraction of numbers in a column required to make the column align right.
784 In a column all non-white fields are considered. If at least this
785 fraction of fields is matched by `org-table-number-fraction',
786 alignment to the right border applies."
787 :group 'org-table-settings
788 :type 'number)
790 (defgroup org-table-editing nil
791 "Bahavior of tables during editing in Org-mode."
792 :tag "Org Table Editing"
793 :group 'org-table)
795 (defcustom org-table-automatic-realign t
796 "Non-nil means, automatically re-align table when pressing TAB or RETURN.
797 When nil, aligning is only done with \\[org-table-align], or after column
798 removal/insertion."
799 :group 'org-table-editing
800 :type 'boolean)
802 (defcustom org-table-auto-blank-field t
803 "Non-nil means, automatically blank table field when starting to type into it.
804 This only happens when typing immediately after a field motion
805 command (TAB, S-TAB or RET).
806 Only relevant when `org-enable-table-editor' is equal to `optimized'."
807 :group 'org-table-editing
808 :type 'boolean)
810 (defcustom org-table-tab-jumps-over-hlines t
811 "Non-nil means, tab in the last column of a table with jump over a hline.
812 If a horizontal separator line is following the current line,
813 `org-table-next-field' can either create a new row before that line, or jump
814 over the line. When this option is nil, a new line will be created before
815 this line."
816 :group 'org-table-editing
817 :type 'boolean)
819 (defcustom org-table-tab-recognizes-table.el t
820 "Non-nil means, TAB will automatically notice a table.el table.
821 When it sees such a table, it moves point into it and - if necessary -
822 calls `table-recognize-table'."
823 :group 'org-table-editing
824 :type 'boolean)
826 (defgroup org-table-calculation nil
827 "Options concerning tables in Org-mode."
828 :tag "Org Table Calculation"
829 :group 'org-table)
831 (defcustom org-table-use-standard-references t
832 "Should org-mode work with table refrences like B3 instead of @3$2?
833 Possible values are:
834 nil never use them
835 from accept as input, do not present for editing
836 t: accept as input and present for editing"
837 :group 'org-table-calculation
838 :type '(choice
839 (const :tag "Never, don't even check unser input for them" nil)
840 (const :tag "Always, both as user input, and when editing" t)
841 (const :tag "Conver user input, don't offerr during editing" 'from)))
843 (defcustom org-table-copy-increment t
844 "Non-nil means, increment when copying current field with \\[org-table-copy-down]."
845 :group 'org-table-calculation
846 :type 'boolean)
848 (defcustom org-calc-default-modes
849 '(calc-internal-prec 12
850 calc-float-format (float 5)
851 calc-angle-mode deg
852 calc-prefer-frac nil
853 calc-symbolic-mode nil
854 calc-date-format (YYYY "-" MM "-" DD " " Www (" " HH ":" mm))
855 calc-display-working-message t
857 "List with Calc mode settings for use in calc-eval for table formulas.
858 The list must contain alternating symbols (Calc modes variables and values).
859 Don't remove any of the default settings, just change the values. Org-mode
860 relies on the variables to be present in the list."
861 :group 'org-table-calculation
862 :type 'plist)
864 (defcustom org-table-formula-evaluate-inline t
865 "Non-nil means, TAB and RET evaluate a formula in current table field.
866 If the current field starts with an equal sign, it is assumed to be a formula
867 which should be evaluated as described in the manual and in the documentation
868 string of the command `org-table-eval-formula'. This feature requires the
869 Emacs calc package.
870 When this variable is nil, formula calculation is only available through
871 the command \\[org-table-eval-formula]."
872 :group 'org-table-calculation
873 :type 'boolean)
875 (defcustom org-table-formula-use-constants t
876 "Non-nil means, interpret constants in formulas in tables.
877 A constant looks like `$c' or `$Grav' and will be replaced before evaluation
878 by the value given in `org-table-formula-constants', or by a value obtained
879 from the `constants.el' package."
880 :group 'org-table-calculation
881 :type 'boolean)
883 ;; FIXME this is also a variable that makes Org-mode files non-portable
884 ;; Maybe I should have a #+ options for constants?
885 (defcustom org-table-formula-constants nil
886 "Alist with constant names and values, for use in table formulas.
887 The car of each element is a name of a constant, without the `$' before it.
888 The cdr is the value as a string. For example, if you'd like to use the
889 speed of light in a formula, you would configure
891 (setq org-table-formula-constants '((\"c\" . \"299792458.\")))
893 and then use it in an equation like `$1*$c'."
894 :group 'org-table-calculation
895 :type '(repeat
896 (cons (string :tag "name")
897 (string :tag "value"))))
899 (defcustom org-table-allow-automatic-line-recalculation t
900 "Non-nil means, lines marked with |#| or |*| will be recomputed automatically.
901 Automatically means, when TAB or RET or C-c C-c are pressed in the line."
902 :group 'org-table-calculation
903 :type 'boolean)
905 (defgroup org-link nil
906 "Options concerning links in Org-mode."
907 :tag "Org Link"
908 :group 'org)
910 (defvar org-link-abbrev-alist-local nil
911 "Buffer-local version of `org-link-abbrev-alist', which see.
912 The value of this is taken from the #+LINK lines.")
913 (make-variable-buffer-local 'org-link-abbrev-alist-local)
915 (defcustom org-link-abbrev-alist nil
916 "Alist of link abbreviations.
917 The car of each element is a string, to be replaced at the start of a link.
918 The cdrs are replacement values, like (\"linkkey\" . REPLACE). Abbreviated
919 links in Org-mode buffers can have an optional tag after a double colon, e.g.
921 [[linkkey:tag][description]]
923 If REPLACE is a string, the tag will simply be appended to create the link.
924 If the string contains \"%s\", the tag will be inserted there. REPLACE may
925 also be a function that will be called with the tag as the only argument to
926 create the link. See the manual for examples."
927 :group 'org-link
928 :type 'alist)
930 (defcustom org-descriptive-links t
931 "Non-nil means, hide link part and only show description of bracket links.
932 Bracket links are like [[link][descritpion]]. This variable sets the initial
933 state in new org-mode buffers. The setting can then be toggled on a
934 per-buffer basis from the Org->Hyperlinks menu."
935 :group 'org-link
936 :type 'boolean)
938 (defcustom org-link-file-path-type 'adaptive
939 "How the path name in file links should be stored.
940 Valid values are:
942 relative relative to the current directory, i.e. the directory of the file
943 into which the link is being inserted.
944 absolute absolute path, if possible with ~ for home directory.
945 noabbrev absolute path, no abbreviation of home directory.
946 adaptive Use relative path for files in the current directory and sub-
947 directories of it. For other files, use an absolute path."
948 :group 'org-link
949 :type '(choice
950 (const relative)
951 (const absolute)
952 (const noabbrev)
953 (const adaptive)))
955 (defcustom org-activate-links '(bracket angle plain radio tag date)
956 "Types of links that should be activated in Org-mode files.
957 This is a list of symbols, each leading to the activation of a certain link
958 type. In principle, it does not hurt to turn on most link types - there may
959 be a small gain when turning off unused link types. The types are:
961 bracket The recommended [[link][description]] or [[link]] links with hiding.
962 angular Links in angular brackes that may contain whitespace like
963 <bbdb:Carsten Dominik>.
964 plain Plain links in normal text, no whitespace, like http://google.com.
965 radio Text that is matched by a radio target, see manual for details.
966 tag Tag settings in a headline (link to tag search).
967 date Time stamps (link to calendar).
969 Changing this variable requires a restart of Emacs to become effective."
970 :group 'org-link
971 :type '(set (const :tag "Double bracket links (new style)" bracket)
972 (const :tag "Angular bracket links (old style)" angular)
973 (const :tag "plain text links" plain)
974 (const :tag "Radio target matches" radio)
975 (const :tag "Tags" tag)
976 (const :tag "Timestamps" date)))
978 (defgroup org-link-store nil
979 "Options concerning storing links in Org-mode"
980 :tag "Org Store Link"
981 :group 'org-link)
983 (defcustom org-email-link-description-format "Email %c: %.30s"
984 "Format of the description part of a link to an email or usenet message.
985 The following %-excapes will be replaced by corresponding information:
987 %F full \"From\" field
988 %f name, taken from \"From\" field, address if no name
989 %T full \"To\" field
990 %t first name in \"To\" field, address if no name
991 %c correspondent. Unually \"from NAME\", but if you sent it yourself, it
992 will be \"to NAME\". See also the variable `org-from-is-user-regexp'.
993 %s subject
994 %m message-id.
996 You may use normal field width specification between the % and the letter.
997 This is for example useful to limit the length of the subject.
999 Examples: \"%f on: %.30s\", \"Email from %f\", \"Email %c\""
1000 :group 'org-link-store
1001 :type 'string)
1003 (defcustom org-from-is-user-regexp
1004 (let (r1 r2)
1005 (when (and user-mail-address (not (string= user-mail-address "")))
1006 (setq r1 (concat "\\<" (regexp-quote user-mail-address) "\\>")))
1007 (when (and user-full-name (not (string= user-full-name "")))
1008 (setq r2 (concat "\\<" (regexp-quote user-full-name) "\\>")))
1009 (if (and r1 r2) (concat r1 "\\|" r2) (or r1 r2)))
1010 "Regexp mached against the \"From:\" header of an email or usenet message.
1011 It should match if the message is from the user him/herself."
1012 :group 'org-link-store
1013 :type 'regexp)
1015 (defcustom org-context-in-file-links t
1016 "Non-nil means, file links from `org-store-link' contain context.
1017 A search string will be added to the file name with :: as separator and
1018 used to find the context when the link is activated by the command
1019 `org-open-at-point'.
1020 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
1021 negates this setting for the duration of the command."
1022 :group 'org-link-store
1023 :type 'boolean)
1025 (defcustom org-keep-stored-link-after-insertion nil
1026 "Non-nil means, keep link in list for entire session.
1028 The command `org-store-link' adds a link pointing to the current
1029 location to an internal list. These links accumulate during a session.
1030 The command `org-insert-link' can be used to insert links into any
1031 Org-mode file (offering completion for all stored links). When this
1032 option is nil, every link which has been inserted once using \\[org-insert-link]
1033 will be removed from the list, to make completing the unused links
1034 more efficient."
1035 :group 'org-link-store
1036 :type 'boolean)
1038 (defcustom org-usenet-links-prefer-google nil
1039 "Non-nil means, `org-store-link' will create web links to Google groups.
1040 When nil, Gnus will be used for such links.
1041 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
1042 negates this setting for the duration of the command."
1043 :group 'org-link-store
1044 :type 'boolean)
1046 (defgroup org-link-follow nil
1047 "Options concerning following links in Org-mode"
1048 :tag "Org Follow Link"
1049 :group 'org-link)
1051 (defcustom org-tab-follows-link nil
1052 "Non-nil means, on links TAB will follow the link.
1053 Needs to be set before org.el is loaded."
1054 :group 'org-link-follow
1055 :type 'boolean)
1057 (defcustom org-return-follows-link nil
1058 "Non-nil means, on links RET will follow the link.
1059 Needs to be set before org.el is loaded."
1060 :group 'org-link-follow
1061 :type 'boolean)
1063 (defcustom org-mouse-1-follows-link t
1064 "Non-nil means, mouse-1 on a link will follow the link.
1065 A longer mouse click will still set point. Does not wortk on XEmacs.
1066 Needs to be set before org.el is loaded."
1067 :group 'org-link-follow
1068 :type 'boolean)
1070 (defcustom org-mark-ring-length 4
1071 "Number of different positions to be recorded in the ring
1072 Changing this requires a restart of Emacs to work correctly."
1073 :group 'org-link-follow
1074 :type 'interger)
1076 (defcustom org-link-frame-setup
1077 '((vm . vm-visit-folder-other-frame)
1078 (gnus . gnus-other-frame)
1079 (file . find-file-other-window))
1080 "Setup the frame configuration for following links.
1081 When following a link with Emacs, it may often be useful to display
1082 this link in another window or frame. This variable can be used to
1083 set this up for the different types of links.
1084 For VM, use any of
1085 `vm-visit-folder'
1086 `vm-visit-folder-other-frame'
1087 For Gnus, use any of
1088 `gnus'
1089 `gnus-other-frame'
1090 For FILE, use any of
1091 `find-file'
1092 `find-file-other-window'
1093 `find-file-other-frame'
1094 For the calendar, use the variable `calendar-setup'.
1095 For BBDB, it is currently only possible to display the matches in
1096 another window."
1097 :group 'org-link-follow
1098 :type '(list
1099 (cons (const vm)
1100 (choice
1101 (const vm-visit-folder)
1102 (const vm-visit-folder-other-window)
1103 (const vm-visit-folder-other-frame)))
1104 (cons (const gnus)
1105 (choice
1106 (const gnus)
1107 (const gnus-other-frame)))
1108 (cons (const file)
1109 (choice
1110 (const find-file)
1111 (const find-file-other-window)
1112 (const find-file-other-frame)))))
1114 (defcustom org-display-internal-link-with-indirect-buffer nil
1115 "Non-nil means, use indirect buffer to display infile links.
1116 Activating internal links (from one location in a file to another location
1117 in the same file) normally just jumps to the location. When the link is
1118 activated with a C-u prefix (or with mouse-3), the link is displayed in
1119 another window. When this option is set, the other window actually displays
1120 an indirect buffer clone of the current buffer, to avoid any visibility
1121 changes to the current buffer."
1122 :group 'org-link-follow
1123 :type 'boolean)
1125 (defcustom org-open-non-existing-files nil
1126 "Non-nil means, `org-open-file' will open non-existing files.
1127 When nil, an error will be generated."
1128 :group 'org-link-follow
1129 :type 'boolean)
1131 (defcustom org-link-mailto-program '(browse-url "mailto:%a?subject=%s")
1132 "Function and arguments to call for following mailto links.
1133 This is a list with the first element being a lisp function, and the
1134 remaining elements being arguments to the function. In string arguments,
1135 %a will be replaced by the address, and %s will be replaced by the subject
1136 if one was given like in <mailto:arthur@galaxy.org::this subject>."
1137 :group 'org-link-follow
1138 :type '(choice
1139 (const :tag "browse-url" (browse-url-mail "mailto:%a?subject=%s"))
1140 (const :tag "compose-mail" (compose-mail "%a" "%s"))
1141 (const :tag "message-mail" (message-mail "%a" "%s"))
1142 (cons :tag "other" (function) (repeat :tag "argument" sexp))))
1144 (defcustom org-confirm-shell-link-function 'yes-or-no-p
1145 "Non-nil means, ask for confirmation before executing shell links.
1146 Shell links can be dangerous, just thing about a link
1148 [[shell:rm -rf ~/*][Google Search]]
1150 This link would show up in your Org-mode document as \"Google Search\"
1151 but really it would remove your entire home directory.
1152 Therefore I *definitely* advise against setting this variable to nil.
1153 Just change it to `y-or-n-p' of you want to confirm with a single key press
1154 rather than having to type \"yes\"."
1155 :group 'org-link-follow
1156 :type '(choice
1157 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1158 (const :tag "with y-or-n (faster)" y-or-n-p)
1159 (const :tag "no confirmation (dangerous)" nil)))
1161 (defcustom org-confirm-elisp-link-function 'yes-or-no-p
1162 "Non-nil means, ask for confirmation before executing elisp links.
1163 Elisp links can be dangerous, just think about a link
1165 [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]]
1167 This link would show up in your Org-mode document as \"Google Search\"
1168 but really it would remove your entire home directory.
1169 Therefore I *definitely* advise against setting this variable to nil.
1170 Just change it to `y-or-n-p' of you want to confirm with a single key press
1171 rather than having to type \"yes\"."
1172 :group 'org-link-follow
1173 :type '(choice
1174 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1175 (const :tag "with y-or-n (faster)" y-or-n-p)
1176 (const :tag "no confirmation (dangerous)" nil)))
1178 (defconst org-file-apps-defaults-gnu
1179 '((remote . emacs)
1180 (t . mailcap))
1181 "Default file applications on a UNIX or GNU/Linux system.
1182 See `org-file-apps'.")
1184 (defconst org-file-apps-defaults-macosx
1185 '((remote . emacs)
1186 (t . "open %s")
1187 ("ps" . "gv %s")
1188 ("ps.gz" . "gv %s")
1189 ("eps" . "gv %s")
1190 ("eps.gz" . "gv %s")
1191 ("dvi" . "xdvi %s")
1192 ("fig" . "xfig %s"))
1193 "Default file applications on a MacOS X system.
1194 The system \"open\" is known as a default, but we use X11 applications
1195 for some files for which the OS does not have a good default.
1196 See `org-file-apps'.")
1198 (defconst org-file-apps-defaults-windowsnt
1199 (list
1200 '(remote . emacs)
1201 (cons t
1202 (list (if (featurep 'xemacs)
1203 'mswindows-shell-execute
1204 'w32-shell-execute)
1205 "open" 'file)))
1206 "Default file applications on a Windows NT system.
1207 The system \"open\" is used for most files.
1208 See `org-file-apps'.")
1210 (defcustom org-file-apps
1212 ("txt" . emacs)
1213 ("tex" . emacs)
1214 ("ltx" . emacs)
1215 ("org" . emacs)
1216 ("el" . emacs)
1217 ("bib" . emacs)
1219 "External applications for opening `file:path' items in a document.
1220 Org-mode uses system defaults for different file types, but
1221 you can use this variable to set the application for a given file
1222 extension. The entries in this list are cons cells where the car identifies
1223 files and the cdr the corresponding command. Possible values for the
1224 file identifier are
1225 \"ext\" A string identifying an extension
1226 `directory' Matches a directory
1227 `remote' Matches a remote file, accessible through tramp or efs.
1228 Remote files most likely should be visited through Emacs
1229 because external applications cannot handle such paths.
1230 t Default for all remaining files
1232 Possible values for the command are:
1233 `emacs' The file will be visited by the current Emacs process.
1234 `default' Use the default application for this file type.
1235 string A command to be executed by a shell; %s will be replaced
1236 by the path to the file.
1237 sexp A Lisp form which will be evaluated. The file path will
1238 be available in the Lisp variable `file'.
1239 For more examples, see the system specific constants
1240 `org-file-apps-defaults-macosx'
1241 `org-file-apps-defaults-windowsnt'
1242 `org-file-apps-defaults-gnu'."
1243 :group 'org-link-follow
1244 :type '(repeat
1245 (cons (choice :value ""
1246 (string :tag "Extension")
1247 (const :tag "Default for unrecognized files" t)
1248 (const :tag "Remote file" remote)
1249 (const :tag "Links to a directory" directory))
1250 (choice :value ""
1251 (const :tag "Visit with Emacs" emacs)
1252 (const :tag "Use system default" default)
1253 (string :tag "Command")
1254 (sexp :tag "Lisp form")))))
1256 (defcustom org-mhe-search-all-folders nil
1257 "Non-nil means, that the search for the mh-message will be extended to
1258 all folders if the message cannot be found in the folder given in the link.
1259 Searching all folders is very efficient with one of the search engines
1260 supported by MH-E, but will be slow with pick."
1261 :group 'org-link-follow
1262 :type 'boolean)
1264 (defgroup org-remember nil
1265 "Options concerning interaction with remember.el."
1266 :tag "Org Remember"
1267 :group 'org)
1269 (defcustom org-directory "~/org"
1270 "Directory with org files.
1271 This directory will be used as default to prompt for org files.
1272 Used by the hooks for remember.el."
1273 :group 'org-remember
1274 :type 'directory)
1276 (defcustom org-default-notes-file "~/.notes"
1277 "Default target for storing notes.
1278 Used by the hooks for remember.el. This can be a string, or nil to mean
1279 the value of `remember-data-file'.
1280 You can set this on a per-template basis with the variable
1281 `org-remember-templates'."
1282 :group 'org-remember
1283 :type '(choice
1284 (const :tag "Default from remember-data-file" nil)
1285 file))
1287 (defcustom org-remember-default-headline ""
1288 "The headline that should be the default location in the notes file.
1289 When filing remember notes, the cursor will start at that position.
1290 You can set this on a per-template basis with the variable
1291 `org-remember-templates'."
1292 :group 'org-remember
1293 :type 'string)
1295 (defcustom org-remember-templates nil
1296 "Templates for the creation of remember buffers.
1297 When nil, just let remember make the buffer.
1298 When not nil, this is a list of 4-element lists. In each entry, the first
1299 element is a character, a unique key to select this template.
1300 The second element is the template. The third element is optional and can
1301 specify a destination file for remember items created with this template.
1302 The default file is given by `org-default-notes-file'. An optional third
1303 element can specify the headline in that file that should be offered
1304 first when the user is asked to file the entry. The default headline is
1305 given in the variable `org-remember-default-headline'.
1307 The template specifies the structure of the remember buffer. It should have
1308 a first line starting with a star, to act as the org-mode headline.
1309 Furthermore, the following %-escapes will be replaced with content:
1311 %^{prompt} prompt the user for a string and replace this sequence with it.
1312 %t time stamp, date only
1313 %T time stamp with date and time
1314 %u, %U like the above, but inactive time stamps
1315 %^t like %t, but prompt for date. Similarly %^T, %^u, %^U
1316 You may define a prompt like %^{Please specify birthday}t
1317 %n user name (taken from `user-full-name')
1318 %a annotation, normally the link created with org-store-link
1319 %i initial content, the region when remember is called with C-u.
1320 If %i is indented, the entire inserted text will be indented
1321 as well.
1323 %? After completing the template, position cursor here.
1325 Apart from these general escapes, you can access information specific to the
1326 link type that is created. For example, calling `remember' in emails or gnus
1327 will record the author and the subject of the message, which you can access
1328 with %:author and %:subject, respectively. Here is a complete list of what
1329 is recorded for each link type.
1331 Link type | Available information
1332 -------------------+------------------------------------------------------
1333 bbdb | %:type %:name %:company
1334 vm, wl, mh, rmail | %:type %:subject %:message-id
1335 | %:from %:fromname %:fromaddress
1336 | %:to %:toname %:toaddress
1337 | %:fromto (either \"to NAME\" or \"from NAME\")
1338 gnus | %:group, for messages also all email fields
1339 w3, w3m | %:type %:url
1340 info | %:type %:file %:node
1341 calendar | %:type %:date"
1342 :group 'org-remember
1343 :get (lambda (var) ; Make sure all entries have 4 elements
1344 (mapcar (lambda (x)
1345 (cond ((= (length x) 3) (append x '("")))
1346 ((= (length x) 2) (append x '("" "")))
1347 (t x)))
1348 (default-value var)))
1349 :type '(repeat
1350 :tag "enabled"
1351 (list :value (?a "\n" nil nil)
1352 (character :tag "Selection Key")
1353 (string :tag "Template")
1354 (file :tag "Destination file (optional)")
1355 (string :tag "Destination headline (optional)"))))
1357 (defcustom org-reverse-note-order nil
1358 "Non-nil means, store new notes at the beginning of a file or entry.
1359 When nil, new notes will be filed to the end of a file or entry."
1360 :group 'org-remember
1361 :type '(choice
1362 (const :tag "Reverse always" t)
1363 (const :tag "Reverse never" nil)
1364 (repeat :tag "By file name regexp"
1365 (cons regexp boolean))))
1367 (defgroup org-todo nil
1368 "Options concerning TODO items in Org-mode."
1369 :tag "Org TODO"
1370 :group 'org)
1372 (defgroup org-progress nil
1373 "Options concerning Progress logging in Org-mode."
1374 :tag "Org Progress"
1375 :group 'org-time)
1377 (defcustom org-todo-keywords '((sequence "TODO" "DONE"))
1378 "List of TODO entry keyword sequences and their interpretation.
1379 \\<org-mode-map>This is a list of sequences.
1381 Each sequence starts with a symbol, either `sequence' or `type',
1382 indicating if the keywords should be interpreted as a sequence of
1383 action steps, or as different types of TODO items. The first
1384 keywords are states requiring action - these states will select a headline
1385 for inclusion into the global TODO list Org-mode produces. If one of
1386 the \"keywords\" is the vertical bat \"|\" the remaining keywords
1387 signify that no further action is necessary. If \"|\" is not found,
1388 the last keyword is treated as the only DONE state of the sequence.
1390 The command \\[org-todo] cycles an entry through these states, and one
1391 additional state where no keyword is present. For details about this
1392 cycling, see the manual.
1394 TODO keywords and interpretation can also be set on a per-file basis with
1395 the special #+SEQ_TODO and #+TYP_TODO lines.
1397 For backward compatibility, this variable may also be just a list
1398 of keywords - in this case the interptetation (sequence or type) will be
1399 taken from the (otherwise obsolete) variable `org-todo-interpretation'."
1400 :group 'org-todo
1401 :group 'org-keywords
1402 :type '(choice
1403 (repeat :tag "Old syntax, just keywords"
1404 (string :tag "Keyword"))
1405 (repeat :tag "New syntax"
1406 (cons
1407 (choice
1408 :tag "Interpretation"
1409 (const :tag "Sequence (cycling hits every state)" sequence)
1410 (const :tag "Type (cycling directly to DONE)" type))
1411 (repeat
1412 (string :tag "Keyword"))))))
1414 (defvar org-todo-keywords-1 nil)
1415 (make-variable-buffer-local 'org-todo-keywords-1)
1416 (defvar org-todo-keywords-for-agenda nil)
1417 (defvar org-done-keywords-for-agenda nil)
1418 (defvar org-not-done-keywords nil)
1419 (make-variable-buffer-local 'org-not-done-keywords)
1420 (defvar org-done-keywords nil)
1421 (make-variable-buffer-local 'org-done-keywords)
1422 (defvar org-todo-heads nil)
1423 (make-variable-buffer-local 'org-todo-heads)
1424 (defvar org-todo-sets nil)
1425 (make-variable-buffer-local 'org-todo-sets)
1426 (defvar org-todo-kwd-alist nil)
1427 (make-variable-buffer-local 'org-todo-kwd-alist)
1429 (defcustom org-todo-interpretation 'sequence
1430 "Controls how TODO keywords are interpreted.
1431 This variable is in principle obsolete and is only used for
1432 backward compatibility, if the interpretation of todo keywords is
1433 not given already in `org-todo-keywords'. See that variable for
1434 more information."
1435 :group 'org-todo
1436 :group 'org-keywords
1437 :type '(choice (const sequence)
1438 (const type)))
1440 (defcustom org-after-todo-state-change-hook nil
1441 "Hook which is run after the state of a TODO item was changed.
1442 The new state (a string with a TODO keyword, or nil) is available in the
1443 Lisp variable `state'."
1444 :group 'org-todo
1445 :type 'hook)
1447 (defcustom org-log-done nil
1448 "When set, insert a (non-active) time stamp when TODO entry is marked DONE.
1449 When the state of an entry is changed from nothing to TODO, remove a previous
1450 closing date.
1452 This can also be a list of symbols indicating under which conditions
1453 the time stamp recording the action should be annotated with a short note.
1454 Valid members of this list are
1456 done Offer to record a note when marking entries done
1457 state Offer to record a note whenever changing the TODO state
1458 of an item. This is only relevant if TODO keywords are
1459 interpreted as sequence, see variable `org-todo-interpretation'.
1460 When `state' is set, this includes tracking `done'.
1461 clock-out Offer to record a note when clocking out of an item.
1463 A separate window will then pop up and allow you to type a note.
1464 After finishing with C-c C-c, the note will be added directly after the
1465 timestamp, as a plain list item. See also the variable
1466 `org-log-note-headings'.
1468 Logging can also be configured on a per-file basis by adding one of
1469 the following lines anywhere in the buffer:
1471 #+STARTUP: logdone
1472 #+STARTUP: nologging
1473 #+STARTUP: lognotedone
1474 #+STARTUP: lognotestate
1475 #+STARTUP: lognoteclock-out"
1476 :group 'org-todo
1477 :group 'org-progress
1478 :type '(choice
1479 (const :tag "off" nil)
1480 (const :tag "on" t)
1481 (set :tag "on, with notes, detailed control" :greedy t :value (done)
1482 (const :tag "when item is marked DONE" done)
1483 (const :tag "when TODO state changes" state)
1484 (const :tag "when clocking out" clock-out))))
1486 (defcustom org-log-done-with-time t
1487 "Non-nil means, the CLOSED time stamp will contain date and time.
1488 When nil, only the date will be recorded."
1489 :group 'org-progress
1490 :type 'boolean)
1492 (defcustom org-log-note-headings
1493 '((done . "CLOSING NOTE %t")
1494 (state . "State %-12s %t")
1495 (clock-out . ""))
1496 "Headings for notes added when clocking out or closing TODO items.
1497 The value is an alist, with the car being a sympol indicating the note
1498 context, and the cdr is the heading to be used. The heading may also be the
1499 empty string.
1500 %t in the heading will be replaced by a time stamp.
1501 %s will be replaced by the new TODO state, in double quotes.
1502 %u will be replaced by the user name.
1503 %U will be replaced by the full user name."
1504 :group 'org-todo
1505 :group 'org-progress
1506 :type '(list :greedy t
1507 (cons (const :tag "Heading when closing an item" done) string)
1508 (cons (const :tag
1509 "Heading when changing todo state (todo sequence only)"
1510 state) string)
1511 (cons (const :tag "Heading when clocking out" clock-out) string)))
1513 (defcustom org-log-repeat t
1514 "Non-nil means, prompt for a note when REPEAT is resetting a TODO entry.
1515 When nil, no note will be taken."
1516 :group 'org-todo
1517 :group 'org-progress
1518 :type 'boolean)
1520 (defgroup org-priorities nil
1521 "Priorities in Org-mode."
1522 :tag "Org Priorities"
1523 :group 'org-todo)
1525 (defcustom org-highest-priority ?A
1526 "The highest priority of TODO items. A character like ?A, ?B etc.
1527 Must have a smaller ASCII number than `org-lowest-priority'."
1528 :group 'org-priorities
1529 :type 'character)
1531 (defcustom org-lowest-priority ?C
1532 "The lowest priority of TODO items. A character like ?A, ?B etc.
1533 Must have a larger ASCII number than `org-highest-priority'."
1534 :group 'org-priorities
1535 :type 'character)
1537 (defcustom org-default-priority ?B
1538 "The default priority of TODO items.
1539 This is the priority an item get if no explicit priority is given."
1540 :group 'org-priorities
1541 :type 'character)
1543 (defgroup org-time nil
1544 "Options concerning time stamps and deadlines in Org-mode."
1545 :tag "Org Time"
1546 :group 'org)
1548 (defcustom org-insert-labeled-timestamps-at-point nil
1549 "Non-nil means, SCHEDULED and DEADLINE timestamps are inserted at point.
1550 When nil, these labeled time stamps are forces into the second line of an
1551 entry, just after the headline. When scheduling from the global TODO list,
1552 the time stamp will always be forced into the second line."
1553 :group 'org-time
1554 :type 'boolean)
1556 (defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
1557 "Formats for `format-time-string' which are used for time stamps.
1558 It is not recommended to change this constant.")
1560 (defcustom org-time-stamp-rounding-minutes 0
1561 "Number of minutes to round time stamps to upon insertion.
1562 When zero, insert the time unmodified. Useful rounding numbers
1563 should be factors of 60, so for example 5, 10, 15.
1564 When this is not zero, you can still force an exact time-stamp by using
1565 a double prefix argument to a time-stamp command like `C-c .' or `C-c !'."
1566 :group 'org-time
1567 :type 'integer)
1569 (defcustom org-display-custom-times nil
1570 "Non-nil means, overlay custom formats over all time stamps.
1571 The formats are defined through the variable `org-time-stamp-custom-formats'.
1572 To turn this on on a per-file basis, insert anywhere in the file:
1573 #+STARTUP: customtime"
1574 :group 'org-time
1575 :set 'set-default
1576 :type 'sexp)
1577 (make-variable-buffer-local 'org-display-custom-times)
1579 (defcustom org-time-stamp-custom-formats
1580 '("<%m/%d/%y %a>" . "<%m/%d/%y %a %H:%M>") ; american
1581 "Custom formats for time stamps. See `format-time-string' for the syntax.
1582 These are overlayed over the default ISO format if the variable
1583 `org-display-custom-times' is set."
1584 :group 'org-time
1585 :type 'sexp)
1587 (defun org-time-stamp-format (&optional long inactive)
1588 "Get the right format for a time string."
1589 (let ((f (if long (cdr org-time-stamp-formats)
1590 (car org-time-stamp-formats))))
1591 (if inactive
1592 (concat "[" (substring f 1 -1) "]")
1593 f)))
1595 (defcustom org-deadline-warning-days 30
1596 "No. of days before expiration during which a deadline becomes active.
1597 This variable governs the display in sparse trees and in the agenda."
1598 :group 'org-time
1599 :type 'number)
1601 (defcustom org-popup-calendar-for-date-prompt t
1602 "Non-nil means, pop up a calendar when prompting for a date.
1603 In the calendar, the date can be selected with mouse-1. However, the
1604 minibuffer will also be active, and you can simply enter the date as well.
1605 When nil, only the minibuffer will be available."
1606 :group 'org-time
1607 :type 'boolean)
1609 (defcustom org-calendar-follow-timestamp-change t
1610 "Non-nil means, make the calendar window follow timestamp changes.
1611 When a timestamp is modified and the calendar window is visible, it will be
1612 moved to the new date."
1613 :group 'org-time
1614 :type 'boolean)
1616 (defgroup org-tags nil
1617 "Options concerning tags in Org-mode."
1618 :tag "Org Tags"
1619 :group 'org)
1621 (defcustom org-tag-alist nil
1622 "List of tags allowed in Org-mode files.
1623 When this list is nil, Org-mode will base TAG input on what is already in the
1624 buffer.
1625 The value of this variable is an alist, the car may be (and should) be a
1626 character that is used to select that tag through the fast-tag-selection
1627 interface. See the manual for details."
1628 :group 'org-tags
1629 :type '(repeat
1630 (choice
1631 (cons (string :tag "Tag name")
1632 (character :tag "Access char"))
1633 (const :tag "Start radio group" (:startgroup))
1634 (const :tag "End radio group" (:endgroup)))))
1636 (defcustom org-use-fast-tag-selection 'auto
1637 "Non-nil means, use fast tag selection scheme.
1638 This is a special interface to select and deselect tags with single keys.
1639 When nil, fast selection is never used.
1640 When the symbol `auto', fast selection is used if and only if selection
1641 characters for tags have been configured, either through the variable
1642 `org-tag-alist' or through a #+TAGS line in the buffer.
1643 When t, fast selection is always used and selection keys are assigned
1644 automatically if necessary."
1645 :group 'org-tags
1646 :type '(choice
1647 (const :tag "Always" t)
1648 (const :tag "Never" nil)
1649 (const :tag "When selection characters are configured" 'auto)))
1651 (defcustom org-fast-tag-selection-single-key nil
1652 "Non-nil means, fast tag selection exits after first change.
1653 When nil, you have to press RET to exit it.
1654 During fast tag selection, you can toggle this flag with `C-c'.
1655 This variable can also have the value `expert'. In this case, the window
1656 displaying the tags menu is not even shown, until you press C-c again."
1657 :group 'org-tags
1658 :type '(choice
1659 (const :tag "No" nil)
1660 (const :tag "Yes" t)
1661 (const :tag "Expert" expert)))
1663 (defcustom org-tags-column 48
1664 "The column to which tags should be indented in a headline.
1665 If this number is positive, it specifies the column. If it is negative,
1666 it means that the tags should be flushright to that column. For example,
1667 -79 works well for a normal 80 character screen."
1668 :group 'org-tags
1669 :type 'integer)
1671 (defcustom org-auto-align-tags t
1672 "Non-nil means, realign tags after pro/demotion of TODO state change.
1673 These operations change the length of a headline and therefore shift
1674 the tags around. With this options turned on, after each such operation
1675 the tags are again aligned to `org-tags-column'."
1676 :group 'org-tags
1677 :type 'boolean)
1679 (defcustom org-use-tag-inheritance t
1680 "Non-nil means, tags in levels apply also for sublevels.
1681 When nil, only the tags directly given in a specific line apply there.
1682 If you turn off this option, you very likely want to turn on the
1683 companion option `org-tags-match-list-sublevels'."
1684 :group 'org-tags
1685 :type 'boolean)
1687 (defcustom org-tags-match-list-sublevels nil
1688 "Non-nil means list also sublevels of headlines matching tag search.
1689 Because of tag inheritance (see variable `org-use-tag-inheritance'),
1690 the sublevels of a headline matching a tag search often also match
1691 the same search. Listing all of them can create very long lists.
1692 Setting this variable to nil causes subtrees of a match to be skipped.
1693 This option is off by default, because inheritance in on. If you turn
1694 inheritance off, you very likely want to turn this option on.
1696 As a special case, if the tag search is restricted to TODO items, the
1697 value of this variable is ignored and sublevels are always checked, to
1698 make sure all corresponding TODO items find their way into the list."
1699 :group 'org-tags
1700 :type 'boolean)
1702 (defvar org-tags-history nil
1703 "History of minibuffer reads for tags.")
1704 (defvar org-last-tags-completion-table nil
1705 "The last used completion table for tags.")
1707 (defgroup org-agenda nil
1708 "Options concerning agenda views in Org-mode."
1709 :tag "Org Agenda"
1710 :group 'org)
1712 (defvar org-category nil
1713 "Variable used by org files to set a category for agenda display.
1714 Such files should use a file variable to set it, for example
1716 # -*- mode: org; org-category: \"ELisp\"
1718 or contain a special line
1720 #+CATEGORY: ELisp
1722 If the file does not specify a category, then file's base name
1723 is used instead.")
1724 (make-variable-buffer-local 'org-category)
1726 (defcustom org-agenda-files nil
1727 "The files to be used for agenda display.
1728 Entries may be added to this list with \\[org-agenda-file-to-front] and removed with
1729 \\[org-remove-file]. You can also use customize to edit the list.
1731 If the value of the variable is not a list but a single file name, then
1732 the list of agenda files is actually stored and maintained in that file, one
1733 agenda file per line."
1734 :group 'org-agenda
1735 :type '(choice
1736 (repeat :tag "List of files" file)
1737 (file :tag "Store list in a file\n" :value "~/.agenda_files")))
1740 (defcustom org-agenda-confirm-kill 1
1741 "When set, remote killing from the agenda buffer needs confirmation.
1742 When t, a confirmation is always needed. When a number N, confirmation is
1743 only needed when the text to be killed contains more than N non-white lines."
1744 :group 'org-agenda
1745 :type '(choice
1746 (const :tag "Never" nil)
1747 (const :tag "Always" t)
1748 (number :tag "When more than N lines")))
1750 (defcustom org-calendar-to-agenda-key [?c]
1751 "The key to be installed in `calendar-mode-map' for switching to the agenda.
1752 The command `org-calendar-goto-agenda' will be bound to this key. The
1753 default is the character `c' because then `c' can be used to switch back and
1754 forth between agenda and calendar."
1755 :group 'org-agenda
1756 :type 'sexp)
1758 (defgroup org-agenda-export nil
1759 "Options concerning exporting agenda views in Org-mode."
1760 :tag "Org Agenda Export"
1761 :group 'org-agenda)
1763 (defcustom org-agenda-with-colors t
1764 "Non-nil means, use colors in agenda views."
1765 :group 'org-agenda-export
1766 :type 'boolean)
1768 (defcustom org-agenda-exporter-settings nil
1769 "Alist of variable/value pairs that should be active during agenda export.
1770 This is a good place to set uptions for ps-print and for htmlize."
1771 :group 'org-agenda-export
1772 :type '(repeat
1773 (list
1774 (variable)
1775 (sexp :tag "Value"))))
1777 (defcustom org-agenda-export-html-style ""
1778 "The style specification for exported HTML Agenda files.
1779 If this variable contains a string, it will replace the default <style>
1780 section as produced by `htmlize'.
1781 Since there are different ways of setting style information, this variable
1782 needs to contain the full HTML structure to provide a style, including the
1783 surrounding HTML tags. The style specifications should include definitions
1784 the fonts used by the agenda, here is an example:
1786 <style type=\"text/css\">
1787 p { font-weight: normal; color: gray; }
1788 .org-agenda-structure {
1789 font-size: 110%;
1790 color: #003399;
1791 font-weight: 600;
1793 .org-todo {
1794 color: #cc6666;Week-agenda:
1795 font-weight: bold;
1797 .org-done {
1798 color: #339933;
1800 .title { text-align: center; }
1801 .todo, .deadline { color: red; }
1802 .done { color: green; }
1803 </style>
1805 or, if you want to keep the style in a file,
1807 <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\">
1809 As the value of this option simply gets inserted into the HTML <head> header,
1810 you can \"misuse\" it to also add other text to the header. However,
1811 <style>...</style> is required, if not present the variable will be ignored."
1812 :group 'org-agenda-export
1813 :group 'org-export-html
1814 :type 'string)
1816 (defgroup org-agenda-custom-commands nil
1817 "Options concerning agenda views in Org-mode."
1818 :tag "Org Agenda Custom Commands"
1819 :group 'org-agenda)
1821 (defcustom org-agenda-custom-commands nil
1822 "Custom commands for the agenda.
1823 These commands will be offered on the splash screen displayed by the
1824 agenda dispatcher \\[org-agenda]. Each entry is a list like this:
1826 (key type match options files)
1828 key The key (a single char as a string) to be associated with the command.
1829 type The command type, any of the following symbols:
1830 todo Entries with a specific TODO keyword, in all agenda files.
1831 tags Tags match in all agenda files.
1832 tags-todo Tags match in all agenda files, TODO entries only.
1833 todo-tree Sparse tree of specific TODO keyword in *current* file.
1834 tags-tree Sparse tree with all tags matches in *current* file.
1835 occur-tree Occur sparse tree for *current* file.
1836 match What to search for:
1837 - a single keyword for TODO keyword searches
1838 - a tags match expression for tags searches
1839 - a regular expression for occur searches
1840 options A list of option setttings, similar to that in a let form, so like
1841 this: ((opt1 val1) (opt2 val2) ...)
1842 files A list of files file to write the produced agenda buffer to
1843 with the command `org-store-agenda-views'.
1844 If a file name ends in \".html\", an HTML version of the buffer
1845 is written out. If it ends in \".ps\", a postscript version is
1846 produced. Otherwide, only the plain text is written to the file.
1848 You can also define a set of commands, to create a composite agenda buffer.
1849 In this case, an entry looks like this:
1851 (key desc (cmd1 cmd2 ...) general-options file)
1853 where
1855 desc A description string to be displayed in the dispatcher menu.
1856 cmd An agenda command, similar to the above. However, tree commands
1857 are no allowed, but instead you can get agenda and global todo list.
1858 So valid commands for a set are:
1859 (agenda)
1860 (alltodo)
1861 (stuck)
1862 (todo \"match\" options files)
1863 (tags \"match\" options files)
1864 (tags-todo \"match\" options files)
1866 Each command can carry a list of options, and another set of options can be
1867 given for the whole set of commands. Individual command options take
1868 precedence over the general options."
1869 :group 'org-agenda-custom-commands
1870 :type '(repeat
1871 (choice :value ("a" tags "" nil)
1872 (list :tag "Single command"
1873 (string :tag "Key")
1874 (choice
1875 (const :tag "Agenda" agenda)
1876 (const :tag "TODO list" alltodo)
1877 (const :tag "Stuck projects" stuck)
1878 (const :tag "Tags search (all agenda files)" tags)
1879 (const :tag "Tags search of TODO entries (all agenda files)" tags-todo)
1880 (const :tag "TODO keyword search (all agenda files)" todo)
1881 (const :tag "Tags sparse tree (current buffer)" tags-tree)
1882 (const :tag "TODO keyword tree (current buffer)" todo-tree)
1883 (const :tag "Occur tree (current buffer)" occur-tree)
1884 (symbol :tag "Other, user-defined function"))
1885 (string :tag "Match")
1886 (repeat :tag "Local options"
1887 (list (variable :tag "Option") (sexp :tag "Value")))
1888 (option (repeat :tag "Export" (file :tag "Export to"))))
1889 (list :tag "Command series, all agenda files"
1890 (string :tag "Key")
1891 (string :tag "Description")
1892 (repeat
1893 (choice
1894 (const :tag "Agenda" (agenda))
1895 (const :tag "TODO list" (alltodo))
1896 (const :tag "Stuck projects" (stuck))
1897 (list :tag "Tags search"
1898 (const :format "" tags)
1899 (string :tag "Match")
1900 (repeat :tag "Local options"
1901 (list (variable :tag "Option")
1902 (sexp :tag "Value"))))
1904 (list :tag "Tags search, TODO entries only"
1905 (const :format "" tags-todo)
1906 (string :tag "Match")
1907 (repeat :tag "Local options"
1908 (list (variable :tag "Option")
1909 (sexp :tag "Value"))))
1911 (list :tag "TODO keyword search"
1912 (const :format "" todo)
1913 (string :tag "Match")
1914 (repeat :tag "Local options"
1915 (list (variable :tag "Option")
1916 (sexp :tag "Value"))))
1918 (list :tag "Other, user-defined function"
1919 (symbol :tag "function")
1920 (string :tag "Match")
1921 (repeat :tag "Local options"
1922 (list (variable :tag "Option")
1923 (sexp :tag "Value"))))))
1925 (repeat :tag "General options"
1926 (list (variable :tag "Option")
1927 (sexp :tag "Value")))
1928 (option (repeat :tag "Export" (file :tag "Export to")))))))
1930 (defcustom org-stuck-projects
1931 '("+LEVEL=2/-DONE" ("TODO" "NEXT" "NEXTACTION") nil "")
1932 "How to identify stuck projects.
1933 This is a list of four items:
1934 1. A tags/todo matcher string that is used to identify a project.
1935 The entire tree below a headline matched by this is considered one project.
1936 2. A list of TODO keywords identifying non-stuck projects.
1937 If the project subtree contains any headline with one of these todo
1938 keywords, the project is considered to be not stuck. If you specify
1939 \"*\" as a keyword, any TODO keyword will mark the project unstuck.
1940 3. A list of tags identifying non-stuck projects.
1941 If the project subtree contains any headline with one of these tags,
1942 the project is considered to be not stuck. If you specify \"*\" as
1943 a tag, any tag will mark the project unstuck.
1944 4. An arbitrary regular expression matching non-stuck projects.
1946 After defining this variable, you may use \\[org-agenda-list-stuck-projects]
1947 or `C-c a #' to produce the list."
1948 :group 'org-agenda-custom-commands
1949 :type '(list
1950 (string :tag "Tags/TODO match to identify a project")
1951 (repeat :tag "Projects are *not* stuck if they have an entry with TODO keyword any of" (string))
1952 (repeat :tag "Projects are *not* stuck if they have an entry with TAG being any of" (string))
1953 (regexp :tag "Projects are *not* stuck if this regexp matches\ninside the subtree")))
1956 (defgroup org-agenda-skip nil
1957 "Options concerning skipping parts of agenda files."
1958 :tag "Org Agenda Skip"
1959 :group 'org-agenda)
1961 (defcustom org-agenda-todo-list-sublevels t
1962 "Non-nil means, check also the sublevels of a TODO entry for TODO entries.
1963 When nil, the sublevels of a TODO entry are not checked, resulting in
1964 potentially much shorter TODO lists."
1965 :group 'org-agenda-skip
1966 :group 'org-todo
1967 :type 'boolean)
1969 (defcustom org-agenda-todo-ignore-scheduled nil
1970 "Non-nil means, don't show scheduled entries in the global todo list.
1971 The idea behind this is that by scheduling it, you have already taken care
1972 of this item."
1973 :group 'org-agenda-skip
1974 :group 'org-todo
1975 :type 'boolean)
1977 (defcustom org-agenda-todo-ignore-deadlines nil
1978 "Non-nil means, don't show near deadline entries in the global todo list.
1979 Near means closer than `org-deadline-warning-days' days.
1980 The idea behind this is that such items will appear in the agenda anyway."
1981 :group 'org-agenda-skip
1982 :group 'org-todo
1983 :type 'boolean)
1985 (defcustom org-agenda-skip-scheduled-if-done nil
1986 "Non-nil means don't show scheduled items in agenda when they are done.
1987 This is relevant for the daily/weekly agenda, not for the TODO list."
1988 :group 'org-agenda-skip
1989 :type 'boolean)
1991 (defcustom org-agenda-skip-deadline-if-done nil
1992 "Non-nil means don't show deadines when the corresponding item is done.
1993 When nil, the deadline is still shown and should give you a happy feeling.
1995 This is relevant for the daily/weekly agenda."
1996 :group 'org-agenda-skip
1997 :type 'boolean)
1999 (defcustom org-timeline-show-empty-dates 3
2000 "Non-nil means, `org-timeline' also shows dates without an entry.
2001 When nil, only the days which actually have entries are shown.
2002 When t, all days between the first and the last date are shown.
2003 When an integer, show also empty dates, but if there is a gap of more than
2004 N days, just insert a special line indicating the size of the gap."
2005 :group 'org-agenda-skip
2006 :type '(choice
2007 (const :tag "None" nil)
2008 (const :tag "All" t)
2009 (number :tag "at most")))
2012 (defgroup org-agenda-startup nil
2013 "Options concerning initial settings in the Agenda in Org Mode."
2014 :tag "Org Agenda Startup"
2015 :group 'org-agenda)
2017 (defcustom org-finalize-agenda-hook nil
2018 "Hook run just before displaying an agenda buffer."
2019 :group 'org-agenda-startup
2020 :type 'hook)
2022 (defcustom org-agenda-mouse-1-follows-link nil
2023 "Non-nil means, mouse-1 on a link will follow the link in the agenda.
2024 A longer mouse click will still set point. Does not wortk on XEmacs.
2025 Needs to be set before org.el is loaded."
2026 :group 'org-agenda-startup
2027 :type 'boolean)
2029 (defcustom org-agenda-start-with-follow-mode nil
2030 "The initial value of follow-mode in a newly created agenda window."
2031 :group 'org-agenda-startup
2032 :type 'boolean)
2034 (defgroup org-agenda-windows nil
2035 "Options concerning the windows used by the Agenda in Org Mode."
2036 :tag "Org Agenda Windows"
2037 :group 'org-agenda)
2039 (defcustom org-agenda-window-setup 'reorganize-frame
2040 "How the agenda buffer should be displayed.
2041 Possible values for this option are:
2043 current-window Show agenda in the current window, keeping all other windows.
2044 other-frame Use `switch-to-buffer-other-frame' to display agenda.
2045 other-window Use `switch-to-buffer-other-window' to display agenda.
2046 reorganize-frame Show only two windows on the current frame, the current
2047 window and the agenda.
2048 See also the variable `org-agenda-restore-windows-after-quit'."
2049 :group 'org-agenda-windows
2050 :type '(choice
2051 (const current-window)
2052 (const other-frame)
2053 (const other-window)
2054 (const reorganize-frame)))
2056 (defcustom org-agenda-restore-windows-after-quit nil
2057 "Non-nil means, restore window configuration open exiting agenda.
2058 Before the window configuration is changed for displaying the agenda,
2059 the current status is recorded. When the agenda is exited with
2060 `q' or `x' and this option is set, the old state is restored. If
2061 `org-agenda-window-setup' is `other-frame', the value of this
2062 option will be ignored.."
2063 :group 'org-agenda-windows
2064 :type 'boolean)
2066 (defcustom org-indirect-buffer-display 'other-window
2067 "How should indirect tree buffers be displayed?
2068 This applies to indirect buffers created with the commands
2069 \\[org-tree-to-indirect-buffer] and \\[org-agenda-tree-to-indirect-buffer].
2070 Valid values are:
2071 current-window Display in the current window
2072 other-window Just display in another window.
2073 dedicated-frame Create one new frame, and re-use it each time.
2074 new-frame Make a new frame each time."
2075 :group 'org-structure
2076 :group 'org-agenda-windows
2077 :type '(choice
2078 (const :tag "In current window" current-window)
2079 (const :tag "In current frame, other window" other-window)
2080 (const :tag "Each time a new frame" new-frame)
2081 (const :tag "One dedicated frame" dedicated-frame)))
2083 (defgroup org-agenda-daily/weekly nil
2084 "Options concerning the daily/weekly agenda."
2085 :tag "Org Agenda Daily/Weekly"
2086 :group 'org-agenda)
2088 (defcustom org-agenda-ndays 7
2089 "Number of days to include in overview display.
2090 Should be 1 or 7."
2091 :group 'org-agenda-daily/weekly
2092 :type 'number)
2094 (defcustom org-agenda-start-on-weekday 1
2095 "Non-nil means, start the overview always on the specified weekday.
2096 0 denotes Sunday, 1 denotes Monday etc.
2097 When nil, always start on the current day."
2098 :group 'org-agenda-daily/weekly
2099 :type '(choice (const :tag "Today" nil)
2100 (number :tag "Weekday No.")))
2102 (defcustom org-agenda-show-all-dates t
2103 "Non-nil means, `org-agenda' shows every day in the selected range.
2104 When nil, only the days which actually have entries are shown."
2105 :group 'org-agenda-daily/weekly
2106 :type 'boolean)
2108 (defcustom org-agenda-date-format "%A %d %B %Y"
2109 "Format string for displaying dates in the agenda.
2110 Used by the daily/weekly agenda and by the timeline. This should be
2111 a format string understood by `format-time-string'.
2112 FIXME: Not used currently, because of timezone problem."
2113 :group 'org-agenda-daily/weekly
2114 :type 'string)
2116 (defcustom org-agenda-include-diary nil
2117 "If non-nil, include in the agenda entries from the Emacs Calendar's diary."
2118 :group 'org-agenda-daily/weekly
2119 :type 'boolean)
2121 (defcustom org-agenda-include-all-todo nil
2122 "Set means weekly/daily agenda will always contain all TODO entries.
2123 The TODO entries will be listed at the top of the agenda, before
2124 the entries for specific days."
2125 :group 'org-agenda-daily/weekly
2126 :type 'boolean)
2128 (defgroup org-agenda-time-grid nil
2129 "Options concerning the time grid in the Org-mode Agenda."
2130 :tag "Org Agenda Time Grid"
2131 :group 'org-agenda)
2133 (defcustom org-agenda-use-time-grid t
2134 "Non-nil means, show a time grid in the agenda schedule.
2135 A time grid is a set of lines for specific times (like every two hours between
2136 8:00 and 20:00). The items scheduled for a day at specific times are
2137 sorted in between these lines.
2138 For details about when the grid will be shown, and what it will look like, see
2139 the variable `org-agenda-time-grid'."
2140 :group 'org-agenda-time-grid
2141 :type 'boolean)
2143 (defcustom org-agenda-time-grid
2144 '((daily today require-timed)
2145 "----------------"
2146 (800 1000 1200 1400 1600 1800 2000))
2148 "The settings for time grid for agenda display.
2149 This is a list of three items. The first item is again a list. It contains
2150 symbols specifying conditions when the grid should be displayed:
2152 daily if the agenda shows a single day
2153 weekly if the agenda shows an entire week
2154 today show grid on current date, independent of daily/weekly display
2155 require-timed show grid only if at least one item has a time specification
2157 The second item is a string which will be places behing the grid time.
2159 The third item is a list of integers, indicating the times that should have
2160 a grid line."
2161 :group 'org-agenda-time-grid
2162 :type
2163 '(list
2164 (set :greedy t :tag "Grid Display Options"
2165 (const :tag "Show grid in single day agenda display" daily)
2166 (const :tag "Show grid in weekly agenda display" weekly)
2167 (const :tag "Always show grid for today" today)
2168 (const :tag "Show grid only if any timed entries are present"
2169 require-timed)
2170 (const :tag "Skip grid times already present in an entry"
2171 remove-match))
2172 (string :tag "Grid String")
2173 (repeat :tag "Grid Times" (integer :tag "Time"))))
2175 (defgroup org-agenda-sorting nil
2176 "Options concerning sorting in the Org-mode Agenda."
2177 :tag "Org Agenda Sorting"
2178 :group 'org-agenda)
2180 (let ((sorting-choice
2181 '(choice
2182 (const time-up) (const time-down)
2183 (const category-keep) (const category-up) (const category-down)
2184 (const tag-down) (const tag-up)
2185 (const priority-up) (const priority-down))))
2187 (defcustom org-agenda-sorting-strategy
2188 '((agenda time-up category-keep priority-down)
2189 (todo category-keep priority-down)
2190 (tags category-keep priority-down))
2191 "Sorting structure for the agenda items of a single day.
2192 This is a list of symbols which will be used in sequence to determine
2193 if an entry should be listed before another entry. The following
2194 symbols are recognized:
2196 time-up Put entries with time-of-day indications first, early first
2197 time-down Put entries with time-of-day indications first, late first
2198 category-keep Keep the default order of categories, corresponding to the
2199 sequence in `org-agenda-files'.
2200 category-up Sort alphabetically by category, A-Z.
2201 category-down Sort alphabetically by category, Z-A.
2202 tag-up Sort alphabetically by last tag, A-Z.
2203 tag-down Sort alphabetically by last tag, Z-A.
2204 priority-up Sort numerically by priority, high priority last.
2205 priority-down Sort numerically by priority, high priority first.
2207 The different possibilities will be tried in sequence, and testing stops
2208 if one comparison returns a \"not-equal\". For example, the default
2209 '(time-up category-keep priority-down)
2210 means: Pull out all entries having a specified time of day and sort them,
2211 in order to make a time schedule for the current day the first thing in the
2212 agenda listing for the day. Of the entries without a time indication, keep
2213 the grouped in categories, don't sort the categories, but keep them in
2214 the sequence given in `org-agenda-files'. Within each category sort by
2215 priority.
2217 Leaving out `category-keep' would mean that items will be sorted across
2218 categories by priority."
2219 :group 'org-agenda-sorting
2220 :type `(choice
2221 (repeat :tag "General" ,sorting-choice)
2222 (list :tag "Individually"
2223 (cons (const :tag "Strategy for Weekly/Daily agenda" agenda)
2224 (repeat ,sorting-choice))
2225 (cons (const :tag "Strategy for TODO lists" todo)
2226 (repeat ,sorting-choice))
2227 (cons (const :tag "Strategy for Tags matches" tags)
2228 (repeat ,sorting-choice))))))
2230 (defcustom org-sort-agenda-notime-is-late t
2231 "Non-nil means, items without time are considered late.
2232 This is only relevant for sorting. When t, items which have no explicit
2233 time like 15:30 will be considered as 99:01, i.e. later than any items which
2234 do have a time. When nil, the default time is before 0:00. You can use this
2235 option to decide if the schedule for today should come before or after timeless
2236 agenda entries."
2237 :group 'org-agenda-sorting
2238 :type 'boolean)
2240 (defgroup org-agenda-prefix nil
2241 "Options concerning the entry prefix in the Org-mode agenda display."
2242 :tag "Org Agenda Prefix"
2243 :group 'org-agenda)
2245 (defcustom org-agenda-prefix-format
2246 '((agenda . " %-12:c%?-12t% s")
2247 (timeline . " % s")
2248 (todo . " %-12:c")
2249 (tags . " %-12:c"))
2250 "Format specifications for the prefix of items in the agenda views.
2251 An alist with four entries, for the different agenda types. The keys to the
2252 sublists are `agenda', `timeline', `todo', and `tags'. The values
2253 are format strings.
2254 This format works similar to a printf format, with the following meaning:
2256 %c the category of the item, \"Diary\" for entries from the diary, or
2257 as given by the CATEGORY keyword or derived from the file name.
2258 %T the *last* tag of the item. Last because inherited tags come
2259 first in the list.
2260 %t the time-of-day specification if one applies to the entry, in the
2261 format HH:MM
2262 %s Scheduling/Deadline information, a short string
2264 All specifiers work basically like the standard `%s' of printf, but may
2265 contain two additional characters: A question mark just after the `%' and
2266 a whitespace/punctuation character just before the final letter.
2268 If the first character after `%' is a question mark, the entire field
2269 will only be included if the corresponding value applies to the
2270 current entry. This is useful for fields which should have fixed
2271 width when present, but zero width when absent. For example,
2272 \"%?-12t\" will result in a 12 character time field if a time of the
2273 day is specified, but will completely disappear in entries which do
2274 not contain a time.
2276 If there is punctuation or whitespace character just before the final
2277 format letter, this character will be appended to the field value if
2278 the value is not empty. For example, the format \"%-12:c\" leads to
2279 \"Diary: \" if the category is \"Diary\". If the category were be
2280 empty, no additional colon would be interted.
2282 The default value of this option is \" %-12:c%?-12t% s\", meaning:
2283 - Indent the line with two space characters
2284 - Give the category in a 12 chars wide field, padded with whitespace on
2285 the right (because of `-'). Append a colon if there is a category
2286 (because of `:').
2287 - If there is a time-of-day, put it into a 12 chars wide field. If no
2288 time, don't put in an empty field, just skip it (because of '?').
2289 - Finally, put the scheduling information and append a whitespace.
2291 As another example, if you don't want the time-of-day of entries in
2292 the prefix, you could use:
2294 (setq org-agenda-prefix-format \" %-11:c% s\")
2296 See also the variables `org-agenda-remove-times-when-in-prefix' and
2297 `org-agenda-remove-tags'."
2298 :type '(choice
2299 (string :tag "General format")
2300 (list :greedy t :tag "View dependent"
2301 (cons (const agenda) (string :tag "Format"))
2302 (cons (const timeline) (string :tag "Format"))
2303 (cons (const todo) (string :tag "Format"))
2304 (cons (const tags) (string :tag "Format"))))
2305 :group 'org-agenda-prefix)
2307 (defvar org-prefix-format-compiled nil
2308 "The compiled version of the most recently used prefix format.
2309 See the variable `org-agenda-prefix-format'.")
2311 (defcustom org-agenda-remove-times-when-in-prefix t
2312 "Non-nil means, remove duplicate time specifications in agenda items.
2313 When the format `org-agenda-prefix-format' contains a `%t' specifier, a
2314 time-of-day specification in a headline or diary entry is extracted and
2315 placed into the prefix. If this option is non-nil, the original specification
2316 \(a timestamp or -range, or just a plain time(range) specification like
2317 11:30-4pm) will be removed for agenda display. This makes the agenda less
2318 cluttered.
2319 The option can be t or nil. It may also be the symbol `beg', indicating
2320 that the time should only be removed what it is located at the beginning of
2321 the headline/diary entry."
2322 :group 'org-agenda-prefix
2323 :type '(choice
2324 (const :tag "Always" t)
2325 (const :tag "Never" nil)
2326 (const :tag "When at beginning of entry" beg)))
2328 (defcustom org-agenda-remove-tags nil
2329 "Non-nil means, remove the tags from the headline copy in the agenda.
2330 When this is the symbol `prefix', only remove tags when
2331 `org-agenda-prefix-format' contains a `%T' specifier."
2332 :group 'org-agenda-prefix
2333 :type '(choice
2334 (const :tag "Always" t)
2335 (const :tag "Never" nil)
2336 (const :tag "When prefix format contains %T" prefix)))
2338 (if (fboundp 'defvaralias)
2339 (defvaralias 'org-agenda-remove-tags-when-in-prefix
2340 'org-agenda-remove-tags))
2342 (defcustom org-agenda-align-tags-to-column 65
2343 "Shift tags in agenda items to this column."
2344 :group 'org-agenda-prefix
2345 :type 'integer)
2347 (defgroup org-latex nil
2348 "Options for embedding LaTeX code into Org-mode"
2349 :tag "Org LaTeX"
2350 :group 'org)
2352 (defcustom org-format-latex-options
2353 '(:foreground default :background default :scale 1.0
2354 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0
2355 :matchers ("begin" "$" "$$" "\\(" "\\["))
2356 "Options for creating images from LaTeX fragments.
2357 This is a property list with the following properties:
2358 :foreground the foreground color for images embedded in emacs, e.g. \"Black\".
2359 `default' means use the forground of the default face.
2360 :background the background color, or \"Transparent\".
2361 `default' means use the background of the default face.
2362 :scale a scaling factor for the size of the images
2363 :html-foreground, :html-background, :html-scale
2364 The same numbers for HTML export.
2365 :matchers a list indicating which matchers should be used to
2366 find LaTeX fragments. Valid members of this list are:
2367 \"begin\" find environments
2368 \"$\" find math expressions surrounded by $...$
2369 \"$$\" find math expressions surrounded by $$....$$
2370 \"\\(\" find math expressions surrounded by \\(...\\)
2371 \"\\ [\" find math expressions surrounded by \\ [...\\]"
2372 :group 'org-latex
2373 :type 'plist)
2375 (defcustom org-format-latex-header "\\documentclass{article}
2376 \\usepackage{fullpage} % do not remove
2377 \\usepackage{amssymb}
2378 \\usepackage[usenames]{color}
2379 \\usepackage{amsmath}
2380 \\usepackage{latexsym}
2381 \\usepackage[mathscr]{eucal}
2382 \\pagestyle{empty} % do not remove"
2383 "The document header used for processing LaTeX fragments."
2384 :group 'org-latex
2385 :type 'string)
2387 (defgroup org-export nil
2388 "Options for exporting org-listings."
2389 :tag "Org Export"
2390 :group 'org)
2392 (defgroup org-export-general nil
2393 "General options for exporting Org-mode files."
2394 :tag "Org Export General"
2395 :group 'org-export)
2397 (defcustom org-export-publishing-directory "."
2398 "Path to the location where exported files should be located.
2399 This path may be relative to the directory where the Org-mode file lives.
2400 The default is to put them into the same directory as the Org-mode file.
2401 The variable may also be an alist with export types `:html', `:ascii',
2402 `:ical', or `:xoxo' and the corresponding directories. If a direcoty path
2403 is relative, it is interpreted relative to the directory where the exported
2404 Org-mode files lives."
2405 :group 'org-export-general
2406 :type '(choice
2407 (directory)
2408 (repeat
2409 (cons
2410 (choice :tag "Type"
2411 (const :html) (const :ascii) (const :ical) (const :xoxo))
2412 (directory)))))
2414 (defcustom org-export-language-setup
2415 '(("en" "Author" "Date" "Table of Contents")
2416 ("cs" "Autor" "Datum" "Obsah")
2417 ("da" "Ophavsmand" "Dato" "Indhold")
2418 ("de" "Autor" "Datum" "Inhaltsverzeichnis")
2419 ("es" "Autor" "Fecha" "\xccndice")
2420 ("fr" "Auteur" "Date" "Table des Mati\xe8res")
2421 ("it" "Autore" "Data" "Indice")
2422 ("nl" "Auteur" "Datum" "Inhoudsopgave")
2423 ("nn" "Forfattar" "Dato" "Innhold") ;; nn = Norsk (nynorsk)
2424 ("sv" "F\xf6rfattarens" "Datum" "Inneh\xe5ll"))
2425 "Terms used in export text, translated to different languages.
2426 Use the variable `org-export-default-language' to set the language,
2427 or use the +OPTION lines for a per-file setting."
2428 :group 'org-export-general
2429 :type '(repeat
2430 (list
2431 (string :tag "HTML language tag")
2432 (string :tag "Author")
2433 (string :tag "Date")
2434 (string :tag "Table of Contents"))))
2436 (defcustom org-export-default-language "en"
2437 "The default language of HTML export, as a string.
2438 This should have an association in `org-export-language-setup'."
2439 :group 'org-export-general
2440 :type 'string)
2442 (defcustom org-export-skip-text-before-1st-heading t
2443 "Non-nil means, skip all text before the first headline when exporting.
2444 When nil, that text is exported as well."
2445 :group 'org-export-general
2446 :type 'boolean)
2448 (defcustom org-export-headline-levels 3
2449 "The last level which is still exported as a headline.
2450 Inferior levels will produce itemize lists when exported.
2451 Note that a numeric prefix argument to an exporter function overrides
2452 this setting.
2454 This option can also be set with the +OPTIONS line, e.g. \"H:2\"."
2455 :group 'org-export-general
2456 :type 'number)
2458 (defcustom org-export-with-section-numbers t
2459 "Non-nil means, add section numbers to headlines when exporting.
2461 This option can also be set with the +OPTIONS line, e.g. \"num:t\"."
2462 :group 'org-export-general
2463 :type 'boolean)
2465 (defcustom org-export-with-toc t
2466 "Non-nil means, create a table of contents in exported files.
2467 The TOC contains headlines with levels up to`org-export-headline-levels'.
2468 When an integer, include levels up to N in the toc, this may then be
2469 different from `org-export-headline-levels', but it will not be allowed
2470 to be larger than the number of headline levels.
2471 When nil, no table of contents is made.
2473 Headlines which contain any TODO items will be marked with \"(*)\" in
2474 ASCII export, and with red color in HTML output, if the option
2475 `org-export-mark-todo-in-toc' is set.
2477 In HTML output, the TOC will be clickable.
2479 This option can also be set with the +OPTIONS line, e.g. \"toc:nil\"
2480 or \"toc:3\"."
2481 :group 'org-export-general
2482 :type '(choice
2483 (const :tag "No Table of Contents" nil)
2484 (const :tag "Full Table of Contents" t)
2485 (integer :tag "TOC to level")))
2487 (defcustom org-export-mark-todo-in-toc nil
2488 "Non-nil means, mark TOC lines that contain any open TODO items."
2489 :group 'org-export-general
2490 :type 'boolean)
2492 (defcustom org-export-preserve-breaks nil
2493 "Non-nil means, preserve all line breaks when exporting.
2494 Normally, in HTML output paragraphs will be reformatted. In ASCII
2495 export, line breaks will always be preserved, regardless of this variable.
2497 This option can also be set with the +OPTIONS line, e.g. \"\\n:t\"."
2498 :group 'org-export-general
2499 :type 'boolean)
2501 (defcustom org-export-with-archived-trees 'headline
2502 "Whether subtrees with the ARCHIVE tag should be exported.
2503 This can have three different values
2504 nil Do not export, pretend this tree is not present
2505 t Do export the entire tree
2506 headline Only export the headline, but skip the tree below it."
2507 :group 'org-export-general
2508 :group 'org-archive
2509 :type '(choice
2510 (const :tag "not at all" nil)
2511 (const :tag "headline only" 'headline)
2512 (const :tag "entirely" t)))
2514 (defcustom org-export-with-timestamps t
2515 "If nil, do not export time stamps and associated keywords."
2516 :group 'org-export-general
2517 :type 'boolean)
2519 (defcustom org-export-remove-timestamps-from-toc t
2520 "If nil, remove timestamps from the table of contents entries."
2521 :group 'org-export-general
2522 :type 'boolean)
2524 (defcustom org-export-with-tags 'not-in-toc
2525 "If nil, do not export tags, just remove them from headlines.
2526 If this is the symbol `not-in-toc', tags will be removed from table of
2527 contents entries, but still be shown in the headlines of the document."
2528 :group 'org-export-general
2529 :type '(choice
2530 (const :tag "Off" nil)
2531 (const :tag "Not in TOC" not-in-toc)
2532 (const :tag "On" t)))
2534 (defgroup org-export-translation nil
2535 "Options for translating special ascii sequences for the export backends."
2536 :tag "Org Export Translation"
2537 :group 'org-export)
2539 (defcustom org-export-with-emphasize t
2540 "Non-nil means, interpret *word*, /word/, and _word_ as emphasized text.
2541 If the export target supports emphasizing text, the word will be
2542 typeset in bold, italic, or underlined, respectively. Works only for
2543 single words, but you can say: I *really* *mean* *this*.
2544 Not all export backends support this.
2546 This option can also be set with the +OPTIONS line, e.g. \"*:nil\"."
2547 :group 'org-export-translation
2548 :type 'boolean)
2550 (defcustom org-export-with-sub-superscripts t
2551 "Non-nil means, interpret \"_\" and \"^\" for export.
2552 When this option is turned on, you can use TeX-like syntax for sub- and
2553 superscripts. Several characters after \"_\" or \"^\" will be
2554 considered as a single item - so grouping with {} is normally not
2555 needed. For example, the following things will be parsed as single
2556 sub- or superscripts.
2558 10^24 or 10^tau several digits will be considered 1 item.
2559 10^-12 or 10^-tau a leading sign with digits or a word
2560 x^2-y^3 will be read as x^2 - y^3, because items are
2561 terminated by almost any nonword/nondigit char.
2562 x_{i^2} or x^(2-i) braces or parenthesis do grouping.
2564 Still, ambiguity is possible - so when in doubt use {} to enclose the
2565 sub/superscript. If you set this variable to the symbol `{}',
2566 the braces are *required* in order to trigger interpretations as
2567 sub/superscript. This can be helpful in documents that need \"_\"
2568 frequently in plain text.
2570 Not all export backends support this, but HTML does.
2572 This option can also be set with the +OPTIONS line, e.g. \"^:nil\"."
2573 :group 'org-export-translation
2574 :type '(choice
2575 (const :tag "Always interpret" t)
2576 (const :tag "Only with braces" {})
2577 (const :tag "Never interpret" nil)))
2579 (defcustom org-export-with-TeX-macros t
2580 "Non-nil means, interpret simple TeX-like macros when exporting.
2581 For example, HTML export converts \\alpha to &alpha; and \\AA to &Aring;.
2582 No only real TeX macros will work here, but the standard HTML entities
2583 for math can be used as macro names as well. For a list of supported
2584 names in HTML export, see the constant `org-html-entities'.
2585 Not all export backends support this.
2587 This option can also be set with the +OPTIONS line, e.g. \"TeX:nil\"."
2588 :group 'org-export-translation
2589 :group 'org-latex
2590 :type 'boolean)
2592 (defcustom org-export-with-LaTeX-fragments nil
2593 "Non-nil means, convert LaTeX fragments to images when exporting to HTML.
2594 When set, the exporter will find LaTeX environments if the \\begin line is
2595 the first non-white thing on a line. It will also find the math delimiters
2596 like $a=b$ and \\( a=b \\) for inline math, $$a=b$$ and \\[ a=b \\] for
2597 display math.
2599 This option can also be set with the +OPTIONS line, e.g. \"LaTeX:t\"."
2600 :group 'org-export-translation
2601 :group 'org-latex
2602 :type 'boolean)
2604 (defcustom org-export-with-fixed-width t
2605 "Non-nil means, lines starting with \":\" will be in fixed width font.
2606 This can be used to have pre-formatted text, fragments of code etc. For
2607 example:
2608 : ;; Some Lisp examples
2609 : (while (defc cnt)
2610 : (ding))
2611 will be looking just like this in also HTML. See also the QUOTE keyword.
2612 Not all export backends support this.
2614 This option can also be set with the +OPTIONS line, e.g. \"::nil\"."
2615 :group 'org-export-translation
2616 :type 'boolean)
2618 (defcustom org-match-sexp-depth 3
2619 "Number of stacked braces for sub/superscript matching.
2620 This has to be set before loading org.el to be effective."
2621 :group 'org-export-translation
2622 :type 'integer)
2624 (defgroup org-export-tables nil
2625 "Options for exporting tables in Org-mode."
2626 :tag "Org Export Tables"
2627 :group 'org-export)
2629 (defcustom org-export-with-tables t
2630 "If non-nil, lines starting with \"|\" define a table.
2631 For example:
2633 | Name | Address | Birthday |
2634 |-------------+----------+-----------|
2635 | Arthur Dent | England | 29.2.2100 |
2637 Not all export backends support this.
2639 This option can also be set with the +OPTIONS line, e.g. \"|:nil\"."
2640 :group 'org-export-tables
2641 :type 'boolean)
2643 (defcustom org-export-highlight-first-table-line t
2644 "Non-nil means, highlight the first table line.
2645 In HTML export, this means use <th> instead of <td>.
2646 In tables created with table.el, this applies to the first table line.
2647 In Org-mode tables, all lines before the first horizontal separator
2648 line will be formatted with <th> tags."
2649 :group 'org-export-tables
2650 :type 'boolean)
2652 (defcustom org-export-table-remove-special-lines t
2653 "Remove special lines and marking characters in calculating tables.
2654 This removes the special marking character column from tables that are set
2655 up for spreadsheet calculations. It also removes the entire lines
2656 marked with `!', `_', or `^'. The lines with `$' are kept, because
2657 the values of constants may be useful to have."
2658 :group 'org-export-tables
2659 :type 'boolean)
2661 (defcustom org-export-prefer-native-exporter-for-tables nil
2662 "Non-nil means, always export tables created with table.el natively.
2663 Natively means, use the HTML code generator in table.el.
2664 When nil, Org-mode's own HTML generator is used when possible (i.e. if
2665 the table does not use row- or column-spanning). This has the
2666 advantage, that the automatic HTML conversions for math symbols and
2667 sub/superscripts can be applied. Org-mode's HTML generator is also
2668 much faster."
2669 :group 'org-export-tables
2670 :type 'boolean)
2672 (defgroup org-export-ascii nil
2673 "Options specific for ASCII export of Org-mode files."
2674 :tag "Org Export ASCII"
2675 :group 'org-export)
2677 (defcustom org-export-ascii-underline '(?\$ ?\# ?^ ?\~ ?\= ?\-)
2678 "Characters for underlining headings in ASCII export.
2679 In the given sequence, these characters will be used for level 1, 2, ..."
2680 :group 'org-export-ascii
2681 :type '(repeat character))
2683 (defcustom org-export-ascii-bullets '(?* ?+ ?-)
2684 "Bullet characters for headlines converted to lists in ASCII export.
2685 The first character is is used for the first lest level generated in this
2686 way, and so on. If there are more levels than characters given here,
2687 the list will be repeated.
2688 Note that plain lists will keep the same bullets as the have in the
2689 Org-mode file."
2690 :group 'org-export-ascii
2691 :type '(repeat character))
2693 (defgroup org-export-xml nil
2694 "Options specific for XML export of Org-mode files."
2695 :tag "Org Export XML"
2696 :group 'org-export)
2698 (defgroup org-export-html nil
2699 "Options specific for HTML export of Org-mode files."
2700 :tag "Org Export HTML"
2701 :group 'org-export)
2703 (defcustom org-export-html-style
2704 "<style type=\"text/css\">
2705 html {
2706 font-family: Times, serif;
2707 font-size: 12pt;
2709 .title { text-align: center; }
2710 .todo { color: red; }
2711 .done { color: green; }
2712 .timestamp { color: grey }
2713 .timestamp-kwd { color: CadetBlue }
2714 .tag { background-color:lightblue; font-weight:normal }
2715 .target { background-color: lavender; }
2716 pre {
2717 border: 1pt solid #AEBDCC;
2718 background-color: #F3F5F7;
2719 padding: 5pt;
2720 font-family: courier, monospace;
2722 table { border-collapse: collapse; }
2723 td, th {
2724 vertical-align: top;
2725 <!--border: 1pt solid #ADB9CC;-->
2727 </style>"
2728 "The default style specification for exported HTML files.
2729 Since there are different ways of setting style information, this variable
2730 needs to contain the full HTML structure to provide a style, including the
2731 surrounding HTML tags. The style specifications should include definitions
2732 for new classes todo, done, title, and deadline. For example, legal values
2733 would be:
2735 <style type=\"text/css\">
2736 p { font-weight: normal; color: gray; }
2737 h1 { color: black; }
2738 .title { text-align: center; }
2739 .todo, .deadline { color: red; }
2740 .done { color: green; }
2741 </style>
2743 or, if you want to keep the style in a file,
2745 <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\">
2747 As the value of this option simply gets inserted into the HTML <head> header,
2748 you can \"misuse\" it to add arbitrary text to the header."
2749 :group 'org-export-html
2750 :type 'string)
2753 (defcustom org-export-html-title-format "<h1 class=\"title\">%s</h1>\n"
2754 "Format for typesetting the document title in HTML export."
2755 :group 'org-export-html
2756 :type 'string)
2758 (defcustom org-export-html-toplevel-hlevel 2
2759 "The <H> level for level 1 headings in HTML export."
2760 :group 'org-export-html
2761 :type 'string)
2763 (defcustom org-export-html-link-org-files-as-html t
2764 "Non-nil means, make file links to `file.org' point to `file.html'.
2765 When org-mode is exporting an org-mode file to HTML, links to
2766 non-html files are directly put into a href tag in HTML.
2767 However, links to other Org-mode files (recognized by the
2768 extension `.org.) should become links to the corresponding html
2769 file, assuming that the linked org-mode file will also be
2770 converted to HTML.
2771 When nil, the links still point to the plain `.org' file."
2772 :group 'org-export-html
2773 :type 'boolean)
2775 (defcustom org-export-html-inline-images 'maybe
2776 "Non-nil means, inline images into exported HTML pages.
2777 This is done using an <img> tag. When nil, an anchor with href is used to
2778 link to the image. If this option is `maybe', then images in links with
2779 an empty description will be inlined, while images with a description will
2780 be linked only."
2781 :group 'org-export-html
2782 :type '(choice (const :tag "Never" nil)
2783 (const :tag "Always" t)
2784 (const :tag "When there is no description" maybe)))
2786 ;; FIXME: rename
2787 (defcustom org-export-html-expand t
2788 "Non-nil means, for HTML export, treat @<...> as HTML tag.
2789 When nil, these tags will be exported as plain text and therefore
2790 not be interpreted by a browser.
2792 This option can also be set with the +OPTIONS line, e.g. \"@:nil\"."
2793 :group 'org-export-html
2794 :type 'boolean)
2796 (defcustom org-export-html-table-tag
2797 "<table border=\"2\" cellspacing=\"0\" cellpadding=\"6\" rules=\"groups\" frame=\"hsides\">"
2798 "The HTML tag that is used to start a table.
2799 This must be a <table> tag, but you may change the options like
2800 borders and spacing."
2801 :group 'org-export-html
2802 :type 'string)
2804 (defcustom org-export-table-header-tags '("<th>" . "</th>")
2805 "The opening tag for table header fields.
2806 This is customizable so that alignment options can be specified."
2807 :group 'org-export-tables
2808 :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
2810 (defcustom org-export-table-data-tags '("<td>" . "</td>")
2811 "The opening tag for table data fields.
2812 This is customizable so that alignment options can be specified."
2813 :group 'org-export-tables
2814 :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
2816 (defcustom org-export-html-with-timestamp nil
2817 "If non-nil, write `org-export-html-html-helper-timestamp'
2818 into the exported HTML text. Otherwise, the buffer will just be saved
2819 to a file."
2820 :group 'org-export-html
2821 :type 'boolean)
2823 (defcustom org-export-html-html-helper-timestamp
2824 "<br/><br/><hr><p><!-- hhmts start --> <!-- hhmts end --></p>\n"
2825 "The HTML tag used as timestamp delimiter for HTML-helper-mode."
2826 :group 'org-export-html
2827 :type 'string)
2829 (defgroup org-export-icalendar nil
2830 "Options specific for iCalendar export of Org-mode files."
2831 :tag "Org Export iCalendar"
2832 :group 'org-export)
2834 (defcustom org-combined-agenda-icalendar-file "~/org.ics"
2835 "The file name for the iCalendar file covering all agenda files.
2836 This file is created with the command \\[org-export-icalendar-all-agenda-files].
2837 The file name should be absolute."
2838 :group 'org-export-icalendar
2839 :type 'file)
2841 (defcustom org-icalendar-include-todo nil
2842 "Non-nil means, export to iCalendar files should also cover TODO items."
2843 :group 'org-export-icalendar
2844 :type '(choice
2845 (const :tag "None" nil)
2846 (const :tag "Unfinished" t)
2847 (const :tag "All" all)))
2849 (defcustom org-icalendar-include-sexps t
2850 "Non-nil means, export to iCalendar files should also cover sexp entries.
2851 These are entries like in the diary, but directly in an Org-mode file."
2852 :group 'org-export-icalendar
2853 :type 'boolean)
2855 (defcustom org-icalendar-combined-name "OrgMode"
2856 "Calendar name for the combined iCalendar representing all agenda files."
2857 :group 'org-export-icalendar
2858 :type 'string)
2860 (defgroup org-font-lock nil
2861 "Font-lock settings for highlighting in Org-mode."
2862 :tag "Org Font Lock"
2863 :group 'org)
2865 (defcustom org-level-color-stars-only nil
2866 "Non-nil means fontify only the stars in each headline.
2867 When nil, the entire headline is fontified.
2868 Changing it requires restart of `font-lock-mode' to become effective
2869 also in regions already fontified."
2870 :group 'org-font-lock
2871 :type 'boolean)
2873 (defcustom org-hide-leading-stars nil
2874 "Non-nil means, hide the first N-1 stars in a headline.
2875 This works by using the face `org-hide' for these stars. This
2876 face is white for a light background, and black for a dark
2877 background. You may have to customize the face `org-hide' to
2878 make this work.
2879 Changing it requires restart of `font-lock-mode' to become effective
2880 also in regions already fontified.
2881 You may also set this on a per-file basis by adding one of the following
2882 lines to the buffer:
2884 #+STARTUP: hidestars
2885 #+STARTUP: showstars"
2886 :group 'org-font-lock
2887 :type 'boolean)
2889 (defcustom org-fontify-done-headline nil
2890 "Non-nil means, change the face of a headline if it is marked DONE.
2891 Normally, only the TODO/DONE keyword indicates the state of a headline.
2892 When this is non-nil, the headline after the keyword is set to the
2893 `org-headline-done' as an additional indication."
2894 :group 'org-font-lock
2895 :type 'boolean)
2897 (defcustom org-fontify-emphasized-text t
2898 "Non-nil means fontify *bold*, /italic/ and _underlined_ text.
2899 Changing this variable requires a restart of Emacs to take effect."
2900 :group 'org-font-lock
2901 :type 'boolean)
2903 (defvar org-emph-re nil
2904 "Regular expression for matching emphasis.")
2905 (defvar org-emphasis-regexp-components) ; defined just below
2906 (defvar org-emphasis-alist) ; defined just below
2907 (defun org-set-emph-re (var val)
2908 "Set variable and compute the emphasis regular expression."
2909 (set var val)
2910 (when (and (boundp 'org-emphasis-alist)
2911 (boundp 'org-emphasis-regexp-components)
2912 org-emphasis-alist org-emphasis-regexp-components)
2913 (let* ((e org-emphasis-regexp-components)
2914 (pre (car e))
2915 (post (nth 1 e))
2916 (border (nth 2 e))
2917 (body (nth 3 e))
2918 (nl (nth 4 e))
2919 (stacked (nth 5 e))
2920 (body1 (concat body "*?"))
2921 (markers (mapconcat 'car org-emphasis-alist "")))
2922 ;; make sure special characters appear at the right position in the class
2923 (if (string-match "\\^" markers)
2924 (setq markers (concat (replace-match "" t t markers) "^")))
2925 (if (string-match "-" markers)
2926 (setq markers (concat (replace-match "" t t markers) "-")))
2927 (if (> nl 0)
2928 (setq body1 (concat body1 "\\(?:\n" body "*?\\)\\{0,"
2929 (int-to-string nl) "\\}")))
2930 ;; Make the regexp
2931 (setq org-emph-re
2932 (concat "\\([" pre (if stacked markers) "]\\|^\\)"
2933 "\\("
2934 "\\([" markers "]\\)"
2935 "\\("
2936 "[^" border (if (and nil stacked) markers) "]"
2937 body1
2938 "[^" border (if (and nil stacked) markers) "]"
2939 "\\)"
2940 "\\3\\)"
2941 "\\([" post (if stacked markers) "]\\|$\\)")))))
2943 (defcustom org-emphasis-regexp-components
2944 '(" \t('\"" "- \t.,:?;'\")" " \t\r\n,\"'" "." 1 nil)
2945 "Components used to build the reqular expression for emphasis.
2946 This is a list with 6 entries. Terminology: In an emphasis string
2947 like \" *strong word* \", we call the initial space PREMATCH, the final
2948 space POSTMATCH, the stars MARKERS, \"s\" and \"d\" are BORDER characters
2949 and \"trong wor\" is the body. The different components in this variable
2950 specify what is allowed/forbidden in each part:
2952 pre Chars allowed as prematch. Beginning of line will be allowed too.
2953 post Chars allowed as postmatch. End of line will be allowed too.
2954 border The chars *forbidden* as border characters. In addition to the
2955 characters given here, all marker characters are forbidden too.
2956 FIXME: the last statement is no longer true.
2957 body-regexp A regexp like \".\" to match a body character. Don't use
2958 non-shy groups here, and don't allow newline here.
2959 newline The maximum number of newlines allowed in an emphasis exp.
2960 stacked Non-nil means, allow stacked styles. This works only in HTML
2961 export. When this is set, all marker characters (as given in
2962 `org-emphasis-alist') will be allowed as pre/post, aiding
2963 inside-out matching.
2964 Use customize to modify this, or restart Emacs after changing it."
2965 :group 'org-font-lock
2966 :set 'org-set-emph-re
2967 :type '(list
2968 (sexp :tag "Allowed chars in pre ")
2969 (sexp :tag "Allowed chars in post ")
2970 (sexp :tag "Forbidden chars in border ")
2971 (sexp :tag "Regexp for body ")
2972 (integer :tag "number of newlines allowed")
2973 (boolean :tag "Stacking allowed ")))
2975 (defcustom org-emphasis-alist
2976 '(("*" bold "<b>" "</b>")
2977 ("/" italic "<i>" "</i>")
2978 ("_" underline "<u>" "</u>")
2979 ("=" shadow "<code>" "</code>")
2980 ("+" (:strike-through t) "<del>" "</del>")
2982 "Special syntax for emphasized text.
2983 Text starting and ending with a special character will be emphasized, for
2984 example *bold*, _underlined_ and /italic/. This variable sets the marker
2985 characters, the face to be used by font-lock for highlighting in Org-mode
2986 Emacs buffers, and the HTML tags to be used for this.
2987 Use customize to modify this, or restart Emacs after changing it."
2988 :group 'org-font-lock
2989 :set 'org-set-emph-re
2990 :type '(repeat
2991 (list
2992 (string :tag "Marker character")
2993 (choice
2994 (face :tag "Font-lock-face")
2995 (plist :tag "Face property list"))
2996 (string :tag "HTML start tag")
2997 (string :tag "HTML end tag"))))
2999 ;;; The faces
3001 (defgroup org-faces nil
3002 "Faces in Org-mode."
3003 :tag "Org Faces"
3004 :group 'org-font-lock)
3006 (defun org-compatible-face (specs)
3007 "Make a compatible face specification.
3008 XEmacs and Emacs 21 do not know about the `min-colors' attribute.
3009 For them we convert a (min-colors 8) entry to a `tty' entry and move it
3010 to the top of the list. The `min-colors' attribute will be removed from
3011 any other entries, and any resulting duplicates will be removed entirely."
3012 (if (or (featurep 'xemacs) (< emacs-major-version 22))
3013 (let (r e a)
3014 (while (setq e (pop specs))
3015 (cond
3016 ((memq (car e) '(t default)) (push e r))
3017 ((setq a (member '(min-colors 8) (car e)))
3018 (nconc r (list (cons (cons '(type tty) (delq (car a) (car e)))
3019 (cdr e)))))
3020 ((setq a (assq 'min-colors (car e)))
3021 (setq e (cons (delq a (car e)) (cdr e)))
3022 (or (assoc (car e) r) (push e r)))
3023 (t (or (assoc (car e) r) (push e r)))))
3024 (nreverse r))
3025 specs))
3027 (defface org-hide
3028 '((((background light)) (:foreground "white"))
3029 (((background dark)) (:foreground "black")))
3030 "Face used to hide leading stars in headlines.
3031 The forground color of this face should be equal to the background
3032 color of the frame."
3033 :group 'org-faces)
3035 (defface org-level-1 ;; font-lock-function-name-face
3036 (org-compatible-face
3037 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
3038 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
3039 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
3040 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
3041 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
3042 (t (:bold t))))
3043 "Face used for level 1 headlines."
3044 :group 'org-faces)
3046 (defface org-level-2 ;; font-lock-variable-name-face
3047 (org-compatible-face
3048 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
3049 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
3050 (((class color) (min-colors 8) (background light)) (:foreground "yellow"))
3051 (((class color) (min-colors 8) (background dark)) (:foreground "yellow" :bold t))
3052 (t (:bold t))))
3053 "Face used for level 2 headlines."
3054 :group 'org-faces)
3056 (defface org-level-3 ;; font-lock-keyword-face
3057 (org-compatible-face
3058 '((((class color) (min-colors 88) (background light)) (:foreground "Purple"))
3059 (((class color) (min-colors 88) (background dark)) (:foreground "Cyan1"))
3060 (((class color) (min-colors 16) (background light)) (:foreground "Purple"))
3061 (((class color) (min-colors 16) (background dark)) (:foreground "Cyan"))
3062 (((class color) (min-colors 8) (background light)) (:foreground "purple" :bold t))
3063 (((class color) (min-colors 8) (background dark)) (:foreground "cyan" :bold t))
3064 (t (:bold t))))
3065 "Face used for level 3 headlines."
3066 :group 'org-faces)
3068 (defface org-level-4 ;; font-lock-comment-face
3069 (org-compatible-face
3070 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
3071 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
3072 (((class color) (min-colors 16) (background light)) (:foreground "red"))
3073 (((class color) (min-colors 16) (background dark)) (:foreground "red1"))
3074 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
3075 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3076 (t (:bold t))))
3077 "Face used for level 4 headlines."
3078 :group 'org-faces)
3080 (defface org-level-5 ;; font-lock-type-face
3081 (org-compatible-face
3082 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
3083 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
3084 (((class color) (min-colors 8)) (:foreground "green"))))
3085 "Face used for level 5 headlines."
3086 :group 'org-faces)
3088 (defface org-level-6 ;; font-lock-constant-face
3089 (org-compatible-face
3090 '((((class color) (min-colors 16) (background light)) (:foreground "CadetBlue"))
3091 (((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine"))
3092 (((class color) (min-colors 8)) (:foreground "magenta"))))
3093 "Face used for level 6 headlines."
3094 :group 'org-faces)
3096 (defface org-level-7 ;; font-lock-builtin-face
3097 (org-compatible-face
3098 '((((class color) (min-colors 16) (background light)) (:foreground "Orchid"))
3099 (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue"))
3100 (((class color) (min-colors 8)) (:foreground "blue"))))
3101 "Face used for level 7 headlines."
3102 :group 'org-faces)
3104 (defface org-level-8 ;; font-lock-string-face
3105 (org-compatible-face
3106 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
3107 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
3108 (((class color) (min-colors 8)) (:foreground "green"))))
3109 "Face used for level 8 headlines."
3110 :group 'org-faces)
3112 (defface org-special-keyword ;; font-lock-string-face
3113 (org-compatible-face
3114 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
3115 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
3116 (t (:italic t))))
3117 "Face used for special keywords."
3118 :group 'org-faces)
3120 (defface org-warning ;; font-lock-warning-face
3121 (org-compatible-face
3122 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
3123 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
3124 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
3125 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3126 (t (:bold t))))
3127 "Face for deadlines and TODO keywords."
3128 :group 'org-faces)
3130 (defface org-archived ; similar to shadow
3131 (org-compatible-face
3132 '((((class color grayscale) (min-colors 88) (background light))
3133 (:foreground "grey50"))
3134 (((class color grayscale) (min-colors 88) (background dark))
3135 (:foreground "grey70"))
3136 (((class color) (min-colors 8) (background light))
3137 (:foreground "green"))
3138 (((class color) (min-colors 8) (background dark))
3139 (:foreground "yellow"))))
3140 "Face for headline with the ARCHIVE tag."
3141 :group 'org-faces)
3143 (defface org-link
3144 '((((class color) (background light)) (:foreground "Purple" :underline t))
3145 (((class color) (background dark)) (:foreground "Cyan" :underline t))
3146 (t (:underline t)))
3147 "Face for links."
3148 :group 'org-faces)
3150 (defface org-date
3151 '((((class color) (background light)) (:foreground "Purple" :underline t))
3152 (((class color) (background dark)) (:foreground "Cyan" :underline t))
3153 (t (:underline t)))
3154 "Face for links."
3155 :group 'org-faces)
3157 (defface org-sexp-date
3158 '((((class color) (background light)) (:foreground "Purple"))
3159 (((class color) (background dark)) (:foreground "Cyan"))
3160 (t (:underline t)))
3161 "Face for links."
3162 :group 'org-faces)
3164 (defface org-tag
3165 '((t (:bold t)))
3166 "Face for tags."
3167 :group 'org-faces)
3169 (defface org-todo ;; font-lock-warning-face
3170 (org-compatible-face
3171 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
3172 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
3173 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
3174 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3175 (t (:inverse-video t :bold t))))
3176 "Face for TODO keywords."
3177 :group 'org-faces)
3179 (defface org-done ;; font-lock-type-face
3180 (org-compatible-face
3181 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen" :bold t))
3182 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen" :bold t))
3183 (((class color) (min-colors 8)) (:foreground "green"))
3184 (t (:bold t))))
3185 "Face used for todo keywords that indicate DONE items."
3186 :group 'org-faces)
3188 (defface org-headline-done ;; font-lock-string-face
3189 (org-compatible-face
3190 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
3191 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
3192 (((class color) (min-colors 8) (background light)) (:bold nil))))
3193 "Face used to indicate that a headline is DONE.
3194 This face is only used if `org-fontify-done-headline' is set. If applies
3195 to the part of the headline after the DONE keyword."
3196 :group 'org-faces)
3198 (defface org-table ;; font-lock-function-name-face
3199 (org-compatible-face
3200 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
3201 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
3202 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
3203 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
3204 (((class color) (min-colors 8) (background light)) (:foreground "blue"))
3205 (((class color) (min-colors 8) (background dark)))))
3206 "Face used for tables."
3207 :group 'org-faces)
3209 (defface org-formula
3210 (org-compatible-face
3211 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
3212 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
3213 (((class color) (min-colors 8) (background light)) (:foreground "red"))
3214 (((class color) (min-colors 8) (background dark)) (:foreground "red"))
3215 (t (:bold t :italic t))))
3216 "Face for formulas."
3217 :group 'org-faces)
3219 (defface org-agenda-structure ;; font-lock-function-name-face
3220 (org-compatible-face
3221 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
3222 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
3223 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
3224 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
3225 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
3226 (t (:bold t))))
3227 "Face used in agenda for captions and dates."
3228 :group 'org-faces)
3230 (defface org-scheduled-today
3231 (org-compatible-face
3232 '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen"))
3233 (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen"))
3234 (((class color) (min-colors 8)) (:foreground "green"))
3235 (t (:bold t :italic t))))
3236 "Face for items scheduled for a certain day."
3237 :group 'org-faces)
3239 (defface org-scheduled-previously
3240 (org-compatible-face
3241 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
3242 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
3243 (((class color) (min-colors 8) (background light)) (:foreground "red"))
3244 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3245 (t (:bold t))))
3246 "Face for items scheduled previously, and not yet done."
3247 :group 'org-faces)
3249 (defface org-upcoming-deadline
3250 (org-compatible-face
3251 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
3252 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
3253 (((class color) (min-colors 8) (background light)) (:foreground "red"))
3254 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3255 (t (:bold t))))
3256 "Face for items scheduled previously, and not yet done."
3257 :group 'org-faces)
3259 (defface org-time-grid ;; font-lock-variable-name-face
3260 (org-compatible-face
3261 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
3262 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
3263 (((class color) (min-colors 8)) (:foreground "yellow" :weight light))))
3264 "Face used for time grids."
3265 :group 'org-faces)
3267 (defconst org-level-faces
3268 '(org-level-1 org-level-2 org-level-3 org-level-4
3269 org-level-5 org-level-6 org-level-7 org-level-8
3271 (defconst org-n-levels (length org-level-faces))
3274 ;;; Variables for pre-computed regular expressions, all buffer local
3276 (defvar org-todo-regexp nil
3277 "Matches any of the TODO state keywords.")
3278 (make-variable-buffer-local 'org-todo-regexp)
3279 (defvar org-not-done-regexp nil
3280 "Matches any of the TODO state keywords except the last one.")
3281 (make-variable-buffer-local 'org-not-done-regexp)
3282 (defvar org-todo-line-regexp nil
3283 "Matches a headline and puts TODO state into group 2 if present.")
3284 (make-variable-buffer-local 'org-todo-line-regexp)
3285 (defvar org-todo-line-tags-regexp nil
3286 "Matches a headline and puts TODO state into group 2 if present.
3287 Also put tags into group 4 if tags are present.")
3288 (make-variable-buffer-local 'org-todo-line-tags-regexp)
3289 (defvar org-nl-done-regexp nil
3290 "Matches newline followed by a headline with the DONE keyword.")
3291 (make-variable-buffer-local 'org-nl-done-regexp)
3292 (defvar org-looking-at-done-regexp nil
3293 "Matches the DONE keyword a point.")
3294 (make-variable-buffer-local 'org-looking-at-done-regexp)
3295 (defvar org-ds-keyword-length 12
3296 "Maximum length of the Deadline and SCHEDULED keywords.")
3297 (make-variable-buffer-local 'org-ds-keyword-length)
3298 (defvar org-deadline-regexp nil
3299 "Matches the DEADLINE keyword.")
3300 (make-variable-buffer-local 'org-deadline-regexp)
3301 (defvar org-deadline-time-regexp nil
3302 "Matches the DEADLINE keyword together with a time stamp.")
3303 (make-variable-buffer-local 'org-deadline-time-regexp)
3304 (defvar org-deadline-line-regexp nil
3305 "Matches the DEADLINE keyword and the rest of the line.")
3306 (make-variable-buffer-local 'org-deadline-line-regexp)
3307 (defvar org-scheduled-regexp nil
3308 "Matches the SCHEDULED keyword.")
3309 (make-variable-buffer-local 'org-scheduled-regexp)
3310 (defvar org-scheduled-time-regexp nil
3311 "Matches the SCHEDULED keyword together with a time stamp.")
3312 (make-variable-buffer-local 'org-scheduled-time-regexp)
3313 (defvar org-closed-time-regexp nil
3314 "Matches the CLOSED keyword together with a time stamp.")
3315 (make-variable-buffer-local 'org-closed-time-regexp)
3317 (defvar org-keyword-time-regexp nil
3318 "Matches any of the 4 keywords, together with the time stamp.")
3319 (make-variable-buffer-local 'org-keyword-time-regexp)
3320 (defvar org-keyword-time-not-clock-regexp nil
3321 "Matches any of the 3 keywords, together with the time stamp.")
3322 (make-variable-buffer-local 'org-keyword-time-not-clock-regexp)
3323 (defvar org-maybe-keyword-time-regexp nil
3324 "Matches a timestamp, possibly preceeded by a keyword.")
3325 (make-variable-buffer-local 'org-maybe-keyword-time-regexp)
3326 (defvar org-planning-or-clock-line-re nil
3327 "Matches a line with planning or clock info.")
3328 (make-variable-buffer-local 'org-planning-or-clock-line-re)
3330 (defconst org-rm-props '(invisible t face t keymap t intangible t mouse-face t
3331 rear-nonsticky t mouse-map t fontified t)
3332 "Properties to remove when a string without properties is wanted.")
3334 (defsubst org-match-string-no-properties (num &optional string)
3335 (if (featurep 'xemacs)
3336 (let ((s (match-string num string)))
3337 (remove-text-properties 0 (length s) org-rm-props s)
3339 (match-string-no-properties num string)))
3341 (defsubst org-no-properties (s)
3342 (remove-text-properties 0 (length s) org-rm-props s)
3345 (defsubst org-get-alist-option (option key)
3346 (cond ((eq key t) t)
3347 ((eq option t) t)
3348 ((assoc key option) (cdr (assoc key option)))
3349 (t (cdr (assq 'default option)))))
3351 (defsubst org-inhibit-invisibility ()
3352 "Modified `buffer-invisibility-spec' for Emacs 21.
3353 Some ops with invisible text do not work correctly on Emacs 21. For these
3354 we turn off invisibility temporarily. Use this in a `let' form."
3355 (if (< emacs-major-version 22) nil buffer-invisibility-spec))
3357 (defsubst org-set-local (var value)
3358 "Make VAR local in current buffer and set it to VALUE."
3359 (set (make-variable-buffer-local var) value))
3361 (defsubst org-mode-p ()
3362 "Check if the current buffer is in Org-mode."
3363 (eq major-mode 'org-mode))
3365 (defsubst org-last (list)
3366 "Return the last element of LIST."
3367 (car (last list)))
3369 (defun org-let (list &rest body)
3370 (eval (cons 'let (cons list body))))
3371 (put 'org-let 'lisp-indent-function 1)
3373 (defun org-let2 (list1 list2 &rest body)
3374 (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body)))))))
3375 (put 'org-let2 'lisp-indent-function 2)
3376 (defconst org-startup-options
3377 '(("fold" org-startup-folded t)
3378 ("overview" org-startup-folded t)
3379 ("nofold" org-startup-folded nil)
3380 ("showall" org-startup-folded nil)
3381 ("content" org-startup-folded content)
3382 ("hidestars" org-hide-leading-stars t)
3383 ("showstars" org-hide-leading-stars nil)
3384 ("odd" org-odd-levels-only t)
3385 ("oddeven" org-odd-levels-only nil)
3386 ("align" org-startup-align-all-tables t)
3387 ("noalign" org-startup-align-all-tables nil)
3388 ("customtime" org-display-custom-times t)
3389 ("logging" org-log-done t)
3390 ("logdone" org-log-done t)
3391 ("nologging" org-log-done nil)
3392 ("lognotedone" org-log-done done push)
3393 ("lognotestate" org-log-done state push)
3394 ("lognoteclock-out" org-log-done clock-out push)
3395 ("logrepeat" org-log-repeat t)
3396 ("nologrepeat" org-log-repeat nil)
3397 ("constcgs" constants-unit-system cgs)
3398 ("constSI" constants-unit-system SI))
3399 "Variable associated with STARTUP options for org-mode.
3400 Each element is a list of three items: The startup options as written
3401 in the #+STARTUP line, the corresponding variable, and the value to
3402 set this variable to if the option is found. An optional forth element PUSH
3403 means to push this value onto the list in the variable.")
3405 (defun org-set-regexps-and-options ()
3406 "Precompute regular expressions for current buffer."
3407 (when (org-mode-p)
3408 (org-set-local 'org-todo-kwd-alist nil)
3409 (org-set-local 'org-todo-keywords-1 nil)
3410 (org-set-local 'org-done-keywords nil)
3411 (org-set-local 'org-todo-heads nil)
3412 (org-set-local 'org-todo-sets nil)
3413 (let ((re (org-make-options-regexp
3414 '("CATEGORY" "SEQ_TODO" "PRI_TODO" "TYP_TODO"
3415 "STARTUP" "ARCHIVE" "TAGS" "LINK" "PRIORITIES")))
3416 (splitre "[ \t]+")
3417 kwds key value cat arch tags links hw dws tail sep kws1 prio)
3418 (save-excursion
3419 (save-restriction
3420 (widen)
3421 (goto-char (point-min))
3422 (while (re-search-forward re nil t)
3423 (setq key (match-string 1) value (org-match-string-no-properties 2))
3424 (cond
3425 ((equal key "CATEGORY")
3426 (if (string-match "[ \t]+$" value)
3427 (setq value (replace-match "" t t value)))
3428 (setq cat (intern value)))
3429 ((equal key "SEQ_TODO")
3430 (push (cons 'sequence (org-split-string value splitre)) kwds))
3431 ((equal key "TYP_TODO")
3432 (push (cons 'type (org-split-string value splitre)) kwds))
3433 ((equal key "TAGS")
3434 (setq tags (append tags (org-split-string value splitre))))
3435 ((equal key "LINK")
3436 (when (string-match "^\\(\\S-+\\)[ \t]+\\(.+\\)" value)
3437 (push (cons (match-string 1 value)
3438 (org-trim (match-string 2 value)))
3439 links)))
3440 ((equal key "PRIORITIES")
3441 (setq prio (org-split-string " +" value)))
3442 ((equal key "STARTUP")
3443 (let ((opts (org-split-string value splitre))
3444 l var val)
3445 (while (setq l (pop opts))
3446 (when (setq l (assoc l org-startup-options))
3447 (setq var (nth 1 l) val (nth 2 l))
3448 (if (not (nth 3 l))
3449 (set (make-local-variable var) val)
3450 (if (not (listp (symbol-value var)))
3451 (set (make-local-variable var) nil))
3452 (set (make-local-variable var) (symbol-value var))
3453 (add-to-list var val))))))
3454 ((equal key "ARCHIVE")
3455 (string-match " *$" value)
3456 (setq arch (replace-match "" t t value))
3457 (remove-text-properties 0 (length arch)
3458 '(face t fontified t) arch)))
3460 (and cat (org-set-local 'org-category cat))
3461 (when prio
3462 (if (< (length prio) 3) (setq prio '("A" "C" "B")))
3463 (setq prio (mapcar 'string-to-char prio))
3464 (org-set-local 'org-highest-priority (nth 0 prio))
3465 (org-set-local 'org-lowest-priority (nth 1 prio))
3466 (org-set-local 'org-default-priority (nth 2 prio)))
3467 (and arch (org-set-local 'org-archive-location arch))
3468 (and links (setq org-link-abbrev-alist-local (nreverse links)))
3469 ;; Process the TODO keywords
3470 (unless kwds
3471 ;; Use the global values as if they had been given locally.
3472 (setq kwds (default-value 'org-todo-keywords))
3473 (if (stringp (car kwds))
3474 (setq kwds (list (cons org-todo-interpretation
3475 (default-value 'org-todo-keywords)))))
3476 (setq kwds (reverse kwds)))
3477 (setq kwds (nreverse kwds))
3478 (let (inter kws)
3479 (while (setq kws (pop kwds))
3480 (setq inter (pop kws) sep (member "|" kws)
3481 kws1 (delete "|" (copy-sequence kws))
3482 hw (car kws1)
3483 dws (if sep (cdr sep) (last kws1))
3484 tail (list inter hw (car dws) (org-last dws)))
3485 (add-to-list 'org-todo-heads hw 'append)
3486 (push kws1 org-todo-sets)
3487 (setq org-done-keywords (append org-done-keywords dws nil))
3488 (mapc (lambda (x) (push (cons x tail) org-todo-kwd-alist)) kws1)
3489 (setq org-todo-keywords-1 (append org-todo-keywords-1 kws1 nil)))
3490 (setq org-todo-sets (nreverse org-todo-sets)
3491 org-todo-kwd-alist (nreverse org-todo-kwd-alist)))
3492 ;; Process the tags.
3493 (when tags
3494 (let (e tgs)
3495 (while (setq e (pop tags))
3496 (cond
3497 ((equal e "{") (push '(:startgroup) tgs))
3498 ((equal e "}") (push '(:endgroup) tgs))
3499 ((string-match "^\\([0-9a-zA-Z_@]+\\)(\\(.\\))$" e)
3500 (push (cons (match-string 1 e)
3501 (string-to-char (match-string 2 e)))
3502 tgs))
3503 (t (push (list e) tgs))))
3504 (org-set-local 'org-tag-alist nil)
3505 (while (setq e (pop tgs))
3506 (or (and (stringp (car e))
3507 (assoc (car e) org-tag-alist))
3508 (push e org-tag-alist))))))
3510 ;; Compute the regular expressions and other local variables
3511 (if (not org-done-keywords)
3512 (setq org-done-keywords (list (org-last org-todo-keywords-1))))
3513 (setq org-ds-keyword-length (+ 2 (max (length org-deadline-string)
3514 (length org-scheduled-string)))
3515 org-not-done-keywords
3516 (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1))
3517 org-todo-regexp
3518 (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords-1
3519 "\\|") "\\)\\>")
3520 org-not-done-regexp
3521 (concat "\\<\\("
3522 (mapconcat 'regexp-quote org-not-done-keywords "\\|")
3523 "\\)\\>")
3524 org-todo-line-regexp
3525 (concat "^\\(\\*+\\)[ \t]*\\(?:\\("
3526 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
3527 "\\)\\>\\)? *\\(.*\\)")
3528 org-nl-done-regexp
3529 (concat "[\r\n]\\*+[ \t]+"
3530 "\\(?:" (mapconcat 'regexp-quote org-done-keywords "\\|")
3531 "\\)" "\\>")
3532 org-todo-line-tags-regexp
3533 (concat "^\\(\\*+\\)[ \t]*\\(?:\\("
3534 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
3535 "\\)\\>\\)? *\\(.*?\\([ \t]:[a-zA-Z0-9:_@]+:[ \t]*\\)?$\\)")
3536 org-looking-at-done-regexp
3537 (concat "^" "\\(?:"
3538 (mapconcat 'regexp-quote org-done-keywords "\\|") "\\)"
3539 "\\>")
3540 org-deadline-regexp (concat "\\<" org-deadline-string)
3541 org-deadline-time-regexp
3542 (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
3543 org-deadline-line-regexp
3544 (concat "\\<\\(" org-deadline-string "\\).*")
3545 org-scheduled-regexp
3546 (concat "\\<" org-scheduled-string)
3547 org-scheduled-time-regexp
3548 (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
3549 org-closed-time-regexp
3550 (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
3551 org-keyword-time-regexp
3552 (concat "\\<\\(" org-scheduled-string
3553 "\\|" org-deadline-string
3554 "\\|" org-closed-string
3555 "\\|" org-clock-string "\\)"
3556 " *[[<]\\([^]>]+\\)[]>]")
3557 org-keyword-time-not-clock-regexp
3558 (concat "\\<\\(" org-scheduled-string
3559 "\\|" org-deadline-string
3560 "\\|" org-closed-string "\\)"
3561 " *[[<]\\([^]>]+\\)[]>]")
3562 org-maybe-keyword-time-regexp
3563 (concat "\\(\\<\\(" org-scheduled-string
3564 "\\|" org-deadline-string
3565 "\\|" org-closed-string
3566 "\\|" org-clock-string "\\)\\)?"
3567 " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^]\r\n>]*?[]>]\\|<%%([^\r\n>]*>\\)")
3568 org-planning-or-clock-line-re
3569 (concat "\\(?:^[ \t]*\\(" org-scheduled-string
3570 "\\|" org-deadline-string
3571 "\\|" org-closed-string "\\|" org-clock-string "\\)\\>\\)")
3574 (org-set-font-lock-defaults)))
3577 ;;; Some variables ujsed in various places
3579 (defvar org-window-configuration nil
3580 "Used in various places to store a window configuration.")
3581 (defvar org-finish-function nil
3582 "Function to be called when `C-c C-c' is used.
3583 This is for getting out of special buffers like remember.")
3585 ;;; Foreign variables, to inform the compiler
3587 ;; XEmacs only
3588 (defvar outline-mode-menu-heading)
3589 (defvar outline-mode-menu-show)
3590 (defvar outline-mode-menu-hide)
3591 (defvar zmacs-regions) ; XEmacs regions
3592 ;; Emacs only
3593 (defvar mark-active)
3595 ;; Packages that org-mode interacts with
3596 (defvar calc-embedded-close-formula)
3597 (defvar calc-embedded-open-formula)
3598 (defvar font-lock-unfontify-region-function)
3599 (defvar org-goto-start-pos)
3600 (defvar vm-message-pointer)
3601 (defvar vm-folder-directory)
3602 (defvar wl-summary-buffer-elmo-folder)
3603 (defvar wl-summary-buffer-folder-name)
3604 (defvar gnus-other-frame-object)
3605 (defvar gnus-group-name)
3606 (defvar gnus-article-current)
3607 (defvar w3m-current-url)
3608 (defvar w3m-current-title)
3609 (defvar mh-progs)
3610 (defvar mh-current-folder)
3611 (defvar mh-show-folder-buffer)
3612 (defvar mh-index-folder)
3613 (defvar mh-searcher)
3614 (defvar calendar-mode-map)
3615 (defvar Info-current-file)
3616 (defvar Info-current-node)
3617 (defvar texmathp-why)
3618 (defvar remember-save-after-remembering)
3619 (defvar remember-data-file)
3620 (defvar annotation) ; from remember.el, dynamically scoped in `remember-mode'
3621 (defvar initial) ; from remember.el, dynamically scoped in `remember-mode'
3622 (defvar org-latex-regexps)
3623 (defvar constants-unit-system)
3625 (defvar original-date) ; dynamically scoped in calendar.el does scope this
3627 ;; FIXME: Occasionally check by commenting these, to make sure
3628 ;; no other functions uses these, forgetting to let-bind them.
3629 (defvar entry)
3630 (defvar state)
3631 (defvar last-state)
3632 (defvar date)
3633 (defvar description)
3636 ;; Defined somewhere in this file, but used before definition.
3637 (defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized
3638 (defvar org-agenda-undo-list)
3639 (defvar org-agenda-pending-undo-list)
3640 (defvar org-agenda-overriding-header)
3641 (defvar orgtbl-mode)
3642 (defvar org-html-entities)
3643 (defvar org-struct-menu)
3644 (defvar org-org-menu)
3645 (defvar org-tbl-menu)
3646 (defvar org-agenda-keymap)
3647 (defvar org-category-table)
3649 ;;;; Emacs/XEmacs compatibility
3651 ;; Overlay compatibility functions
3652 (defun org-make-overlay (beg end &optional buffer)
3653 (if (featurep 'xemacs)
3654 (make-extent beg end buffer)
3655 (make-overlay beg end buffer)))
3656 (defun org-delete-overlay (ovl)
3657 (if (featurep 'xemacs) (delete-extent ovl) (delete-overlay ovl)))
3658 (defun org-detach-overlay (ovl)
3659 (if (featurep 'xemacs) (detach-extent ovl) (delete-overlay ovl)))
3660 (defun org-move-overlay (ovl beg end &optional buffer)
3661 (if (featurep 'xemacs)
3662 (set-extent-endpoints ovl beg end (or buffer (current-buffer)))
3663 (move-overlay ovl beg end buffer)))
3664 (defun org-overlay-put (ovl prop value)
3665 (if (featurep 'xemacs)
3666 (set-extent-property ovl prop value)
3667 (overlay-put ovl prop value)))
3668 (defun org-overlay-display (ovl text &optional face evap)
3669 "Make overlay OVL display TEXT with face FACE."
3670 (if (featurep 'xemacs)
3671 (let ((gl (make-glyph text)))
3672 (and face (set-glyph-face gl face))
3673 (set-extent-property ovl 'invisible t)
3674 (set-extent-property ovl 'end-glyph gl))
3675 (overlay-put ovl 'display text)
3676 (if face (overlay-put ovl 'face face))
3677 (if evap (overlay-put ovl 'evaporate t))))
3678 (defun org-overlay-before-string (ovl text &optional face evap)
3679 "Make overlay OVL display TEXT with face FACE."
3680 (if (featurep 'xemacs)
3681 (let ((gl (make-glyph text)))
3682 (and face (set-glyph-face gl face))
3683 (set-extent-property ovl 'begin-glyph gl))
3684 (if face (org-add-props text nil 'face face))
3685 (overlay-put ovl 'before-string text)
3686 (if evap (overlay-put ovl 'evaporate t))))
3687 (defun org-overlay-get (ovl prop)
3688 (if (featurep 'xemacs)
3689 (extent-property ovl prop)
3690 (overlay-get ovl prop)))
3691 (defun org-overlays-at (pos)
3692 (if (featurep 'xemacs) (extents-at pos) (overlays-at pos)))
3693 ;; FIXME: this is currently not used
3694 (defun org-overlays-in (&optional start end)
3695 (if (featurep 'xemacs)
3696 (extent-list nil start end)
3697 (overlays-in start end)))
3698 (defun org-overlay-start (o)
3699 (if (featurep 'xemacs) (extent-start-position o) (overlay-start o)))
3700 (defun org-overlay-end (o)
3701 (if (featurep 'xemacs) (extent-end-position o) (overlay-end o)))
3702 ;; FIXME: this is currently not used
3703 (defun org-find-overlays (prop &optional pos delete)
3704 "Find all overlays specifying PROP at POS or point.
3705 If DELETE is non-nil, delete all those overlays."
3706 (let ((overlays (org-overlays-at (or pos (point))))
3707 ov found)
3708 (while (setq ov (pop overlays))
3709 (if (org-overlay-get ov prop)
3710 (if delete (org-delete-overlay ov) (push ov found))))
3711 found))
3713 ;; Region compatibility
3715 (defun org-add-hook (hook function &optional append local)
3716 "Add-hook, compatible with both Emacsen."
3717 (if (and local (featurep 'xemacs))
3718 (add-local-hook hook function append)
3719 (add-hook hook function append local)))
3721 (defvar org-ignore-region nil
3722 "To temporarily disable the active region.")
3724 (defun org-region-active-p ()
3725 "Is `transient-mark-mode' on and the region active?
3726 Works on both Emacs and XEmacs."
3727 (if org-ignore-region
3729 (if (featurep 'xemacs)
3730 (and zmacs-regions (region-active-p))
3731 (and transient-mark-mode mark-active))))
3733 ;; Invisibility compatibility
3735 (defun org-add-to-invisibility-spec (arg)
3736 "Add elements to `buffer-invisibility-spec'.
3737 See documentation for `buffer-invisibility-spec' for the kind of elements
3738 that can be added."
3739 (cond
3740 ((fboundp 'add-to-invisibility-spec)
3741 (add-to-invisibility-spec arg))
3742 ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t))
3743 (setq buffer-invisibility-spec (list arg)))
3745 (setq buffer-invisibility-spec
3746 (cons arg buffer-invisibility-spec)))))
3748 (defun org-remove-from-invisibility-spec (arg)
3749 "Remove elements from `buffer-invisibility-spec'."
3750 (if (fboundp 'remove-from-invisibility-spec)
3751 (remove-from-invisibility-spec arg)
3752 (if (consp buffer-invisibility-spec)
3753 (setq buffer-invisibility-spec
3754 (delete arg buffer-invisibility-spec)))))
3756 ;; FIXME: this is currently not used
3757 (defun org-in-invisibility-spec-p (arg)
3758 "Is ARG a member of `buffer-invisibility-spec'?"
3759 (if (consp buffer-invisibility-spec)
3760 (member arg buffer-invisibility-spec)
3761 nil))
3763 ;;;; Define the Org-mode
3765 (if (and (not (keymapp outline-mode-map)) (featurep 'allout))
3766 (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."))
3769 ;; We use a before-change function to check if a table might need
3770 ;; an update.
3771 (defvar org-table-may-need-update t
3772 "Indicates that a table might need an update.
3773 This variable is set by `org-before-change-function'.
3774 `org-table-align' sets it back to nil.")
3775 (defvar org-mode-map)
3776 (defvar org-mode-hook nil)
3777 (defvar org-inhibit-startup nil) ; Dynamically-scoped param.
3778 (defvar org-agenda-keep-modes nil) ; Dynamically-scoped param.
3779 (defvar org-table-buffer-is-an nil)
3782 ;;;###autoload
3783 (define-derived-mode org-mode outline-mode "Org"
3784 "Outline-based notes management and organizer, alias
3785 \"Carsten's outline-mode for keeping track of everything.\"
3787 Org-mode develops organizational tasks around a NOTES file which
3788 contains information about projects as plain text. Org-mode is
3789 implemented on top of outline-mode, which is ideal to keep the content
3790 of large files well structured. It supports ToDo items, deadlines and
3791 time stamps, which magically appear in the diary listing of the Emacs
3792 calendar. Tables are easily created with a built-in table editor.
3793 Plain text URL-like links connect to websites, emails (VM), Usenet
3794 messages (Gnus), BBDB entries, and any files related to the project.
3795 For printing and sharing of notes, an Org-mode file (or a part of it)
3796 can be exported as a structured ASCII or HTML file.
3798 The following commands are available:
3800 \\{org-mode-map}"
3802 ;; Get rid of Outline menus, they are not needed
3803 ;; Need to do this here because define-derived-mode sets up
3804 ;; the keymap so late. Still, it is a waste to call this each time
3805 ;; we switch another buffer into org-mode.
3806 (if (featurep 'xemacs)
3807 (when (boundp 'outline-mode-menu-heading)
3808 ;; Assume this is Greg's port, it used easymenu
3809 (easy-menu-remove outline-mode-menu-heading)
3810 (easy-menu-remove outline-mode-menu-show)
3811 (easy-menu-remove outline-mode-menu-hide))
3812 (define-key org-mode-map [menu-bar headings] 'undefined)
3813 (define-key org-mode-map [menu-bar hide] 'undefined)
3814 (define-key org-mode-map [menu-bar show] 'undefined))
3816 (easy-menu-add org-org-menu)
3817 (easy-menu-add org-tbl-menu)
3818 (org-install-agenda-files-menu)
3819 (if org-descriptive-links (org-add-to-invisibility-spec '(org-link)))
3820 (org-add-to-invisibility-spec '(org-cwidth))
3821 (when (featurep 'xemacs)
3822 (org-set-local 'line-move-ignore-invisible t))
3823 (setq outline-regexp "\\*+")
3824 (setq outline-level 'org-outline-level)
3825 (when (and org-ellipsis (stringp org-ellipsis)
3826 (fboundp 'set-display-table-slot) (boundp 'buffer-display-table))
3827 (unless org-display-table
3828 (setq org-display-table (make-display-table)))
3829 (set-display-table-slot org-display-table
3830 4 (string-to-vector org-ellipsis))
3831 (setq buffer-display-table org-display-table))
3832 (org-set-regexps-and-options)
3833 ;; Calc embedded
3834 (org-set-local 'calc-embedded-open-mode "# ")
3835 (modify-syntax-entry ?# "<")
3836 (modify-syntax-entry ?@ "w")
3837 (if org-startup-truncated (setq truncate-lines t))
3838 (org-set-local 'font-lock-unfontify-region-function
3839 'org-unfontify-region)
3840 ;; Activate before-change-function
3841 (org-set-local 'org-table-may-need-update t)
3842 (org-add-hook 'before-change-functions 'org-before-change-function nil
3843 'local)
3844 ;; Check for running clock before killing a buffer
3845 (org-add-hook 'kill-buffer-hook 'org-check-running-clock nil 'local)
3846 ;; Paragraphs and auto-filling
3847 (org-set-autofill-regexps)
3848 (setq indent-line-function 'org-indent-line-function)
3849 (org-update-radio-target-regexp)
3851 ;; Comment characters
3852 ; (org-set-local 'comment-start "#") ;; FIXME: this breaks wrapping
3853 (org-set-local 'comment-padding " ")
3855 ;; Make isearch reveal context
3856 (if (or (featurep 'xemacs)
3857 (not (boundp 'outline-isearch-open-invisible-function)))
3858 ;; Emacs 21 and XEmacs make use of the hook
3859 (org-add-hook 'isearch-mode-end-hook 'org-isearch-end 'append 'local)
3860 ;; Emacs 22 deals with this through a special variable
3861 (org-set-local 'outline-isearch-open-invisible-function
3862 (lambda (&rest ignore) (org-show-context 'isearch))))
3864 ;; If empty file that did not turn on org-mode automatically, make it to.
3865 (if (and org-insert-mode-line-in-empty-file
3866 (interactive-p)
3867 (= (point-min) (point-max)))
3868 (insert "# -*- mode: org -*-\n\n"))
3870 (unless org-inhibit-startup
3871 (when org-startup-align-all-tables
3872 (let ((bmp (buffer-modified-p)))
3873 (org-table-map-tables 'org-table-align)
3874 (set-buffer-modified-p bmp)))
3875 (cond
3876 ((eq org-startup-folded t)
3877 (org-cycle '(4)))
3878 ((eq org-startup-folded 'content)
3879 (let ((this-command 'org-cycle) (last-command 'org-cycle))
3880 (org-cycle '(4)) (org-cycle '(4)))))))
3882 (put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify)
3884 (defsubst org-call-with-arg (command arg)
3885 "Call COMMAND interactively, but pretend prefix are was ARG."
3886 (let ((current-prefix-arg arg)) (call-interactively command)))
3888 (defsubst org-current-line (&optional pos)
3889 (save-excursion
3890 (and pos (goto-char pos))
3891 (+ (if (bolp) 1 0) (count-lines 1 (point)))))
3893 (defun org-current-time ()
3894 "Current time, possibly rounded to `org-time-stamp-rounding-minutes'."
3895 (if (> org-time-stamp-rounding-minutes 0)
3896 (let ((r org-time-stamp-rounding-minutes)
3897 (time (decode-time)))
3898 (apply 'encode-time
3899 (append (list 0 (* r (floor (+ .5 (/ (float (nth 1 time)) r)))))
3900 (nthcdr 2 time))))
3901 (current-time)))
3903 (defun org-add-props (string plist &rest props)
3904 "Add text properties to entire string, from beginning to end.
3905 PLIST may be a list of properties, PROPS are individual properties and values
3906 that will be added to PLIST. Returns the string that was modified."
3907 (add-text-properties
3908 0 (length string) (if props (append plist props) plist) string)
3909 string)
3910 (put 'org-add-props 'lisp-indent-function 2)
3913 ;;;; Font-Lock stuff, including the activators
3915 (defvar org-mouse-map (make-sparse-keymap))
3916 (org-defkey org-mouse-map
3917 (if (featurep 'xemacs) [button2] [mouse-2]) 'org-open-at-mouse)
3918 (org-defkey org-mouse-map
3919 (if (featurep 'xemacs) [button3] [mouse-3]) 'org-find-file-at-mouse)
3920 (when org-mouse-1-follows-link
3921 (org-defkey org-mouse-map [follow-link] 'mouse-face))
3922 (when org-tab-follows-link
3923 (org-defkey org-mouse-map [(tab)] 'org-open-at-point)
3924 (org-defkey org-mouse-map "\C-i" 'org-open-at-point))
3925 (when org-return-follows-link
3926 (org-defkey org-mouse-map [(return)] 'org-open-at-point)
3927 (org-defkey org-mouse-map "\C-m" 'org-open-at-point))
3929 (require 'font-lock)
3931 (defconst org-non-link-chars "]\t\n\r<>")
3932 (defconst org-link-types '("http" "https" "ftp" "mailto" "file" "news" "bbdb" "vm"
3933 "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
3934 (defconst org-link-re-with-space
3935 (concat
3936 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
3937 "\\([^" org-non-link-chars " ]"
3938 "[^" org-non-link-chars "]*"
3939 "[^" org-non-link-chars " ]\\)>?")
3940 "Matches a link with spaces, optional angular brackets around it.")
3942 (defconst org-link-re-with-space2
3943 (concat
3944 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
3945 "\\([^" org-non-link-chars " ]"
3946 "[^]\t\n\r]*"
3947 "[^" org-non-link-chars " ]\\)>?")
3948 "Matches a link with spaces, optional angular brackets around it.")
3950 (defconst org-angle-link-re
3951 (concat
3952 "<\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
3953 "\\([^" org-non-link-chars " ]"
3954 "[^" org-non-link-chars "]*"
3955 "\\)>")
3956 "Matches link with angular brackets, spaces are allowed.")
3957 (defconst org-plain-link-re
3958 (concat
3959 "\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
3960 "\\([^]\t\n\r<>,;() ]+\\)")
3961 "Matches plain link, without spaces.")
3963 (defconst org-bracket-link-regexp
3964 "\\[\\[\\([^]]+\\)\\]\\(\\[\\([^]]+\\)\\]\\)?\\]"
3965 "Matches a link in double brackets.")
3967 (defconst org-bracket-link-analytic-regexp
3968 (concat
3969 "\\[\\["
3970 "\\(\\(" (mapconcat 'identity org-link-types "\\|") "\\):\\)?"
3971 "\\([^]]+\\)"
3972 "\\]"
3973 "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
3974 "\\]"))
3975 ; 1: http:
3976 ; 2: http
3977 ; 3: path
3978 ; 4: [desc]
3979 ; 5: desc
3981 (defconst org-any-link-re
3982 (concat "\\(" org-bracket-link-regexp "\\)\\|\\("
3983 org-angle-link-re "\\)\\|\\("
3984 org-plain-link-re "\\)")
3985 "Regular expression matching any link.")
3987 (defconst org-ts-lengths
3988 (cons (length (format-time-string (car org-time-stamp-formats)))
3989 (length (format-time-string (cdr org-time-stamp-formats))))
3990 "This holds the lengths of the two different time formats.")
3991 (defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)>"
3992 "Regular expression for fast time stamp matching.")
3993 (defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)[]>]"
3994 "Regular expression for fast time stamp matching.")
3995 (defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) \\([^]0-9>\r\n]*\\)\\(\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
3996 "Regular expression matching time strings for analysis.")
3997 (defconst org-ts-regexp2 (concat "<" org-ts-regexp1 "[^>\n]\\{0,5\\}>")
3998 "Regular expression matching time stamps, with groups.")
3999 ;; FIXME need to exclude ] here as well, also need to think about lengths
4000 (defconst org-ts-regexp3 (concat "[[<]" org-ts-regexp1 "[^]>\n]\\{0,5\\}[]>]")
4001 "Regular expression matching time stamps (also [..]), with groups.")
4002 (defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp)
4003 "Regular expression matching a time stamp range.")
4004 (defconst org-tr-regexp-both
4005 (concat org-ts-regexp-both "--?-?" org-ts-regexp-both)
4006 "Regular expression matching a time stamp range.")
4007 (defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?"
4008 org-ts-regexp "\\)?")
4009 "Regular expression matching a time stamp or time stamp range.")
4010 (defconst org-tsr-regexp-both (concat org-ts-regexp-both "\\(--?-?"
4011 org-ts-regexp-both "\\)?")
4012 "Regular expression matching a time stamp or time stamp range.
4013 The time stamps may be either active or inactive.")
4015 (defvar org-emph-face nil)
4017 (defun org-do-emphasis-faces (limit)
4018 "Run through the buffer and add overlays to links."
4019 (let (rtn)
4020 (while (and (not rtn) (re-search-forward org-emph-re limit t))
4021 (if (not (= (char-after (match-beginning 3))
4022 (char-after (match-beginning 4))))
4023 (progn
4024 (setq rtn t)
4025 (font-lock-prepend-text-property (match-beginning 2) (match-end 2)
4026 'face
4027 (nth 1 (assoc (match-string 3)
4028 org-emphasis-alist)))
4029 (add-text-properties (match-beginning 2) (match-end 2)
4030 '(font-lock-multiline t))
4031 (backward-char 1))))
4032 rtn))
4034 (defun org-emphasize (&optional char)
4035 "Insert or change an emphasis, i.e. a font like bold or italic.
4036 If there is an active region, change that region to a new emphasis.
4037 If there is no region, just insert the marker characters and position
4038 the cursor between them.
4039 CHAR should be either the marker character, or the first character of the
4040 HTML tag associated with that emphasis. If CHAR is a space, the means
4041 to remove the emphasis of the selected region.
4042 If char is not given (for example in an interactive call) it
4043 will be prompted for."
4044 (interactive)
4045 (let ((eal org-emphasis-alist) e det
4046 (erc org-emphasis-regexp-components)
4047 (prompt "")
4048 (string "") beg end move tag c s)
4049 (if (org-region-active-p)
4050 (setq beg (region-beginning) end (region-end)
4051 string (buffer-substring beg end))
4052 (setq move t))
4054 (while (setq e (pop eal))
4055 (setq tag (car (org-split-string (nth 2 e) "[ <>/]+"))
4056 c (aref tag 0))
4057 (push (cons c (string-to-char (car e))) det)
4058 (setq prompt (concat prompt (format " [%s%c]%s" (car e) c
4059 (substring tag 1)))))
4060 (unless char
4061 (message "%s" (concat "Emphasis marker or tag:" prompt))
4062 (setq char (read-char-exclusive)))
4063 (setq char (or (cdr (assoc char det)) char))
4064 (if (equal char ?\ )
4065 (setq s "" move nil)
4066 (unless (assoc (char-to-string char) org-emphasis-alist)
4067 (error "No such emphasis marker: \"%c\"" char))
4068 (setq s (char-to-string char)))
4069 (while (and (> (length string) 1)
4070 (equal (substring string 0 1) (substring string -1))
4071 (assoc (substring string 0 1) org-emphasis-alist))
4072 (setq string (substring string 1 -1)))
4073 (setq string (concat s string s))
4074 (if beg (delete-region beg end))
4075 (unless (or (bolp)
4076 (string-match (concat "[" (nth 0 erc) "\n]")
4077 (char-to-string (char-before (point)))))
4078 (insert " "))
4079 (unless (string-match (concat "[" (nth 1 erc) "\n]")
4080 (char-to-string (char-after (point))))
4081 (insert " ") (backward-char 1))
4082 (insert string)
4083 (and move (backward-char 1))))
4085 (defun org-activate-plain-links (limit)
4086 "Run through the buffer and add overlays to links."
4087 (catch 'exit
4088 (let (f)
4089 (while (re-search-forward org-plain-link-re limit t)
4090 (setq f (get-text-property (match-beginning 0) 'face))
4091 (if (or (eq f 'org-tag)
4092 (and (listp f) (memq 'org-tag f)))
4094 (add-text-properties (match-beginning 0) (match-end 0)
4095 (list 'mouse-face 'highlight
4096 'rear-nonsticky t
4097 'keymap org-mouse-map
4099 (throw 'exit t))))))
4101 (defun org-activate-angle-links (limit)
4102 "Run through the buffer and add overlays to links."
4103 (if (re-search-forward org-angle-link-re limit t)
4104 (progn
4105 (add-text-properties (match-beginning 0) (match-end 0)
4106 (list 'mouse-face 'highlight
4107 'rear-nonsticky t
4108 'keymap org-mouse-map
4110 t)))
4112 (defmacro org-maybe-intangible (props)
4113 "Add '(intangigble t) to PROPS if Emacs version is earlier than Emacs 22.
4114 In emacs 21, invisible text is not avoided by the command loop, so the
4115 intangible property is needed to make sure point skips this text.
4116 In Emacs 22, this is not necessary. The intangible text property has
4117 led to problems with flyspell. These problems are fixed in flyspell.el,
4118 but we still avoid setting the property in Emacs 22 and later.
4119 We use a macro so that the test can happen at compilation time."
4120 (if (< emacs-major-version 22)
4121 `(append '(intangible t) ,props)
4122 props))
4124 (defun org-activate-bracket-links (limit)
4125 "Run through the buffer and add overlays to bracketed links."
4126 (if (re-search-forward org-bracket-link-regexp limit t)
4127 (let* ((help (concat "LINK: "
4128 (org-match-string-no-properties 1)))
4129 ;; FIXME: above we should remove the escapes.
4130 ;; but that requires another match, protecting match data,
4131 ;; a lot of overhead for font-lock.
4132 (ip (org-maybe-intangible
4133 (list 'invisible 'org-link 'rear-nonsticky t
4134 'keymap org-mouse-map 'mouse-face 'highlight
4135 'help-echo help)))
4136 (vp (list 'rear-nonsticky t
4137 'keymap org-mouse-map 'mouse-face 'highlight
4138 'help-echo help)))
4139 ;; We need to remove the invisible property here. Table narrowing
4140 ;; may have made some of this invisible.
4141 (remove-text-properties (match-beginning 0) (match-end 0)
4142 '(invisible nil))
4143 (if (match-end 3)
4144 (progn
4145 (add-text-properties (match-beginning 0) (match-beginning 3) ip)
4146 (add-text-properties (match-beginning 3) (match-end 3) vp)
4147 (add-text-properties (match-end 3) (match-end 0) ip))
4148 (add-text-properties (match-beginning 0) (match-beginning 1) ip)
4149 (add-text-properties (match-beginning 1) (match-end 1) vp)
4150 (add-text-properties (match-end 1) (match-end 0) ip))
4151 t)))
4153 (defun org-activate-dates (limit)
4154 "Run through the buffer and add overlays to dates."
4155 (if (re-search-forward org-tsr-regexp-both limit t)
4156 (progn
4157 (add-text-properties (match-beginning 0) (match-end 0)
4158 (list 'mouse-face 'highlight
4159 'rear-nonsticky t
4160 'keymap org-mouse-map))
4161 (when org-display-custom-times
4162 (if (match-end 3)
4163 (org-display-custom-time (match-beginning 3) (match-end 3)))
4164 (org-display-custom-time (match-beginning 1) (match-end 1)))
4165 t)))
4167 (defvar org-target-link-regexp nil
4168 "Regular expression matching radio targets in plain text.")
4169 (defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>"
4170 "Regular expression matching a link target.")
4171 (defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>"
4172 "Regular expression matching a link target.")
4174 (defun org-activate-target-links (limit)
4175 "Run through the buffer and add overlays to target matches."
4176 (when org-target-link-regexp
4177 (let ((case-fold-search t))
4178 (if (re-search-forward org-target-link-regexp limit t)
4179 (progn
4180 (add-text-properties (match-beginning 0) (match-end 0)
4181 (list 'mouse-face 'highlight
4182 'rear-nonsticky t
4183 'keymap org-mouse-map
4184 'help-echo "Radio target link"
4185 'org-linked-text t))
4186 t)))))
4188 (defun org-update-radio-target-regexp ()
4189 "Find all radio targets in this file and update the regular expression."
4190 (interactive)
4191 (when (memq 'radio org-activate-links)
4192 (setq org-target-link-regexp
4193 (org-make-target-link-regexp (org-all-targets 'radio)))
4194 (org-restart-font-lock)))
4196 (defun org-hide-wide-columns (limit)
4197 (let (s e)
4198 (setq s (text-property-any (point) (or limit (point-max))
4199 'org-cwidth t))
4200 (when s
4201 (setq e (next-single-property-change s 'org-cwidth))
4202 (add-text-properties s e (org-maybe-intangible '(invisible org-cwidth)))
4203 (goto-char e)
4204 t)))
4206 (defun org-restart-font-lock ()
4207 "Restart font-lock-mode, to force refontification."
4208 (when (and (boundp 'font-lock-mode) font-lock-mode)
4209 (font-lock-mode -1)
4210 (font-lock-mode 1)))
4212 (defun org-all-targets (&optional radio)
4213 "Return a list of all targets in this file.
4214 With optional argument RADIO, only find radio targets."
4215 (let ((re (if radio org-radio-target-regexp org-target-regexp))
4216 rtn)
4217 (save-excursion
4218 (goto-char (point-min))
4219 (while (re-search-forward re nil t)
4220 (add-to-list 'rtn (downcase (org-match-string-no-properties 1))))
4221 rtn)))
4223 (defun org-make-target-link-regexp (targets)
4224 "Make regular expression matching all strings in TARGETS.
4225 The regular expression finds the targets also if there is a line break
4226 between words."
4227 (and targets
4228 (concat
4229 "\\<\\("
4230 (mapconcat
4231 (lambda (x)
4232 (while (string-match " +" x)
4233 (setq x (replace-match "\\s-+" t t x)))
4235 targets
4236 "\\|")
4237 "\\)\\>")))
4239 (defun org-activate-tags (limit)
4240 (if (re-search-forward "[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \r\n]" limit t)
4241 (progn
4242 (add-text-properties (match-beginning 1) (match-end 1)
4243 (list 'mouse-face 'highlight
4244 'rear-nonsticky t
4245 'keymap org-mouse-map))
4246 t)))
4248 (defun org-outline-level ()
4249 (save-excursion
4250 (looking-at outline-regexp)
4251 (if (match-beginning 1)
4252 (+ (org-get-string-indentation (match-string 1)) 1000)
4253 (- (match-end 0) (match-beginning 0)))))
4255 (defvar org-font-lock-keywords nil)
4257 (defun org-set-font-lock-defaults ()
4258 (let* ((em org-fontify-emphasized-text)
4259 (lk org-activate-links)
4260 (org-font-lock-extra-keywords
4261 ;; Headlines
4262 (list
4263 '("^\\(\\**\\)\\(\\*\\)\\(.*\\)" (1 (org-get-level-face 1))
4264 (2 (org-get-level-face 2)) (3 (org-get-level-face 3)))
4265 '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)"
4266 (1 'org-table))
4267 ;; Links
4268 (if (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
4269 (if (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
4270 (if (memq 'plain lk) '(org-activate-plain-links (0 'org-link t)))
4271 (if (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
4272 (if (memq 'radio lk) '(org-activate-target-links (0 'org-link t)))
4273 (if (memq 'date lk) '(org-activate-dates (0 'org-date t)))
4274 '("^&?%%(.*\\|<%%([^>\n]*?>" (0 'org-sexp-date t))
4275 '(org-hide-wide-columns (0 nil append))
4276 ;; TODO lines
4277 (list (concat "^\\*+[ \t]*" org-not-done-regexp)
4278 '(1 'org-todo t))
4279 ;; Priorities
4280 (list (concat "\\[#[A-Z0-9]\\]") '(0 'org-special-keyword t))
4281 ;; Special keywords
4282 (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t))
4283 (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword t))
4284 (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t))
4285 (list (concat "\\<" org-clock-string) '(0 'org-special-keyword t))
4286 ;; Emphasis
4287 (if em
4288 (if (featurep 'xemacs)
4289 '(org-do-emphasis-faces (0 nil append))
4290 '(org-do-emphasis-faces)))
4291 ;; Checkboxes, similar to Frank Ruell's org-checklet.el
4292 '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)"
4293 2 'bold prepend)
4294 (if org-provide-checkbox-statistics
4295 '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
4296 (0 (org-get-checkbox-statistics-face) t)))
4297 ;; COMMENT
4298 (list (concat "^\\*+[ \t]*\\<\\(" org-comment-string
4299 "\\|" org-quote-string "\\)\\>")
4300 '(1 'org-special-keyword t))
4301 '("^#.*" (0 'font-lock-comment-face t))
4302 ;; DONE
4303 (if org-fontify-done-headline
4304 (list (concat "^[*]+ +\\<\\("
4305 (mapconcat 'regexp-quote org-done-keywords "\\|")
4306 "\\)\\(.*\\)")
4307 '(1 'org-done t) '(2 'org-headline-done t))
4308 (list (concat "^[*]+ +\\<\\("
4309 (mapconcat 'regexp-quote org-done-keywords "\\|")
4310 "\\)\\>")
4311 '(1 'org-done t)))
4312 ;; Table stuff
4313 '("^[ \t]*\\(:.*\\)" (1 'org-table t))
4314 '("| *\\(:?=[^|\n]*\\)" (1 'org-formula t))
4315 '("^[ \t]*| *\\([#!$*_^]\\) *|" (1 'org-formula t))
4316 (if org-format-transports-properties-p
4317 '("| *\\(<[0-9]+>\\) *" (1 'org-formula t)))
4318 '("^\\*+ \\(.*:ARCHIVE:.*\\)" (1 'org-archived prepend))
4320 (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords))
4321 ;; Now set the full font-lock-keywords
4322 (org-set-local 'org-font-lock-keywords org-font-lock-extra-keywords)
4323 (org-set-local 'font-lock-defaults
4324 '(org-font-lock-keywords t nil nil backward-paragraph))
4325 (kill-local-variable 'font-lock-keywords) nil))
4327 (defvar org-m nil)
4328 (defvar org-l nil)
4329 (defvar org-f nil)
4330 (defun org-get-level-face (n)
4331 "Get the right face for match N in font-lock matching of healdines."
4332 (setq org-l (- (match-end 2) (match-beginning 1)))
4333 (if org-odd-levels-only (setq org-l (1+ (/ org-l 2))))
4334 ; (setq org-f (nth (1- (% org-l org-n-levels)) org-level-faces))
4335 (setq org-f (nth (% (1- org-l) org-n-levels) org-level-faces))
4336 (cond
4337 ((eq n 1) (if org-hide-leading-stars 'org-hide org-f))
4338 ((eq n 2) org-f)
4339 (t (if org-level-color-stars-only nil org-f))))
4341 (defun org-unfontify-region (beg end &optional maybe_loudly)
4342 "Remove fontification and activation overlays from links."
4343 (font-lock-default-unfontify-region beg end)
4344 (let* ((buffer-undo-list t)
4345 (inhibit-read-only t) (inhibit-point-motion-hooks t)
4346 (inhibit-modification-hooks t)
4347 deactivate-mark buffer-file-name buffer-file-truename)
4348 (remove-text-properties beg end
4349 '(mouse-face t keymap t org-linked-text t
4350 rear-nonsticky t
4351 invisible t intangible t))))
4353 ;;;; Visibility cycling, including org-goto and indirect buffer
4355 ;;; Cycling
4357 (defvar org-cycle-global-status nil)
4358 (make-variable-buffer-local 'org-cycle-global-status)
4359 (defvar org-cycle-subtree-status nil)
4360 (make-variable-buffer-local 'org-cycle-subtree-status)
4362 ;;;###autoload
4363 (defun org-cycle (&optional arg)
4364 "Visibility cycling for Org-mode.
4366 - When this function is called with a prefix argument, rotate the entire
4367 buffer through 3 states (global cycling)
4368 1. OVERVIEW: Show only top-level headlines.
4369 2. CONTENTS: Show all headlines of all levels, but no body text.
4370 3. SHOW ALL: Show everything.
4372 - When point is at the beginning of a headline, rotate the subtree started
4373 by this line through 3 different states (local cycling)
4374 1. FOLDED: Only the main headline is shown.
4375 2. CHILDREN: The main headline and the direct children are shown.
4376 From this state, you can move to one of the children
4377 and zoom in further.
4378 3. SUBTREE: Show the entire subtree, including body text.
4380 - When there is a numeric prefix, go up to a heading with level ARG, do
4381 a `show-subtree' and return to the previous cursor position. If ARG
4382 is negative, go up that many levels.
4384 - When point is not at the beginning of a headline, execute
4385 `indent-relative', like TAB normally does. See the option
4386 `org-cycle-emulate-tab' for details.
4388 - Special case: if point is the the beginning of the buffer and there is
4389 no headline in line 1, this function will act as if called with prefix arg."
4390 (interactive "P")
4391 (let* ((outline-regexp
4392 (if (and (org-mode-p) org-cycle-include-plain-lists)
4393 "\\(?:\\*+\\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) \\)"
4394 outline-regexp))
4395 (bob-special (and org-cycle-global-at-bob (bobp)
4396 (not (looking-at outline-regexp))))
4397 (org-cycle-hook
4398 (if bob-special
4399 (delq 'org-optimize-window-after-visibility-change
4400 (copy-sequence org-cycle-hook))
4401 org-cycle-hook))
4402 (pos (point)))
4404 (if (or bob-special (equal arg '(4)))
4405 ;; special case: use global cycling
4406 (setq arg t))
4408 (cond
4410 ((org-at-table-p 'any)
4411 ;; Enter the table or move to the next field in the table
4412 (or (org-table-recognize-table.el)
4413 (progn
4414 (if arg (org-table-edit-field t)
4415 (org-table-justify-field-maybe)
4416 (call-interactively 'org-table-next-field)))))
4418 ((eq arg t) ;; Global cycling
4420 (cond
4421 ((and (eq last-command this-command)
4422 (eq org-cycle-global-status 'overview))
4423 ;; We just created the overview - now do table of contents
4424 ;; This can be slow in very large buffers, so indicate action
4425 (message "CONTENTS...")
4426 (org-content)
4427 (message "CONTENTS...done")
4428 (setq org-cycle-global-status 'contents)
4429 (run-hook-with-args 'org-cycle-hook 'contents))
4431 ((and (eq last-command this-command)
4432 (eq org-cycle-global-status 'contents))
4433 ;; We just showed the table of contents - now show everything
4434 (show-all)
4435 (message "SHOW ALL")
4436 (setq org-cycle-global-status 'all)
4437 (run-hook-with-args 'org-cycle-hook 'all))
4440 ;; Default action: go to overview
4441 (org-overview)
4442 (message "OVERVIEW")
4443 (setq org-cycle-global-status 'overview)
4444 (run-hook-with-args 'org-cycle-hook 'overview))))
4446 ((integerp arg)
4447 ;; Show-subtree, ARG levels up from here.
4448 (save-excursion
4449 (org-back-to-heading)
4450 (outline-up-heading (if (< arg 0) (- arg)
4451 (- (funcall outline-level) arg)))
4452 (org-show-subtree)))
4454 ((and (save-excursion (beginning-of-line 1) (looking-at outline-regexp))
4455 (or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
4456 ;; At a heading: rotate between three different views
4457 (org-back-to-heading)
4458 (let ((goal-column 0) eoh eol eos)
4459 ;; First, some boundaries
4460 (save-excursion
4461 (org-back-to-heading)
4462 (save-excursion
4463 (beginning-of-line 2)
4464 (while (and (not (eobp)) ;; this is like `next-line'
4465 (get-char-property (1- (point)) 'invisible))
4466 (beginning-of-line 2)) (setq eol (point)))
4467 (outline-end-of-heading) (setq eoh (point))
4468 (org-end-of-subtree t)
4469 (unless (eobp)
4470 (skip-chars-forward " \t\n")
4471 (beginning-of-line 1) ; in case this is an item
4473 (setq eos (1- (point))))
4474 ;; Find out what to do next and set `this-command'
4475 (cond
4476 ((= eos eoh)
4477 ;; Nothing is hidden behind this heading
4478 (message "EMPTY ENTRY")
4479 (setq org-cycle-subtree-status nil))
4480 ((>= eol eos)
4481 ;; Entire subtree is hidden in one line: open it
4482 (org-show-entry)
4483 (show-children)
4484 (message "CHILDREN")
4485 (setq org-cycle-subtree-status 'children)
4486 (run-hook-with-args 'org-cycle-hook 'children))
4487 ((and (eq last-command this-command)
4488 (eq org-cycle-subtree-status 'children))
4489 ;; We just showed the children, now show everything.
4490 (org-show-subtree)
4491 (message "SUBTREE")
4492 (setq org-cycle-subtree-status 'subtree)
4493 (run-hook-with-args 'org-cycle-hook 'subtree))
4495 ;; Default action: hide the subtree.
4496 (hide-subtree)
4497 (message "FOLDED")
4498 (setq org-cycle-subtree-status 'folded)
4499 (run-hook-with-args 'org-cycle-hook 'folded)))))
4501 ;; TAB emulation
4502 (buffer-read-only (org-back-to-heading))
4504 ((org-try-cdlatex-tab))
4506 ((and (eq org-cycle-emulate-tab 'exc-hl-bol)
4507 (or (not (bolp))
4508 (not (looking-at outline-regexp))))
4509 (call-interactively (global-key-binding "\t")))
4511 ((if (and (memq org-cycle-emulate-tab '(white whitestart))
4512 (save-excursion (beginning-of-line 1) (looking-at "[ \t]*"))
4513 (or (and (eq org-cycle-emulate-tab 'white)
4514 (= (match-end 0) (point-at-eol)))
4515 (and (eq org-cycle-emulate-tab 'whitestart)
4516 (>= (match-end 0) pos))))
4518 (eq org-cycle-emulate-tab t))
4519 (if (and (looking-at "[ \n\r\t]")
4520 (string-match "^[ \t]*$" (buffer-substring
4521 (point-at-bol) (point))))
4522 (progn
4523 (beginning-of-line 1)
4524 (and (looking-at "[ \t]+") (replace-match ""))))
4525 (call-interactively (global-key-binding "\t")))
4527 (t (save-excursion
4528 (org-back-to-heading)
4529 (org-cycle))))))
4531 ;;;###autoload
4532 (defun org-global-cycle (&optional arg)
4533 "Cycle the global visibility. For details see `org-cycle'."
4534 (interactive "P")
4535 (let ((org-cycle-include-plain-lists
4536 (if (org-mode-p) org-cycle-include-plain-lists nil)))
4537 (if (integerp arg)
4538 (progn
4539 (show-all)
4540 (hide-sublevels arg)
4541 (setq org-cycle-global-status 'contents))
4542 (org-cycle '(4)))))
4544 (defun org-overview ()
4545 "Switch to overview mode, shoing only top-level headlines.
4546 Really, this shows all headlines with level equal or greater than the level
4547 of the first headline in the buffer. This is important, because if the
4548 first headline is not level one, then (hide-sublevels 1) gives confusing
4549 results."
4550 (interactive)
4551 (let ((level (save-excursion
4552 (goto-char (point-min))
4553 (if (re-search-forward (concat "^" outline-regexp) nil t)
4554 (progn
4555 (goto-char (match-beginning 0))
4556 (funcall outline-level))))))
4557 (and level (hide-sublevels level))))
4559 (defun org-content (&optional arg)
4560 "Show all headlines in the buffer, like a table of contents.
4561 With numerical argument N, show content up to level N."
4562 (interactive "P")
4563 (save-excursion
4564 ;; Visit all headings and show their offspring
4565 (and (integerp arg) (org-overview))
4566 (goto-char (point-max))
4567 (catch 'exit
4568 (while (and (progn (condition-case nil
4569 (outline-previous-visible-heading 1)
4570 (error (goto-char (point-min))))
4572 (looking-at outline-regexp))
4573 (if (integerp arg)
4574 (show-children (1- arg))
4575 (show-branches))
4576 (if (bobp) (throw 'exit nil))))))
4579 (defun org-optimize-window-after-visibility-change (state)
4580 "Adjust the window after a change in outline visibility.
4581 This function is the default value of the hook `org-cycle-hook'."
4582 (when (get-buffer-window (current-buffer))
4583 (cond
4584 ; ((eq state 'overview) (org-first-headline-recenter 1))
4585 ; ((eq state 'overview) (org-beginning-of-line))
4586 ((eq state 'content) nil)
4587 ((eq state 'all) nil)
4588 ((eq state 'folded) nil)
4589 ((eq state 'children) (or (org-subtree-end-visible-p) (recenter 1)))
4590 ((eq state 'subtree) (or (org-subtree-end-visible-p) (recenter 1))))))
4593 (defun org-cycle-show-empty-lines (state)
4594 "Show empty lines above all visible headlines.
4595 The region to be covered depends on STATE when called through
4596 `org-cycle-hook'. Lisp program can use t for STATE to get the
4597 entire buffer covered. Note that an empty line is only shown if there
4598 are at least `org-cycle-separator-lines' empty lines before the headeline."
4599 (when (> org-cycle-separator-lines 0)
4600 (save-excursion
4601 (let* ((n org-cycle-separator-lines)
4602 (re (cond
4603 ((= n 1) "\\(\n[ \t]*\n\\*+\\) ")
4604 ((= n 2) "^[ \t]*\\(\n[ \t]*\n\\*+\\) ")
4605 (t (let ((ns (number-to-string (- n 2))))
4606 (concat "^\\(?:[ \t]*\n\\)\\{" ns "," ns "\\}"
4607 "[ \t]*\\(\n[ \t]*\n\\*+\\) ")))))
4608 beg end)
4609 (cond
4610 ((memq state '(overview contents t))
4611 (setq beg (point-min) end (point-max)))
4612 ((memq state '(children folded))
4613 (setq beg (point) end (progn (org-end-of-subtree t t)
4614 (beginning-of-line 2)
4615 (point)))))
4616 (when beg
4617 (goto-char beg)
4618 (while (re-search-forward re end t)
4619 (if (not (get-char-property (match-end 1) 'invisible))
4620 (outline-flag-region
4621 (match-beginning 1) (match-end 1) nil)))))))
4622 ;; Never hide empty lines at the end of the file.
4623 (save-excursion
4624 (goto-char (point-max))
4625 (outline-previous-heading)
4626 (outline-end-of-heading)
4627 (if (and (looking-at "[ \t\n]+")
4628 (= (match-end 0) (point-max)))
4629 (outline-flag-region (point) (match-end 0) nil))))
4631 (defun org-subtree-end-visible-p ()
4632 "Is the end of the current subtree visible?"
4633 (pos-visible-in-window-p
4634 (save-excursion (org-end-of-subtree t) (point))))
4636 (defun org-first-headline-recenter (&optional N)
4637 "Move cursor to the first headline and recenter the headline.
4638 Optional argument N means, put the headline into the Nth line of the window."
4639 (goto-char (point-min))
4640 (when (re-search-forward (concat "^\\(" outline-regexp "\\)") nil t)
4641 (beginning-of-line)
4642 (recenter (prefix-numeric-value N))))
4644 ;;; Org-goto
4646 (defvar org-goto-window-configuration nil)
4647 (defvar org-goto-marker nil)
4648 (defvar org-goto-map (make-sparse-keymap))
4649 (let ((cmds '(isearch-forward isearch-backward)) cmd)
4650 (while (setq cmd (pop cmds))
4651 (substitute-key-definition cmd cmd org-goto-map global-map)))
4652 (org-defkey org-goto-map "\C-m" 'org-goto-ret)
4653 (org-defkey org-goto-map [(left)] 'org-goto-left)
4654 (org-defkey org-goto-map [(right)] 'org-goto-right)
4655 (org-defkey org-goto-map [(?q)] 'org-goto-quit)
4656 (org-defkey org-goto-map [(control ?g)] 'org-goto-quit)
4657 (org-defkey org-goto-map "\C-i" 'org-cycle)
4658 (org-defkey org-goto-map [(tab)] 'org-cycle)
4659 (org-defkey org-goto-map [(down)] 'outline-next-visible-heading)
4660 (org-defkey org-goto-map [(up)] 'outline-previous-visible-heading)
4661 (org-defkey org-goto-map "n" 'outline-next-visible-heading)
4662 (org-defkey org-goto-map "p" 'outline-previous-visible-heading)
4663 (org-defkey org-goto-map "f" 'outline-forward-same-level)
4664 (org-defkey org-goto-map "b" 'outline-backward-same-level)
4665 (org-defkey org-goto-map "u" 'outline-up-heading)
4666 (org-defkey org-goto-map "\C-c\C-n" 'outline-next-visible-heading)
4667 (org-defkey org-goto-map "\C-c\C-p" 'outline-previous-visible-heading)
4668 (org-defkey org-goto-map "\C-c\C-f" 'outline-forward-same-level)
4669 (org-defkey org-goto-map "\C-c\C-b" 'outline-backward-same-level)
4670 (org-defkey org-goto-map "\C-c\C-u" 'outline-up-heading)
4671 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
4672 (while l (org-defkey org-goto-map (int-to-string (pop l)) 'digit-argument)))
4674 (defconst org-goto-help
4675 "Select a location to jump to, press RET
4676 \[Up]/[Down]=next/prev headline TAB=cycle visibility RET=select [Q]uit")
4678 (defun org-goto ()
4679 "Go to a different location of the document, keeping current visibility.
4681 When you want to go to a different location in a document, the fastest way
4682 is often to fold the entire buffer and then dive into the tree. This
4683 method has the disadvantage, that the previous location will be folded,
4684 which may not be what you want.
4686 This command works around this by showing a copy of the current buffer in
4687 overview mode. You can dive into the tree in that copy, to find the
4688 location you want to reach. When pressing RET, the command returns to the
4689 original buffer in which the visibility is still unchanged. It then jumps
4690 to the new location, making it and the headline hierarchy above it visible."
4691 (interactive)
4692 (let* ((org-goto-start-pos (point))
4693 (selected-point
4694 (org-get-location (current-buffer) org-goto-help)))
4695 (if selected-point
4696 (progn
4697 (org-mark-ring-push org-goto-start-pos)
4698 (goto-char selected-point)
4699 (if (or (org-invisible-p) (org-invisible-p2))
4700 (org-show-context 'org-goto)))
4701 (error "Quit"))))
4703 (defvar org-selected-point nil) ; dynamically scoped parameter
4705 (defun org-get-location (buf help)
4706 "Let the user select a location in the Org-mode buffer BUF.
4707 This function uses a recursive edit. It returns the selected position
4708 or nil."
4709 (let (org-selected-point)
4710 (save-excursion
4711 (save-window-excursion
4712 (delete-other-windows)
4713 (switch-to-buffer (get-buffer-create "*org-goto*"))
4714 (with-output-to-temp-buffer "*Help*"
4715 (princ help))
4716 (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*"))
4717 (setq buffer-read-only nil)
4718 (erase-buffer)
4719 (insert-buffer-substring buf)
4720 (let ((org-startup-truncated t)
4721 (org-startup-folded t)
4722 (org-startup-align-all-tables nil))
4723 (org-mode))
4724 (setq buffer-read-only t)
4725 (if (and (boundp 'org-goto-start-pos)
4726 (integer-or-marker-p org-goto-start-pos))
4727 (let ((org-show-hierarchy-above t)
4728 (org-show-siblings t)
4729 (org-show-following-heading t))
4730 (goto-char org-goto-start-pos)
4731 (and (org-invisible-p) (org-show-context)))
4732 (goto-char (point-min)))
4733 (org-beginning-of-line)
4734 (message "Select location and press RET")
4735 ;; now we make sure that during selection, ony very few keys work
4736 ;; and that it is impossible to switch to another window.
4737 (let ((gm (current-global-map))
4738 (overriding-local-map org-goto-map))
4739 (unwind-protect
4740 (progn
4741 (use-global-map org-goto-map)
4742 (recursive-edit))
4743 (use-global-map gm)))))
4744 (kill-buffer "*org-goto*")
4745 org-selected-point))
4747 (defun org-goto-ret (&optional arg)
4748 "Finish `org-goto' by going to the new location."
4749 (interactive "P")
4750 (setq org-selected-point (point)
4751 current-prefix-arg arg)
4752 (throw 'exit nil))
4754 (defun org-goto-left ()
4755 "Finish `org-goto' by going to the new location."
4756 (interactive)
4757 (if (org-on-heading-p)
4758 (progn
4759 (beginning-of-line 1)
4760 (setq org-selected-point (point)
4761 current-prefix-arg (- (match-end 0) (match-beginning 0)))
4762 (throw 'exit nil))
4763 (error "Not on a heading")))
4765 (defun org-goto-right ()
4766 "Finish `org-goto' by going to the new location."
4767 (interactive)
4768 (if (org-on-heading-p)
4769 (progn
4770 (outline-end-of-subtree)
4771 (or (eobp) (forward-char 1))
4772 (setq org-selected-point (point)
4773 current-prefix-arg (- (match-end 0) (match-beginning 0)))
4774 (throw 'exit nil))
4775 (error "Not on a heading")))
4777 (defun org-goto-quit ()
4778 "Finish `org-goto' without cursor motion."
4779 (interactive)
4780 (setq org-selected-point nil)
4781 (throw 'exit nil))
4783 ;;; Indirect buffer display of subtrees
4785 (defvar org-indirect-dedicated-frame nil
4786 "This is the frame being used for indirect tree display.")
4787 (defvar org-last-indirect-buffer nil)
4789 (defun org-tree-to-indirect-buffer (&optional arg)
4790 "Create indirect buffer and narrow it to current subtree.
4791 With numerical prefix ARG, go up to this level and then take that tree.
4792 If ARG is negative, go up that many levels.
4793 Normally this command removes the indirect buffer previously made
4794 with this command. However, when called with a C-u prefix, the last buffer
4795 is kept so that you can work with several indirect buffers at the same time.
4796 If `org-indirect-buffer-display' is `dedicated-frame', the C-u prefix also
4797 requests that a new frame be made for the new buffer, so that the dedicated
4798 frame is not changed."
4799 (interactive "P")
4800 (let ((cbuf (current-buffer))
4801 (cwin (selected-window))
4802 (pos (point))
4803 beg end level heading ibuf)
4804 (save-excursion
4805 (org-back-to-heading t)
4806 (when (numberp arg)
4807 (setq level (org-outline-level))
4808 (if (< arg 0) (setq arg (+ level arg)))
4809 (while (> (setq level (org-outline-level)) arg)
4810 (outline-up-heading 1 t)))
4811 (setq beg (point)
4812 heading (org-get-heading))
4813 (org-end-of-subtree t) (setq end (point)))
4814 (if (and (not arg)
4815 (buffer-live-p org-last-indirect-buffer))
4816 (kill-buffer org-last-indirect-buffer))
4817 (setq ibuf (org-get-indirect-buffer cbuf)
4818 org-last-indirect-buffer ibuf)
4819 (cond
4820 ((or (eq org-indirect-buffer-display 'new-frame)
4821 (and arg (eq org-indirect-buffer-display 'dedicated-frame)))
4822 (select-frame (make-frame))
4823 (delete-other-windows)
4824 (switch-to-buffer ibuf)
4825 (org-set-frame-title heading))
4826 ((eq org-indirect-buffer-display 'dedicated-frame)
4827 (raise-frame
4828 (select-frame (or (and org-indirect-dedicated-frame
4829 (frame-live-p org-indirect-dedicated-frame)
4830 org-indirect-dedicated-frame)
4831 (setq org-indirect-dedicated-frame (make-frame)))))
4832 (delete-other-windows)
4833 (switch-to-buffer ibuf)
4834 (org-set-frame-title (concat "Indirect: " heading)))
4835 ((eq org-indirect-buffer-display 'current-window)
4836 (switch-to-buffer ibuf))
4837 ((eq org-indirect-buffer-display 'other-window)
4838 (pop-to-buffer ibuf))
4839 (t (error "Invalid value.")))
4840 (if (featurep 'xemacs)
4841 (save-excursion (org-mode) (turn-on-font-lock)))
4842 (narrow-to-region beg end)
4843 (show-all)
4844 (goto-char pos)
4845 (and (window-live-p cwin) (select-window cwin))))
4847 (defun org-get-indirect-buffer (&optional buffer)
4848 (setq buffer (or buffer (current-buffer)))
4849 (let ((n 1) (base (buffer-name buffer)) bname)
4850 (while (buffer-live-p
4851 (get-buffer (setq bname (concat base "-" (number-to-string n)))))
4852 (setq n (1+ n)))
4853 (condition-case nil
4854 (make-indirect-buffer buffer bname 'clone)
4855 (error (make-indirect-buffer buffer bname)))))
4857 (defun org-set-frame-title (title)
4858 "Set the title of the current frame to the string TITLE."
4859 ;; FIXME: how to name a single frame in XEmacs???
4860 (unless (featurep 'xemacs)
4861 (modify-frame-parameters (selected-frame) (list (cons 'name title)))))
4863 ;;;; Structure editing
4865 ;;; Inserting headlines
4867 (defun org-insert-heading (&optional force-heading)
4868 "Insert a new heading or item with same depth at point.
4869 If point is in a plain list and FORCE-HEADING is nil, create a new list item.
4870 If point is at the beginning of a headline, insert a sibling before the
4871 current headline. If point is in the middle of a headline, split the headline
4872 at that position and make the rest of the headline part of the sibling below
4873 the current headline."
4874 (interactive "P")
4875 (if (= (buffer-size) 0)
4876 (insert "\n* ")
4877 (when (or force-heading (not (org-insert-item)))
4878 (let* ((head (save-excursion
4879 (condition-case nil
4880 (progn
4881 (org-back-to-heading)
4882 (match-string 0))
4883 (error "*"))))
4884 (blank (cdr (assq 'heading org-blank-before-new-entry)))
4885 pos)
4886 (cond
4887 ((and (org-on-heading-p) (bolp)
4888 (or (bobp)
4889 (save-excursion (backward-char 1) (not (org-invisible-p)))))
4890 (open-line (if blank 2 1)))
4891 ((and (bolp)
4892 (or (bobp)
4893 (save-excursion
4894 (backward-char 1) (not (org-invisible-p)))))
4895 nil)
4896 (t (newline (if blank 2 1))))
4897 (insert head) (just-one-space)
4898 (setq pos (point))
4899 (end-of-line 1)
4900 (unless (= (point) pos) (just-one-space) (backward-delete-char 1))
4901 (run-hooks 'org-insert-heading-hook)))))
4904 (defun org-insert-todo-heading (arg)
4905 "Insert a new heading with the same level and TODO state as current heading.
4906 If the heading has no TODO state, or if the state is DONE, use the first
4907 state (TODO by default). Also with prefix arg, force first state."
4908 (interactive "P")
4909 (when (not (org-insert-item 'checkbox))
4910 (org-insert-heading)
4911 (save-excursion
4912 (org-back-to-heading)
4913 (outline-previous-heading)
4914 (looking-at org-todo-line-regexp))
4915 (if (or arg
4916 (not (match-beginning 2))
4917 (member (match-string 2) org-done-keywords))
4918 (insert (car org-todo-keywords-1) " ")
4919 (insert (match-string 2) " "))))
4921 ;;; Promotion and Demotion
4923 (defun org-promote-subtree ()
4924 "Promote the entire subtree.
4925 See also `org-promote'."
4926 (interactive)
4927 (save-excursion
4928 (org-map-tree 'org-promote))
4929 (org-fix-position-after-promote))
4931 (defun org-demote-subtree ()
4932 "Demote the entire subtree. See `org-demote'.
4933 See also `org-promote'."
4934 (interactive)
4935 (save-excursion
4936 (org-map-tree 'org-demote))
4937 (org-fix-position-after-promote))
4940 (defun org-do-promote ()
4941 "Promote the current heading higher up the tree.
4942 If the region is active in `transient-mark-mode', promote all headings
4943 in the region."
4944 (interactive)
4945 (save-excursion
4946 (if (org-region-active-p)
4947 (org-map-region 'org-promote (region-beginning) (region-end))
4948 (org-promote)))
4949 (org-fix-position-after-promote))
4951 (defun org-do-demote ()
4952 "Demote the current heading lower down the tree.
4953 If the region is active in `transient-mark-mode', demote all headings
4954 in the region."
4955 (interactive)
4956 (save-excursion
4957 (if (org-region-active-p)
4958 (org-map-region 'org-demote (region-beginning) (region-end))
4959 (org-demote)))
4960 (org-fix-position-after-promote))
4962 (defun org-fix-position-after-promote ()
4963 "Make sure that after pro/demotion cursor position is right."
4964 (let ((pos (point)))
4965 (when (save-excursion
4966 (beginning-of-line 1)
4967 (looking-at org-todo-line-regexp)
4968 (or (equal pos (match-end 1)) (equal pos (match-end 2))))
4969 (cond ((eobp) (insert " "))
4970 ((eolp) (insert " "))
4971 ((equal (char-after) ?\ ) (forward-char 1))))))
4973 (defun org-get-legal-level (level &optional change)
4974 "Rectify a level change under the influence of `org-odd-levels-only'
4975 LEVEL is a current level, CHANGE is by how much the level should be
4976 modified. Even if CHANGE is nil, LEVEL may be returned modified because
4977 even level numbers will become the next higher odd number."
4978 (if org-odd-levels-only
4979 (cond ((or (not change) (= 0 change)) (1+ (* 2 (/ level 2))))
4980 ((> change 0) (1+ (* 2 (/ (+ level (* 2 change)) 2))))
4981 ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2))))))
4982 (max 1 (+ level change))))
4984 (defun org-promote ()
4985 "Promote the current heading higher up the tree.
4986 If the region is active in `transient-mark-mode', promote all headings
4987 in the region."
4988 (org-back-to-heading t)
4989 (let* ((level (save-match-data (funcall outline-level)))
4990 (up-head (make-string (org-get-legal-level level -1) ?*))
4991 (diff (abs (- level (length up-head)))))
4992 (if (= level 1) (error "Cannot promote to level 0. UNDO to recover if necessary"))
4993 (replace-match up-head nil t)
4994 ;; Fixup tag positioning
4995 (and org-auto-align-tags (org-set-tags nil t))
4996 (if org-adapt-indentation (org-fixup-indentation (- diff)))))
4998 (defun org-demote ()
4999 "Demote the current heading lower down the tree.
5000 If the region is active in `transient-mark-mode', demote all headings
5001 in the region."
5002 (org-back-to-heading t)
5003 (let* ((level (save-match-data (funcall outline-level)))
5004 (down-head (make-string (org-get-legal-level level 1) ?*))
5005 (diff (abs (- level (length down-head)))))
5006 (replace-match down-head nil t)
5007 ;; Fixup tag positioning
5008 (and org-auto-align-tags (org-set-tags nil t))
5009 (if org-adapt-indentation (org-fixup-indentation diff))))
5011 (defun org-map-tree (fun)
5012 "Call FUN for every heading underneath the current one."
5013 (org-back-to-heading)
5014 (let ((level (funcall outline-level)))
5015 (save-excursion
5016 (funcall fun)
5017 (while (and (progn
5018 (outline-next-heading)
5019 (> (funcall outline-level) level))
5020 (not (eobp)))
5021 (funcall fun)))))
5023 (defun org-map-region (fun beg end)
5024 "Call FUN for every heading between BEG and END."
5025 (let ((org-ignore-region t))
5026 (save-excursion
5027 (setq end (copy-marker end))
5028 (goto-char beg)
5029 (if (and (re-search-forward (concat "^" outline-regexp) nil t)
5030 (< (point) end))
5031 (funcall fun))
5032 (while (and (progn
5033 (outline-next-heading)
5034 (< (point) end))
5035 (not (eobp)))
5036 (funcall fun)))))
5038 (defun org-fixup-indentation (diff)
5039 "Change the indentation in the current entry by DIFF
5040 However, if any line in the current entry has no indentation, or if it
5041 would end up with no indentation after the change, nothing at all is done."
5042 (save-excursion
5043 (let ((end (save-excursion (outline-next-heading)
5044 (point-marker)))
5045 (prohibit (if (> diff 0)
5046 "^\\S-"
5047 (concat "^ \\{0," (int-to-string (- diff)) "\\}\\S-")))
5048 col)
5049 (unless (save-excursion (re-search-forward prohibit end t))
5050 (while (re-search-forward "^[ \t]+" end t)
5051 (goto-char (match-end 0))
5052 (setq col (current-column))
5053 (if (< diff 0) (replace-match ""))
5054 (indent-to (+ diff col))))
5055 (move-marker end nil))))
5057 (defun org-convert-to-odd-levels ()
5058 "Convert an org-mode file with all levels allowed to one with odd levels.
5059 This will leave level 1 alone, convert level 2 to level 3, level 3 to
5060 level 5 etc."
5061 (interactive)
5062 (when (yes-or-no-p "Are you sure you want to globally change levels to odd? ")
5063 (let ((org-odd-levels-only nil) n)
5064 (save-excursion
5065 (goto-char (point-min))
5066 (while (re-search-forward "^\\*\\*+" nil t)
5067 (setq n (1- (length (match-string 0))))
5068 (while (>= (setq n (1- n)) 0)
5069 (org-demote))
5070 (end-of-line 1))))))
5073 (defun org-convert-to-oddeven-levels ()
5074 "Convert an org-mode file with only odd levels to one with odd and even levels.
5075 This promotes level 3 to level 2, level 5 to level 3 etc. If the file contains a
5076 section with an even level, conversion would destroy the structure of the file. An error
5077 is signaled in this case."
5078 (interactive)
5079 (goto-char (point-min))
5080 ;; First check if there are no even levels
5081 (when (re-search-forward "^\\(\\*\\*\\)+[^*]" nil t)
5082 (org-show-context t)
5083 (error "Not all levels are odd in this file. Conversion not possible."))
5084 (when (yes-or-no-p "Are you sure you want to globally change levels to odd-even? ")
5085 (let ((org-odd-levels-only nil) n)
5086 (save-excursion
5087 (goto-char (point-min))
5088 (while (re-search-forward "^\\*\\*+" nil t)
5089 (setq n (/ (length (match-string 0)) 2))
5090 (while (>= (setq n (1- n)) 0)
5091 (org-promote))
5092 (end-of-line 1))))))
5094 (defun org-tr-level (n)
5095 "Make N odd if required."
5096 (if org-odd-levels-only (1+ (/ n 2)) n))
5098 ;;; Vertical tree motion, cutting and pasting of subtrees
5100 (defun org-move-subtree-up (&optional arg)
5101 "Move the current subtree up past ARG headlines of the same level."
5102 (interactive "p")
5103 (org-move-subtree-down (- (prefix-numeric-value arg))))
5105 (defun org-move-subtree-down (&optional arg)
5106 "Move the current subtree down past ARG headlines of the same level."
5107 (interactive "p")
5108 (setq arg (prefix-numeric-value arg))
5109 (let ((movfunc (if (> arg 0) 'outline-get-next-sibling
5110 'outline-get-last-sibling))
5111 (ins-point (make-marker))
5112 (cnt (abs arg))
5113 beg end txt folded)
5114 ;; Select the tree
5115 (org-back-to-heading)
5116 (setq beg (point))
5117 (save-match-data
5118 (save-excursion (outline-end-of-heading)
5119 (setq folded (org-invisible-p)))
5120 (outline-end-of-subtree))
5121 (outline-next-heading)
5122 (setq end (point))
5123 ;; Find insertion point, with error handling
5124 (goto-char beg)
5125 (while (> cnt 0)
5126 (or (and (funcall movfunc) (looking-at outline-regexp))
5127 (progn (goto-char beg)
5128 (error "Cannot move past superior level or buffer limit")))
5129 (setq cnt (1- cnt)))
5130 (if (> arg 0)
5131 ;; Moving forward - still need to move over subtree
5132 (progn (outline-end-of-subtree)
5133 (outline-next-heading)
5134 (if (not (or (looking-at (concat "^" outline-regexp))
5135 (bolp)))
5136 (newline))))
5137 (move-marker ins-point (point))
5138 (setq txt (buffer-substring beg end))
5139 (delete-region beg end)
5140 (insert txt)
5141 (or (bolp) (insert "\n"))
5142 (goto-char ins-point)
5143 (if folded (hide-subtree))
5144 (move-marker ins-point nil)))
5146 (defvar org-subtree-clip ""
5147 "Clipboard for cut and paste of subtrees.
5148 This is actually only a copy of the kill, because we use the normal kill
5149 ring. We need it to check if the kill was created by `org-copy-subtree'.")
5151 (defvar org-subtree-clip-folded nil
5152 "Was the last copied subtree folded?
5153 This is used to fold the tree back after pasting.")
5155 (defun org-cut-subtree ()
5156 "Cut the current subtree into the clipboard.
5157 This is a short-hand for marking the subtree and then cutting it."
5158 (interactive)
5159 (org-copy-subtree 'cut))
5161 (defun org-copy-subtree (&optional cut)
5162 "Cut the current subtree into the clipboard.
5163 This is a short-hand for marking the subtree and then copying it.
5164 If CUT is non-nil, actually cut the subtree."
5165 (interactive)
5166 (let (beg end folded)
5167 (if (interactive-p)
5168 (org-back-to-heading nil) ; take what looks like a subtree
5169 (org-back-to-heading t)) ; take what is really there
5170 (setq beg (point))
5171 (save-match-data
5172 (save-excursion (outline-end-of-heading)
5173 (setq folded (org-invisible-p)))
5174 (outline-end-of-subtree))
5175 (if (equal (char-after) ?\n) (forward-char 1))
5176 (setq end (point))
5177 (goto-char beg)
5178 (when (> end beg)
5179 (setq org-subtree-clip-folded folded)
5180 (if cut (kill-region beg end) (copy-region-as-kill beg end))
5181 (setq org-subtree-clip (current-kill 0))
5182 (message "%s: Subtree with %d characters"
5183 (if cut "Cut" "Copied")
5184 (length org-subtree-clip)))))
5186 (defun org-paste-subtree (&optional level tree)
5187 "Paste the clipboard as a subtree, with modification of headline level.
5188 The entire subtree is promoted or demoted in order to match a new headline
5189 level. By default, the new level is derived from the visible headings
5190 before and after the insertion point, and taken to be the inferior headline
5191 level of the two. So if the previous visible heading is level 3 and the
5192 next is level 4 (or vice versa), level 4 will be used for insertion.
5193 This makes sure that the subtree remains an independent subtree and does
5194 not swallow low level entries.
5196 You can also force a different level, either by using a numeric prefix
5197 argument, or by inserting the heading marker by hand. For example, if the
5198 cursor is after \"*****\", then the tree will be shifted to level 5.
5200 If you want to insert the tree as is, just use \\[yank].
5202 If optional TREE is given, use this text instead of the kill ring."
5203 (interactive "P")
5204 (unless (org-kill-is-subtree-p tree)
5205 (error
5206 (substitute-command-keys
5207 "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway")))
5208 (let* ((txt (or tree (and kill-ring (current-kill 0))))
5209 (^re (concat "^\\(" outline-regexp "\\)"))
5210 (re (concat "\\(" outline-regexp "\\)"))
5211 (^re_ (concat "\\(" outline-regexp "\\)[ \t]*"))
5213 (old-level (if (string-match ^re txt)
5214 (- (match-end 0) (match-beginning 0))
5215 -1))
5216 (force-level (cond (level (prefix-numeric-value level))
5217 ((string-match
5218 ^re_ (buffer-substring (point-at-bol) (point)))
5219 (- (match-end 0) (match-beginning 0)))
5220 (t nil)))
5221 (previous-level (save-excursion
5222 (condition-case nil
5223 (progn
5224 (outline-previous-visible-heading 1)
5225 (if (looking-at re)
5226 (- (match-end 0) (match-beginning 0))
5228 (error 1))))
5229 (next-level (save-excursion
5230 (condition-case nil
5231 (progn
5232 (outline-next-visible-heading 1)
5233 (if (looking-at re)
5234 (- (match-end 0) (match-beginning 0))
5236 (error 1))))
5237 (new-level (or force-level (max previous-level next-level)))
5238 (shift (if (or (= old-level -1)
5239 (= new-level -1)
5240 (= old-level new-level))
5242 (- new-level old-level)))
5243 (shift1 shift)
5244 (delta (if (> shift 0) -1 1))
5245 (func (if (> shift 0) 'org-demote 'org-promote))
5246 (org-odd-levels-only nil)
5247 beg end)
5248 ;; Remove the forces level indicator
5249 (if force-level
5250 (delete-region (point-at-bol) (point)))
5251 ;; Make sure we start at the beginning of an empty line
5252 (if (not (bolp)) (insert "\n"))
5253 (if (not (looking-at "[ \t]*$"))
5254 (progn (insert "\n") (backward-char 1)))
5255 ;; Paste
5256 (setq beg (point))
5257 (if (string-match "[ \t\r\n]+\\'" txt)
5258 (setq txt (replace-match "\n" t t txt)))
5259 (insert txt)
5260 (setq end (point))
5261 (if (looking-at "[ \t\r\n]+")
5262 (replace-match "\n"))
5263 (goto-char beg)
5264 ;; Shift if necessary
5265 (if (= shift 0)
5266 (message "Pasted at level %d, without shift" new-level)
5267 (save-restriction
5268 (narrow-to-region beg end)
5269 (while (not (= shift 0))
5270 (org-map-region func (point-min) (point-max))
5271 (setq shift (+ delta shift)))
5272 (goto-char (point-min))
5273 (message "Pasted at level %d, with shift by %d levels"
5274 new-level shift1)))
5275 (if (and kill-ring
5276 (eq org-subtree-clip (current-kill 0))
5277 org-subtree-clip-folded)
5278 ;; The tree was folded before it was killed/copied
5279 (hide-subtree))))
5281 (defun org-kill-is-subtree-p (&optional txt)
5282 "Check if the current kill is an outline subtree, or a set of trees.
5283 Returns nil if kill does not start with a headline, or if the first
5284 headline level is not the largest headline level in the tree.
5285 So this will actually accept several entries of equal levels as well,
5286 which is OK for `org-paste-subtree'.
5287 If optional TXT is given, check this string instead of the current kill."
5288 (let* ((kill (or txt (and kill-ring (current-kill 0)) ""))
5289 (start-level (and kill
5290 (string-match (concat "\\`" outline-regexp) kill)
5291 (- (match-end 0) (match-beginning 0))))
5292 (re (concat "^" outline-regexp))
5293 (start 1))
5294 (if (not start-level)
5295 nil ;; does not even start with a heading
5296 (catch 'exit
5297 (while (setq start (string-match re kill (1+ start)))
5298 (if (< (- (match-end 0) (match-beginning 0)) start-level)
5299 (throw 'exit nil)))
5300 t))))
5302 (defun org-narrow-to-subtree ()
5303 "Narrow buffer to the current subtree."
5304 (interactive)
5305 (save-excursion
5306 (narrow-to-region
5307 (progn (org-back-to-heading) (point))
5308 (progn (org-end-of-subtree t t) (point)))))
5311 ;;; Outline Sorting
5313 (defun org-sort (with-case)
5314 "Call `org-sort-entries' or `org-table-sort-lines', depending on context."
5315 (interactive "P")
5316 (if (org-at-table-p)
5317 (org-call-with-arg 'org-table-sort-lines with-case)
5318 (org-call-with-arg 'org-sort-entries with-case)))
5320 (defun org-sort-entries (&optional with-case sorting-type)
5321 "Sort entries on a certain level of an outline tree.
5322 If there is an active region, the entries in the region are sorted.
5323 Else, if the cursor is before the first entry, sort the top-level items.
5324 Else, the children of the entry at point are sorted.
5326 Sorting can be alphabetically, numerically, and by date/time as given by
5327 the first time stamp in the entry. The command prompts for the sorting
5328 type unless it has been given to the function through the SORTING-TYPE
5329 argument, which needs to a character, any of (?n ?N ?a ?A ?t ?T).
5331 Comparing entries ignores case by default. However, with an optional argument
5332 WITH-CASE, the sorting considers case as well. With two prefix arguments
5333 `C-u C-u', sorting is case-sensitive and duplicate entries will be removed."
5334 (interactive "P")
5335 (let ((unique (equal with-case '(16)))
5336 start beg end entries stars re re2 p nentries (nremoved 0)
5337 last txt what)
5338 ;; Find beginning and end of region to sort
5339 (cond
5340 ((org-region-active-p)
5341 ;; we will sort the region
5342 (setq end (region-end)
5343 what "region")
5344 (goto-char (region-beginning))
5345 (if (not (org-on-heading-p)) (outline-next-heading))
5346 (setq start (point)))
5347 ((or (org-on-heading-p)
5348 (condition-case nil (progn (org-back-to-heading) t) (error nil)))
5349 ;; we will sort the children of the current headline
5350 (org-back-to-heading)
5351 (setq start (point) end (org-end-of-subtree) what "children")
5352 (goto-char start)
5353 (show-subtree)
5354 (outline-next-heading))
5356 ;; we will sort the top-level entries in this file
5357 (goto-char (point-min))
5358 (or (org-on-heading-p) (outline-next-heading))
5359 (setq start (point) end (point-max) what "top-level")
5360 (goto-char start)
5361 (show-all)))
5362 (setq beg (point))
5363 (if (>= (point) end) (error "Nothing to sort"))
5364 (looking-at "\\(\\*+\\)")
5365 (setq stars (match-string 1)
5366 re (concat "^" (regexp-quote stars) " +")
5367 re2 (concat "^" (regexp-quote (substring stars 0 -1)) "[^*]")
5368 txt (buffer-substring beg end))
5369 (if (not (equal (substring txt -1) "\n")) (setq txt (concat txt "\n")))
5370 (if (and (not (equal stars "*")) (string-match re2 txt))
5371 (error "Region to sort contains a level above the first entry"))
5372 ;; Make a list that can be sorted.
5373 ;; The car is the string for comparison, the cdr is the subtree
5374 (message "Sorting entries...")
5375 (setq entries
5376 (mapcar
5377 (lambda (x)
5378 (string-match "^.*\\(\n.*\\)?" x) ; take two lines
5379 (cons (match-string 0 x) x))
5380 (org-split-string txt re)))
5382 ;; Sort the list
5383 (save-excursion
5384 (goto-char start)
5385 (setq entries (org-do-sort entries what with-case sorting-type)))
5387 ;; Delete the old stuff
5388 (goto-char beg)
5389 (kill-region beg end)
5390 (setq nentries (length entries))
5391 ;; Insert the sorted entries, and remove duplicates if this is required
5392 (while (setq p (pop entries))
5393 (if (and unique (equal last (setq last (org-trim (cdr p)))))
5394 (setq nremoved (1+ nremoved)) ; same entry as before, skip it
5395 (insert stars " " (cdr p))))
5396 (goto-char start)
5397 (message "Sorting entries...done (%d entries%s)"
5398 nentries
5399 (if unique (format ", %d duplicates removed" nremoved) ""))))
5401 (defun org-do-sort (table what &optional with-case sorting-type)
5402 "Sort TABLE of WHAT according to SORTING-TYPE.
5403 The user will be prompted for the SORTING-TYPE if the call to this
5404 function does not specify it. WHAT is only for the prompt, to indicate
5405 what is being sorted. The sorting key will be extracted from
5406 the car of the elements of the table.
5407 If WITH-CASE is non-nil, the sorting will be case-sensitive."
5408 (unless sorting-type
5409 (message
5410 "Sort %s: [a]lphabetically [n]umerically [t]ime. A/N/T means reversed:"
5411 what)
5412 (setq sorting-type (read-char-exclusive)))
5413 (let ((dcst (downcase sorting-type))
5414 extractfun comparefun)
5415 ;; Define the appropriate functions
5416 (cond
5417 ((= dcst ?n)
5418 (setq extractfun 'string-to-number
5419 comparefun (if (= dcst sorting-type) '< '>)))
5420 ((= dcst ?a)
5421 (setq extractfun (if with-case 'identity 'downcase)
5422 comparefun (if (= dcst sorting-type)
5423 'string<
5424 (lambda (a b) (and (not (string< a b))
5425 (not (string= a b)))))))
5426 ((= dcst ?t)
5427 (setq extractfun
5428 (lambda (x)
5429 (if (string-match org-ts-regexp x)
5430 (time-to-seconds
5431 (org-time-string-to-time (match-string 0 x)))
5433 comparefun (if (= dcst sorting-type) '< '>)))
5434 (t (error "Invalid sorting type `%c'" sorting-type)))
5436 (sort (mapcar (lambda (x) (cons (funcall extractfun (car x)) (cdr x)))
5437 table)
5438 (lambda (a b) (funcall comparefun (car a) (car b))))))
5440 ;;;; Plain list items, including checkboxes
5442 ;;; Plain list items
5444 (defun org-at-item-p ()
5445 "Is point in a line starting a hand-formatted item?"
5446 (let ((llt org-plain-list-ordered-item-terminator))
5447 (save-excursion
5448 (goto-char (point-at-bol))
5449 (looking-at
5450 (cond
5451 ((eq llt t) "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
5452 ((= llt ?.) "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
5453 ((= llt ?\)) "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
5454 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))))))
5457 (defun org-in-item-p ()
5458 "It the cursor inside a plain list item.
5459 Does not have to be the first line."
5460 (save-excursion
5461 (condition-case nil
5462 (progn
5463 (org-beginning-of-item)
5464 (org-at-item-p)
5466 (error nil))))
5468 (defun org-insert-item (&optional checkbox)
5469 "Insert a new item at the current level.
5470 Return t when things worked, nil when we are not in an item."
5471 (when (save-excursion
5472 (condition-case nil
5473 (progn
5474 (org-beginning-of-item)
5475 (org-at-item-p)
5476 (if (org-invisible-p) (error "Invisible item"))
5478 (error nil)))
5479 (let* ((bul (match-string 0))
5480 (eow (save-excursion (beginning-of-line 1) (looking-at "[ \t]*")
5481 (match-end 0)))
5482 (blank (cdr (assq 'plain-list-item org-blank-before-new-entry)))
5483 pos)
5484 (cond
5485 ((and (org-at-item-p) (<= (point) eow))
5486 ;; before the bullet
5487 (beginning-of-line 1)
5488 (open-line (if blank 2 1)))
5489 ((<= (point) eow)
5490 (beginning-of-line 1))
5491 (t (newline (if blank 2 1))))
5492 (insert bul (if checkbox "[ ]" ""))
5493 (just-one-space)
5494 (setq pos (point))
5495 (end-of-line 1)
5496 (unless (= (point) pos) (just-one-space) (backward-delete-char 1)))
5497 (org-maybe-renumber-ordered-list)
5498 (and checkbox (org-update-checkbox-count-maybe))
5501 ;;; Checkboxes
5503 (defun org-at-item-checkbox-p ()
5504 "Is point at a line starting a plain-list item with a checklet?"
5505 (and (org-at-item-p)
5506 (save-excursion
5507 (goto-char (match-end 0))
5508 (skip-chars-forward " \t")
5509 (looking-at "\\[[ X]\\]"))))
5511 (defun org-toggle-checkbox (&optional arg)
5512 "Toggle the checkbox in the current line."
5513 (interactive "P")
5514 (catch 'exit
5515 (let (beg end status (firstnew 'unknown))
5516 (cond
5517 ((org-region-active-p)
5518 (setq beg (region-beginning) end (region-end)))
5519 ((org-on-heading-p)
5520 (setq beg (point) end (save-excursion (outline-next-heading) (point))))
5521 ((org-at-item-checkbox-p)
5522 (save-excursion
5523 (replace-match (if (equal (match-string 0) "[ ]") "[X]" "[ ]") t t))
5524 (throw 'exit t))
5525 (t (error "Not at a checkbox or heading, and no active region")))
5526 (save-excursion
5527 (goto-char beg)
5528 (while (< (point) end)
5529 (when (org-at-item-checkbox-p)
5530 (setq status (equal (match-string 0) "[X]"))
5531 (when (eq firstnew 'unknown)
5532 (setq firstnew (not status)))
5533 (replace-match
5534 (if (if arg (not status) firstnew) "[X]" "[ ]") t t))
5535 (beginning-of-line 2)))))
5536 (org-update-checkbox-count-maybe))
5538 (defun org-update-checkbox-count-maybe ()
5539 "Update checkbox statistics unless turned off by user."
5540 (when org-provide-checkbox-statistics
5541 (org-update-checkbox-count)))
5543 (defun org-update-checkbox-count (&optional all)
5544 "Update the checkbox statistics in the current section.
5545 This will find all statistic cookies like [57%] and [6/12] and update them
5546 with the current numbers. With optional prefix argument ALL, do this for
5547 the whole buffer."
5548 (interactive "P")
5549 (save-excursion
5550 (let* ((buffer-invisibility-spec (org-inhibit-invisibility)) ; Emacs 21
5551 (beg (progn (outline-back-to-heading) (point)))
5552 (end (move-marker (make-marker)
5553 (progn (outline-next-heading) (point))))
5554 (re "\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)")
5555 (re-box "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)")
5556 b1 e1 f1 c-on c-off lim (cstat 0))
5557 (when all
5558 (goto-char (point-min))
5559 (outline-next-heading)
5560 (setq beg (point) end (point-max)))
5561 (goto-char beg)
5562 (while (re-search-forward re end t)
5563 (setq cstat (1+ cstat)
5564 b1 (match-beginning 0)
5565 e1 (match-end 0)
5566 f1 (match-beginning 1)
5567 lim (cond
5568 ((org-on-heading-p) (outline-next-heading) (point))
5569 ((org-at-item-p) (org-end-of-item) (point))
5570 (t nil))
5571 c-on 0 c-off 0)
5572 (goto-char e1)
5573 (when lim
5574 (while (re-search-forward re-box lim t)
5575 (if (equal (match-string 2) "[ ]")
5576 (setq c-off (1+ c-off))
5577 (setq c-on (1+ c-on))))
5578 (delete-region b1 e1)
5579 (goto-char b1)
5580 (insert (if f1
5581 (format "[%d%%]" (/ (* 100 c-on) (max 1 (+ c-on c-off))))
5582 (format "[%d/%d]" c-on (+ c-on c-off))))))
5583 (when (interactive-p)
5584 (message "Checkbox satistics updated %s (%d places)"
5585 (if all "in entire file" "in current outline entry") cstat)))))
5587 (defun org-get-checkbox-statistics-face ()
5588 "Select the face for checkbox statistics.
5589 The face will be `org-done' when all relevant boxes are checked. Otherwise
5590 it will be `org-todo'."
5591 (if (match-end 1)
5592 (if (equal (match-string 1) "100%") 'org-done 'org-todo)
5593 (if (and (> (match-end 2) (match-beginning 2))
5594 (equal (match-string 2) (match-string 3)))
5595 'org-done
5596 'org-todo)))
5598 (defun org-get-indentation (&optional line)
5599 "Get the indentation of the current line, interpreting tabs.
5600 When LINE is given, assume it represents a line and compute its indentation."
5601 (if line
5602 (if (string-match "^ *" (org-remove-tabs line))
5603 (match-end 0))
5604 (save-excursion
5605 (beginning-of-line 1)
5606 (skip-chars-forward " \t")
5607 (current-column))))
5609 (defun org-remove-tabs (s &optional width)
5610 "Replace tabulators in S with spaces.
5611 Assumes that s is a single line, starting in column 0."
5612 (setq width (or width tab-width))
5613 (while (string-match "\t" s)
5614 (setq s (replace-match
5615 (make-string
5616 (- (* width (/ (+ (match-beginning 0) width) width))
5617 (match-beginning 0)) ?\ )
5618 t t s)))
5621 (defun org-fix-indentation (line ind)
5622 "Fix indentation in LINE.
5623 IND is a cons cell with target and minimum indentation.
5624 If the current indenation in LINE is smaller than the minimum,
5625 leave it alone. If it is larger than ind, set it to the target."
5626 (let* ((l (org-remove-tabs line))
5627 (i (org-get-indentation l))
5628 (i1 (car ind)) (i2 (cdr ind)))
5629 (if (>= i i2) (setq l (substring line i2)))
5630 (if (> i1 0)
5631 (concat (make-string i1 ?\ ) l)
5632 l)))
5634 (defcustom org-empty-line-terminates-plain-lists nil
5635 "Non-nil means, an empty line ends all plain list levels.
5636 When nil, empty lines are part of the preceeding item."
5637 :group 'org-plain-lists
5638 :type 'boolean)
5640 (defun org-beginning-of-item ()
5641 "Go to the beginning of the current hand-formatted item.
5642 If the cursor is not in an item, throw an error."
5643 (interactive)
5644 (let ((pos (point))
5645 (limit (save-excursion
5646 (condition-case nil
5647 (progn
5648 (org-back-to-heading)
5649 (beginning-of-line 2) (point))
5650 (error (point-min)))))
5651 (ind-empty (if org-empty-line-terminates-plain-lists 0 10000))
5652 ind ind1)
5653 (if (org-at-item-p)
5654 (beginning-of-line 1)
5655 (beginning-of-line 1)
5656 (skip-chars-forward " \t")
5657 (setq ind (current-column))
5658 (if (catch 'exit
5659 (while t
5660 (beginning-of-line 0)
5661 (if (or (bobp) (< (point) limit)) (throw 'exit nil))
5663 (if (looking-at "[ \t]*$")
5664 (setq ind1 ind-empty)
5665 (skip-chars-forward " \t")
5666 (setq ind1 (current-column)))
5667 (if (< ind1 ind)
5668 (progn (beginning-of-line 1) (throw 'exit (org-at-item-p))))))
5670 (goto-char pos)
5671 (error "Not in an item")))))
5673 (defun org-end-of-item ()
5674 "Go to the end of the current hand-formatted item.
5675 If the cursor is not in an item, throw an error."
5676 (interactive)
5677 (let* ((pos (point))
5678 ind1
5679 (ind-empty (if org-empty-line-terminates-plain-lists 0 10000))
5680 (limit (save-excursion (outline-next-heading) (point)))
5681 (ind (save-excursion
5682 (org-beginning-of-item)
5683 (skip-chars-forward " \t")
5684 (current-column)))
5685 (end (catch 'exit
5686 (while t
5687 (beginning-of-line 2)
5688 (if (eobp) (throw 'exit (point)))
5689 (if (>= (point) limit) (throw 'exit (point-at-bol)))
5690 (if (looking-at "[ \t]*$")
5691 (setq ind1 ind-empty)
5692 (skip-chars-forward " \t")
5693 (setq ind1 (current-column)))
5694 (if (<= ind1 ind)
5695 (throw 'exit (point-at-bol)))))))
5696 (if end
5697 (goto-char end)
5698 (goto-char pos)
5699 (error "Not in an item"))))
5701 (defun org-next-item ()
5702 "Move to the beginning of the next item in the current plain list.
5703 Error if not at a plain list, or if this is the last item in the list."
5704 (interactive)
5705 (let (ind ind1 (pos (point)))
5706 (org-beginning-of-item)
5707 (setq ind (org-get-indentation))
5708 (org-end-of-item)
5709 (setq ind1 (org-get-indentation))
5710 (unless (and (org-at-item-p) (= ind ind1))
5711 (goto-char pos)
5712 (error "On last item"))))
5714 (defun org-previous-item ()
5715 "Move to the beginning of the previous item in the current plain list.
5716 Error if not at a plain list, or if this is the last item in the list."
5717 (interactive)
5718 (let (beg ind (pos (point)))
5719 (org-beginning-of-item)
5720 (setq beg (point))
5721 (setq ind (org-get-indentation))
5722 (goto-char beg)
5723 (catch 'exit
5724 (while t
5725 (beginning-of-line 0)
5726 (if (looking-at "[ \t]*$")
5728 (if (<= (org-get-indentation) ind)
5729 (throw 'exit t)))))
5730 (condition-case nil
5731 (org-beginning-of-item)
5732 (error (goto-char pos)
5733 (error "On first item")))))
5735 (defun org-move-item-down ()
5736 "Move the plain list item at point down, i.e. swap with following item.
5737 Subitems (items with larger indentation) are considered part of the item,
5738 so this really moves item trees."
5739 (interactive)
5740 (let (beg end ind ind1 (pos (point)) txt)
5741 (org-beginning-of-item)
5742 (setq beg (point))
5743 (setq ind (org-get-indentation))
5744 (org-end-of-item)
5745 (setq end (point))
5746 (setq ind1 (org-get-indentation))
5747 (if (and (org-at-item-p) (= ind ind1))
5748 (progn
5749 (org-end-of-item)
5750 (setq txt (buffer-substring beg end))
5751 (save-excursion
5752 (delete-region beg end))
5753 (setq pos (point))
5754 (insert txt)
5755 (goto-char pos)
5756 (org-maybe-renumber-ordered-list))
5757 (goto-char pos)
5758 (error "Cannot move this item further down"))))
5760 (defun org-move-item-up (arg)
5761 "Move the plain list item at point up, i.e. swap with previous item.
5762 Subitems (items with larger indentation) are considered part of the item,
5763 so this really moves item trees."
5764 (interactive "p")
5765 (let (beg end ind ind1 (pos (point)) txt)
5766 (org-beginning-of-item)
5767 (setq beg (point))
5768 (setq ind (org-get-indentation))
5769 (org-end-of-item)
5770 (setq end (point))
5771 (goto-char beg)
5772 (catch 'exit
5773 (while t
5774 (beginning-of-line 0)
5775 (if (looking-at "[ \t]*$")
5776 (if org-empty-line-terminates-plain-lists
5777 (progn
5778 (goto-char pos)
5779 (error "Cannot move this item further up"))
5780 nil)
5781 (if (<= (setq ind1 (org-get-indentation)) ind)
5782 (throw 'exit t)))))
5783 (condition-case nil
5784 (org-beginning-of-item)
5785 (error (goto-char beg)
5786 (error "Cannot move this item further up")))
5787 (setq ind1 (org-get-indentation))
5788 (if (and (org-at-item-p) (= ind ind1))
5789 (progn
5790 (setq txt (buffer-substring beg end))
5791 (save-excursion
5792 (delete-region beg end))
5793 (setq pos (point))
5794 (insert txt)
5795 (goto-char pos)
5796 (org-maybe-renumber-ordered-list))
5797 (goto-char pos)
5798 (error "Cannot move this item further up"))))
5800 (defun org-maybe-renumber-ordered-list ()
5801 "Renumber the ordered list at point if setup allows it.
5802 This tests the user option `org-auto-renumber-ordered-lists' before
5803 doing the renumbering."
5804 (and org-auto-renumber-ordered-lists
5805 (org-at-item-p)
5806 (match-beginning 3)
5807 (org-renumber-ordered-list 1)))
5809 (defun org-get-string-indentation (s)
5810 "What indentation has S due to SPACE and TAB at the beginning of the string?"
5811 (let ((n -1) (i 0) (w tab-width) c)
5812 (catch 'exit
5813 (while (< (setq n (1+ n)) (length s))
5814 (setq c (aref s n))
5815 (cond ((= c ?\ ) (setq i (1+ i)))
5816 ((= c ?\t) (setq i (* (/ (+ w i) w) w)))
5817 (t (throw 'exit t)))))
5820 (defun org-renumber-ordered-list (arg)
5821 "Renumber an ordered plain list.
5822 Cursor needs to be in the first line of an item, the line that starts
5823 with something like \"1.\" or \"2)\"."
5824 (interactive "p")
5825 (unless (and (org-at-item-p)
5826 (match-beginning 3))
5827 (error "This is not an ordered list"))
5828 (let ((line (org-current-line))
5829 (col (current-column))
5830 (ind (org-get-string-indentation
5831 (buffer-substring (point-at-bol) (match-beginning 3))))
5832 ;; (term (substring (match-string 3) -1))
5833 ind1 (n (1- arg)))
5834 ;; find where this list begins
5835 (catch 'exit
5836 (while t
5837 (catch 'next
5838 (beginning-of-line 0)
5839 (if (looking-at "[ \t]*$") (throw 'next t))
5840 (skip-chars-forward " \t") (setq ind1 (current-column))
5841 (if (or (< ind1 ind)
5842 (and (= ind1 ind)
5843 (not (org-at-item-p))))
5844 (throw 'exit t)))))
5845 ;; Walk forward and replace these numbers
5846 (catch 'exit
5847 (while t
5848 (catch 'next
5849 (beginning-of-line 2)
5850 (if (eobp) (throw 'exit nil))
5851 (if (looking-at "[ \t]*$") (throw 'next nil))
5852 (skip-chars-forward " \t") (setq ind1 (current-column))
5853 (if (> ind1 ind) (throw 'next t))
5854 (if (< ind1 ind) (throw 'exit t))
5855 (if (not (org-at-item-p)) (throw 'exit nil))
5856 (if (not (match-beginning 3))
5857 (error "unordered bullet in ordered list. Press \\[undo] to recover"))
5858 (delete-region (match-beginning 3) (1- (match-end 3)))
5859 (goto-char (match-beginning 3))
5860 (insert (format "%d" (setq n (1+ n)))))))
5861 (goto-line line)
5862 (move-to-column col)))
5864 (defvar org-last-indent-begin-marker (make-marker))
5865 (defvar org-last-indent-end-marker (make-marker))
5867 (defun org-outdent-item (arg)
5868 "Outdent a local list item."
5869 (interactive "p")
5870 (org-indent-item (- arg)))
5872 (defun org-indent-item (arg)
5873 "Indent a local list item."
5874 (interactive "p")
5875 (unless (org-at-item-p)
5876 (error "Not on an item"))
5877 (save-excursion
5878 (let (beg end ind ind1)
5879 (if (memq last-command '(org-shiftmetaright org-shiftmetaleft))
5880 (setq beg org-last-indent-begin-marker
5881 end org-last-indent-end-marker)
5882 (org-beginning-of-item)
5883 (setq beg (move-marker org-last-indent-begin-marker (point)))
5884 (org-end-of-item)
5885 (setq end (move-marker org-last-indent-end-marker (point))))
5886 (goto-char beg)
5887 (skip-chars-forward " \t") (setq ind (current-column))
5888 (if (< (+ arg ind) 0) (error "Cannot outdent beyond margin"))
5889 (while (< (point) end)
5890 (beginning-of-line 1)
5891 (skip-chars-forward " \t") (setq ind1 (current-column))
5892 (delete-region (point-at-bol) (point))
5893 (indent-to-column (+ ind1 arg))
5894 (beginning-of-line 2)))))
5896 ;;;; Archiving
5898 (defalias 'org-advertized-archive-subtree 'org-archive-subtree)
5900 (defun org-archive-subtree (&optional find-done)
5901 "Move the current subtree to the archive.
5902 The archive can be a certain top-level heading in the current file, or in
5903 a different file. The tree will be moved to that location, the subtree
5904 heading be marked DONE, and the current time will be added.
5906 When called with prefix argument FIND-DONE, find whole trees without any
5907 open TODO items and archive them (after getting confirmation from the user).
5908 If the cursor is not at a headline when this comand is called, try all level
5909 1 trees. If the cursor is on a headline, only try the direct children of
5910 this heading."
5911 (interactive "P")
5912 (if find-done
5913 (org-archive-all-done)
5914 ;; Save all relevant TODO keyword-relatex variables
5916 (let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler
5917 (tr-org-todo-keywords-1 org-todo-keywords-1)
5918 (tr-org-todo-kwd-alist org-todo-kwd-alist)
5919 (tr-org-done-keywords org-done-keywords)
5920 (tr-org-todo-regexp org-todo-regexp)
5921 (tr-org-todo-line-regexp org-todo-line-regexp)
5922 (tr-org-odd-levels-only org-odd-levels-only)
5923 (this-buffer (current-buffer))
5924 (org-archive-location org-archive-location)
5925 (re "^#\\+ARCHIVE:[ \t]+\\(\\S-.*\\S-\\)[ \t]*$")
5926 file heading buffer level newfile-p)
5928 ;; Try to find a local archive location
5929 (save-excursion
5930 (save-restriction
5931 (widen)
5932 (if (or (re-search-backward re nil t) (re-search-forward re nil t))
5933 (setq org-archive-location (match-string 1)))))
5935 (if (string-match "\\(.*\\)::\\(.*\\)" org-archive-location)
5936 (progn
5937 (setq file (format (match-string 1 org-archive-location)
5938 (file-name-nondirectory buffer-file-name))
5939 heading (match-string 2 org-archive-location)))
5940 (error "Invalid `org-archive-location'"))
5941 (if (> (length file) 0)
5942 (setq newfile-p (not (file-exists-p file))
5943 buffer (find-file-noselect file))
5944 (setq buffer (current-buffer)))
5945 (unless buffer
5946 (error "Cannot access file \"%s\"" file))
5947 (if (and (> (length heading) 0)
5948 (string-match "^\\*+" heading))
5949 (setq level (match-end 0))
5950 (setq heading nil level 0))
5951 (save-excursion
5952 ;; We first only copy, in case something goes wrong
5953 ;; we need to protect this-command, to avoid kill-region sets it,
5954 ;; which would lead to duplication of subtrees
5955 (let (this-command) (org-copy-subtree))
5956 (set-buffer buffer)
5957 ;; Enforce org-mode for the archive buffer
5958 (if (not (org-mode-p))
5959 ;; Force the mode for future visits.
5960 (let ((org-insert-mode-line-in-empty-file t)
5961 (org-inhibit-startup t))
5962 (call-interactively 'org-mode)))
5963 (when newfile-p
5964 (goto-char (point-max))
5965 (insert (format "\nArchived entries from file %s\n\n"
5966 (buffer-file-name this-buffer))))
5967 ;; Force the TODO keywords of the original buffer
5968 (let ((org-todo-line-regexp tr-org-todo-line-regexp)
5969 (org-todo-keywords-1 tr-org-todo-keywords-1)
5970 (org-todo-kwd-alist tr-org-todo-kwd-alist)
5971 (org-done-keywords tr-org-done-keywords)
5972 (org-todo-regexp tr-org-todo-regexp)
5973 (org-todo-line-regexp tr-org-todo-line-regexp)
5974 (org-odd-levels-only
5975 (if (local-variable-p 'org-odd-levels-only (current-buffer))
5976 org-odd-levels-only
5977 tr-org-odd-levels-only)))
5978 (goto-char (point-min))
5979 (if heading
5980 (progn
5981 (if (re-search-forward
5982 (concat "\\(^\\|\r\\)"
5983 (regexp-quote heading) "[ \t]*\\(:[a-zA-Z0-9_@:]+:\\)?[ \t]*\\($\\|\r\\)")
5984 nil t)
5985 (goto-char (match-end 0))
5986 ;; Heading not found, just insert it at the end
5987 (goto-char (point-max))
5988 (or (bolp) (insert "\n"))
5989 (insert "\n" heading "\n")
5990 (end-of-line 0))
5991 ;; Make the subtree visible
5992 (show-subtree)
5993 (org-end-of-subtree t)
5994 (skip-chars-backward " \t\r\n")
5995 (and (looking-at "[ \t\r\n]*")
5996 (replace-match "\n\n")))
5997 ;; No specific heading, just go to end of file.
5998 (goto-char (point-max)) (insert "\n"))
5999 ;; Paste
6000 (org-paste-subtree (org-get-legal-level level 1))
6001 ;; Mark the entry as done, i.e. set to last word in org-todo-keywords-1 FIXME: not right anymore!!!!!!!
6002 (if org-archive-mark-done
6003 (let (org-log-done)
6004 (org-todo (length org-todo-keywords-1))))
6005 ;; Move cursor to right after the TODO keyword
6006 (when org-archive-stamp-time
6007 (beginning-of-line 1)
6008 (looking-at org-todo-line-regexp)
6009 (goto-char (or (match-end 2) (match-beginning 3)))
6010 (org-insert-time-stamp (org-current-time) t t "(" ")"))
6011 ;; Save the buffer, if it is not the same buffer.
6012 (if (not (eq this-buffer buffer)) (save-buffer))))
6013 ;; Here we are back in the original buffer. Everything seems to have
6014 ;; worked. So now cut the tree and finish up.
6015 (let (this-command) (org-cut-subtree))
6016 (if (and (not (eobp)) (looking-at "[ \t]*$")) (kill-line))
6017 (message "Subtree archived %s"
6018 (if (eq this-buffer buffer)
6019 (concat "under heading: " heading)
6020 (concat "in file: " (abbreviate-file-name file)))))))
6022 (defun org-archive-all-done (&optional tag)
6023 "Archive sublevels of the current tree without open TODO items.
6024 If the cursor is not on a headline, try all level 1 trees. If
6025 it is on a headline, try all direct children.
6026 When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag."
6027 (let ((re (concat "^\\*+ +" org-not-done-regexp)) re1
6028 (rea (concat ".*:" org-archive-tag ":"))
6029 (begm (make-marker))
6030 (endm (make-marker))
6031 (question (if tag "Set ARCHIVE tag (no open TODO items)? "
6032 "Move subtree to archive (no open TODO items)? "))
6033 beg end (cntarch 0))
6034 (if (org-on-heading-p)
6035 (progn
6036 (setq re1 (concat "^" (regexp-quote
6037 (make-string
6038 (1+ (- (match-end 0) (match-beginning 0)))
6039 ?*))
6040 " "))
6041 (move-marker begm (point))
6042 (move-marker endm (org-end-of-subtree t)))
6043 (setq re1 "^* ")
6044 (move-marker begm (point-min))
6045 (move-marker endm (point-max)))
6046 (save-excursion
6047 (goto-char begm)
6048 (while (re-search-forward re1 endm t)
6049 (setq beg (match-beginning 0)
6050 end (save-excursion (org-end-of-subtree t) (point)))
6051 (goto-char beg)
6052 (if (re-search-forward re end t)
6053 (goto-char end)
6054 (goto-char beg)
6055 (if (and (or (not tag) (not (looking-at rea)))
6056 (y-or-n-p question))
6057 (progn
6058 (if tag
6059 (org-toggle-tag org-archive-tag 'on)
6060 (org-archive-subtree))
6061 (setq cntarch (1+ cntarch)))
6062 (goto-char end)))))
6063 (message "%d trees archived" cntarch)))
6065 (defun org-cycle-hide-archived-subtrees (state)
6066 "Re-hide all archived subtrees after a visibility state change."
6067 (when (and (not org-cycle-open-archived-trees)
6068 (not (memq state '(overview folded))))
6069 (save-excursion
6070 (let* ((globalp (memq state '(contents all)))
6071 (beg (if globalp (point-min) (point)))
6072 (end (if globalp (point-max) (org-end-of-subtree t))))
6073 (org-hide-archived-subtrees beg end)
6074 (goto-char beg)
6075 (if (looking-at (concat ".*:" org-archive-tag ":"))
6076 (message (substitute-command-keys
6077 "Subtree is archived and stays closed. Use \\[org-force-cycle-archived] to cycle it anyway.")))))))
6079 (defun org-force-cycle-archived ()
6080 "Cycle subtree even if it is archived."
6081 (interactive)
6082 (setq this-command 'org-cycle)
6083 (let ((org-cycle-open-archived-trees t))
6084 (call-interactively 'org-cycle)))
6086 (defun org-hide-archived-subtrees (beg end)
6087 "Re-hide all archived subtrees after a visibility state change."
6088 (save-excursion
6089 (let* ((re (concat ":" org-archive-tag ":")))
6090 (goto-char beg)
6091 (while (re-search-forward re end t)
6092 (and (org-on-heading-p) (hide-subtree))
6093 (org-end-of-subtree t)))))
6095 (defun org-toggle-tag (tag &optional onoff)
6096 "Toggle the tag TAG for the current line.
6097 If ONOFF is `on' or `off', don't toggle but set to this state."
6098 (unless (org-on-heading-p t) (error "Not on headling"))
6099 (let (res current)
6100 (save-excursion
6101 (beginning-of-line)
6102 (if (re-search-forward "[ \t]:\\([a-zA-Z0-9_@:]+\\):[ \t]*$"
6103 (point-at-eol) t)
6104 (progn
6105 (setq current (match-string 1))
6106 (replace-match ""))
6107 (setq current ""))
6108 (setq current (nreverse (org-split-string current ":")))
6109 (cond
6110 ((eq onoff 'on)
6111 (setq res t)
6112 (or (member tag current) (push tag current)))
6113 ((eq onoff 'off)
6114 (or (not (member tag current)) (setq current (delete tag current))))
6115 (t (if (member tag current)
6116 (setq current (delete tag current))
6117 (setq res t)
6118 (push tag current))))
6119 (end-of-line 1)
6120 (when current
6121 (insert " :" (mapconcat 'identity (nreverse current) ":") ":"))
6122 (org-set-tags nil t))
6123 res))
6125 (defun org-toggle-archive-tag (&optional arg)
6126 "Toggle the archive tag for the current headline.
6127 With prefix ARG, check all children of current headline and offer tagging
6128 the children that do not contain any open TODO items."
6129 (interactive "P")
6130 (if arg
6131 (org-archive-all-done 'tag)
6132 (let (set)
6133 (save-excursion
6134 (org-back-to-heading t)
6135 (setq set (org-toggle-tag org-archive-tag))
6136 (when set (hide-subtree)))
6137 (and set (beginning-of-line 1))
6138 (message "Subtree %s" (if set "archived" "unarchived")))))
6141 ;;;; Tables
6143 ;;; The table editor
6145 ;; Watch out: Here we are talking about two different kind of tables.
6146 ;; Most of the code is for the tables created with the Org-mode table editor.
6147 ;; Sometimes, we talk about tables created and edited with the table.el
6148 ;; Emacs package. We call the former org-type tables, and the latter
6149 ;; table.el-type tables.
6151 (defun org-before-change-function (beg end)
6152 "Every change indicates that a table might need an update."
6153 (setq org-table-may-need-update t))
6155 (defconst org-table-line-regexp "^[ \t]*|"
6156 "Detects an org-type table line.")
6157 (defconst org-table-dataline-regexp "^[ \t]*|[^-]"
6158 "Detects an org-type table line.")
6159 (defconst org-table-auto-recalculate-regexp "^[ \t]*| *# *\\(|\\|$\\)"
6160 "Detects a table line marked for automatic recalculation.")
6161 (defconst org-table-recalculate-regexp "^[ \t]*| *[#*] *\\(|\\|$\\)"
6162 "Detects a table line marked for automatic recalculation.")
6163 (defconst org-table-calculate-mark-regexp "^[ \t]*| *[!$^_#*] *\\(|\\|$\\)"
6164 "Detects a table line marked for automatic recalculation.")
6165 (defconst org-table-hline-regexp "^[ \t]*|-"
6166 "Detects an org-type table hline.")
6167 (defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]"
6168 "Detects a table-type table hline.")
6169 (defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)"
6170 "Detects an org-type or table-type table.")
6171 (defconst org-table-border-regexp "^[ \t]*[^| \t]"
6172 "Searching from within a table (any type) this finds the first line
6173 outside the table.")
6174 (defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]"
6175 "Searching from within a table (any type) this finds the first line
6176 outside the table.")
6178 (defvar org-table-last-highlighted-reference nil)
6179 (defvar org-table-formula-history nil)
6181 (defvar org-table-column-names nil
6182 "Alist with column names, derived from the `!' line.")
6183 (defvar org-table-column-name-regexp nil
6184 "Regular expression matching the current column names.")
6185 (defvar org-table-local-parameters nil
6186 "Alist with parameter names, derived from the `$' line.")
6187 (defvar org-table-named-field-locations nil
6188 "Alist with locations of named fields.")
6190 (defvar org-table-current-line-types nil
6191 "Table row types, non-nil only for the duration of a comand.")
6192 (defvar org-table-current-begin-line nil
6193 "Table begin line, non-nil only for the duration of a comand.")
6194 (defvar org-table-current-begin-pos nil
6195 "Table begin position, non-nil only for the duration of a comand.")
6196 (defvar org-table-dlines nil
6197 "Vector of data line line numbers in the current table.")
6198 (defvar org-table-hlines nil
6199 "Vector of hline line numbers in the current table.")
6201 (defconst org-table-range-regexp
6202 "@\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\(\\.\\.@?\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\)?"
6203 ;; 1 2 3 4 5
6204 "Regular expression for matching ranges in formulas.")
6206 (defconst org-table-range-regexp2
6207 (concat
6208 "\\(" "@[-0-9I$&]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\|" "\\$[a-zA-Z0-9]+" "\\)"
6209 "\\.\\."
6210 "\\(" "@?[-0-9I$&]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\|" "\\$[a-zA-Z0-9]+" "\\)")
6211 "Match a range for reference display.")
6213 (defconst org-table-translate-regexp
6214 (concat "\\(" "@[-0-9I$]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\)")
6215 "Match a reference that needs translation, for reference display.")
6217 (defvar org-inhibit-highlight-removal nil) ; dynamically scoped param
6219 (defun org-table-create-with-table.el ()
6220 "Use the table.el package to insert a new table.
6221 If there is already a table at point, convert between Org-mode tables
6222 and table.el tables."
6223 (interactive)
6224 (require 'table)
6225 (cond
6226 ((org-at-table.el-p)
6227 (if (y-or-n-p "Convert table to Org-mode table? ")
6228 (org-table-convert)))
6229 ((org-at-table-p)
6230 (if (y-or-n-p "Convert table to table.el table? ")
6231 (org-table-convert)))
6232 (t (call-interactively 'table-insert))))
6234 (defun org-table-create-or-convert-from-region (arg)
6235 "Convert region to table, or create an empty table.
6236 If there is an active region, convert it to a table, using the function
6237 `org-table-convert-region'.
6238 If there is no such region, create an empty table with `org-table-create'."
6239 (interactive "P")
6240 (if (org-region-active-p)
6241 (org-table-convert-region (region-beginning) (region-end) arg)
6242 (org-table-create arg)))
6244 (defun org-table-create (&optional size)
6245 "Query for a size and insert a table skeleton.
6246 SIZE is a string Columns x Rows like for example \"3x2\"."
6247 (interactive "P")
6248 (unless size
6249 (setq size (read-string
6250 (concat "Table size Columns x Rows [e.g. "
6251 org-table-default-size "]: ")
6252 "" nil org-table-default-size)))
6254 (let* ((pos (point))
6255 (indent (make-string (current-column) ?\ ))
6256 (split (org-split-string size " *x *"))
6257 (rows (string-to-number (nth 1 split)))
6258 (columns (string-to-number (car split)))
6259 (line (concat (apply 'concat indent "|" (make-list columns " |"))
6260 "\n")))
6261 (if (string-match "^[ \t]*$" (buffer-substring-no-properties
6262 (point-at-bol) (point)))
6263 (beginning-of-line 1)
6264 (newline))
6265 ;; (mapcar (lambda (x) (insert line)) (make-list rows t))
6266 (dotimes (i rows) (insert line))
6267 (goto-char pos)
6268 (if (> rows 1)
6269 ;; Insert a hline after the first row.
6270 (progn
6271 (end-of-line 1)
6272 (insert "\n|-")
6273 (goto-char pos)))
6274 (org-table-align)))
6276 (defun org-table-convert-region (beg0 end0 &optional nspace)
6277 "Convert region to a table.
6278 The region goes from BEG0 to END0, but these borders will be moved
6279 slightly, to make sure a beginning of line in the first line is included.
6280 When NSPACE is non-nil, it indicates the minimum number of spaces that
6281 separate columns. By default, the function first checks if every line
6282 contains at lease one TAB. If yes, it assumes that the material is TAB
6283 separated. If not, it assumes a single space as separator."
6284 ;; FIXME: Allow CSV?????
6285 (interactive "rP")
6286 (let* ((beg (min beg0 end0))
6287 (end (max beg0 end0))
6288 (tabsep t)
6290 (goto-char beg)
6291 (beginning-of-line 1)
6292 (setq beg (move-marker (make-marker) (point)))
6293 (goto-char end)
6294 (if (bolp) (backward-char 1) (end-of-line 1))
6295 (setq end (move-marker (make-marker) (point)))
6296 ;; Lets see if this is tab-separated material. If every nonempty line
6297 ;; contains a tab, we will assume that it is tab-separated material
6298 (if nspace
6299 (setq tabsep nil)
6300 (goto-char beg)
6301 (and (re-search-forward "^[^\n\t]+$" end t) (setq tabsep nil)))
6302 (if nspace (setq tabsep nil))
6303 (if tabsep
6304 (setq re "^\\|\t")
6305 (setq re (format "^ *\\| *\t *\\| \\{%d,\\}"
6306 (max 1 (prefix-numeric-value nspace)))))
6307 (goto-char beg)
6308 (while (re-search-forward re end t)
6309 (replace-match "| " t t))
6310 (goto-char beg)
6311 (insert " ")
6312 (org-table-align)))
6314 (defun org-table-import (file arg)
6315 "Import FILE as a table.
6316 The file is assumed to be tab-separated. Such files can be produced by most
6317 spreadsheet and database applications. If no tabs (at least one per line)
6318 are found, lines will be split on whitespace into fields."
6319 (interactive "f\nP")
6320 (or (bolp) (newline))
6321 (let ((beg (point))
6322 (pm (point-max)))
6323 (insert-file-contents file)
6324 (org-table-convert-region beg (+ (point) (- (point-max) pm)) arg)))
6326 (defun org-table-export ()
6327 "Export table as a tab-separated file.
6328 Such a file can be imported into a spreadsheet program like Excel."
6329 (interactive)
6330 (let* ((beg (org-table-begin))
6331 (end (org-table-end))
6332 (table (buffer-substring beg end))
6333 (file (read-file-name "Export table to: "))
6334 buf)
6335 (unless (or (not (file-exists-p file))
6336 (y-or-n-p (format "Overwrite file %s? " file)))
6337 (error "Abort"))
6338 (with-current-buffer (find-file-noselect file)
6339 (setq buf (current-buffer))
6340 (erase-buffer)
6341 (fundamental-mode)
6342 (insert table)
6343 (goto-char (point-min))
6344 (while (re-search-forward "^[ \t]*|[ \t]*" nil t)
6345 (replace-match "" t t)
6346 (end-of-line 1))
6347 (goto-char (point-min))
6348 (while (re-search-forward "[ \t]*|[ \t]*$" nil t)
6349 (replace-match "" t t)
6350 (goto-char (min (1+ (point)) (point-max))))
6351 (goto-char (point-min))
6352 (while (re-search-forward "^-[-+]*$" nil t)
6353 (replace-match "")
6354 (if (looking-at "\n")
6355 (delete-char 1)))
6356 (goto-char (point-min))
6357 (while (re-search-forward "[ \t]*|[ \t]*" nil t)
6358 (replace-match "\t" t t))
6359 (save-buffer))
6360 (kill-buffer buf)))
6362 (defvar org-table-aligned-begin-marker (make-marker)
6363 "Marker at the beginning of the table last aligned.
6364 Used to check if cursor still is in that table, to minimize realignment.")
6365 (defvar org-table-aligned-end-marker (make-marker)
6366 "Marker at the end of the table last aligned.
6367 Used to check if cursor still is in that table, to minimize realignment.")
6368 (defvar org-table-last-alignment nil
6369 "List of flags for flushright alignment, from the last re-alignment.
6370 This is being used to correctly align a single field after TAB or RET.")
6371 (defvar org-table-last-column-widths nil
6372 "List of max width of fields in each column.
6373 This is being used to correctly align a single field after TAB or RET.")
6374 (defvar org-table-overlay-coordinates nil
6375 "Overlay coordinates after each align of a table.")
6376 (make-variable-buffer-local 'org-table-overlay-coordinates)
6378 (defvar org-last-recalc-line nil)
6379 (defconst org-narrow-column-arrow "=>"
6380 "Used as display property in narrowed table columns.")
6382 (defun org-table-align ()
6383 "Align the table at point by aligning all vertical bars."
6384 (interactive)
6385 (let* (
6386 ;; Limits of table
6387 (beg (org-table-begin))
6388 (end (org-table-end))
6389 ;; Current cursor position
6390 (linepos (org-current-line))
6391 (colpos (org-table-current-column))
6392 (winstart (window-start))
6393 (winstartline (org-current-line (min winstart (1- (point-max)))))
6394 lines (new "") lengths l typenums ty fields maxfields i
6395 column
6396 (indent "") cnt frac
6397 rfmt hfmt
6398 (spaces '(1 . 1))
6399 (sp1 (car spaces))
6400 (sp2 (cdr spaces))
6401 (rfmt1 (concat
6402 (make-string sp2 ?\ ) "%%%s%ds" (make-string sp1 ?\ ) "|"))
6403 (hfmt1 (concat
6404 (make-string sp2 ?-) "%s" (make-string sp1 ?-) "+"))
6405 emptystrings links dates narrow fmax f1 len c e)
6406 (untabify beg end)
6407 (remove-text-properties beg end '(org-cwidth t org-dwidth t display t))
6408 ;; Check if we have links or dates
6409 (goto-char beg)
6410 (setq links (re-search-forward org-bracket-link-regexp end t))
6411 (goto-char beg)
6412 (setq dates (and org-display-custom-times
6413 (re-search-forward org-ts-regexp-both end t)))
6414 ;; Make sure the link properties are right
6415 (when links (goto-char beg) (while (org-activate-bracket-links end)))
6416 ;; Make sure the date properties are right
6417 (when dates (goto-char beg) (while (org-activate-dates end)))
6419 ;; Check if we are narrowing any columns
6420 (goto-char beg)
6421 (setq narrow (and org-format-transports-properties-p
6422 (re-search-forward "<[0-9]+>" end t)))
6423 ;; Get the rows
6424 (setq lines (org-split-string
6425 (buffer-substring beg end) "\n"))
6426 ;; Store the indentation of the first line
6427 (if (string-match "^ *" (car lines))
6428 (setq indent (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
6429 ;; Mark the hlines by setting the corresponding element to nil
6430 ;; At the same time, we remove trailing space.
6431 (setq lines (mapcar (lambda (l)
6432 (if (string-match "^ *|-" l)
6434 (if (string-match "[ \t]+$" l)
6435 (substring l 0 (match-beginning 0))
6436 l)))
6437 lines))
6438 ;; Get the data fields by splitting the lines.
6439 (setq fields (mapcar
6440 (lambda (l)
6441 (org-split-string l " *| *"))
6442 (delq nil (copy-sequence lines))))
6443 ;; How many fields in the longest line?
6444 (condition-case nil
6445 (setq maxfields (apply 'max (mapcar 'length fields)))
6446 (error
6447 (kill-region beg end)
6448 (org-table-create org-table-default-size)
6449 (error "Empty table - created default table")))
6450 ;; A list of empty strings to fill any short rows on output
6451 (setq emptystrings (make-list maxfields ""))
6452 ;; Check for special formatting.
6453 (setq i -1)
6454 (while (< (setq i (1+ i)) maxfields) ;; Loop over all columns
6455 (setq column (mapcar (lambda (x) (or (nth i x) "")) fields))
6456 ;; Check if there is an explicit width specified
6457 (when narrow
6458 (setq c column fmax nil)
6459 (while c
6460 (setq e (pop c))
6461 (if (and (stringp e) (string-match "^<\\([0-9]+\\)>$" e))
6462 (setq fmax (string-to-number (match-string 1 e)) c nil)))
6463 ;; Find fields that are wider than fmax, and shorten them
6464 (when fmax
6465 (loop for xx in column do
6466 (when (and (stringp xx)
6467 (> (org-string-width xx) fmax))
6468 (org-add-props xx nil
6469 'help-echo
6470 (concat "Clipped table field, use C-c ` to edit. Full value is:\n" (org-no-properties (copy-sequence xx))))
6471 (setq f1 (min fmax (or (string-match org-bracket-link-regexp xx) fmax)))
6472 (unless (> f1 1)
6473 (error "Cannot narrow field starting with wide link \"%s\""
6474 (match-string 0 xx)))
6475 (add-text-properties f1 (length xx) (list 'org-cwidth t) xx)
6476 (add-text-properties (- f1 2) f1
6477 (list 'display org-narrow-column-arrow)
6478 xx)))))
6479 ;; Get the maximum width for each column
6480 (push (apply 'max 1 (mapcar 'org-string-width column)) lengths)
6481 ;; Get the fraction of numbers, to decide about alignment of the column
6482 (setq cnt 0 frac 0.0)
6483 (loop for x in column do
6484 (if (equal x "")
6486 (setq frac ( / (+ (* frac cnt)
6487 (if (string-match org-table-number-regexp x) 1 0))
6488 (setq cnt (1+ cnt))))))
6489 (push (>= frac org-table-number-fraction) typenums))
6490 (setq lengths (nreverse lengths) typenums (nreverse typenums))
6492 ;; Store the alignment of this table, for later editing of single fields
6493 (setq org-table-last-alignment typenums
6494 org-table-last-column-widths lengths)
6496 ;; With invisible characters, `format' does not get the field width right
6497 ;; So we need to make these fields wide by hand.
6498 (when links
6499 (loop for i from 0 upto (1- maxfields) do
6500 (setq len (nth i lengths))
6501 (loop for j from 0 upto (1- (length fields)) do
6502 (setq c (nthcdr i (car (nthcdr j fields))))
6503 (if (and (stringp (car c))
6504 (string-match org-bracket-link-regexp (car c))
6505 (< (org-string-width (car c)) len))
6506 (setcar c (concat (car c) (make-string (- len (org-string-width (car c))) ?\ )))))))
6508 ;; Compute the formats needed for output of the table
6509 (setq rfmt (concat indent "|") hfmt (concat indent "|"))
6510 (while (setq l (pop lengths))
6511 (setq ty (if (pop typenums) "" "-")) ; number types flushright
6512 (setq rfmt (concat rfmt (format rfmt1 ty l))
6513 hfmt (concat hfmt (format hfmt1 (make-string l ?-)))))
6514 (setq rfmt (concat rfmt "\n")
6515 hfmt (concat (substring hfmt 0 -1) "|\n"))
6517 (setq new (mapconcat
6518 (lambda (l)
6519 (if l (apply 'format rfmt
6520 (append (pop fields) emptystrings))
6521 hfmt))
6522 lines ""))
6523 ;; Replace the old one
6524 (delete-region beg end)
6525 (move-marker end nil)
6526 (move-marker org-table-aligned-begin-marker (point))
6527 (insert new)
6528 (move-marker org-table-aligned-end-marker (point))
6529 (when (and orgtbl-mode (not (org-mode-p)))
6530 (goto-char org-table-aligned-begin-marker)
6531 (while (org-hide-wide-columns org-table-aligned-end-marker)))
6532 ;; Try to move to the old location
6533 (goto-line winstartline)
6534 (setq winstart (point-at-bol))
6535 (goto-line linepos)
6536 (set-window-start (selected-window) winstart 'noforce)
6537 (org-table-goto-column colpos)
6538 (and org-table-overlay-coordinates (org-table-overlay-coordinates))
6539 (setq org-table-may-need-update nil)
6542 (defun org-string-width (s)
6543 "Compute width of string, ignoring invisible characters.
6544 This ignores character with invisibility property `org-link', and also
6545 characters with property `org-cwidth', because these will become invisible
6546 upon the next fontification round."
6547 (let (b l)
6548 (when (or (eq t buffer-invisibility-spec)
6549 (assq 'org-link buffer-invisibility-spec))
6550 (while (setq b (text-property-any 0 (length s)
6551 'invisible 'org-link s))
6552 (setq s (concat (substring s 0 b)
6553 (substring s (or (next-single-property-change
6554 b 'invisible s) (length s)))))))
6555 (while (setq b (text-property-any 0 (length s) 'org-cwidth t s))
6556 (setq s (concat (substring s 0 b)
6557 (substring s (or (next-single-property-change
6558 b 'org-cwidth s) (length s))))))
6559 (setq l (string-width s) b -1)
6560 (while (setq b (text-property-any (1+ b) (length s) 'org-dwidth t s))
6561 (setq l (- l (get-text-property b 'org-dwidth-n s))))
6564 (defun org-table-begin (&optional table-type)
6565 "Find the beginning of the table and return its position.
6566 With argument TABLE-TYPE, go to the beginning of a table.el-type table."
6567 (save-excursion
6568 (if (not (re-search-backward
6569 (if table-type org-table-any-border-regexp
6570 org-table-border-regexp)
6571 nil t))
6572 (progn (goto-char (point-min)) (point))
6573 (goto-char (match-beginning 0))
6574 (beginning-of-line 2)
6575 (point))))
6577 (defun org-table-end (&optional table-type)
6578 "Find the end of the table and return its position.
6579 With argument TABLE-TYPE, go to the end of a table.el-type table."
6580 (save-excursion
6581 (if (not (re-search-forward
6582 (if table-type org-table-any-border-regexp
6583 org-table-border-regexp)
6584 nil t))
6585 (goto-char (point-max))
6586 (goto-char (match-beginning 0)))
6587 (point-marker)))
6589 (defun org-table-justify-field-maybe (&optional new)
6590 "Justify the current field, text to left, number to right.
6591 Optional argument NEW may specify text to replace the current field content."
6592 (cond
6593 ((and (not new) org-table-may-need-update)) ; Realignment will happen anyway
6594 ((org-at-table-hline-p))
6595 ((and (not new)
6596 (or (not (equal (marker-buffer org-table-aligned-begin-marker)
6597 (current-buffer)))
6598 (< (point) org-table-aligned-begin-marker)
6599 (>= (point) org-table-aligned-end-marker)))
6600 ;; This is not the same table, force a full re-align
6601 (setq org-table-may-need-update t))
6602 (t ;; realign the current field, based on previous full realign
6603 (let* ((pos (point)) s
6604 (col (org-table-current-column))
6605 (num (if (> col 0) (nth (1- col) org-table-last-alignment)))
6606 l f n o e)
6607 (when (> col 0)
6608 (skip-chars-backward "^|\n")
6609 (if (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)")
6610 (progn
6611 (setq s (match-string 1)
6612 o (match-string 0)
6613 l (max 1 (- (match-end 0) (match-beginning 0) 3))
6614 e (not (= (match-beginning 2) (match-end 2))))
6615 (setq f (format (if num " %%%ds %s" " %%-%ds %s")
6616 l (if e "|" (setq org-table-may-need-update t) ""))
6617 n (format f s))
6618 (if new
6619 (if (<= (length new) l) ;; FIXME: length -> str-width?
6620 (setq n (format f new))
6621 (setq n (concat new "|") org-table-may-need-update t)))
6622 (or (equal n o)
6623 (let (org-table-may-need-update)
6624 (replace-match n))))
6625 (setq org-table-may-need-update t))
6626 (goto-char pos))))))
6628 (defun org-table-next-field ()
6629 "Go to the next field in the current table, creating new lines as needed.
6630 Before doing so, re-align the table if necessary."
6631 (interactive)
6632 (org-table-maybe-eval-formula)
6633 (org-table-maybe-recalculate-line)
6634 (if (and org-table-automatic-realign
6635 org-table-may-need-update)
6636 (org-table-align))
6637 (let ((end (org-table-end)))
6638 (if (org-at-table-hline-p)
6639 (end-of-line 1))
6640 (condition-case nil
6641 (progn
6642 (re-search-forward "|" end)
6643 (if (looking-at "[ \t]*$")
6644 (re-search-forward "|" end))
6645 (if (and (looking-at "-")
6646 org-table-tab-jumps-over-hlines
6647 (re-search-forward "^[ \t]*|\\([^-]\\)" end t))
6648 (goto-char (match-beginning 1)))
6649 (if (looking-at "-")
6650 (progn
6651 (beginning-of-line 0)
6652 (org-table-insert-row 'below))
6653 (if (looking-at " ") (forward-char 1))))
6654 (error
6655 (org-table-insert-row 'below)))))
6657 (defun org-table-previous-field ()
6658 "Go to the previous field in the table.
6659 Before doing so, re-align the table if necessary."
6660 (interactive)
6661 (org-table-justify-field-maybe)
6662 (org-table-maybe-recalculate-line)
6663 (if (and org-table-automatic-realign
6664 org-table-may-need-update)
6665 (org-table-align))
6666 (if (org-at-table-hline-p)
6667 (end-of-line 1))
6668 (re-search-backward "|" (org-table-begin))
6669 (re-search-backward "|" (org-table-begin))
6670 (while (looking-at "|\\(-\\|[ \t]*$\\)")
6671 (re-search-backward "|" (org-table-begin)))
6672 (if (looking-at "| ?")
6673 (goto-char (match-end 0))))
6675 (defun org-table-next-row ()
6676 "Go to the next row (same column) in the current table.
6677 Before doing so, re-align the table if necessary."
6678 (interactive)
6679 (org-table-maybe-eval-formula)
6680 (org-table-maybe-recalculate-line)
6681 (if (or (looking-at "[ \t]*$")
6682 (save-excursion (skip-chars-backward " \t") (bolp)))
6683 (newline)
6684 (if (and org-table-automatic-realign
6685 org-table-may-need-update)
6686 (org-table-align))
6687 (let ((col (org-table-current-column)))
6688 (beginning-of-line 2)
6689 (if (or (not (org-at-table-p))
6690 (org-at-table-hline-p))
6691 (progn
6692 (beginning-of-line 0)
6693 (org-table-insert-row 'below)))
6694 (org-table-goto-column col)
6695 (skip-chars-backward "^|\n\r")
6696 (if (looking-at " ") (forward-char 1)))))
6698 (defun org-table-copy-down (n)
6699 "Copy a field down in the current column.
6700 If the field at the cursor is empty, copy into it the content of the nearest
6701 non-empty field above. With argument N, use the Nth non-empty field.
6702 If the current field is not empty, it is copied down to the next row, and
6703 the cursor is moved with it. Therefore, repeating this command causes the
6704 column to be filled row-by-row.
6705 If the variable `org-table-copy-increment' is non-nil and the field is an
6706 integer or a timestamp, it will be incremented while copying. In the case of
6707 a timestamp, if the cursor is on the year, change the year. If it is on the
6708 month or the day, change that. Point will stay on the current date field
6709 in order to easily repeat the interval."
6710 (interactive "p")
6711 (let* ((colpos (org-table-current-column))
6712 (col (current-column))
6713 (field (org-table-get-field))
6714 (non-empty (string-match "[^ \t]" field))
6715 (beg (org-table-begin))
6716 txt)
6717 (org-table-check-inside-data-field)
6718 (if non-empty
6719 (progn
6720 (setq txt (org-trim field))
6721 (org-table-next-row)
6722 (org-table-blank-field))
6723 (save-excursion
6724 (setq txt
6725 (catch 'exit
6726 (while (progn (beginning-of-line 1)
6727 (re-search-backward org-table-dataline-regexp
6728 beg t))
6729 (org-table-goto-column colpos t)
6730 (if (and (looking-at
6731 "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|")
6732 (= (setq n (1- n)) 0))
6733 (throw 'exit (match-string 1))))))))
6734 (if txt
6735 (progn
6736 (if (and org-table-copy-increment
6737 (string-match "^[0-9]+$" txt))
6738 (setq txt (format "%d" (+ (string-to-number txt) 1))))
6739 (insert txt)
6740 (move-to-column col)
6741 (if (and org-table-copy-increment (org-at-timestamp-p t))
6742 (org-timestamp-up 1)
6743 (org-table-maybe-recalculate-line))
6744 (org-table-align)
6745 (move-to-column col))
6746 (error "No non-empty field found"))))
6748 (defun org-table-check-inside-data-field ()
6749 "Is point inside a table data field?
6750 I.e. not on a hline or before the first or after the last column?
6751 This actually throws an error, so it aborts the current command."
6752 (if (or (not (org-at-table-p))
6753 (= (org-table-current-column) 0)
6754 (org-at-table-hline-p)
6755 (looking-at "[ \t]*$"))
6756 (error "Not in table data field")))
6758 (defvar org-table-clip nil
6759 "Clipboard for table regions.")
6761 (defun org-table-blank-field ()
6762 "Blank the current table field or active region."
6763 (interactive)
6764 (org-table-check-inside-data-field)
6765 (if (and (interactive-p) (org-region-active-p))
6766 (let (org-table-clip)
6767 (org-table-cut-region (region-beginning) (region-end)))
6768 (skip-chars-backward "^|")
6769 (backward-char 1)
6770 (if (looking-at "|[^|\n]+")
6771 (let* ((pos (match-beginning 0))
6772 (match (match-string 0))
6773 (len (org-string-width match)))
6774 (replace-match (concat "|" (make-string (1- len) ?\ )))
6775 (goto-char (+ 2 pos))
6776 (substring match 1)))))
6778 (defun org-table-get-field (&optional n replace)
6779 "Return the value of the field in column N of current row.
6780 N defaults to current field.
6781 If REPLACE is a string, replace field with this value. The return value
6782 is always the old value."
6783 (and n (org-table-goto-column n))
6784 (skip-chars-backward "^|\n")
6785 (backward-char 1)
6786 (if (looking-at "|[^|\r\n]*")
6787 (let* ((pos (match-beginning 0))
6788 (val (buffer-substring (1+ pos) (match-end 0))))
6789 (if replace
6790 (replace-match (concat "|" replace) t t))
6791 (goto-char (min (point-at-eol) (+ 2 pos)))
6792 val)
6793 (forward-char 1) ""))
6796 (defun org-table-field-info (arg)
6797 "Show info about the current field, and highlight any reference at point."
6798 (interactive "P")
6799 (org-table-get-specials)
6800 (save-excursion
6801 (let* ((pos (point))
6802 (col (org-table-current-column))
6803 (cname (car (rassoc (int-to-string col) org-table-column-names)))
6804 (name (car (rassoc (list (org-current-line) col)
6805 org-table-named-field-locations)))
6806 (eql (org-table-get-stored-formulas))
6807 (dline (org-table-current-dline))
6808 (ref (format "@%d$%d" dline col))
6809 (ref1 (org-table-convert-refs-to-an ref))
6810 (fequation (or (assoc name eql) (assoc ref eql)))
6811 (cequation (assoc (int-to-string col) eql))
6812 (eqn (or fequation cequation)))
6813 (goto-char pos)
6814 (condition-case nil
6815 (org-table-show-reference 'local)
6816 (error nil))
6817 (message "line @%d, col $%s%s, ref @%d$%d or %s%s%s"
6818 dline col
6819 (if cname (concat " or $" cname) "")
6820 dline col ref1
6821 (if name (concat " or $" name) "")
6822 ;; FIXME: formula info not correct if special table line
6823 (if eqn
6824 (concat ", formula: "
6825 (org-table-formula-to-user
6826 (concat
6827 (if (string-match "^[$@]"(car eqn)) "" "$")
6828 (car eqn) "=" (cdr eqn))))
6829 "")))))
6831 (defun org-table-current-column ()
6832 "Find out which column we are in.
6833 When called interactively, column is also displayed in echo area."
6834 (interactive)
6835 (if (interactive-p) (org-table-check-inside-data-field))
6836 (save-excursion
6837 (let ((cnt 0) (pos (point)))
6838 (beginning-of-line 1)
6839 (while (search-forward "|" pos t)
6840 (setq cnt (1+ cnt)))
6841 (if (interactive-p) (message "This is table column %d" cnt))
6842 cnt)))
6844 (defun org-table-current-dline ()
6845 "Find out what table data line we are in.
6846 Only datalins count for this."
6847 (interactive)
6848 (if (interactive-p) (org-table-check-inside-data-field))
6849 (save-excursion
6850 (let ((cnt 0) (pos (point)))
6851 (goto-char (org-table-begin))
6852 (while (<= (point) pos)
6853 (if (looking-at org-table-dataline-regexp) (setq cnt (1+ cnt)))
6854 (beginning-of-line 2))
6855 (if (interactive-p) (message "This is table line %d" cnt))
6856 cnt)))
6858 (defun org-table-goto-column (n &optional on-delim force)
6859 "Move the cursor to the Nth column in the current table line.
6860 With optional argument ON-DELIM, stop with point before the left delimiter
6861 of the field.
6862 If there are less than N fields, just go to after the last delimiter.
6863 However, when FORCE is non-nil, create new columns if necessary."
6864 (interactive "p")
6865 (let ((pos (point-at-eol)))
6866 (beginning-of-line 1)
6867 (when (> n 0)
6868 (while (and (> (setq n (1- n)) -1)
6869 (or (search-forward "|" pos t)
6870 (and force
6871 (progn (end-of-line 1)
6872 (skip-chars-backward "^|")
6873 (insert " | "))))))
6874 ; (backward-char 2) t)))))
6875 (when (and force (not (looking-at ".*|")))
6876 (save-excursion (end-of-line 1) (insert " | ")))
6877 (if on-delim
6878 (backward-char 1)
6879 (if (looking-at " ") (forward-char 1))))))
6881 (defun org-at-table-p (&optional table-type)
6882 "Return t if the cursor is inside an org-type table.
6883 If TABLE-TYPE is non-nil, also check for table.el-type tables."
6884 (if org-enable-table-editor
6885 (save-excursion
6886 (beginning-of-line 1)
6887 (looking-at (if table-type org-table-any-line-regexp
6888 org-table-line-regexp)))
6889 nil))
6891 (defun org-at-table.el-p ()
6892 "Return t if and only if we are at a table.el table."
6893 (and (org-at-table-p 'any)
6894 (save-excursion
6895 (goto-char (org-table-begin 'any))
6896 (looking-at org-table1-hline-regexp))))
6898 (defun org-table-recognize-table.el ()
6899 "If there is a table.el table nearby, recognize it and move into it."
6900 (if org-table-tab-recognizes-table.el
6901 (if (org-at-table.el-p)
6902 (progn
6903 (beginning-of-line 1)
6904 (if (looking-at org-table-dataline-regexp)
6906 (if (looking-at org-table1-hline-regexp)
6907 (progn
6908 (beginning-of-line 2)
6909 (if (looking-at org-table-any-border-regexp)
6910 (beginning-of-line -1)))))
6911 (if (re-search-forward "|" (org-table-end t) t)
6912 (progn
6913 (require 'table)
6914 (if (table--at-cell-p (point))
6916 (message "recognizing table.el table...")
6917 (table-recognize-table)
6918 (message "recognizing table.el table...done")))
6919 (error "This should not happen..."))
6921 nil)
6922 nil))
6924 (defun org-at-table-hline-p ()
6925 "Return t if the cursor is inside a hline in a table."
6926 (if org-enable-table-editor
6927 (save-excursion
6928 (beginning-of-line 1)
6929 (looking-at org-table-hline-regexp))
6930 nil))
6932 (defun org-table-insert-column ()
6933 "Insert a new column into the table."
6934 (interactive)
6935 (if (not (org-at-table-p))
6936 (error "Not at a table"))
6937 (org-table-find-dataline)
6938 (let* ((col (max 1 (org-table-current-column)))
6939 (beg (org-table-begin))
6940 (end (org-table-end))
6941 ;; Current cursor position
6942 (linepos (org-current-line))
6943 (colpos col))
6944 (goto-char beg)
6945 (while (< (point) end)
6946 (if (org-at-table-hline-p)
6948 (org-table-goto-column col t)
6949 (insert "| "))
6950 (beginning-of-line 2))
6951 (move-marker end nil)
6952 (goto-line linepos)
6953 (org-table-goto-column colpos)
6954 (org-table-align)
6955 (org-table-fix-formulas "$" nil (1- col) 1)))
6957 (defun org-table-find-dataline ()
6958 "Find a dataline in the current table, which is needed for column commands."
6959 (if (and (org-at-table-p)
6960 (not (org-at-table-hline-p)))
6962 (let ((col (current-column))
6963 (end (org-table-end)))
6964 (move-to-column col)
6965 (while (and (< (point) end)
6966 (or (not (= (current-column) col))
6967 (org-at-table-hline-p)))
6968 (beginning-of-line 2)
6969 (move-to-column col))
6970 (if (and (org-at-table-p)
6971 (not (org-at-table-hline-p)))
6973 (error
6974 "Please position cursor in a data line for column operations")))))
6976 (defun org-table-delete-column ()
6977 "Delete a column from the table."
6978 (interactive)
6979 (if (not (org-at-table-p))
6980 (error "Not at a table"))
6981 (org-table-find-dataline)
6982 (org-table-check-inside-data-field)
6983 (let* ((col (org-table-current-column))
6984 (beg (org-table-begin))
6985 (end (org-table-end))
6986 ;; Current cursor position
6987 (linepos (org-current-line))
6988 (colpos col))
6989 (goto-char beg)
6990 (while (< (point) end)
6991 (if (org-at-table-hline-p)
6993 (org-table-goto-column col t)
6994 (and (looking-at "|[^|\n]+|")
6995 (replace-match "|")))
6996 (beginning-of-line 2))
6997 (move-marker end nil)
6998 (goto-line linepos)
6999 (org-table-goto-column colpos)
7000 (org-table-align)
7001 (org-table-fix-formulas "$" (list (cons (number-to-string col) "INVALID"))
7002 col -1 col)))
7004 (defun org-table-move-column-right ()
7005 "Move column to the right."
7006 (interactive)
7007 (org-table-move-column nil))
7008 (defun org-table-move-column-left ()
7009 "Move column to the left."
7010 (interactive)
7011 (org-table-move-column 'left))
7013 (defun org-table-move-column (&optional left)
7014 "Move the current column to the right. With arg LEFT, move to the left."
7015 (interactive "P")
7016 (if (not (org-at-table-p))
7017 (error "Not at a table"))
7018 (org-table-find-dataline)
7019 (org-table-check-inside-data-field)
7020 (let* ((col (org-table-current-column))
7021 (col1 (if left (1- col) col))
7022 (beg (org-table-begin))
7023 (end (org-table-end))
7024 ;; Current cursor position
7025 (linepos (org-current-line))
7026 (colpos (if left (1- col) (1+ col))))
7027 (if (and left (= col 1))
7028 (error "Cannot move column further left"))
7029 (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$"))
7030 (error "Cannot move column further right"))
7031 (goto-char beg)
7032 (while (< (point) end)
7033 (if (org-at-table-hline-p)
7035 (org-table-goto-column col1 t)
7036 (and (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|")
7037 (replace-match "|\\2|\\1|")))
7038 (beginning-of-line 2))
7039 (move-marker end nil)
7040 (goto-line linepos)
7041 (org-table-goto-column colpos)
7042 (org-table-align)
7043 (org-table-fix-formulas
7044 "$" (list (cons (number-to-string col) (number-to-string colpos))
7045 (cons (number-to-string colpos) (number-to-string col))))))
7047 (defun org-table-move-row-down ()
7048 "Move table row down."
7049 (interactive)
7050 (org-table-move-row nil))
7051 (defun org-table-move-row-up ()
7052 "Move table row up."
7053 (interactive)
7054 (org-table-move-row 'up))
7056 (defun org-table-move-row (&optional up)
7057 "Move the current table line down. With arg UP, move it up."
7058 (interactive "P")
7059 (let* ((col (current-column))
7060 (pos (point))
7061 (hline1p (save-excursion (beginning-of-line 1)
7062 (looking-at org-table-hline-regexp)))
7063 (dline1 (org-table-current-dline))
7064 (dline2 (+ dline1 (if up -1 1)))
7065 (tonew (if up 0 2))
7066 txt hline2p)
7067 (beginning-of-line tonew)
7068 (unless (org-at-table-p)
7069 (goto-char pos)
7070 (error "Cannot move row further"))
7071 (setq hline2p (looking-at org-table-hline-regexp))
7072 (goto-char pos)
7073 (beginning-of-line 1)
7074 (setq pos (point))
7075 (setq txt (buffer-substring (point) (1+ (point-at-eol))))
7076 (delete-region (point) (1+ (point-at-eol)))
7077 (beginning-of-line tonew)
7078 (insert txt)
7079 (beginning-of-line 0)
7080 (move-to-column col)
7081 (unless (or hline1p hline2p)
7082 (org-table-fix-formulas
7083 "@" (list (cons (number-to-string dline1) (number-to-string dline2))
7084 (cons (number-to-string dline2) (number-to-string dline1)))))))
7086 (defun org-table-insert-row (&optional arg)
7087 "Insert a new row above the current line into the table.
7088 With prefix ARG, insert below the current line."
7089 (interactive "P")
7090 (if (not (org-at-table-p))
7091 (error "Not at a table"))
7092 (let* ((line (buffer-substring (point-at-bol) (point-at-eol)))
7093 (new (org-table-clean-line line)))
7094 ;; Fix the first field if necessary
7095 (if (string-match "^[ \t]*| *[#$] *|" line)
7096 (setq new (replace-match (match-string 0 line) t t new)))
7097 (beginning-of-line (if arg 2 1))
7098 (let (org-table-may-need-update) (insert-before-markers new "\n"))
7099 (beginning-of-line 0)
7100 (re-search-forward "| ?" (point-at-eol) t)
7101 (and (or org-table-may-need-update org-table-overlay-coordinates)
7102 (org-table-align))
7103 (org-table-fix-formulas "@" nil (1- (org-table-current-dline)) 1)))
7105 (defun org-table-insert-hline (&optional above)
7106 "Insert a horizontal-line below the current line into the table.
7107 With prefix ABOVE, insert above the current line."
7108 (interactive "P")
7109 (if (not (org-at-table-p))
7110 (error "Not at a table"))
7111 (let ((line (org-table-clean-line
7112 (buffer-substring (point-at-bol) (point-at-eol))))
7113 (col (current-column)))
7114 (while (string-match "|\\( +\\)|" line)
7115 (setq line (replace-match
7116 (concat "+" (make-string (- (match-end 1) (match-beginning 1))
7117 ?-) "|") t t line)))
7118 (and (string-match "\\+" line) (setq line (replace-match "|" t t line)))
7119 (beginning-of-line (if above 1 2))
7120 (insert line "\n")
7121 (beginning-of-line (if above 1 -1))
7122 (move-to-column col)
7123 (and org-table-overlay-coordinates (org-table-align))))
7125 (defun org-table-hline-and-move (&optional same-column)
7126 "Insert a hline and move to the row below that line."
7127 (interactive "P")
7128 (let ((col (org-table-current-column)))
7129 (org-table-maybe-eval-formula)
7130 (org-table-maybe-recalculate-line)
7131 (org-table-insert-hline)
7132 (end-of-line 2)
7133 (if (looking-at "\n[ \t]*|-")
7134 (progn (insert "\n|") (org-table-align))
7135 (org-table-next-field))
7136 (if same-column (org-table-goto-column col))))
7138 (defun org-table-clean-line (s)
7139 "Convert a table line S into a string with only \"|\" and space.
7140 In particular, this does handle wide and invisible characters."
7141 (if (string-match "^[ \t]*|-" s)
7142 ;; It's a hline, just map the characters
7143 (setq s (mapconcat (lambda (x) (if (member x '(?| ?+)) "|" " ")) s ""))
7144 (while (string-match "|\\([ \t]*?[^ \t\r\n|][^\r\n|]*\\)|" s)
7145 (setq s (replace-match
7146 (concat "|" (make-string (org-string-width (match-string 1 s))
7147 ?\ ) "|")
7148 t t s)))
7151 (defun org-table-kill-row ()
7152 "Delete the current row or horizontal line from the table."
7153 (interactive)
7154 (if (not (org-at-table-p))
7155 (error "Not at a table"))
7156 (let ((col (current-column))
7157 (dline (org-table-current-dline)))
7158 (kill-region (point-at-bol) (min (1+ (point-at-eol)) (point-max)))
7159 (if (not (org-at-table-p)) (beginning-of-line 0))
7160 (move-to-column col)
7161 (org-table-fix-formulas "@" (list (cons (number-to-string dline) "INVALID"))
7162 dline -1 dline)))
7165 (defun org-table-sort-lines (with-case &optional sorting-type)
7166 "Sort table lines according to the column at point.
7168 The position of point indicates the column to be used for
7169 sorting, and the range of lines is the range between the nearest
7170 horizontal separator lines, or the entire table of no such lines
7171 exist. If point is before the first column, you will be prompted
7172 for the sorting column. If there is an active region, the mark
7173 specifies the first line and the sorting column, while point
7174 should be in the last line to be included into the sorting.
7176 The command then prompts for the sorting type which can be
7177 alphabetically, numerically, or by time (as given in a time stamp
7178 in the field). Sorting in reverse order is also possible.
7180 With prefix argument WITH-CASE, alphabetic sorting will be case-sensitive.
7182 If SORTING-TYPE is specified when this function is called from a Lisp
7183 program, no prompting will take place. SORTING-TYPE must be a character,
7184 any of (?a ?A ?n ?N ?t ?T) where the capital letter indicate that sorting
7185 should be done in reverse order."
7186 (interactive "P")
7187 (let* ((thisline (org-current-line))
7188 (thiscol (org-table-current-column))
7189 beg end bcol ecol tend tbeg column lns pos)
7190 (when (equal thiscol 0)
7191 (if (interactive-p)
7192 (setq thiscol
7193 (string-to-number
7194 (read-string "Use column N for sorting: ")))
7195 (setq thiscol 1))
7196 (org-table-goto-column thiscol))
7197 (org-table-check-inside-data-field)
7198 (if (org-region-active-p)
7199 (progn
7200 (setq beg (region-beginning) end (region-end))
7201 (goto-char beg)
7202 (setq column (org-table-current-column)
7203 beg (point-at-bol))
7204 (goto-char end)
7205 (setq end (point-at-bol 2)))
7206 (setq column (org-table-current-column)
7207 pos (point)
7208 tbeg (org-table-begin)
7209 tend (org-table-end))
7210 (if (re-search-backward org-table-hline-regexp tbeg t)
7211 (setq beg (point-at-bol 2))
7212 (goto-char tbeg)
7213 (setq beg (point-at-bol 1)))
7214 (goto-char pos)
7215 (if (re-search-forward org-table-hline-regexp tend t)
7216 (setq beg (point-at-bol 0))
7217 (goto-char tend)
7218 (setq end (point-at-bol))))
7219 (setq beg (move-marker (make-marker) beg)
7220 end (move-marker (make-marker) end))
7221 (untabify beg end)
7222 (goto-char beg)
7223 (org-table-goto-column column)
7224 (skip-chars-backward "^|")
7225 (setq bcol (current-column))
7226 (org-table-goto-column (1+ column))
7227 (skip-chars-backward "^|")
7228 (setq ecol (1- (current-column)))
7229 (org-table-goto-column column)
7230 (setq lns (mapcar (lambda(x) (cons (org-trim (substring x bcol ecol)) x))
7231 (org-split-string (buffer-substring beg end) "\n")))
7232 (setq lns (org-do-sort lns "Table" with-case sorting-type))
7233 (delete-region beg end)
7234 (move-marker beg nil)
7235 (move-marker end nil)
7236 (insert (mapconcat 'cdr lns "\n") "\n")
7237 (goto-line thisline)
7238 (org-table-goto-column thiscol)
7239 (message "%d lines sorted, based on column %d" (length lns) column)))
7241 (defun org-table-cut-region (beg end)
7242 "Copy region in table to the clipboard and blank all relevant fields."
7243 (interactive "r")
7244 (org-table-copy-region beg end 'cut))
7246 (defun org-table-copy-region (beg end &optional cut)
7247 "Copy rectangular region in table to clipboard.
7248 A special clipboard is used which can only be accessed
7249 with `org-table-paste-rectangle'."
7250 (interactive "rP")
7251 (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2
7252 region cols
7253 (rpl (if cut " " nil)))
7254 (goto-char beg)
7255 (org-table-check-inside-data-field)
7256 (setq l01 (org-current-line)
7257 c01 (org-table-current-column))
7258 (goto-char end)
7259 (org-table-check-inside-data-field)
7260 (setq l02 (org-current-line)
7261 c02 (org-table-current-column))
7262 (setq l1 (min l01 l02) l2 (max l01 l02)
7263 c1 (min c01 c02) c2 (max c01 c02))
7264 (catch 'exit
7265 (while t
7266 (catch 'nextline
7267 (if (> l1 l2) (throw 'exit t))
7268 (goto-line l1)
7269 (if (org-at-table-hline-p) (throw 'nextline (setq l1 (1+ l1))))
7270 (setq cols nil ic1 c1 ic2 c2)
7271 (while (< ic1 (1+ ic2))
7272 (push (org-table-get-field ic1 rpl) cols)
7273 (setq ic1 (1+ ic1)))
7274 (push (nreverse cols) region)
7275 (setq l1 (1+ l1)))))
7276 (setq org-table-clip (nreverse region))
7277 (if cut (org-table-align))
7278 org-table-clip))
7280 (defun org-table-paste-rectangle ()
7281 "Paste a rectangular region into a table.
7282 The upper right corner ends up in the current field. All involved fields
7283 will be overwritten. If the rectangle does not fit into the present table,
7284 the table is enlarged as needed. The process ignores horizontal separator
7285 lines."
7286 (interactive)
7287 (unless (and org-table-clip (listp org-table-clip))
7288 (error "First cut/copy a region to paste!"))
7289 (org-table-check-inside-data-field)
7290 (let* ((clip org-table-clip)
7291 (line (org-current-line))
7292 (col (org-table-current-column))
7293 (org-enable-table-editor t)
7294 (org-table-automatic-realign nil)
7295 c cols field)
7296 (while (setq cols (pop clip))
7297 (while (org-at-table-hline-p) (beginning-of-line 2))
7298 (if (not (org-at-table-p))
7299 (progn (end-of-line 0) (org-table-next-field)))
7300 (setq c col)
7301 (while (setq field (pop cols))
7302 (org-table-goto-column c nil 'force)
7303 (org-table-get-field nil field)
7304 (setq c (1+ c)))
7305 (beginning-of-line 2))
7306 (goto-line line)
7307 (org-table-goto-column col)
7308 (org-table-align)))
7310 (defun org-table-convert ()
7311 "Convert from `org-mode' table to table.el and back.
7312 Obviously, this only works within limits. When an Org-mode table is
7313 converted to table.el, all horizontal separator lines get lost, because
7314 table.el uses these as cell boundaries and has no notion of horizontal lines.
7315 A table.el table can be converted to an Org-mode table only if it does not
7316 do row or column spanning. Multiline cells will become multiple cells.
7317 Beware, Org-mode does not test if the table can be successfully converted - it
7318 blindly applies a recipe that works for simple tables."
7319 (interactive)
7320 (require 'table)
7321 (if (org-at-table.el-p)
7322 ;; convert to Org-mode table
7323 (let ((beg (move-marker (make-marker) (org-table-begin t)))
7324 (end (move-marker (make-marker) (org-table-end t))))
7325 (table-unrecognize-region beg end)
7326 (goto-char beg)
7327 (while (re-search-forward "^\\([ \t]*\\)\\+-.*\n" end t)
7328 (replace-match ""))
7329 (goto-char beg))
7330 (if (org-at-table-p)
7331 ;; convert to table.el table
7332 (let ((beg (move-marker (make-marker) (org-table-begin)))
7333 (end (move-marker (make-marker) (org-table-end))))
7334 ;; first, get rid of all horizontal lines
7335 (goto-char beg)
7336 (while (re-search-forward "^\\([ \t]*\\)|-.*\n" end t)
7337 (replace-match ""))
7338 ;; insert a hline before first
7339 (goto-char beg)
7340 (org-table-insert-hline 'above)
7341 (beginning-of-line -1)
7342 ;; insert a hline after each line
7343 (while (progn (beginning-of-line 3) (< (point) end))
7344 (org-table-insert-hline))
7345 (goto-char beg)
7346 (setq end (move-marker end (org-table-end)))
7347 ;; replace "+" at beginning and ending of hlines
7348 (while (re-search-forward "^\\([ \t]*\\)|-" end t)
7349 (replace-match "\\1+-"))
7350 (goto-char beg)
7351 (while (re-search-forward "-|[ \t]*$" end t)
7352 (replace-match "-+"))
7353 (goto-char beg)))))
7355 (defun org-table-wrap-region (arg)
7356 "Wrap several fields in a column like a paragraph.
7357 This is useful if you'd like to spread the contents of a field over several
7358 lines, in order to keep the table compact.
7360 If there is an active region, and both point and mark are in the same column,
7361 the text in the column is wrapped to minimum width for the given number of
7362 lines. Generally, this makes the table more compact. A prefix ARG may be
7363 used to change the number of desired lines. For example, `C-2 \\[org-table-wrap]'
7364 formats the selected text to two lines. If the region was longer than two
7365 lines, the remaining lines remain empty. A negative prefix argument reduces
7366 the current number of lines by that amount. The wrapped text is pasted back
7367 into the table. If you formatted it to more lines than it was before, fields
7368 further down in the table get overwritten - so you might need to make space in
7369 the table first.
7371 If there is no region, the current field is split at the cursor position and
7372 the text fragment to the right of the cursor is prepended to the field one
7373 line down.
7375 If there is no region, but you specify a prefix ARG, the current field gets
7376 blank, and the content is appended to the field above."
7377 (interactive "P")
7378 (org-table-check-inside-data-field)
7379 (if (org-region-active-p)
7380 ;; There is a region: fill as a paragraph
7381 (let* ((beg (region-beginning))
7382 (cline (save-excursion (goto-char beg) (org-current-line)))
7383 (ccol (save-excursion (goto-char beg) (org-table-current-column)))
7384 nlines)
7385 (org-table-cut-region (region-beginning) (region-end))
7386 (if (> (length (car org-table-clip)) 1)
7387 (error "Region must be limited to single column"))
7388 (setq nlines (if arg
7389 (if (< arg 1)
7390 (+ (length org-table-clip) arg)
7391 arg)
7392 (length org-table-clip)))
7393 (setq org-table-clip
7394 (mapcar 'list (org-wrap (mapconcat 'car org-table-clip " ")
7395 nil nlines)))
7396 (goto-line cline)
7397 (org-table-goto-column ccol)
7398 (org-table-paste-rectangle))
7399 ;; No region, split the current field at point
7400 (if arg
7401 ;; combine with field above
7402 (let ((s (org-table-blank-field))
7403 (col (org-table-current-column)))
7404 (beginning-of-line 0)
7405 (while (org-at-table-hline-p) (beginning-of-line 0))
7406 (org-table-goto-column col)
7407 (skip-chars-forward "^|")
7408 (skip-chars-backward " ")
7409 (insert " " (org-trim s))
7410 (org-table-align))
7411 ;; split field
7412 (when (looking-at "\\([^|]+\\)+|")
7413 (let ((s (match-string 1)))
7414 (replace-match " |")
7415 (goto-char (match-beginning 0))
7416 (org-table-next-row)
7417 (insert (org-trim s) " ")
7418 (org-table-align))))))
7420 (defvar org-field-marker nil)
7422 (defun org-table-edit-field (arg)
7423 "Edit table field in a different window.
7424 This is mainly useful for fields that contain hidden parts.
7425 When called with a \\[universal-argument] prefix, just make the full field visible so that
7426 it can be edited in place."
7427 (interactive "P")
7428 (if arg
7429 (let ((b (save-excursion (skip-chars-backward "^|") (point)))
7430 (e (save-excursion (skip-chars-forward "^|\r\n") (point))))
7431 (remove-text-properties b e '(org-cwidth t invisible t
7432 display t intangible t))
7433 (if (and (boundp 'font-lock-mode) font-lock-mode)
7434 (font-lock-fontify-block)))
7435 (let ((pos (move-marker (make-marker) (point)))
7436 (field (org-table-get-field))
7437 (cw (current-window-configuration))
7439 (switch-to-buffer-other-window "*Org tmp*")
7440 (erase-buffer)
7441 (insert "#\n# Edit field and finish with C-c C-c\n#\n")
7442 (let ((org-inhibit-startup t)) (org-mode))
7443 (goto-char (setq p (point-max)))
7444 (insert (org-trim field))
7445 (remove-text-properties p (point-max)
7446 '(invisible t org-cwidth t display t
7447 intangible t))
7448 (goto-char p)
7449 (org-set-local 'org-finish-function 'org-table-finish-edit-field)
7450 (org-set-local 'org-window-configuration cw)
7451 (org-set-local 'org-field-marker pos)
7452 (message "Edit and finish with C-c C-c"))))
7454 (defun org-table-finish-edit-field ()
7455 "Finish editing a table data field.
7456 Remove all newline characters, insert the result into the table, realign
7457 the table and kill the editing buffer."
7458 (let ((pos org-field-marker)
7459 (cw org-window-configuration)
7460 (cb (current-buffer))
7461 text)
7462 (goto-char (point-min))
7463 (while (re-search-forward "^#.*\n?" nil t) (replace-match ""))
7464 (while (re-search-forward "\\([ \t]*\n[ \t]*\\)+" nil t)
7465 (replace-match " "))
7466 (setq text (org-trim (buffer-string)))
7467 (set-window-configuration cw)
7468 (kill-buffer cb)
7469 (select-window (get-buffer-window (marker-buffer pos)))
7470 (goto-char pos)
7471 (move-marker pos nil)
7472 (org-table-check-inside-data-field)
7473 (org-table-get-field nil text)
7474 (org-table-align)
7475 (message "New field value inserted")))
7477 (defun org-trim (s)
7478 "Remove whitespace at beginning and end of string."
7479 (if (string-match "^[ \t\n\r]+" s) (setq s (replace-match "" t t s)))
7480 (if (string-match "[ \t\n\r]+$" s) (setq s (replace-match "" t t s)))
7483 (defun org-wrap (string &optional width lines)
7484 "Wrap string to either a number of lines, or a width in characters.
7485 If WIDTH is non-nil, the string is wrapped to that width, however many lines
7486 that costs. If there is a word longer than WIDTH, the text is actually
7487 wrapped to the length of that word.
7488 IF WIDTH is nil and LINES is non-nil, the string is forced into at most that
7489 many lines, whatever width that takes.
7490 The return value is a list of lines, without newlines at the end."
7491 (let* ((words (org-split-string string "[ \t\n]+"))
7492 (maxword (apply 'max (mapcar 'org-string-width words)))
7493 w ll)
7494 (cond (width
7495 (org-do-wrap words (max maxword width)))
7496 (lines
7497 (setq w maxword)
7498 (setq ll (org-do-wrap words maxword))
7499 (if (<= (length ll) lines)
7501 (setq ll words)
7502 (while (> (length ll) lines)
7503 (setq w (1+ w))
7504 (setq ll (org-do-wrap words w)))
7505 ll))
7506 (t (error "Cannot wrap this")))))
7509 (defun org-do-wrap (words width)
7510 "Create lines of maximum width WIDTH (in characters) from word list WORDS."
7511 (let (lines line)
7512 (while words
7513 (setq line (pop words))
7514 (while (and words (< (+ (length line) (length (car words))) width))
7515 (setq line (concat line " " (pop words))))
7516 (setq lines (push line lines)))
7517 (nreverse lines)))
7519 (defun org-split-string (string &optional separators)
7520 "Splits STRING into substrings at SEPARATORS.
7521 No empty strings are returned if there are matches at the beginning
7522 and end of string."
7523 (let ((rexp (or separators "[ \f\t\n\r\v]+"))
7524 (start 0)
7525 notfirst
7526 (list nil))
7527 (while (and (string-match rexp string
7528 (if (and notfirst
7529 (= start (match-beginning 0))
7530 (< start (length string)))
7531 (1+ start) start))
7532 (< (match-beginning 0) (length string)))
7533 (setq notfirst t)
7534 (or (eq (match-beginning 0) 0)
7535 (and (eq (match-beginning 0) (match-end 0))
7536 (eq (match-beginning 0) start))
7537 (setq list
7538 (cons (substring string start (match-beginning 0))
7539 list)))
7540 (setq start (match-end 0)))
7541 (or (eq start (length string))
7542 (setq list
7543 (cons (substring string start)
7544 list)))
7545 (nreverse list)))
7547 (defun org-table-map-tables (function)
7548 "Apply FUNCTION to the start of all tables in the buffer."
7549 (save-excursion
7550 (save-restriction
7551 (widen)
7552 (goto-char (point-min))
7553 (while (re-search-forward org-table-any-line-regexp nil t)
7554 (message "Mapping tables: %d%%" (/ (* 100.0 (point)) (buffer-size)))
7555 (beginning-of-line 1)
7556 (if (looking-at org-table-line-regexp)
7557 (save-excursion (funcall function)))
7558 (re-search-forward org-table-any-border-regexp nil 1))))
7559 (message "Mapping tables: done"))
7561 (defvar org-timecnt) ; dynamically scoped parameter
7563 (defun org-table-sum (&optional beg end nlast)
7564 "Sum numbers in region of current table column.
7565 The result will be displayed in the echo area, and will be available
7566 as kill to be inserted with \\[yank].
7568 If there is an active region, it is interpreted as a rectangle and all
7569 numbers in that rectangle will be summed. If there is no active
7570 region and point is located in a table column, sum all numbers in that
7571 column.
7573 If at least one number looks like a time HH:MM or HH:MM:SS, all other
7574 numbers are assumed to be times as well (in decimal hours) and the
7575 numbers are added as such.
7577 If NLAST is a number, only the NLAST fields will actually be summed."
7578 (interactive)
7579 (save-excursion
7580 (let (col (org-timecnt 0) diff h m s org-table-clip)
7581 (cond
7582 ((and beg end)) ; beg and end given explicitly
7583 ((org-region-active-p)
7584 (setq beg (region-beginning) end (region-end)))
7586 (setq col (org-table-current-column))
7587 (goto-char (org-table-begin))
7588 (unless (re-search-forward "^[ \t]*|[^-]" nil t)
7589 (error "No table data"))
7590 (org-table-goto-column col)
7591 (setq beg (point))
7592 (goto-char (org-table-end))
7593 (unless (re-search-backward "^[ \t]*|[^-]" nil t)
7594 (error "No table data"))
7595 (org-table-goto-column col)
7596 (setq end (point))))
7597 (let* ((items (apply 'append (org-table-copy-region beg end)))
7598 (items1 (cond ((not nlast) items)
7599 ((>= nlast (length items)) items)
7600 (t (setq items (reverse items))
7601 (setcdr (nthcdr (1- nlast) items) nil)
7602 (nreverse items))))
7603 (numbers (delq nil (mapcar 'org-table-get-number-for-summing
7604 items1)))
7605 (res (apply '+ numbers))
7606 (sres (if (= org-timecnt 0)
7607 (format "%g" res)
7608 (setq diff (* 3600 res)
7609 h (floor (/ diff 3600)) diff (mod diff 3600)
7610 m (floor (/ diff 60)) diff (mod diff 60)
7611 s diff)
7612 (format "%d:%02d:%02d" h m s))))
7613 (kill-new sres)
7614 (if (interactive-p)
7615 (message "%s"
7616 (substitute-command-keys
7617 (format "Sum of %d items: %-20s (\\[yank] will insert result into buffer)"
7618 (length numbers) sres))))
7619 sres))))
7621 (defun org-table-get-number-for-summing (s)
7622 (let (n)
7623 (if (string-match "^ *|? *" s)
7624 (setq s (replace-match "" nil nil s)))
7625 (if (string-match " *|? *$" s)
7626 (setq s (replace-match "" nil nil s)))
7627 (setq n (string-to-number s))
7628 (cond
7629 ((and (string-match "0" s)
7630 (string-match "\\`[-+ \t0.edED]+\\'" s)) 0)
7631 ((string-match "\\`[ \t]+\\'" s) nil)
7632 ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?\\'" s)
7633 (let ((h (string-to-number (or (match-string 1 s) "0")))
7634 (m (string-to-number (or (match-string 2 s) "0")))
7635 (s (string-to-number (or (match-string 4 s) "0"))))
7636 (if (boundp 'org-timecnt) (setq org-timecnt (1+ org-timecnt)))
7637 (* 1.0 (+ h (/ m 60.0) (/ s 3600.0)))))
7638 ((equal n 0) nil)
7639 (t n))))
7641 (defun org-table-current-field-formula (&optional key noerror)
7642 "Return the formula active for the current field.
7643 Assumes that specials are in place.
7644 If KEY is given, return the key to this formula.
7645 Otherwise return the formula preceeded with \"=\" or \":=\"."
7646 (let* ((name (car (rassoc (list (org-current-line)
7647 (org-table-current-column))
7648 org-table-named-field-locations)))
7649 (col (org-table-current-column))
7650 (scol (int-to-string col))
7651 (ref (format "@%d$%d" (org-table-current-dline) col))
7652 (stored-list (org-table-get-stored-formulas noerror))
7653 (ass (or (assoc name stored-list)
7654 (assoc ref stored-list)
7655 (assoc scol stored-list))))
7656 (if key
7657 (car ass)
7658 (if ass (concat (if (string-match "^[0-9]+$" (car ass)) "=" ":=")
7659 (cdr ass))))))
7661 (defun org-table-get-formula (&optional equation named)
7662 "Read a formula from the minibuffer, offer stored formula as default.
7663 When NAMED is non-nil, look for a named equation."
7664 (let* ((stored-list (org-table-get-stored-formulas))
7665 (name (car (rassoc (list (org-current-line)
7666 (org-table-current-column))
7667 org-table-named-field-locations)))
7668 (ref (format "@%d$%d" (org-table-current-dline)
7669 (org-table-current-column)))
7670 (refass (assoc ref stored-list))
7671 (scol (if named
7672 (if name name ref)
7673 (int-to-string (org-table-current-column))))
7674 (dummy (and (or name refass) (not named)
7675 (not (y-or-n-p "Replace field formula with column formula? " ))
7676 (error "Abort")))
7677 (name (or name ref))
7678 (org-table-may-need-update nil)
7679 (stored (cdr (assoc scol stored-list)))
7680 (eq (cond
7681 ((and stored equation (string-match "^ *=? *$" equation))
7682 stored)
7683 ((stringp equation)
7684 equation)
7685 (t (org-table-formula-from-user
7686 (read-string
7687 (org-table-formula-to-user
7688 (format "%s formula %s%s="
7689 (if named "Field" "Column")
7690 (if (member (string-to-char scol) '(?$ ?@)) "" "$")
7691 scol))
7692 (if stored (org-table-formula-to-user stored) "")
7693 'org-table-formula-history
7694 )))))
7695 mustsave)
7696 (when (not (string-match "\\S-" eq))
7697 ;; remove formula
7698 (setq stored-list (delq (assoc scol stored-list) stored-list))
7699 (org-table-store-formulas stored-list)
7700 (error "Formula removed"))
7701 (if (string-match "^ *=?" eq) (setq eq (replace-match "" t t eq)))
7702 (if (string-match " *$" eq) (setq eq (replace-match "" t t eq)))
7703 (if (and name (not named))
7704 ;; We set the column equation, delete the named one.
7705 (setq stored-list (delq (assoc name stored-list) stored-list)
7706 mustsave t))
7707 (if stored
7708 (setcdr (assoc scol stored-list) eq)
7709 (setq stored-list (cons (cons scol eq) stored-list)))
7710 (if (or mustsave (not (equal stored eq)))
7711 (org-table-store-formulas stored-list))
7712 eq))
7714 (defun org-table-store-formulas (alist)
7715 "Store the list of formulas below the current table."
7716 (setq alist (sort alist 'org-table-formula-less-p))
7717 (save-excursion
7718 (goto-char (org-table-end))
7719 (if (looking-at "\\([ \t]*\n\\)*#\\+TBLFM:\\(.*\n?\\)")
7720 (progn
7721 ;; don't overwrite TBLFM, we might use text properties to store stuff
7722 (goto-char (match-beginning 2))
7723 (delete-region (match-beginning 2) (match-end 0)))
7724 (insert "#+TBLFM:"))
7725 (insert " "
7726 (mapconcat (lambda (x)
7727 (concat
7728 (if (equal (string-to-char (car x)) ?@) "" "$")
7729 (car x) "=" (cdr x)))
7730 alist "::")
7731 "\n")))
7733 (defsubst org-table-formula-make-cmp-string (a)
7734 (when (string-match "^\\(@\\([0-9]+\\)\\)?\\(\\$?\\([0-9]+\\)\\)?\\(\\$?[a-zA-Z0-9]+\\)?" a)
7735 (concat
7736 (if (match-end 2) (format "@%05d" (string-to-number (match-string 2 a))) "")
7737 (if (match-end 4) (format "$%05d" (string-to-number (match-string 4 a))) "")
7738 (if (match-end 5) (concat "@@" (match-string 5 a))))))
7740 (defun org-table-formula-less-p (a b)
7741 "Compare two formulas for sorting."
7742 (let ((as (org-table-formula-make-cmp-string (car a)))
7743 (bs (org-table-formula-make-cmp-string (car b))))
7744 (and as bs (string< as bs))))
7746 (defun org-table-get-stored-formulas (&optional noerror)
7747 "Return an alist with the stored formulas directly after current table."
7748 (interactive)
7749 (let (scol eq eq-alist strings string seen)
7750 (save-excursion
7751 (goto-char (org-table-end))
7752 (when (looking-at "\\([ \t]*\n\\)*#\\+TBLFM: *\\(.*\\)")
7753 (setq strings (org-split-string (match-string 2) " *:: *"))
7754 (while (setq string (pop strings))
7755 (when (string-match "\\(@[0-9]+\\$[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*[^ \t]\\)" string)
7756 (setq scol (if (match-end 2)
7757 (match-string 2 string)
7758 (match-string 1 string))
7759 eq (match-string 3 string)
7760 eq-alist (cons (cons scol eq) eq-alist))
7761 (if (member scol seen)
7762 (if noerror
7763 (progn
7764 (message "Double definition `$%s=' in TBLFM line, please fix by hand" scol)
7765 (ding)
7766 (sit-for 2))
7767 (error "Double definition `$%s=' in TBLFM line, please fix by hand" scol))
7768 (push scol seen))))))
7769 (nreverse eq-alist)))
7771 (defun org-table-fix-formulas (key replace &optional limit delta remove)
7772 "Modify the equations after the table structure has been edited.
7773 KEY is \"@\" or \"$\". REPLACE is an alist of numbers to replace.
7774 For all numbers larger than LIMIT, shift them by DELTA."
7775 (save-excursion
7776 (goto-char (org-table-end))
7777 (when (looking-at "#\\+TBLFM:")
7778 (let ((re (concat key "\\([0-9]+\\)"))
7779 (re2
7780 (when remove
7781 (if (equal key "$")
7782 (format "\\(@[0-9]+\\)?\\$%d=.*?\\(::\\|$\\)" remove)
7783 (format "@%d\\$[0-9]+=.*?\\(::\\|$\\)" remove))))
7784 s n a)
7785 (when remove
7786 (while (re-search-forward re2 (point-at-eol) t)
7787 (replace-match "")))
7788 (while (re-search-forward re (point-at-eol) t)
7789 (setq s (match-string 1) n (string-to-number s))
7790 (cond
7791 ((setq a (assoc s replace))
7792 (replace-match (concat key (cdr a)) t t))
7793 ((and limit (> n limit))
7794 (replace-match (concat key (int-to-string (+ n delta))) t t))))))))
7796 (defun org-table-get-specials ()
7797 "Get the column names and local parameters for this table."
7798 (save-excursion
7799 (let ((beg (org-table-begin)) (end (org-table-end))
7800 names name fields fields1 field cnt
7801 c v l line col types dlines hlines)
7802 (setq org-table-column-names nil
7803 org-table-local-parameters nil
7804 org-table-named-field-locations nil
7805 org-table-current-begin-line nil
7806 org-table-current-begin-pos nil
7807 org-table-current-line-types nil)
7808 (goto-char beg)
7809 (when (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t)
7810 (setq names (org-split-string (match-string 1) " *| *")
7811 cnt 1)
7812 (while (setq name (pop names))
7813 (setq cnt (1+ cnt))
7814 (if (string-match "^[a-zA-Z][a-zA-Z0-9]*$" name)
7815 (push (cons name (int-to-string cnt)) org-table-column-names))))
7816 (setq org-table-column-names (nreverse org-table-column-names))
7817 (setq org-table-column-name-regexp
7818 (concat "\\$\\(" (mapconcat 'car org-table-column-names "\\|") "\\)\\>"))
7819 (goto-char beg)
7820 (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t)
7821 (setq fields (org-split-string (match-string 1) " *| *"))
7822 (while (setq field (pop fields))
7823 (if (string-match "^\\([a-zA-Z][a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field)
7824 (push (cons (match-string 1 field) (match-string 2 field))
7825 org-table-local-parameters))))
7826 (goto-char beg)
7827 (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t)
7828 (setq c (match-string 1)
7829 fields (org-split-string (match-string 2) " *| *"))
7830 (save-excursion
7831 (beginning-of-line (if (equal c "_") 2 0))
7832 (setq line (org-current-line) col 1)
7833 (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)")
7834 (setq fields1 (org-split-string (match-string 1) " *| *"))))
7835 (while (and fields1 (setq field (pop fields)))
7836 (setq v (pop fields1) col (1+ col))
7837 (when (and (stringp field) (stringp v)
7838 (string-match "^[a-zA-Z][a-zA-Z0-9]*$" field))
7839 (push (cons field v) org-table-local-parameters)
7840 (push (list field line col) org-table-named-field-locations))))
7841 ;; Analyse the line types
7842 (goto-char beg)
7843 (setq org-table-current-begin-line (org-current-line)
7844 org-table-current-begin-pos (point)
7845 l org-table-current-begin-line)
7846 (while (looking-at "[ \t]*|\\(-\\)?")
7847 (push (if (match-end 1) 'hline 'dline) types)
7848 (if (match-end 1) (push l hlines) (push l dlines))
7849 (beginning-of-line 2)
7850 (setq l (1+ l)))
7851 (setq org-table-current-line-types (apply 'vector (nreverse types))
7852 org-table-dlines (apply 'vector (cons nil (nreverse dlines)))
7853 org-table-hlines (apply 'vector (cons nil (nreverse hlines)))))))
7855 (defun org-table-maybe-eval-formula ()
7856 "Check if the current field starts with \"=\" or \":=\".
7857 If yes, store the formula and apply it."
7858 ;; We already know we are in a table. Get field will only return a formula
7859 ;; when appropriate. It might return a separator line, but no problem.
7860 (when org-table-formula-evaluate-inline
7861 (let* ((field (org-trim (or (org-table-get-field) "")))
7862 named eq)
7863 (when (string-match "^:?=\\(.*\\)" field)
7864 (setq named (equal (string-to-char field) ?:)
7865 eq (match-string 1 field))
7866 (if (or (fboundp 'calc-eval)
7867 (equal (substring eq 0 (min 2 (length eq))) "'("))
7868 (org-table-eval-formula (if named '(4) nil)
7869 (org-table-formula-from-user eq))
7870 (error "Calc does not seem to be installed, and is needed to evaluate the formula"))))))
7872 (defvar org-recalc-commands nil
7873 "List of commands triggering the recalculation of a line.
7874 Will be filled automatically during use.")
7876 (defvar org-recalc-marks
7877 '((" " . "Unmarked: no special line, no automatic recalculation")
7878 ("#" . "Automatically recalculate this line upon TAB, RET, and C-c C-c in the line")
7879 ("*" . "Recalculate only when entire table is recalculated with `C-u C-c *'")
7880 ("!" . "Column name definition line. Reference in formula as $name.")
7881 ("$" . "Parameter definition line name=value. Reference in formula as $name.")
7882 ("_" . "Names for values in row below this one.")
7883 ("^" . "Names for values in row above this one.")))
7885 (defun org-table-rotate-recalc-marks (&optional newchar)
7886 "Rotate the recalculation mark in the first column.
7887 If in any row, the first field is not consistent with a mark,
7888 insert a new column for the markers.
7889 When there is an active region, change all the lines in the region,
7890 after prompting for the marking character.
7891 After each change, a message will be displayed indicating the meaning
7892 of the new mark."
7893 (interactive)
7894 (unless (org-at-table-p) (error "Not at a table"))
7895 (let* ((marks (append (mapcar 'car org-recalc-marks) '(" ")))
7896 (beg (org-table-begin))
7897 (end (org-table-end))
7898 (l (org-current-line))
7899 (l1 (if (org-region-active-p) (org-current-line (region-beginning))))
7900 (l2 (if (org-region-active-p) (org-current-line (region-end))))
7901 (have-col
7902 (save-excursion
7903 (goto-char beg)
7904 (not (re-search-forward "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" end t))))
7905 (col (org-table-current-column))
7906 (forcenew (car (assoc newchar org-recalc-marks)))
7907 epos new)
7908 (when l1
7909 (message "Change region to what mark? Type # * ! $ or SPC: ")
7910 (setq newchar (char-to-string (read-char-exclusive))
7911 forcenew (car (assoc newchar org-recalc-marks))))
7912 (if (and newchar (not forcenew))
7913 (error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'"
7914 newchar))
7915 (if l1 (goto-line l1))
7916 (save-excursion
7917 (beginning-of-line 1)
7918 (unless (looking-at org-table-dataline-regexp)
7919 (error "Not at a table data line")))
7920 (unless have-col
7921 (org-table-goto-column 1)
7922 (org-table-insert-column)
7923 (org-table-goto-column (1+ col)))
7924 (setq epos (point-at-eol))
7925 (save-excursion
7926 (beginning-of-line 1)
7927 (org-table-get-field
7928 1 (if (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|")
7929 (concat " "
7930 (setq new (or forcenew
7931 (cadr (member (match-string 1) marks))))
7932 " ")
7933 " # ")))
7934 (if (and l1 l2)
7935 (progn
7936 (goto-line l1)
7937 (while (progn (beginning-of-line 2) (not (= (org-current-line) l2)))
7938 (and (looking-at org-table-dataline-regexp)
7939 (org-table-get-field 1 (concat " " new " "))))
7940 (goto-line l1)))
7941 (if (not (= epos (point-at-eol))) (org-table-align))
7942 (goto-line l)
7943 (and (interactive-p) (message (cdr (assoc new org-recalc-marks))))))
7945 (defun org-table-maybe-recalculate-line ()
7946 "Recompute the current line if marked for it, and if we haven't just done it."
7947 (interactive)
7948 (and org-table-allow-automatic-line-recalculation
7949 (not (and (memq last-command org-recalc-commands)
7950 (equal org-last-recalc-line (org-current-line))))
7951 (save-excursion (beginning-of-line 1)
7952 (looking-at org-table-auto-recalculate-regexp))
7953 (org-table-recalculate) t))
7955 (defvar org-table-formula-debug nil
7956 "Non-nil means, debug table formulas.
7957 When nil, simply write \"#ERROR\" in corrupted fields.")
7958 (make-variable-buffer-local 'org-table-formula-debug)
7960 (defvar modes)
7961 (defsubst org-set-calc-mode (var &optional value)
7962 (if (stringp var)
7963 (setq var (assoc var '(("D" calc-angle-mode deg)
7964 ("R" calc-angle-mode rad)
7965 ("F" calc-prefer-frac t)
7966 ("S" calc-symbolic-mode t)))
7967 value (nth 2 var) var (nth 1 var)))
7968 (if (memq var modes)
7969 (setcar (cdr (memq var modes)) value)
7970 (cons var (cons value modes)))
7971 modes)
7973 (defun org-table-eval-formula (&optional arg equation
7974 suppress-align suppress-const
7975 suppress-store suppress-analysis)
7976 "Replace the table field value at the cursor by the result of a calculation.
7978 This function makes use of Dave Gillespie's Calc package, in my view the
7979 most exciting program ever written for GNU Emacs. So you need to have Calc
7980 installed in order to use this function.
7982 In a table, this command replaces the value in the current field with the
7983 result of a formula. It also installs the formula as the \"current\" column
7984 formula, by storing it in a special line below the table. When called
7985 with a `C-u' prefix, the current field must ba a named field, and the
7986 formula is installed as valid in only this specific field.
7988 When called with two `C-u' prefixes, insert the active equation
7989 for the field back into the current field, so that it can be
7990 edited there. This is useful in order to use \\[org-table-show-reference]
7991 to check the referenced fields.
7993 When called, the command first prompts for a formula, which is read in
7994 the minibuffer. Previously entered formulas are available through the
7995 history list, and the last used formula is offered as a default.
7996 These stored formulas are adapted correctly when moving, inserting, or
7997 deleting columns with the corresponding commands.
7999 The formula can be any algebraic expression understood by the Calc package.
8000 For details, see the Org-mode manual.
8002 This function can also be called from Lisp programs and offers
8003 additional arguments: EQUATION can be the formula to apply. If this
8004 argument is given, the user will not be prompted. SUPPRESS-ALIGN is
8005 used to speed-up recursive calls by by-passing unnecessary aligns.
8006 SUPPRESS-CONST suppresses the interpretation of constants in the
8007 formula, assuming that this has been done already outside the function.
8008 SUPPRESS-STORE means the formula should not be stored, either because
8009 it is already stored, or because it is a modified equation that should
8010 not overwrite the stored one."
8011 (interactive "P")
8012 (org-table-check-inside-data-field)
8013 (or suppress-analysis (org-table-get-specials))
8014 (if (equal arg '(16))
8015 (let ((eq (org-table-current-field-formula)))
8016 (or eq (error "No equation active for current field"))
8017 (org-table-get-field nil eq)
8018 (org-table-align)
8019 (setq org-table-may-need-update t))
8020 (let* (fields
8021 (ndown (if (integerp arg) arg 1))
8022 (org-table-automatic-realign nil)
8023 (case-fold-search nil)
8024 (down (> ndown 1))
8025 (formula (if (and equation suppress-store)
8026 equation
8027 (org-table-get-formula equation (equal arg '(4)))))
8028 (n0 (org-table-current-column))
8029 (modes (copy-sequence org-calc-default-modes))
8030 (numbers nil) ; was a variable, now fixed default
8031 (keep-empty nil)
8032 n form form0 bw fmt x ev orig c lispp)
8033 ;; Parse the format string. Since we have a lot of modes, this is
8034 ;; a lot of work. However, I think calc still uses most of the time.
8035 (if (string-match ";" formula)
8036 (let ((tmp (org-split-string formula ";")))
8037 (setq formula (car tmp)
8038 fmt (concat (cdr (assoc "%" org-table-local-parameters))
8039 (nth 1 tmp)))
8040 (while (string-match "\\([pnfse]\\)\\(-?[0-9]+\\)" fmt)
8041 (setq c (string-to-char (match-string 1 fmt))
8042 n (string-to-number (match-string 2 fmt)))
8043 (if (= c ?p)
8044 (setq modes (org-set-calc-mode 'calc-internal-prec n))
8045 (setq modes (org-set-calc-mode
8046 'calc-float-format
8047 (list (cdr (assoc c '((?n . float) (?f . fix)
8048 (?s . sci) (?e . eng))))
8049 n))))
8050 (setq fmt (replace-match "" t t fmt)))
8051 (if (string-match "[NT]" fmt)
8052 (setq numbers (equal (match-string 0 fmt) "N")
8053 fmt (replace-match "" t t fmt)))
8054 (if (string-match "E" fmt)
8055 (setq keep-empty t
8056 fmt (replace-match "" t t fmt)))
8057 (while (string-match "[DRFS]" fmt)
8058 (setq modes (org-set-calc-mode (match-string 0 fmt)))
8059 (setq fmt (replace-match "" t t fmt)))
8060 (unless (string-match "\\S-" fmt)
8061 (setq fmt nil))))
8062 (if (and (not suppress-const) org-table-formula-use-constants)
8063 (setq formula (org-table-formula-substitute-names formula)))
8064 (setq orig (or (get-text-property 1 :orig-formula formula) "?"))
8065 (while (> ndown 0)
8066 (setq fields (org-split-string
8067 (org-no-properties
8068 (buffer-substring (point-at-bol) (point-at-eol)))
8069 " *| *"))
8070 (if numbers
8071 (setq fields (mapcar
8072 (lambda (x) (number-to-string (string-to-number x)))
8073 fields)))
8074 (setq ndown (1- ndown))
8075 (setq form (copy-sequence formula)
8076 lispp (and (> (length form) 2)(equal (substring form 0 2) "'(")))
8077 ;; Check for old vertical references
8078 (setq form (org-rewrite-old-row-references form))
8079 ;; Insert complex ranges
8080 (while (string-match org-table-range-regexp form)
8081 (setq form
8082 (replace-match
8083 (save-match-data
8084 (org-table-make-reference
8085 (org-table-get-range (match-string 0 form) nil n0)
8086 keep-empty numbers lispp))
8087 t t form)))
8088 ;; Insert simple ranges
8089 (while (string-match "\\$\\([0-9]+\\)\\.\\.\\$\\([0-9]+\\)" form)
8090 (setq form
8091 (replace-match
8092 (save-match-data
8093 (org-table-make-reference
8094 (org-sublist
8095 fields (string-to-number (match-string 1 form))
8096 (string-to-number (match-string 2 form)))
8097 keep-empty numbers lispp))
8098 t t form)))
8099 (setq form0 form)
8100 ;; Insert the references to fields in same row
8101 (while (string-match "\\$\\([0-9]+\\)" form)
8102 (setq n (string-to-number (match-string 1 form))
8103 x (nth (1- (if (= n 0) n0 n)) fields))
8104 (unless x (error "Invalid field specifier \"%s\""
8105 (match-string 0 form)))
8106 (setq form (replace-match
8107 (save-match-data
8108 (org-table-make-reference x nil numbers lispp))
8109 t t form)))
8111 (if lispp
8112 (setq ev (condition-case nil
8113 (eval (eval (read form)))
8114 (error "#ERROR"))
8115 ev (if (numberp ev) (number-to-string ev) ev))
8116 (or (fboundp 'calc-eval)
8117 (error "Calc does not seem to be installed, and is needed to evaluate the formula"))
8118 (setq ev (calc-eval (cons form modes)
8119 (if numbers 'num))))
8121 (when org-table-formula-debug
8122 (with-output-to-temp-buffer "*Substitution History*"
8123 (princ (format "Substitution history of formula
8124 Orig: %s
8125 $xyz-> %s
8126 @r$c-> %s
8127 $1-> %s\n" orig formula form0 form))
8128 (if (listp ev)
8129 (princ (format " %s^\nError: %s"
8130 (make-string (car ev) ?\-) (nth 1 ev)))
8131 (princ (format "Result: %s\nFormat: %s\nFinal: %s"
8132 ev (or fmt "NONE")
8133 (if fmt (format fmt (string-to-number ev)) ev)))))
8134 (setq bw (get-buffer-window "*Substitution History*"))
8135 (shrink-window-if-larger-than-buffer bw)
8136 (unless (and (interactive-p) (not ndown))
8137 (unless (let (inhibit-redisplay)
8138 (y-or-n-p "Debugging Formula. Continue to next? "))
8139 (org-table-align)
8140 (error "Abort"))
8141 (delete-window bw)
8142 (message "")))
8143 (if (listp ev) (setq fmt nil ev "#ERROR"))
8144 (org-table-justify-field-maybe
8145 (if fmt (format fmt (string-to-number ev)) ev))
8146 (if (and down (> ndown 0) (looking-at ".*\n[ \t]*|[^-]"))
8147 (call-interactively 'org-return)
8148 (setq ndown 0)))
8149 (and down (org-table-maybe-recalculate-line))
8150 (or suppress-align (and org-table-may-need-update
8151 (org-table-align))))))
8153 (defun org-table-get-range (desc &optional tbeg col highlight)
8154 "Get a calc vector from a column, accorting to descriptor DESC.
8155 Optional arguments TBEG and COL can give the beginning of the table and
8156 the current column, to avoid unnecessary parsing.
8157 HIGHLIGHT means, just highlight the range."
8158 (if (not (equal (string-to-char desc) ?@))
8159 (setq desc (concat "@" desc)))
8160 (save-excursion
8161 (or tbeg (setq tbeg (org-table-begin)))
8162 (or col (setq col (org-table-current-column)))
8163 (let ((thisline (org-current-line))
8164 beg end c1 c2 r1 r2 rangep tmp)
8165 (unless (string-match org-table-range-regexp desc)
8166 (error "Invalid table range specifier `%s'" desc))
8167 (setq rangep (match-end 3)
8168 r1 (and (match-end 1) (match-string 1 desc))
8169 r2 (and (match-end 4) (match-string 4 desc))
8170 c1 (and (match-end 2) (substring (match-string 2 desc) 1))
8171 c2 (and (match-end 5) (substring (match-string 5 desc) 1)))
8173 (and c1 (setq c1 (+ (string-to-number c1)
8174 (if (memq (string-to-char c1) '(?- ?+)) col 0))))
8175 (and c2 (setq c2 (+ (string-to-number c2)
8176 (if (memq (string-to-char c2) '(?- ?+)) col 0))))
8177 (if (equal r1 "") (setq r1 nil))
8178 (if (equal r2 "") (setq r2 nil))
8179 (if r1 (setq r1 (org-table-get-descriptor-line r1)))
8180 (if r2 (setq r2 (org-table-get-descriptor-line r2)))
8181 ; (setq r2 (or r2 r1) c2 (or c2 c1))
8182 (if (not r1) (setq r1 thisline))
8183 (if (not r2) (setq r2 thisline))
8184 (if (not c1) (setq c1 col))
8185 (if (not c2) (setq c2 col))
8186 (if (or (not rangep) (and (= r1 r2) (= c1 c2)))
8187 ;; just one field
8188 (progn
8189 (goto-line r1)
8190 (while (not (looking-at org-table-dataline-regexp))
8191 (beginning-of-line 2))
8192 (prog1 (org-table-get-field c1)
8193 (if highlight (org-table-highlight-rectangle (point) (point)))))
8194 ;; A range, return a vector
8195 ;; First sort the numbers to get a regular ractangle
8196 (if (< r2 r1) (setq tmp r1 r1 r2 r2 tmp))
8197 (if (< c2 c1) (setq tmp c1 c1 c2 c2 tmp))
8198 (goto-line r1)
8199 (while (not (looking-at org-table-dataline-regexp))
8200 (beginning-of-line 2))
8201 (org-table-goto-column c1)
8202 (setq beg (point))
8203 (goto-line r2)
8204 (while (not (looking-at org-table-dataline-regexp))
8205 (beginning-of-line 0))
8206 (org-table-goto-column c2)
8207 (setq end (point))
8208 (if highlight
8209 (org-table-highlight-rectangle
8210 beg (progn (skip-chars-forward "^|\n") (point))))
8211 ;; return string representation of calc vector
8212 (apply 'append (org-table-copy-region beg end))))))
8214 (defun org-table-get-descriptor-line (desc &optional cline bline table)
8215 "Analyze descriptor DESC and retrieve the corresponding line number.
8216 The cursor is currently in line CLINE, the table begins in line BLINE,
8217 and TABLE is a vector with line types."
8218 (if (string-match "^[0-9]+$" desc)
8219 (aref org-table-dlines (string-to-number desc))
8220 (setq cline (or cline (org-current-line))
8221 bline (or bline org-table-current-begin-line)
8222 table (or table org-table-current-line-types))
8223 (if (or
8224 (not (string-match "^\\(\\([-+]\\)?\\(I+\\)\\)?\\(\\([-+]\\)?\\([0-9]+\\)\\)?" desc))
8225 ;; 1 2 3 4 5 6
8226 (and (not (match-end 3)) (not (match-end 6)))
8227 (and (match-end 3) (match-end 6) (not (match-end 5))))
8228 (error "invalid row descriptor `%s'" desc))
8229 (let* ((hdir (and (match-end 2) (match-string 2 desc)))
8230 (hn (if (match-end 3) (- (match-end 3) (match-beginning 3)) nil))
8231 (odir (and (match-end 5) (match-string 5 desc)))
8232 (on (if (match-end 6) (string-to-number (match-string 6 desc))))
8233 (i (- cline bline))
8234 (rel (and (match-end 6)
8235 (or (and (match-end 1) (not (match-end 3)))
8236 (match-end 5)))))
8237 (if (and hn (not hdir))
8238 (progn
8239 (setq i 0 hdir "+")
8240 (if (eq (aref table 0) 'hline) (setq hn (1- hn)))))
8241 (if (and (not hn) on (not odir))
8242 (error "should never happen");;(aref org-table-dlines on) FIXME
8243 (if (and hn (> hn 0))
8244 (setq i (org-find-row-type table i 'hline (equal hdir "-") nil hn)))
8245 (if on
8246 (setq i (org-find-row-type table i 'dline (equal odir "-") rel on)))
8247 (+ bline i)))))
8249 (defun org-find-row-type (table i type backwards relative n)
8250 (let ((l (length table)))
8251 (while (> n 0)
8252 (while (and (setq i (+ i (if backwards -1 1)))
8253 (>= i 0) (< i l)
8254 (not (eq (aref table i) type))
8255 (if (and relative (eq (aref table i) 'hline))
8256 (progn (setq i (- i (if backwards -1 1)) n 1) nil)
8257 t)))
8258 (setq n (1- n)))
8259 (if (or (< i 0) (>= i l))
8260 (error "Row descriptior leads outside table")
8261 i)))
8263 (defun org-rewrite-old-row-references (s)
8264 (if (string-match "&[-+0-9I]" s)
8265 (error "Formula contains old &row reference, please rewrite using @-syntax")
8268 (defun org-table-make-reference (elements keep-empty numbers lispp)
8269 "Convert list ELEMENTS to something appropriate to insert into formula.
8270 KEEP-EMPTY indicated to keep empty fields, default is to skip them.
8271 NUMBERS indicates that everything should be converted to numbers.
8272 LISPP means to return something appropriate for a Lisp list."
8273 (if (stringp elements) ; just a single val
8274 (if lispp
8275 (prin1-to-string (if numbers (string-to-number elements) elements))
8276 (if (equal elements "") (setq elements "0"))
8277 (if numbers (number-to-string (string-to-number elements)) elements))
8278 (unless keep-empty
8279 (setq elements
8280 (delq nil
8281 (mapcar (lambda (x) (if (string-match "\\S-" x) x nil))
8282 elements))))
8283 (setq elements (or elements '("0")))
8284 (if lispp
8285 (mapconcat 'prin1-to-string
8286 (if numbers (mapcar 'string-to-number elements) elements)
8287 " ")
8288 (concat "[" (mapconcat
8289 (lambda (x)
8290 (if numbers (number-to-string (string-to-number x)) x))
8291 elements
8292 ",") "]"))))
8294 (defun org-table-recalculate (&optional all noalign)
8295 "Recalculate the current table line by applying all stored formulas.
8296 With prefix arg ALL, do this for all lines in the table."
8297 (interactive "P")
8298 (or (memq this-command org-recalc-commands)
8299 (setq org-recalc-commands (cons this-command org-recalc-commands)))
8300 (unless (org-at-table-p) (error "Not at a table"))
8301 (if (equal all '(16))
8302 (org-table-iterate)
8303 (org-table-get-specials)
8304 (let* ((eqlist (sort (org-table-get-stored-formulas)
8305 (lambda (a b) (string< (car a) (car b)))))
8306 (inhibit-redisplay (not debug-on-error))
8307 (line-re org-table-dataline-regexp)
8308 (thisline (org-current-line))
8309 (thiscol (org-table-current-column))
8310 beg end entry eqlnum eqlname eql (cnt 0) eq a name)
8311 ;; Insert constants in all formulas
8312 (setq eqlist
8313 (mapcar (lambda (x)
8314 (setcdr x (org-table-formula-substitute-names (cdr x)))
8316 eqlist))
8317 ;; Split the equation list
8318 (while (setq eq (pop eqlist))
8319 (if (<= (string-to-char (car eq)) ?9)
8320 (push eq eqlnum)
8321 (push eq eqlname)))
8322 (setq eqlnum (nreverse eqlnum) eqlname (nreverse eqlname))
8323 (if all
8324 (progn
8325 (setq end (move-marker (make-marker) (1+ (org-table-end))))
8326 (goto-char (setq beg (org-table-begin)))
8327 (if (re-search-forward org-table-calculate-mark-regexp end t)
8328 ;; This is a table with marked lines, compute selected lines
8329 (setq line-re org-table-recalculate-regexp)
8330 ;; Move forward to the first non-header line
8331 (if (and (re-search-forward org-table-dataline-regexp end t)
8332 (re-search-forward org-table-hline-regexp end t)
8333 (re-search-forward org-table-dataline-regexp end t))
8334 (setq beg (match-beginning 0))
8335 nil))) ;; just leave beg where it is
8336 (setq beg (point-at-bol)
8337 end (move-marker (make-marker) (1+ (point-at-eol)))))
8338 (goto-char beg)
8339 (and all (message "Re-applying formulas to full table..."))
8340 (while (re-search-forward line-re end t)
8341 (unless (string-match "^ *[_^!$] *$" (org-table-get-field 1))
8342 ;; Unprotected line, recalculate
8343 (and all (message "Re-applying formulas to full table...(line %d)"
8344 (setq cnt (1+ cnt))))
8345 (setq org-last-recalc-line (org-current-line))
8346 (setq eql eqlnum)
8347 (while (setq entry (pop eql))
8348 (goto-line org-last-recalc-line)
8349 (org-table-goto-column (string-to-number (car entry)) nil 'force)
8350 (org-table-eval-formula nil (cdr entry)
8351 'noalign 'nocst 'nostore 'noanalysis))))
8352 (goto-line thisline)
8353 (org-table-goto-column thiscol)
8354 (or noalign (and org-table-may-need-update (org-table-align))
8355 (and all (message "Re-applying formulas to %d lines...done" cnt)))
8356 ;; Now do the named fields
8357 (while (setq eq (pop eqlname))
8358 (setq name (car eq)
8359 a (assoc name org-table-named-field-locations))
8360 (and (not a)
8361 (string-match "@\\([0-9]+\\)\\$\\([0-9]+\\)" name)
8362 (setq a
8363 (list
8364 name
8365 (aref org-table-dlines
8366 (string-to-number (match-string 1 name)))
8367 (string-to-number (match-string 2 name)))))
8368 (when (and a (or all (equal (nth 1 a) thisline)))
8369 (message "Re-applying formula to field: %s" name)
8370 (goto-line (nth 1 a))
8371 (org-table-goto-column (nth 2 a))
8372 (org-table-eval-formula nil (cdr eq) 'noalign 'nocst
8373 'nostore 'noanalysis)))
8374 ;; back to initial position
8375 (message "Re-applying formulas...done")
8376 (goto-line thisline)
8377 (org-table-goto-column thiscol)
8378 (or noalign (and org-table-may-need-update (org-table-align))
8379 (and all (message "Re-applying formulas...done"))))))
8381 (defun org-table-iterate (&optional arg)
8382 "Recalculate the table until it does not change anymore."
8383 (interactive "P")
8384 (let ((imax (if arg (prefix-numeric-value arg) 10))
8385 (i 0)
8386 (lasttbl (buffer-substring (org-table-begin) (org-table-end)))
8387 thistbl)
8388 (catch 'exit
8389 (while (< i imax)
8390 (setq i (1+ i))
8391 (org-table-recalculate 'all)
8392 (setq thistbl (buffer-substring (org-table-begin) (org-table-end)))
8393 (if (not (string= lasttbl thistbl))
8394 (setq lasttbl thistbl)
8395 (if (> i 1)
8396 (message "Convergence after %d iterations" i)
8397 (message "Table was already stable"))
8398 (throw 'exit t)))
8399 (error "No convergence after %d iterations" i))))
8401 (defun org-table-formula-substitute-names (f)
8402 "Replace $const with values in string F."
8403 (let ((start 0) a (f1 f))
8404 ;; First, check for column names
8405 (while (setq start (string-match org-table-column-name-regexp f start))
8406 (setq start (1+ start))
8407 (setq a (assoc (match-string 1 f) org-table-column-names))
8408 (setq f (replace-match (concat "$" (cdr a)) t t f)))
8409 ;; Parameters and constants
8410 (setq start 0)
8411 (while (setq start (string-match "\\$\\([a-zA-Z][a-zA-Z0-9]*\\)" f start))
8412 (setq start (1+ start))
8413 (if (setq a (save-match-data
8414 (org-table-get-constant (match-string 1 f))))
8415 (setq f (replace-match (concat "(" a ")") t t f))))
8416 (if org-table-formula-debug
8417 (put-text-property 0 (length f) :orig-formula f1 f))
8420 (defun org-table-get-constant (const)
8421 "Find the value for a parameter or constant in a formula.
8422 Parameters get priority."
8423 (or (cdr (assoc const org-table-local-parameters))
8424 (cdr (assoc const org-table-formula-constants))
8425 (and (fboundp 'constants-get) (constants-get const))
8426 "#UNDEFINED_NAME"))
8428 (defvar org-table-fedit-map (make-sparse-keymap))
8429 (org-defkey org-table-fedit-map "\C-x\C-s" 'org-table-fedit-finish)
8430 (org-defkey org-table-fedit-map "\C-c\C-s" 'org-table-fedit-finish)
8431 (org-defkey org-table-fedit-map "\C-c\C-c" 'org-table-fedit-finish)
8432 (org-defkey org-table-fedit-map "\C-c\C-q" 'org-table-fedit-abort)
8433 (org-defkey org-table-fedit-map "\C-c?" 'org-table-show-reference)
8434 (org-defkey org-table-fedit-map [(meta shift up)] 'org-table-fedit-line-up)
8435 (org-defkey org-table-fedit-map [(meta shift down)] 'org-table-fedit-line-down)
8436 (org-defkey org-table-fedit-map [(shift up)] 'org-table-fedit-ref-up)
8437 (org-defkey org-table-fedit-map [(shift down)] 'org-table-fedit-ref-down)
8438 (org-defkey org-table-fedit-map [(shift left)] 'org-table-fedit-ref-left)
8439 (org-defkey org-table-fedit-map [(shift right)] 'org-table-fedit-ref-right)
8440 (org-defkey org-table-fedit-map [(meta up)] 'org-table-fedit-scroll-down)
8441 (org-defkey org-table-fedit-map [(meta down)] 'org-table-fedit-scroll)
8442 (org-defkey org-table-fedit-map [(meta tab)] 'lisp-complete-symbol)
8443 (org-defkey org-table-fedit-map "\M-\C-i" 'lisp-complete-symbol)
8444 (org-defkey org-table-fedit-map [(tab)] 'org-table-fedit-lisp-indent)
8445 (org-defkey org-table-fedit-map "\C-i" 'org-table-fedit-lisp-indent)
8446 (org-defkey org-table-fedit-map "\C-c\C-r" 'org-table-fedit-toggle-ref-type)
8447 (org-defkey org-table-fedit-map "\C-c}" 'org-table-fedit-toggle-coordinates)
8449 (easy-menu-define org-table-fedit-menu org-table-fedit-map "Org Edit Formulas Menu"
8450 '("Edit-Formulas"
8451 ["Finish and Install" org-table-fedit-finish t]
8452 ["Finish, Install, and Apply" (org-table-fedit-finish t) :keys "C-u C-c C-c"]
8453 ["Abort" org-table-fedit-abort t]
8454 "--"
8455 ["Pretty-Print Lisp Formula" org-table-fedit-lisp-indent t]
8456 ["Complete Lisp Symbol" lisp-complete-symbol t]
8457 "--"
8458 "Shift Reference at Point"
8459 ["Up" org-table-fedit-ref-up t]
8460 ["Down" org-table-fedit-ref-down t]
8461 ["Left" org-table-fedit-ref-left t]
8462 ["Right" org-table-fedit-ref-right t]
8464 "Change Test Row for Column Formulas"
8465 ["Up" org-table-fedit-line-up t]
8466 ["Down" org-table-fedit-line-down t]
8467 "--"
8468 ["Scroll Table Window" org-table-fedit-scroll t]
8469 ["Scroll Table Window down" org-table-fedit-scroll-down t]
8470 ["Show Table Grid" org-table-fedit-toggle-coordinates
8471 :style toggle :selected (with-current-buffer (marker-buffer org-pos)
8472 org-table-overlay-coordinates)]
8473 "--"
8474 ["Standard Refs (B3 instead of @3$2)" org-table-fedit-toggle-ref-type
8475 :style toggle :selected org-table-buffer-is-an]))
8477 (defvar org-pos)
8479 (defun org-table-edit-formulas ()
8480 "Edit the formulas of the current table in a separate buffer."
8481 (interactive)
8482 (when (save-excursion (beginning-of-line 1) (looking-at "#\\+TBLFM"))
8483 (beginning-of-line 0))
8484 (unless (org-at-table-p) (error "Not at a table"))
8485 (org-table-get-specials)
8486 (let ((key (org-table-current-field-formula 'key 'noerror))
8487 (eql (sort (org-table-get-stored-formulas 'noerror)
8488 'org-table-formula-less-p))
8489 (pos (move-marker (make-marker) (point)))
8490 (startline 1)
8491 (wc (current-window-configuration))
8492 (titles '((column . "# Column Formulas\n")
8493 (field . "# Field Formulas\n")
8494 (named . "# Named Field Formulas\n")))
8495 entry s type title)
8496 (switch-to-buffer-other-window "*Edit Formulas*")
8497 (erase-buffer)
8498 ;; Keep global-font-lock-mode from turning on font-lock-mode
8499 (let ((font-lock-global-modes '(not fundamental-mode)))
8500 (fundamental-mode))
8501 (org-set-local 'font-lock-global-modes (list 'not major-mode))
8502 (org-set-local 'org-pos pos)
8503 (org-set-local 'org-window-configuration wc)
8504 (use-local-map org-table-fedit-map)
8505 (org-add-hook 'post-command-hook 'org-table-fedit-post-command t t)
8506 (easy-menu-add org-table-fedit-menu)
8507 (setq startline (org-current-line))
8508 (while (setq entry (pop eql))
8509 (setq type (cond
8510 ((equal (string-to-char (car entry)) ?@) 'field)
8511 ((string-match "^[0-9]" (car entry)) 'column)
8512 (t 'named)))
8513 (when (setq title (assq type titles))
8514 (or (bobp) (insert "\n"))
8515 (insert (org-add-props (cdr title) nil 'face font-lock-comment-face))
8516 (setq titles (delq title titles)))
8517 (if (equal key (car entry)) (setq startline (org-current-line)))
8518 (setq s (concat (if (equal (string-to-char (car entry)) ?@) "" "$")
8519 (car entry) " = " (cdr entry) "\n"))
8520 (remove-text-properties 0 (length s) '(face nil) s)
8521 (insert s))
8522 (if (eq org-table-use-standard-references t)
8523 (org-table-fedit-toggle-ref-type))
8524 (goto-line startline)
8525 (message "Edit formulas and finish with `C-c C-c'. See menu for more commands.")))
8527 (defun org-table-fedit-post-command ()
8528 (when (not (memq this-command '(lisp-complete-symbol)))
8529 (let ((win (selected-window)))
8530 (save-excursion
8531 (condition-case nil
8532 (org-table-show-reference)
8533 (error nil))
8534 (select-window win)))))
8536 (defun org-table-formula-to-user (s)
8537 "Convert a formula from internal to user representation."
8538 (if (eq org-table-use-standard-references t)
8539 (org-table-convert-refs-to-an s)
8542 (defun org-table-formula-from-user (s)
8543 "Convert a formula from user to internal representation."
8544 (if org-table-use-standard-references
8545 (org-table-convert-refs-to-rc s)
8548 (defun org-table-convert-refs-to-rc (s)
8549 "Convert spreadsheet references from AB7 to @7$28.
8550 Works for single references, but also for entire formulas and even the
8551 full TBLFM line."
8552 (let ((start 0))
8553 (while (string-match "\\<\\([a-zA-Z]+\\)\\([0-9]+\\>\\|&\\)\\|\\(;[^\r\n:]+\\)" s start)
8554 (if (match-end 3)
8555 ;; format match, just advance
8556 (setq start (match-end 0))
8557 (setq start (match-beginning 0)
8558 s (replace-match
8559 (if (equal (match-string 2 s) "&")
8560 (format "$%d" (org-letters-to-number (match-string 1 s)))
8561 (format "@%d$%d"
8562 (string-to-number (match-string 2 s))
8563 (org-letters-to-number (match-string 1 s))))
8564 t t s))))
8567 (defun org-table-convert-refs-to-an (s)
8568 "Convert spreadsheet references from to @7$28 to AB7.
8569 Works for single references, but also for entire formulas and even the
8570 full TBLFM line."
8571 (while (string-match "@\\([0-9]+\\)$\\([0-9]+\\)" s)
8572 (setq s (replace-match
8573 (format "%s%d"
8574 (org-number-to-letters
8575 (string-to-number (match-string 2 s)))
8576 (string-to-number (match-string 1 s)))
8577 t t s)))
8578 (while (string-match "\\(^\\|[^0-9a-zA-Z]\\)\\$\\([0-9]+\\)" s)
8579 (setq s (replace-match (concat "\\1"
8580 (org-number-to-letters
8581 (string-to-number (match-string 2 s))) "&")
8582 t nil s)))
8585 (defun org-letters-to-number (s)
8586 "Convert a base 26 number represented by letters into an integer.
8587 For example: AB -> 28."
8588 (let ((n 0))
8589 (setq s (upcase s))
8590 (while (> (length s) 0)
8591 (setq n (+ (* n 26) (string-to-char s) (- ?A) 1)
8592 s (substring s 1)))
8595 (defun org-number-to-letters (n)
8596 "Convert an integer into a base 26 number represented by letters.
8597 For example: 28 -> AB."
8598 (let ((s ""))
8599 (while (> n 0)
8600 (setq s (concat (char-to-string (+ (mod (1- n) 26) ?A)) s)
8601 n (/ (1- n) 26)))
8604 (defun org-table-fedit-convert-buffer (function)
8605 "Convert all references in this buffer, using FUNTION."
8606 (let ((line (org-current-line)))
8607 (goto-char (point-min))
8608 (while (not (eobp))
8609 (insert (funcall function (buffer-substring (point) (point-at-eol))))
8610 (delete-region (point) (point-at-eol))
8611 (or (eobp) (forward-char 1)))
8612 (goto-line line)))
8614 (defun org-table-fedit-toggle-ref-type ()
8615 "Convert all references in the buffer from B3 to @3$2 and back."
8616 (interactive)
8617 (org-set-local 'org-table-buffer-is-an (not org-table-buffer-is-an))
8618 (org-table-fedit-convert-buffer
8619 (if org-table-buffer-is-an
8620 'org-table-convert-refs-to-an 'org-table-convert-refs-to-rc))
8621 (message "Reference type switched to %s"
8622 (if org-table-buffer-is-an "A1 etc" "@row$column")))
8624 (defun org-table-fedit-ref-up ()
8625 "Shift the reference at point one row/hline up."
8626 (interactive)
8627 (org-table-fedit-shift-reference 'up))
8628 (defun org-table-fedit-ref-down ()
8629 "Shift the reference at point one row/hline down."
8630 (interactive)
8631 (org-table-fedit-shift-reference 'down))
8632 (defun org-table-fedit-ref-left ()
8633 "Shift the reference at point one field to the left."
8634 (interactive)
8635 (org-table-fedit-shift-reference 'left))
8636 (defun org-table-fedit-ref-right ()
8637 "Shift the reference at point one field to the right."
8638 (interactive)
8639 (org-table-fedit-shift-reference 'right))
8641 (defun org-table-fedit-shift-reference (dir)
8642 (cond
8643 ((org-at-regexp-p "\\(\\<[a-zA-Z]\\)&")
8644 (if (memq dir '(left right))
8645 (org-rematch-and-replace 1 (eq dir 'left))
8646 (error "Cannot shift reference in this direction")))
8647 ((org-at-regexp-p "\\(\\<[a-zA-Z]\\{1,2\\}\\)\\([0-9]+\\)")
8648 ;; A B3-like reference
8649 (if (memq dir '(up down))
8650 (org-rematch-and-replace 2 (eq dir 'up))
8651 (org-rematch-and-replace 1 (eq dir 'left))))
8652 ((org-at-regexp-p
8653 "\\(@\\|\\.\\.\\)\\([-+]?\\(I+\\>\\|[0-9]+\\)\\)\\(\\$\\([-+]?[0-9]+\\)\\)?")
8654 ;; An internal reference
8655 (if (memq dir '(up down))
8656 (org-rematch-and-replace 2 (eq dir 'up) (match-end 3))
8657 (org-rematch-and-replace 5 (eq dir 'left))))))
8659 (defun org-rematch-and-replace (n &optional decr hline)
8660 "Re-match the group N, and replace it with the shifted refrence."
8661 (or (match-end n) (error "Cannot shift reference in this direction"))
8662 (goto-char (match-beginning n))
8663 (and (looking-at (regexp-quote (match-string n)))
8664 (replace-match (org-shift-refpart (match-string 0) decr hline)
8665 t t)))
8667 (defun org-shift-refpart (ref &optional decr hline)
8668 "Shift a refrence part REF.
8669 If DECR is set, decrease the references row/column, else increase.
8670 If HLINE is set, this may be a hline reference, it certainly is not
8671 a translation reference."
8672 (save-match-data
8673 (let* ((sign (string-match "^[-+]" ref)) n)
8675 (if sign (setq sign (substring ref 0 1) ref (substring ref 1)))
8676 (cond
8677 ((and hline (string-match "^I+" ref))
8678 (setq n (string-to-number (concat sign (number-to-string (length ref)))))
8679 (setq n (+ n (if decr -1 1)))
8680 (if (= n 0) (setq n (+ n (if decr -1 1))))
8681 (if sign
8682 (setq sign (if (< n 0) "-" "+") n (abs n))
8683 (setq n (max 1 n)))
8684 (concat sign (make-string n ?I)))
8686 ((string-match "^[0-9]+" ref)
8687 (setq n (string-to-number (concat sign ref)))
8688 (setq n (+ n (if decr -1 1)))
8689 (if sign
8690 (concat (if (< n 0) "-" "+") (number-to-string (abs n)))
8691 (number-to-string (max 1 n))))
8693 ((string-match "^[a-zA-Z]+" ref)
8694 (org-number-to-letters
8695 (max 1 (+ (org-letters-to-number ref) (if decr -1 1)))))
8697 (t (error "Cannot shift reference"))))))
8699 (defun org-table-fedit-toggle-coordinates ()
8700 "Toggle the display of coordinates in the refrenced table."
8701 (interactive)
8702 (let ((pos (marker-position org-pos)))
8703 (with-current-buffer (marker-buffer org-pos)
8704 (save-excursion
8705 (goto-char pos)
8706 (org-table-toggle-coordinate-overlays)))))
8708 (defun org-table-fedit-finish (&optional arg)
8709 "Parse the buffer for formula definitions and install them.
8710 With prefix ARG, apply the new formulas to the table."
8711 (interactive "P")
8712 (org-table-remove-rectangle-highlight)
8713 (if org-table-use-standard-references
8714 (progn
8715 (org-table-fedit-convert-buffer 'org-table-convert-refs-to-rc)
8716 (setq org-table-buffer-is-an nil)))
8717 (let ((pos org-pos) eql var form)
8718 (goto-char (point-min))
8719 (while (re-search-forward
8720 "^\\(@[0-9]+\\$[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*\\(\n[ \t]+.*$\\)*\\)"
8721 nil t)
8722 (setq var (if (match-end 2) (match-string 2) (match-string 1))
8723 form (match-string 3))
8724 (setq form (org-trim form))
8725 (when (not (equal form ""))
8726 (while (string-match "[ \t]*\n[ \t]*" form)
8727 (setq form (replace-match " " t t form)))
8728 (when (assoc var eql)
8729 (error "Double formulas for %s" var))
8730 (push (cons var form) eql)))
8731 (setq org-pos nil)
8732 (set-window-configuration org-window-configuration)
8733 (select-window (get-buffer-window (marker-buffer pos)))
8734 (goto-char pos)
8735 (unless (org-at-table-p)
8736 (error "Lost table position - cannot install formulae"))
8737 (org-table-store-formulas eql)
8738 (move-marker pos nil)
8739 (kill-buffer "*Edit Formulas*")
8740 (if arg
8741 (org-table-recalculate 'all)
8742 (message "New formulas installed - press C-u C-c C-c to apply."))))
8744 (defun org-table-fedit-abort ()
8745 "Abort editing formulas, without installing the changes."
8746 (interactive)
8747 (org-table-remove-rectangle-highlight)
8748 (let ((pos org-pos))
8749 (set-window-configuration org-window-configuration)
8750 (select-window (get-buffer-window (marker-buffer pos)))
8751 (goto-char pos)
8752 (move-marker pos nil)
8753 (message "Formula editing aborted without installing changes")))
8755 (defun org-table-fedit-lisp-indent ()
8756 "Pretty-print and re-indent Lisp expressions in the Formula Editor."
8757 (interactive)
8758 (let ((pos (point)) beg end ind)
8759 (beginning-of-line 1)
8760 (cond
8761 ((looking-at "[ \t]")
8762 (goto-char pos)
8763 (call-interactively 'lisp-indent-line))
8764 ((looking-at "[$@0-9a-zA-Z]+ *= *[^ \t\n']") (goto-char pos))
8765 ((not (fboundp 'pp-buffer))
8766 (error "Cannot pretty-print. Command `pp-buffer' is not available."))
8767 ((looking-at "[$@0-9a-zA-Z]+ *= *'(")
8768 (goto-char (- (match-end 0) 2))
8769 (setq beg (point))
8770 (setq ind (make-string (current-column) ?\ ))
8771 (condition-case nil (forward-sexp 1)
8772 (error
8773 (error "Cannot pretty-print Lisp expression: Unbalanced parenthesis")))
8774 (setq end (point))
8775 (save-restriction
8776 (narrow-to-region beg end)
8777 (if (eq last-command this-command)
8778 (progn
8779 (goto-char (point-min))
8780 (setq this-command nil)
8781 (while (re-search-forward "[ \t]*\n[ \t]*" nil t)
8782 (replace-match " ")))
8783 (pp-buffer)
8784 (untabify (point-min) (point-max))
8785 (goto-char (1+ (point-min)))
8786 (while (re-search-forward "^." nil t)
8787 (beginning-of-line 1)
8788 (insert ind))
8789 (goto-char (point-max))
8790 (backward-delete-char 1)))
8791 (goto-char beg))
8792 (t nil))))
8794 (defvar org-show-positions nil)
8796 (defun org-table-show-reference (&optional local)
8797 "Show the location/value of the $ expression at point."
8798 (interactive)
8799 (org-table-remove-rectangle-highlight)
8800 (catch 'exit
8801 (let ((pos (if local (point) org-pos))
8802 (face2 'highlight)
8803 (org-inhibit-highlight-removal t)
8804 (win (selected-window))
8805 (org-show-positions nil)
8806 var name e what match dest)
8807 (if local (org-table-get-specials))
8808 (setq what (cond
8809 ((or (org-at-regexp-p org-table-range-regexp2)
8810 (org-at-regexp-p org-table-translate-regexp)
8811 (org-at-regexp-p org-table-range-regexp))
8812 (setq match
8813 (save-match-data
8814 (org-table-convert-refs-to-rc (match-string 0))))
8815 'range)
8816 ((org-at-regexp-p "\\$[a-zA-Z][a-zA-Z0-9]*") 'name)
8817 ((org-at-regexp-p "\\$[0-9]+") 'column)
8818 ((not local) nil)
8819 (t (error "No reference at point")))
8820 match (and what (or match (match-string 0))))
8821 (when (and match (not (equal (match-beginning 0) (point-at-bol))))
8822 (org-table-add-rectangle-overlay (match-beginning 0) (match-end 0)
8823 'secondary-selection))
8824 (org-add-hook 'before-change-functions
8825 'org-table-remove-rectangle-highlight)
8826 (if (eq what 'name) (setq var (substring match 1)))
8827 (when (eq what 'range)
8828 (or (equal (string-to-char match) ?@) (setq match (concat "@" match)))
8829 (setq match (org-table-formula-substitute-names match)))
8830 (unless local
8831 (save-excursion
8832 (end-of-line 1)
8833 (re-search-backward "^\\S-" nil t)
8834 (beginning-of-line 1)
8835 (when (looking-at "\\(\\$[0-9a-zA-Z]+\\|@[0-9]+\\$[0-9]+\\|[a-zA-Z]+\\([0-9]+\\|&\\)\\) *=")
8836 (setq dest
8837 (save-match-data
8838 (org-table-convert-refs-to-rc (match-string 1))))
8839 (org-table-add-rectangle-overlay
8840 (match-beginning 1) (match-end 1) face2))))
8841 (if (and (markerp pos) (marker-buffer pos))
8842 (if (get-buffer-window (marker-buffer pos))
8843 (select-window (get-buffer-window (marker-buffer pos)))
8844 (switch-to-buffer-other-window (get-buffer-window
8845 (marker-buffer pos)))))
8846 (goto-char pos)
8847 (org-table-force-dataline)
8848 (when dest
8849 (setq name (substring dest 1))
8850 (cond
8851 ((string-match "^\\$[a-zA-Z][a-zA-Z0-9]*" dest)
8852 (setq e (assoc name org-table-named-field-locations))
8853 (goto-line (nth 1 e))
8854 (org-table-goto-column (nth 2 e)))
8855 ((string-match "^@\\([0-9]+\\)\\$\\([0-9]+\\)" dest)
8856 (let ((l (string-to-number (match-string 1 dest)))
8857 (c (string-to-number (match-string 2 dest))))
8858 (goto-line (aref org-table-dlines l))
8859 (org-table-goto-column c)))
8860 (t (org-table-goto-column (string-to-number name))))
8861 (move-marker pos (point))
8862 (org-table-highlight-rectangle nil nil face2))
8863 (cond
8864 ((equal dest match))
8865 ((not match))
8866 ((eq what 'range)
8867 (condition-case nil
8868 (save-excursion
8869 (org-table-get-range match nil nil 'highlight))
8870 (error nil)))
8871 ((setq e (assoc var org-table-named-field-locations))
8872 (goto-line (nth 1 e))
8873 (org-table-goto-column (nth 2 e))
8874 (org-table-highlight-rectangle (point) (point))
8875 (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e)))
8876 ((setq e (assoc var org-table-column-names))
8877 (org-table-goto-column (string-to-number (cdr e)))
8878 (org-table-highlight-rectangle (point) (point))
8879 (goto-char (org-table-begin))
8880 (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|")
8881 (org-table-end) t)
8882 (progn
8883 (goto-char (match-beginning 1))
8884 (org-table-highlight-rectangle)
8885 (message "Named column (column %s)" (cdr e)))
8886 (error "Column name not found")))
8887 ((eq what 'column)
8888 ;; column number
8889 (org-table-goto-column (string-to-number (substring match 1)))
8890 (org-table-highlight-rectangle (point) (point))
8891 (message "Column %s" (substring match 1)))
8892 ((setq e (assoc var org-table-local-parameters))
8893 (goto-char (org-table-begin))
8894 (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") nil t)
8895 (progn
8896 (goto-char (match-beginning 1))
8897 (org-table-highlight-rectangle)
8898 (message "Local parameter."))
8899 (error "Parameter not found")))
8901 (cond
8902 ((not var) (error "No reference at point"))
8903 ((setq e (assoc var org-table-formula-constants))
8904 (message "Constant: $%s=%s in `org-table-formula-constants'."
8905 var (cdr e)))
8906 ((setq e (and (fboundp 'constants-get) (constants-get var)))
8907 (message "Constant: $%s=%s, from `constants.el'%s."
8908 var e (format " (%s units)" constants-unit-system)))
8909 (t (error "Undefined name $%s" var)))))
8910 (goto-char pos)
8911 (when (and org-show-positions
8912 (not (memq this-command '(org-table-fedit-scroll
8913 org-table-fedit-scroll-down))))
8914 (push pos org-show-positions)
8915 (push org-table-current-begin-pos org-show-positions)
8916 (let ((min (apply 'min org-show-positions))
8917 (max (apply 'max org-show-positions)))
8918 (goto-char min) (recenter 0)
8919 (goto-char max)
8920 (or (pos-visible-in-window-p max) (recenter -1))))
8921 (select-window win))))
8923 (defun org-table-force-dataline ()
8924 "Make sure the cursor is in a dataline in a table."
8925 (unless (save-excursion
8926 (beginning-of-line 1)
8927 (looking-at org-table-dataline-regexp))
8928 (let* ((re org-table-dataline-regexp)
8929 (p1 (save-excursion (re-search-forward re nil 'move)))
8930 (p2 (save-excursion (re-search-backward re nil 'move))))
8931 (cond ((and p1 p2)
8932 (goto-char (if (< (abs (- p1 (point))) (abs (- p2 (point))))
8933 p1 p2)))
8934 ((or p1 p2) (goto-char (or p1 p2)))
8935 (t (error "No table dataline around here"))))))
8937 (defun org-table-fedit-line-up ()
8938 "Move cursor one line up in the window showing the table."
8939 (interactive)
8940 (org-table-fedit-move 'previous-line))
8942 (defun org-table-fedit-line-down ()
8943 "Move cursor one line down in the window showing the table."
8944 (interactive)
8945 (org-table-fedit-move 'next-line))
8947 (defun org-table-fedit-move (command)
8948 "Move the cursor in the window shoinw the table.
8949 Use COMMAND to do the motion, repeat if necessary to end up in a data line."
8950 (let ((org-table-allow-automatic-line-recalculation nil)
8951 (pos org-pos) (win (selected-window)) p)
8952 (select-window (get-buffer-window (marker-buffer org-pos)))
8953 (setq p (point))
8954 (call-interactively command)
8955 (while (and (org-at-table-p)
8956 (org-at-table-hline-p))
8957 (call-interactively command))
8958 (or (org-at-table-p) (goto-char p))
8959 (move-marker pos (point))
8960 (select-window win)))
8962 (defun org-table-fedit-scroll (N)
8963 (interactive "p")
8964 (let ((other-window-scroll-buffer (marker-buffer org-pos)))
8965 (scroll-other-window N)))
8967 (defun org-table-fedit-scroll-down (N)
8968 (interactive "p")
8969 (org-table-fedit-scroll (- N)))
8971 (defvar org-table-rectangle-overlays nil)
8973 (defun org-table-add-rectangle-overlay (beg end &optional face)
8974 "Add a new overlay."
8975 (let ((ov (org-make-overlay beg end)))
8976 (org-overlay-put ov 'face (or face 'secondary-selection))
8977 (push ov org-table-rectangle-overlays)))
8979 (defun org-table-highlight-rectangle (&optional beg end face)
8980 "Highlight rectangular region in a table."
8981 (setq beg (or beg (point)) end (or end (point)))
8982 (let ((b (min beg end))
8983 (e (max beg end))
8984 l1 c1 l2 c2 tmp)
8985 (and (boundp 'org-show-positions)
8986 (setq org-show-positions (cons b (cons e org-show-positions))))
8987 (goto-char (min beg end))
8988 (setq l1 (org-current-line)
8989 c1 (org-table-current-column))
8990 (goto-char (max beg end))
8991 (setq l2 (org-current-line)
8992 c2 (org-table-current-column))
8993 (if (> c1 c2) (setq tmp c1 c1 c2 c2 tmp))
8994 (goto-line l1)
8995 (beginning-of-line 1)
8996 (loop for line from l1 to l2 do
8997 (when (looking-at org-table-dataline-regexp)
8998 (org-table-goto-column c1)
8999 (skip-chars-backward "^|\n") (setq beg (point))
9000 (org-table-goto-column c2)
9001 (skip-chars-forward "^|\n") (setq end (point))
9002 (org-table-add-rectangle-overlay beg end face))
9003 (beginning-of-line 2))
9004 (goto-char b))
9005 (add-hook 'before-change-functions 'org-table-remove-rectangle-highlight))
9007 (defun org-table-remove-rectangle-highlight (&rest ignore)
9008 "Remove the rectangle overlays."
9009 (unless org-inhibit-highlight-removal
9010 (remove-hook 'before-change-functions 'org-table-remove-rectangle-highlight)
9011 (mapc 'org-delete-overlay org-table-rectangle-overlays)
9012 (setq org-table-rectangle-overlays nil)))
9014 (defvar org-table-coordinate-overlays nil
9015 "Collects the cooordinate grid overlays, so that they can be removed.")
9016 (make-variable-buffer-local 'org-table-coordinate-overlays)
9018 (defun org-table-overlay-coordinates ()
9019 "Add overlays to the table at point, to show row/column coordinates."
9020 (interactive)
9021 (mapc 'org-delete-overlay org-table-coordinate-overlays)
9022 (setq org-table-coordinate-overlays nil)
9023 (save-excursion
9024 (let ((id 0) (ih 0) hline eol s1 s2 str ic ov beg)
9025 (goto-char (org-table-begin))
9026 (while (org-at-table-p)
9027 (setq eol (point-at-eol))
9028 (setq ov (org-make-overlay (point-at-bol) (1+ (point-at-bol))))
9029 (push ov org-table-coordinate-overlays)
9030 (setq hline (looking-at org-table-hline-regexp))
9031 (setq str (if hline (format "I*%-2d" (setq ih (1+ ih)))
9032 (format "%4d" (setq id (1+ id)))))
9033 (org-overlay-before-string ov str 'org-special-keyword 'evaporate)
9034 (when hline
9035 (setq ic 0)
9036 (while (re-search-forward "[+|]\\(-+\\)" eol t)
9037 (setq beg (1+ (match-beginning 0))
9038 ic (1+ ic)
9039 s1 (concat "$" (int-to-string ic))
9040 s2 (org-number-to-letters ic)
9041 str (if org-table-use-standard-references s2 s1))
9042 (setq ov (org-make-overlay beg (+ beg (length str))))
9043 (push ov org-table-coordinate-overlays)
9044 (org-overlay-display ov str 'org-special-keyword 'evaporate)))
9045 (beginning-of-line 2)))))
9047 (defun org-table-toggle-coordinate-overlays ()
9048 "Toggle the display of Row/Column numbers in tables."
9049 (interactive)
9050 (setq org-table-overlay-coordinates (not org-table-overlay-coordinates))
9051 (message "Row/Column number display turned %s"
9052 (if org-table-overlay-coordinates "on" "off"))
9053 (if (and (org-at-table-p) org-table-overlay-coordinates)
9054 (org-table-align))
9055 (unless org-table-overlay-coordinates
9056 (mapc 'org-delete-overlay org-table-coordinate-overlays)
9057 (setq org-table-coordinate-overlays nil)))
9059 (defun org-table-toggle-formula-debugger ()
9060 "Toggle the formula debugger in tables."
9061 (interactive)
9062 (setq org-table-formula-debug (not org-table-formula-debug))
9063 (message "Formula debugging has been turned %s"
9064 (if org-table-formula-debug "on" "off")))
9066 ;;; The orgtbl minor mode
9068 ;; Define a minor mode which can be used in other modes in order to
9069 ;; integrate the org-mode table editor.
9071 ;; This is really a hack, because the org-mode table editor uses several
9072 ;; keys which normally belong to the major mode, for example the TAB and
9073 ;; RET keys. Here is how it works: The minor mode defines all the keys
9074 ;; necessary to operate the table editor, but wraps the commands into a
9075 ;; function which tests if the cursor is currently inside a table. If that
9076 ;; is the case, the table editor command is executed. However, when any of
9077 ;; those keys is used outside a table, the function uses `key-binding' to
9078 ;; look up if the key has an associated command in another currently active
9079 ;; keymap (minor modes, major mode, global), and executes that command.
9080 ;; There might be problems if any of the keys used by the table editor is
9081 ;; otherwise used as a prefix key.
9083 ;; Another challenge is that the key binding for TAB can be tab or \C-i,
9084 ;; likewise the binding for RET can be return or \C-m. Orgtbl-mode
9085 ;; addresses this by checking explicitly for both bindings.
9087 ;; The optimized version (see variable `orgtbl-optimized') takes over
9088 ;; all keys which are bound to `self-insert-command' in the *global map*.
9089 ;; Some modes bind other commands to simple characters, for example
9090 ;; AUCTeX binds the double quote to `Tex-insert-quote'. With orgtbl-mode
9091 ;; active, this binding is ignored inside tables and replaced with a
9092 ;; modified self-insert.
9094 (defvar orgtbl-mode nil
9095 "Variable controlling `orgtbl-mode', a minor mode enabling the `org-mode'
9096 table editor in arbitrary modes.")
9097 (make-variable-buffer-local 'orgtbl-mode)
9099 (defvar orgtbl-mode-map (make-keymap)
9100 "Keymap for `orgtbl-mode'.")
9102 ;;;###autoload
9103 (defun turn-on-orgtbl ()
9104 "Unconditionally turn on `orgtbl-mode'."
9105 (orgtbl-mode 1))
9107 (defvar org-old-auto-fill-inhibit-regexp nil
9108 "Local variable used by `orgtbl-mode'")
9110 (defconst orgtbl-line-start-regexp "[ \t]*\\(|\\|#\\+\\(TBLFM\\|ORGTBL\\):\\)"
9111 "Matches a line belonging to an orgtbl.")
9113 (defconst orgtbl-extra-font-lock-keywords
9114 (list (list (concat "^" orgtbl-line-start-regexp ".*")
9115 0 (quote 'org-table) 'prepend))
9116 "Extra font-lock-keywords to be added when orgtbl-mode is active.")
9118 ;;;###autoload
9119 (defun orgtbl-mode (&optional arg)
9120 "The `org-mode' table editor as a minor mode for use in other modes."
9121 (interactive)
9122 (if (org-mode-p)
9123 ;; Exit without error, in case some hook functions calls this
9124 ;; by accident in org-mode.
9125 (message "Orgtbl-mode is not useful in org-mode, command ignored")
9126 (setq orgtbl-mode
9127 (if arg (> (prefix-numeric-value arg) 0) (not orgtbl-mode)))
9128 (if orgtbl-mode
9129 (progn
9130 (and (orgtbl-setup) (defun orgtbl-setup () nil))
9131 ;; Make sure we are first in minor-mode-map-alist
9132 (let ((c (assq 'orgtbl-mode minor-mode-map-alist)))
9133 (and c (setq minor-mode-map-alist
9134 (cons c (delq c minor-mode-map-alist)))))
9135 (org-set-local (quote org-table-may-need-update) t)
9136 (org-add-hook 'before-change-functions 'org-before-change-function
9137 nil 'local)
9138 (org-set-local 'org-old-auto-fill-inhibit-regexp
9139 auto-fill-inhibit-regexp)
9140 (org-set-local 'auto-fill-inhibit-regexp
9141 (if auto-fill-inhibit-regexp
9142 (concat orgtbl-line-start-regexp "\\|"
9143 auto-fill-inhibit-regexp)
9144 orgtbl-line-start-regexp))
9145 (org-add-to-invisibility-spec '(org-cwidth))
9146 (when (fboundp 'font-lock-add-keywords)
9147 (font-lock-add-keywords nil orgtbl-extra-font-lock-keywords)
9148 (org-restart-font-lock))
9149 (easy-menu-add orgtbl-mode-menu)
9150 (run-hooks 'orgtbl-mode-hook))
9151 (setq auto-fill-inhibit-regexp org-old-auto-fill-inhibit-regexp)
9152 (org-cleanup-narrow-column-properties)
9153 (org-remove-from-invisibility-spec '(org-cwidth))
9154 (remove-hook 'before-change-functions 'org-before-change-function t)
9155 (when (fboundp 'font-lock-remove-keywords)
9156 (font-lock-remove-keywords nil orgtbl-extra-font-lock-keywords)
9157 (org-restart-font-lock))
9158 (easy-menu-remove orgtbl-mode-menu)
9159 (force-mode-line-update 'all))))
9161 (defun org-cleanup-narrow-column-properties ()
9162 "Remove all properties related to narrow-column invisibility."
9163 (let ((s 1))
9164 (while (setq s (text-property-any s (point-max)
9165 'display org-narrow-column-arrow))
9166 (remove-text-properties s (1+ s) '(display t)))
9167 (setq s 1)
9168 (while (setq s (text-property-any s (point-max) 'org-cwidth 1))
9169 (remove-text-properties s (1+ s) '(org-cwidth t)))
9170 (setq s 1)
9171 (while (setq s (text-property-any s (point-max) 'invisible 'org-cwidth))
9172 (remove-text-properties s (1+ s) '(invisible t)))))
9174 ;; Install it as a minor mode.
9175 (put 'orgtbl-mode :included t)
9176 (put 'orgtbl-mode :menu-tag "Org Table Mode")
9177 (add-minor-mode 'orgtbl-mode " OrgTbl" orgtbl-mode-map)
9179 (defun orgtbl-make-binding (fun n &rest keys)
9180 "Create a function for binding in the table minor mode.
9181 FUN is the command to call inside a table. N is used to create a unique
9182 command name. KEYS are keys that should be checked in for a command
9183 to execute outside of tables."
9184 (eval
9185 (list 'defun
9186 (intern (concat "orgtbl-hijacker-command-" (int-to-string n)))
9187 '(arg)
9188 (concat "In tables, run `" (symbol-name fun) "'.\n"
9189 "Outside of tables, run the binding of `"
9190 (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
9191 "'.")
9192 '(interactive "p")
9193 (list 'if
9194 '(org-at-table-p)
9195 (list 'call-interactively (list 'quote fun))
9196 (list 'let '(orgtbl-mode)
9197 (list 'call-interactively
9198 (append '(or)
9199 (mapcar (lambda (k)
9200 (list 'key-binding k))
9201 keys)
9202 '('orgtbl-error))))))))
9204 (defun orgtbl-error ()
9205 "Error when there is no default binding for a table key."
9206 (interactive)
9207 (error "This key is has no function outside tables"))
9209 (defun orgtbl-setup ()
9210 "Setup orgtbl keymaps."
9211 (let ((nfunc 0)
9212 (bindings
9213 (list
9214 '([(meta shift left)] org-table-delete-column)
9215 '([(meta left)] org-table-move-column-left)
9216 '([(meta right)] org-table-move-column-right)
9217 '([(meta shift right)] org-table-insert-column)
9218 '([(meta shift up)] org-table-kill-row)
9219 '([(meta shift down)] org-table-insert-row)
9220 '([(meta up)] org-table-move-row-up)
9221 '([(meta down)] org-table-move-row-down)
9222 '("\C-c\C-w" org-table-cut-region)
9223 '("\C-c\M-w" org-table-copy-region)
9224 '("\C-c\C-y" org-table-paste-rectangle)
9225 '("\C-c-" org-table-insert-hline)
9226 '("\C-c}" org-table-toggle-coordinate-overlays)
9227 '("\C-c{" org-table-toggle-formula-debugger)
9228 '("\C-m" org-table-next-row)
9229 '([(shift return)] org-table-copy-down)
9230 '("\C-c\C-q" org-table-wrap-region)
9231 '("\C-c?" org-table-field-info)
9232 '("\C-c " org-table-blank-field)
9233 '("\C-c+" org-table-sum)
9234 '("\C-c=" org-table-eval-formula)
9235 '("\C-c'" org-table-edit-formulas)
9236 '("\C-c`" org-table-edit-field)
9237 '("\C-c*" org-table-recalculate)
9238 '("\C-c|" org-table-create-or-convert-from-region)
9239 '("\C-c^" org-table-sort-lines)
9240 '([(control ?#)] org-table-rotate-recalc-marks)))
9241 elt key fun cmd)
9242 (while (setq elt (pop bindings))
9243 (setq nfunc (1+ nfunc))
9244 (setq key (org-key (car elt))
9245 fun (nth 1 elt)
9246 cmd (orgtbl-make-binding fun nfunc key))
9247 (org-defkey orgtbl-mode-map key cmd))
9249 ;; Special treatment needed for TAB and RET
9250 (org-defkey orgtbl-mode-map [(return)]
9251 (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m"))
9252 (org-defkey orgtbl-mode-map "\C-m"
9253 (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)]))
9255 (org-defkey orgtbl-mode-map [(tab)]
9256 (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i"))
9257 (org-defkey orgtbl-mode-map "\C-i"
9258 (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)]))
9260 (org-defkey orgtbl-mode-map [(shift tab)]
9261 (orgtbl-make-binding 'org-table-previous-field 104
9262 [(shift tab)] [(tab)] "\C-i"))
9264 (org-defkey orgtbl-mode-map "\M-\C-m"
9265 (orgtbl-make-binding 'org-table-wrap-region 105
9266 "\M-\C-m" [(meta return)]))
9267 (org-defkey orgtbl-mode-map [(meta return)]
9268 (orgtbl-make-binding 'org-table-wrap-region 106
9269 [(meta return)] "\M-\C-m"))
9271 (org-defkey orgtbl-mode-map "\C-c\C-c" 'orgtbl-ctrl-c-ctrl-c)
9272 (when orgtbl-optimized
9273 ;; If the user wants maximum table support, we need to hijack
9274 ;; some standard editing functions
9275 (org-remap orgtbl-mode-map
9276 'self-insert-command 'orgtbl-self-insert-command
9277 'delete-char 'org-delete-char
9278 'delete-backward-char 'org-delete-backward-char)
9279 (org-defkey orgtbl-mode-map "|" 'org-force-self-insert))
9280 (easy-menu-define orgtbl-mode-menu orgtbl-mode-map "OrgTbl menu"
9281 '("OrgTbl"
9282 ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p) :keys "C-c C-c"]
9283 ["Next Field" org-cycle :active (org-at-table-p) :keys "TAB"]
9284 ["Previous Field" org-shifttab :active (org-at-table-p) :keys "S-TAB"]
9285 ["Next Row" org-return :active (org-at-table-p) :keys "RET"]
9286 "--"
9287 ["Blank Field" org-table-blank-field :active (org-at-table-p) :keys "C-c SPC"]
9288 ["Edit Field" org-table-edit-field :active (org-at-table-p) :keys "C-c ` "]
9289 ["Copy Field from Above"
9290 org-table-copy-down :active (org-at-table-p) :keys "S-RET"]
9291 "--"
9292 ("Column"
9293 ["Move Column Left" org-metaleft :active (org-at-table-p) :keys "M-<left>"]
9294 ["Move Column Right" org-metaright :active (org-at-table-p) :keys "M-<right>"]
9295 ["Delete Column" org-shiftmetaleft :active (org-at-table-p) :keys "M-S-<left>"]
9296 ["Insert Column" org-shiftmetaright :active (org-at-table-p) :keys "M-S-<right>"])
9297 ("Row"
9298 ["Move Row Up" org-metaup :active (org-at-table-p) :keys "M-<up>"]
9299 ["Move Row Down" org-metadown :active (org-at-table-p) :keys "M-<down>"]
9300 ["Delete Row" org-shiftmetaup :active (org-at-table-p) :keys "M-S-<up>"]
9301 ["Insert Row" org-shiftmetadown :active (org-at-table-p) :keys "M-S-<down>"]
9302 ["Sort lines in region" org-table-sort-lines (org-at-table-p) :keys "C-c ^"]
9303 "--"
9304 ["Insert Hline" org-table-insert-hline :active (org-at-table-p) :keys "C-c -"])
9305 ("Rectangle"
9306 ["Copy Rectangle" org-copy-special :active (org-at-table-p)]
9307 ["Cut Rectangle" org-cut-special :active (org-at-table-p)]
9308 ["Paste Rectangle" org-paste-special :active (org-at-table-p)]
9309 ["Fill Rectangle" org-table-wrap-region :active (org-at-table-p)])
9310 "--"
9311 ("Radio tables"
9312 ["Insert table template" orgtbl-insert-radio-table
9313 (assq major-mode orgtbl-radio-table-templates)]
9314 ["Comment/uncomment table" orgtbl-toggle-comment t])
9315 "--"
9316 ["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="]
9317 ["Set Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
9318 ["Edit Formulas" org-table-edit-formulas :active (org-at-table-p) :keys "C-c '"]
9319 ["Recalculate line" org-table-recalculate :active (org-at-table-p) :keys "C-c *"]
9320 ["Recalculate all" (org-table-recalculate '(4)) :active (org-at-table-p) :keys "C-u C-c *"]
9321 ["Iterate all" (org-table-recalculate '(16)) :active (org-at-table-p) :keys "C-u C-u C-c *"]
9322 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks :active (org-at-table-p) :keys "C-c #"]
9323 ["Sum Column/Rectangle" org-table-sum
9324 :active (or (org-at-table-p) (org-region-active-p)) :keys "C-c +"]
9325 ["Which Column?" org-table-current-column :active (org-at-table-p) :keys "C-c ?"]
9326 ["Debug Formulas"
9327 org-table-toggle-formula-debugger :active (org-at-table-p)
9328 :keys "C-c {"
9329 :style toggle :selected org-table-formula-debug]
9330 ["Show Col/Row Numbers"
9331 org-table-toggle-coordinate-overlays :active (org-at-table-p)
9332 :keys "C-c }"
9333 :style toggle :selected org-table-overlay-coordinates]
9337 (defun orgtbl-ctrl-c-ctrl-c (arg)
9338 "If the cursor is inside a table, realign the table.
9339 It it is a table to be sent away to a receiver, do it.
9340 With prefix arg, also recompute table."
9341 (interactive "P")
9342 (let ((pos (point)) action)
9343 (save-excursion
9344 (beginning-of-line 1)
9345 (setq action (cond ((looking-at "#\\+ORGTBL:.*\n[ \t]*|") (match-end 0))
9346 ((looking-at "[ \t]*|") pos)
9347 ((looking-at "#\\+TBLFM:") 'recalc))))
9348 (cond
9349 ((integerp action)
9350 (goto-char action)
9351 (org-table-maybe-eval-formula)
9352 (if arg
9353 (call-interactively 'org-table-recalculate)
9354 (org-table-maybe-recalculate-line))
9355 (call-interactively 'org-table-align)
9356 (orgtbl-send-table 'maybe))
9357 ((eq action 'recalc)
9358 (save-excursion
9359 (beginning-of-line 1)
9360 (skip-chars-backward " \r\n\t")
9361 (if (org-at-table-p)
9362 (org-call-with-arg 'org-table-recalculate t))))
9363 (t (let (orgtbl-mode)
9364 (call-interactively (key-binding "\C-c\C-c")))))))
9366 (defun orgtbl-tab (arg)
9367 "Justification and field motion for `orgtbl-mode'."
9368 (interactive "P")
9369 (if arg (org-table-edit-field t)
9370 (org-table-justify-field-maybe)
9371 (org-table-next-field)))
9373 (defun orgtbl-ret ()
9374 "Justification and field motion for `orgtbl-mode'."
9375 (interactive)
9376 (org-table-justify-field-maybe)
9377 (org-table-next-row))
9379 (defun orgtbl-self-insert-command (N)
9380 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
9381 If the cursor is in a table looking at whitespace, the whitespace is
9382 overwritten, and the table is not marked as requiring realignment."
9383 (interactive "p")
9384 (if (and (org-at-table-p)
9386 (and org-table-auto-blank-field
9387 (member last-command
9388 '(orgtbl-hijacker-command-100
9389 orgtbl-hijacker-command-101
9390 orgtbl-hijacker-command-102
9391 orgtbl-hijacker-command-103
9392 orgtbl-hijacker-command-104
9393 orgtbl-hijacker-command-105))
9394 (org-table-blank-field))
9396 (eq N 1)
9397 (looking-at "[^|\n]* +|"))
9398 (let (org-table-may-need-update)
9399 (goto-char (1- (match-end 0)))
9400 (delete-backward-char 1)
9401 (goto-char (match-beginning 0))
9402 (self-insert-command N))
9403 (setq org-table-may-need-update t)
9404 (let (orgtbl-mode)
9405 (call-interactively (key-binding (vector last-input-event))))))
9407 (defun org-force-self-insert (N)
9408 "Needed to enforce self-insert under remapping."
9409 (interactive "p")
9410 (self-insert-command N))
9412 (defvar orgtbl-exp-regexp "^\\([-+]?[0-9][0-9.]*\\)[eE]\\([-+]?[0-9]+\\)$"
9413 "Regula expression matching exponentials as produced by calc.")
9415 (defvar org-table-clean-did-remove-column-1 nil)
9417 (defun orgtbl-export (table target)
9418 (let ((func (intern (concat "orgtbl-to-" (symbol-name target))))
9419 (lines (org-split-string table "[ \t]*\n[ \t]*"))
9420 org-table-last-alignment org-table-last-column-widths
9421 maxcol column)
9422 (if (not (fboundp func))
9423 (error "Cannot export orgtbl table to %s" target))
9424 (setq lines (org-table-clean-before-export lines))
9425 (setq table
9426 (mapcar
9427 (lambda (x)
9428 (if (string-match org-table-hline-regexp x)
9429 'hline
9430 (org-split-string (org-trim x) "\\s-*|\\s-*")))
9431 lines))
9432 (setq maxcol (apply 'max (mapcar (lambda (x) (if (listp x) (length x) 0))
9433 table)))
9434 (loop for i from (1- maxcol) downto 0 do
9435 (setq column (mapcar (lambda (x) (if (listp x) (nth i x) nil)) table))
9436 (setq column (delq nil column))
9437 (push (apply 'max (mapcar 'string-width column)) org-table-last-column-widths)
9438 (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))
9439 (funcall func table nil)))
9441 (defun orgtbl-send-table (&optional maybe)
9442 "Send a tranformed version of this table to the receiver position.
9443 With argument MAYBE, fail quietly if no transformation is defined for
9444 this table."
9445 (interactive)
9446 (catch 'exit
9447 (unless (org-at-table-p) (error "Not at a table"))
9448 ;; when non-interactive, we assume align has just happened.
9449 (when (interactive-p) (org-table-align))
9450 (save-excursion
9451 (goto-char (org-table-begin))
9452 (beginning-of-line 0)
9453 (unless (looking-at "#\\+ORGTBL: *SEND +\\([a-zA-Z0-9_]+\\) +\\([^ \t\r\n]+\\)\\( +.*\\)?")
9454 (if maybe
9455 (throw 'exit nil)
9456 (error "Don't know how to transform this table."))))
9457 (let* ((name (match-string 1))
9459 (transform (intern (match-string 2)))
9460 (params (if (match-end 3) (read (concat "(" (match-string 3) ")"))))
9461 (skip (plist-get params :skip))
9462 (skipcols (plist-get params :skipcols))
9463 (txt (buffer-substring-no-properties
9464 (org-table-begin) (org-table-end)))
9465 (lines (nthcdr (or skip 0) (org-split-string txt "[ \t]*\n[ \t]*")))
9466 (lines (org-table-clean-before-export lines))
9467 (i0 (if org-table-clean-did-remove-column-1 2 1))
9468 (table (mapcar
9469 (lambda (x)
9470 (if (string-match org-table-hline-regexp x)
9471 'hline
9472 (org-remove-by-index
9473 (org-split-string (org-trim x) "\\s-*|\\s-*")
9474 skipcols i0)))
9475 lines))
9476 (fun (if (= i0 2) 'cdr 'identity))
9477 (org-table-last-alignment
9478 (org-remove-by-index (funcall fun org-table-last-alignment)
9479 skipcols i0))
9480 (org-table-last-column-widths
9481 (org-remove-by-index (funcall fun org-table-last-column-widths)
9482 skipcols i0)))
9484 (unless (fboundp transform)
9485 (error "No such transformation function %s" transform))
9486 (setq txt (funcall transform table params))
9487 ;; Find the insertion place
9488 (save-excursion
9489 (goto-char (point-min))
9490 (unless (re-search-forward
9491 (concat "BEGIN RECEIVE ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
9492 (error "Don't know where to insert translated table"))
9493 (goto-char (match-beginning 0))
9494 (beginning-of-line 2)
9495 (setq beg (point))
9496 (unless (re-search-forward (concat "END RECEIVE ORGTBL +" name) nil t)
9497 (error "Cannot find end of insertion region"))
9498 (beginning-of-line 1)
9499 (delete-region beg (point))
9500 (goto-char beg)
9501 (insert txt "\n"))
9502 (message "Table converted and installed at receiver location"))))
9504 (defun org-remove-by-index (list indices &optional i0)
9505 "Remove the elements in LIST with indices in INDICES.
9506 First element has index 0, or I0 if given."
9507 (if (not indices)
9508 list
9509 (if (integerp indices) (setq indices (list indices)))
9510 (setq i0 (1- (or i0 0)))
9511 (delq :rm (mapcar (lambda (x)
9512 (setq i0 (1+ i0))
9513 (if (memq i0 indices) :rm x))
9514 list))))
9516 (defun orgtbl-toggle-comment ()
9517 "Comment or uncomment the orgtbl at point."
9518 (interactive)
9519 (let* ((re1 (concat "^" (regexp-quote comment-start) orgtbl-line-start-regexp))
9520 (re2 (concat "^" orgtbl-line-start-regexp))
9521 (commented (save-excursion (beginning-of-line 1)
9522 (cond ((looking-at re1) t)
9523 ((looking-at re2) nil)
9524 (t (error "Not at an org table")))))
9525 (re (if commented re1 re2))
9526 beg end)
9527 (save-excursion
9528 (beginning-of-line 1)
9529 (while (looking-at re) (beginning-of-line 0))
9530 (beginning-of-line 2)
9531 (setq beg (point))
9532 (while (looking-at re) (beginning-of-line 2))
9533 (setq end (point)))
9534 (comment-region beg end (if commented '(4) nil))))
9536 (defun orgtbl-insert-radio-table ()
9537 "Insert a radio table template appropriate for this major mode."
9538 (interactive)
9539 (let* ((e (assq major-mode orgtbl-radio-table-templates))
9540 (txt (nth 1 e))
9541 name pos)
9542 (unless e (error "No radio table setup defined for %s" major-mode))
9543 (setq name (read-string "Table name: "))
9544 (while (string-match "%n" txt)
9545 (setq txt (replace-match name t t txt)))
9546 (or (bolp) (insert "\n"))
9547 (setq pos (point))
9548 (insert txt)
9549 (goto-char pos)))
9551 (defun org-get-param (params header i sym &optional hsym)
9552 "Get parameter value for symbol SYM.
9553 If this is a header line, actually get the value for the symbol with an
9554 additional \"h\" inserted after the colon.
9555 If the value is a protperty list, get the element for the current column.
9556 Assumes variables VAL, PARAMS, HEAD and I to be scoped into the function."
9557 (let ((val (plist-get params sym)))
9558 (and hsym header (setq val (or (plist-get params hsym) val)))
9559 (if (consp val) (plist-get val i) val)))
9561 (defun orgtbl-to-generic (table params)
9562 "Convert the orgtbl-mode TABLE to some other format.
9563 This generic routine can be used for many standard cases.
9564 TABLE is a list, each entry either the symbol `hline' for a horizontal
9565 separator line, or a list of fields for that line.
9566 PARAMS is a property list of parameters that can influence the conversion.
9567 For the generic converter, some parameters are obligatory: You need to
9568 specify either :lfmt, or all of (:lstart :lend :sep). If you do not use
9569 :splice, you must have :tstart and :tend.
9571 Valid parameters are
9573 :tstart String to start the table. Ignored when :splice is t.
9574 :tend String to end the table. Ignored when :splice is t.
9576 :splice When set to t, return only table body lines, don't wrap
9577 them into :tstart and :tend. Default is nil.
9579 :hline String to be inserted on horizontal separation lines.
9580 May be nil to ignore hlines.
9582 :lstart String to start a new table line.
9583 :lend String to end a table line
9584 :sep Separator between two fields
9585 :lfmt Format for entire line, with enough %s to capture all fields.
9586 If this is present, :lstart, :lend, and :sep are ignored.
9587 :fmt A format to be used to wrap the field, should contain
9588 %s for the original field value. For example, to wrap
9589 everything in dollars, you could use :fmt \"$%s$\".
9590 This may also be a property list with column numbers and
9591 formats. for example :fmt (2 \"$%s$\" 4 \"%s%%\")
9593 :hlstart :hlend :hlsep :hlfmt :hfmt
9594 Same as above, specific for the header lines in the table.
9595 All lines before the first hline are treated as header.
9596 If any of these is not present, the data line value is used.
9598 :efmt Use this format to print numbers with exponentials.
9599 The format should have %s twice for inserting mantissa
9600 and exponent, for example \"%s\\\\times10^{%s}\". This
9601 may also be a property list with column numbers and
9602 formats. :fmt will still be applied after :efmt.
9604 In addition to this, the parameters :skip and :skipcols are always handled
9605 directly by `orgtbl-send-table'. See manual."
9606 (interactive)
9607 (let* ((p params)
9608 (splicep (plist-get p :splice))
9609 (hline (plist-get p :hline))
9610 rtn line i fm efm lfmt h)
9612 ;; Do we have a header?
9613 (if (and (not splicep) (listp (car table)) (memq 'hline table))
9614 (setq h t))
9616 ;; Put header
9617 (unless splicep
9618 (push (or (plist-get p :tstart) "ERROR: no :tstart") rtn))
9620 ;; Now loop over all lines
9621 (while (setq line (pop table))
9622 (if (eq line 'hline)
9623 ;; A horizontal separator line
9624 (progn (if hline (push hline rtn))
9625 (setq h nil)) ; no longer in header
9626 ;; A normal line. Convert the fields, push line onto the result list
9627 (setq i 0)
9628 (setq line
9629 (mapcar
9630 (lambda (f)
9631 (setq i (1+ i)
9632 fm (org-get-param p h i :fmt :hfmt)
9633 efm (org-get-param p h i :efmt))
9634 (if (and efm (string-match orgtbl-exp-regexp f))
9635 (setq f (format
9636 efm (match-string 1 f) (match-string 2 f))))
9637 (if fm (setq f (format fm f)))
9639 line))
9640 (if (setq lfmt (org-get-param p h i :lfmt :hlfmt))
9641 (push (apply 'format lfmt line) rtn)
9642 (push (concat
9643 (org-get-param p h i :lstart :hlstart)
9644 (mapconcat 'identity line (org-get-param p h i :sep :hsep))
9645 (org-get-param p h i :lend :hlend))
9646 rtn))))
9648 (unless splicep
9649 (push (or (plist-get p :tend) "ERROR: no :tend") rtn))
9651 (mapconcat 'identity (nreverse rtn) "\n")))
9653 (defun orgtbl-to-latex (table params)
9654 "Convert the orgtbl-mode TABLE to LaTeX.
9655 TABLE is a list, each entry either the symbol `hline' for a horizontal
9656 separator line, or a list of fields for that line.
9657 PARAMS is a property list of parameters that can influence the conversion.
9658 Supports all parameters from `orgtbl-to-generic'. Most important for
9659 LaTeX are:
9661 :splice When set to t, return only table body lines, don't wrap
9662 them into a tabular environment. Default is nil.
9664 :fmt A format to be used to wrap the field, should contain %s for the
9665 original field value. For example, to wrap everything in dollars,
9666 use :fmt \"$%s$\". This may also be a property list with column
9667 numbers and formats. for example :fmt (2 \"$%s$\" 4 \"%s%%\")
9669 :efmt Format for transforming numbers with exponentials. The format
9670 should have %s twice for inserting mantissa and exponent, for
9671 example \"%s\\\\times10^{%s}\". LaTeX default is \"%s\\\\,(%s)\".
9672 This may also be a property list with column numbers and formats.
9674 The general parameters :skip and :skipcols have already been applied when
9675 this function is called."
9676 (let* ((alignment (mapconcat (lambda (x) (if x "r" "l"))
9677 org-table-last-alignment ""))
9678 (params2
9679 (list
9680 :tstart (concat "\\begin{tabular}{" alignment "}")
9681 :tend "\\end{tabular}"
9682 :lstart "" :lend " \\\\" :sep " & "
9683 :efmt "%s\\,(%s)" :hline "\\hline")))
9684 (orgtbl-to-generic table (org-combine-plists params2 params))))
9686 (defun orgtbl-to-html (table params)
9687 "Convert the orgtbl-mode TABLE to LaTeX.
9688 TABLE is a list, each entry either the symbol `hline' for a horizontal
9689 separator line, or a list of fields for that line.
9690 PARAMS is a property list of parameters that can influence the conversion.
9691 Currently this function recognizes the following parameters:
9693 :splice When set to t, return only table body lines, don't wrap
9694 them into a <table> environment. Default is nil.
9696 The general parameters :skip and :skipcols have already been applied when
9697 this function is called. The function does *not* use `orgtbl-to-generic',
9698 so you cannot specify parameters for it."
9699 (let* ((splicep (plist-get params :splice))
9700 html)
9701 ;; Just call the formatter we already have
9702 ;; We need to make text lines for it, so put the fields back together.
9703 (setq html (org-format-org-table-html
9704 (mapcar
9705 (lambda (x)
9706 (if (eq x 'hline)
9707 "|----+----|"
9708 (concat "| " (mapconcat 'identity x " | ") " |")))
9709 table)
9710 splicep))
9711 (if (string-match "\n+\\'" html)
9712 (setq html (replace-match "" t t html)))
9713 html))
9715 (defun orgtbl-to-texinfo (table params)
9716 "Convert the orgtbl-mode TABLE to TeXInfo.
9717 TABLE is a list, each entry either the symbol `hline' for a horizontal
9718 separator line, or a list of fields for that line.
9719 PARAMS is a property list of parameters that can influence the conversion.
9720 Supports all parameters from `orgtbl-to-generic'. Most important for
9721 TeXInfo are:
9723 :splice nil/t When set to t, return only table body lines, don't wrap
9724 them into a multitable environment. Default is nil.
9726 :fmt fmt A format to be used to wrap the field, should contain
9727 %s for the original field value. For example, to wrap
9728 everything in @kbd{}, you could use :fmt \"@kbd{%s}\".
9729 This may also be a property list with column numbers and
9730 formats. for example :fmt (2 \"@kbd{%s}\" 4 \"@code{%s}\").
9732 :cf \"f1 f2..\" The column fractions for the table. Bye default these
9733 are computed automatically from the width of the columns
9734 under org-mode.
9736 The general parameters :skip and :skipcols have already been applied when
9737 this function is called."
9738 (let* ((total (float (apply '+ org-table-last-column-widths)))
9739 (colfrac (or (plist-get params :cf)
9740 (mapconcat
9741 (lambda (x) (format "%.3f" (/ (float x) total)))
9742 org-table-last-column-widths " ")))
9743 (params2
9744 (list
9745 :tstart (concat "@multitable @columnfractions " colfrac)
9746 :tend "@end multitable"
9747 :lstart "@item " :lend "" :sep " @tab "
9748 :hlstart "@headitem ")))
9749 (orgtbl-to-generic table (org-combine-plists params2 params))))
9751 ;;;; Link Stuff
9753 ;;; Link abbreviations
9755 (defun org-link-expand-abbrev (link)
9756 "Apply replacements as defined in `org-link-abbrev-alist."
9757 (if (string-match "^\\([a-zA-Z]+\\)\\(::?\\(.*\\)\\)?$" link)
9758 (let* ((key (match-string 1 link))
9759 (as (or (assoc key org-link-abbrev-alist-local)
9760 (assoc key org-link-abbrev-alist)))
9761 (tag (and (match-end 2) (match-string 3 link)))
9762 rpl)
9763 (if (not as)
9764 link
9765 (setq rpl (cdr as))
9766 (cond
9767 ((symbolp rpl) (funcall rpl tag))
9768 ((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
9769 (t (concat rpl tag)))))
9770 link))
9772 ;;; Storing and inserting links
9774 (defvar org-insert-link-history nil
9775 "Minibuffer history for links inserted with `org-insert-link'.")
9777 (defvar org-stored-links nil
9778 "Contains the links stored with `org-store-link'.")
9780 (defvar org-store-link-plist nil
9781 "Plist with info about the most recently link created with `org-store-link'.")
9783 ;;;###autoload
9784 (defun org-store-link (arg)
9785 "\\<org-mode-map>Store an org-link to the current location.
9786 This link can later be inserted into an org-buffer with
9787 \\[org-insert-link].
9788 For some link types, a prefix arg is interpreted:
9789 For links to usenet articles, arg negates `org-usenet-links-prefer-google'.
9790 For file links, arg negates `org-context-in-file-links'."
9791 (interactive "P")
9792 (setq org-store-link-plist nil) ; reset
9793 (let (link cpltxt desc description search txt)
9794 (cond
9796 ((eq major-mode 'bbdb-mode)
9797 (let ((name (bbdb-record-name (bbdb-current-record)))
9798 (company (bbdb-record-company (bbdb-current-record))))
9799 (setq cpltxt (concat "bbdb:" (or name company))
9800 link (org-make-link cpltxt))
9801 (org-store-link-props :type "bbdb" :name name :company company)))
9803 ((eq major-mode 'Info-mode)
9804 (setq link (org-make-link "info:"
9805 (file-name-nondirectory Info-current-file)
9806 ":" Info-current-node))
9807 (setq cpltxt (concat (file-name-nondirectory Info-current-file)
9808 ":" Info-current-node))
9809 (org-store-link-props :type "info" :file Info-current-file
9810 :node Info-current-node))
9812 ((eq major-mode 'calendar-mode)
9813 (let ((cd (calendar-cursor-to-date)))
9814 (setq link
9815 (format-time-string
9816 (car org-time-stamp-formats)
9817 (apply 'encode-time
9818 (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
9819 nil nil nil))))
9820 (org-store-link-props :type "calendar" :date cd)))
9822 ((or (eq major-mode 'vm-summary-mode)
9823 (eq major-mode 'vm-presentation-mode))
9824 (and (eq major-mode 'vm-presentation-mode) (vm-summarize))
9825 (vm-follow-summary-cursor)
9826 (save-excursion
9827 (vm-select-folder-buffer)
9828 (let* ((message (car vm-message-pointer))
9829 (folder buffer-file-name)
9830 (subject (vm-su-subject message))
9831 (to (vm-get-header-contents message "To"))
9832 (from (vm-get-header-contents message "From"))
9833 (message-id (vm-su-message-id message)))
9834 (org-store-link-props :type "vm" :from from :to to :subject subject
9835 :message-id message-id)
9836 (setq message-id (org-remove-angle-brackets message-id))
9837 (setq folder (abbreviate-file-name folder))
9838 (if (string-match (concat "^" (regexp-quote vm-folder-directory))
9839 folder)
9840 (setq folder (replace-match "" t t folder)))
9841 (setq cpltxt (org-email-link-description))
9842 (setq link (org-make-link "vm:" folder "#" message-id)))))
9844 ((eq major-mode 'wl-summary-mode)
9845 (let* ((msgnum (wl-summary-message-number))
9846 (message-id (elmo-message-field wl-summary-buffer-elmo-folder
9847 msgnum 'message-id))
9848 (wl-message-entity
9849 (if (fboundp 'elmo-message-entity)
9850 (elmo-message-entity
9851 wl-summary-buffer-elmo-folder msgnum)
9852 (elmo-msgdb-overview-get-entity
9853 msgnum (wl-summary-buffer-msgdb))))
9854 (from (wl-summary-line-from))
9855 (to (car (elmo-message-entity-field wl-message-entity 'to)))
9856 (subject (let (wl-thr-indent-string wl-parent-message-entity)
9857 (wl-summary-line-subject))))
9858 (org-store-link-props :type "wl" :from from :to to
9859 :subject subject :message-id message-id)
9860 (setq message-id (org-remove-angle-brackets message-id))
9861 (setq cpltxt (org-email-link-description))
9862 (setq link (org-make-link "wl:" wl-summary-buffer-folder-name
9863 "#" message-id))))
9865 ((or (equal major-mode 'mh-folder-mode)
9866 (equal major-mode 'mh-show-mode))
9867 (let ((from (org-mhe-get-header "From:"))
9868 (to (org-mhe-get-header "To:"))
9869 (message-id (org-mhe-get-header "Message-Id:"))
9870 (subject (org-mhe-get-header "Subject:")))
9871 (org-store-link-props :type "mh" :from from :to to
9872 :subject subject :message-id message-id)
9873 (setq cpltxt (org-email-link-description))
9874 (setq link (org-make-link "mhe:" (org-mhe-get-message-real-folder) "#"
9875 (org-remove-angle-brackets message-id)))))
9877 ((eq major-mode 'rmail-mode)
9878 (save-excursion
9879 (save-restriction
9880 (rmail-narrow-to-non-pruned-header)
9881 (let ((folder buffer-file-name)
9882 (message-id (mail-fetch-field "message-id"))
9883 (from (mail-fetch-field "from"))
9884 (to (mail-fetch-field "to"))
9885 (subject (mail-fetch-field "subject")))
9886 (org-store-link-props
9887 :type "rmail" :from from :to to
9888 :subject subject :message-id message-id)
9889 (setq message-id (org-remove-angle-brackets message-id))
9890 (setq cpltxt (org-email-link-description))
9891 (setq link (org-make-link "rmail:" folder "#" message-id))))))
9893 ((eq major-mode 'gnus-group-mode)
9894 (let ((group (cond ((fboundp 'gnus-group-group-name) ; depending on Gnus
9895 (gnus-group-group-name)) ; version
9896 ((fboundp 'gnus-group-name)
9897 (gnus-group-name))
9898 (t "???"))))
9899 (unless group (error "Not on a group"))
9900 (org-store-link-props :type "gnus" :group group)
9901 (setq cpltxt (concat
9902 (if (org-xor arg org-usenet-links-prefer-google)
9903 "http://groups.google.com/groups?group="
9904 "gnus:")
9905 group)
9906 link (org-make-link cpltxt))))
9908 ((memq major-mode '(gnus-summary-mode gnus-article-mode))
9909 (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary))
9910 (let* ((group gnus-newsgroup-name)
9911 (article (gnus-summary-article-number))
9912 (header (gnus-summary-article-header article))
9913 (from (mail-header-from header))
9914 (message-id (mail-header-id header))
9915 (date (mail-header-date header))
9916 (subject (gnus-summary-subject-string)))
9917 (org-store-link-props :type "gnus" :from from :subject subject
9918 :message-id message-id :group group)
9919 (setq cpltxt (org-email-link-description))
9920 (if (org-xor arg org-usenet-links-prefer-google)
9921 (setq link
9922 (concat
9923 cpltxt "\n "
9924 (format "http://groups.google.com/groups?as_umsgid=%s"
9925 (org-fixup-message-id-for-http message-id))))
9926 (setq link (org-make-link "gnus:" group
9927 "#" (number-to-string article))))))
9929 ((eq major-mode 'w3-mode)
9930 (setq cpltxt (url-view-url t)
9931 link (org-make-link cpltxt))
9932 (org-store-link-props :type "w3" :url (url-view-url t)))
9934 ((eq major-mode 'w3m-mode)
9935 (setq cpltxt (or w3m-current-title w3m-current-url)
9936 link (org-make-link w3m-current-url))
9937 (org-store-link-props :type "w3m" :url (url-view-url t)))
9939 ((setq search (run-hook-with-args-until-success
9940 'org-create-file-search-functions))
9941 (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
9942 "::" search))
9943 (setq cpltxt (or description link)))
9945 ((eq major-mode 'image-mode)
9946 (setq cpltxt (concat "file:"
9947 (abbreviate-file-name buffer-file-name))
9948 link (org-make-link cpltxt))
9949 (org-store-link-props :type "image" :file buffer-file-name))
9951 ((eq major-mode 'dired-mode)
9952 ;; link to the file in the current line
9953 (setq cpltxt (concat "file:"
9954 (abbreviate-file-name
9955 (expand-file-name
9956 (dired-get-filename nil t))))
9957 link (org-make-link cpltxt)))
9959 ((and buffer-file-name (org-mode-p))
9960 ;; Just link to current headline
9961 (setq cpltxt (concat "file:"
9962 (abbreviate-file-name buffer-file-name)))
9963 ;; Add a context search string
9964 (when (org-xor org-context-in-file-links arg)
9965 ;; Check if we are on a target
9966 (if (org-in-regexp "<<\\(.*?\\)>>")
9967 (setq cpltxt (concat cpltxt "::" (match-string 1)))
9968 (setq txt (cond
9969 ((org-on-heading-p) nil)
9970 ((org-region-active-p)
9971 (buffer-substring (region-beginning) (region-end)))
9972 (t (buffer-substring (point-at-bol) (point-at-eol)))))
9973 (when (or (null txt) (string-match "\\S-" txt))
9974 (setq cpltxt
9975 (concat cpltxt "::" (org-make-org-heading-search-string txt))
9976 desc "NONE"))))
9977 (if (string-match "::\\'" cpltxt)
9978 (setq cpltxt (substring cpltxt 0 -2)))
9979 (setq link (org-make-link cpltxt)))
9981 (buffer-file-name
9982 ;; Just link to this file here.
9983 (setq cpltxt (concat "file:"
9984 (abbreviate-file-name buffer-file-name)))
9985 ;; Add a context string
9986 (when (org-xor org-context-in-file-links arg)
9987 (setq txt (if (org-region-active-p)
9988 (buffer-substring (region-beginning) (region-end))
9989 (buffer-substring (point-at-bol) (point-at-eol))))
9990 ;; Only use search option if there is some text.
9991 (when (string-match "\\S-" txt)
9992 (setq cpltxt
9993 (concat cpltxt "::" (org-make-org-heading-search-string txt))
9994 desc "NONE")))
9995 (setq link (org-make-link cpltxt)))
9997 ((interactive-p)
9998 (error "Cannot link to a buffer which is not visiting a file"))
10000 (t (setq link nil)))
10002 (if (consp link) (setq cpltxt (car link) link (cdr link)))
10003 (setq link (or link cpltxt)
10004 desc (or desc cpltxt))
10005 (if (equal desc "NONE") (setq desc nil))
10007 (if (and (interactive-p) link)
10008 (progn
10009 (setq org-stored-links
10010 (cons (list cpltxt link desc) org-stored-links))
10011 (message "Stored: %s" (or cpltxt link)))
10012 (org-make-link-string link desc))))
10014 (defun org-store-link-props (&rest plist)
10015 "Store link properties, extract names and addresses."
10016 (let (x adr)
10017 (when (setq x (plist-get plist :from))
10018 (setq adr (mail-extract-address-components x))
10019 (plist-put plist :fromname (car adr))
10020 (plist-put plist :fromaddress (nth 1 adr)))
10021 (when (setq x (plist-get plist :to))
10022 (setq adr (mail-extract-address-components x))
10023 (plist-put plist :toname (car adr))
10024 (plist-put plist :toaddress (nth 1 adr))))
10025 (let ((from (plist-get plist :from))
10026 (to (plist-get plist :to)))
10027 (when (and from to org-from-is-user-regexp)
10028 (plist-put plist :fromto
10029 (if (string-match org-from-is-user-regexp from)
10030 (concat "to %t")
10031 (concat "from %f")))))
10032 (setq org-store-link-plist plist))
10034 (defun org-email-link-description (&optional fmt)
10035 "Return the description part of an email link.
10036 This takes information from `org-store-link-plist' and formats it
10037 according to FMT (default from `org-email-link-description-format')."
10038 (setq fmt (or fmt org-email-link-description-format))
10039 (let* ((p org-store-link-plist)
10040 (to (plist-get p :toaddress))
10041 (from (plist-get p :fromaddress))
10042 (table
10043 (list
10044 (cons "%c" (plist-get p :fromto))
10045 (cons "%F" (plist-get p :from))
10046 (cons "%f" (or (plist-get p :fromname) (plist-get p :fromaddress) "?"))
10047 (cons "%T" (plist-get p :to))
10048 (cons "%t" (or (plist-get p :toname) (plist-get p :toaddress) "?"))
10049 (cons "%s" (plist-get p :subject))
10050 (cons "%m" (plist-get p :message-id)))))
10051 (when (string-match "%c" fmt)
10052 ;; Check if the user wrote this message
10053 (if (and org-from-is-user-regexp from to
10054 (save-match-data (string-match org-from-is-user-regexp from)))
10055 (setq fmt (replace-match "to %t" t t fmt))
10056 (setq fmt (replace-match "from %f" t t fmt))))
10057 (org-replace-escapes fmt table)))
10059 (defun org-make-org-heading-search-string (&optional string heading)
10060 "Make search string for STRING or current headline."
10061 (interactive)
10062 (let ((s (or string (org-get-heading))))
10063 (unless (and string (not heading))
10064 ;; We are using a headline, clean up garbage in there.
10065 (if (string-match org-todo-regexp s)
10066 (setq s (replace-match "" t t s)))
10067 (if (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" s)
10068 (setq s (replace-match "" t t s)))
10069 (setq s (org-trim s))
10070 (if (string-match (concat "^\\(" org-quote-string "\\|"
10071 org-comment-string "\\)") s)
10072 (setq s (replace-match "" t t s)))
10073 (while (string-match org-ts-regexp s)
10074 (setq s (replace-match "" t t s))))
10075 (while (string-match "[^a-zA-Z_0-9 \t]+" s)
10076 (setq s (replace-match " " t t s)))
10077 (or string (setq s (concat "*" s))) ; Add * for headlines
10078 (mapconcat 'identity (org-split-string s "[ \t]+") " ")))
10080 (defun org-make-link (&rest strings)
10081 "Concatenate STRINGS, format resulting string with `org-link-format'."
10082 (apply 'concat strings))
10084 (defun org-make-link-string (link &optional description)
10085 "Make a link with brackets, consisting of LINK and DESCRIPTION."
10086 (when (stringp description)
10087 ;; Remove brackets from the description, they are fatal.
10088 (while (string-match "\\[\\|\\]" description)
10089 (setq description (replace-match "" t t description))))
10090 (when (equal (org-link-escape link) description)
10091 ;; No description needed, it is identical
10092 (setq description nil))
10093 (when (and (not description)
10094 (not (equal link (org-link-escape link))))
10095 (setq description link))
10096 (concat "[[" (org-link-escape link) "]"
10097 (if description (concat "[" description "]") "")
10098 "]"))
10100 (defconst org-link-escape-chars '(("[" . "%5B") ("]" . "%5D") (" " . "%20"))
10101 "Association list of escapes for some characters problematic in links.")
10103 (defun org-link-escape (text)
10104 "Escape charaters in TEXT that are problematic for links."
10105 (when text
10106 (let ((re (mapconcat (lambda (x) (regexp-quote (car x)))
10107 org-link-escape-chars "\\|")))
10108 (while (string-match re text)
10109 (setq text
10110 (replace-match
10111 (cdr (assoc (match-string 0 text) org-link-escape-chars))
10112 t t text)))
10113 text)))
10115 (defun org-link-unescape (text)
10116 "Reverse the action of `org-link-escape'."
10117 (when text
10118 (let ((re (mapconcat (lambda (x) (regexp-quote (cdr x)))
10119 org-link-escape-chars "\\|")))
10120 (while (string-match re text)
10121 (setq text
10122 (replace-match
10123 (car (rassoc (match-string 0 text) org-link-escape-chars))
10124 t t text)))
10125 text)))
10127 (defun org-xor (a b)
10128 "Exclusive or."
10129 (if a (not b) b))
10131 (defun org-get-header (header)
10132 "Find a header field in the current buffer."
10133 (save-excursion
10134 (goto-char (point-min))
10135 (let ((case-fold-search t) s)
10136 (cond
10137 ((eq header 'from)
10138 (if (re-search-forward "^From:\\s-+\\(.*\\)" nil t)
10139 (setq s (match-string 1)))
10140 (while (string-match "\"" s)
10141 (setq s (replace-match "" t t s)))
10142 (if (string-match "[<(].*" s)
10143 (setq s (replace-match "" t t s))))
10144 ((eq header 'message-id)
10145 (if (re-search-forward "^message-id:\\s-+\\(.*\\)" nil t)
10146 (setq s (match-string 1))))
10147 ((eq header 'subject)
10148 (if (re-search-forward "^subject:\\s-+\\(.*\\)" nil t)
10149 (setq s (match-string 1)))))
10150 (if (string-match "\\`[ \t\]+" s) (setq s (replace-match "" t t s)))
10151 (if (string-match "[ \t\]+\\'" s) (setq s (replace-match "" t t s)))
10152 s)))
10155 (defun org-fixup-message-id-for-http (s)
10156 "Replace special characters in a message id, so it can be used in an http query."
10157 (while (string-match "<" s)
10158 (setq s (replace-match "%3C" t t s)))
10159 (while (string-match ">" s)
10160 (setq s (replace-match "%3E" t t s)))
10161 (while (string-match "@" s)
10162 (setq s (replace-match "%40" t t s)))
10165 (defun org-insert-link (&optional complete-file)
10166 "Insert a link. At the prompt, enter the link.
10168 Completion can be used to select a link previously stored with
10169 `org-store-link'. When the empty string is entered (i.e. if you just
10170 press RET at the prompt), the link defaults to the most recently
10171 stored link. As SPC triggers completion in the minibuffer, you need to
10172 use M-SPC or C-q SPC to force the insertion of a space character.
10174 You will also be prompted for a description, and if one is given, it will
10175 be displayed in the buffer instead of the link.
10177 If there is already a link at point, this command will allow you to edit link
10178 and description parts.
10180 With a \\[universal-argument] prefix, prompts for a file to link to. The file name can be
10181 selected using completion. The path to the file will be relative to
10182 the current directory if the file is in the current directory or a
10183 subdirectory. Otherwise, the link will be the absolute path as
10184 completed in the minibuffer (i.e. normally ~/path/to/file).
10186 With two \\[universal-argument] prefixes, enforce an absolute path even if the file
10187 is in the current directory or below.
10188 With three \\[universal-argument] prefixes, negate the meaning of
10189 `org-keep-stored-link-after-insertion'."
10190 (interactive "P")
10191 (let ((wcf (current-window-configuration))
10192 (region (if (org-region-active-p)
10193 (prog1 (buffer-substring (region-beginning) (region-end))
10194 (delete-region (region-beginning) (region-end)))))
10195 tmphist ; byte-compile incorrectly complains about this
10196 link desc entry remove file)
10197 (cond
10198 ((org-in-regexp org-bracket-link-regexp 1)
10199 ;; We do have a link at point, and we are going to edit it.
10200 (setq remove (list (match-beginning 0) (match-end 0)))
10201 (setq desc (if (match-end 3) (org-match-string-no-properties 3)))
10202 (setq link (read-string "Link: "
10203 (org-link-unescape
10204 (org-match-string-no-properties 1)))))
10205 ((or (org-in-regexp org-angle-link-re)
10206 (org-in-regexp org-plain-link-re))
10207 ;; Convert to bracket link
10208 (setq remove (list (match-beginning 0) (match-end 0))
10209 link (read-string "Link: "
10210 (org-remove-angle-brackets (match-string 0)))))
10211 ((equal complete-file '(4))
10212 ;; Completing read for file names.
10213 (setq file (read-file-name "File: "))
10214 (let ((pwd (file-name-as-directory (expand-file-name ".")))
10215 (pwd1 (file-name-as-directory (abbreviate-file-name
10216 (expand-file-name ".")))))
10217 (cond
10218 ((equal complete-file '(16))
10219 (setq link (org-make-link
10220 "file:"
10221 (abbreviate-file-name (expand-file-name file)))))
10222 ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
10223 (setq link (org-make-link "file:" (match-string 1 file))))
10224 ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
10225 (expand-file-name file))
10226 (setq link (org-make-link
10227 "file:" (match-string 1 (expand-file-name file)))))
10228 (t (setq link (org-make-link "file:" file))))))
10230 ;; Read link, with completion for stored links.
10231 (with-output-to-temp-buffer "*Org Links*"
10232 (princ "Insert a link. Use TAB to complete valid link prefixes.\n")
10233 (when org-stored-links
10234 (princ "\nStored links ar available with <up>/<down> (most recent with RET):\n\n")
10235 (princ (mapconcat 'car (reverse org-stored-links) "\n"))))
10236 (let ((cw (selected-window)))
10237 (select-window (get-buffer-window "*Org Links*"))
10238 (shrink-window-if-larger-than-buffer)
10239 (setq truncate-lines t)
10240 (select-window cw))
10241 ;; Fake a link history, containing the stored links.
10242 (setq tmphist (append (mapcar 'car org-stored-links)
10243 org-insert-link-history))
10244 (unwind-protect
10245 (setq link (org-completing-read
10246 "Link: "
10247 (append
10248 (mapcar (lambda (x) (concat (car x) ":"))
10249 (append org-link-abbrev-alist-local org-link-abbrev-alist))
10250 (mapcar (lambda (x) (concat x ":")) org-link-types))
10251 nil nil nil
10252 'tmphist
10253 (or (car (car org-stored-links)))))
10254 (set-window-configuration wcf)
10255 (kill-buffer "*Org Links*"))
10256 (setq entry (assoc link org-stored-links))
10257 (or entry (push link org-insert-link-history))
10258 (if (funcall (if (equal complete-file '(64)) 'not 'identity)
10259 (not org-keep-stored-link-after-insertion))
10260 (setq org-stored-links (delq (assoc link org-stored-links)
10261 org-stored-links)))
10262 (setq link (if entry (nth 1 entry) link)
10263 desc (or region desc (nth 2 entry)))))
10265 (if (string-match org-plain-link-re link)
10266 ;; URL-like link, normalize the use of angular brackets.
10267 (setq link (org-make-link (org-remove-angle-brackets link))))
10269 ;; Check if we are linking to the current file with a search option
10270 ;; If yes, simplify the link by using only the search option.
10271 (when (and buffer-file-name
10272 (string-match "\\<file:\\(.+?\\)::\\([^>]+\\)" link))
10273 (let* ((path (match-string 1 link))
10274 (case-fold-search nil)
10275 (search (match-string 2 link)))
10276 (save-match-data
10277 (if (equal (file-truename buffer-file-name) (file-truename path))
10278 ;; We are linking to this same file, with a search option
10279 (setq link search)))))
10281 ;; Check if we can/should use a relative path. If yes, simplify the link
10282 (when (string-match "\\<file:\\(.*\\)" link)
10283 (let* ((path (match-string 1 link))
10284 (case-fold-search nil))
10285 (cond
10286 ((eq org-link-file-path-type 'absolute)
10287 (setq path (abbreviate-file-name (expand-file-name path))))
10288 ((eq org-link-file-path-type 'noabbrev)
10289 (setq path (expand-file-name path)))
10290 ((eq org-link-file-path-type 'relative)
10291 (setq path (file-relative-name path)))
10293 (save-match-data
10294 (if (string-match (concat "^" (regexp-quote
10295 (file-name-as-directory
10296 (expand-file-name "."))))
10297 (expand-file-name path))
10298 ;; We are linking a file with relative path name.
10299 (setq path (substring (expand-file-name path)
10300 (match-end 0)))))))
10301 (setq link (concat "file:" path))))
10303 (setq desc (read-string "Description: " desc))
10304 (unless (string-match "\\S-" desc) (setq desc nil))
10305 (if remove (apply 'delete-region remove))
10306 (insert (org-make-link-string link desc))))
10308 (defun org-completing-read (&rest args)
10309 (let ((minibuffer-local-completion-map
10310 (copy-keymap minibuffer-local-completion-map)))
10311 (org-defkey minibuffer-local-completion-map " " 'self-insert-command)
10312 (apply 'completing-read args)))
10314 ;;; Opening/following a link
10315 (defvar org-link-search-failed nil)
10317 (defun org-next-link ()
10318 "Move forward to the next link.
10319 If the link is in hidden text, expose it."
10320 (interactive)
10321 (when (and org-link-search-failed (eq this-command last-command))
10322 (goto-char (point-min))
10323 (message "Link search wrapped back to beginning of buffer"))
10324 (setq org-link-search-failed nil)
10325 (let* ((pos (point))
10326 (ct (org-context))
10327 (a (assoc :link ct)))
10328 (if a (goto-char (nth 2 a)))
10329 (if (re-search-forward org-any-link-re nil t)
10330 (progn
10331 (goto-char (match-beginning 0))
10332 (if (org-invisible-p) (org-show-context)))
10333 (goto-char pos)
10334 (setq org-link-search-failed t)
10335 (error "No further link found"))))
10337 (defun org-previous-link ()
10338 "Move backward to the previous link.
10339 If the link is in hidden text, expose it."
10340 (interactive)
10341 (when (and org-link-search-failed (eq this-command last-command))
10342 (goto-char (point-max))
10343 (message "Link search wrapped back to end of buffer"))
10344 (setq org-link-search-failed nil)
10345 (let* ((pos (point))
10346 (ct (org-context))
10347 (a (assoc :link ct)))
10348 (if a (goto-char (nth 1 a)))
10349 (if (re-search-backward org-any-link-re nil t)
10350 (progn
10351 (goto-char (match-beginning 0))
10352 (if (org-invisible-p) (org-show-context)))
10353 (goto-char pos)
10354 (setq org-link-search-failed t)
10355 (error "No further link found"))))
10357 (defun org-find-file-at-mouse (ev)
10358 "Open file link or URL at mouse."
10359 (interactive "e")
10360 (mouse-set-point ev)
10361 (org-open-at-point 'in-emacs))
10363 (defun org-open-at-mouse (ev)
10364 "Open file link or URL at mouse."
10365 (interactive "e")
10366 (mouse-set-point ev)
10367 (org-open-at-point))
10369 (defvar org-window-config-before-follow-link nil
10370 "The window configuration before following a link.
10371 This is saved in case the need arises to restore it.")
10373 (defvar org-open-link-marker (make-marker)
10374 "Marker pointing to the location where `org-open-at-point; was called.")
10376 (defun org-open-at-point (&optional in-emacs)
10377 "Open link at or after point.
10378 If there is no link at point, this function will search forward up to
10379 the end of the current subtree.
10380 Normally, files will be opened by an appropriate application. If the
10381 optional argument IN-EMACS is non-nil, Emacs will visit the file."
10382 (interactive "P")
10383 (move-marker org-open-link-marker (point))
10384 (setq org-window-config-before-follow-link (current-window-configuration))
10385 (org-remove-occur-highlights nil nil t)
10386 (if (org-at-timestamp-p t)
10387 (org-follow-timestamp-link)
10388 (let (type path link line search (pos (point)))
10389 (catch 'match
10390 (save-excursion
10391 (skip-chars-forward "^]\n\r")
10392 (when (org-in-regexp org-bracket-link-regexp)
10393 (setq link (org-link-unescape (org-match-string-no-properties 1)))
10394 (while (string-match " *\n *" link)
10395 (setq link (replace-match " " t t link)))
10396 (setq link (org-link-expand-abbrev link))
10397 (if (string-match org-link-re-with-space2 link)
10398 (setq type (match-string 1 link) path (match-string 2 link))
10399 (setq type "thisfile" path link))
10400 (throw 'match t)))
10402 (when (get-text-property (point) 'org-linked-text)
10403 (setq type "thisfile"
10404 pos (if (get-text-property (1+ (point)) 'org-linked-text)
10405 (1+ (point)) (point))
10406 path (buffer-substring
10407 (previous-single-property-change pos 'org-linked-text)
10408 (next-single-property-change pos 'org-linked-text)))
10409 (throw 'match t))
10411 (save-excursion
10412 (when (or (org-in-regexp org-angle-link-re)
10413 (org-in-regexp org-plain-link-re))
10414 (setq type (match-string 1) path (match-string 2))
10415 (throw 'match t)))
10416 (save-excursion
10417 (when (org-in-regexp "\\(:[A-Za-z_@0-9:]+\\):[ \t]*$")
10418 (setq type "tags"
10419 path (match-string 1))
10420 (while (string-match ":" path)
10421 (setq path (replace-match "+" t t path)))
10422 (throw 'match t))))
10423 (unless path
10424 (error "No link found"))
10425 ;; Remove any trailing spaces in path
10426 (if (string-match " +\\'" path)
10427 (setq path (replace-match "" t t path)))
10429 (cond
10431 ((equal type "mailto")
10432 (let ((cmd (car org-link-mailto-program))
10433 (args (cdr org-link-mailto-program)) args1
10434 (address path) (subject "") a)
10435 (if (string-match "\\(.*\\)::\\(.*\\)" path)
10436 (setq address (match-string 1 path)
10437 subject (org-link-escape (match-string 2 path))))
10438 (while args
10439 (cond
10440 ((not (stringp (car args))) (push (pop args) args1))
10441 (t (setq a (pop args))
10442 (if (string-match "%a" a)
10443 (setq a (replace-match address t t a)))
10444 (if (string-match "%s" a)
10445 (setq a (replace-match subject t t a)))
10446 (push a args1))))
10447 (apply cmd (nreverse args1))))
10449 ((member type '("http" "https" "ftp" "news"))
10450 (browse-url (concat type ":" path)))
10452 ((string= type "tags")
10453 (org-tags-view in-emacs path))
10454 ((string= type "thisfile")
10455 (if in-emacs
10456 (switch-to-buffer-other-window
10457 (org-get-buffer-for-internal-link (current-buffer)))
10458 (org-mark-ring-push))
10459 (org-link-search
10460 path
10461 (cond ((equal in-emacs '(4)) 'occur)
10462 ((equal in-emacs '(16)) 'org-occur)
10463 (t nil))
10464 pos))
10466 ((string= type "file")
10467 (if (string-match "::\\([0-9]+\\)\\'" path)
10468 (setq line (string-to-number (match-string 1 path))
10469 path (substring path 0 (match-beginning 0)))
10470 (if (string-match "::\\(.+\\)\\'" path)
10471 (setq search (match-string 1 path)
10472 path (substring path 0 (match-beginning 0)))))
10473 (org-open-file path in-emacs line search))
10475 ((string= type "news")
10476 (org-follow-gnus-link path))
10478 ((string= type "bbdb")
10479 (org-follow-bbdb-link path))
10481 ((string= type "info")
10482 (org-follow-info-link path))
10484 ((string= type "gnus")
10485 (let (group article)
10486 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10487 (error "Error in Gnus link"))
10488 (setq group (match-string 1 path)
10489 article (match-string 3 path))
10490 (org-follow-gnus-link group article)))
10492 ((string= type "vm")
10493 (let (folder article)
10494 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10495 (error "Error in VM link"))
10496 (setq folder (match-string 1 path)
10497 article (match-string 3 path))
10498 ;; in-emacs is the prefix arg, will be interpreted as read-only
10499 (org-follow-vm-link folder article in-emacs)))
10501 ((string= type "wl")
10502 (let (folder article)
10503 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10504 (error "Error in Wanderlust link"))
10505 (setq folder (match-string 1 path)
10506 article (match-string 3 path))
10507 (org-follow-wl-link folder article)))
10509 ((string= type "mhe")
10510 (let (folder article)
10511 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10512 (error "Error in MHE link"))
10513 (setq folder (match-string 1 path)
10514 article (match-string 3 path))
10515 (org-follow-mhe-link folder article)))
10517 ((string= type "rmail")
10518 (let (folder article)
10519 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10520 (error "Error in RMAIL link"))
10521 (setq folder (match-string 1 path)
10522 article (match-string 3 path))
10523 (org-follow-rmail-link folder article)))
10525 ((string= type "shell")
10526 (let ((cmd path))
10527 ;; FIXME: the following is only for backward compatibility
10528 (while (string-match "@{" cmd) (setq cmd (replace-match "<" t t cmd)))
10529 (while (string-match "@}" cmd) (setq cmd (replace-match ">" t t cmd)))
10530 (if (or (not org-confirm-shell-link-function)
10531 (funcall org-confirm-shell-link-function
10532 (format "Execute \"%s\" in shell? "
10533 (org-add-props cmd nil
10534 'face 'org-warning))))
10535 (progn
10536 (message "Executing %s" cmd)
10537 (shell-command cmd))
10538 (error "Abort"))))
10540 ((string= type "elisp")
10541 (let ((cmd path))
10542 (if (or (not org-confirm-elisp-link-function)
10543 (funcall org-confirm-elisp-link-function
10544 (format "Execute \"%s\" as elisp? "
10545 (org-add-props cmd nil
10546 'face 'org-warning))))
10547 (message "%s => %s" cmd (eval (read cmd)))
10548 (error "Abort"))))
10551 (browse-url-at-point)))))
10552 (move-marker org-open-link-marker nil))
10555 ;;; File search
10557 (defvar org-create-file-search-functions nil
10558 "List of functions to construct the right search string for a file link.
10559 These functions are called in turn with point at the location to
10560 which the link should point.
10562 A function in the hook should first test if it would like to
10563 handle this file type, for example by checking the major-mode or
10564 the file extension. If it decides not to handle this file, it
10565 should just return nil to give other functions a chance. If it
10566 does handle the file, it must return the search string to be used
10567 when following the link. The search string will be part of the
10568 file link, given after a double colon, and `org-open-at-point'
10569 will automatically search for it. If special measures must be
10570 taken to make the search successful, another function should be
10571 added to the companion hook `org-execute-file-search-functions',
10572 which see.
10574 A function in this hook may also use `setq' to set the variable
10575 `description' to provide a suggestion for the descriptive text to
10576 be used for this link when it gets inserted into an Org-mode
10577 buffer with \\[org-insert-link].")
10579 (defvar org-execute-file-search-functions nil
10580 "List of functions to execute a file search triggered by a link.
10582 Functions added to this hook must accept a single argument, the
10583 search string that was part of the file link, the part after the
10584 double colon. The function must first check if it would like to
10585 handle this search, for example by checking the major-mode or the
10586 file extension. If it decides not to handle this search, it
10587 should just return nil to give other functions a chance. If it
10588 does handle the search, it must return a non-nil value to keep
10589 other functions from trying.
10591 Each function can access the current prefix argument through the
10592 variable `current-prefix-argument'. Note that a single prefix is
10593 used to force opening a link in Emacs, so it may be good to only
10594 use a numeric or double prefix to guide the search function.
10596 In case this is needed, a function in this hook can also restore
10597 the window configuration before `org-open-at-point' was called using:
10599 (set-window-configuration org-window-config-before-follow-link)")
10601 (defun org-link-search (s &optional type avoid-pos)
10602 "Search for a link search option.
10603 If S is surrounded by forward slashes, it is interpreted as a
10604 regular expression. In org-mode files, this will create an `org-occur'
10605 sparse tree. In ordinary files, `occur' will be used to list matches.
10606 If the current buffer is in `dired-mode', grep will be used to search
10607 in all files. If AVOID-POS is given, ignore matches near that position."
10608 (let ((case-fold-search t)
10609 (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " "))
10610 (markers (concat "\\(?:" (mapconcat (lambda (x) (regexp-quote (car x)))
10611 (append '((" ") ("\t") ("\n"))
10612 org-emphasis-alist)
10613 "\\|") "\\)"))
10614 (pos (point))
10615 (pre "") (post "")
10616 words re0 re1 re2 re3 re4 re5 re2a reall)
10617 (cond
10618 ;; First check if there are any special
10619 ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
10620 ;; Now try the builtin stuff
10621 ((save-excursion
10622 (goto-char (point-min))
10623 (and
10624 (re-search-forward
10625 (concat "<<" (regexp-quote s0) ">>") nil t)
10626 (setq pos (match-beginning 0))))
10627 ;; There is an exact target for this
10628 (goto-char pos))
10629 ((string-match "^/\\(.*\\)/$" s)
10630 ;; A regular expression
10631 (cond
10632 ((org-mode-p)
10633 (org-occur (match-string 1 s)))
10634 ;;((eq major-mode 'dired-mode)
10635 ;; (grep (concat "grep -n -e '" (match-string 1 s) "' *")))
10636 (t (org-do-occur (match-string 1 s)))))
10638 ;; A normal search string
10639 (when (equal (string-to-char s) ?*)
10640 ;; Anchor on headlines, post may include tags.
10641 (setq pre "^\\*+[ \t]*\\(?:\\sw+\\)?[ \t]*"
10642 post "[ \t]*\\(?:[ \t]+:[a-zA-Z_@0-9:+]:[ \t]*\\)?$"
10643 s (substring s 1)))
10644 (remove-text-properties
10645 0 (length s)
10646 '(face nil mouse-face nil keymap nil fontified nil) s)
10647 ;; Make a series of regular expressions to find a match
10648 (setq words (org-split-string s "[ \n\r\t]+")
10649 re0 (concat "\\(<<" (regexp-quote s0) ">>\\)")
10650 re2 (concat markers "\\(" (mapconcat 'downcase words "[ \t]+")
10651 "\\)" markers)
10652 re2a (concat "[ \t\r\n]\\(" (mapconcat 'downcase words "[ \t\r\n]+") "\\)[ \t\r\n]")
10653 re4 (concat "[^a-zA-Z_]\\(" (mapconcat 'downcase words "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
10654 re1 (concat pre re2 post)
10655 re3 (concat pre re4 post)
10656 re5 (concat pre ".*" re4)
10657 re2 (concat pre re2)
10658 re2a (concat pre re2a)
10659 re4 (concat pre re4)
10660 reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2
10661 "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\("
10662 re5 "\\)"
10664 (cond
10665 ((eq type 'org-occur) (org-occur reall))
10666 ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
10667 (t (goto-char (point-min))
10668 (if (or (org-search-not-self 1 re0 nil t)
10669 (org-search-not-self 1 re1 nil t)
10670 (org-search-not-self 1 re2 nil t)
10671 (org-search-not-self 1 re2a nil t)
10672 (org-search-not-self 1 re3 nil t)
10673 (org-search-not-self 1 re4 nil t)
10674 (org-search-not-self 1 re5 nil t)
10676 (goto-char (match-beginning 1))
10677 (goto-char pos)
10678 (error "No match")))))
10680 ;; Normal string-search
10681 (goto-char (point-min))
10682 (if (search-forward s nil t)
10683 (goto-char (match-beginning 0))
10684 (error "No match"))))
10685 (and (org-mode-p) (org-show-context 'link-search))))
10687 (defun org-search-not-self (group &rest args)
10688 "Execute `re-search-forward', but only accept matches that do not
10689 enclose the position of `org-open-link-marker'."
10690 (let ((m org-open-link-marker))
10691 (catch 'exit
10692 (while (apply 're-search-forward args)
10693 (unless (get-text-property (match-end group) 'intangible) ; Emacs 21
10694 (goto-char (match-end group))
10695 (if (and (or (not (eq (marker-buffer m) (current-buffer)))
10696 (> (match-beginning 0) (marker-position m))
10697 (< (match-end 0) (marker-position m)))
10698 (save-match-data
10699 (or (not (org-in-regexp
10700 org-bracket-link-analytic-regexp 1))
10701 (not (match-end 4)) ; no description
10702 (and (<= (match-beginning 4) (point))
10703 (>= (match-end 4) (point))))))
10704 (throw 'exit (point))))))))
10706 (defun org-get-buffer-for-internal-link (buffer)
10707 "Return a buffer to be used for displaying the link target of internal links."
10708 (cond
10709 ((not org-display-internal-link-with-indirect-buffer)
10710 buffer)
10711 ((string-match "(Clone)$" (buffer-name buffer))
10712 (message "Buffer is already a clone, not making another one")
10713 ;; we also do not modify visibility in this case
10714 buffer)
10715 (t ; make a new indirect buffer for displaying the link
10716 (let* ((bn (buffer-name buffer))
10717 (ibn (concat bn "(Clone)"))
10718 (ib (or (get-buffer ibn) (make-indirect-buffer buffer ibn 'clone))))
10719 (with-current-buffer ib (org-overview))
10720 ib))))
10722 (defun org-do-occur (regexp &optional cleanup)
10723 "Call the Emacs command `occur'.
10724 If CLEANUP is non-nil, remove the printout of the regular expression
10725 in the *Occur* buffer. This is useful if the regex is long and not useful
10726 to read."
10727 (occur regexp)
10728 (when cleanup
10729 (let ((cwin (selected-window)) win beg end)
10730 (when (setq win (get-buffer-window "*Occur*"))
10731 (select-window win))
10732 (goto-char (point-min))
10733 (when (re-search-forward "match[a-z]+" nil t)
10734 (setq beg (match-end 0))
10735 (if (re-search-forward "^[ \t]*[0-9]+" nil t)
10736 (setq end (1- (match-beginning 0)))))
10737 (and beg end (let ((buffer-read-only)) (delete-region beg end)))
10738 (goto-char (point-min))
10739 (select-window cwin))))
10741 ;;; The mark ring for links jumps
10743 (defvar org-mark-ring nil
10744 "Mark ring for positions before jumps in Org-mode.")
10745 (defvar org-mark-ring-last-goto nil
10746 "Last position in the mark ring used to go back.")
10747 ;; Fill and close the ring
10748 (setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is reloaded
10749 (loop for i from 1 to org-mark-ring-length do
10750 (push (make-marker) org-mark-ring))
10751 (setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring)
10752 org-mark-ring)
10754 (defun org-mark-ring-push (&optional pos buffer)
10755 "Put the current position or POS into the mark ring and rotate it."
10756 (interactive)
10757 (setq pos (or pos (point)))
10758 (setq org-mark-ring (nthcdr (1- org-mark-ring-length) org-mark-ring))
10759 (move-marker (car org-mark-ring)
10760 (or pos (point))
10761 (or buffer (current-buffer)))
10762 (message
10763 (substitute-command-keys
10764 "Position saved to mark ring, go back with \\[org-mark-ring-goto].")))
10766 (defun org-mark-ring-goto (&optional n)
10767 "Jump to the previous position in the mark ring.
10768 With prefix arg N, jump back that many stored positions. When
10769 called several times in succession, walk through the entire ring.
10770 Org-mode commands jumping to a different position in the current file,
10771 or to another Org-mode file, automatically push the old position
10772 onto the ring."
10773 (interactive "p")
10774 (let (p m)
10775 (if (eq last-command this-command)
10776 (setq p (nthcdr n (or org-mark-ring-last-goto org-mark-ring)))
10777 (setq p org-mark-ring))
10778 (setq org-mark-ring-last-goto p)
10779 (setq m (car p))
10780 (switch-to-buffer (marker-buffer m))
10781 (goto-char m)
10782 (if (or (org-invisible-p) (org-invisible-p2)) (org-show-context 'mark-goto))))
10784 (defun org-remove-angle-brackets (s)
10785 (if (equal (substring s 0 1) "<") (setq s (substring s 1)))
10786 (if (equal (substring s -1) ">") (setq s (substring s 0 -1)))
10788 (defun org-add-angle-brackets (s)
10789 (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s)))
10790 (if (equal (substring s -1) ">") nil (setq s (concat s ">")))
10793 ;;; Following specific links
10795 (defun org-follow-timestamp-link ()
10796 (cond
10797 ((org-at-date-range-p t)
10798 (let ((org-agenda-start-on-weekday)
10799 (t1 (match-string 1))
10800 (t2 (match-string 2)))
10801 (setq t1 (time-to-days (org-time-string-to-time t1))
10802 t2 (time-to-days (org-time-string-to-time t2)))
10803 (org-agenda-list nil t1 (1+ (- t2 t1)))))
10804 ((org-at-timestamp-p t)
10805 (org-agenda-list nil (time-to-days (org-time-string-to-time
10806 (substring (match-string 1) 0 10)))
10808 (t (error "This should not happen"))))
10811 (defun org-follow-bbdb-link (name)
10812 "Follow a BBDB link to NAME."
10813 (require 'bbdb)
10814 (let ((inhibit-redisplay (not debug-on-error))
10815 (bbdb-electric-p nil))
10816 (catch 'exit
10817 ;; Exact match on name
10818 (bbdb-name (concat "\\`" name "\\'") nil)
10819 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
10820 ;; Exact match on name
10821 (bbdb-company (concat "\\`" name "\\'") nil)
10822 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
10823 ;; Partial match on name
10824 (bbdb-name name nil)
10825 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
10826 ;; Partial match on company
10827 (bbdb-company name nil)
10828 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
10829 ;; General match including network address and notes
10830 (bbdb name nil)
10831 (when (= 0 (buffer-size (get-buffer "*BBDB*")))
10832 (delete-window (get-buffer-window "*BBDB*"))
10833 (error "No matching BBDB record")))))
10835 (defun org-follow-info-link (name)
10836 "Follow an info file & node link to NAME."
10837 (if (or (string-match "\\(.*\\)::?\\(.*\\)" name)
10838 (string-match "\\(.*\\)" name))
10839 (progn
10840 (require 'info)
10841 (if (match-string 2 name) ; If there isn't a node, choose "Top"
10842 (Info-find-node (match-string 1 name) (match-string 2 name))
10843 (Info-find-node (match-string 1 name) "Top")))
10844 (message (concat "Could not open: " name))))
10846 (defun org-follow-gnus-link (&optional group article)
10847 "Follow a Gnus link to GROUP and ARTICLE."
10848 (require 'gnus)
10849 (funcall (cdr (assq 'gnus org-link-frame-setup)))
10850 (if gnus-other-frame-object (select-frame gnus-other-frame-object))
10851 (cond ((and group article)
10852 (gnus-group-read-group 1 nil group)
10853 (gnus-summary-goto-article (string-to-number article) nil t))
10854 (group (gnus-group-jump-to-group group))))
10856 (defun org-follow-vm-link (&optional folder article readonly)
10857 "Follow a VM link to FOLDER and ARTICLE."
10858 (require 'vm)
10859 (setq article (org-add-angle-brackets article))
10860 (if (string-match "^//\\([a-zA-Z]+@\\)?\\([^:]+\\):\\(.*\\)" folder)
10861 ;; ange-ftp or efs or tramp access
10862 (let ((user (or (match-string 1 folder) (user-login-name)))
10863 (host (match-string 2 folder))
10864 (file (match-string 3 folder)))
10865 (cond
10866 ((featurep 'tramp)
10867 ;; use tramp to access the file
10868 (if (featurep 'xemacs)
10869 (setq folder (format "[%s@%s]%s" user host file))
10870 (setq folder (format "/%s@%s:%s" user host file))))
10872 ;; use ange-ftp or efs
10873 (require (if (featurep 'xemacs) 'efs 'ange-ftp))
10874 (setq folder (format "/%s@%s:%s" user host file))))))
10875 (when folder
10876 (funcall (cdr (assq 'vm org-link-frame-setup)) folder readonly)
10877 (sit-for 0.1)
10878 (when article
10879 (vm-select-folder-buffer)
10880 (widen)
10881 (let ((case-fold-search t))
10882 (goto-char (point-min))
10883 (if (not (re-search-forward
10884 (concat "^" "message-id: *" (regexp-quote article))))
10885 (error "Could not find the specified message in this folder"))
10886 (vm-isearch-update)
10887 (vm-isearch-narrow)
10888 (vm-beginning-of-message)
10889 (vm-summarize)))))
10891 (defun org-follow-wl-link (folder article)
10892 "Follow a Wanderlust link to FOLDER and ARTICLE."
10893 (if (and (string= folder "%")
10894 article
10895 (string-match "^\\([^#]+\\)\\(#\\(.*\\)\\)?" article))
10896 ;; XXX: imap-uw supports folders starting with '#' such as "#mh/inbox".
10897 ;; Thus, we recompose folder and article ids.
10898 (setq folder (format "%s#%s" folder (match-string 1 article))
10899 article (match-string 3 article)))
10900 (if (not (elmo-folder-exists-p (wl-folder-get-elmo-folder folder)))
10901 (error "No such folder: %s" folder))
10902 (wl-summary-goto-folder-subr folder 'no-sync t nil t nil nil)
10903 (and article
10904 (wl-summary-jump-to-msg-by-message-id (org-add-angle-brackets article))
10905 (wl-summary-redisplay)))
10907 (defun org-follow-rmail-link (folder article)
10908 "Follow an RMAIL link to FOLDER and ARTICLE."
10909 (setq article (org-add-angle-brackets article))
10910 (let (message-number)
10911 (save-excursion
10912 (save-window-excursion
10913 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
10914 (setq message-number
10915 (save-restriction
10916 (widen)
10917 (goto-char (point-max))
10918 (if (re-search-backward
10919 (concat "^Message-ID:\\s-+" (regexp-quote
10920 (or article "")))
10921 nil t)
10922 (rmail-what-message))))))
10923 (if message-number
10924 (progn
10925 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
10926 (rmail-show-message message-number)
10927 message-number)
10928 (error "Message not found"))))
10930 ;;; mh-e integration based on planner-mode
10931 (defun org-mhe-get-message-real-folder ()
10932 "Return the name of the current message real folder, so if you use
10933 sequences, it will now work."
10934 (save-excursion
10935 (let* ((folder
10936 (if (equal major-mode 'mh-folder-mode)
10937 mh-current-folder
10938 ;; Refer to the show buffer
10939 mh-show-folder-buffer))
10940 (end-index
10941 (if (boundp 'mh-index-folder)
10942 (min (length mh-index-folder) (length folder))))
10944 ;; a simple test on mh-index-data does not work, because
10945 ;; mh-index-data is always nil in a show buffer.
10946 (if (and (boundp 'mh-index-folder)
10947 (string= mh-index-folder (substring folder 0 end-index)))
10948 (if (equal major-mode 'mh-show-mode)
10949 (save-window-excursion
10950 (when (buffer-live-p (get-buffer folder))
10951 (progn
10952 (pop-to-buffer folder)
10953 (org-mhe-get-message-folder-from-index)
10956 (org-mhe-get-message-folder-from-index)
10958 folder
10962 (defun org-mhe-get-message-folder-from-index ()
10963 "Returns the name of the message folder in a index folder buffer."
10964 (save-excursion
10965 (mh-index-previous-folder)
10966 (re-search-forward "^\\(+.*\\)$" nil t)
10967 (message (match-string 1))))
10969 (defun org-mhe-get-message-folder ()
10970 "Return the name of the current message folder. Be careful if you
10971 use sequences."
10972 (save-excursion
10973 (if (equal major-mode 'mh-folder-mode)
10974 mh-current-folder
10975 ;; Refer to the show buffer
10976 mh-show-folder-buffer)))
10978 (defun org-mhe-get-message-num ()
10979 "Return the number of the current message. Be careful if you
10980 use sequences."
10981 (save-excursion
10982 (if (equal major-mode 'mh-folder-mode)
10983 (mh-get-msg-num nil)
10984 ;; Refer to the show buffer
10985 (mh-show-buffer-message-number))))
10987 (defun org-mhe-get-header (header)
10988 "Return a header of the message in folder mode. This will create a
10989 show buffer for the corresponding message. If you have a more clever
10990 idea..."
10991 (let* ((folder (org-mhe-get-message-folder))
10992 (num (org-mhe-get-message-num))
10993 (buffer (get-buffer-create (concat "show-" folder)))
10994 (header-field))
10995 (with-current-buffer buffer
10996 (mh-display-msg num folder)
10997 (if (equal major-mode 'mh-folder-mode)
10998 (mh-header-display)
10999 (mh-show-header-display))
11000 (set-buffer buffer)
11001 (setq header-field (mh-get-header-field header))
11002 (if (equal major-mode 'mh-folder-mode)
11003 (mh-show)
11004 (mh-show-show))
11005 header-field)))
11007 (defun org-follow-mhe-link (folder article)
11008 "Follow an MHE link to FOLDER and ARTICLE.
11009 If ARTICLE is nil FOLDER is shown. If the configuration variable
11010 `org-mhe-search-all-folders' is t and `mh-searcher' is pick,
11011 ARTICLE is searched in all folders. Indexed searches (swish++,
11012 namazu, and others supported by MH-E) will always search in all
11013 folders."
11014 (require 'mh-e)
11015 (require 'mh-search)
11016 (require 'mh-utils)
11017 (mh-find-path)
11018 (if (not article)
11019 (mh-visit-folder (mh-normalize-folder-name folder))
11020 (setq article (org-add-angle-brackets article))
11021 (mh-search-choose)
11022 (if (equal mh-searcher 'pick)
11023 (progn
11024 (mh-search folder (list "--message-id" article))
11025 (when (and org-mhe-search-all-folders
11026 (not (org-mhe-get-message-real-folder)))
11027 (kill-this-buffer)
11028 (mh-search "+" (list "--message-id" article))))
11029 (mh-search "+" article))
11030 (if (org-mhe-get-message-real-folder)
11031 (mh-show-msg 1)
11032 (kill-this-buffer)
11033 (error "Message not found"))))
11035 ;;; BibTeX links
11037 ;; Use the custom search meachnism to construct and use search strings for
11038 ;; file links to BibTeX database entries.
11040 (defun org-create-file-search-in-bibtex ()
11041 "Create the search string and description for a BibTeX database entry."
11042 (when (eq major-mode 'bibtex-mode)
11043 ;; yes, we want to construct this search string.
11044 ;; Make a good description for this entry, using names, year and the title
11045 ;; Put it into the `description' variable which is dynamically scoped.
11046 (let ((bibtex-autokey-names 1)
11047 (bibtex-autokey-names-stretch 1)
11048 (bibtex-autokey-name-case-convert-function 'identity)
11049 (bibtex-autokey-name-separator " & ")
11050 (bibtex-autokey-additional-names " et al.")
11051 (bibtex-autokey-year-length 4)
11052 (bibtex-autokey-name-year-separator " ")
11053 (bibtex-autokey-titlewords 3)
11054 (bibtex-autokey-titleword-separator " ")
11055 (bibtex-autokey-titleword-case-convert-function 'identity)
11056 (bibtex-autokey-titleword-length 'infty)
11057 (bibtex-autokey-year-title-separator ": "))
11058 (setq description (bibtex-generate-autokey)))
11059 ;; Now parse the entry, get the key and return it.
11060 (save-excursion
11061 (bibtex-beginning-of-entry)
11062 (cdr (assoc "=key=" (bibtex-parse-entry))))))
11064 (defun org-execute-file-search-in-bibtex (s)
11065 "Find the link search string S as a key for a database entry."
11066 (when (eq major-mode 'bibtex-mode)
11067 ;; Yes, we want to do the search in this file.
11068 ;; We construct a regexp that searches for "@entrytype{" followed by the key
11069 (goto-char (point-min))
11070 (and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*"
11071 (regexp-quote s) "[ \t\n]*,") nil t)
11072 (goto-char (match-beginning 0)))
11073 (if (and (match-beginning 0) (equal current-prefix-arg '(16)))
11074 ;; Use double prefix to indicate that any web link should be browsed
11075 (let ((b (current-buffer)) (p (point)))
11076 ;; Restore the window configuration because we just use the web link
11077 (set-window-configuration org-window-config-before-follow-link)
11078 (save-excursion (set-buffer b) (goto-char p)
11079 (bibtex-url)))
11080 (recenter 0)) ; Move entry start to beginning of window
11081 ;; return t to indicate that the search is done.
11084 ;; Finally add the functions to the right hooks.
11085 (add-hook 'org-create-file-search-functions 'org-create-file-search-in-bibtex)
11086 (add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-bibtex)
11088 ;; end of Bibtex link setup
11090 ;;; Following file links
11092 (defun org-open-file (path &optional in-emacs line search)
11093 "Open the file at PATH.
11094 First, this expands any special file name abbreviations. Then the
11095 configuration variable `org-file-apps' is checked if it contains an
11096 entry for this file type, and if yes, the corresponding command is launched.
11097 If no application is found, Emacs simply visits the file.
11098 With optional argument IN-EMACS, Emacs will visit the file.
11099 Optional LINE specifies a line to go to, optional SEARCH a string to
11100 search for. If LINE or SEARCH is given, the file will always be
11101 opened in Emacs.
11102 If the file does not exist, an error is thrown."
11103 (setq in-emacs (or in-emacs line search))
11104 (let* ((file (if (equal path "")
11105 buffer-file-name
11106 (substitute-in-file-name (expand-file-name path))))
11107 (apps (append org-file-apps (org-default-apps)))
11108 (remp (and (assq 'remote apps) (org-file-remote-p file)))
11109 (dirp (if remp nil (file-directory-p file)))
11110 (dfile (downcase file))
11111 (old-buffer (current-buffer))
11112 (old-pos (point))
11113 (old-mode major-mode)
11114 ext cmd)
11115 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
11116 (setq ext (match-string 1 dfile))
11117 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
11118 (setq ext (match-string 1 dfile))))
11119 (if in-emacs
11120 (setq cmd 'emacs)
11121 (setq cmd (or (and remp (cdr (assoc 'remote apps)))
11122 (and dirp (cdr (assoc 'directory apps)))
11123 (cdr (assoc ext apps))
11124 (cdr (assoc t apps)))))
11125 (when (eq cmd 'mailcap)
11126 (require 'mailcap)
11127 (mailcap-parse-mailcaps)
11128 (let* ((mime-type (mailcap-extension-to-mime (or ext "")))
11129 (command (mailcap-mime-info mime-type)))
11130 (if (stringp command)
11131 (setq cmd command)
11132 (setq cmd 'emacs))))
11133 (if (and (not (eq cmd 'emacs)) ; Emacs has no problems with non-ex files
11134 (not (file-exists-p file))
11135 (not org-open-non-existing-files))
11136 (error "No such file: %s" file))
11137 (cond
11138 ((and (stringp cmd) (not (string-match "^\\s-*$" cmd)))
11139 ;; Remove quotes around the file name - we'll use shell-quote-argument.
11140 (if (string-match "['\"]%s['\"]" cmd)
11141 (setq cmd (replace-match "%s" t t cmd)))
11142 (setq cmd (format cmd (shell-quote-argument file)))
11143 (save-window-excursion
11144 (shell-command (concat cmd " &"))))
11145 ((or (stringp cmd)
11146 (eq cmd 'emacs))
11147 (funcall (cdr (assq 'file org-link-frame-setup)) file)
11148 (if line (goto-line line)
11149 (if search (org-link-search search))))
11150 ((consp cmd)
11151 (eval cmd))
11152 (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
11153 (and (org-mode-p) (eq old-mode 'org-mode)
11154 (or (not (equal old-buffer (current-buffer)))
11155 (not (equal old-pos (point))))
11156 (org-mark-ring-push old-pos old-buffer))))
11158 (defun org-default-apps ()
11159 "Return the default applications for this operating system."
11160 (cond
11161 ((eq system-type 'darwin)
11162 org-file-apps-defaults-macosx)
11163 ((eq system-type 'windows-nt)
11164 org-file-apps-defaults-windowsnt)
11165 (t org-file-apps-defaults-gnu)))
11167 (defvar ange-ftp-name-format) ; to silence the XEmacs compiler.
11168 (defun org-file-remote-p (file)
11169 "Test whether FILE specifies a location on a remote system.
11170 Return non-nil if the location is indeed remote.
11172 For example, the filename \"/user@host:/foo\" specifies a location
11173 on the system \"/user@host:\"."
11174 (cond ((fboundp 'file-remote-p)
11175 (file-remote-p file))
11176 ((fboundp 'tramp-handle-file-remote-p)
11177 (tramp-handle-file-remote-p file))
11178 ((and (boundp 'ange-ftp-name-format)
11179 (string-match (car ange-ftp-name-format) file))
11181 (t nil)))
11184 ;;;; Hooks for remember.el
11186 ;;;###autoload
11187 (defun org-remember-annotation ()
11188 "Return a link to the current location as an annotation for remember.el.
11189 If you are using Org-mode files as target for data storage with
11190 remember.el, then the annotations should include a link compatible with the
11191 conventions in Org-mode. This function returns such a link."
11192 (org-store-link nil))
11194 (defconst org-remember-help
11195 "Select a destination location for the note.
11196 UP/DOWN=headline TAB=cycle visibility [Q]uit RET/<left>/<right>=Store
11197 RET at beg-of-buf -> Append to file as level 2 headline
11198 RET on headline -> Store as sublevel entry to current headline
11199 <left>/<right> -> before/after current headline, same headings level")
11201 ;;;###autoload
11202 (defun org-remember-apply-template (&optional use-char skip-interactive)
11203 "Initialize *remember* buffer with template, invoke `org-mode'.
11204 This function should be placed into `remember-mode-hook' and in fact requires
11205 to be run from that hook to fucntion properly."
11206 (if org-remember-templates
11208 (let* ((char (or use-char
11209 (if (= (length org-remember-templates) 1)
11210 (caar org-remember-templates)
11211 (message "Select template: %s"
11212 (mapconcat
11213 (lambda (x) (char-to-string (car x)))
11214 org-remember-templates " "))
11215 (read-char-exclusive))))
11216 (entry (cdr (assoc char org-remember-templates)))
11217 (tpl (car entry))
11218 (plist-p (if org-store-link-plist t nil))
11219 (file (if (and (nth 1 entry) (stringp (nth 1 entry))
11220 (string-match "\\S-" (nth 1 entry)))
11221 (nth 1 entry)
11222 org-default-notes-file))
11223 (headline (nth 2 entry))
11224 (v-t (format-time-string (car org-time-stamp-formats) (org-current-time)))
11225 (v-T (format-time-string (cdr org-time-stamp-formats) (org-current-time)))
11226 (v-u (concat "[" (substring v-t 1 -1) "]"))
11227 (v-U (concat "[" (substring v-T 1 -1) "]"))
11228 (v-i initial) ; defined in `remember-mode'
11229 (v-a (if (equal annotation "[[]]") "" annotation)) ; likewise
11230 (v-n user-full-name)
11231 (org-startup-folded nil)
11232 org-time-was-given x prompt char time)
11233 (setq org-store-link-plist
11234 (append (list :annotation v-a :initial v-i)))
11235 (unless tpl (setq tpl "") (message "No template") (ding))
11236 (erase-buffer)
11237 (insert (substitute-command-keys
11238 (format
11239 "## `C-c C-c' to file interactively, `C-u C-c C-c' to file directly.
11240 ## Target file \"%s\", headline \"%s\"
11241 ## To switch templates, use `\\[org-remember]'.\n\n"
11242 (abbreviate-file-name (or file org-default-notes-file))
11243 (or headline ""))))
11244 (insert tpl) (goto-char (point-min))
11245 ;; Simple %-escapes
11246 (while (re-search-forward "%\\([tTuUai]\\)" nil t)
11247 (when (and initial (equal (match-string 0) "%i"))
11248 (save-match-data
11249 (let* ((lead (buffer-substring
11250 (point-at-bol) (match-beginning 0))))
11251 (setq v-i (mapconcat 'identity
11252 (org-split-string initial "\n")
11253 (concat "\n" lead))))))
11254 (replace-match
11255 (or (eval (intern (concat "v-" (match-string 1)))) "")
11256 t t))
11257 ;; From the property list
11258 (when plist-p
11259 (goto-char (point-min))
11260 (while (re-search-forward "%\\(:[-a-zA-Z]+\\)" nil t)
11261 (and (setq x (plist-get org-store-link-plist
11262 (intern (match-string 1))))
11263 (replace-match x t t))))
11264 ;; Turn on org-mode in the remember buffer, set local variables
11265 (org-mode)
11266 (org-set-local 'org-finish-function 'remember-buffer)
11267 (if (and file (string-match "\\S-" file) (not (file-directory-p file)))
11268 (org-set-local 'org-default-notes-file file))
11269 (if (and headline (stringp headline) (string-match "\\S-" headline))
11270 (org-set-local 'org-remember-default-headline headline))
11271 ;; Interactive template entries
11272 (goto-char (point-min))
11273 (while (re-search-forward "%^\\({\\([^}]*\\)}\\)?\\([uUtT]\\)?" nil t)
11274 (setq char (if (match-end 3) (match-string 3))
11275 prompt (if (match-end 2) (match-string 2)))
11276 (goto-char (match-beginning 0))
11277 (replace-match "")
11278 (if char
11279 (progn
11280 (setq org-time-was-given (equal (upcase char) char))
11281 (setq time (org-read-date (equal (upcase char) "U") t nil
11282 prompt))
11283 (org-insert-time-stamp time org-time-was-given
11284 (member char '("u" "U"))))
11285 (insert (read-string
11286 (if prompt (concat prompt ": ") "Enter string")))))
11287 (goto-char (point-min))
11288 (if (re-search-forward "%\\?" nil t)
11289 (replace-match "")
11290 (and (re-search-forward "^[^#\n]" nil t) (backward-char 1))))
11291 (org-mode)
11292 (org-set-local 'org-finish-function 'remember-buffer)))
11294 ;;;###autoload
11295 (defun org-remember ()
11296 "Call `remember'. If this is already a remember buffer, re-apply template.
11297 If there is an active region, make sure remember uses it as initial content
11298 of the remember buffer."
11299 (interactive)
11300 (if (eq org-finish-function 'remember-buffer)
11301 (progn
11302 (when (< (length org-remember-templates) 2)
11303 (error "No other template available"))
11304 (erase-buffer)
11305 (let ((annotation (plist-get org-store-link-plist :annotation))
11306 (initial (plist-get org-store-link-plist :initial)))
11307 (org-remember-apply-template))
11308 (message "Press C-c C-c to remember data"))
11309 (if (org-region-active-p)
11310 (remember (buffer-substring (point) (mark)))
11311 (call-interactively 'remember))))
11313 ;;;###autoload
11314 (defun org-remember-handler ()
11315 "Store stuff from remember.el into an org file.
11316 First prompts for an org file. If the user just presses return, the value
11317 of `org-default-notes-file' is used.
11318 Then the command offers the headings tree of the selected file in order to
11319 file the text at a specific location.
11320 You can either immediately press RET to get the note appended to the
11321 file, or you can use vertical cursor motion and visibility cycling (TAB) to
11322 find a better place. Then press RET or <left> or <right> in insert the note.
11324 Key Cursor position Note gets inserted
11325 -----------------------------------------------------------------------------
11326 RET buffer-start as level 2 heading at end of file
11327 RET on headline as sublevel of the heading at cursor
11328 RET no heading at cursor position, level taken from context.
11329 Or use prefix arg to specify level manually.
11330 <left> on headline as same level, before current heading
11331 <right> on headline as same level, after current heading
11333 So the fastest way to store the note is to press RET RET to append it to
11334 the default file. This way your current train of thought is not
11335 interrupted, in accordance with the principles of remember.el. But with
11336 little extra effort, you can push it directly to the correct location.
11338 Before being stored away, the function ensures that the text has a
11339 headline, i.e. a first line that starts with a \"*\". If not, a headline
11340 is constructed from the current date and some additional data.
11342 If the variable `org-adapt-indentation' is non-nil, the entire text is
11343 also indented so that it starts in the same column as the headline
11344 \(i.e. after the stars).
11346 See also the variable `org-reverse-note-order'."
11347 (goto-char (point-min))
11348 (while (looking-at "^[ \t]*\n\\|^##.*\n")
11349 (replace-match ""))
11350 (catch 'quit
11351 (let* ((txt (buffer-substring (point-min) (point-max)))
11352 (fastp (equal current-prefix-arg '(4)))
11353 (file (if fastp org-default-notes-file (org-get-org-file)))
11354 (heading org-remember-default-headline)
11355 (visiting (org-find-base-buffer-visiting file))
11356 (org-startup-folded nil)
11357 (org-startup-align-all-tables nil)
11358 (org-goto-start-pos 1)
11359 spos level indent reversed)
11360 (setq current-prefix-arg nil)
11361 ;; Modify text so that it becomes a nice subtree which can be inserted
11362 ;; into an org tree.
11363 (let* ((lines (split-string txt "\n"))
11364 first)
11365 (setq first (car lines) lines (cdr lines))
11366 (if (string-match "^\\*+" first)
11367 ;; Is already a headline
11368 (setq indent nil)
11369 ;; We need to add a headline: Use time and first buffer line
11370 (setq lines (cons first lines)
11371 first (concat "* " (current-time-string)
11372 " (" (remember-buffer-desc) ")")
11373 indent " "))
11374 (if (and org-adapt-indentation indent)
11375 (setq lines (mapcar (lambda (x) (concat indent x)) lines)))
11376 (setq txt (concat first "\n"
11377 (mapconcat 'identity lines "\n"))))
11378 ;; Find the file
11379 (if (not visiting) (find-file-noselect file))
11380 (with-current-buffer (or visiting (get-file-buffer file))
11381 (save-excursion
11382 (save-restriction
11383 (widen)
11384 (and (goto-char (point-min))
11385 (not (re-search-forward "^\\* " nil t))
11386 (insert "\n* Notes\n"))
11387 (setq reversed (org-notes-order-reversed-p))
11389 ;; Find the default location
11390 (when (and heading (stringp heading) (string-match "\\S-" heading))
11391 (goto-char (point-min))
11392 (if (re-search-forward
11393 (concat "^\\*+[ \t]+" (regexp-quote heading)
11394 "\\([ \t]+:[@a-zA-Z0-9_:]*\\)?[ \t]*$")
11395 nil t)
11396 (setq org-goto-start-pos (match-beginning 0))))
11398 ;; Ask the User for a location
11399 (setq spos (if fastp
11400 org-goto-start-pos
11401 (org-get-location (current-buffer) org-remember-help)))
11402 (if (not spos) (throw 'quit nil)) ; return nil to show we did
11403 ; not handle this note
11404 (goto-char spos)
11405 (cond ((and (bobp) (not reversed))
11406 ;; Put it at the end, one level below level 1
11407 (save-restriction
11408 (widen)
11409 (goto-char (point-max))
11410 (if (not (bolp)) (newline))
11411 (org-paste-subtree (org-get-legal-level 1 1) txt)))
11412 ((and (bobp) reversed)
11413 ;; Put it at the start, as level 1
11414 (save-restriction
11415 (widen)
11416 (goto-char (point-min))
11417 (re-search-forward "^\\*" nil t)
11418 (beginning-of-line 1)
11419 (org-paste-subtree 1 txt)))
11420 ((and (org-on-heading-p t) (not current-prefix-arg))
11421 ;; Put it below this entry, at the beg/end of the subtree
11422 (org-back-to-heading t)
11423 (setq level (funcall outline-level))
11424 (if reversed
11425 (outline-next-heading)
11426 (org-end-of-subtree t))
11427 (if (not (bolp)) (newline))
11428 (beginning-of-line 1)
11429 (org-paste-subtree (org-get-legal-level level 1) txt))
11431 ;; Put it right there, with automatic level determined by
11432 ;; org-paste-subtree or from prefix arg
11433 (org-paste-subtree
11434 (if (numberp current-prefix-arg) current-prefix-arg)
11435 txt)))
11436 (when remember-save-after-remembering
11437 (save-buffer)
11438 (if (not visiting) (kill-buffer (current-buffer)))))))))
11439 t) ;; return t to indicate that we took care of this note.
11441 (defun org-get-org-file ()
11442 "Read a filename, with default directory `org-directory'."
11443 (let ((default (or org-default-notes-file remember-data-file)))
11444 (read-file-name (format "File name [%s]: " default)
11445 (file-name-as-directory org-directory)
11446 default)))
11448 (defun org-notes-order-reversed-p ()
11449 "Check if the current file should receive notes in reversed order."
11450 (cond
11451 ((not org-reverse-note-order) nil)
11452 ((eq t org-reverse-note-order) t)
11453 ((not (listp org-reverse-note-order)) nil)
11454 (t (catch 'exit
11455 (let ((all org-reverse-note-order)
11456 entry)
11457 (while (setq entry (pop all))
11458 (if (string-match (car entry) buffer-file-name)
11459 (throw 'exit (cdr entry))))
11460 nil)))))
11462 ;;;; Dynamic blocks
11464 (defun org-find-dblock (name)
11465 "Find the first dynamic block with name NAME in the buffer.
11466 If not found, stay at current position and return nil."
11467 (let (pos)
11468 (save-excursion
11469 (goto-char (point-min))
11470 (setq pos (and (re-search-forward (concat "^#\\+BEGIN:[ \t]+" name "\\>")
11471 nil t)
11472 (match-beginning 0))))
11473 (if pos (goto-char pos))
11474 pos))
11476 (defconst org-dblock-start-re
11477 "^#\\+BEGIN:[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?"
11478 "Matches the startline of a dynamic block, with parameters.")
11480 (defconst org-dblock-end-re "^#\\+END\\([: \t\r\n]\\|$\\)"
11481 "Matches the end of a dyhamic block.")
11483 (defun org-create-dblock (plist)
11484 "Create a dynamic block section, with parameters taken from PLIST.
11485 PLIST must containe a :name entry which is used as name of the block."
11486 (unless (bolp) (newline))
11487 (let ((name (plist-get plist :name)))
11488 (insert "#+BEGIN: " name)
11489 (while plist
11490 (if (eq (car plist) :name)
11491 (setq plist (cddr plist))
11492 (insert " " (prin1-to-string (pop plist)))))
11493 (insert "\n\n#+END:\n")
11494 (beginning-of-line -2)))
11496 (defun org-prepare-dblock ()
11497 "Prepare dynamic block for refresh.
11498 This empties the block, puts the cursor at the insert position and returns
11499 the property list including an extra property :name with the block name."
11500 (unless (looking-at org-dblock-start-re)
11501 (error "Not at a dynamic block"))
11502 (let* ((begdel (1+ (match-end 0)))
11503 (name (match-string 1))
11504 (params (append (list :name name)
11505 (read (concat "(" (match-string 3) ")")))))
11506 (unless (re-search-forward org-dblock-end-re nil t)
11507 (error "Dynamic block not terminated"))
11508 (delete-region begdel (match-beginning 0))
11509 (goto-char begdel)
11510 (open-line 1)
11511 params))
11513 (defun org-map-dblocks (&optional command)
11514 "Apply COMMAND to all dynamic blocks in the current buffer.
11515 If COMMAND is not given, use `org-update-dblock'."
11516 (let ((cmd (or command 'org-update-dblock))
11517 pos)
11518 (save-excursion
11519 (goto-char (point-min))
11520 (while (re-search-forward org-dblock-start-re nil t)
11521 (goto-char (setq pos (match-beginning 0)))
11522 (condition-case nil
11523 (funcall cmd)
11524 (error (message "Error during update of dynamic block")))
11525 (goto-char pos)
11526 (unless (re-search-forward org-dblock-end-re nil t)
11527 (error "Dynamic block not terminated"))))))
11529 (defun org-dblock-update (&optional arg)
11530 "User command for updating dynamic blocks.
11531 Update the dynamic block at point. With prefix ARG, update all dynamic
11532 blocks in the buffer."
11533 (interactive "P")
11534 (if arg
11535 (org-update-all-dblocks)
11536 (or (looking-at org-dblock-start-re)
11537 (org-beginning-of-dblock))
11538 (org-update-dblock)))
11540 (defun org-update-dblock ()
11541 "Update the dynamic block at point
11542 This means to empty the block, parse for parameters and then call
11543 the correct writing function."
11544 (let* ((pos (point))
11545 (params (org-prepare-dblock))
11546 (name (plist-get params :name))
11547 (cmd (intern (concat "org-dblock-write:" name))))
11548 (funcall cmd params)
11549 (goto-char pos)))
11551 (defun org-beginning-of-dblock ()
11552 "Find the beginning of the dynamic block at point.
11553 Error if there is no scuh block at point."
11554 (let ((pos (point))
11555 beg)
11556 (end-of-line 1)
11557 (if (and (re-search-backward org-dblock-start-re nil t)
11558 (setq beg (match-beginning 0))
11559 (re-search-forward org-dblock-end-re nil t)
11560 (> (match-end 0) pos))
11561 (goto-char beg)
11562 (goto-char pos)
11563 (error "Not in a dynamic block"))))
11565 (defun org-update-all-dblocks ()
11566 "Update all dynamic blocks in the buffer.
11567 This function can be used in a hook."
11568 (when (org-mode-p)
11569 (org-map-dblocks 'org-update-dblock)))
11572 ;;;; Completion
11574 (defun org-complete (&optional arg)
11575 "Perform completion on word at point.
11576 At the beginning of a headline, this completes TODO keywords as given in
11577 `org-todo-keywords'.
11578 If the current word is preceded by a backslash, completes the TeX symbols
11579 that are supported for HTML support.
11580 If the current word is preceded by \"#+\", completes special words for
11581 setting file options.
11582 In the line after \"#+STARTUP:, complete valid keywords.\"
11583 At all other locations, this simply calls `ispell-complete-word'."
11584 (interactive "P")
11585 (catch 'exit
11586 (let* ((end (point))
11587 (beg1 (save-excursion
11588 (skip-chars-backward "a-zA-Z_@0-9")
11589 (point)))
11590 (beg (save-excursion
11591 (skip-chars-backward "a-zA-Z0-9_:$")
11592 (point)))
11593 (confirm (lambda (x) (stringp (car x))))
11594 (searchhead (equal (char-before beg) ?*))
11595 (tag (equal (char-before beg1) ?:))
11596 (texp (equal (char-before beg) ?\\))
11597 (link (equal (char-before beg) ?\[))
11598 (opt (equal (buffer-substring (max (point-at-bol) (- beg 2))
11599 beg)
11600 "#+"))
11601 (startup (string-match "^#\\+STARTUP:.*"
11602 (buffer-substring (point-at-bol) (point))))
11603 (completion-ignore-case opt)
11604 (type nil)
11605 (tbl nil)
11606 (table (cond
11607 (opt
11608 (setq type :opt)
11609 (mapcar (lambda (x)
11610 (string-match "^#\\+\\(\\([A-Z_]+:?\\).*\\)" x)
11611 (cons (match-string 2 x) (match-string 1 x)))
11612 (org-split-string (org-get-current-options) "\n")))
11613 (startup
11614 (setq type :startup)
11615 org-startup-options)
11616 (link (append org-link-abbrev-alist-local
11617 org-link-abbrev-alist))
11618 (texp
11619 (setq type :tex)
11620 org-html-entities)
11621 ((string-match "\\`\\*+[ \t]*\\'"
11622 (buffer-substring (point-at-bol) beg))
11623 (setq type :todo)
11624 (mapcar 'list org-todo-keywords-1))
11625 (searchhead
11626 (setq type :searchhead)
11627 (save-excursion
11628 (goto-char (point-min))
11629 (while (re-search-forward org-todo-line-regexp nil t)
11630 (push (list
11631 (org-make-org-heading-search-string
11632 (match-string 3) t))
11633 tbl)))
11634 tbl)
11635 (tag (setq type :tag beg beg1)
11636 (or org-tag-alist (org-get-buffer-tags)))
11637 (t (progn (ispell-complete-word arg) (throw 'exit nil)))))
11638 (pattern (buffer-substring-no-properties beg end))
11639 (completion (try-completion pattern table confirm)))
11640 (cond ((eq completion t)
11641 (if (equal type :opt)
11642 (insert (substring (cdr (assoc (upcase pattern) table))
11643 (length pattern)))
11644 (if (equal type :tag) (insert ":"))))
11645 ((null completion)
11646 (message "Can't find completion for \"%s\"" pattern)
11647 (ding))
11648 ((not (string= pattern completion))
11649 (delete-region beg end)
11650 (if (string-match " +$" completion)
11651 (setq completion (replace-match "" t t completion)))
11652 (insert completion)
11653 (if (get-buffer-window "*Completions*")
11654 (delete-window (get-buffer-window "*Completions*")))
11655 (if (assoc completion table)
11656 (if (eq type :todo) (insert " ")
11657 (if (eq type :tag) (insert ":"))))
11658 (if (and (equal type :opt) (assoc completion table))
11659 (message "%s" (substitute-command-keys
11660 "Press \\[org-complete] again to insert example settings"))))
11662 (message "Making completion list...")
11663 (let ((list (sort (all-completions pattern table confirm)
11664 'string<)))
11665 (with-output-to-temp-buffer "*Completions*"
11666 (condition-case nil
11667 ;; Protection needed for XEmacs and emacs 21
11668 (display-completion-list list pattern)
11669 (error (display-completion-list list)))))
11670 (message "Making completion list...%s" "done"))))))
11672 ;;;; TODO, DEADLINE, Comments
11674 (defun org-toggle-comment ()
11675 "Change the COMMENT state of an entry."
11676 (interactive)
11677 (save-excursion
11678 (org-back-to-heading)
11679 (if (looking-at (concat outline-regexp
11680 "\\( +\\<" org-comment-string "\\>\\)"))
11681 (replace-match "" t t nil 1)
11682 (if (looking-at outline-regexp)
11683 (progn
11684 (goto-char (match-end 0))
11685 (insert " " org-comment-string))))))
11687 (defvar org-last-todo-state-is-todo nil
11688 "This is non-nil when the last TODO state change led to a TODO state.
11689 If the last change removed the TODO tag or switched to DONE, then
11690 this is nil.")
11692 (defun org-todo (&optional arg)
11693 "Change the TODO state of an item.
11694 The state of an item is given by a keyword at the start of the heading,
11695 like
11696 *** TODO Write paper
11697 *** DONE Call mom
11699 The different keywords are specified in the variable `org-todo-keywords'.
11700 By default the available states are \"TODO\" and \"DONE\".
11701 So for this example: when the item starts with TODO, it is changed to DONE.
11702 When it starts with DONE, the DONE is removed. And when neither TODO nor
11703 DONE are present, add TODO at the beginning of the heading.
11705 With C-u prefix arg, use completion to determine the new state.
11706 With numeric prefix arg, switch to that state.
11708 For calling through lisp, arg is also interpreted in the following way:
11709 'none -> empty state
11710 \"\"(empty string) -> switch to empty state
11711 'done -> switch to DONE
11712 'nextset -> switch to the next set of keywords
11713 'previousset -> switch to the previous set of keywords
11714 \"WAITING\" -> switch to the specified keyword, but only if it
11715 really is a member of `org-todo-keywords'."
11716 (interactive "P")
11717 (save-excursion
11718 (org-back-to-heading)
11719 (if (looking-at outline-regexp) (goto-char (match-end 0)))
11720 (or (looking-at (concat " +" org-todo-regexp " *"))
11721 (looking-at " *"))
11722 (let* ((this (match-string 1))
11723 (head (org-get-todo-sequence-head this))
11724 (ass (assoc head org-todo-kwd-alist))
11725 (interpret (nth 1 ass))
11726 (done-word (nth 3 ass))
11727 (final-done-word (nth 4 ass))
11728 (last-state (or this ""))
11729 (completion-ignore-case t)
11730 (member (member this org-todo-keywords-1))
11731 (tail (cdr member))
11732 (state (cond
11733 ((equal arg '(4))
11734 ;; Read a state with completion
11735 (completing-read "State: " (mapcar (lambda(x) (list x))
11736 org-todo-keywords-1)
11737 nil t))
11738 ((eq arg 'right)
11739 (if this
11740 (if tail (car tail) nil)
11741 (car org-todo-keywords-1)))
11742 ((eq arg 'left)
11743 (if (equal member org-todo-keywords-1)
11745 (if this
11746 (nth (- (length org-todo-keywords-1) (length tail) 2)
11747 org-todo-keywords-1)
11748 (org-last org-todo-keywords-1))))
11749 (arg
11750 ;; user or caller requests a specific state
11751 (cond
11752 ((equal arg "") nil)
11753 ((eq arg 'none) nil)
11754 ((eq arg 'done) (or done-word (car org-done-keywords)))
11755 ((eq arg 'nextset)
11756 (or (car (cdr (member head org-todo-heads)))
11757 (car org-todo-heads)))
11758 ((eq arg 'previousset)
11759 (let ((org-todo-heads (reverse org-todo-heads)))
11760 (or (car (cdr (member head org-todo-heads)))
11761 (car org-todo-heads))))
11762 ((car (member arg org-todo-keywords-1)))
11763 ((nth (1- (prefix-numeric-value arg))
11764 org-todo-keywords-1))))
11765 ((null member) (or head (car org-todo-keywords-1)))
11766 ((equal this final-done-word) nil) ;; -> make empty
11767 ((null tail) nil) ;; -> first entry
11768 ((eq interpret 'sequence)
11769 (car tail))
11770 ((memq interpret '(type priority))
11771 (if (eq this-command last-command)
11772 (car tail)
11773 (if (> (length tail) 0)
11774 (or done-word (car org-done-keywords))
11775 nil)))
11776 (t nil)))
11777 (next (if state (concat " " state " ") " "))
11778 dostates)
11779 (replace-match next t t)
11780 (unless head
11781 (setq head (org-get-todo-sequence-head state)
11782 ass (assoc head org-todo-kwd-alist)
11783 interpret (nth 1 ass)
11784 done-word (nth 3 ass)
11785 final-done-word (nth 4 ass)))
11786 (when (memq arg '(nextset previousset))
11787 (message "Keyword set: %s"
11788 (mapconcat 'identity (assoc state org-todo-sets) " ")))
11789 (setq org-last-todo-state-is-todo
11790 (not (member state org-done-keywords)))
11791 (when (and org-log-done (not (memq arg '(nextset previousset))))
11792 (setq dostates (and (eq interpret 'sequence)
11793 (listp org-log-done) (memq 'state org-log-done)))
11794 (cond
11795 ((and state (not this))
11796 (org-add-planning-info nil nil 'closed)
11797 (and dostates (org-add-log-maybe 'state state 'findpos)))
11798 ((and state dostates)
11799 (org-add-log-maybe 'state state 'findpos))
11800 ((member state org-done-keywords)
11801 ;; Planning info calls the note-setting command.
11802 (org-add-planning-info 'closed (org-current-time)
11803 (if (org-get-repeat) nil 'scheduled))
11804 (org-add-log-maybe 'done state 'findpos))))
11805 ;; Fixup tag positioning
11806 (and org-auto-align-tags (org-set-tags nil t))
11807 (run-hooks 'org-after-todo-state-change-hook)
11808 (and (member state org-done-keywords) (org-auto-repeat-maybe))
11809 (if (and arg (not (member state org-done-keywords)))
11810 (setq head (org-get-todo-sequence-head state)))
11811 (put-text-property (point-at-bol) (point-at-eol) 'org-todo-head head)))
11812 ;; Fixup cursor location if close to the keyword
11813 (if (and (outline-on-heading-p)
11814 (not (bolp))
11815 (save-excursion (beginning-of-line 1)
11816 (looking-at org-todo-line-regexp))
11817 (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
11818 (progn
11819 (goto-char (or (match-end 2) (match-end 1)))
11820 (just-one-space))))
11822 (defun org-get-todo-sequence-head (kwd)
11823 "Return the head of the TODO sequence to which KWD belongs.
11824 If KWD is not set, check if there is a text property remembering the
11825 right sequence."
11826 (let (p)
11827 (cond
11828 ((not kwd)
11829 (or (get-text-property (point-at-bol) 'org-todo-head)
11830 (progn
11831 (setq p (next-single-property-change (point-at-bol) 'org-todo-head
11832 nil (point-at-eol)))
11833 (get-text-property p 'org-todo-head))))
11834 ((not (member kwd org-todo-keywords-1))
11835 (car org-todo-keywords-1))
11836 (t (nth 2 (assoc kwd org-todo-kwd-alist))))))
11838 (defun org-get-repeat ()
11839 "Check if tere is a deadline/schedule with repeater in this entry."
11840 (save-match-data
11841 (save-excursion
11842 (org-back-to-heading t)
11843 (if (re-search-forward
11844 org-repeat-re (save-excursion (outline-next-heading) (point)) t)
11845 (match-string 1)))))
11847 (defvar org-last-changed-timestamp)
11848 (defvar org-log-post-message)
11849 (defun org-auto-repeat-maybe ()
11850 "Check if the current headline contains a repeated deadline/schedule.
11851 If yes, set TODO state back to what it was and change the base date
11852 of repeating deadline/scheduled time stamps to new date.
11853 This function should be run in the `org-after-todo-state-change-hook'."
11854 ;; last-state is dynamically scoped into this function
11855 (let* ((repeat (org-get-repeat))
11856 (aa (assoc last-state org-todo-kwd-alist))
11857 (interpret (nth 1 aa))
11858 (head (nth 2 aa))
11859 (done-word (nth 3 aa))
11860 (whata '(("d" . day) ("m" . month) ("y" . year)))
11861 (msg "Entry repeats: ")
11862 (org-log-done)
11863 re type n what ts)
11864 (when repeat
11865 (org-todo (if (eq interpret 'type) last-state head))
11866 (when (and org-log-repeat
11867 (not (memq 'org-add-log-note
11868 (default-value 'post-command-hook))))
11869 ;; Make sure a note is taken
11870 (let ((org-log-done '(done)))
11871 (org-add-log-maybe 'done (or done-word (car org-done-keywords))
11872 'findpos)))
11873 (org-back-to-heading t)
11874 (org-add-planning-info nil nil 'closed)
11875 (setq re (concat "\\(" org-scheduled-time-regexp "\\)\\|\\("
11876 org-deadline-time-regexp "\\)"))
11877 (while (re-search-forward
11878 re (save-excursion (outline-next-heading) (point)) t)
11879 (setq type (if (match-end 1) org-scheduled-string org-deadline-string)
11880 ts (match-string (if (match-end 2) 2 4)))
11881 (when (string-match "\\([-+]?[0-9]+\\)\\([dwmy]\\)" ts)
11882 (setq n (string-to-number (match-string 1 ts))
11883 what (match-string 2 ts))
11884 (if (equal what "w") (setq n (* n 7) what "d"))
11885 (org-timestamp-change n (cdr (assoc what whata))))
11886 (setq msg (concat msg type org-last-changed-timestamp " ")))
11887 (setq org-log-post-message msg)
11888 (message msg))))
11890 (defun org-show-todo-tree (arg)
11891 "Make a compact tree which shows all headlines marked with TODO.
11892 The tree will show the lines where the regexp matches, and all higher
11893 headlines above the match.
11894 With \\[universal-argument] prefix, also show the DONE entries.
11895 With a numeric prefix N, construct a sparse tree for the Nth element
11896 of `org-todo-keywords-1'."
11897 (interactive "P")
11898 (let ((case-fold-search nil)
11899 (kwd-re
11900 (cond ((null arg) org-not-done-regexp)
11901 ((equal arg '(4))
11902 (let ((kwd (completing-read "Keyword (or KWD1|KWD2|...): "
11903 (mapcar 'list org-todo-keywords-1))))
11904 (concat "\\("
11905 (mapconcat 'identity (org-split-string kwd "|") "\\|")
11906 "\\)\\>")))
11907 ((<= (prefix-numeric-value arg) (length org-todo-keywords-1))
11908 (regexp-quote (nth (1- (prefix-numeric-value arg))
11909 org-todo-keywords-1)))
11910 (t (error "Invalid prefix argument: %s" arg)))))
11911 (message "%d TODO entries found"
11912 (org-occur (concat "^" outline-regexp " +" kwd-re )))))
11914 (defun org-deadline ()
11915 "Insert the DEADLINE: string to make a deadline.
11916 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
11917 to modify it to the correct date."
11918 (interactive)
11919 (org-add-planning-info 'deadline nil 'closed))
11921 (defun org-schedule ()
11922 "Insert the SCHEDULED: string to schedule a TODO item.
11923 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
11924 to modify it to the correct date."
11925 (interactive)
11926 (org-add-planning-info 'scheduled nil 'closed))
11928 (defun org-add-planning-info (what &optional time &rest remove)
11929 "Insert new timestamp with keyword in the line directly after the headline.
11930 WHAT indicates what kind of time stamp to add. TIME indicated the time to use.
11931 If non is given, the user is prompted for a date.
11932 REMOVE indicates what kind of entries to remove. An old WHAT entry will also
11933 be removed."
11934 (interactive)
11935 (let (org-time-was-given)
11936 (when what (setq time (or time (org-read-date nil 'to-time))))
11937 (when (and org-insert-labeled-timestamps-at-point
11938 (member what '(scheduled deadline)))
11939 (insert
11940 (if (eq what 'scheduled) org-scheduled-string org-deadline-string) " ")
11941 (org-insert-time-stamp time org-time-was-given)
11942 (setq what nil))
11943 (save-excursion
11944 (save-restriction
11945 (let (col list elt ts buffer-invisibility-spec)
11946 (org-back-to-heading t)
11947 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"))
11948 (goto-char (match-end 1))
11949 (setq col (current-column))
11950 (goto-char (1+ (match-end 0)))
11951 (if (and (not (looking-at outline-regexp))
11952 (looking-at (concat "[^\r\n]*?" org-keyword-time-regexp
11953 "[^\r\n]*"))
11954 (not (equal (match-string 1) org-clock-string)))
11955 (narrow-to-region (match-beginning 0) (match-end 0))
11956 (insert "\n")
11957 (backward-char 1)
11958 (narrow-to-region (point) (point))
11959 (indent-to-column col))
11960 ;; Check if we have to remove something.
11961 (setq list (cons what remove))
11962 (while list
11963 (setq elt (pop list))
11964 (goto-char (point-min))
11965 (when (or (and (eq elt 'scheduled)
11966 (re-search-forward org-scheduled-time-regexp nil t))
11967 (and (eq elt 'deadline)
11968 (re-search-forward org-deadline-time-regexp nil t))
11969 (and (eq elt 'closed)
11970 (re-search-forward org-closed-time-regexp nil t)))
11971 (replace-match "")
11972 (if (looking-at "--+<[^>]+>") (replace-match ""))
11973 (if (looking-at " +") (replace-match ""))))
11974 (goto-char (point-max))
11975 (when what
11976 (insert
11977 (if (not (equal (char-before) ?\ )) " " "")
11978 (cond ((eq what 'scheduled) org-scheduled-string)
11979 ((eq what 'deadline) org-deadline-string)
11980 ((eq what 'closed) org-closed-string))
11981 " ")
11982 (org-insert-time-stamp
11983 time
11984 (or org-time-was-given
11985 (and (eq what 'closed) org-log-done-with-time))
11986 (eq what 'closed))
11987 (end-of-line 1))
11988 (goto-char (point-min))
11989 (widen)
11990 (if (looking-at "[ \t]+\r?\n")
11991 (replace-match ""))
11992 ts)))))
11994 (defvar org-log-note-marker (make-marker))
11995 (defvar org-log-note-purpose nil)
11996 (defvar org-log-note-state nil)
11997 (defvar org-log-note-window-configuration nil)
11998 (defvar org-log-note-return-to (make-marker))
11999 (defvar org-log-post-message nil
12000 "Message to be displayed after a log note has been stored.
12001 The auto-repeater uses this.")
12003 (defun org-add-log-maybe (&optional purpose state findpos)
12004 "FIXME"
12005 (save-excursion
12006 (when (and (listp org-log-done)
12007 (memq purpose org-log-done))
12008 (when findpos
12009 (org-back-to-heading t)
12010 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"
12011 "\\(\n[^\r\n]*?" org-keyword-time-not-clock-regexp
12012 "[^\r\n]*\\)?"))
12013 (goto-char (match-end 0)))
12014 (move-marker org-log-note-marker (point))
12015 (setq org-log-note-purpose purpose)
12016 (setq org-log-note-state state)
12017 (add-hook 'post-command-hook 'org-add-log-note 'append))))
12019 (defun org-add-log-note (&optional purpose)
12020 "Pop up a window for taking a note, and add this note later at point."
12021 (remove-hook 'post-command-hook 'org-add-log-note)
12022 (setq org-log-note-window-configuration (current-window-configuration))
12023 (delete-other-windows)
12024 (move-marker org-log-note-return-to (point))
12025 (switch-to-buffer (marker-buffer org-log-note-marker))
12026 (goto-char org-log-note-marker)
12027 (switch-to-buffer-other-window "*Org Note*")
12028 (erase-buffer)
12029 (let ((org-inhibit-startup t)) (org-mode))
12030 (insert (format "# Insert note for %s, finish with C-c C-c.\n\n"
12031 (cond
12032 ((eq org-log-note-purpose 'clock-out) "stopped clock")
12033 ((eq org-log-note-purpose 'done) "closed todo item")
12034 ((eq org-log-note-purpose 'state) "state change")
12035 (t (error "This should not happen")))))
12036 (org-set-local 'org-finish-function 'org-store-log-note))
12038 (defun org-store-log-note ()
12039 "Finish taking a log note, and insert it to where it belongs."
12040 (let ((txt (buffer-string))
12041 (note (cdr (assq org-log-note-purpose org-log-note-headings)))
12042 lines ind)
12043 (kill-buffer (current-buffer))
12044 (if (string-match "^#.*\n[ \t\n]*" txt)
12045 (setq txt (replace-match "" t t txt)))
12046 (if (string-match "\\s-+\\'" txt)
12047 (setq txt (replace-match "" t t txt)))
12048 (setq lines (org-split-string txt "\n"))
12049 (when (and note (string-match "\\S-" note))
12050 (setq note
12051 (org-replace-escapes
12052 note
12053 (list (cons "%u" (user-login-name))
12054 (cons "%U" user-full-name)
12055 (cons "%t" (format-time-string
12056 (org-time-stamp-format 'long 'inactive)
12057 (current-time)))
12058 (cons "%s" (if org-log-note-state
12059 (concat "\"" org-log-note-state "\"")
12060 "")))))
12061 (if lines (setq note (concat note " \\\\")))
12062 (push note lines))
12063 (when lines
12064 (save-excursion
12065 (set-buffer (marker-buffer org-log-note-marker))
12066 (save-excursion
12067 (goto-char org-log-note-marker)
12068 (move-marker org-log-note-marker nil)
12069 (end-of-line 1)
12070 (if (not (bolp)) (insert "\n")) (indent-relative nil)
12071 (setq ind (concat (buffer-substring (point-at-bol) (point)) " "))
12072 (insert " - " (pop lines))
12073 (while lines
12074 (insert "\n" ind (pop lines)))))))
12075 (set-window-configuration org-log-note-window-configuration)
12076 (with-current-buffer (marker-buffer org-log-note-return-to)
12077 (goto-char org-log-note-return-to))
12078 (move-marker org-log-note-return-to nil)
12079 (and org-log-post-message (message org-log-post-message)))
12081 (defvar org-occur-highlights nil)
12082 (make-variable-buffer-local 'org-occur-highlights)
12084 (defun org-occur (regexp &optional keep-previous callback)
12085 "Make a compact tree which shows all matches of REGEXP.
12086 The tree will show the lines where the regexp matches, and all higher
12087 headlines above the match. It will also show the heading after the match,
12088 to make sure editing the matching entry is easy.
12089 If KEEP-PREVIOUS is non-nil, highlighting and exposing done by a previous
12090 call to `org-occur' will be kept, to allow stacking of calls to this
12091 command.
12092 If CALLBACK is non-nil, it is a function which is called to confirm
12093 that the match should indeed be shown."
12094 (interactive "sRegexp: \nP")
12095 (or keep-previous (org-remove-occur-highlights nil nil t))
12096 (let ((cnt 0))
12097 (save-excursion
12098 (goto-char (point-min))
12099 (if (or (not keep-previous) ; do not want to keep
12100 (not org-occur-highlights)) ; no previous matches
12101 ;; hide everything
12102 (org-overview))
12103 (while (re-search-forward regexp nil t)
12104 (when (or (not callback)
12105 (save-match-data (funcall callback)))
12106 (setq cnt (1+ cnt))
12107 (when org-highlight-sparse-tree-matches
12108 (org-highlight-new-match (match-beginning 0) (match-end 0)))
12109 (org-show-context 'occur-tree))))
12110 (when org-remove-highlights-with-change
12111 (org-add-hook 'before-change-functions 'org-remove-occur-highlights
12112 nil 'local))
12113 (unless org-sparse-tree-open-archived-trees
12114 (org-hide-archived-subtrees (point-min) (point-max)))
12115 (run-hooks 'org-occur-hook)
12116 (if (interactive-p)
12117 (message "%d match(es) for regexp %s" cnt regexp))
12118 cnt))
12120 (defun org-show-context (&optional key)
12121 "Make sure point and context and visible.
12122 How much context is shown depends upon the variables
12123 `org-show-hierarchy-above', `org-show-following-heading'. and
12124 `org-show-siblings'."
12125 (let ((heading-p (org-on-heading-p t))
12126 (hierarchy-p (org-get-alist-option org-show-hierarchy-above key))
12127 (following-p (org-get-alist-option org-show-following-heading key))
12128 (siblings-p (org-get-alist-option org-show-siblings key)))
12129 (catch 'exit
12130 ;; Show heading or entry text
12131 (if heading-p
12132 (org-flag-heading nil) ; only show the heading
12133 (and (or (org-invisible-p) (org-invisible-p2))
12134 (org-show-hidden-entry))) ; show entire entry
12135 (when following-p
12136 ;; Show next sibling, or heading below text
12137 (save-excursion
12138 (and (if heading-p (org-goto-sibling) (outline-next-heading))
12139 (org-flag-heading nil))))
12140 (when siblings-p (org-show-siblings))
12141 (when hierarchy-p
12142 ;; show all higher headings, possibly with siblings
12143 (save-excursion
12144 (while (and (condition-case nil
12145 (progn (org-up-heading-all 1) t)
12146 (error nil))
12147 (not (bobp)))
12148 (org-flag-heading nil)
12149 (when siblings-p (org-show-siblings))))))))
12151 (defun org-reveal (&optional siblings)
12152 "Show current entry, hierarchy above it, and the following headline.
12153 This can be used to show a consistent set of context around locations
12154 exposed with `org-show-hierarchy-above' or `org-show-following-heading'
12155 not t for the search context.
12157 With optional argument SIBLINGS, on each level of the hierarchy all
12158 siblings are shown. This repairs the tree structure to what it would
12159 look like when opened with hierarchical calls to `org-cycle'."
12160 (interactive "P")
12161 (let ((org-show-hierarchy-above t)
12162 (org-show-following-heading t)
12163 (org-show-siblings (if siblings t org-show-siblings)))
12164 (org-show-context nil)))
12166 (defun org-highlight-new-match (beg end)
12167 "Highlight from BEG to END and mark the highlight is an occur headline."
12168 (let ((ov (org-make-overlay beg end)))
12169 (org-overlay-put ov 'face 'secondary-selection)
12170 (push ov org-occur-highlights)))
12172 (defun org-remove-occur-highlights (&optional beg end noremove)
12173 "Remove the occur highlights from the buffer.
12174 BEG and END are ignored. If NOREMOVE is nil, remove this function
12175 from the `before-change-functions' in the current buffer."
12176 (interactive)
12177 (unless org-inhibit-highlight-removal
12178 (mapc 'org-delete-overlay org-occur-highlights)
12179 (setq org-occur-highlights nil)
12180 (unless noremove
12181 (remove-hook 'before-change-functions
12182 'org-remove-occur-highlights 'local))))
12184 ;;;; Priorities
12186 (defvar org-priority-regexp ".*?\\(\\[#\\([A-Z0-9]\\)\\] ?\\)"
12187 "Regular expression matching the priority indicator.")
12189 (defvar org-remove-priority-next-time nil)
12191 (defun org-priority-up ()
12192 "Increase the priority of the current item."
12193 (interactive)
12194 (org-priority 'up))
12196 (defun org-priority-down ()
12197 "Decrease the priority of the current item."
12198 (interactive)
12199 (org-priority 'down))
12201 (defun org-priority (&optional action)
12202 "Change the priority of an item by ARG.
12203 ACTION can be set, up, or down."
12204 (interactive)
12205 (setq action (or action 'set))
12206 (let (current new news have remove)
12207 (save-excursion
12208 (org-back-to-heading)
12209 (if (looking-at org-priority-regexp)
12210 (setq current (string-to-char (match-string 2))
12211 have t)
12212 (setq current org-default-priority))
12213 (cond
12214 ((eq action 'set)
12215 (message "Priority %c-%c, SPC to remove: " org-highest-priority org-lowest-priority)
12216 (setq new (read-char-exclusive))
12217 (cond ((equal new ?\ ) (setq remove t))
12218 ((or (< (upcase new) org-highest-priority) (> (upcase new) org-lowest-priority))
12219 (error "Priority must be between `%c' and `%c'"
12220 org-highest-priority org-lowest-priority))))
12221 ((eq action 'up)
12222 (setq new (1- current)))
12223 ((eq action 'down)
12224 (setq new (1+ current)))
12225 (t (error "Invalid action")))
12226 (setq new (min (max org-highest-priority (upcase new)) org-lowest-priority))
12227 (setq news (format "%c" new))
12228 (if have
12229 (if remove
12230 (replace-match "" t t nil 1)
12231 (replace-match news t t nil 2))
12232 (if remove
12233 (error "No priority cookie found in line")
12234 (looking-at org-todo-line-regexp)
12235 (if (match-end 2)
12236 (progn
12237 (goto-char (match-end 2))
12238 (insert " [#" news "]"))
12239 (goto-char (match-beginning 3))
12240 (insert "[#" news "] ")))))
12241 (if remove
12242 (message "Priority removed")
12243 (message "Priority of current item set to %s" news))))
12246 (defun org-get-priority (s)
12247 "Find priority cookie and return priority."
12248 (save-match-data
12249 (if (not (string-match org-priority-regexp s))
12250 (* 1000 (- org-lowest-priority org-default-priority))
12251 (* 1000 (- org-lowest-priority
12252 (string-to-char (match-string 2 s)))))))
12254 ;;;; Tags
12256 (defun org-scan-tags (action matcher &optional todo-only)
12257 "Scan headline tags with inheritance and produce output ACTION.
12258 ACTION can be `sparse-tree' or `agenda'. MATCHER is a Lisp form to be
12259 evaluated, testing if a given set of tags qualifies a headline for
12260 inclusion. When TODO-ONLY is non-nil, only lines with a TODO keyword
12261 are included in the output."
12262 (let* ((re (concat "[\n\r]" outline-regexp " *\\(\\<\\("
12263 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
12264 "\\>\\)\\)? *\\(.*?\\)\\(:[A-Za-z_@0-9:]+:\\)?[ \t]*$"))
12265 (props (list 'face nil
12266 'done-face 'org-done
12267 'undone-face nil
12268 'mouse-face 'highlight
12269 'org-not-done-regexp org-not-done-regexp
12270 'org-todo-regexp org-todo-regexp
12271 'keymap org-agenda-keymap
12272 'help-echo
12273 (format "mouse-2 or RET jump to org file %s"
12274 (abbreviate-file-name buffer-file-name))))
12275 (case-fold-search nil)
12276 lspos
12277 tags tags-list tags-alist (llast 0) rtn level category i txt
12278 todo marker entry priority)
12279 (save-excursion
12280 (goto-char (point-min))
12281 (when (eq action 'sparse-tree) (org-overview))
12282 (while (re-search-forward re nil t)
12283 (catch :skip
12284 (setq todo (if (match-end 1) (match-string 2))
12285 tags (if (match-end 4) (match-string 4)))
12286 (goto-char (setq lspos (1+ (match-beginning 0))))
12287 (setq level (funcall outline-level)
12288 category (org-get-category))
12289 (setq i llast llast level)
12290 ;; remove tag lists from same and sublevels
12291 (while (>= i level)
12292 (when (setq entry (assoc i tags-alist))
12293 (setq tags-alist (delete entry tags-alist)))
12294 (setq i (1- i)))
12295 ;; add the nex tags
12296 (when tags
12297 (setq tags (mapcar 'downcase (org-split-string tags ":"))
12298 tags-alist
12299 (cons (cons level tags) tags-alist)))
12300 ;; compile tags for current headline
12301 (setq tags-list
12302 (if org-use-tag-inheritance
12303 (apply 'append (mapcar 'cdr tags-alist))
12304 tags))
12305 (when (and (or (not todo-only) (member todo org-not-done-keywords))
12306 (eval matcher)
12307 (or (not org-agenda-skip-archived-trees)
12308 (not (member org-archive-tag tags-list))))
12309 (and (eq action 'agenda) (org-agenda-skip))
12310 ;; list this headline
12311 (if (eq action 'sparse-tree)
12312 (progn
12313 (org-show-context 'tags-tree))
12314 (setq txt (org-format-agenda-item
12316 (concat
12317 (if org-tags-match-list-sublevels
12318 (make-string (1- level) ?.) "")
12319 (org-get-heading))
12320 category tags-list)
12321 priority (org-get-priority txt))
12322 (goto-char lspos)
12323 (setq marker (org-agenda-new-marker))
12324 (org-add-props txt props
12325 'org-marker marker 'org-hd-marker marker 'org-category category
12326 'priority priority 'type "tagsmatch")
12327 (push txt rtn))
12328 ;; if we are to skip sublevels, jump to end of subtree
12329 (or org-tags-match-list-sublevels (org-end-of-subtree t))))))
12330 (when (and (eq action 'sparse-tree)
12331 (not org-sparse-tree-open-archived-trees))
12332 (org-hide-archived-subtrees (point-min) (point-max)))
12333 (nreverse rtn)))
12335 (defvar todo-only) ;; dynamically scoped
12337 (defun org-tags-sparse-tree (&optional todo-only match)
12338 "Create a sparse tree according to tags string MATCH.
12339 MATCH can contain positive and negative selection of tags, like
12340 \"+WORK+URGENT-WITHBOSS\".
12341 If optional argument TODO_ONLY is non-nil, only select lines that are
12342 also TODO lines."
12343 (interactive "P")
12344 (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match)) todo-only))
12346 (defun org-make-tags-matcher (match)
12347 "Create the TAGS//TODO matcher form for the selection string MATCH."
12348 ;; todo-only is scoped dynamically into this function, and the function
12349 ;; may change it it the matcher asksk for it.
12350 (unless match
12351 ;; Get a new match request, with completion
12352 (setq org-last-tags-completion-table
12353 (or org-tag-alist
12354 org-last-tags-completion-table))
12355 (setq match (completing-read
12356 "Match: " 'org-tags-completion-function nil nil nil
12357 'org-tags-history)))
12359 ;; Parse the string and create a lisp form
12360 (let ((match0 match)
12361 (re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL=\\([0-9]+\\)\\|[A-Za-z_@0-9]+\\)")
12362 minus tag mm
12363 tagsmatch todomatch tagsmatcher todomatcher kwd matcher
12364 orterms term orlist re-p level-p)
12365 (if (string-match "/+" match)
12366 ;; match contains also a todo-matching request
12367 (progn
12368 (setq tagsmatch (substring match 0 (match-beginning 0))
12369 todomatch (substring match (match-end 0)))
12370 (if (string-match "^!" todomatch)
12371 (setq todo-only t todomatch (substring todomatch 1)))
12372 (if (string-match "^\\s-*$" todomatch)
12373 (setq todomatch nil)))
12374 ;; only matching tags
12375 (setq tagsmatch match todomatch nil))
12377 ;; Make the tags matcher
12378 (if (or (not tagsmatch) (not (string-match "\\S-" tagsmatch)))
12379 (setq tagsmatcher t)
12380 (setq orterms (org-split-string tagsmatch "|") orlist nil)
12381 (while (setq term (pop orterms))
12382 (while (and (equal (substring term -1) "\\") orterms)
12383 (setq term (concat term "|" (pop orterms)))) ; repair bad split
12384 (while (string-match re term)
12385 (setq minus (and (match-end 1)
12386 (equal (match-string 1 term) "-"))
12387 tag (match-string 2 term)
12388 re-p (equal (string-to-char tag) ?{)
12389 level-p (match-end 3)
12390 mm (cond
12391 (re-p `(org-match-any-p ,(substring tag 1 -1) tags-list))
12392 (level-p `(= level ,(string-to-number
12393 (match-string 3 term))))
12394 (t `(member ,(downcase tag) tags-list)))
12395 mm (if minus (list 'not mm) mm)
12396 term (substring term (match-end 0)))
12397 (push mm tagsmatcher))
12398 (push (if (> (length tagsmatcher) 1)
12399 (cons 'and tagsmatcher)
12400 (car tagsmatcher))
12401 orlist)
12402 (setq tagsmatcher nil))
12403 (setq tagsmatcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist))))
12405 ;; Make the todo matcher
12406 (if (or (not todomatch) (not (string-match "\\S-" todomatch)))
12407 (setq todomatcher t)
12408 (setq orterms (org-split-string todomatch "|") orlist nil)
12409 (while (setq term (pop orterms))
12410 (while (string-match re term)
12411 (setq minus (and (match-end 1)
12412 (equal (match-string 1 term) "-"))
12413 kwd (match-string 2 term)
12414 re-p (equal (string-to-char kwd) ?{)
12415 term (substring term (match-end 0))
12416 mm (if re-p
12417 `(string-match ,(substring kwd 1 -1) todo)
12418 (list 'equal 'todo kwd))
12419 mm (if minus (list 'not mm) mm))
12420 (push mm todomatcher))
12421 (push (if (> (length todomatcher) 1)
12422 (cons 'and todomatcher)
12423 (car todomatcher))
12424 orlist)
12425 (setq todomatcher nil))
12426 (setq todomatcher (if (> (length orlist) 1)
12427 (cons 'or orlist) (car orlist))))
12429 ;; Return the string and lisp forms of the matcher
12430 (setq matcher (if todomatcher
12431 (list 'and tagsmatcher todomatcher)
12432 tagsmatcher))
12433 (cons match0 matcher)))
12435 (defun org-match-any-p (re list)
12436 "Does re match any element of list?"
12437 (setq list (mapcar (lambda (x) (string-match re x)) list))
12438 (delq nil list))
12440 (defvar org-add-colon-after-tag-completion nil) ;; dynamically skoped param
12441 (defvar org-tags-overlay (org-make-overlay 1 1))
12442 (org-detach-overlay org-tags-overlay)
12444 (defun org-set-tags (&optional arg just-align)
12445 "Set the tags for the current headline.
12446 With prefix ARG, realign all tags in headings in the current buffer."
12447 (interactive "P")
12448 (let* ((re (concat "^" outline-regexp))
12449 (current (org-get-tags))
12450 table current-tags inherited-tags ; computed below when needed
12451 tags p0 c0 c1 rpl)
12452 (if arg
12453 (save-excursion
12454 (goto-char (point-min))
12455 (let ((buffer-invisibility-spec (org-inhibit-invisibility)))
12456 (while (re-search-forward re nil t)
12457 (org-set-tags nil t)
12458 (end-of-line 1)))
12459 (message "All tags realigned to column %d" org-tags-column))
12460 (if just-align
12461 (setq tags current)
12462 ;; Get a new set of tags from the user
12463 (save-excursion
12464 (setq table (or org-tag-alist (org-get-buffer-tags))
12465 org-last-tags-completion-table table
12466 current-tags (org-split-string current ":")
12467 inherited-tags (nreverse
12468 (nthcdr (length current-tags)
12469 (nreverse (org-get-tags-at))))
12470 tags
12471 (if (or (eq t org-use-fast-tag-selection)
12472 (and org-use-fast-tag-selection
12473 (delq nil (mapcar 'cdr table))))
12474 (org-fast-tag-selection current-tags inherited-tags table)
12475 (let ((org-add-colon-after-tag-completion t))
12476 (org-trim
12477 (completing-read "Tags: " 'org-tags-completion-function
12478 nil nil current 'org-tags-history))))))
12479 (while (string-match "[-+&]+" tags)
12480 ;; No boolean logic, just a list
12481 (setq tags (replace-match ":" t t tags))))
12483 (if (string-match "\\`[\t ]*\\'" tags)
12484 (setq tags "")
12485 (unless (string-match ":$" tags) (setq tags (concat tags ":")))
12486 (unless (string-match "^:" tags) (setq tags (concat ":" tags))))
12488 ;; Insert new tags at the correct column
12489 (beginning-of-line 1)
12490 (if (re-search-forward
12491 (concat "\\([ \t]*" (regexp-quote current) "\\)[ \t]*$")
12492 (point-at-eol) t)
12493 (progn
12494 (if (equal tags "")
12495 (setq rpl "")
12496 (goto-char (match-beginning 0))
12497 (setq c0 (current-column) p0 (point)
12498 c1 (max (1+ c0) (if (> org-tags-column 0)
12499 org-tags-column
12500 (- (- org-tags-column) (length tags))))
12501 rpl (concat (make-string (max 0 (- c1 c0)) ?\ ) tags)))
12502 (replace-match rpl t t)
12503 (and (not (featurep 'xemacs)) c0 (tabify p0 (point)))
12504 tags)
12505 (error "Tags alignment failed")))))
12507 (defun org-tags-completion-function (string predicate &optional flag)
12508 (let (s1 s2 rtn (ctable org-last-tags-completion-table)
12509 (confirm (lambda (x) (stringp (car x)))))
12510 (if (string-match "^\\(.*[-+:&|]\\)\\([^-+:&|]*\\)$" string)
12511 (setq s1 (match-string 1 string)
12512 s2 (match-string 2 string))
12513 (setq s1 "" s2 string))
12514 (cond
12515 ((eq flag nil)
12516 ;; try completion
12517 (setq rtn (try-completion s2 ctable confirm))
12518 (if (stringp rtn)
12519 (concat s1 s2 (substring rtn (length s2))
12520 (if (and org-add-colon-after-tag-completion
12521 (assoc rtn ctable))
12522 ":" "")))
12524 ((eq flag t)
12525 ;; all-completions
12526 (all-completions s2 ctable confirm)
12528 ((eq flag 'lambda)
12529 ;; exact match?
12530 (assoc s2 ctable)))
12533 (defun org-fast-tag-insert (kwd tags face &optional end)
12534 "Insert KDW, and the TAGS, the latter with face FACE. Also inser END."
12535 (insert (format "%-12s" (concat kwd ":"))
12536 (org-add-props (mapconcat 'identity tags " ") nil 'face face)
12537 (or end "")))
12539 (defun org-fast-tag-show-exit (flag)
12540 (save-excursion
12541 (goto-line 3)
12542 (if (re-search-forward "[ \t]+Next change exits" (point-at-eol) t)
12543 (replace-match ""))
12544 (when flag
12545 (end-of-line 1)
12546 (move-to-column (- (window-width) 19) t)
12547 (insert (org-add-props " Next change exits" nil 'face 'org-warning)))))
12549 (defun org-set-current-tags-overlay (current prefix)
12550 (let ((s (concat ":" (mapconcat 'identity current ":") ":")))
12551 (if (featurep 'xemacs)
12552 (org-overlay-display org-tags-overlay (concat prefix s)
12553 'secondary-selection)
12554 (put-text-property 0 (length s) 'face '(secondary-selection org-tag) s)
12555 (org-overlay-display org-tags-overlay (concat prefix s)))))
12557 (defun org-fast-tag-selection (current inherited table)
12558 "Fast tag selection with single keys.
12559 CURRENT is the current list of tags in the headline, INHERITED is the
12560 list of inherited tags, and TABLE is an alist of tags and corresponding keys,
12561 possibly with grouping information.
12562 If the keys are nil, a-z are automatically assigned.
12563 Returns the new tags string, or nil to not change the current settings."
12564 (let* ((maxlen (apply 'max (mapcar
12565 (lambda (x)
12566 (if (stringp (car x)) (string-width (car x)) 0))
12567 table)))
12568 (buf (current-buffer))
12569 (expert (eq org-fast-tag-selection-single-key 'expert))
12570 (buffer-tags nil)
12571 (fwidth (+ maxlen 3 1 3))
12572 (ncol (/ (- (window-width) 4) fwidth))
12573 (i-face 'org-done)
12574 (c-face 'org-todo)
12575 tg cnt e c char c1 c2 ntable tbl rtn
12576 ov-start ov-end ov-prefix
12577 (exit-after-next org-fast-tag-selection-single-key)
12578 groups ingroup)
12579 (save-excursion
12580 (beginning-of-line 1)
12581 (if (looking-at ".*[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \t]*\\(\r\\|$\\)")
12582 (setq ov-start (match-beginning 1)
12583 ov-end (match-end 1)
12584 ov-prefix "")
12585 (setq ov-start (1- (point-at-eol))
12586 ov-end (1+ ov-start))
12587 (skip-chars-forward "^\n\r")
12588 (setq ov-prefix
12589 (concat
12590 (buffer-substring (1- (point)) (point))
12591 (if (> (current-column) org-tags-column)
12593 (make-string (- org-tags-column (current-column)) ?\ ))))))
12594 (org-move-overlay org-tags-overlay ov-start ov-end)
12595 (save-window-excursion
12596 (if expert
12597 (set-buffer (get-buffer-create " *Org tags*"))
12598 (delete-other-windows)
12599 (split-window-vertically)
12600 (switch-to-buffer-other-window (get-buffer-create " *Org tags*")))
12601 (erase-buffer)
12602 (org-fast-tag-insert "Inherited" inherited i-face "\n")
12603 (org-fast-tag-insert "Current" current c-face "\n\n")
12604 (org-fast-tag-show-exit exit-after-next)
12605 (org-set-current-tags-overlay current ov-prefix)
12606 (setq tbl table char ?a cnt 0)
12607 (while (setq e (pop tbl))
12608 (cond
12609 ((equal e '(:startgroup))
12610 (push '() groups) (setq ingroup t)
12611 (when (not (= cnt 0))
12612 (setq cnt 0)
12613 (insert "\n"))
12614 (insert "{ "))
12615 ((equal e '(:endgroup))
12616 (setq ingroup nil cnt 0)
12617 (insert "}\n"))
12619 (setq tg (car e) c2 nil)
12620 (if (cdr e)
12621 (setq c (cdr e))
12622 ;; automatically assign a character.
12623 (setq c1 (string-to-char
12624 (downcase (substring
12625 tg (if (= (string-to-char tg) ?@) 1 0)))))
12626 (if (or (rassoc c1 ntable) (rassoc c1 table))
12627 (while (or (rassoc char ntable) (rassoc char table))
12628 (setq char (1+ char)))
12629 (setq c2 c1))
12630 (setq c (or c2 char)))
12631 (if ingroup (push tg (car groups)))
12632 (setq tg (org-add-props tg nil 'face
12633 (cond
12634 ((member tg current) c-face)
12635 ((member tg inherited) i-face)
12636 (t nil))))
12637 (if (and (= cnt 0) (not ingroup)) (insert " "))
12638 (insert "[" c "] " tg (make-string
12639 (- fwidth 4 (length tg)) ?\ ))
12640 (push (cons tg c) ntable)
12641 (when (= (setq cnt (1+ cnt)) ncol)
12642 (insert "\n")
12643 (if ingroup (insert " "))
12644 (setq cnt 0)))))
12645 (setq ntable (nreverse ntable))
12646 (insert "\n")
12647 (goto-char (point-min))
12648 (if (and (not expert) (fboundp 'fit-window-to-buffer))
12649 (fit-window-to-buffer))
12650 (setq rtn
12651 (catch 'exit
12652 (while t
12653 (message "[a-z..]:Toggle [SPC]:clear [RET]:accept [TAB]:free%s%s"
12654 (if groups " [!] no groups" " [!]groups")
12655 (if expert " [C-c]:window" (if exit-after-next " [C-c]:single" " [C-c]:multi")))
12656 (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
12657 (cond
12658 ((= c ?\r) (throw 'exit t))
12659 ((= c ?!)
12660 (setq groups (not groups))
12661 (goto-char (point-min))
12662 (while (re-search-forward "[{}]" nil t) (replace-match " ")))
12663 ((= c ?\C-c)
12664 (if (not expert)
12665 (org-fast-tag-show-exit
12666 (setq exit-after-next (not exit-after-next)))
12667 (setq expert nil)
12668 (delete-other-windows)
12669 (split-window-vertically)
12670 (switch-to-buffer-other-window " *Org tags*")
12671 (and (fboundp 'fit-window-to-buffer)
12672 (fit-window-to-buffer))))
12673 ((or (= c ?\C-g)
12674 (and (= c ?q) (not (rassoc c ntable))))
12675 (org-detach-overlay org-tags-overlay)
12676 (setq quit-flag t))
12677 ((= c ?\ )
12678 (setq current nil)
12679 (if exit-after-next (setq exit-after-next 'now)))
12680 ((= c ?\t)
12681 (condition-case nil
12682 (setq tg (completing-read
12683 "Tag: "
12684 (or buffer-tags
12685 (with-current-buffer buf
12686 (org-get-buffer-tags)))))
12687 (quit (setq tg "")))
12688 (when (string-match "\\S-" tg)
12689 (add-to-list 'buffer-tags (list tg))
12690 (if (member tg current)
12691 (setq current (delete tg current))
12692 (push tg current)))
12693 (if exit-after-next (setq exit-after-next 'now)))
12694 ((setq e (rassoc c ntable) tg (car e))
12695 (if (member tg current)
12696 (setq current (delete tg current))
12697 (loop for g in groups do
12698 (if (member tg g)
12699 (mapcar (lambda (x)
12700 (setq current (delete x current)))
12701 g)))
12702 (push tg current))
12703 (if exit-after-next (setq exit-after-next 'now))))
12705 ;; Create a sorted list
12706 (setq current
12707 (sort current
12708 (lambda (a b)
12709 (assoc b (cdr (memq (assoc a ntable) ntable))))))
12710 (if (eq exit-after-next 'now) (throw 'exit t))
12711 (goto-char (point-min))
12712 (beginning-of-line 2)
12713 (delete-region (point) (point-at-eol))
12714 (org-fast-tag-insert "Current" current c-face)
12715 (org-set-current-tags-overlay current ov-prefix)
12716 (while (re-search-forward "\\[.\\] \\([a-zA-Z0-9_@]+\\)" nil t)
12717 (setq tg (match-string 1))
12718 (add-text-properties (match-beginning 1) (match-end 1)
12719 (list 'face
12720 (cond
12721 ((member tg current) c-face)
12722 ((member tg inherited) i-face)
12723 (t nil)))))
12724 (goto-char (point-min)))))
12725 (org-detach-overlay org-tags-overlay)
12726 (if rtn
12727 (mapconcat 'identity current ":")
12728 nil))))
12730 (defun org-get-tags ()
12731 "Get the TAGS string in the current headline."
12732 (unless (org-on-heading-p t)
12733 (error "Not on a heading"))
12734 (save-excursion
12735 (beginning-of-line 1)
12736 (if (looking-at ".*[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \t]*\\(\r\\|$\\)")
12737 (org-match-string-no-properties 1)
12738 "")))
12740 (defun org-get-buffer-tags ()
12741 "Get a table of all tags used in the buffer, for completion."
12742 (let (tags)
12743 (save-excursion
12744 (goto-char (point-min))
12745 (while (re-search-forward "[ \t]:\\([A-Za-z_@0-9:]+\\):[ \t\r\n]" nil t)
12746 (mapc (lambda (x) (add-to-list 'tags x))
12747 (org-split-string (org-match-string-no-properties 1) ":"))))
12748 (mapcar 'list tags)))
12750 ;;;; Timestamps
12752 (defvar org-last-changed-timestamp nil)
12753 (defvar org-time-was-given) ; dynamically scoped parameter
12754 (defvar org-ts-what) ; dynamically scoped parameter
12756 (defun org-time-stamp (arg)
12757 "Prompt for a date/time and insert a time stamp.
12758 If the user specifies a time like HH:MM, or if this command is called
12759 with a prefix argument, the time stamp will contain date and time.
12760 Otherwise, only the date will be included. All parts of a date not
12761 specified by the user will be filled in from the current date/time.
12762 So if you press just return without typing anything, the time stamp
12763 will represent the current date/time. If there is already a timestamp
12764 at the cursor, it will be modified."
12765 (interactive "P")
12766 (let (org-time-was-given time)
12767 (cond
12768 ((and (org-at-timestamp-p)
12769 (eq last-command 'org-time-stamp)
12770 (eq this-command 'org-time-stamp))
12771 (insert "--")
12772 (setq time (let ((this-command this-command))
12773 (org-read-date arg 'totime)))
12774 (org-insert-time-stamp time (or org-time-was-given arg)))
12775 ((org-at-timestamp-p)
12776 (setq time (let ((this-command this-command))
12777 (org-read-date arg 'totime)))
12778 (when (org-at-timestamp-p) ; just to get the match data
12779 (replace-match "")
12780 (setq org-last-changed-timestamp
12781 (org-insert-time-stamp time (or org-time-was-given arg))))
12782 (message "Timestamp updated"))
12784 (setq time (let ((this-command this-command))
12785 (org-read-date arg 'totime)))
12786 (org-insert-time-stamp time (or org-time-was-given arg))))))
12788 (defun org-time-stamp-inactive (&optional arg)
12789 "Insert an inactive time stamp.
12790 An inactive time stamp is enclosed in square brackets instead of angle
12791 brackets. It is inactive in the sense that it does not trigger agenda entries,
12792 does not link to the calendar and cannot be changed with the S-cursor keys.
12793 So these are more for recording a certain time/date."
12794 (interactive "P")
12795 (let (org-time-was-given time)
12796 (setq time (org-read-date arg 'totime))
12797 (org-insert-time-stamp time (or org-time-was-given arg) 'inactive)))
12799 (defvar org-date-ovl (org-make-overlay 1 1))
12800 (org-overlay-put org-date-ovl 'face 'org-warning)
12801 (org-detach-overlay org-date-ovl)
12803 (defvar org-ans1) ; dynamically scoped parameter
12804 (defvar org-ans2) ; dynamically scoped parameter
12806 (defun org-read-date (&optional with-time to-time from-string prompt)
12807 "Read a date and make things smooth for the user.
12808 The prompt will suggest to enter an ISO date, but you can also enter anything
12809 which will at least partially be understood by `parse-time-string'.
12810 Unrecognized parts of the date will default to the current day, month, year,
12811 hour and minute. For example,
12812 3-2-5 --> 2003-02-05
12813 feb 15 --> currentyear-02-15
12814 sep 12 9 --> 2009-09-12
12815 12:45 --> today 12:45
12816 22 sept 0:34 --> currentyear-09-22 0:34
12817 12 --> currentyear-currentmonth-12
12818 Fri --> nearest Friday (today or later)
12819 +4 --> four days from today (only if +N is the only thing given)
12820 etc.
12821 The function understands only English month and weekday abbreviations,
12822 but this can be configured with the variables `parse-time-months' and
12823 `parse-time-weekdays'.
12825 While prompting, a calendar is popped up - you can also select the
12826 date with the mouse (button 1). The calendar shows a period of three
12827 months. To scroll it to other months, use the keys `>' and `<'.
12828 If you don't like the calendar, turn it off with
12829 \(setq org-popup-calendar-for-date-prompt nil)
12831 With optional argument TO-TIME, the date will immediately be converted
12832 to an internal time.
12833 With an optional argument WITH-TIME, the prompt will suggest to also
12834 insert a time. Note that when WITH-TIME is not set, you can still
12835 enter a time, and this function will inform the calling routine about
12836 this change. The calling routine may then choose to change the format
12837 used to insert the time stamp into the buffer to include the time."
12838 (require 'parse-time)
12839 (let* ((org-time-stamp-rounding-minutes
12840 (if (equal with-time '(16)) 0 org-time-stamp-rounding-minutes))
12841 (ct (org-current-time))
12842 (default-time
12843 ;; Default time is either today, or, when entering a range,
12844 ;; the range start.
12845 (if (save-excursion
12846 (re-search-backward
12847 (concat org-ts-regexp "--?-?\\=") ; 1-3 minuses
12848 (- (point) 20) t))
12849 (apply
12850 'encode-time
12851 (mapcar (lambda(x) (or x 0))
12852 (parse-time-string (match-string 1))))
12853 ct))
12854 (calendar-move-hook nil)
12855 (view-diary-entries-initially nil)
12856 (view-calendar-holidays-initially nil)
12857 (timestr (format-time-string
12858 (if with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") default-time))
12859 (prompt (concat (if prompt (concat prompt " ") "")
12860 (format "Date and/or time (default [%s]): " timestr)))
12861 ans (org-ans0 "") org-ans1 org-ans2 (deltadays 0)
12862 second minute hour day month year tl wday wday1 pm)
12864 (cond
12865 (from-string (setq ans from-string))
12866 (org-popup-calendar-for-date-prompt
12867 (save-excursion
12868 (save-window-excursion
12869 (calendar)
12870 (calendar-forward-day (- (time-to-days default-time)
12871 (calendar-absolute-from-gregorian
12872 (calendar-current-date))))
12873 (org-eval-in-calendar nil t)
12874 (let* ((old-map (current-local-map))
12875 (map (copy-keymap calendar-mode-map))
12876 (minibuffer-local-map (copy-keymap minibuffer-local-map)))
12877 (org-defkey map (kbd "RET") 'org-calendar-select)
12878 (org-defkey map (if (featurep 'xemacs) [button1] [mouse-1])
12879 'org-calendar-select-mouse)
12880 (org-defkey map (if (featurep 'xemacs) [button2] [mouse-2])
12881 'org-calendar-select-mouse)
12882 (org-defkey minibuffer-local-map [(meta shift left)]
12883 (lambda () (interactive)
12884 (org-eval-in-calendar '(calendar-backward-month 1))))
12885 (org-defkey minibuffer-local-map [(meta shift right)]
12886 (lambda () (interactive)
12887 (org-eval-in-calendar '(calendar-forward-month 1))))
12888 (org-defkey minibuffer-local-map [(shift up)]
12889 (lambda () (interactive)
12890 (org-eval-in-calendar '(calendar-backward-week 1))))
12891 (org-defkey minibuffer-local-map [(shift down)]
12892 (lambda () (interactive)
12893 (org-eval-in-calendar '(calendar-forward-week 1))))
12894 (org-defkey minibuffer-local-map [(shift left)]
12895 (lambda () (interactive)
12896 (org-eval-in-calendar '(calendar-backward-day 1))))
12897 (org-defkey minibuffer-local-map [(shift right)]
12898 (lambda () (interactive)
12899 (org-eval-in-calendar '(calendar-forward-day 1))))
12900 (org-defkey minibuffer-local-map ">"
12901 (lambda () (interactive)
12902 (org-eval-in-calendar '(scroll-calendar-left 1))))
12903 (org-defkey minibuffer-local-map "<"
12904 (lambda () (interactive)
12905 (org-eval-in-calendar '(scroll-calendar-right 1))))
12906 (unwind-protect
12907 (progn
12908 (use-local-map map)
12909 (setq org-ans0 (read-string prompt "" nil nil))
12910 ;; org-ans0: from prompt
12911 ;; org-ans1: from mouse click
12912 ;; org-ans2: from calendar motion
12913 (setq ans (concat org-ans0 " " (or org-ans1 org-ans2))))
12914 (use-local-map old-map))))))
12915 (t ; Naked prompt only
12916 (setq ans (read-string prompt "" nil timestr))))
12917 (org-detach-overlay org-date-ovl)
12919 (if (string-match "^[ \t]*[-+][0-9]+[ \t]*$" org-ans0)
12920 (setq deltadays (string-to-number ans) ans ""))
12922 ;; Help matching ISO dates with single digit month ot day, like 2006-8-11.
12923 (when (string-match
12924 "^ *\\(\\([0-9]+\\)-\\)?\\([0-1]?[0-9]\\)-\\([0-3]?[0-9]\\)\\([^-0-9]\\|$\\)" ans)
12925 (setq year (if (match-end 2)
12926 (string-to-number (match-string 2 ans))
12927 (string-to-number (format-time-string "%Y")))
12928 month (string-to-number (match-string 3 ans))
12929 day (string-to-number (match-string 4 ans)))
12930 (if (< year 100) (setq year (+ 2000 year)))
12931 (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
12932 t nil ans)))
12933 ;; Help matching am/pm times, because `parse-time-string' does not do that.
12934 ;; If there is a time with am/pm, and *no* time without it, we convert
12935 ;; convert so that matching will be successful.
12936 (when (and (not (string-match "[012]?[0-9]:[0-9][0-9]\\([ \t\n]\\|$\\)" ans))
12937 (string-match "\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\(am\\|AM\\|pm\\|PM\\)\\>" ans))
12938 (setq hour (string-to-number (match-string 1 ans))
12939 minute (if (match-end 3) (string-to-number (match-string 3 ans)) 0)
12940 pm (equal ?p (string-to-char (downcase (match-string 4 ans)))))
12941 (if (and (= hour 12) (not pm))
12942 (setq hour 0)
12943 (if (and pm (< hour 12)) (setq hour (+ 12 hour))))
12944 (setq ans (replace-match (format "%02d:%02d" hour minute) t t ans)))
12946 (setq tl (parse-time-string ans)
12947 year (or (nth 5 tl) (string-to-number (format-time-string "%Y" ct)))
12948 month (or (nth 4 tl) (string-to-number (format-time-string "%m" ct)))
12949 day (or (nth 3 tl) (string-to-number (format-time-string "%d" ct)))
12950 hour (or (nth 2 tl) (string-to-number (format-time-string "%H" ct)))
12951 minute (or (nth 1 tl) (string-to-number (format-time-string "%M" ct)))
12952 second (or (nth 0 tl) 0)
12953 wday (nth 6 tl))
12954 (setq day (+ day deltadays))
12955 (when (and wday (not (nth 3 tl)))
12956 ;; Weekday was given, but no day, so pick that day in the week
12957 ;; on or after the derived date.
12958 (setq wday1 (nth 6 (decode-time (encode-time 0 0 0 day month year))))
12959 (unless (equal wday wday1)
12960 (setq day (+ day (% (- wday wday1 -7) 7)))))
12961 (if (and (boundp 'org-time-was-given)
12962 (nth 2 tl))
12963 (setq org-time-was-given t))
12964 (if (< year 100) (setq year (+ 2000 year)))
12965 (if to-time
12966 (encode-time second minute hour day month year)
12967 (if (or (nth 1 tl) (nth 2 tl))
12968 (format "%04d-%02d-%02d %02d:%02d" year month day hour minute)
12969 (format "%04d-%02d-%02d" year month day)))))
12971 (defun org-eval-in-calendar (form &optional keepdate)
12972 "Eval FORM in the calendar window and return to current window.
12973 Also, store the cursor date in variable org-ans2."
12974 (let ((sw (selected-window)))
12975 (select-window (get-buffer-window "*Calendar*"))
12976 (eval form)
12977 (when (and (not keepdate) (calendar-cursor-to-date))
12978 (let* ((date (calendar-cursor-to-date))
12979 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
12980 (setq org-ans2 (format-time-string "%Y-%m-%d" time))))
12981 (org-move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer))
12982 (select-window sw)
12983 ;; Update the prompt to show new default date
12984 (save-excursion
12985 (goto-char (point-min))
12986 (when (and org-ans2
12987 (re-search-forward "\\[[-0-9]+\\]" nil t)
12988 (get-text-property (match-end 0) 'field))
12989 (let ((inhibit-read-only t))
12990 (replace-match (concat "[" org-ans2 "]") t t)
12991 (add-text-properties (point-min) (1+ (match-end 0))
12992 (text-properties-at (1+ (point-min)))))))))
12994 (defun org-calendar-select ()
12995 "Return to `org-read-date' with the date currently selected.
12996 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
12997 (interactive)
12998 (when (calendar-cursor-to-date)
12999 (let* ((date (calendar-cursor-to-date))
13000 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
13001 (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
13002 (if (active-minibuffer-window) (exit-minibuffer))))
13004 (defun org-insert-time-stamp (time &optional with-hm inactive pre post extra)
13005 "Insert a date stamp for the date given by the internal TIME.
13006 WITH-HM means, use the stamp format that includes the time of the day.
13007 INACTIVE means use square brackets instead of angular ones, so that the
13008 stamp will not contribute to the agenda.
13009 PRE and POST are optional strings to be inserted before and after the
13010 stamp.
13011 The command returns the inserted time stamp."
13012 (let ((fmt (funcall (if with-hm 'cdr 'car) org-time-stamp-formats))
13013 stamp)
13014 (if inactive (setq fmt (concat "[" (substring fmt 1 -1) "]")))
13015 (insert (or pre ""))
13016 (insert (setq stamp (format-time-string fmt time)))
13017 (when extra
13018 (backward-char 1)
13019 (insert extra)
13020 (forward-char 1))
13021 (insert (or post ""))
13022 stamp))
13024 (defun org-toggle-time-stamp-overlays ()
13025 "Toggle the use of custom time stamp formats."
13026 (interactive)
13027 (setq org-display-custom-times (not org-display-custom-times))
13028 (unless org-display-custom-times
13029 (let ((p (point-min)) (bmp (buffer-modified-p)))
13030 (while (setq p (next-single-property-change p 'display))
13031 (if (and (get-text-property p 'display)
13032 (eq (get-text-property p 'face) 'org-date))
13033 (remove-text-properties
13034 p (setq p (next-single-property-change p 'display))
13035 '(display t))))
13036 (set-buffer-modified-p bmp)))
13037 (if (featurep 'xemacs)
13038 (remove-text-properties (point-min) (point-max) '(end-glyph t)))
13039 (org-restart-font-lock)
13040 (setq org-table-may-need-update t)
13041 (if org-display-custom-times
13042 (message "Time stamps are overlayed with custom format")
13043 (message "Time stamp overlays removed")))
13045 ;; FIXME: do something about the repeaters
13046 (defun org-display-custom-time (beg end)
13047 "Overlay modified time stamp format over timestamp between BED and END."
13048 (let* ((t1 (save-match-data
13049 (org-parse-time-string (buffer-substring beg end) t)))
13050 (w1 (- end beg))
13051 (with-hm (and (nth 1 t1) (nth 2 t1)))
13052 (tf (funcall (if with-hm 'cdr 'car) org-time-stamp-custom-formats))
13053 (time (org-fix-decoded-time t1))
13054 (str (org-add-props
13055 (format-time-string
13056 (substring tf 1 -1) (apply 'encode-time time))
13057 nil 'mouse-face 'highlight))
13058 (w2 (length str)))
13059 (if (not (= w2 w1))
13060 (add-text-properties (1+ beg) (+ 2 beg)
13061 (list 'org-dwidth t 'org-dwidth-n (- w1 w2))))
13062 (if (featurep 'xemacs)
13063 (progn
13064 (put-text-property beg end 'invisible t)
13065 (put-text-property beg end 'end-glyph (make-glyph str)))
13066 (put-text-property beg end 'display str))))
13068 (defun org-translate-time (string)
13069 "Translate all timestamps in STRING to custom format.
13070 But do this only if the variable `org-display-custom-times' is set."
13071 (when org-display-custom-times
13072 (save-match-data
13073 (let* ((start 0)
13074 (re org-ts-regexp-both)
13075 t1 with-hm inactive tf time str beg end)
13076 (while (setq start (string-match re string start))
13077 (setq beg (match-beginning 0)
13078 end (match-end 0)
13079 t1 (save-match-data
13080 (org-parse-time-string (substring string beg end) t))
13081 with-hm (and (nth 1 t1) (nth 2 t1))
13082 inactive (equal (substring string beg (1+ beg)) "[")
13083 tf (funcall (if with-hm 'cdr 'car)
13084 org-time-stamp-custom-formats)
13085 time (org-fix-decoded-time t1)
13086 str (format-time-string
13087 (concat
13088 (if inactive "[" "<") (substring tf 1 -1)
13089 (if inactive "]" ">"))
13090 (apply 'encode-time time))
13091 string (replace-match str t t string)
13092 start (+ start (length str)))))))
13093 string)
13095 (defun org-fix-decoded-time (time)
13096 "Set 0 instead of nil for the first 6 elements of time.
13097 Don't touch the rest."
13098 (let ((n 0))
13099 (mapcar (lambda (x) (if (< (setq n (1+ n)) 7) (or x 0) x)) time)))
13101 (defun org-days-to-time (timestamp-string)
13102 "Difference between TIMESTAMP-STRING and now in days."
13103 (- (time-to-days (org-time-string-to-time timestamp-string))
13104 (time-to-days (current-time))))
13106 (defun org-deadline-close (timestamp-string &optional ndays)
13107 "Is the time in TIMESTAMP-STRING close to the current date?"
13108 (and (< (org-days-to-time timestamp-string)
13109 (or ndays org-deadline-warning-days))
13110 (not (org-entry-is-done-p))))
13112 (defun org-calendar-select-mouse (ev)
13113 "Return to `org-read-date' with the date currently selected.
13114 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
13115 (interactive "e")
13116 (mouse-set-point ev)
13117 (when (calendar-cursor-to-date)
13118 (let* ((date (calendar-cursor-to-date))
13119 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
13120 (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
13121 (if (active-minibuffer-window) (exit-minibuffer))))
13123 (defun org-check-deadlines (ndays)
13124 "Check if there are any deadlines due or past due.
13125 A deadline is considered due if it happens within `org-deadline-warning-days'
13126 days from today's date. If the deadline appears in an entry marked DONE,
13127 it is not shown. The prefix arg NDAYS can be used to test that many
13128 days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are shown."
13129 (interactive "P")
13130 (let* ((org-warn-days
13131 (cond
13132 ((equal ndays '(4)) 100000)
13133 (ndays (prefix-numeric-value ndays))
13134 (t org-deadline-warning-days)))
13135 (case-fold-search nil)
13136 (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>"))
13137 (callback
13138 (lambda () (org-deadline-close (match-string 1) org-warn-days))))
13140 (message "%d deadlines past-due or due within %d days"
13141 (org-occur regexp nil callback)
13142 org-warn-days)))
13144 (defun org-evaluate-time-range (&optional to-buffer)
13145 "Evaluate a time range by computing the difference between start and end.
13146 Normally the result is just printed in the echo area, but with prefix arg
13147 TO-BUFFER, the result is inserted just after the date stamp into the buffer.
13148 If the time range is actually in a table, the result is inserted into the
13149 next column.
13150 For time difference computation, a year is assumed to be exactly 365
13151 days in order to avoid rounding problems."
13152 (interactive "P")
13154 (org-clock-update-time-maybe)
13155 (save-excursion
13156 (unless (org-at-date-range-p)
13157 (goto-char (point-at-bol))
13158 (re-search-forward org-tr-regexp (point-at-eol) t))
13159 (if (not (org-at-date-range-p))
13160 (error "Not at a time-stamp range, and none found in current line")))
13161 (let* ((ts1 (match-string 1))
13162 (ts2 (match-string 2))
13163 (havetime (or (> (length ts1) 15) (> (length ts2) 15)))
13164 (match-end (match-end 0))
13165 (time1 (org-time-string-to-time ts1))
13166 (time2 (org-time-string-to-time ts2))
13167 (t1 (time-to-seconds time1))
13168 (t2 (time-to-seconds time2))
13169 (diff (abs (- t2 t1)))
13170 (negative (< (- t2 t1) 0))
13171 ;; (ys (floor (* 365 24 60 60)))
13172 (ds (* 24 60 60))
13173 (hs (* 60 60))
13174 (fy "%dy %dd %02d:%02d")
13175 (fy1 "%dy %dd")
13176 (fd "%dd %02d:%02d")
13177 (fd1 "%dd")
13178 (fh "%02d:%02d")
13179 y d h m align)
13180 (if havetime
13181 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
13183 d (floor (/ diff ds)) diff (mod diff ds)
13184 h (floor (/ diff hs)) diff (mod diff hs)
13185 m (floor (/ diff 60)))
13186 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
13188 d (floor (+ (/ diff ds) 0.5))
13189 h 0 m 0))
13190 (if (not to-buffer)
13191 (message (org-make-tdiff-string y d h m))
13192 (when (org-at-table-p)
13193 (goto-char match-end)
13194 (setq align t)
13195 (and (looking-at " *|") (goto-char (match-end 0))))
13196 (if (looking-at
13197 "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]")
13198 (replace-match ""))
13199 (if negative (insert " -"))
13200 (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m))
13201 (if (> d 0) (insert " " (format (if havetime fd fd1) d h m))
13202 (insert " " (format fh h m))))
13203 (if align (org-table-align))
13204 (message "Time difference inserted")))))
13206 (defun org-make-tdiff-string (y d h m)
13207 (let ((fmt "")
13208 (l nil))
13209 (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ")
13210 l (push y l)))
13211 (if (> d 0) (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ")
13212 l (push d l)))
13213 (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ")
13214 l (push h l)))
13215 (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ")
13216 l (push m l)))
13217 (apply 'format fmt (nreverse l))))
13219 (defun org-time-string-to-time (s)
13220 (apply 'encode-time (org-parse-time-string s)))
13222 (defun org-time-string-to-absolute (s &optional daynr)
13223 "Convert a time stamp to an absolute day number.
13224 If there is a specifyer for a cyclic time stamp, get the closest date to
13225 DATE."
13226 (cond
13227 ((and daynr (string-match "\\`%%\\((.*)\\)" s))
13228 (if (org-diary-sexp-entry (match-string 1 s) "" date)
13229 daynr
13230 (+ daynr 1000)))
13231 ((and daynr (string-match "\\+[0-9]+[dwmy]" s))
13232 (org-closest-date s (if (and (boundp 'daynr) (integerp daynr)) daynr
13233 (time-to-days (current-time))) (match-string 0 s)))
13234 (t (time-to-days (apply 'encode-time (org-parse-time-string s))))))
13236 (defun org-calendar-holiday ()
13237 "List of holidays, for Diary display in Org-mode."
13238 (let ((hl (check-calendar-holidays date)))
13239 (if hl (mapconcat 'identity hl "; "))))
13241 (defun org-diary-sexp-entry (sexp entry date)
13242 "Process a SEXP diary ENTRY for DATE."
13243 (let ((result (if calendar-debug-sexp
13244 (let ((stack-trace-on-error t))
13245 (eval (car (read-from-string sexp))))
13246 (condition-case nil
13247 (eval (car (read-from-string sexp)))
13248 (error
13249 (beep)
13250 (message "Bad sexp at line %d in %s: %s"
13251 (org-current-line)
13252 (buffer-file-name) sexp)
13253 (sleep-for 2))))))
13254 (cond ((stringp result) result)
13255 ((and (consp result)
13256 (stringp (cdr result))) (cdr result))
13257 (result entry)
13258 (t nil))))
13260 (defun org-diary-to-ical-string (frombuf)
13261 "FIXME"
13262 (let* ((tmpdir (if (featurep 'xemacs)
13263 (temp-directory)
13264 temporary-file-directory))
13265 (tmpfile (make-temp-name
13266 (expand-file-name "orgics" tmpdir)))
13267 buf rtn b e)
13268 (save-excursion
13269 (set-buffer frombuf)
13270 (icalendar-export-region (point-min) (point-max) tmpfile)
13271 (setq buf (find-buffer-visiting tmpfile))
13272 (set-buffer buf)
13273 (goto-char (point-min))
13274 (if (re-search-forward "^BEGIN:VEVENT" nil t)
13275 (setq b (match-beginning 0)))
13276 (goto-char (point-max))
13277 (if (re-search-backward "^END:VEVENT" nil t)
13278 (setq e (match-end 0)))
13279 (setq rtn (if (and b e) (concat (buffer-substring b e) "\n") "")))
13280 (kill-buffer buf)
13281 (kill-buffer frombuf)
13282 (delete-file tmpfile)
13283 rtn))
13285 (defun org-closest-date (start current change)
13286 "Find the date closest to CURRENT that is consistent with START and CHANGE."
13287 ;; Make the proper lists from the dates
13288 (catch 'exit
13289 (let ((a1 '(("d" . day) ("w" . week) ("m" . month) ("y" . year)))
13290 dn dw sday cday n1 n2
13291 d m y y1 y2 date1 date2 nmonths nm ny m2)
13293 (setq start (org-date-to-gregorian start)
13294 current (org-date-to-gregorian current)
13295 sday (calendar-absolute-from-gregorian start)
13296 cday (calendar-absolute-from-gregorian current))
13298 (if (<= cday sday) (throw 'exit sday))
13300 (if (string-match "\\(\\+[0-9]+\\)\\([dwmy]\\)" change)
13301 (setq dn (string-to-number (match-string 1 change))
13302 dw (cdr (assoc (match-string 2 change) a1)))
13303 (error "Invalid change specifyer: %s" change))
13304 (if (eq dw 'week) (setq dw 'day dn (* 7 dn)))
13305 (cond
13306 ((eq dw 'day)
13307 (setq n1 (+ sday (* dn (floor (/ (- cday sday) dn))))
13308 n2 (+ n1 dn)))
13309 ((eq dw 'year)
13310 (setq d (nth 1 start) m (car start) y1 (nth 2 start) y2 (nth 2 current))
13311 (setq y1 (+ (* (floor (/ (- y2 y1) dn)) dn) y1))
13312 (setq date1 (list m d y1)
13313 n1 (calendar-absolute-from-gregorian date1)
13314 date2 (list m d (+ y1 (* (if (< n1 cday) 1 -1) dn)))
13315 n2 (calendar-absolute-from-gregorian date2)))
13316 ((eq dw 'month)
13317 ;; approx number of month between the tow dates
13318 (setq nmonths (floor (/ (- cday sday) 30.436875)))
13319 ;; How often does dn fit in there?
13320 (setq d (nth 1 start) m (car start) y (nth 2 start)
13321 nm (* dn (max 0 (1- (floor (/ nmonths dn)))))
13322 m (+ m nm)
13323 ny (floor (/ m 12))
13324 y (+ y ny)
13325 m (- m (* ny 12)))
13326 (while (> m 12) (setq m (- m 12) y (1+ y)))
13327 (setq n1 (calendar-absolute-from-gregorian (list m d y)))
13328 (setq m2 (+ m dn) y2 y)
13329 (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
13330 (setq n2 (calendar-absolute-from-gregorian (list m2 d y2)))
13331 (while (< n2 cday)
13332 (setq n1 n2 m m2 y y2)
13333 (setq m2 (+ m dn) y2 y)
13334 (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
13335 (setq n2 (calendar-absolute-from-gregorian (list m2 d y2))))))
13337 (if (> (abs (- cday n1)) (abs (- cday n2))) n2 n1))))
13339 (defun org-date-to-gregorian (date)
13340 "Turn any specification of DATE into a gregorian date for the calendar."
13341 (cond ((integerp date) (calendar-gregorian-from-absolute date))
13342 ((and (listp date) (= (length date) 3)) date)
13343 ((stringp date)
13344 (setq date (org-parse-time-string date))
13345 (list (nth 4 date) (nth 3 date) (nth 5 date)))
13346 ((listp date)
13347 (list (nth 4 date) (nth 3 date) (nth 5 date)))))
13349 (defun org-parse-time-string (s &optional nodefault)
13350 "Parse the standard Org-mode time string.
13351 This should be a lot faster than the normal `parse-time-string'.
13352 If time is not given, defaults to 0:00. However, with optional NODEFAULT,
13353 hour and minute fields will be nil if not given."
13354 (if (string-match org-ts-regexp1 s)
13355 (list 0
13356 (if (or (match-beginning 8) (not nodefault))
13357 (string-to-number (or (match-string 8 s) "0")))
13358 (if (or (match-beginning 7) (not nodefault))
13359 (string-to-number (or (match-string 7 s) "0")))
13360 (string-to-number (match-string 4 s))
13361 (string-to-number (match-string 3 s))
13362 (string-to-number (match-string 2 s))
13363 nil nil nil)
13364 (make-list 9 0)))
13366 (defun org-timestamp-up (&optional arg)
13367 "Increase the date item at the cursor by one.
13368 If the cursor is on the year, change the year. If it is on the month or
13369 the day, change that.
13370 With prefix ARG, change by that many units."
13371 (interactive "p")
13372 (org-timestamp-change (prefix-numeric-value arg)))
13374 (defun org-timestamp-down (&optional arg)
13375 "Decrease the date item at the cursor by one.
13376 If the cursor is on the year, change the year. If it is on the month or
13377 the day, change that.
13378 With prefix ARG, change by that many units."
13379 (interactive "p")
13380 (org-timestamp-change (- (prefix-numeric-value arg))))
13382 (defun org-timestamp-up-day (&optional arg)
13383 "Increase the date in the time stamp by one day.
13384 With prefix ARG, change that many days."
13385 (interactive "p")
13386 (if (and (not (org-at-timestamp-p t))
13387 (org-on-heading-p))
13388 (org-todo 'up)
13389 (org-timestamp-change (prefix-numeric-value arg) 'day)))
13391 (defun org-timestamp-down-day (&optional arg)
13392 "Decrease the date in the time stamp by one day.
13393 With prefix ARG, change that many days."
13394 (interactive "p")
13395 (if (and (not (org-at-timestamp-p t))
13396 (org-on-heading-p))
13397 (org-todo 'down)
13398 (org-timestamp-change (- (prefix-numeric-value arg)) 'day)))
13400 (defsubst org-pos-in-match-range (pos n)
13401 (and (match-beginning n)
13402 (<= (match-beginning n) pos)
13403 (>= (match-end n) pos)))
13405 (defun org-at-timestamp-p (&optional inactive-ok)
13406 "Determine if the cursor is in or at a timestamp."
13407 (interactive)
13408 (let* ((tsr (if inactive-ok org-ts-regexp3 org-ts-regexp2))
13409 (pos (point))
13410 (ans (or (looking-at tsr)
13411 (save-excursion
13412 (skip-chars-backward "^[<\n\r\t")
13413 (if (> (point) 1) (backward-char 1))
13414 (and (looking-at tsr)
13415 (> (- (match-end 0) pos) -1))))))
13416 (and (boundp 'org-ts-what)
13417 (setq org-ts-what
13418 (cond
13419 ((org-pos-in-match-range pos 2) 'year)
13420 ((org-pos-in-match-range pos 3) 'month)
13421 ((org-pos-in-match-range pos 7) 'hour)
13422 ((org-pos-in-match-range pos 8) 'minute)
13423 ((or (org-pos-in-match-range pos 4)
13424 (org-pos-in-match-range pos 5)) 'day)
13425 (t 'day))))
13426 ans))
13428 (defun org-timestamp-change (n &optional what)
13429 "Change the date in the time stamp at point.
13430 The date will be changed by N times WHAT. WHAT can be `day', `month',
13431 `year', `minute', `second'. If WHAT is not given, the cursor position
13432 in the timestamp determines what will be changed."
13433 (let ((pos (point))
13434 with-hm inactive
13435 org-ts-what
13436 extra
13437 ts time time0)
13438 (if (not (org-at-timestamp-p t))
13439 (error "Not at a timestamp"))
13440 (if (and (not what) (not (eq org-ts-what 'day))
13441 org-display-custom-times
13442 (get-text-property (point) 'display)
13443 (not (get-text-property (1- (point)) 'display)))
13444 (setq org-ts-what 'day))
13445 (setq org-ts-what (or what org-ts-what)
13446 with-hm (<= (abs (- (cdr org-ts-lengths)
13447 (- (match-end 0) (match-beginning 0))))
13449 inactive (= (char-after (match-beginning 0)) ?\[)
13450 ts (match-string 0))
13451 (replace-match "")
13452 (if (string-match " \\+[0-9]+[dwmy]" ts)
13453 (setq extra (match-string 0 ts)))
13454 (setq time0 (org-parse-time-string ts))
13455 (setq time
13456 (apply 'encode-time
13457 (append
13458 (list (or (car time0) 0))
13459 (list (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0)))
13460 (list (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0)))
13461 (list (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0)))
13462 (list (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0)))
13463 (list (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0)))
13464 (nthcdr 6 time0))))
13465 (if (eq what 'calendar)
13466 (let ((cal-date
13467 (save-excursion
13468 (save-match-data
13469 (set-buffer "*Calendar*")
13470 (calendar-cursor-to-date)))))
13471 (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month
13472 (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day
13473 (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year
13474 (setcar time0 (or (car time0) 0))
13475 (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
13476 (setcar (nthcdr 2 time0) (or (nth 1 time0) 0))
13477 (setq time (apply 'encode-time time0))))
13478 (setq org-last-changed-timestamp
13479 (org-insert-time-stamp time with-hm inactive nil nil extra))
13480 (org-clock-update-time-maybe)
13481 (goto-char pos)
13482 ;; Try to recenter the calendar window, if any
13483 (if (and org-calendar-follow-timestamp-change
13484 (get-buffer-window "*Calendar*" t)
13485 (memq org-ts-what '(day month year)))
13486 (org-recenter-calendar (time-to-days time)))))
13488 (defun org-recenter-calendar (date)
13489 "If the calendar is visible, recenter it to DATE."
13490 (let* ((win (selected-window))
13491 (cwin (get-buffer-window "*Calendar*" t))
13492 (calendar-move-hook nil))
13493 (when cwin
13494 (select-window cwin)
13495 (calendar-goto-date (if (listp date) date
13496 (calendar-gregorian-from-absolute date)))
13497 (select-window win))))
13499 (defun org-goto-calendar (&optional arg)
13500 "Go to the Emacs calendar at the current date.
13501 If there is a time stamp in the current line, go to that date.
13502 A prefix ARG can be used to force the current date."
13503 (interactive "P")
13504 (let ((tsr org-ts-regexp) diff
13505 (calendar-move-hook nil)
13506 (view-calendar-holidays-initially nil)
13507 (view-diary-entries-initially nil))
13508 (if (or (org-at-timestamp-p)
13509 (save-excursion
13510 (beginning-of-line 1)
13511 (looking-at (concat ".*" tsr))))
13512 (let ((d1 (time-to-days (current-time)))
13513 (d2 (time-to-days
13514 (org-time-string-to-time (match-string 1)))))
13515 (setq diff (- d2 d1))))
13516 (calendar)
13517 (calendar-goto-today)
13518 (if (and diff (not arg)) (calendar-forward-day diff))))
13520 (defun org-date-from-calendar ()
13521 "Insert time stamp corresponding to cursor date in *Calendar* buffer.
13522 If there is already a time stamp at the cursor position, update it."
13523 (interactive)
13524 (org-timestamp-change 0 'calendar))
13526 ;;; The clock for measuring work time.
13528 (defvar org-mode-line-string "")
13529 (put 'org-mode-line-string 'risky-local-variable t)
13531 (defvar org-mode-line-timer nil)
13532 (defvar org-clock-heading "")
13533 (defvar org-clock-start-time "")
13535 (defun org-update-mode-line ()
13536 (let* ((delta (- (time-to-seconds (current-time))
13537 (time-to-seconds org-clock-start-time)))
13538 (h (floor delta 3600))
13539 (m (floor (- delta (* 3600 h)) 60)))
13540 (setq org-mode-line-string
13541 (propertize (format "-[%d:%02d (%s)]" h m org-clock-heading)
13542 'help-echo "Org-mode clock is running"))
13543 (force-mode-line-update)))
13545 (defvar org-clock-marker (make-marker)
13546 "Marker recording the last clock-in.")
13547 (defvar org-clock-mode-line-entry nil
13548 "Information for the modeline about the running clock.")
13550 (defun org-clock-in ()
13551 "Start the clock on the current item.
13552 If necessary, clock-out of the currently active clock."
13553 (interactive)
13554 (org-clock-out t)
13555 (let (ts)
13556 (save-excursion
13557 (org-back-to-heading t)
13558 (if (looking-at org-todo-line-regexp)
13559 (setq org-clock-heading (match-string 3))
13560 (setq org-clock-heading "???"))
13561 (setq org-clock-heading (propertize org-clock-heading 'face nil))
13562 (beginning-of-line 2)
13563 (when (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
13564 (not (equal (match-string 1) org-clock-string)))
13565 ;; First line hast scheduling info, move one further
13566 (beginning-of-line 2)
13567 (or (bolp) (newline)))
13568 (insert "\n") (backward-char 1)
13569 (indent-relative)
13570 (insert org-clock-string " ")
13571 (setq org-clock-start-time (current-time))
13572 (setq ts (org-insert-time-stamp (current-time) 'with-hm 'inactive))
13573 (move-marker org-clock-marker (point) (buffer-base-buffer))
13574 (or global-mode-string (setq global-mode-string '("")))
13575 (or (memq 'org-mode-line-string global-mode-string)
13576 (setq global-mode-string
13577 (append global-mode-string '(org-mode-line-string))))
13578 (org-update-mode-line)
13579 (setq org-mode-line-timer (run-with-timer 60 60 'org-update-mode-line))
13580 (message "Clock started at %s" ts))))
13582 (defun org-clock-out (&optional fail-quietly)
13583 "Stop the currently running clock.
13584 If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
13585 (interactive)
13586 (catch 'exit
13587 (if (not (marker-buffer org-clock-marker))
13588 (if fail-quietly (throw 'exit t) (error "No active clock")))
13589 (let (ts te s h m)
13590 (save-excursion
13591 (set-buffer (marker-buffer org-clock-marker))
13592 (goto-char org-clock-marker)
13593 (beginning-of-line 1)
13594 (if (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
13595 (equal (match-string 1) org-clock-string))
13596 (setq ts (match-string 2))
13597 (if fail-quietly (throw 'exit nil) (error "Clock start time is gone")))
13598 (goto-char org-clock-marker)
13599 (insert "--")
13600 (setq te (org-insert-time-stamp (current-time) 'with-hm 'inactive))
13601 (setq s (- (time-to-seconds (apply 'encode-time (org-parse-time-string te)))
13602 (time-to-seconds (apply 'encode-time (org-parse-time-string ts))))
13603 h (floor (/ s 3600))
13604 s (- s (* 3600 h))
13605 m (floor (/ s 60))
13606 s (- s (* 60 s)))
13607 (insert " => " (format "%2d:%02d" h m))
13608 (move-marker org-clock-marker nil)
13609 (org-add-log-maybe 'clock-out)
13610 (when org-mode-line-timer
13611 (cancel-timer org-mode-line-timer)
13612 (setq org-mode-line-timer nil))
13613 (setq global-mode-string
13614 (delq 'org-mode-line-string global-mode-string))
13615 (force-mode-line-update)
13616 (message "Clock stopped at %s after HH:MM = %d:%02d" te h m)))))
13618 (defun org-clock-cancel ()
13619 "Cancel the running clock be removing the start timestamp."
13620 (interactive)
13621 (if (not (marker-buffer org-clock-marker))
13622 (error "No active clock"))
13623 (save-excursion
13624 (set-buffer (marker-buffer org-clock-marker))
13625 (goto-char org-clock-marker)
13626 (delete-region (1- (point-at-bol)) (point-at-eol)))
13627 (message "Clock canceled"))
13629 (defvar org-clock-file-total-minutes nil
13630 "Holds the file total time in minutes, after a call to `org-clock-sum'.")
13631 (make-variable-buffer-local 'org-clock-file-total-minutes)
13633 (defun org-clock-sum (&optional tstart tend)
13634 "Sum the times for each subtree.
13635 Puts the resulting times in minutes as a text property on each headline."
13636 (interactive)
13637 (let* ((bmp (buffer-modified-p))
13638 (re (concat "^\\(\\*+\\)[ \t]\\|^[ \t]*"
13639 org-clock-string
13640 "[ \t]*\\(\\[.*?\\]\\)-+\\(\\[.*?\\]\\)"))
13641 (lmax 30)
13642 (ltimes (make-vector lmax 0))
13643 (t1 0)
13644 (level 0)
13645 ts te dt
13646 time)
13647 (remove-text-properties (point-min) (point-max) '(:org-clock-minutes t))
13648 (save-excursion
13649 (goto-char (point-max))
13650 (while (re-search-backward re nil t)
13651 (if (match-end 2)
13652 ;; A time
13653 (setq ts (match-string 2)
13654 te (match-string 3)
13655 ts (time-to-seconds
13656 (apply 'encode-time (org-parse-time-string ts)))
13657 te (time-to-seconds
13658 (apply 'encode-time (org-parse-time-string te)))
13659 ts (if tstart (max ts tstart) ts)
13660 te (if tend (min te tend) te)
13661 dt (- te ts)
13662 t1 (if (> dt 0) (+ t1 (floor (/ dt 60))) t1))
13663 ;; A headline
13664 (setq level (- (match-end 1) (match-beginning 1)))
13665 (when (or (> t1 0) (> (aref ltimes level) 0))
13666 (loop for l from 0 to level do
13667 (aset ltimes l (+ (aref ltimes l) t1)))
13668 (setq t1 0 time (aref ltimes level))
13669 (loop for l from level to (1- lmax) do
13670 (aset ltimes l 0))
13671 (goto-char (match-beginning 0))
13672 (put-text-property (point) (point-at-eol) :org-clock-minutes time))))
13673 (setq org-clock-file-total-minutes (aref ltimes 0)))
13674 (set-buffer-modified-p bmp)))
13676 (defun org-clock-display (&optional total-only)
13677 "Show subtree times in the entire buffer.
13678 If TOTAL-ONLY is non-nil, only show the total time for the entire file
13679 in the echo area."
13680 (interactive)
13681 (org-remove-clock-overlays)
13682 (let (time h m p)
13683 (org-clock-sum)
13684 (unless total-only
13685 (save-excursion
13686 (goto-char (point-min))
13687 (while (setq p (next-single-property-change (point) :org-clock-minutes))
13688 (goto-char p)
13689 (when (setq time (get-text-property p :org-clock-minutes))
13690 (org-put-clock-overlay time (funcall outline-level))))
13691 (setq h (/ org-clock-file-total-minutes 60)
13692 m (- org-clock-file-total-minutes (* 60 h)))
13693 ;; Arrange to remove the overlays upon next change.
13694 (when org-remove-highlights-with-change
13695 (org-add-hook 'before-change-functions 'org-remove-clock-overlays
13696 nil 'local))))
13697 (message "Total file time: %d:%02d (%d hours and %d minutes)" h m h m)))
13699 (defvar org-clock-overlays nil)
13700 (make-variable-buffer-local 'org-clock-overlays)
13702 (defun org-put-clock-overlay (time &optional level)
13703 "Put an overlays on the current line, displaying TIME.
13704 If LEVEL is given, prefix time with a corresponding number of stars.
13705 This creates a new overlay and stores it in `org-clock-overlays', so that it
13706 will be easy to remove."
13707 (let* ((c 60) (h (floor (/ time 60))) (m (- time (* 60 h)))
13708 (l (if level (org-get-legal-level level 0) 0))
13709 (off 0)
13710 ov tx)
13711 (move-to-column c)
13712 (unless (eolp) (skip-chars-backward "^ \t"))
13713 (skip-chars-backward " \t")
13714 (setq ov (org-make-overlay (1- (point)) (point-at-eol))
13715 tx (concat (buffer-substring (1- (point)) (point))
13716 (make-string (+ off (max 0 (- c (current-column)))) ?.)
13717 (org-add-props (format "%s %2d:%02d%s"
13718 (make-string l ?*) h m
13719 (make-string (- 10 l) ?\ ))
13720 '(face secondary-selection))
13721 ""))
13722 (if (not (featurep 'xemacs))
13723 (org-overlay-put ov 'display tx)
13724 (org-overlay-put ov 'invisible t)
13725 (org-overlay-put ov 'end-glyph (make-glyph tx)))
13726 (push ov org-clock-overlays)))
13728 (defun org-remove-clock-overlays (&optional beg end noremove)
13729 "Remove the occur highlights from the buffer.
13730 BEG and END are ignored. If NOREMOVE is nil, remove this function
13731 from the `before-change-functions' in the current buffer."
13732 (interactive)
13733 (unless org-inhibit-highlight-removal
13734 (mapc 'org-delete-overlay org-clock-overlays)
13735 (setq org-clock-overlays nil)
13736 (unless noremove
13737 (remove-hook 'before-change-functions
13738 'org-remove-clock-overlays 'local))))
13740 (defun org-clock-out-if-current ()
13741 "Clock out if the current entry contains the running clock.
13742 This is used to stop the clock after a TODO entry is marked DONE."
13743 (when (and (member state org-done-keywords)
13744 (equal (marker-buffer org-clock-marker) (current-buffer))
13745 (< (point) org-clock-marker)
13746 (> (save-excursion (outline-next-heading) (point))
13747 org-clock-marker))
13748 ;; Clock out, but don't accept a logging message for this.
13749 (let ((org-log-done (if (and (listp org-log-done)
13750 (member 'clock-out org-log-done))
13751 '(done)
13752 org-log-done)))
13753 (org-clock-out))))
13755 (add-hook 'org-after-todo-state-change-hook
13756 'org-clock-out-if-current)
13758 (defun org-check-running-clock ()
13759 "Check if the current buffer contains the running clock.
13760 If yes, offer to stop it and to save the buffer with the changes."
13761 (when (and (equal (marker-buffer org-clock-marker) (current-buffer))
13762 (y-or-n-p (format "Clock-out in buffer %s before killing it? "
13763 (buffer-name))))
13764 (org-clock-out)
13765 (when (y-or-n-p "Save changed buffer?")
13766 (save-buffer))))
13768 (defun org-clock-report ()
13769 "Create a table containing a report about clocked time.
13770 If the buffer contains lines
13771 #+BEGIN: clocktable :maxlevel 3 :emphasize nil
13773 #+END: clocktable
13774 then the table will be inserted between these lines, replacing whatever
13775 is was there before. If these lines are not in the buffer, the table
13776 is inserted at point, surrounded by the special lines.
13777 The BEGIN line can contain parameters. Allowed are:
13778 :maxlevel The maximum level to be included in the table. Default is 3.
13779 :emphasize t/nil, if levell 1 and level 2 should be bold/italic in the table."
13780 (interactive)
13781 (org-remove-clock-overlays)
13782 (unless (org-find-dblock "clocktable")
13783 (org-create-dblock (list :name "clocktable"
13784 :maxlevel 2 :emphasize nil)))
13785 (org-update-dblock))
13787 (defun org-clock-update-time-maybe ()
13788 "If this is a CLOCK line, update it and return t.
13789 Otherwise, return nil."
13790 (interactive)
13791 (save-excursion
13792 (beginning-of-line 1)
13793 (skip-chars-forward " \t")
13794 (when (looking-at org-clock-string)
13795 (let ((re (concat "[ \t]*" org-clock-string
13796 " *[[<]\\([^]>]+\\)[]>]-+[[<]\\([^]>]+\\)[]>]"
13797 "\\([ \t]*=>.*\\)?"))
13798 ts te h m s)
13799 (if (not (looking-at re))
13801 (and (match-end 3) (delete-region (match-beginning 3) (match-end 3)))
13802 (end-of-line 1)
13803 (setq ts (match-string 1)
13804 te (match-string 2))
13805 (setq s (- (time-to-seconds
13806 (apply 'encode-time (org-parse-time-string te)))
13807 (time-to-seconds
13808 (apply 'encode-time (org-parse-time-string ts))))
13809 h (floor (/ s 3600))
13810 s (- s (* 3600 h))
13811 m (floor (/ s 60))
13812 s (- s (* 60 s)))
13813 (insert " => " (format "%2d:%02d" h m))
13814 t)))))
13816 (defun org-clock-special-range (key &optional time as-strings)
13817 "Return two times bordering a special time range.
13818 Key is a symbol specifying the range and can be one of `today', `yesterday',
13819 `thisweek', `lastweek', `thismonth', `lastmonth', `thisyear', `lastyear'.
13820 A week starts Monday 0:00 and ends Sunday 24:00.
13821 The range is determined relative to TIME. TIME defaults to the current time.
13822 The return value is a cons cell with two internal times like the ones
13823 returned by `current time' or `encode-time'. if AS-STRINGS is non-nil,
13824 the returned times will be formatted strings."
13825 (let* ((tm (decode-time (or time (current-time))))
13826 (s 0) (m (nth 1 tm)) (h (nth 2 tm))
13827 (d (nth 3 tm)) (month (nth 4 tm)) (y (nth 5 tm))
13828 (dow (nth 6 tm))
13829 s1 m1 h1 d1 month1 y1 diff ts te fm)
13830 (cond
13831 ((eq key 'today)
13832 (setq h 0 m 0 h1 24 m1 0))
13833 ((eq key 'yesterday)
13834 (setq d (1- d) h 0 m 0 h1 24 m1 0))
13835 ((eq key 'thisweek)
13836 (setq diff (if (= dow 0) 6 (1- dow))
13837 m 0 h 0 d (- d diff) d1 (+ 7 d)))
13838 ((eq key 'lastweek)
13839 (setq diff (+ 7 (if (= dow 0) 6 (1- dow)))
13840 m 0 h 0 d (- d diff) d1 (+ 7 d)))
13841 ((eq key 'thismonth)
13842 (setq d 1 h 0 m 0 d1 1 month1 (1+ month) h1 0 m1 0))
13843 ((eq key 'lastmonth)
13844 (setq d 1 h 0 m 0 d1 1 month (1- month) month1 (1+ month) h1 0 m1 0))
13845 ((eq key 'thisyear)
13846 (setq m 0 h 0 d 1 month 1 y1 (1+ y)))
13847 ((eq key 'lastyear)
13848 (setq m 0 h 0 d 1 month 1 y (1- y) y1 (1+ y)))
13849 (t (error "No such time block %s" key)))
13850 (setq ts (encode-time s m h d month y)
13851 te (encode-time (or s1 s) (or m1 m) (or h1 h)
13852 (or d1 d) (or month1 month) (or y1 y)))
13853 (setq fm (cdr org-time-stamp-formats))
13854 (if as-strings
13855 (cons (format-time-string fm ts) (format-time-string fm te))
13856 (cons ts te))))
13858 (defun org-dblock-write:clocktable (params)
13859 "Write the standard clocktable."
13860 (let ((hlchars '((1 . "*") (2 . ?/)))
13861 (emph nil)
13862 (ins (make-marker))
13863 ipos time h m p level hlc hdl maxlevel
13864 ts te cc block)
13865 (setq maxlevel (or (plist-get params :maxlevel) 3)
13866 emph (plist-get params :emphasize)
13867 ts (plist-get params :tstart)
13868 te (plist-get params :tend)
13869 block (plist-get params :block))
13870 (when block
13871 (setq cc (org-clock-special-range block nil t)
13872 ts (car cc) te (cdr cc)))
13873 (if ts (setq ts (time-to-seconds
13874 (apply 'encode-time (org-parse-time-string ts)))))
13875 (if te (setq te (time-to-seconds
13876 (apply 'encode-time (org-parse-time-string te)))))
13877 (move-marker ins (point))
13878 (setq ipos (point))
13879 (insert-before-markers "Clock summary at ["
13880 (substring
13881 (format-time-string (cdr org-time-stamp-formats))
13882 1 -1)
13883 "]."
13884 (if block
13885 (format " Considered range is /%s/." block)
13887 "\n\n|L|Headline|Time|\n")
13888 (org-clock-sum ts te)
13889 (setq h (/ org-clock-file-total-minutes 60)
13890 m (- org-clock-file-total-minutes (* 60 h)))
13891 (insert-before-markers "|-\n|0|" "*Total file time*| "
13892 (format "*%d:%02d*" h m)
13893 "|\n")
13894 (goto-char (point-min))
13895 (while (setq p (next-single-property-change (point) :org-clock-minutes))
13896 (goto-char p)
13897 (when (setq time (get-text-property p :org-clock-minutes))
13898 (save-excursion
13899 (beginning-of-line 1)
13900 (when (and (looking-at "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ \t]+:[0-9a-zA-Z_@:]+:\\)?[ \t]*$")
13901 (setq level (- (match-end 1) (match-beginning 1)))
13902 (<= level maxlevel))
13903 (setq hlc (if emph (or (cdr (assoc level hlchars)) "") "")
13904 hdl (match-string 2)
13905 h (/ time 60)
13906 m (- time (* 60 h)))
13907 (goto-char ins)
13908 (if (= level 1) (insert-before-markers "|-\n"))
13909 (insert-before-markers
13910 "| " (int-to-string level) "|" hlc hdl hlc " |"
13911 (make-string (1- level) ?|)
13913 (format "%d:%02d" h m)
13915 " |\n")))))
13916 (goto-char ins)
13917 (backward-delete-char 1)
13918 (goto-char ipos)
13919 (skip-chars-forward "^|")
13920 (org-table-align)))
13922 ;; FIXME: I don't think anybody uses this, ask David
13923 (defun org-collect-clock-time-entries ()
13924 "Return an internal list with clocking information.
13925 This list has one entry for each CLOCK interval.
13926 FIXME: describe the elements."
13927 (interactive)
13928 (let ((re (concat "^[ \t]*" org-clock-string
13929 " *\\[\\(.*?\\)\\]--\\[\\(.*?\\)\\]"))
13930 rtn beg end next cont level title total closedp leafp
13931 clockpos titlepos h m donep)
13932 (save-excursion
13933 (org-clock-sum)
13934 (goto-char (point-min))
13935 (while (re-search-forward re nil t)
13936 (setq clockpos (match-beginning 0)
13937 beg (match-string 1) end (match-string 2)
13938 cont (match-end 0))
13939 (setq beg (apply 'encode-time (org-parse-time-string beg))
13940 end (apply 'encode-time (org-parse-time-string end)))
13941 (org-back-to-heading t)
13942 (setq donep (org-entry-is-done-p))
13943 (setq titlepos (point)
13944 total (or (get-text-property (1+ (point)) :org-clock-minutes) 0)
13945 h (/ total 60) m (- total (* 60 h))
13946 total (cons h m))
13947 (looking-at "\\(\\*+\\) +\\(.*\\)")
13948 (setq level (- (match-end 1) (match-beginning 1))
13949 title (org-match-string-no-properties 2))
13950 (save-excursion (outline-next-heading) (setq next (point)))
13951 (setq closedp (re-search-forward org-closed-time-regexp next t))
13952 (goto-char next)
13953 (setq leafp (and (looking-at "^\\*+ ")
13954 (<= (- (match-end 0) (point)) level)))
13955 (push (list beg end clockpos closedp donep
13956 total title titlepos level leafp)
13957 rtn)
13958 (goto-char cont)))
13959 (nreverse rtn)))
13961 ;;;; Agenda, and Diary Integration
13963 ;;; Define the Org-agenda-mode
13965 (defvar org-agenda-mode-map (make-sparse-keymap)
13966 "Keymap for `org-agenda-mode'.")
13968 (defvar org-agenda-menu) ; defined later in this file.
13969 (defvar org-agenda-follow-mode nil)
13970 (defvar org-agenda-show-log nil)
13971 (defvar org-agenda-redo-command nil)
13972 (defvar org-agenda-mode-hook nil)
13973 (defvar org-agenda-type nil)
13974 (defvar org-agenda-force-single-file nil)
13976 (defun org-agenda-mode ()
13977 "Mode for time-sorted view on action items in Org-mode files.
13979 The following commands are available:
13981 \\{org-agenda-mode-map}"
13982 (interactive)
13983 (kill-all-local-variables)
13984 (setq org-agenda-undo-list nil
13985 org-agenda-pending-undo-list nil)
13986 (setq major-mode 'org-agenda-mode)
13987 ;; Keep global-font-lock-mode from turning on font-lock-mode
13988 (org-set-local 'font-lock-global-modes (list 'not major-mode))
13989 (setq mode-name "Org-Agenda")
13990 (use-local-map org-agenda-mode-map)
13991 (easy-menu-add org-agenda-menu)
13992 (if org-startup-truncated (setq truncate-lines t))
13993 (org-add-hook 'post-command-hook 'org-agenda-post-command-hook nil 'local)
13994 (org-add-hook 'pre-command-hook 'org-unhighlight nil 'local)
13995 ;; Make sure properties are removed when copying text
13996 (when (boundp 'buffer-substring-filters)
13997 (org-set-local 'buffer-substring-filters
13998 (cons (lambda (x)
13999 (set-text-properties 0 (length x) nil x) x)
14000 buffer-substring-filters)))
14001 (unless org-agenda-keep-modes
14002 (setq org-agenda-follow-mode org-agenda-start-with-follow-mode
14003 org-agenda-show-log nil))
14004 (easy-menu-change
14005 '("Agenda") "Agenda Files"
14006 (append
14007 (list
14008 (vector
14009 (if (get 'org-agenda-files 'org-restrict)
14010 "Restricted to single file"
14011 "Edit File List")
14012 '(org-edit-agenda-file-list)
14013 (not (get 'org-agenda-files 'org-restrict)))
14014 "--")
14015 (mapcar 'org-file-menu-entry (org-agenda-files))))
14016 (org-agenda-set-mode-name)
14017 (apply
14018 (if (fboundp 'run-mode-hooks) 'run-mode-hooks 'run-hooks)
14019 (list 'org-agenda-mode-hook)))
14021 (substitute-key-definition 'undo 'org-agenda-undo
14022 org-agenda-mode-map global-map)
14023 (org-defkey org-agenda-mode-map "\C-i" 'org-agenda-goto)
14024 (org-defkey org-agenda-mode-map [(tab)] 'org-agenda-goto)
14025 (org-defkey org-agenda-mode-map "\C-m" 'org-agenda-switch-to)
14026 (org-defkey org-agenda-mode-map "\C-k" 'org-agenda-kill)
14027 (org-defkey org-agenda-mode-map "\C-c$" 'org-agenda-archive)
14028 (org-defkey org-agenda-mode-map "\C-c\C-x\C-s" 'org-agenda-archive)
14029 (org-defkey org-agenda-mode-map "$" 'org-agenda-archive)
14030 (org-defkey org-agenda-mode-map "\C-c\C-o" 'org-agenda-open-link)
14031 (org-defkey org-agenda-mode-map " " 'org-agenda-show)
14032 (org-defkey org-agenda-mode-map "\C-c\C-t" 'org-agenda-todo)
14033 (org-defkey org-agenda-mode-map [(control shift right)] 'org-agenda-todo-nextset)
14034 (org-defkey org-agenda-mode-map [(control shift left)] 'org-agenda-todo-previousset)
14035 (org-defkey org-agenda-mode-map "\C-c\C-xb" 'org-agenda-tree-to-indirect-buffer)
14036 (org-defkey org-agenda-mode-map "b" 'org-agenda-tree-to-indirect-buffer)
14037 (org-defkey org-agenda-mode-map "o" 'delete-other-windows)
14038 (org-defkey org-agenda-mode-map "L" 'org-agenda-recenter)
14039 (org-defkey org-agenda-mode-map "t" 'org-agenda-todo)
14040 (org-defkey org-agenda-mode-map "a" 'org-agenda-toggle-archive-tag)
14041 (org-defkey org-agenda-mode-map ":" 'org-agenda-set-tags)
14042 (org-defkey org-agenda-mode-map "." 'org-agenda-goto-today)
14043 (org-defkey org-agenda-mode-map "d" 'org-agenda-day-view)
14044 (org-defkey org-agenda-mode-map "w" 'org-agenda-week-view)
14045 (org-defkey org-agenda-mode-map [(shift right)] 'org-agenda-date-later)
14046 (org-defkey org-agenda-mode-map [(shift left)] 'org-agenda-date-earlier)
14047 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (right)] 'org-agenda-date-later)
14048 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (left)] 'org-agenda-date-earlier)
14050 (org-defkey org-agenda-mode-map ">" 'org-agenda-date-prompt)
14051 (org-defkey org-agenda-mode-map "\C-c\C-s" 'org-agenda-schedule)
14052 (org-defkey org-agenda-mode-map "\C-c\C-d" 'org-agenda-deadline)
14053 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
14054 (while l (org-defkey org-agenda-mode-map
14055 (int-to-string (pop l)) 'digit-argument)))
14057 (org-defkey org-agenda-mode-map "f" 'org-agenda-follow-mode)
14058 (org-defkey org-agenda-mode-map "l" 'org-agenda-log-mode)
14059 (org-defkey org-agenda-mode-map "D" 'org-agenda-toggle-diary)
14060 (org-defkey org-agenda-mode-map "g" 'org-agenda-toggle-time-grid)
14061 (org-defkey org-agenda-mode-map "r" 'org-agenda-redo)
14062 (org-defkey org-agenda-mode-map "q" 'org-agenda-quit)
14063 (org-defkey org-agenda-mode-map "x" 'org-agenda-exit)
14064 (org-defkey org-agenda-mode-map "\C-x\C-w" 'org-write-agenda)
14065 (org-defkey org-agenda-mode-map "s" 'org-save-all-org-buffers)
14066 (org-defkey org-agenda-mode-map "P" 'org-agenda-show-priority)
14067 (org-defkey org-agenda-mode-map "T" 'org-agenda-show-tags)
14068 (org-defkey org-agenda-mode-map "n" 'next-line)
14069 (org-defkey org-agenda-mode-map "p" 'previous-line)
14070 (org-defkey org-agenda-mode-map "\C-n" 'org-agenda-next-date-line)
14071 (org-defkey org-agenda-mode-map "\C-p" 'org-agenda-previous-date-line)
14072 (org-defkey org-agenda-mode-map "," 'org-agenda-priority)
14073 (org-defkey org-agenda-mode-map "\C-c," 'org-agenda-priority)
14074 (org-defkey org-agenda-mode-map "i" 'org-agenda-diary-entry)
14075 (org-defkey org-agenda-mode-map "c" 'org-agenda-goto-calendar)
14076 (eval-after-load "calendar"
14077 '(org-defkey calendar-mode-map org-calendar-to-agenda-key
14078 'org-calendar-goto-agenda))
14079 (org-defkey org-agenda-mode-map "C" 'org-agenda-convert-date)
14080 (org-defkey org-agenda-mode-map "m" 'org-agenda-phases-of-moon)
14081 (org-defkey org-agenda-mode-map "M" 'org-agenda-phases-of-moon)
14082 (org-defkey org-agenda-mode-map "S" 'org-agenda-sunrise-sunset)
14083 (org-defkey org-agenda-mode-map "h" 'org-agenda-holidays)
14084 (org-defkey org-agenda-mode-map "H" 'org-agenda-holidays)
14085 (org-defkey org-agenda-mode-map "I" 'org-agenda-clock-in)
14086 (org-defkey org-agenda-mode-map "O" 'org-agenda-clock-out)
14087 (org-defkey org-agenda-mode-map "X" 'org-agenda-clock-cancel)
14088 (org-defkey org-agenda-mode-map "+" 'org-agenda-priority-up)
14089 (org-defkey org-agenda-mode-map "-" 'org-agenda-priority-down)
14090 (org-defkey org-agenda-mode-map [(shift up)] 'org-agenda-priority-up)
14091 (org-defkey org-agenda-mode-map [(shift down)] 'org-agenda-priority-down)
14092 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (up)] 'org-agenda-priority-up)
14093 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (down)] 'org-agenda-priority-down)
14094 (org-defkey org-agenda-mode-map [(right)] 'org-agenda-later)
14095 (org-defkey org-agenda-mode-map [(left)] 'org-agenda-earlier)
14096 (org-defkey org-agenda-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files)
14097 (defvar org-agenda-keymap (copy-keymap org-agenda-mode-map)
14098 "Local keymap for agenda entries from Org-mode.")
14100 (org-defkey org-agenda-keymap
14101 (if (featurep 'xemacs) [(button2)] [(mouse-2)]) 'org-agenda-goto-mouse)
14102 (org-defkey org-agenda-keymap
14103 (if (featurep 'xemacs) [(button3)] [(mouse-3)]) 'org-agenda-show-mouse)
14104 (when org-agenda-mouse-1-follows-link
14105 (org-defkey org-agenda-keymap [follow-link] 'mouse-face))
14106 (easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu"
14107 '("Agenda"
14108 ("Agenda Files")
14109 "--"
14110 ["Show" org-agenda-show t]
14111 ["Go To (other window)" org-agenda-goto t]
14112 ["Go To (this window)" org-agenda-switch-to t]
14113 ["Follow Mode" org-agenda-follow-mode
14114 :style toggle :selected org-agenda-follow-mode :active t]
14115 ["Tree to indirect frame" org-agenda-tree-to-indirect-buffer t]
14116 "--"
14117 ["Cycle TODO" org-agenda-todo t]
14118 ["Archive subtree" org-agenda-archive t]
14119 ["Delete subtree" org-agenda-kill t]
14120 "--"
14121 ["Goto Today" org-agenda-goto-today (org-agenda-check-type nil 'agenda 'timeline)]
14122 ["Next Dates" org-agenda-later (org-agenda-check-type nil 'agenda)]
14123 ["Previous Dates" org-agenda-earlier (org-agenda-check-type nil 'agenda)]
14124 "--"
14125 ("Tags"
14126 ["Show all Tags" org-agenda-show-tags t]
14127 ["Set Tags" org-agenda-set-tags t])
14128 ("Date/Schedule"
14129 ["Schedule" org-agenda-schedule t]
14130 ["Set Deadline" org-agenda-deadline t]
14131 "--"
14132 ["Change date +1 day" org-agenda-date-later (org-agenda-check-type nil 'agenda 'timeline)]
14133 ["Change date -1 day" org-agenda-date-earlier (org-agenda-check-type nil 'agenda 'timeline)]
14134 ["Change date to ..." org-agenda-date-prompt (org-agenda-check-type nil 'agenda 'timeline)])
14135 ("Priority"
14136 ["Set Priority" org-agenda-priority t]
14137 ["Increase Priority" org-agenda-priority-up t]
14138 ["Decrease Priority" org-agenda-priority-down t]
14139 ["Show Priority" org-agenda-show-priority t])
14140 ("Calendar/Diary"
14141 ["New Diary Entry" org-agenda-diary-entry (org-agenda-check-type nil 'agenda 'timeline)]
14142 ["Goto Calendar" org-agenda-goto-calendar (org-agenda-check-type nil 'agenda 'timeline)]
14143 ["Phases of the Moon" org-agenda-phases-of-moon (org-agenda-check-type nil 'agenda 'timeline)]
14144 ["Sunrise/Sunset" org-agenda-sunrise-sunset (org-agenda-check-type nil 'agenda 'timeline)]
14145 ["Holidays" org-agenda-holidays (org-agenda-check-type nil 'agenda 'timeline)]
14146 ["Convert" org-agenda-convert-date (org-agenda-check-type nil 'agenda 'timeline)]
14147 "--"
14148 ["Create iCalendar file" org-export-icalendar-combine-agenda-files t])
14149 "--"
14150 ("View"
14151 ["Day View" org-agenda-day-view :active (org-agenda-check-type nil 'agenda)
14152 :style radio :selected (equal org-agenda-ndays 1)]
14153 ["Week View" org-agenda-week-view :active (org-agenda-check-type nil 'agenda)
14154 :style radio :selected (equal org-agenda-ndays 7)]
14155 "--"
14156 ["Show Logbook entries" org-agenda-log-mode
14157 :style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)]
14158 ["Include Diary" org-agenda-toggle-diary
14159 :style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)]
14160 ["Use Time Grid" org-agenda-toggle-time-grid
14161 :style toggle :selected org-agenda-use-time-grid :active (org-agenda-check-type nil 'agenda)])
14162 ["Write view to file" org-write-agenda t]
14163 ["Rebuild buffer" org-agenda-redo t]
14164 ["Save all Org-mode Buffers" org-save-all-org-buffers t]
14165 "--"
14166 ["Undo Remote Editing" org-agenda-undo org-agenda-undo-list]
14167 "--"
14168 ["Quit" org-agenda-quit t]
14169 ["Exit and Release Buffers" org-agenda-exit t]
14172 ;;; Agenda undo
14174 (defvar org-agenda-allow-remote-undo t
14175 "Non-nil means, allow remote undo from the agenda buffer.")
14176 (defvar org-agenda-undo-list nil
14177 "List of undoable operations in the agenda since last refresh.")
14178 (defvar org-agenda-undo-has-started-in nil
14179 "Buffers that have already seen `undo-start' in the current undo sequence.")
14180 (defvar org-agenda-pending-undo-list nil
14181 "In a series of undo commands, this is the list of remaning undo items.")
14183 (defmacro org-if-unprotected (&rest body)
14184 "Execute BODY if ther is no `org-protected' text property at point."
14185 (declare (debug t))
14186 `(unless (get-text-property (point) 'org-protected)
14187 ,@body))
14189 (defmacro org-unmodified (&rest body)
14190 "Execute body without changing buffer-modified-p."
14191 `(set-buffer-modified-p
14192 (prog1 (buffer-modified-p) ,@body)))
14194 (defmacro org-with-remote-undo (_buffer &rest _body)
14195 "Execute BODY while recording undo information in two buffers."
14196 (declare (indent 1) (debug t))
14197 `(let ((_cline (org-current-line))
14198 (_cmd this-command)
14199 (_buf1 (current-buffer))
14200 (_buf2 ,_buffer)
14201 (_undo1 buffer-undo-list)
14202 (_undo2 (with-current-buffer ,_buffer buffer-undo-list))
14203 _c1 _c2)
14204 ,@_body
14205 (when org-agenda-allow-remote-undo
14206 (setq _c1 (org-verify-change-for-undo
14207 _undo1 (with-current-buffer _buf1 buffer-undo-list))
14208 _c2 (org-verify-change-for-undo
14209 _undo2 (with-current-buffer _buf2 buffer-undo-list)))
14210 (when (or _c1 _c2)
14211 ;; make sure there are undo boundaries
14212 (and _c1 (with-current-buffer _buf1 (undo-boundary)))
14213 (and _c2 (with-current-buffer _buf2 (undo-boundary)))
14214 ;; remember which buffer to undo
14215 (push (list _cmd _cline _buf1 _c1 _buf2 _c2)
14216 org-agenda-undo-list)))))
14218 (defun org-agenda-undo ()
14219 "Undo a remote editing step in the agenda.
14220 This undoes changes both in the agenda buffer and in the remote buffer
14221 that have been changed along."
14222 (interactive)
14223 (or org-agenda-allow-remote-undo
14224 (error "Check the variable `org-agenda-allow-remote-undo' to activate remote undo."))
14225 (if (not (eq this-command last-command))
14226 (setq org-agenda-undo-has-started-in nil
14227 org-agenda-pending-undo-list org-agenda-undo-list))
14228 (if (not org-agenda-pending-undo-list)
14229 (error "No further undo information"))
14230 (let* ((entry (pop org-agenda-pending-undo-list))
14231 buf line cmd rembuf)
14232 (setq cmd (pop entry) line (pop entry))
14233 (setq rembuf (nth 2 entry))
14234 (org-with-remote-undo rembuf
14235 (while (bufferp (setq buf (pop entry)))
14236 (if (pop entry)
14237 (with-current-buffer buf
14238 (let ((last-undo-buffer buf)
14239 buffer-read-only)
14240 (unless (memq buf org-agenda-undo-has-started-in)
14241 (push buf org-agenda-undo-has-started-in)
14242 (make-local-variable 'pending-undo-list)
14243 (undo-start))
14244 (while (and pending-undo-list
14245 (listp pending-undo-list)
14246 (not (car pending-undo-list)))
14247 (pop pending-undo-list))
14248 (undo-more 1))))))
14249 (goto-line line)
14250 (message "`%s' undone (buffer %s)" cmd (buffer-name rembuf))))
14252 (defun org-verify-change-for-undo (l1 l2)
14253 "Verify that a real change occurred between the undo lists L1 and L2."
14254 (while (and l1 (listp l1) (null (car l1))) (pop l1))
14255 (while (and l2 (listp l2) (null (car l2))) (pop l2))
14256 (not (eq l1 l2)))
14258 ;;; Agenda dispatch
14260 (defvar org-agenda-restrict nil)
14261 (defvar org-agenda-restrict-begin (make-marker))
14262 (defvar org-agenda-restrict-end (make-marker))
14263 (defvar org-agenda-last-dispatch-buffer nil)
14265 ;;;###autoload
14266 (defun org-agenda (arg)
14267 "Dispatch agenda commands to collect entries to the agenda buffer.
14268 Prompts for a character to select a command. Any prefix arg will be passed
14269 on to the selected command. The default selections are:
14271 a Call `org-agenda-list' to display the agenda for current day or week.
14272 t Call `org-todo-list' to display the global todo list.
14273 T Call `org-todo-list' to display the global todo list, select only
14274 entries with a specific TODO keyword (the user gets a prompt).
14275 m Call `org-tags-view' to display headlines with tags matching
14276 a condition (the user is prompted for the condition).
14277 M Like `m', but select only TODO entries, no ordinary headlines.
14278 l Create a timeline for the current buffer.
14279 e Export views to associated files.
14281 More commands can be added by configuring the variable
14282 `org-agenda-custom-commands'. In particular, specific tags and TODO keyword
14283 searches can be pre-defined in this way.
14285 If the current buffer is in Org-mode and visiting a file, you can also
14286 first press `1' to indicate that the agenda should be temporarily (until the
14287 next use of \\[org-agenda]) restricted to the current file."
14288 (interactive "P")
14289 (catch 'exit
14290 (let* ((buf (current-buffer))
14291 (bfn (buffer-file-name (buffer-base-buffer)))
14292 (restrict-ok (and bfn (org-mode-p)))
14293 (custom org-agenda-custom-commands)
14294 c entry key type match lprops)
14295 ;; Turn off restriction
14296 (put 'org-agenda-files 'org-restrict nil)
14297 (setq org-agenda-restrict nil)
14298 (move-marker org-agenda-restrict-begin nil)
14299 (move-marker org-agenda-restrict-end nil)
14300 ;; Remember where this call originated
14301 (setq org-agenda-last-dispatch-buffer (current-buffer))
14302 (save-window-excursion
14303 (delete-other-windows)
14304 (switch-to-buffer-other-window " *Agenda Commands*")
14305 (erase-buffer)
14306 (insert (eval-when-compile
14307 (let ((header
14308 "Press key for an agenda command:
14309 -------------------------------- C Configure custom agenda commands
14310 a Agenda for current week or day e Export agenda views
14311 t List of all TODO entries T Entries with special TODO kwd
14312 m Match a TAGS query M Like m, but only TODO entries
14313 L Timeline for current buffer # List stuck projects (!=configure)
14315 (start 0))
14316 (while (string-match "\\(^\\| \\|(\\)\\(\\S-\\)\\( \\|=\\)" header start)
14317 (setq start (match-end 0))
14318 (add-text-properties (match-beginning 2) (match-end 2)
14319 '(face bold) header))
14320 header)))
14321 (while (setq entry (pop custom))
14322 (setq key (car entry) type (nth 1 entry) match (nth 2 entry))
14323 (insert (format "\n%-4s%-14s: %s"
14324 (org-add-props (copy-sequence key)
14325 '(face bold))
14326 (cond
14327 ((stringp type) type)
14328 ((eq type 'agenda) "Agenda for current week or day")
14329 ((eq type 'alltodo) "List of all TODO entries")
14330 ((eq type 'stuck) "List of stuck projects")
14331 ((eq type 'todo) "TODO keyword")
14332 ((eq type 'tags) "Tags query")
14333 ((eq type 'tags-todo) "Tags (TODO)")
14334 ((eq type 'tags-tree) "Tags tree")
14335 ((eq type 'todo-tree) "TODO kwd tree")
14336 ((eq type 'occur-tree) "Occur tree")
14337 ((functionp type) (symbol-name type))
14338 (t "???"))
14339 (if (stringp match)
14340 (org-add-props match nil 'face 'org-warning)
14341 (format "set of %d commands" (length match))))))
14342 (if restrict-ok
14343 (insert "\n"
14344 (org-add-props "1 Restrict call to current buffer 0 Restrict call to region or subtree" nil 'face 'org-table)))
14345 (goto-char (point-min))
14346 (if (fboundp 'fit-window-to-buffer) (fit-window-to-buffer))
14347 (message "Press key for agenda command%s"
14348 (if restrict-ok ", or [1] or [0] to restrict" ""))
14349 (setq c (read-char-exclusive))
14350 (message "")
14351 (when (memq c '(?L ?1 ?0))
14352 (if restrict-ok
14353 (put 'org-agenda-files 'org-restrict (list bfn))
14354 (error "Cannot restrict agenda to current buffer"))
14355 (with-current-buffer " *Agenda Commands*"
14356 (goto-char (point-max))
14357 (delete-region (point-at-bol) (point))
14358 (goto-char (point-min)))
14359 (when (eq c ?0)
14360 (setq org-agenda-restrict t)
14361 (with-current-buffer buf
14362 (if (org-region-active-p)
14363 (progn
14364 (move-marker org-agenda-restrict-begin (region-beginning))
14365 (move-marker org-agenda-restrict-end (region-end)))
14366 (save-excursion
14367 (org-back-to-heading t)
14368 (move-marker org-agenda-restrict-begin (point))
14369 (move-marker org-agenda-restrict-end
14370 (progn (org-end-of-subtree t)))))))
14371 (unless (eq c ?L)
14372 (message "Press key for agenda command%s"
14373 (if restrict-ok " (restricted to current file)" ""))
14374 (setq c (read-char-exclusive)))
14375 (message "")))
14376 (require 'calendar) ; FIXME: can we avoid this for some commands?
14377 ;; For example the todo list should not need it (but does...)
14378 (cond
14379 ((setq entry (assoc (char-to-string c) org-agenda-custom-commands))
14380 (if (symbolp (nth 1 entry))
14381 (progn
14382 (setq type (nth 1 entry) match (nth 2 entry) lprops (nth 3 entry)
14383 lprops (nth 3 entry))
14384 (cond
14385 ((eq type 'agenda)
14386 (org-let lprops '(org-agenda-list current-prefix-arg)))
14387 ((eq type 'alltodo)
14388 (org-let lprops '(org-todo-list current-prefix-arg)))
14389 ((eq type 'stuck)
14390 (org-let lprops '(org-agenda-list-stuck-projects
14391 current-prefix-arg)))
14392 ((eq type 'tags)
14393 (org-let lprops '(org-tags-view current-prefix-arg match)))
14394 ((eq type 'tags-todo)
14395 (org-let lprops '(org-tags-view '(4) match)))
14396 ((eq type 'todo)
14397 (org-let lprops '(org-todo-list match)))
14398 ((eq type 'tags-tree)
14399 (org-check-for-org-mode)
14400 (org-let lprops '(org-tags-sparse-tree current-prefix-arg match)))
14401 ((eq type 'todo-tree)
14402 (org-check-for-org-mode)
14403 (org-let lprops
14404 '(org-occur (concat "^" outline-regexp "[ \t]*"
14405 (regexp-quote match) "\\>"))))
14406 ((eq type 'occur-tree)
14407 (org-check-for-org-mode)
14408 (org-let lprops '(org-occur match)))
14409 ((fboundp type)
14410 (org-let lprops '(funcall type match)))
14411 (t (error "Invalid custom agenda command type %s" type))))
14412 (org-run-agenda-series (cddr entry))))
14413 ((equal c ?C) (customize-variable 'org-agenda-custom-commands))
14414 ((equal c ?a) (call-interactively 'org-agenda-list))
14415 ((equal c ?t) (call-interactively 'org-todo-list))
14416 ((equal c ?T) (org-call-with-arg 'org-todo-list (or arg '(4))))
14417 ((equal c ?m) (call-interactively 'org-tags-view))
14418 ((equal c ?M) (org-call-with-arg 'org-tags-view (or arg '(4))))
14419 ((equal c ?e) (call-interactively 'org-store-agenda-views))
14420 ((equal c ?L)
14421 (unless restrict-ok
14422 (error "This is not an Org-mode file"))
14423 (org-call-with-arg 'org-timeline arg))
14424 ((equal c ?#) (call-interactively 'org-agenda-list-stuck-projects))
14425 ((equal c ?!) (customize-variable 'org-stuck-projects))
14426 (t (error "Invalid key"))))))
14428 (defun org-run-agenda-series (series)
14429 (org-prepare-agenda)
14430 (let* ((org-agenda-multi t)
14431 (redo (list 'org-run-agenda-series (list 'quote series)))
14432 (cmds (car series))
14433 (gprops (nth 1 series))
14434 match ;; The byte compiler incorrectly complains about this. Keep it!
14435 cmd type lprops)
14436 (while (setq cmd (pop cmds))
14437 (setq type (car cmd) match (nth 1 cmd) lprops (nth 2 cmd))
14438 (cond
14439 ((eq type 'agenda)
14440 (org-let2 gprops lprops
14441 '(call-interactively 'org-agenda-list)))
14442 ((eq type 'alltodo)
14443 (org-let2 gprops lprops
14444 '(call-interactively 'org-todo-list)))
14445 ((eq type 'stuck)
14446 (org-let2 gprops lprops
14447 '(call-interactively 'org-agenda-list-stuck-projects)))
14448 ((eq type 'tags)
14449 (org-let2 gprops lprops
14450 '(org-tags-view current-prefix-arg match)))
14451 ((eq type 'tags-todo)
14452 (org-let2 gprops lprops
14453 '(org-tags-view '(4) match)))
14454 ((eq type 'todo)
14455 (org-let2 gprops lprops
14456 '(org-todo-list match)))
14457 ((fboundp type)
14458 (org-let2 gprops lprops
14459 '(funcall type match)))
14460 (t (error "Invalid type in command series"))))
14461 (widen)
14462 (setq org-agenda-redo-command redo)
14463 (goto-char (point-min)))
14464 (org-finalize-agenda))
14466 ;;;###autoload
14467 (defmacro org-batch-agenda (cmd-key &rest parameters)
14468 "Run an agenda command in batch mode and send the result to STDOUT.
14469 If CMD-KEY is a string of length 1, it is used as a key in
14470 `org-agenda-custom-commands' and triggers this command. If it is a
14471 longer string is is used as a tags/todo match string.
14472 Paramters are alternating variable names and values that will be bound
14473 before running the agenda command."
14474 (let (pars)
14475 (while parameters
14476 (push (list (pop parameters) (if parameters (pop parameters))) pars))
14477 (if (> (length cmd-key) 1)
14478 (eval (list 'let (nreverse pars)
14479 (list 'org-tags-view nil cmd-key)))
14480 (flet ((read-char-exclusive () (string-to-char cmd-key)))
14481 (eval (list 'let (nreverse pars) '(org-agenda nil)))))
14482 (set-buffer "*Org Agenda*")
14483 (princ (buffer-string))))
14485 (defvar org-agenda-info nil)
14487 ;;;###autoload
14488 (defmacro org-batch-agenda-csv (cmd-key &rest parameters)
14489 "Run an agenda command in batch mode and send the result to STDOUT.
14490 If CMD-KEY is a string of length 1, it is used as a key in
14491 `org-agenda-custom-commands' and triggers this command. If it is a
14492 longer string is is used as a tags/todo match string.
14493 Paramters are alternating variable names and values that will be bound
14494 before running the agenda command.
14496 The output gives a line for each selected agenda item. Each
14497 item is a list of comma-separated values, like this:
14499 category,head,type,todo,tags,date,time,extra,priority-l,priority-n
14501 category The category of the item
14502 head The headline, without TODO kwd, TAGS and PRIORITY
14503 type The type of the agenda entry, can be
14504 todo selected in TODO match
14505 tagsmatch selected in tags match
14506 diary imported from diary
14507 deadline a deadline on given date
14508 scheduled scheduled on given date
14509 timestamp entry has timestamp on given date
14510 closed entry was closed on given date
14511 upcoming-deadline warning about deadline
14512 past-scheduled forwarded scheduled item
14513 block entry has date block including g. date
14514 todo The todo keyword, if any
14515 tags All tags including inherited ones, separated by colons
14516 date The relevant date, like 2007-2-14
14517 time The time, like 15:00-16:50
14518 extra Sting with extra planning info
14519 priority-l The priority letter if any was given
14520 priority-n The computed numerical priority"
14522 (let (pars)
14523 (while parameters
14524 (push (list (pop parameters) (if parameters (pop parameters))) pars))
14525 (push (list 'org-agenda-remove-tags t) pars)
14526 (if (> (length cmd-key) 1)
14527 (eval (list 'let (nreverse pars)
14528 (list 'org-tags-view nil cmd-key)))
14529 (flet ((read-char-exclusive () (string-to-char cmd-key)))
14530 (eval (list 'let (nreverse pars) '(org-agenda nil)))))
14531 (set-buffer "*Org Agenda*")
14532 (let* ((lines (org-split-string (buffer-string) "\n"))
14533 line)
14534 (while (setq line (pop lines))
14535 (catch 'next
14536 (if (not (get-text-property 0 'org-category line)) (throw 'next nil))
14537 (setq org-agenda-info
14538 (org-fix-agenda-info (text-properties-at 0 line)))
14539 (princ
14540 (mapconcat 'org-agenda-export-csv-mapper
14541 '(org-category txt type todo tags date time-of-day extra
14542 priority-letter priority)
14543 ","))
14544 (princ "\n"))))))
14546 (defun org-fix-agenda-info (props)
14547 "FIXME"
14548 (let (tmp re)
14549 (when (setq tmp (plist-get props 'tags))
14550 (setq props (plist-put props 'tags (mapconcat 'identity tmp ":"))))
14551 (when (setq tmp (plist-get props 'date))
14552 (if (integerp tmp) (setq tmp (calendar-gregorian-from-absolute tmp)))
14553 (let ((calendar-date-display-form '(year "-" month "-" day)))
14554 (setq tmp (calendar-date-string tmp)))
14555 (setq props (plist-put props 'date tmp)))
14556 (when (setq tmp (plist-get props 'txt))
14557 (when (string-match "\\[#\\([A-Z0-9]\\)\\] ?" tmp)
14558 (plist-put props 'priority-letter (match-string 1 tmp))
14559 (setq tmp (replace-match "" t t tmp)))
14560 (when (and (setq re (plist-get props 'org-todo-regexp))
14561 (setq re (concat "\\`\\.*" re " ?"))
14562 (string-match re tmp))
14563 (plist-put props 'todo (match-string 1 tmp))
14564 (setq tmp (replace-match "" t t tmp)))
14565 (plist-put props 'txt tmp)))
14566 props)
14568 (defun org-agenda-export-csv-mapper (prop)
14569 (let ((res (plist-get org-agenda-info prop)))
14570 (setq res
14571 (cond
14572 ((not res) "")
14573 ((stringp res) res)
14574 (t (prin1-to-string res))))
14575 (while (string-match "," res)
14576 (setq res (replace-match ";" t t res)))
14577 (org-trim res)))
14580 ;;;###autoload
14581 (defun org-store-agenda-views (&rest parameters)
14582 (interactive)
14583 (eval (list 'org-batch-store-agenda-views)))
14585 (defvar org-agenda-buffer-name)
14587 ;; FIXME, why is this a macro?????
14588 ;;;###autoload
14589 (defmacro org-batch-store-agenda-views (&rest parameters)
14590 "Run all custom agenda commands that have a file argument."
14591 (let ((cmds org-agenda-custom-commands)
14592 pars cmd thiscmdkey files opts)
14593 (while parameters
14594 (push (list (pop parameters) (if parameters (pop parameters))) pars))
14595 (setq pars (reverse pars))
14596 (save-window-excursion
14597 (while cmds
14598 (setq cmd (pop cmds)
14599 thiscmdkey (car cmd)
14600 opts (nth 3 cmd)
14601 files (org-last cmd))
14602 (if (stringp files) (setq files (list files)))
14603 (when files
14604 (flet ((read-char-exclusive () (string-to-char thiscmdkey)))
14605 (eval (list 'let (append org-agenda-exporter-settings opts pars)
14606 '(org-agenda nil))))
14607 (set-buffer "*Org Agenda*")
14608 (while files
14609 (eval (list 'let (append org-agenda-exporter-settings opts pars)
14610 (list 'org-write-agenda (pop files) t)))))
14611 (kill-buffer org-agenda-buffer-name)))))
14613 (defun org-write-agenda (file &optional nosettings)
14614 "Write the current buffer (an agenda view) as a file.
14615 Depending on the extension of the file name, plain text (.txt),
14616 HTML (.html or .htm) or Postscript (.ps) is produced.
14617 If NOSETTINGS is given, do not scope the settings of
14618 `org-agenda-exporter-settings' into the export commands. This is used when
14619 the settings have already been scoped and we do not wish to overrule other,
14620 higher priority settings."
14621 (interactive "FWrite agenda to file: ")
14622 (if (not (file-writable-p file))
14623 (error "Cannot write agenda to file %s" file))
14624 (cond
14625 ((string-match "\\.html?\\'" file) (require 'htmlize))
14626 ((string-match "\\.ps\\'" file) (require 'ps-print)))
14627 (org-let (if nosettings nil org-agenda-exporter-settings)
14628 '(save-excursion
14629 (save-window-excursion
14630 (cond
14631 ((string-match "\\.html?\\'" file)
14632 (set-buffer (htmlize-buffer (current-buffer)))
14634 (when (and org-agenda-export-html-style
14635 (string-match "<style>" org-agenda-export-html-style))
14636 ;; replace <style> section with org-agenda-export-html-style
14637 (goto-char (point-min))
14638 (kill-region (- (search-forward "<style") 6)
14639 (search-forward "</style>"))
14640 (insert org-agenda-export-html-style))
14641 (write-file file)
14642 (kill-buffer (current-buffer))
14643 (message "HTML written to %s" file))
14644 ((string-match "\\.ps\\'" file)
14645 (ps-print-buffer-with-faces file)
14646 (message "Postscript written to %s" file))
14648 (let ((bs (buffer-string)))
14649 (find-file file)
14650 (insert bs)
14651 (save-buffer 0)
14652 (kill-buffer (current-buffer))
14653 (message "Plain text written to %s" file))))))
14654 (set-buffer org-agenda-buffer-name)))
14656 (defmacro org-no-read-only (&rest body)
14657 "Inhibit read-only for BODY."
14658 `(let ((inhibit-read-only t)) ,@body))
14660 (defun org-check-for-org-mode ()
14661 "Make sure current buffer is in org-mode. Error if not."
14662 (or (org-mode-p)
14663 (error "Cannot execute org-mode agenda command on buffer in %s."
14664 major-mode)))
14666 (defun org-fit-agenda-window ()
14667 "Fit the window to the buffer size."
14668 (and (memq org-agenda-window-setup '(reorganize-frame))
14669 (fboundp 'fit-window-to-buffer)
14670 (fit-window-to-buffer nil (/ (* (frame-height) 3) 4)
14671 (/ (frame-height) 2))))
14673 ;;; Agenda file list
14675 (defun org-agenda-files (&optional unrestricted)
14676 "Get the list of agenda files.
14677 Optional UNRESTRICTED means return the full list even if a restriction
14678 is currently in place."
14679 (cond
14680 ((and (not unrestricted) (get 'org-agenda-files 'org-restrict)))
14681 ((stringp org-agenda-files) (org-read-agenda-file-list))
14682 ((listp org-agenda-files) org-agenda-files)
14683 (t (error "Invalid value of `org-agenda-files'"))))
14685 (defun org-edit-agenda-file-list ()
14686 "Edit the list of agenda files.
14687 Depending on setup, this either uses customize to edit the variable
14688 `org-agenda-files', or it visits the file that is holding the list. In the
14689 latter case, the buffer is set up in a way that saving it automatically kills
14690 the buffer and restores the previous window configuration."
14691 (interactive)
14692 (if (stringp org-agenda-files)
14693 (let ((cw (current-window-configuration)))
14694 (find-file org-agenda-files)
14695 (org-set-local 'org-window-configuration cw)
14696 (org-add-hook 'after-save-hook
14697 (lambda ()
14698 (set-window-configuration
14699 (prog1 org-window-configuration
14700 (kill-buffer (current-buffer))))
14701 (org-install-agenda-files-menu)
14702 (message "New agenda file list installed"))
14703 nil 'local)
14704 (message (substitute-command-keys
14705 "Edit list and finish with \\[save-buffer]")))
14706 (customize-variable 'org-agenda-files)))
14708 (defun org-store-new-agenda-file-list (list)
14709 "Set new value for the agenda file list and save it correcly."
14710 (if (stringp org-agenda-files)
14711 (let ((f org-agenda-files) b)
14712 (while (setq b (find-buffer-visiting f)) (kill-buffer b))
14713 (with-temp-file f
14714 (insert (mapconcat 'identity list "\n") "\n")))
14715 (let ((org-mode-hook nil) (default-major-mode 'fundamental-mode))
14716 (setq org-agenda-files list)
14717 (customize-save-variable 'org-agenda-files org-agenda-files))))
14719 (defun org-read-agenda-file-list ()
14720 "Read the list of agenda files from a file."
14721 (when (stringp org-agenda-files)
14722 (with-temp-buffer
14723 (insert-file-contents org-agenda-files)
14724 (org-split-string (buffer-string) "[ \t\r\n]*?[\r\n][ \t\r\n]*"))))
14727 ;;;###autoload
14728 (defun org-cycle-agenda-files ()
14729 "Cycle through the files in `org-agenda-files'.
14730 If the current buffer visits an agenda file, find the next one in the list.
14731 If the current buffer does not, find the first agenda file."
14732 (interactive)
14733 (let* ((fs (org-agenda-files t))
14734 (files (append fs (list (car fs))))
14735 (tcf (if buffer-file-name (file-truename buffer-file-name)))
14736 file)
14737 (unless files (error "No agenda files"))
14738 (catch 'exit
14739 (while (setq file (pop files))
14740 (if (equal (file-truename file) tcf)
14741 (when (car files)
14742 (find-file (car files))
14743 (throw 'exit t))))
14744 (find-file (car fs)))
14745 (if (buffer-base-buffer) (switch-to-buffer (buffer-base-buffer)))))
14747 (defun org-agenda-file-to-front (&optional to-end)
14748 "Move/add the current file to the top of the agenda file list.
14749 If the file is not present in the list, it is added to the front. If it is
14750 present, it is moved there. With optional argument TO-END, add/move to the
14751 end of the list."
14752 (interactive "P")
14753 (let ((file-alist (mapcar (lambda (x)
14754 (cons (file-truename x) x))
14755 (org-agenda-files t)))
14756 (ctf (file-truename buffer-file-name))
14757 x had)
14758 (setq x (assoc ctf file-alist) had x)
14760 (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name))))
14761 (if to-end
14762 (setq file-alist (append (delq x file-alist) (list x)))
14763 (setq file-alist (cons x (delq x file-alist))))
14764 (org-store-new-agenda-file-list (mapcar 'cdr file-alist))
14765 (org-install-agenda-files-menu)
14766 (message "File %s to %s of agenda file list"
14767 (if had "moved" "added") (if to-end "end" "front"))))
14769 (defun org-remove-file (&optional file)
14770 "Remove current file from the list of files in variable `org-agenda-files'.
14771 These are the files which are being checked for agenda entries.
14772 Optional argument FILE means, use this file instead of the current."
14773 (interactive)
14774 (let* ((file (or file buffer-file-name))
14775 (true-file (file-truename file))
14776 (afile (abbreviate-file-name file))
14777 (files (delq nil (mapcar
14778 (lambda (x)
14779 (if (equal true-file
14780 (file-truename x))
14781 nil x))
14782 (org-agenda-files t)))))
14783 (if (not (= (length files) (length (org-agenda-files t))))
14784 (progn
14785 (org-store-new-agenda-file-list files)
14786 (org-install-agenda-files-menu)
14787 (message "Removed file: %s" afile))
14788 (message "File was not in list: %s" afile))))
14790 (defun org-file-menu-entry (file)
14791 (vector file (list 'find-file file) t))
14793 (defun org-check-agenda-file (file)
14794 "Make sure FILE exists. If not, ask user what to do."
14795 (when (not (file-exists-p file))
14796 (message "non-existent file %s. [R]emove from list or [A]bort?"
14797 (abbreviate-file-name file))
14798 (let ((r (downcase (read-char-exclusive))))
14799 (cond
14800 ((equal r ?r)
14801 (org-remove-file file)
14802 (throw 'nextfile t))
14803 (t (error "Abort"))))))
14805 ;;; Agenda prepare and finalize
14807 (defvar org-agenda-multi nil) ; dynammically scoped
14808 (defvar org-agenda-buffer-name "*Org Agenda*")
14809 (defvar org-pre-agenda-window-conf nil)
14810 (defun org-prepare-agenda ()
14811 (setq org-todo-keywords-for-agenda nil)
14812 (setq org-done-keywords-for-agenda nil)
14813 (if org-agenda-multi
14814 (progn
14815 (setq buffer-read-only nil)
14816 (goto-char (point-max))
14817 (unless (= (point) 1)
14818 (insert "\n" (make-string (window-width) ?=) "\n"))
14819 (narrow-to-region (point) (point-max)))
14820 (org-agenda-maybe-reset-markers 'force)
14821 (org-prepare-agenda-buffers (org-agenda-files))
14822 (setq org-todo-keywords-for-agenda
14823 (org-uniquify org-todo-keywords-for-agenda))
14824 (setq org-done-keywords-for-agenda
14825 (org-uniquify org-done-keywords-for-agenda))
14826 (let* ((abuf (get-buffer-create org-agenda-buffer-name))
14827 (awin (get-buffer-window abuf)))
14828 (cond
14829 ((equal (current-buffer) abuf) nil)
14830 (awin (select-window awin))
14831 ((not (setq org-pre-agenda-window-conf (current-window-configuration))))
14832 ((equal org-agenda-window-setup 'current-window)
14833 (switch-to-buffer abuf))
14834 ((equal org-agenda-window-setup 'other-window)
14835 (switch-to-buffer-other-window abuf))
14836 ((equal org-agenda-window-setup 'other-frame)
14837 (switch-to-buffer-other-frame abuf))
14838 ((equal org-agenda-window-setup 'reorganize-frame)
14839 (delete-other-windows)
14840 (switch-to-buffer-other-window abuf))))
14841 (setq buffer-read-only nil)
14842 (erase-buffer)
14843 (org-agenda-mode))
14844 (setq buffer-read-only nil))
14846 (defun org-finalize-agenda ()
14847 "Finishing touch for the agenda buffer, called just before displaying it."
14848 (unless org-agenda-multi
14849 (org-agenda-align-tags)
14850 (save-excursion
14851 (let ((buffer-read-only))
14852 (goto-char (point-min))
14853 (while (org-activate-bracket-links (point-max))
14854 (add-text-properties (match-beginning 0) (match-end 0)
14855 '(face org-link)))
14856 (unless org-agenda-with-colors
14857 (remove-text-properties (point-min) (point-max) '(face nil))))
14858 (run-hooks 'org-finalize-agenda-hook))))
14860 (defun org-prepare-agenda-buffers (files)
14861 "Create buffers for all agenda files, protect archived trees and comments."
14862 (interactive)
14863 (let ((pa '(:org-archived t))
14864 (pc '(:org-comment t))
14865 (pall '(:org-archived t :org-comment t))
14866 (rea (concat ":" org-archive-tag ":"))
14867 bmp file re)
14868 (save-excursion
14869 (save-restriction
14870 (while (setq file (pop files))
14871 (org-check-agenda-file file)
14872 (set-buffer (org-get-agenda-file-buffer file))
14873 (widen)
14874 (setq bmp (buffer-modified-p))
14875 (setq org-todo-keywords-for-agenda
14876 (append org-todo-keywords-for-agenda org-todo-keywords-1))
14877 (setq org-done-keywords-for-agenda
14878 (append org-done-keywords-for-agenda org-done-keywords))
14879 (save-excursion
14880 (remove-text-properties (point-min) (point-max) pall)
14881 (when org-agenda-skip-archived-trees
14882 (goto-char (point-min))
14883 (while (re-search-forward rea nil t)
14884 (if (org-on-heading-p t)
14885 (add-text-properties (point-at-bol) (org-end-of-subtree t) pa))))
14886 (goto-char (point-min))
14887 (setq re (concat "^\\*+ +" org-comment-string "\\>"))
14888 (while (re-search-forward re nil t)
14889 (add-text-properties
14890 (match-beginning 0) (org-end-of-subtree t) pc)))
14891 (set-buffer-modified-p bmp))))))
14893 (defvar org-agenda-skip-function nil
14894 "Function to be called at each match during agenda construction.
14895 If this function return nil, the current match should not be skipped.
14896 Otherwise, the function must return a position from where the search
14897 should be continued.
14898 Never set this variable using `setq' or so, because then it will apply
14899 to all future agenda commands. Instead, bind it with `let' to scope
14900 it dynamically into the agenda-constructing command.")
14902 (defun org-agenda-skip ()
14903 "Throw to `:skip' in places that should be skipped.
14904 Also moves point to the end of the skipped region, so that search can
14905 continue from there."
14906 (let ((p (point-at-bol)) to)
14907 (and org-agenda-skip-archived-trees
14908 (get-text-property p :org-archived)
14909 (org-end-of-subtree t)
14910 (throw :skip t))
14911 (and (get-text-property p :org-comment)
14912 (org-end-of-subtree t)
14913 (throw :skip t))
14914 (if (equal (char-after p) ?#) (throw :skip t))
14915 (when (and (functionp org-agenda-skip-function)
14916 (setq to (save-excursion
14917 (save-match-data
14918 (funcall org-agenda-skip-function)))))
14919 (goto-char to)
14920 (throw :skip t))))
14922 (defvar org-agenda-markers nil
14923 "List of all currently active markers created by `org-agenda'.")
14924 (defvar org-agenda-last-marker-time (time-to-seconds (current-time))
14925 "Creation time of the last agenda marker.")
14927 (defun org-agenda-new-marker (&optional pos)
14928 "Return a new agenda marker.
14929 Org-mode keeps a list of these markers and resets them when they are
14930 no longer in use."
14931 (let ((m (copy-marker (or pos (point)))))
14932 (setq org-agenda-last-marker-time (time-to-seconds (current-time)))
14933 (push m org-agenda-markers)
14936 (defun org-agenda-maybe-reset-markers (&optional force)
14937 "Reset markers created by `org-agenda'. But only if they are old enough."
14938 (if (or (and force (not org-agenda-multi))
14939 (> (- (time-to-seconds (current-time))
14940 org-agenda-last-marker-time)
14942 (while org-agenda-markers
14943 (move-marker (pop org-agenda-markers) nil))))
14945 (defvar org-agenda-new-buffers nil
14946 "Buffers created to visit agenda files.")
14948 (defun org-get-agenda-file-buffer (file)
14949 "Get a buffer visiting FILE. If the buffer needs to be created, add
14950 it to the list of buffers which might be released later."
14951 (let ((buf (org-find-base-buffer-visiting file)))
14952 (if buf
14953 buf ; just return it
14954 ;; Make a new buffer and remember it
14955 (setq buf (find-file-noselect file))
14956 (if buf (push buf org-agenda-new-buffers))
14957 buf)))
14959 (defun org-release-buffers (blist)
14960 "Release all buffers in list, asking the user for confirmation when needed.
14961 When a buffer is unmodified, it is just killed. When modified, it is saved
14962 \(if the user agrees) and then killed."
14963 (let (buf file)
14964 (while (setq buf (pop blist))
14965 (setq file (buffer-file-name buf))
14966 (when (and (buffer-modified-p buf)
14967 file
14968 (y-or-n-p (format "Save file %s? " file)))
14969 (with-current-buffer buf (save-buffer)))
14970 (kill-buffer buf))))
14972 (defvar org-category-table nil)
14973 (defun org-get-category-table ()
14974 "Get the table of categories and positions in current buffer."
14975 (let (tbl)
14976 (save-excursion
14977 (save-restriction
14978 (widen)
14979 (goto-char (point-min))
14980 (while (re-search-forward "^#\\+CATEGORY:[ \t]*\\(.*\\)"
14981 nil t)
14982 (push (cons (match-beginning 1)
14983 (org-trim (match-string 1))) tbl))))
14984 tbl))
14986 (defun org-get-category (&optional pos)
14987 "Get the category applying to position POS."
14988 (if (not org-category-table)
14989 (cond
14990 ((null org-category)
14991 (setq org-category
14992 (if buffer-file-name
14993 (file-name-sans-extension
14994 (file-name-nondirectory buffer-file-name))
14995 "???")))
14996 ((symbolp org-category) (symbol-name org-category))
14997 (t org-category))
14998 (let ((tbl org-category-table)
14999 (pos (or pos (point))))
15000 (while (and tbl (> (caar tbl) pos))
15001 (pop tbl))
15002 (or (cdar tbl) (cdr (nth (1- (length org-category-table))
15003 org-category-table))))))
15004 ;;; Agenda timeline
15006 (defun org-timeline (&optional include-all)
15007 "Show a time-sorted view of the entries in the current org file.
15008 Only entries with a time stamp of today or later will be listed. With
15009 \\[universal-argument] prefix, all unfinished TODO items will also be shown,
15010 under the current date.
15011 If the buffer contains an active region, only check the region for
15012 dates."
15013 (interactive "P")
15014 (require 'calendar)
15015 (org-compile-prefix-format 'timeline)
15016 (org-set-sorting-strategy 'timeline)
15017 (let* ((dopast t)
15018 (dotodo include-all)
15019 (doclosed org-agenda-show-log)
15020 (entry buffer-file-name)
15021 (date (calendar-current-date))
15022 (beg (if (org-region-active-p) (region-beginning) (point-min)))
15023 (end (if (org-region-active-p) (region-end) (point-max)))
15024 (day-numbers (org-get-all-dates beg end 'no-ranges
15025 t doclosed ; always include today
15026 org-timeline-show-empty-dates))
15027 (today (time-to-days (current-time)))
15028 (past t)
15029 args
15030 s e rtn d emptyp)
15031 (setq org-agenda-redo-command
15032 (list 'progn
15033 (list 'switch-to-buffer-other-window (current-buffer))
15034 (list 'org-timeline (list 'quote include-all))))
15035 (if (not dopast)
15036 ;; Remove past dates from the list of dates.
15037 (setq day-numbers (delq nil (mapcar (lambda(x)
15038 (if (>= x today) x nil))
15039 day-numbers))))
15040 (org-prepare-agenda)
15041 (if doclosed (push :closed args))
15042 (push :timestamp args)
15043 (push :sexp args)
15044 (if dotodo (push :todo args))
15045 (while (setq d (pop day-numbers))
15046 (if (and (listp d) (eq (car d) :omitted))
15047 (progn
15048 (setq s (point))
15049 (insert (format "\n[... %d empty days omitted]\n\n" (cdr d)))
15050 (put-text-property s (1- (point)) 'face 'org-agenda-structure))
15051 (if (listp d) (setq d (car d) emptyp t) (setq emptyp nil))
15052 (if (and (>= d today)
15053 dopast
15054 past)
15055 (progn
15056 (setq past nil)
15057 (insert (make-string 79 ?-) "\n")))
15058 (setq date (calendar-gregorian-from-absolute d))
15059 (setq s (point))
15060 (setq rtn (and (not emptyp)
15061 (apply 'org-agenda-get-day-entries
15062 entry date args)))
15063 (if (or rtn (equal d today) org-timeline-show-empty-dates)
15064 (progn
15065 (insert (calendar-day-name date) " "
15066 (number-to-string (extract-calendar-day date)) " "
15067 (calendar-month-name (extract-calendar-month date)) " "
15068 (number-to-string (extract-calendar-year date)) "\n")
15069 ; FIXME: this gives a timezone problem
15070 ; (insert (format-time-string org-agenda-date-format
15071 ; (calendar-time-from-absolute d 0))
15072 ; "\n")
15073 (put-text-property s (1- (point)) 'face 'org-agenda-structure)
15074 (put-text-property s (1- (point)) 'org-date-line t)
15075 (if (equal d today)
15076 (put-text-property s (1- (point)) 'org-today t))
15077 (and rtn (insert (org-finalize-agenda-entries rtn) "\n"))
15078 (put-text-property s (1- (point)) 'day d)))))
15079 (goto-char (point-min))
15080 (goto-char (or (text-property-any (point-min) (point-max) 'org-today t)
15081 (point-min)))
15082 (add-text-properties (point-min) (point-max) '(org-agenda-type timeline))
15083 (org-finalize-agenda)
15084 (setq buffer-read-only t)))
15086 (defun org-get-all-dates (beg end &optional no-ranges force-today inactive empty)
15087 "Return a list of all relevant day numbers from BEG to END buffer positions.
15088 If NO-RANGES is non-nil, include only the start and end dates of a range,
15089 not every single day in the range. If FORCE-TODAY is non-nil, make
15090 sure that TODAY is included in the list. If INACTIVE is non-nil, also
15091 inactive time stamps (those in square brackets) are included.
15092 When EMPTY is non-nil, also include days without any entries."
15093 (let ((re (if inactive org-ts-regexp-both org-ts-regexp))
15094 dates dates1 date day day1 day2 ts1 ts2)
15095 (if force-today
15096 (setq dates (list (time-to-days (current-time)))))
15097 (save-excursion
15098 (goto-char beg)
15099 (while (re-search-forward re end t)
15100 (setq day (time-to-days (org-time-string-to-time
15101 (substring (match-string 1) 0 10))))
15102 (or (memq day dates) (push day dates)))
15103 (unless no-ranges
15104 (goto-char beg)
15105 (while (re-search-forward org-tr-regexp end t)
15106 (setq ts1 (substring (match-string 1) 0 10)
15107 ts2 (substring (match-string 2) 0 10)
15108 day1 (time-to-days (org-time-string-to-time ts1))
15109 day2 (time-to-days (org-time-string-to-time ts2)))
15110 (while (< (setq day1 (1+ day1)) day2)
15111 (or (memq day1 dates) (push day1 dates)))))
15112 (setq dates (sort dates '<))
15113 (when empty
15114 (while (setq day (pop dates))
15115 (setq day2 (car dates))
15116 (push day dates1)
15117 (when (and day2 empty)
15118 (if (or (eq empty t)
15119 (and (numberp empty) (<= (- day2 day) empty)))
15120 (while (< (setq day (1+ day)) day2)
15121 (push (list day) dates1))
15122 (push (cons :omitted (- day2 day)) dates1))))
15123 (setq dates (nreverse dates1)))
15124 dates)))
15126 ;;; Agenda Daily/Weekly
15128 (defvar org-agenda-overriding-arguments nil) ; dynamically scoped parameter
15129 (defvar org-agenda-last-arguments nil
15130 "The arguments of the previous call to org-agenda")
15131 (defvar org-starting-day nil) ; local variable in the agenda buffer
15132 (defvar org-include-all-loc nil) ; local variable
15135 ;;;###autoload
15136 (defun org-agenda-list (&optional include-all start-day ndays)
15137 "Produce a weekly view from all files in variable `org-agenda-files'.
15138 The view will be for the current week, but from the overview buffer you
15139 will be able to go to other weeks.
15140 With one \\[universal-argument] prefix argument INCLUDE-ALL, all unfinished TODO items will
15141 also be shown, under the current date.
15142 With two \\[universal-argument] prefix argument INCLUDE-ALL, all TODO entries marked DONE
15143 on the days are also shown. See the variable `org-log-done' for how
15144 to turn on logging.
15145 START-DAY defaults to TODAY, or to the most recent match for the weekday
15146 given in `org-agenda-start-on-weekday'.
15147 NDAYS defaults to `org-agenda-ndays'."
15148 (interactive "P")
15149 (if org-agenda-overriding-arguments
15150 (setq include-all (car org-agenda-overriding-arguments)
15151 start-day (nth 1 org-agenda-overriding-arguments)
15152 ndays (nth 2 org-agenda-overriding-arguments)))
15153 (setq org-agenda-last-arguments (list include-all start-day ndays))
15154 (org-compile-prefix-format 'agenda)
15155 (org-set-sorting-strategy 'agenda)
15156 (require 'calendar)
15157 (let* ((org-agenda-start-on-weekday
15158 (if (or (equal ndays 1)
15159 (and (null ndays) (equal 1 org-agenda-ndays)))
15160 nil org-agenda-start-on-weekday))
15161 (thefiles (org-agenda-files))
15162 (files thefiles)
15163 (today (time-to-days (current-time)))
15164 (sd (or start-day today))
15165 (start (if (or (null org-agenda-start-on-weekday)
15166 (< org-agenda-ndays 7))
15168 (let* ((nt (calendar-day-of-week
15169 (calendar-gregorian-from-absolute sd)))
15170 (n1 org-agenda-start-on-weekday)
15171 (d (- nt n1)))
15172 (- sd (+ (if (< d 0) 7 0) d)))))
15173 (day-numbers (list start))
15174 (inhibit-redisplay (not debug-on-error))
15175 s e rtn rtnall file date d start-pos end-pos todayp nd)
15176 (setq org-agenda-redo-command
15177 (list 'org-agenda-list (list 'quote include-all) start-day ndays))
15178 ;; Make the list of days
15179 (setq ndays (or ndays org-agenda-ndays)
15180 nd ndays)
15181 (while (> ndays 1)
15182 (push (1+ (car day-numbers)) day-numbers)
15183 (setq ndays (1- ndays)))
15184 (setq day-numbers (nreverse day-numbers))
15185 (org-prepare-agenda)
15186 (org-set-local 'org-starting-day (car day-numbers))
15187 (org-set-local 'org-include-all-loc include-all)
15188 (when (and (or include-all org-agenda-include-all-todo)
15189 (member today day-numbers))
15190 (setq files thefiles
15191 rtnall nil)
15192 (while (setq file (pop files))
15193 (catch 'nextfile
15194 (org-check-agenda-file file)
15195 (setq date (calendar-gregorian-from-absolute today)
15196 rtn (org-agenda-get-day-entries
15197 file date :todo))
15198 (setq rtnall (append rtnall rtn))))
15199 (when rtnall
15200 (insert "ALL CURRENTLY OPEN TODO ITEMS:\n")
15201 (add-text-properties (point-min) (1- (point))
15202 (list 'face 'org-agenda-structure))
15203 (insert (org-finalize-agenda-entries rtnall) "\n")))
15204 (setq s (point))
15205 (insert (if (= nd 7) "Week-" "Day-") "agenda:\n")
15206 (add-text-properties s (1- (point)) (list 'face 'org-agenda-structure
15207 'org-date-line t))
15208 (while (setq d (pop day-numbers))
15209 (setq date (calendar-gregorian-from-absolute d)
15210 s (point))
15211 (if (or (setq todayp (= d today))
15212 (and (not start-pos) (= d sd)))
15213 (setq start-pos (point))
15214 (if (and start-pos (not end-pos))
15215 (setq end-pos (point))))
15216 (setq files thefiles
15217 rtnall nil)
15218 (while (setq file (pop files))
15219 (catch 'nextfile
15220 (org-check-agenda-file file)
15221 (if org-agenda-show-log
15222 (setq rtn (org-agenda-get-day-entries
15223 file date
15224 :deadline :scheduled :timestamp :sexp :closed))
15225 (setq rtn (org-agenda-get-day-entries
15226 file date
15227 :deadline :scheduled :sexp :timestamp)))
15228 (setq rtnall (append rtnall rtn))))
15229 (if org-agenda-include-diary
15230 (progn
15231 (require 'diary-lib)
15232 (setq rtn (org-get-entries-from-diary date))
15233 (setq rtnall (append rtnall rtn))))
15234 (if (or rtnall org-agenda-show-all-dates)
15235 (progn
15236 (insert (format "%-9s %2d %s %4d\n"
15237 (calendar-day-name date)
15238 (extract-calendar-day date)
15239 (calendar-month-name (extract-calendar-month date))
15240 (extract-calendar-year date)))
15241 ; FIXME: this gives a timezone problem
15242 ; (insert (format-time-string org-agenda-date-format
15243 ; (calendar-time-from-absolute d 0)) "\n")
15244 (put-text-property s (1- (point)) 'face 'org-agenda-structure)
15245 (put-text-property s (1- (point)) 'org-date-line t)
15246 (if todayp (put-text-property s (1- (point)) 'org-today t))
15247 (if rtnall (insert
15248 (org-finalize-agenda-entries
15249 (org-agenda-add-time-grid-maybe
15250 rtnall nd todayp))
15251 "\n"))
15252 (put-text-property s (1- (point)) 'day d))))
15253 (goto-char (point-min))
15254 (org-fit-agenda-window)
15255 (unless (and (pos-visible-in-window-p (point-min))
15256 (pos-visible-in-window-p (point-max)))
15257 (goto-char (1- (point-max)))
15258 (recenter -1)
15259 (if (not (pos-visible-in-window-p (or start-pos 1)))
15260 (progn
15261 (goto-char (or start-pos 1))
15262 (recenter 1))))
15263 (goto-char (or start-pos 1))
15264 (add-text-properties (point-min) (point-max) '(org-agenda-type agenda))
15265 (org-finalize-agenda)
15266 (setq buffer-read-only t)
15267 (message "")))
15269 ;;; Agenda TODO list
15271 (defvar org-select-this-todo-keyword nil)
15272 (defvar org-last-arg nil)
15274 ;;;###autoload
15275 (defun org-todo-list (arg)
15276 "Show all TODO entries from all agenda file in a single list.
15277 The prefix arg can be used to select a specific TODO keyword and limit
15278 the list to these. When using \\[universal-argument], you will be prompted
15279 for a keyword. A numeric prefix directly selects the Nth keyword in
15280 `org-todo-keywords-1'."
15281 (interactive "P")
15282 (require 'calendar)
15283 (org-compile-prefix-format 'todo)
15284 (org-set-sorting-strategy 'todo)
15285 (org-prepare-agenda)
15286 (let* ((today (time-to-days (current-time)))
15287 (date (calendar-gregorian-from-absolute today))
15288 (kwds org-todo-keywords-for-agenda)
15289 (completion-ignore-case t)
15290 (org-select-this-todo-keyword
15291 (if (stringp arg) arg
15292 (and arg (integerp arg) (> arg 0)
15293 (nth (1- arg) kwds))))
15294 rtn rtnall files file pos)
15295 (when (equal arg '(4))
15296 (setq org-select-this-todo-keyword
15297 (completing-read "Keyword (or KWD1|K2D2|...): "
15298 (mapcar 'list kwds) nil nil)))
15299 (and (equal 0 arg) (setq org-select-this-todo-keyword nil))
15300 (org-set-local 'org-last-arg arg)
15301 ;FIXME (org-set-local 'org-todo-keywords-for-agenda kwds)
15302 (setq org-agenda-redo-command
15303 '(org-todo-list (or current-prefix-arg org-last-arg)))
15304 (setq files (org-agenda-files)
15305 rtnall nil)
15306 (while (setq file (pop files))
15307 (catch 'nextfile
15308 (org-check-agenda-file file)
15309 (setq rtn (org-agenda-get-day-entries file date :todo))
15310 (setq rtnall (append rtnall rtn))))
15311 (if org-agenda-overriding-header
15312 (insert (org-add-props (copy-sequence org-agenda-overriding-header)
15313 nil 'face 'org-agenda-structure) "\n")
15314 (insert "Global list of TODO items of type: ")
15315 (add-text-properties (point-min) (1- (point))
15316 (list 'face 'org-agenda-structure))
15317 (setq pos (point))
15318 (insert (or org-select-this-todo-keyword "ALL") "\n")
15319 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
15320 (setq pos (point))
15321 (unless org-agenda-multi
15322 (insert "Available with `N r': (0)ALL")
15323 (let ((n 0) s)
15324 (mapc (lambda (x)
15325 (setq s (format "(%d)%s" (setq n (1+ n)) x))
15326 (if (> (+ (current-column) (string-width s) 1) (frame-width))
15327 (insert "\n "))
15328 (insert " " s))
15329 kwds))
15330 (insert "\n"))
15331 (add-text-properties pos (1- (point)) (list 'face 'org-agenda-structure)))
15332 (when rtnall
15333 (insert (org-finalize-agenda-entries rtnall) "\n"))
15334 (goto-char (point-min))
15335 (org-fit-agenda-window)
15336 (add-text-properties (point-min) (point-max) '(org-agenda-type todo))
15337 (org-finalize-agenda)
15338 (setq buffer-read-only t)))
15340 ;;; Agenda tags match
15342 ;;;###autoload
15343 (defun org-tags-view (&optional todo-only match)
15344 "Show all headlines for all `org-agenda-files' matching a TAGS criterion.
15345 The prefix arg TODO-ONLY limits the search to TODO entries."
15346 (interactive "P")
15347 (org-compile-prefix-format 'tags)
15348 (org-set-sorting-strategy 'tags)
15349 (let* ((org-tags-match-list-sublevels
15350 (if todo-only t org-tags-match-list-sublevels))
15351 (completion-ignore-case t)
15352 rtn rtnall files file pos matcher
15353 buffer)
15354 (setq matcher (org-make-tags-matcher match)
15355 match (car matcher) matcher (cdr matcher))
15356 (org-prepare-agenda)
15357 (setq org-agenda-redo-command
15358 (list 'org-tags-view (list 'quote todo-only)
15359 (list 'if 'current-prefix-arg nil match)))
15360 (setq files (org-agenda-files)
15361 rtnall nil)
15362 (while (setq file (pop files))
15363 (catch 'nextfile
15364 (org-check-agenda-file file)
15365 (setq buffer (if (file-exists-p file)
15366 (org-get-agenda-file-buffer file)
15367 (error "No such file %s" file)))
15368 (if (not buffer)
15369 ;; If file does not exist, merror message to agenda
15370 (setq rtn (list
15371 (format "ORG-AGENDA-ERROR: No such org-file %s" file))
15372 rtnall (append rtnall rtn))
15373 (with-current-buffer buffer
15374 (unless (org-mode-p)
15375 (error "Agenda file %s is not in `org-mode'" file))
15376 (setq org-category-table (org-get-category-table))
15377 (save-excursion
15378 (save-restriction
15379 (if org-agenda-restrict
15380 (narrow-to-region org-agenda-restrict-begin
15381 org-agenda-restrict-end)
15382 (widen))
15383 (setq rtn (org-scan-tags 'agenda matcher todo-only))
15384 (setq rtnall (append rtnall rtn))))))))
15385 (if org-agenda-overriding-header
15386 (insert (org-add-props (copy-sequence org-agenda-overriding-header)
15387 nil 'face 'org-agenda-structure) "\n")
15388 (insert "Headlines with TAGS match: ")
15389 (add-text-properties (point-min) (1- (point))
15390 (list 'face 'org-agenda-structure))
15391 (setq pos (point))
15392 (insert match "\n")
15393 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
15394 (setq pos (point))
15395 (unless org-agenda-multi
15396 (insert "Press `C-u r' to search again with new search string\n"))
15397 (add-text-properties pos (1- (point)) (list 'face 'org-agenda-structure)))
15398 (when rtnall
15399 (insert (org-finalize-agenda-entries rtnall) "\n"))
15400 (goto-char (point-min))
15401 (org-fit-agenda-window)
15402 (add-text-properties (point-min) (point-max) '(org-agenda-type tags))
15403 (org-finalize-agenda)
15404 (setq buffer-read-only t)))
15406 ;;; Agenda Finding stuck projects
15408 (defvar org-agenda-skip-regexp nil
15409 "Regular expression used in skipping subtrees for the agenda.
15410 This is basically a temporary global variable that can be set and then
15411 used by user-defined selections using `org-agenda-skip-function'.")
15413 (defvar org-agenda-overriding-header nil
15414 "When this is set during todo and tags searches, will replace header.")
15416 (defun org-agenda-skip-subtree-when-regexp-matches ()
15417 "Checks if the current subtree contains match for `org-agenda-skip-regexp'.
15418 If yes, it returns the end position of this tree, causing agenda commands
15419 to skip this subtree. This is a function that can be put into
15420 `org-agenda-skip-function' for the duration of a command."
15421 (save-match-data
15422 (let ((end (save-excursion (org-end-of-subtree t)))
15423 skip)
15424 (save-excursion
15425 (setq skip (re-search-forward org-agenda-skip-regexp end t)))
15426 (and skip end))))
15428 (defun org-agenda-list-stuck-projects (&rest ignore)
15429 "Create agenda view for projects that are stuck.
15430 Stuck projects are project that have no next actions. For the definitions
15431 of what a project is and how to check if it stuck, customize the variable
15432 `org-stuck-projects'.
15433 MATCH is being ignored."
15434 (interactive)
15435 (let* ((org-agenda-skip-function 'org-agenda-skip-subtree-when-regexp-matches)
15436 (org-agenda-overriding-header "List of stuck projects: ")
15437 (matcher (nth 0 org-stuck-projects))
15438 (todo (nth 1 org-stuck-projects))
15439 (todo-wds (if (member "*" todo)
15440 (progn
15441 (org-prepare-agenda-buffers (org-agenda-files))
15442 (org-delete-all
15443 org-done-keywords-for-agenda
15444 (copy-sequence org-todo-keywords-for-agenda)))
15445 todo))
15446 (todo-re (concat "^\\*+[ \t]+\\("
15447 (mapconcat 'identity todo-wds "\\|")
15448 "\\)\\>"))
15449 (tags (nth 2 org-stuck-projects))
15450 (tags-re (if (member "*" tags)
15451 "^\\*+.*:[a-zA-Z0-9_@]+:[ \t]*$"
15452 (concat "^\\*+.*:\\("
15453 (mapconcat 'identity tags "\\|")
15454 "\\):[a-zA-Z0-9_@:]*[ \t]*$")))
15455 (gen-re (nth 3 org-stuck-projects))
15456 (re-list
15457 (delq nil
15458 (list
15459 (if todo todo-re)
15460 (if tags tags-re)
15461 (and gen-re (stringp gen-re) (string-match "\\S-" gen-re)
15462 gen-re)))))
15463 (setq org-agenda-skip-regexp
15464 (if re-list
15465 (mapconcat 'identity re-list "\\|")
15466 (error "No information how to identify unstuck projects")))
15467 (org-tags-view nil matcher)
15468 (with-current-buffer org-agenda-buffer-name
15469 (setq org-agenda-redo-command
15470 '(org-agenda-list-stuck-projects
15471 (or current-prefix-arg org-last-arg))))))
15473 ;;; Diary integration
15475 (defvar org-disable-agenda-to-diary nil) ;Dynamically-scoped param.
15477 (defun org-get-entries-from-diary (date)
15478 "Get the (Emacs Calendar) diary entries for DATE."
15479 (let* ((fancy-diary-buffer "*temporary-fancy-diary-buffer*")
15480 (diary-display-hook '(fancy-diary-display))
15481 (list-diary-entries-hook
15482 (cons 'org-diary-default-entry list-diary-entries-hook))
15483 (diary-file-name-prefix-function nil) ; turn this feature off
15484 (diary-modify-entry-list-string-function 'org-modify-diary-entry-string)
15485 entries
15486 (org-disable-agenda-to-diary t))
15487 (save-excursion
15488 (save-window-excursion
15489 (list-diary-entries date 1))) ;; Keep this name for now, compatibility
15490 (if (not (get-buffer fancy-diary-buffer))
15491 (setq entries nil)
15492 (with-current-buffer fancy-diary-buffer
15493 (setq buffer-read-only nil)
15494 (if (= (point-max) 1)
15495 ;; No entries
15496 (setq entries nil)
15497 ;; Omit the date and other unnecessary stuff
15498 (org-agenda-cleanup-fancy-diary)
15499 ;; Add prefix to each line and extend the text properties
15500 (if (= (point-max) 1)
15501 (setq entries nil)
15502 (setq entries (buffer-substring (point-min) (- (point-max) 1)))))
15503 (set-buffer-modified-p nil)
15504 (kill-buffer fancy-diary-buffer)))
15505 (when entries
15506 (setq entries (org-split-string entries "\n"))
15507 (setq entries
15508 (mapcar
15509 (lambda (x)
15510 (setq x (org-format-agenda-item "" x "Diary" nil 'time))
15511 ;; Extend the text properties to the beginning of the line
15512 (org-add-props x (text-properties-at (1- (length x)) x)
15513 'type "diary" 'date date))
15514 entries)))))
15516 (defun org-agenda-cleanup-fancy-diary ()
15517 "Remove unwanted stuff in buffer created by `fancy-diary-display'.
15518 This gets rid of the date, the underline under the date, and
15519 the dummy entry installed by `org-mode' to ensure non-empty diary for each
15520 date. It also removes lines that contain only whitespace."
15521 (goto-char (point-min))
15522 (if (looking-at ".*?:[ \t]*")
15523 (progn
15524 (replace-match "")
15525 (re-search-forward "\n=+$" nil t)
15526 (replace-match "")
15527 (while (re-search-backward "^ +\n?" nil t) (replace-match "")))
15528 (re-search-forward "\n=+$" nil t)
15529 (delete-region (point-min) (min (point-max) (1+ (match-end 0)))))
15530 (goto-char (point-min))
15531 (while (re-search-forward "^ +\n" nil t)
15532 (replace-match ""))
15533 (goto-char (point-min))
15534 (if (re-search-forward "^Org-mode dummy\n?" nil t)
15535 (replace-match "")))
15537 ;; Make sure entries from the diary have the right text properties.
15538 (eval-after-load "diary-lib"
15539 '(if (boundp 'diary-modify-entry-list-string-function)
15540 ;; We can rely on the hook, nothing to do
15542 ;; Hook not avaiable, must use advice to make this work
15543 (defadvice add-to-diary-list (before org-mark-diary-entry activate)
15544 "Make the position visible."
15545 (if (and org-disable-agenda-to-diary ;; called from org-agenda
15546 (stringp string)
15547 buffer-file-name)
15548 (setq string (org-modify-diary-entry-string string))))))
15550 (defun org-modify-diary-entry-string (string)
15551 "Add text properties to string, allowing org-mode to act on it."
15552 (org-add-props string nil
15553 'mouse-face 'highlight
15554 'keymap org-agenda-keymap
15555 'help-echo (format "mouse-2 or RET jump to diary file %s"
15556 (abbreviate-file-name buffer-file-name))
15557 'org-agenda-diary-link t
15558 'org-marker (org-agenda-new-marker (point-at-bol))))
15560 (defun org-diary-default-entry ()
15561 "Add a dummy entry to the diary.
15562 Needed to avoid empty dates which mess up holiday display."
15563 ;; Catch the error if dealing with the new add-to-diary-alist
15564 (when org-disable-agenda-to-diary
15565 (condition-case nil
15566 (add-to-diary-list original-date "Org-mode dummy" "")
15567 (error
15568 (add-to-diary-list original-date "Org-mode dummy" "" nil)))))
15570 ;;;###autoload
15571 (defun org-diary (&rest args)
15572 "Return diary information from org-files.
15573 This function can be used in a \"sexp\" diary entry in the Emacs calendar.
15574 It accesses org files and extracts information from those files to be
15575 listed in the diary. The function accepts arguments specifying what
15576 items should be listed. The following arguments are allowed:
15578 :timestamp List the headlines of items containing a date stamp or
15579 date range matching the selected date. Deadlines will
15580 also be listed, on the expiration day.
15582 :sexp FIXME
15584 :deadline List any deadlines past due, or due within
15585 `org-deadline-warning-days'. The listing occurs only
15586 in the diary for *today*, not at any other date. If
15587 an entry is marked DONE, it is no longer listed.
15589 :scheduled List all items which are scheduled for the given date.
15590 The diary for *today* also contains items which were
15591 scheduled earlier and are not yet marked DONE.
15593 :todo List all TODO items from the org-file. This may be a
15594 long list - so this is not turned on by default.
15595 Like deadlines, these entries only show up in the
15596 diary for *today*, not at any other date.
15598 The call in the diary file should look like this:
15600 &%%(org-diary) ~/path/to/some/orgfile.org
15602 Use a separate line for each org file to check. Or, if you omit the file name,
15603 all files listed in `org-agenda-files' will be checked automatically:
15605 &%%(org-diary)
15607 If you don't give any arguments (as in the example above), the default
15608 arguments (:deadline :scheduled :timestamp :sexp) are used.
15609 So the example above may also be written as
15611 &%%(org-diary :deadline :timestamp :sexp :scheduled)
15613 The function expects the lisp variables `entry' and `date' to be provided
15614 by the caller, because this is how the calendar works. Don't use this
15615 function from a program - use `org-agenda-get-day-entries' instead."
15616 (org-agenda-maybe-reset-markers)
15617 (org-compile-prefix-format 'agenda)
15618 (org-set-sorting-strategy 'agenda)
15619 (setq args (or args '(:deadline :scheduled :timestamp :sexp)))
15620 (let* ((files (if (and entry (stringp entry) (string-match "\\S-" entry))
15621 (list entry)
15622 (org-agenda-files t)))
15623 file rtn results)
15624 (org-prepare-agenda-buffers files)
15625 ;; If this is called during org-agenda, don't return any entries to
15626 ;; the calendar. Org Agenda will list these entries itself.
15627 (if org-disable-agenda-to-diary (setq files nil))
15628 (while (setq file (pop files))
15629 (setq rtn (apply 'org-agenda-get-day-entries file date args))
15630 (setq results (append results rtn)))
15631 (if results
15632 (concat (org-finalize-agenda-entries results) "\n"))))
15634 ;;; Agenda entry finders
15636 (defun org-agenda-get-day-entries (file date &rest args)
15637 "Does the work for `org-diary' and `org-agenda'.
15638 FILE is the path to a file to be checked for entries. DATE is date like
15639 the one returned by `calendar-current-date'. ARGS are symbols indicating
15640 which kind of entries should be extracted. For details about these, see
15641 the documentation of `org-diary'."
15642 (setq args (or args '(:deadline :scheduled :timestamp :sexp)))
15643 (let* ((org-startup-folded nil)
15644 (org-startup-align-all-tables nil)
15645 (buffer (if (file-exists-p file)
15646 (org-get-agenda-file-buffer file)
15647 (error "No such file %s" file)))
15648 arg results rtn)
15649 (if (not buffer)
15650 ;; If file does not exist, make sure an error message ends up in diary
15651 (list (format "ORG-AGENDA-ERROR: No such org-file %s" file))
15652 (with-current-buffer buffer
15653 (unless (org-mode-p)
15654 (error "Agenda file %s is not in `org-mode'" file))
15655 (setq org-category-table (org-get-category-table))
15656 (let ((case-fold-search nil))
15657 (save-excursion
15658 (save-restriction
15659 (if org-agenda-restrict
15660 (narrow-to-region org-agenda-restrict-begin
15661 org-agenda-restrict-end)
15662 (widen))
15663 ;; The way we repeatedly append to `results' makes it O(n^2) :-(
15664 (while (setq arg (pop args))
15665 (cond
15666 ((and (eq arg :todo)
15667 (equal date (calendar-current-date)))
15668 (setq rtn (org-agenda-get-todos))
15669 (setq results (append results rtn)))
15670 ((eq arg :timestamp)
15671 (setq rtn (org-agenda-get-blocks))
15672 (setq results (append results rtn))
15673 (setq rtn (org-agenda-get-timestamps))
15674 (setq results (append results rtn)))
15675 ((eq arg :sexp)
15676 (setq rtn (org-agenda-get-sexps))
15677 (setq results (append results rtn)))
15678 ((eq arg :scheduled)
15679 (setq rtn (org-agenda-get-scheduled))
15680 (setq results (append results rtn)))
15681 ((eq arg :closed)
15682 (setq rtn (org-agenda-get-closed))
15683 (setq results (append results rtn)))
15684 ((and (eq arg :deadline)
15685 (equal date (calendar-current-date)))
15686 (setq rtn (org-agenda-get-deadlines))
15687 (setq results (append results rtn))))))))
15688 results))))
15690 (defun org-entry-is-done-p ()
15691 "Is the current entry marked DONE?"
15692 (save-excursion
15693 (and (re-search-backward "[\r\n]\\*" nil t)
15694 (looking-at org-nl-done-regexp))))
15696 (defun org-at-date-range-p (&optional inactive-ok)
15697 "Is the cursor inside a date range?"
15698 (interactive)
15699 (save-excursion
15700 (catch 'exit
15701 (let ((pos (point)))
15702 (skip-chars-backward "^[<\r\n")
15703 (skip-chars-backward "<[")
15704 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
15705 (>= (match-end 0) pos)
15706 (throw 'exit t))
15707 (skip-chars-backward "^<[\r\n")
15708 (skip-chars-backward "<[")
15709 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
15710 (>= (match-end 0) pos)
15711 (throw 'exit t)))
15712 nil)))
15714 (defun org-agenda-get-todos ()
15715 "Return the TODO information for agenda display."
15716 (let* ((props (list 'face nil
15717 'done-face 'org-done
15718 'org-not-done-regexp org-not-done-regexp
15719 'org-todo-regexp org-todo-regexp
15720 'mouse-face 'highlight
15721 'keymap org-agenda-keymap
15722 'help-echo
15723 (format "mouse-2 or RET jump to org file %s"
15724 (abbreviate-file-name buffer-file-name))))
15725 ;; FIXME: get rid of the \n at some point but watch out
15726 (regexp (concat "[\n\r]\\*+ *\\("
15727 (if org-select-this-todo-keyword
15728 (if (equal org-select-this-todo-keyword "*")
15729 org-todo-regexp
15730 (concat "\\<\\("
15731 (mapconcat 'identity (org-split-string org-select-this-todo-keyword "|") "\\|")
15732 "\\)\\>"))
15733 org-not-done-regexp)
15734 "[^\n\r]*\\)"))
15735 marker priority category tags
15736 ee txt beg end)
15737 (goto-char (point-min))
15738 (while (re-search-forward regexp nil t)
15739 (catch :skip
15740 (save-match-data
15741 (beginning-of-line)
15742 (setq beg (point) end (progn (outline-next-heading) (point)))
15743 (when (or (and org-agenda-todo-ignore-scheduled (goto-char beg)
15744 (re-search-forward org-scheduled-time-regexp end t))
15745 (and org-agenda-todo-ignore-deadlines (goto-char beg)
15746 (re-search-forward org-deadline-time-regexp end t)
15747 (org-deadline-close (match-string 1))))
15748 (goto-char beg)
15749 (or org-agenda-todo-list-sublevels (org-end-of-subtree 'invisible))
15750 (throw :skip nil)))
15751 (goto-char beg)
15752 (org-agenda-skip)
15753 (goto-char (match-beginning 1))
15754 (setq marker (org-agenda-new-marker (1+ (match-beginning 0)))
15755 category (org-get-category)
15756 tags (org-get-tags-at (point))
15757 txt (org-format-agenda-item "" (match-string 1) category tags)
15758 priority (1+ (org-get-priority txt)))
15759 (org-add-props txt props
15760 'org-marker marker 'org-hd-marker marker
15761 'priority priority 'org-category category
15762 'type "todo")
15763 (push txt ee)
15764 (if org-agenda-todo-list-sublevels
15765 (goto-char (match-end 1))
15766 (org-end-of-subtree 'invisible))))
15767 (nreverse ee)))
15769 (defconst org-agenda-no-heading-message
15770 "No heading for this item in buffer or region.")
15772 (defun org-agenda-get-timestamps ()
15773 "Return the date stamp information for agenda display."
15774 (let* ((props (list 'face nil
15775 'org-not-done-regexp org-not-done-regexp
15776 'org-todo-regexp org-todo-regexp
15777 'mouse-face 'highlight
15778 'keymap org-agenda-keymap
15779 'help-echo
15780 (format "mouse-2 or RET jump to org file %s"
15781 (abbreviate-file-name buffer-file-name))))
15782 ;???? (regexp (regexp-quote
15783 ; (substring
15784 ; (format-time-string
15785 ; (car org-time-stamp-formats)
15786 ; (apply 'encode-time ; DATE bound by calendar
15787 ; (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
15788 ; 0 11)))
15789 (d1 (calendar-absolute-from-gregorian date))
15790 (regexp
15791 (concat
15792 (regexp-quote
15793 (substring
15794 (format-time-string
15795 (car org-time-stamp-formats)
15796 (apply 'encode-time ; DATE bound by calendar
15797 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
15798 0 11))
15799 "\\|\\(<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[dwmy]>\\)"
15800 "\\|\\(<%%\\(([^>\n]+)\\)>\\)"))
15801 marker hdmarker deadlinep scheduledp donep tmp priority category
15802 ee txt timestr tags b0 b3 e3)
15803 (goto-char (point-min))
15804 (while (re-search-forward regexp nil t)
15805 (setq b0 (match-beginning 0)
15806 b3 (match-beginning 3) e3 (match-end 3))
15807 (catch :skip
15808 (and (org-at-date-range-p) (throw :skip nil))
15809 (org-agenda-skip)
15810 (if (and (match-end 1)
15811 (not (= d1 (org-time-string-to-absolute (match-string 1) d1))))
15812 (throw :skip nil))
15813 (if (and e3
15814 (not (org-diary-sexp-entry (buffer-substring b3 e3) "" date)))
15815 (throw :skip nil))
15816 (setq marker (org-agenda-new-marker b0)
15817 category (org-get-category b0)
15818 tmp (buffer-substring (max (point-min)
15819 (- b0 org-ds-keyword-length))
15821 timestr (if b3 "" (buffer-substring b0 (point-at-eol)))
15822 deadlinep (string-match org-deadline-regexp tmp)
15823 scheduledp (string-match org-scheduled-regexp tmp)
15824 donep (org-entry-is-done-p))
15825 (and org-agenda-skip-scheduled-if-done
15826 scheduledp donep
15827 (throw :skip t))
15828 (and org-agenda-skip-deadline-if-done
15829 deadlinep donep
15830 (throw :skip t))
15831 (if (string-match ">" timestr)
15832 ;; substring should only run to end of time stamp
15833 (setq timestr (substring timestr 0 (match-end 0))))
15834 (save-excursion
15835 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
15836 (progn
15837 (goto-char (match-end 1))
15838 (setq hdmarker (org-agenda-new-marker)
15839 tags (org-get-tags-at))
15840 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
15841 (setq txt (org-format-agenda-item
15842 (format "%s%s"
15843 (if deadlinep "Deadline: " "")
15844 (if scheduledp "Scheduled: " ""))
15845 (match-string 1) category tags timestr)))
15846 (setq txt org-agenda-no-heading-message))
15847 (setq priority (org-get-priority txt))
15848 (org-add-props txt props
15849 'org-marker marker 'org-hd-marker hdmarker)
15850 (if deadlinep
15851 (org-add-props txt nil
15852 'face (if donep 'org-done 'org-warning)
15853 'type "deadline" 'date date
15854 'undone-face 'org-warning 'done-face 'org-done
15855 'org-category category 'priority (+ 100 priority))
15856 (if scheduledp
15857 (org-add-props txt nil
15858 'face 'org-scheduled-today
15859 'type "scheduled" 'date date
15860 'undone-face 'org-scheduled-today 'done-face 'org-done
15861 'org-category category 'priority (+ 99 priority))
15862 (org-add-props txt nil 'priority priority
15863 'org-category category 'date date
15864 'type "timestamp")))
15865 (push txt ee))
15866 (outline-next-heading)))
15867 (nreverse ee)))
15869 (defun org-agenda-get-sexps ()
15870 "Return the sexp information for agenda display."
15871 (require 'diary-lib)
15872 (let* ((props (list 'face nil
15873 'mouse-face 'highlight
15874 'keymap org-agenda-keymap
15875 'help-echo
15876 (format "mouse-2 or RET jump to org file %s"
15877 (abbreviate-file-name buffer-file-name))))
15878 (regexp "^&?%%(")
15879 marker category ee txt tags entry result beg b sexp sexp-entry)
15880 (goto-char (point-min))
15881 (while (re-search-forward regexp nil t)
15882 (catch :skip
15883 (org-agenda-skip)
15884 (setq beg (match-beginning 0))
15885 (goto-char (1- (match-end 0)))
15886 (setq b (point))
15887 (forward-sexp 1)
15888 (setq sexp (buffer-substring b (point)))
15889 (setq sexp-entry (if (looking-at "[ \t]*\\(\\S-.*\\)")
15890 (org-trim (match-string 1))
15891 ""))
15892 (setq result (org-diary-sexp-entry sexp sexp-entry date))
15893 (when result
15894 (setq marker (org-agenda-new-marker beg)
15895 category (org-get-category beg))
15897 (if (string-match "\\S-" result)
15898 (setq txt result)
15899 (setq txt "SEXP entry returned empty string"))
15901 (setq txt (org-format-agenda-item
15902 "" txt category tags 'time))
15903 (org-add-props txt props 'org-marker marker)
15904 (org-add-props txt nil
15905 'org-category category 'date date
15906 'type "sexp")
15907 (push txt ee))))
15908 (nreverse ee)))
15910 (defun org-agenda-get-closed ()
15911 "Return the logged TODO entries for agenda display."
15912 (let* ((props (list 'mouse-face 'highlight
15913 'org-not-done-regexp org-not-done-regexp
15914 'org-todo-regexp org-todo-regexp
15915 'keymap org-agenda-keymap
15916 'help-echo
15917 (format "mouse-2 or RET jump to org file %s"
15918 (abbreviate-file-name buffer-file-name))))
15919 (regexp (concat
15920 "\\<\\(" org-closed-string "\\|" org-clock-string "\\) *\\["
15921 (regexp-quote
15922 (substring
15923 (format-time-string
15924 (car org-time-stamp-formats)
15925 (apply 'encode-time ; DATE bound by calendar
15926 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
15927 1 11))))
15928 marker hdmarker priority category tags closedp
15929 ee txt timestr)
15930 (goto-char (point-min))
15931 (while (re-search-forward regexp nil t)
15932 (catch :skip
15933 (org-agenda-skip)
15934 (setq marker (org-agenda-new-marker (match-beginning 0))
15935 closedp (equal (match-string 1) org-closed-string)
15936 category (org-get-category (match-beginning 0))
15937 timestr (buffer-substring (match-beginning 0) (point-at-eol))
15938 ;; donep (org-entry-is-done-p)
15940 (if (string-match "\\]" timestr)
15941 ;; substring should only run to end of time stamp
15942 (setq timestr (substring timestr 0 (match-end 0))))
15943 (save-excursion
15944 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
15945 (progn
15946 (goto-char (match-end 1))
15947 (setq hdmarker (org-agenda-new-marker)
15948 tags (org-get-tags-at))
15949 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
15950 (setq txt (org-format-agenda-item
15951 (if closedp "Closed: " "Clocked: ")
15952 (match-string 1) category tags timestr)))
15953 (setq txt org-agenda-no-heading-message))
15954 (setq priority 100000)
15955 (org-add-props txt props
15956 'org-marker marker 'org-hd-marker hdmarker 'face 'org-done
15957 'priority priority 'org-category category
15958 'type "closed" 'date date
15959 'undone-face 'org-warning 'done-face 'org-done)
15960 (push txt ee))
15961 (outline-next-heading)))
15962 (nreverse ee)))
15964 (defun org-agenda-get-deadlines ()
15965 "Return the deadline information for agenda display."
15966 (let* ((wdays org-deadline-warning-days)
15967 (props (list 'mouse-face 'highlight
15968 'org-not-done-regexp org-not-done-regexp
15969 'org-todo-regexp org-todo-regexp
15970 'keymap org-agenda-keymap
15971 'help-echo
15972 (format "mouse-2 or RET jump to org file %s"
15973 (abbreviate-file-name buffer-file-name))))
15974 (regexp org-deadline-time-regexp)
15975 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
15976 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
15977 d2 diff pos pos1 category tags
15978 ee txt head face)
15979 (goto-char (point-min))
15980 (while (re-search-forward regexp nil t)
15981 (catch :skip
15982 (org-agenda-skip)
15983 (setq pos (1- (match-beginning 1))
15984 ;??? d2 (time-to-days
15985 ;??? (org-time-string-to-time (match-string 1)))
15986 d2 (org-time-string-to-absolute (match-string 1) d1)
15987 diff (- d2 d1))
15988 ;; When to show a deadline in the calendar:
15989 ;; If the expiration is within wdays warning time.
15990 ;; Past-due deadlines are only shown on the current date
15991 (if (and (< diff wdays) todayp (not (= diff 0)))
15992 (save-excursion
15993 (setq category (org-get-category))
15994 (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t)
15995 (progn
15996 (goto-char (match-end 0))
15997 (setq pos1 (match-end 1))
15998 (setq tags (org-get-tags-at pos1))
15999 (setq head (buffer-substring-no-properties
16000 (point)
16001 (progn (skip-chars-forward "^\r\n")
16002 (point))))
16003 (if (string-match org-looking-at-done-regexp head)
16004 (setq txt nil)
16005 (setq txt (org-format-agenda-item
16006 (format "In %3d d.: " diff) head category tags))))
16007 (setq txt org-agenda-no-heading-message))
16008 (when txt
16009 (setq face (cond ((<= diff 0) 'org-warning)
16010 ((<= diff 5) 'org-upcoming-deadline)
16011 (t nil)))
16012 (org-add-props txt props
16013 'org-marker (org-agenda-new-marker pos)
16014 'org-hd-marker (org-agenda-new-marker pos1)
16015 'priority (+ (- 10 diff) (org-get-priority txt))
16016 'org-category category
16017 'type "upcoming-deadline" 'date d2
16018 'face face 'undone-face face 'done-face 'org-done)
16019 (push txt ee))))))
16020 ee))
16022 (defun org-agenda-get-scheduled ()
16023 "Return the scheduled information for agenda display."
16024 (let* ((props (list 'face 'org-scheduled-previously
16025 'org-not-done-regexp org-not-done-regexp
16026 'org-todo-regexp org-todo-regexp
16027 'undone-face 'org-scheduled-previously
16028 'done-face 'org-done
16029 'mouse-face 'highlight
16030 'keymap org-agenda-keymap
16031 'help-echo
16032 (format "mouse-2 or RET jump to org file %s"
16033 (abbreviate-file-name buffer-file-name))))
16034 (regexp org-scheduled-time-regexp)
16035 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
16036 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
16037 d2 diff pos pos1 category tags
16038 ee txt head)
16039 (goto-char (point-min))
16040 (while (re-search-forward regexp nil t)
16041 (catch :skip
16042 (org-agenda-skip)
16043 (setq pos (1- (match-beginning 1))
16044 d2 (org-time-string-to-absolute (match-string 1) d1)
16045 ;??? d2 (time-to-days
16046 ;??? (org-time-string-to-time (match-string 1)))
16047 diff (- d2 d1))
16048 ;; When to show a scheduled item in the calendar:
16049 ;; If it is on or past the date.
16050 (if (and (< diff 0) todayp)
16051 (save-excursion
16052 (setq category (org-get-category))
16053 (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t)
16054 (progn
16055 (goto-char (match-end 0))
16056 (setq pos1 (match-end 1))
16057 (setq tags (org-get-tags-at))
16058 (setq head (buffer-substring-no-properties
16059 (point)
16060 (progn (skip-chars-forward "^\r\n") (point))))
16061 (if (string-match org-looking-at-done-regexp head)
16062 (setq txt nil)
16063 (setq txt (org-format-agenda-item
16064 (format "Sched.%2dx: " (- 1 diff)) head
16065 category tags))))
16066 (setq txt org-agenda-no-heading-message))
16067 (when txt
16068 (org-add-props txt props
16069 'org-marker (org-agenda-new-marker pos)
16070 'org-hd-marker (org-agenda-new-marker pos1)
16071 'type "past-scheduled" 'date d2
16072 'priority (+ (- 5 diff) (org-get-priority txt))
16073 'org-category category)
16074 (push txt ee))))))
16075 ee))
16077 (defun org-agenda-get-blocks ()
16078 "Return the date-range information for agenda display."
16079 (let* ((props (list 'face nil
16080 'org-not-done-regexp org-not-done-regexp
16081 'org-todo-regexp org-todo-regexp
16082 'mouse-face 'highlight
16083 'keymap org-agenda-keymap
16084 'help-echo
16085 (format "mouse-2 or RET jump to org file %s"
16086 (abbreviate-file-name buffer-file-name))))
16087 (regexp org-tr-regexp)
16088 (d0 (calendar-absolute-from-gregorian date))
16089 marker hdmarker ee txt d1 d2 s1 s2 timestr category tags pos)
16090 (goto-char (point-min))
16091 (while (re-search-forward regexp nil t)
16092 (catch :skip
16093 (org-agenda-skip)
16094 (setq pos (point))
16095 (setq timestr (match-string 0)
16096 s1 (match-string 1)
16097 s2 (match-string 2)
16098 d1 (time-to-days (org-time-string-to-time s1))
16099 d2 (time-to-days (org-time-string-to-time s2)))
16100 (if (and (> (- d0 d1) -1) (> (- d2 d0) -1))
16101 ;; Only allow days between the limits, because the normal
16102 ;; date stamps will catch the limits.
16103 (save-excursion
16104 (setq marker (org-agenda-new-marker (point)))
16105 (setq category (org-get-category))
16106 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
16107 (progn
16108 (setq hdmarker (org-agenda-new-marker (match-end 1)))
16109 (goto-char (match-end 1))
16110 (setq tags (org-get-tags-at))
16111 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
16112 (setq txt (org-format-agenda-item
16113 (format (if (= d1 d2) "" "(%d/%d): ")
16114 (1+ (- d0 d1)) (1+ (- d2 d1)))
16115 (match-string 1) category tags
16116 (if (= d0 d1) timestr))))
16117 (setq txt org-agenda-no-heading-message))
16118 (org-add-props txt props
16119 'org-marker marker 'org-hd-marker hdmarker
16120 'type "block" 'date date
16121 'priority (org-get-priority txt) 'org-category category)
16122 (push txt ee)))
16123 (goto-char pos)))
16124 ;; Sort the entries by expiration date.
16125 (nreverse ee)))
16127 ;;; Agenda presentation and sorting
16129 ;; FIXME: should I allow spaces around the dash?
16130 (defconst org-plain-time-of-day-regexp
16131 (concat
16132 "\\(\\<[012]?[0-9]"
16133 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
16134 "\\(--?"
16135 "\\(\\<[012]?[0-9]"
16136 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
16137 "\\)?")
16138 "Regular expression to match a plain time or time range.
16139 Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
16140 groups carry important information:
16141 0 the full match
16142 1 the first time, range or not
16143 8 the second time, if it is a range.")
16145 (defconst org-stamp-time-of-day-regexp
16146 (concat
16147 "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +\\sw+ +\\)"
16148 "\\([012][0-9]:[0-5][0-9]\\)>"
16149 "\\(--?"
16150 "<\\1\\([012][0-9]:[0-5][0-9]\\)>\\)?")
16151 "Regular expression to match a timestamp time or time range.
16152 After a match, the following groups carry important information:
16153 0 the full match
16154 1 date plus weekday, for backreferencing to make sure both times on same day
16155 2 the first time, range or not
16156 4 the second time, if it is a range.")
16158 (defvar org-prefix-has-time nil
16159 "A flag, set by `org-compile-prefix-format'.
16160 The flag is set if the currently compiled format contains a `%t'.")
16161 (defvar org-prefix-has-tag nil
16162 "A flag, set by `org-compile-prefix-format'.
16163 The flag is set if the currently compiled format contains a `%T'.")
16165 (defun org-format-agenda-item (extra txt &optional category tags dotime
16166 noprefix)
16167 "Format TXT to be inserted into the agenda buffer.
16168 In particular, it adds the prefix and corresponding text properties. EXTRA
16169 must be a string and replaces the `%s' specifier in the prefix format.
16170 CATEGORY (string, symbol or nil) may be used to overrule the default
16171 category taken from local variable or file name. It will replace the `%c'
16172 specifier in the format. DOTIME, when non-nil, indicates that a
16173 time-of-day should be extracted from TXT for sorting of this entry, and for
16174 the `%t' specifier in the format. When DOTIME is a string, this string is
16175 searched for a time before TXT is. NOPREFIX is a flag and indicates that
16176 only the correctly processes TXT should be returned - this is used by
16177 `org-agenda-change-all-lines'. TAGS can be the tags of the headline."
16178 (save-match-data
16179 ;; Diary entries sometimes have extra whitespace at the beginning
16180 (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt)))
16181 (let* ((category (or category
16182 org-category
16183 (if buffer-file-name
16184 (file-name-sans-extension
16185 (file-name-nondirectory buffer-file-name))
16186 "")))
16187 (tag (if tags (nth (1- (length tags)) tags) ""))
16188 time ; time and tag are needed for the eval of the prefix format
16189 (ts (if dotime (concat (if (stringp dotime) dotime "") txt)))
16190 (time-of-day (and dotime (org-get-time-of-day ts)))
16191 stamp plain s0 s1 s2 rtn)
16192 (when (and dotime time-of-day org-prefix-has-time)
16193 ;; Extract starting and ending time and move them to prefix
16194 (when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts))
16195 (setq plain (string-match org-plain-time-of-day-regexp ts)))
16196 (setq s0 (match-string 0 ts)
16197 s1 (match-string (if plain 1 2) ts)
16198 s2 (match-string (if plain 8 4) ts))
16200 ;; If the times are in TXT (not in DOTIMES), and the prefix will list
16201 ;; them, we might want to remove them there to avoid duplication.
16202 ;; The user can turn this off with a variable.
16203 (if (and org-agenda-remove-times-when-in-prefix (or stamp plain)
16204 (string-match (concat (regexp-quote s0) " *") txt)
16205 (if (eq org-agenda-remove-times-when-in-prefix 'beg)
16206 (= (match-beginning 0) 0)
16208 (setq txt (replace-match "" nil nil txt))))
16209 ;; Normalize the time(s) to 24 hour
16210 (if s1 (setq s1 (org-get-time-of-day s1 'string t)))
16211 (if s2 (setq s2 (org-get-time-of-day s2 'string t))))
16213 (when (string-match "\\([ \t]+\\)\\(:[a-zA-Z_@0-9:]+:\\)[ \t]*$" txt)
16214 ;; Tags are in the string
16215 (if (or (eq org-agenda-remove-tags t)
16216 (and org-agenda-remove-tags
16217 org-prefix-has-tag))
16218 (setq txt (replace-match "" t t txt))
16219 (setq txt (replace-match
16220 (concat (make-string (max (- 50 (length txt)) 1) ?\ )
16221 (match-string 2 txt))
16222 t t txt))))
16224 ;; Create the final string
16225 (if noprefix
16226 (setq rtn txt)
16227 ;; Prepare the variables needed in the eval of the compiled format
16228 (setq time (cond (s2 (concat s1 "-" s2))
16229 (s1 (concat s1 "......"))
16230 (t ""))
16231 extra (or extra "")
16232 category (if (symbolp category) (symbol-name category) category))
16233 ;; Evaluate the compiled format
16234 (setq rtn (concat (eval org-prefix-format-compiled) txt)))
16236 ;; And finally add the text properties
16237 (org-add-props rtn nil
16238 'org-category (downcase category) 'tags tags
16239 'prefix-length (- (length rtn) (length txt))
16240 'time-of-day time-of-day
16241 'txt txt
16242 'time time
16243 'extra extra
16244 'dotime dotime))))
16246 (defvar org-agenda-sorting-strategy) ;; FIXME: can be removed?
16247 (defvar org-agenda-sorting-strategy-selected nil)
16249 (defun org-agenda-add-time-grid-maybe (list ndays todayp)
16250 (catch 'exit
16251 (cond ((not org-agenda-use-time-grid) (throw 'exit list))
16252 ((and todayp (member 'today (car org-agenda-time-grid))))
16253 ((and (= ndays 1) (member 'daily (car org-agenda-time-grid))))
16254 ((member 'weekly (car org-agenda-time-grid)))
16255 (t (throw 'exit list)))
16256 (let* ((have (delq nil (mapcar
16257 (lambda (x) (get-text-property 1 'time-of-day x))
16258 list)))
16259 (string (nth 1 org-agenda-time-grid))
16260 (gridtimes (nth 2 org-agenda-time-grid))
16261 (req (car org-agenda-time-grid))
16262 (remove (member 'remove-match req))
16263 new time)
16264 (if (and (member 'require-timed req) (not have))
16265 ;; don't show empty grid
16266 (throw 'exit list))
16267 (while (setq time (pop gridtimes))
16268 (unless (and remove (member time have))
16269 (setq time (int-to-string time))
16270 (push (org-format-agenda-item
16271 nil string "" nil
16272 (concat (substring time 0 -2) ":" (substring time -2)))
16273 new)
16274 (put-text-property
16275 1 (length (car new)) 'face 'org-time-grid (car new))))
16276 (if (member 'time-up org-agenda-sorting-strategy-selected)
16277 (append new list)
16278 (append list new)))))
16280 (defun org-compile-prefix-format (key)
16281 "Compile the prefix format into a Lisp form that can be evaluated.
16282 The resulting form is returned and stored in the variable
16283 `org-prefix-format-compiled'."
16284 (setq org-prefix-has-time nil org-prefix-has-tag nil)
16285 (let ((s (cond
16286 ((stringp org-agenda-prefix-format)
16287 org-agenda-prefix-format)
16288 ((assq key org-agenda-prefix-format)
16289 (cdr (assq key org-agenda-prefix-format)))
16290 (t " %-12:c%?-12t% s")))
16291 (start 0)
16292 varform vars var e c f opt)
16293 (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([cts]\\)"
16294 s start)
16295 (setq var (cdr (assoc (match-string 4 s)
16296 '(("c" . category) ("t" . time) ("s" . extra)
16297 ("T" . tag))))
16298 c (or (match-string 3 s) "")
16299 opt (match-beginning 1)
16300 start (1+ (match-beginning 0)))
16301 (if (equal var 'time) (setq org-prefix-has-time t))
16302 (if (equal var 'tag) (setq org-prefix-has-tag t))
16303 (setq f (concat "%" (match-string 2 s) "s"))
16304 (if opt
16305 (setq varform
16306 `(if (equal "" ,var)
16308 (format ,f (if (equal "" ,var) "" (concat ,var ,c)))))
16309 (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c)))))
16310 (setq s (replace-match "%s" t nil s))
16311 (push varform vars))
16312 (setq vars (nreverse vars))
16313 (setq org-prefix-format-compiled `(format ,s ,@vars))))
16315 (defun org-set-sorting-strategy (key)
16316 (if (symbolp (car org-agenda-sorting-strategy))
16317 ;; the old format
16318 (setq org-agenda-sorting-strategy-selected org-agenda-sorting-strategy)
16319 (setq org-agenda-sorting-strategy-selected
16320 (or (cdr (assq key org-agenda-sorting-strategy))
16321 (cdr (assq 'agenda org-agenda-sorting-strategy))
16322 '(time-up category-keep priority-down)))))
16324 (defun org-get-time-of-day (s &optional string mod24)
16325 "Check string S for a time of day.
16326 If found, return it as a military time number between 0 and 2400.
16327 If not found, return nil.
16328 The optional STRING argument forces conversion into a 5 character wide string
16329 HH:MM."
16330 (save-match-data
16331 (when
16333 (string-match
16334 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)\\([AaPp][Mm]\\)?\\> *" s)
16335 (string-match
16336 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\([AaPp][Mm]\\)\\> *" s))
16337 (let* ((h (string-to-number (match-string 1 s)))
16338 (m (if (match-end 3) (string-to-number (match-string 3 s)) 0))
16339 (ampm (if (match-end 4) (downcase (match-string 4 s))))
16340 (am-p (equal ampm "am"))
16341 (h1 (cond ((not ampm) h)
16342 ((= h 12) (if am-p 0 12))
16343 (t (+ h (if am-p 0 12)))))
16344 (h2 (if (and string mod24 (not (and (= m 0) (= h1 24))))
16345 (mod h1 24) h1))
16346 (t0 (+ (* 100 h2) m))
16347 (t1 (concat (if (>= h1 24) "+" " ")
16348 (if (< t0 100) "0" "")
16349 (if (< t0 10) "0" "")
16350 (int-to-string t0))))
16351 (if string (concat (substring t1 -4 -2) ":" (substring t1 -2)) t0)))))
16353 (defun org-finalize-agenda-entries (list &optional nosort)
16354 "Sort and concatenate the agenda items."
16355 (setq list (mapcar 'org-agenda-highlight-todo list))
16356 (if nosort
16357 list
16358 (mapconcat 'identity (sort list 'org-entries-lessp) "\n")))
16360 (defun org-agenda-highlight-todo (x)
16361 (let (re pl)
16362 (if (eq x 'line)
16363 (save-excursion
16364 (beginning-of-line 1)
16365 (setq re (get-text-property (point) 'org-not-done-regexp))
16366 (goto-char (+ (point) (or (get-text-property (point) 'prefix-length) 0)))
16367 (and (looking-at (concat "[ \t]*\\.*" re))
16368 (add-text-properties (match-beginning 0) (match-end 0)
16369 '(face org-todo))))
16370 (setq re (concat (get-text-property 0 'org-not-done-regexp x))
16371 pl (get-text-property 0 'prefix-length x))
16372 (and re (equal (string-match (concat "\\(\\.*\\)" re) x (or pl 0)) pl)
16373 (add-text-properties (or (match-end 1) (match-end 0)) (match-end 0)
16374 '(face org-todo) x))
16375 x)))
16377 (defsubst org-cmp-priority (a b)
16378 "Compare the priorities of string A and B."
16379 (let ((pa (or (get-text-property 1 'priority a) 0))
16380 (pb (or (get-text-property 1 'priority b) 0)))
16381 (cond ((> pa pb) +1)
16382 ((< pa pb) -1)
16383 (t nil))))
16385 (defsubst org-cmp-category (a b)
16386 "Compare the string values of categories of strings A and B."
16387 (let ((ca (or (get-text-property 1 'category a) ""))
16388 (cb (or (get-text-property 1 'category b) "")))
16389 (cond ((string-lessp ca cb) -1)
16390 ((string-lessp cb ca) +1)
16391 (t nil))))
16393 (defsubst org-cmp-tag (a b)
16394 "Compare the string values of categories of strings A and B."
16395 (let ((ta (car (last (get-text-property 1 'tags a))))
16396 (tb (car (last (get-text-property 1 'tags b)))))
16397 (cond ((not ta) +1)
16398 ((not tb) -1)
16399 ((string-lessp ta tb) -1)
16400 ((string-lessp tb ta) +1)
16401 (t nil))))
16403 (defsubst org-cmp-time (a b)
16404 "Compare the time-of-day values of strings A and B."
16405 (let* ((def (if org-sort-agenda-notime-is-late 9901 -1))
16406 (ta (or (get-text-property 1 'time-of-day a) def))
16407 (tb (or (get-text-property 1 'time-of-day b) def)))
16408 (cond ((< ta tb) -1)
16409 ((< tb ta) +1)
16410 (t nil))))
16412 (defun org-entries-lessp (a b)
16413 "Predicate for sorting agenda entries."
16414 ;; The following variables will be used when the form is evaluated.
16415 ;; So even though the compiler complains, keep them.
16416 (let* ((time-up (org-cmp-time a b))
16417 (time-down (if time-up (- time-up) nil))
16418 (priority-up (org-cmp-priority a b))
16419 (priority-down (if priority-up (- priority-up) nil))
16420 (category-up (org-cmp-category a b))
16421 (category-down (if category-up (- category-up) nil))
16422 (category-keep (if category-up +1 nil))
16423 (tag-up (org-cmp-tag a b))
16424 (tag-down (if tag-up (- tag-up) nil)))
16425 (cdr (assoc
16426 (eval (cons 'or org-agenda-sorting-strategy-selected))
16427 '((-1 . t) (1 . nil) (nil . nil))))))
16429 ;;; Agenda commands
16431 (defun org-agenda-check-type (error &rest types)
16432 "Check if agenda buffer is of allowed type.
16433 If ERROR is non-nil, throw an error, otherwise just return nil."
16434 (if (memq org-agenda-type types)
16436 (if error
16437 (error "Not allowed in %s-type agenda buffers" org-agenda-type)
16438 nil)))
16440 (defun org-agenda-quit ()
16441 "Exit agenda by removing the window or the buffer."
16442 (interactive)
16443 (let ((buf (current-buffer)))
16444 (if (not (one-window-p)) (delete-window))
16445 (kill-buffer buf)
16446 (org-agenda-maybe-reset-markers 'force))
16447 ;; Maybe restore the pre-agenda window configuration.
16448 (and org-agenda-restore-windows-after-quit
16449 (not (eq org-agenda-window-setup 'other-frame))
16450 org-pre-agenda-window-conf
16451 (set-window-configuration org-pre-agenda-window-conf)))
16453 (defun org-agenda-exit ()
16454 "Exit agenda by removing the window or the buffer.
16455 Also kill all Org-mode buffers which have been loaded by `org-agenda'.
16456 Org-mode buffers visited directly by the user will not be touched."
16457 (interactive)
16458 (org-release-buffers org-agenda-new-buffers)
16459 (setq org-agenda-new-buffers nil)
16460 (org-agenda-quit))
16462 (defun org-save-all-org-buffers ()
16463 "Save all Org-mode buffers without user confirmation."
16464 (interactive)
16465 (message "Saving all Org-mode buffers...")
16466 (save-some-buffers t 'org-mode-p)
16467 (message "Saving all Org-mode buffers... done"))
16469 (defun org-agenda-redo ()
16470 "Rebuild Agenda.
16471 When this is the global TODO list, a prefix argument will be interpreted."
16472 (interactive)
16473 (let* ((org-agenda-keep-modes t)
16474 (line (org-current-line))
16475 (window-line (- line (org-current-line (window-start)))))
16476 (message "Rebuilding agenda buffer...")
16477 (eval org-agenda-redo-command)
16478 (setq org-agenda-undo-list nil
16479 org-agenda-pending-undo-list nil)
16480 (message "Rebuilding agenda buffer...done")
16481 (goto-line line)
16482 (recenter window-line)))
16484 (defun org-agenda-goto-today ()
16485 "Go to today."
16486 (interactive)
16487 (org-agenda-check-type t 'timeline 'agenda)
16488 (let ((tdpos (text-property-any (point-min) (point-max) 'org-today t)))
16489 (cond
16490 (tdpos (goto-char tdpos))
16491 ((eq org-agenda-type 'agenda)
16492 (let ((org-agenda-overriding-arguments org-agenda-last-arguments))
16493 (setf (nth 1 org-agenda-overriding-arguments) nil)
16494 (org-agenda-redo)
16495 (org-agenda-find-today-or-agenda)))
16496 (t (error "Cannot find today")))))
16498 (defun org-agenda-find-today-or-agenda ()
16499 (goto-char
16500 (or (text-property-any (point-min) (point-max) 'org-today t)
16501 (text-property-any (point-min) (point-max) 'org-agenda-type 'agenda)
16502 (point-min))))
16504 (defun org-agenda-later (arg)
16505 "Go forward in time by `org-agenda-ndays' days.
16506 With prefix ARG, go forward that many times `org-agenda-ndays'."
16507 (interactive "p")
16508 (org-agenda-check-type t 'agenda)
16509 (let ((org-agenda-overriding-arguments
16510 (list (car org-agenda-last-arguments)
16511 (+ org-starting-day (* arg org-agenda-ndays))
16512 nil t)))
16513 (org-agenda-redo)
16514 (org-agenda-find-today-or-agenda)))
16516 (defun org-agenda-earlier (arg)
16517 "Go back in time by `org-agenda-ndays' days.
16518 With prefix ARG, go back that many times `org-agenda-ndays'."
16519 (interactive "p")
16520 (org-agenda-check-type t 'agenda)
16521 (let ((org-agenda-overriding-arguments
16522 (list (car org-agenda-last-arguments)
16523 (- org-starting-day (* arg org-agenda-ndays))
16524 nil t)))
16525 (org-agenda-redo)
16526 (org-agenda-find-today-or-agenda)))
16528 (defun org-agenda-week-view ()
16529 "Switch to weekly view for agenda."
16530 (interactive)
16531 (org-agenda-check-type t 'agenda)
16532 (if (= org-agenda-ndays 7)
16533 (error "This is already the week view"))
16534 (setq org-agenda-ndays 7)
16535 (let ((org-agenda-overriding-arguments
16536 (list (car org-agenda-last-arguments)
16537 (or (get-text-property (point) 'day)
16538 org-starting-day)
16539 nil t)))
16540 (org-agenda-redo)
16541 (org-agenda-find-today-or-agenda))
16542 (org-agenda-set-mode-name)
16543 (message "Switched to week view"))
16545 (defun org-agenda-day-view ()
16546 "Switch to daily view for agenda."
16547 (interactive)
16548 (org-agenda-check-type t 'agenda)
16549 (if (= org-agenda-ndays 1)
16550 (error "This is already the day view"))
16551 (setq org-agenda-ndays 1)
16552 (let ((org-agenda-overriding-arguments
16553 (list (car org-agenda-last-arguments)
16554 (or (get-text-property (point) 'day)
16555 org-starting-day)
16556 nil t)))
16557 (org-agenda-redo)
16558 (org-agenda-find-today-or-agenda))
16559 (org-agenda-set-mode-name)
16560 (message "Switched to day view"))
16562 ;; FIXME: this no longer works if user make date format that starts with a blank
16563 (defun org-agenda-next-date-line (&optional arg)
16564 "Jump to the next line indicating a date in agenda buffer."
16565 (interactive "p")
16566 (org-agenda-check-type t 'agenda 'timeline)
16567 (beginning-of-line 1)
16568 (if (looking-at "^\\S-") (forward-char 1))
16569 (if (not (re-search-forward "^\\S-" nil t arg))
16570 (progn
16571 (backward-char 1)
16572 (error "No next date after this line in this buffer")))
16573 (goto-char (match-beginning 0)))
16575 (defun org-agenda-previous-date-line (&optional arg)
16576 "Jump to the previous line indicating a date in agenda buffer."
16577 (interactive "p")
16578 (org-agenda-check-type t 'agenda 'timeline)
16579 (beginning-of-line 1)
16580 (if (not (re-search-backward "^\\S-" nil t arg))
16581 (error "No previous date before this line in this buffer")))
16583 ;; Initialize the highlight
16584 (defvar org-hl (org-make-overlay 1 1))
16585 (org-overlay-put org-hl 'face 'highlight)
16587 (defun org-highlight (begin end &optional buffer)
16588 "Highlight a region with overlay."
16589 (funcall (if (featurep 'xemacs) 'set-extent-endpoints 'move-overlay)
16590 org-hl begin end (or buffer (current-buffer))))
16592 (defun org-unhighlight ()
16593 "Detach overlay INDEX."
16594 (funcall (if (featurep 'xemacs) 'detach-extent 'delete-overlay) org-hl))
16596 ;; FIXME this is currently not used.
16597 (defun org-highlight-until-next-command (beg end &optional buffer)
16598 (org-highlight beg end buffer)
16599 (add-hook 'pre-command-hook 'org-unhighlight-once))
16601 (defun org-unhighlight-once ()
16602 (remove-hook 'pre-command-hook 'org-unhighlight-once)
16603 (org-unhighlight))
16605 (defun org-agenda-follow-mode ()
16606 "Toggle follow mode in an agenda buffer."
16607 (interactive)
16608 (setq org-agenda-follow-mode (not org-agenda-follow-mode))
16609 (org-agenda-set-mode-name)
16610 (message "Follow mode is %s"
16611 (if org-agenda-follow-mode "on" "off")))
16613 (defun org-agenda-log-mode ()
16614 "Toggle log mode in an agenda buffer."
16615 (interactive)
16616 (org-agenda-check-type t 'agenda 'timeline)
16617 (setq org-agenda-show-log (not org-agenda-show-log))
16618 (org-agenda-set-mode-name)
16619 (org-agenda-redo)
16620 (message "Log mode is %s"
16621 (if org-agenda-show-log "on" "off")))
16623 (defun org-agenda-toggle-diary ()
16624 "Toggle diary inclusion in an agenda buffer."
16625 (interactive)
16626 (org-agenda-check-type t 'agenda)
16627 (setq org-agenda-include-diary (not org-agenda-include-diary))
16628 (org-agenda-redo)
16629 (org-agenda-set-mode-name)
16630 (message "Diary inclusion turned %s"
16631 (if org-agenda-include-diary "on" "off")))
16633 (defun org-agenda-toggle-time-grid ()
16634 "Toggle time grid in an agenda buffer."
16635 (interactive)
16636 (org-agenda-check-type t 'agenda)
16637 (setq org-agenda-use-time-grid (not org-agenda-use-time-grid))
16638 (org-agenda-redo)
16639 (org-agenda-set-mode-name)
16640 (message "Time-grid turned %s"
16641 (if org-agenda-use-time-grid "on" "off")))
16643 (defun org-agenda-set-mode-name ()
16644 "Set the mode name to indicate all the small mode settings."
16645 (setq mode-name
16646 (concat "Org-Agenda"
16647 (if (equal org-agenda-ndays 1) " Day" "")
16648 (if (equal org-agenda-ndays 7) " Week" "")
16649 (if org-agenda-follow-mode " Follow" "")
16650 (if org-agenda-include-diary " Diary" "")
16651 (if org-agenda-use-time-grid " Grid" "")
16652 (if org-agenda-show-log " Log" "")))
16653 (force-mode-line-update))
16655 (defun org-agenda-post-command-hook ()
16656 (and (eolp) (not (bolp)) (backward-char 1))
16657 (setq org-agenda-type (get-text-property (point) 'org-agenda-type))
16658 (if (and org-agenda-follow-mode
16659 (get-text-property (point) 'org-marker))
16660 (org-agenda-show)))
16662 (defun org-agenda-show-priority ()
16663 "Show the priority of the current item.
16664 This priority is composed of the main priority given with the [#A] cookies,
16665 and by additional input from the age of a schedules or deadline entry."
16666 (interactive)
16667 (let* ((pri (get-text-property (point-at-bol) 'priority)))
16668 (message "Priority is %d" (if pri pri -1000))))
16670 (defun org-agenda-show-tags ()
16671 "Show the tags applicable to the current item."
16672 (interactive)
16673 (let* ((tags (get-text-property (point-at-bol) 'tags)))
16674 (if tags
16675 (message "Tags are :%s:"
16676 (org-no-properties (mapconcat 'identity tags ":")))
16677 (message "No tags associated with this line"))))
16679 (defun org-agenda-goto (&optional highlight)
16680 "Go to the Org-mode file which contains the item at point."
16681 (interactive)
16682 (let* ((marker (or (get-text-property (point) 'org-marker)
16683 (org-agenda-error)))
16684 (buffer (marker-buffer marker))
16685 (pos (marker-position marker)))
16686 (switch-to-buffer-other-window buffer)
16687 (widen)
16688 (goto-char pos)
16689 (when (org-mode-p)
16690 (org-show-context 'agenda)
16691 (save-excursion
16692 (and (outline-next-heading)
16693 (org-flag-heading nil)))) ; show the next heading
16694 (and highlight (org-highlight (point-at-bol) (point-at-eol)))))
16696 (defun org-agenda-kill ()
16697 "Kill the entry or subtree belonging to the current agenda entry."
16698 (interactive)
16699 (or (eq major-mode 'org-agenda-mode) (error "Not in agenda"))
16700 (let* ((marker (or (get-text-property (point) 'org-marker)
16701 (org-agenda-error)))
16702 (buffer (marker-buffer marker))
16703 (pos (marker-position marker))
16704 (type (get-text-property (point) 'type))
16705 dbeg dend (n 0) conf)
16706 (org-with-remote-undo buffer
16707 (with-current-buffer buffer
16708 (save-excursion
16709 (goto-char pos)
16710 (if (and (org-mode-p) (not (member type '("sexp"))))
16711 (setq dbeg (progn (org-back-to-heading t) (point))
16712 dend (org-end-of-subtree t))
16713 (setq dbeg (point-at-bol)
16714 dend (min (point-max) (1+ (point-at-eol)))))
16715 (goto-char dbeg)
16716 (while (re-search-forward "^[ \t]*\\S-" dend t) (setq n (1+ n)))))
16717 (setq conf (or (eq t org-agenda-confirm-kill)
16718 (and (numberp org-agenda-confirm-kill)
16719 (> n org-agenda-confirm-kill))))
16720 (and conf
16721 (not (y-or-n-p
16722 (format "Delete entry with %d lines in buffer \"%s\"? "
16723 n (buffer-name buffer))))
16724 (error "Abort"))
16725 (org-remove-subtree-entries-from-agenda buffer dbeg dend)
16726 (with-current-buffer buffer (delete-region dbeg dend))
16727 (message "Agenda item and source killed"))))
16729 (defun org-agenda-archive ()
16730 "Kill the entry or subtree belonging to the current agenda entry."
16731 (interactive)
16732 (or (eq major-mode 'org-agenda-mode) (error "Not in agenda"))
16733 (let* ((marker (or (get-text-property (point) 'org-marker)
16734 (org-agenda-error)))
16735 (buffer (marker-buffer marker))
16736 (pos (marker-position marker)))
16737 (org-with-remote-undo buffer
16738 (with-current-buffer buffer
16739 (if (org-mode-p)
16740 (save-excursion
16741 (goto-char pos)
16742 (org-remove-subtree-entries-from-agenda)
16743 (org-back-to-heading t)
16744 (org-archive-subtree))
16745 (error "Archiving works only in Org-mode files"))))))
16747 (defun org-remove-subtree-entries-from-agenda (&optional buf beg end)
16748 "Remove all lines in the agenda that correspond to a given subtree.
16749 The subtree is the one in buffer BUF, starting at BEG and ending at END.
16750 If this information is not given, the function uses the tree at point."
16751 (let ((buf (or buf (current-buffer))) m p)
16752 (save-excursion
16753 (unless (and beg end)
16754 (org-back-to-heading t)
16755 (setq beg (point))
16756 (org-end-of-subtree t)
16757 (setq end (point)))
16758 (set-buffer (get-buffer org-agenda-buffer-name))
16759 (save-excursion
16760 (goto-char (point-max))
16761 (beginning-of-line 1)
16762 (while (not (bobp))
16763 (when (and (setq m (get-text-property (point) 'org-marker))
16764 (equal buf (marker-buffer m))
16765 (setq p (marker-position m))
16766 (>= p beg)
16767 (<= p end))
16768 (let (buffer-read-only)
16769 (delete-region (point-at-bol) (1+ (point-at-eol)))))
16770 (beginning-of-line 0))))))
16772 (defun org-agenda-open-link ()
16773 "Follow the link in the current line, if any."
16774 (interactive)
16775 (let ((eol (point-at-eol)))
16776 (save-excursion
16777 (if (or (re-search-forward org-bracket-link-regexp eol t)
16778 (re-search-forward org-angle-link-re eol t)
16779 (re-search-forward org-plain-link-re eol t))
16780 (call-interactively 'org-open-at-point)
16781 (error "No link in current line")))))
16783 (defun org-agenda-switch-to (&optional delete-other-windows)
16784 "Go to the Org-mode file which contains the item at point."
16785 (interactive)
16786 (let* ((marker (or (get-text-property (point) 'org-marker)
16787 (org-agenda-error)))
16788 (buffer (marker-buffer marker))
16789 (pos (marker-position marker)))
16790 (switch-to-buffer buffer)
16791 (and delete-other-windows (delete-other-windows))
16792 (widen)
16793 (goto-char pos)
16794 (when (org-mode-p)
16795 (org-show-context 'agenda)
16796 (save-excursion
16797 (and (outline-next-heading)
16798 (org-flag-heading nil)))))) ; show the next heading
16800 (defun org-agenda-goto-mouse (ev)
16801 "Go to the Org-mode file which contains the item at the mouse click."
16802 (interactive "e")
16803 (mouse-set-point ev)
16804 (org-agenda-goto))
16806 (defun org-agenda-show ()
16807 "Display the Org-mode file which contains the item at point."
16808 (interactive)
16809 (let ((win (selected-window)))
16810 (org-agenda-goto t)
16811 (select-window win)))
16813 (defun org-agenda-recenter (arg)
16814 "Display the Org-mode file which contains the item at point and recenter."
16815 (interactive "P")
16816 (let ((win (selected-window)))
16817 (org-agenda-goto t)
16818 (recenter arg)
16819 (select-window win)))
16821 (defun org-agenda-show-mouse (ev)
16822 "Display the Org-mode file which contains the item at the mouse click."
16823 (interactive "e")
16824 (mouse-set-point ev)
16825 (org-agenda-show))
16827 (defun org-agenda-check-no-diary ()
16828 "Check if the entry is a diary link and abort if yes."
16829 (if (get-text-property (point) 'org-agenda-diary-link)
16830 (org-agenda-error)))
16832 (defun org-agenda-error ()
16833 (error "Command not allowed in this line"))
16835 (defun org-agenda-tree-to-indirect-buffer ()
16836 "Show the subtree corresponding to the current entry in an indirect buffer.
16837 This calls the command `org-tree-to-indirect-buffer' from the original
16838 Org-mode buffer.
16839 With numerical prefix arg ARG, go up to this level and then take that tree.
16840 With a C-u prefix, make a separate frame for this tree (i.e. don't use the
16841 dedicated frame)."
16842 (interactive)
16843 (org-agenda-check-no-diary)
16844 (let* ((marker (or (get-text-property (point) 'org-marker)
16845 (org-agenda-error)))
16846 (buffer (marker-buffer marker))
16847 (pos (marker-position marker)))
16848 (with-current-buffer buffer
16849 (save-excursion
16850 (goto-char pos)
16851 (call-interactively 'org-tree-to-indirect-buffer)))))
16853 (defvar org-last-heading-marker (make-marker)
16854 "Marker pointing to the headline that last changed its TODO state
16855 by a remote command from the agenda.")
16857 (defun org-agenda-todo-nextset ()
16858 "Switch TODO entry to next sequence."
16859 (interactive)
16860 (org-agenda-todo 'nextset))
16862 (defun org-agenda-todo-previousset ()
16863 "Switch TODO entry to previous sequence."
16864 (interactive)
16865 (org-agenda-todo 'previousset))
16867 (defun org-agenda-todo (&optional arg)
16868 "Cycle TODO state of line at point, also in Org-mode file.
16869 This changes the line at point, all other lines in the agenda referring to
16870 the same tree node, and the headline of the tree node in the Org-mode file."
16871 (interactive "P")
16872 (org-agenda-check-no-diary)
16873 (let* ((col (current-column))
16874 (marker (or (get-text-property (point) 'org-marker)
16875 (org-agenda-error)))
16876 (buffer (marker-buffer marker))
16877 (pos (marker-position marker))
16878 (hdmarker (get-text-property (point) 'org-hd-marker))
16879 (buffer-read-only nil)
16880 newhead)
16881 (org-with-remote-undo buffer
16882 (with-current-buffer buffer
16883 (widen)
16884 (goto-char pos)
16885 (org-show-context 'agenda)
16886 (save-excursion
16887 (and (outline-next-heading)
16888 (org-flag-heading nil))) ; show the next heading
16889 (org-todo arg)
16890 (and (bolp) (forward-char 1))
16891 (setq newhead (org-get-heading))
16892 (save-excursion
16893 (org-back-to-heading)
16894 (move-marker org-last-heading-marker (point))))
16895 (beginning-of-line 1)
16896 (save-excursion
16897 (org-agenda-change-all-lines newhead hdmarker 'fixface))
16898 (move-to-column col))))
16900 (defun org-agenda-change-all-lines (newhead hdmarker &optional fixface)
16901 "Change all lines in the agenda buffer which match HDMARKER.
16902 The new content of the line will be NEWHEAD (as modified by
16903 `org-format-agenda-item'). HDMARKER is checked with
16904 `equal' against all `org-hd-marker' text properties in the file.
16905 If FIXFACE is non-nil, the face of each item is modified acording to
16906 the new TODO state."
16907 (let* ((buffer-read-only nil)
16908 props m pl undone-face done-face finish new dotime cat tags)
16909 (save-excursion
16910 (goto-char (point-max))
16911 (beginning-of-line 1)
16912 (while (not finish)
16913 (setq finish (bobp))
16914 (when (and (setq m (get-text-property (point) 'org-hd-marker))
16915 (equal m hdmarker))
16916 (setq props (text-properties-at (point))
16917 dotime (get-text-property (point) 'dotime)
16918 cat (get-text-property (point) 'org-category)
16919 tags (get-text-property (point) 'tags)
16920 new (org-format-agenda-item "x" newhead cat tags dotime 'noprefix)
16921 pl (get-text-property (point) 'prefix-length)
16922 undone-face (get-text-property (point) 'undone-face)
16923 done-face (get-text-property (point) 'done-face))
16924 (move-to-column pl)
16925 (cond
16926 ((equal new "")
16927 (beginning-of-line 1)
16928 (and (looking-at ".*\n?") (replace-match "")))
16929 ((looking-at ".*")
16930 (replace-match new t t)
16931 (beginning-of-line 1)
16932 (add-text-properties (point-at-bol) (point-at-eol) props)
16933 (when fixface
16934 (add-text-properties
16935 (point-at-bol) (point-at-eol)
16936 (list 'face
16937 (if org-last-todo-state-is-todo
16938 undone-face done-face))))
16939 (org-agenda-highlight-todo 'line)
16940 (beginning-of-line 1))
16941 (t (error "Line update did not work"))))
16942 (beginning-of-line 0)))
16943 (org-finalize-agenda)))
16945 ;; FIXME: allow negative value for org-agenda-align-tags-to-column
16946 ;; See the code in set-tags for the way to do this.
16947 (defun org-agenda-align-tags (&optional line)
16948 "Align all tags in agenda items to `org-agenda-align-tags-to-column'."
16949 (let ((buffer-read-only))
16950 (save-excursion
16951 (goto-char (if line (point-at-bol) (point-min)))
16952 (while (re-search-forward "\\([ \t]+\\):[a-zA-Z0-9_@:]+:[ \t]*$"
16953 (if line (point-at-eol) nil) t)
16954 (delete-region (match-beginning 1) (match-end 1))
16955 (goto-char (match-beginning 1))
16956 (insert (org-add-props
16957 (make-string (max 1 (- org-agenda-align-tags-to-column
16958 (current-column))) ?\ )
16959 (text-properties-at (point))))))))
16961 (defun org-agenda-priority-up ()
16962 "Increase the priority of line at point, also in Org-mode file."
16963 (interactive)
16964 (org-agenda-priority 'up))
16966 (defun org-agenda-priority-down ()
16967 "Decrease the priority of line at point, also in Org-mode file."
16968 (interactive)
16969 (org-agenda-priority 'down))
16971 (defun org-agenda-priority (&optional force-direction)
16972 "Set the priority of line at point, also in Org-mode file.
16973 This changes the line at point, all other lines in the agenda referring to
16974 the same tree node, and the headline of the tree node in the Org-mode file."
16975 (interactive)
16976 (org-agenda-check-no-diary)
16977 (let* ((marker (or (get-text-property (point) 'org-marker)
16978 (org-agenda-error)))
16979 (buffer (marker-buffer marker))
16980 (pos (marker-position marker))
16981 (hdmarker (get-text-property (point) 'org-hd-marker))
16982 (buffer-read-only nil)
16983 newhead)
16984 (org-with-remote-undo buffer
16985 (with-current-buffer buffer
16986 (widen)
16987 (goto-char pos)
16988 (org-show-context 'agenda)
16989 (save-excursion
16990 (and (outline-next-heading)
16991 (org-flag-heading nil))) ; show the next heading
16992 (funcall 'org-priority force-direction)
16993 (end-of-line 1)
16994 (setq newhead (org-get-heading)))
16995 (org-agenda-change-all-lines newhead hdmarker)
16996 (beginning-of-line 1))))
16998 (defun org-get-tags-at (&optional pos)
16999 "Get a list of all headline tags applicable at POS.
17000 POS defaults to point. If tags are inherited, the list contains
17001 the targets in the same sequence as the headlines appear, i.e.
17002 the tags of the current headline come last."
17003 (interactive)
17004 (let (tags)
17005 (save-excursion
17006 (save-restriction
17007 (widen)
17008 (goto-char (or pos (point)))
17009 (save-match-data
17010 (org-back-to-heading t)
17011 (condition-case nil
17012 (while t
17013 (if (looking-at "[^\r\n]+?:\\([a-zA-Z_@0-9:]+\\):[ \t]*\\([\n\r]\\|\\'\\)")
17014 (setq tags (append (org-split-string
17015 (org-match-string-no-properties 1) ":")
17016 tags)))
17017 (or org-use-tag-inheritance (error ""))
17018 (org-up-heading-all 1))
17019 (error nil))))
17020 tags)))
17022 ;; FIXME: should fix the tags property of the agenda line.
17023 (defun org-agenda-set-tags ()
17024 "Set tags for the current headline."
17025 (interactive)
17026 (org-agenda-check-no-diary)
17027 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
17028 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
17029 (org-agenda-error)))
17030 (buffer (marker-buffer hdmarker))
17031 (pos (marker-position hdmarker))
17032 (buffer-read-only nil)
17033 newhead)
17034 (org-with-remote-undo buffer
17035 (with-current-buffer buffer
17036 (widen)
17037 (goto-char pos)
17038 (save-excursion
17039 (org-show-context 'agenda))
17040 (save-excursion
17041 (and (outline-next-heading)
17042 (org-flag-heading nil))) ; show the next heading
17043 (goto-char pos)
17044 (call-interactively 'org-set-tags)
17045 (end-of-line 1)
17046 (setq newhead (org-get-heading)))
17047 (org-agenda-change-all-lines newhead hdmarker)
17048 (beginning-of-line 1))))
17050 (defun org-agenda-toggle-archive-tag ()
17051 "Toggle the archive tag for the current entry."
17052 (interactive)
17053 (org-agenda-check-no-diary)
17054 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
17055 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
17056 (org-agenda-error)))
17057 (buffer (marker-buffer hdmarker))
17058 (pos (marker-position hdmarker))
17059 (buffer-read-only nil)
17060 newhead)
17061 (org-with-remote-undo buffer
17062 (with-current-buffer buffer
17063 (widen)
17064 (goto-char pos)
17065 (org-show-context 'agenda)
17066 (save-excursion
17067 (and (outline-next-heading)
17068 (org-flag-heading nil))) ; show the next heading
17069 (call-interactively 'org-toggle-archive-tag)
17070 (end-of-line 1)
17071 (setq newhead (org-get-heading)))
17072 (org-agenda-change-all-lines newhead hdmarker)
17073 (beginning-of-line 1))))
17075 (defun org-agenda-date-later (arg &optional what)
17076 "Change the date of this item to one day later."
17077 (interactive "p")
17078 (org-agenda-check-type t 'agenda 'timeline)
17079 (org-agenda-check-no-diary)
17080 (let* ((marker (or (get-text-property (point) 'org-marker)
17081 (org-agenda-error)))
17082 (buffer (marker-buffer marker))
17083 (pos (marker-position marker)))
17084 (org-with-remote-undo buffer
17085 (with-current-buffer buffer
17086 (widen)
17087 (goto-char pos)
17088 (if (not (org-at-timestamp-p))
17089 (error "Cannot find time stamp"))
17090 (org-timestamp-change arg (or what 'day)))
17091 (org-agenda-show-new-time marker org-last-changed-timestamp))
17092 (message "Time stamp changed to %s" org-last-changed-timestamp)))
17094 (defun org-agenda-date-earlier (arg &optional what)
17095 "Change the date of this item to one day earlier."
17096 (interactive "p")
17097 (org-agenda-date-later (- arg) what))
17099 (defun org-agenda-show-new-time (marker stamp)
17100 "Show new date stamp via text properties."
17101 ;; We use text properties to make this undoable
17102 (let ((buffer-read-only nil))
17103 (setq stamp (concat " => " stamp))
17104 (save-excursion
17105 (goto-char (point-max))
17106 (while (not (bobp))
17107 (when (equal marker (get-text-property (point) 'org-marker))
17108 (move-to-column (- (window-width) (length stamp)) t)
17109 (if (featurep 'xemacs)
17110 ;; Use `duplicable' property to trigger undo recording
17111 (let ((ex (make-extent nil nil))
17112 (gl (make-glyph stamp)))
17113 (set-glyph-face gl 'secondary-selection)
17114 (set-extent-properties
17115 ex (list 'invisible t 'end-glyph gl 'duplicable t))
17116 (insert-extent ex (1- (point)) (point-at-eol)))
17117 (add-text-properties
17118 (1- (point)) (point-at-eol)
17119 (list 'display (org-add-props stamp nil
17120 'face 'secondary-selection))))
17121 (beginning-of-line 1))
17122 (beginning-of-line 0)))))
17124 (defun org-agenda-date-prompt (arg)
17125 "Change the date of this item. Date is prompted for, with default today.
17126 The prefix ARG is passed to the `org-time-stamp' command and can therefore
17127 be used to request time specification in the time stamp."
17128 (interactive "P")
17129 (org-agenda-check-type t 'agenda 'timeline)
17130 (org-agenda-check-no-diary)
17131 (let* ((marker (or (get-text-property (point) 'org-marker)
17132 (org-agenda-error)))
17133 (buffer (marker-buffer marker))
17134 (pos (marker-position marker)))
17135 (org-with-remote-undo buffer
17136 (with-current-buffer buffer
17137 (widen)
17138 (goto-char pos)
17139 (if (not (org-at-timestamp-p))
17140 (error "Cannot find time stamp"))
17141 (org-time-stamp arg)
17142 (message "Time stamp changed to %s" org-last-changed-timestamp)))))
17144 (defun org-agenda-schedule (arg)
17145 "Schedule the item at point."
17146 (interactive "P")
17147 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
17148 (org-agenda-check-no-diary)
17149 (let* ((marker (or (get-text-property (point) 'org-marker)
17150 (org-agenda-error)))
17151 (buffer (marker-buffer marker))
17152 (pos (marker-position marker))
17153 (org-insert-labeled-timestamps-at-point nil)
17155 (org-with-remote-undo buffer
17156 (with-current-buffer buffer
17157 (widen)
17158 (goto-char pos)
17159 (setq ts (org-schedule))
17160 (message "Item scheduled for %s" ts)))))
17162 (defun org-agenda-deadline (arg)
17163 "Schedule the item at point."
17164 (interactive "P")
17165 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
17166 (org-agenda-check-no-diary)
17167 (let* ((marker (or (get-text-property (point) 'org-marker)
17168 (org-agenda-error)))
17169 (buffer (marker-buffer marker))
17170 (pos (marker-position marker))
17171 (org-insert-labeled-timestamps-at-point nil)
17173 (org-with-remote-undo buffer
17174 (with-current-buffer buffer
17175 (widen)
17176 (goto-char pos)
17177 (setq ts (org-deadline))
17178 (message "Deadline for this item set to %s" ts)))))
17180 (defun org-get-heading ()
17181 "Return the heading of the current entry, without the stars."
17182 (save-excursion
17183 (org-back-to-heading t)
17184 (if (looking-at "\\*+[ \t]+\\([^\r\n]*\\)") (match-string 1) "")))
17186 (defun org-agenda-clock-in (&optional arg)
17187 "Start the clock on the currently selected item."
17188 (interactive "P")
17189 (org-agenda-check-no-diary)
17190 (let* ((marker (or (get-text-property (point) 'org-marker)
17191 (org-agenda-error)))
17192 (pos (marker-position marker)))
17193 (org-with-remote-undo (marker-buffer marker)
17194 (with-current-buffer (marker-buffer marker)
17195 (widen)
17196 (goto-char pos)
17197 (org-clock-in)))))
17199 (defun org-agenda-clock-out (&optional arg)
17200 "Stop the currently running clock."
17201 (interactive "P")
17202 (unless (marker-buffer org-clock-marker)
17203 (error "No running clock"))
17204 (org-with-remote-undo (marker-buffer org-clock-marker)
17205 (org-clock-out)))
17207 (defun org-agenda-clock-cancel (&optional arg)
17208 "Cancel the currently running clock."
17209 (interactive "P")
17210 (unless (marker-buffer org-clock-marker)
17211 (error "No running clock"))
17212 (org-with-remote-undo (marker-buffer org-clock-marker)
17213 (org-clock-cancel)))
17215 (defun org-agenda-diary-entry ()
17216 "Make a diary entry, like the `i' command from the calendar.
17217 All the standard commands work: block, weekly etc."
17218 (interactive)
17219 (org-agenda-check-type t 'agenda 'timeline)
17220 (require 'diary-lib)
17221 (let* ((char (progn
17222 (message "Diary entry: [d]ay [w]eekly [m]onthly [y]early [a]nniversary [b]lock [c]yclic")
17223 (read-char-exclusive)))
17224 (cmd (cdr (assoc char
17225 '((?d . insert-diary-entry)
17226 (?w . insert-weekly-diary-entry)
17227 (?m . insert-monthly-diary-entry)
17228 (?y . insert-yearly-diary-entry)
17229 (?a . insert-anniversary-diary-entry)
17230 (?b . insert-block-diary-entry)
17231 (?c . insert-cyclic-diary-entry)))))
17232 (oldf (symbol-function 'calendar-cursor-to-date))
17233 ; (buf (get-file-buffer (substitute-in-file-name diary-file)))
17234 (point (point))
17235 (mark (or (mark t) (point))))
17236 (unless cmd
17237 (error "No command associated with <%c>" char))
17238 (unless (and (get-text-property point 'day)
17239 (or (not (equal ?b char))
17240 (get-text-property mark 'day)))
17241 (error "Don't know which date to use for diary entry"))
17242 ;; We implement this by hacking the `calendar-cursor-to-date' function
17243 ;; and the `calendar-mark-ring' variable. Saves a lot of code.
17244 (let ((calendar-mark-ring
17245 (list (calendar-gregorian-from-absolute
17246 (or (get-text-property mark 'day)
17247 (get-text-property point 'day))))))
17248 (unwind-protect
17249 (progn
17250 (fset 'calendar-cursor-to-date
17251 (lambda (&optional error)
17252 (calendar-gregorian-from-absolute
17253 (get-text-property point 'day))))
17254 (call-interactively cmd))
17255 (fset 'calendar-cursor-to-date oldf)))))
17258 (defun org-agenda-execute-calendar-command (cmd)
17259 "Execute a calendar command from the agenda, with the date associated to
17260 the cursor position."
17261 (org-agenda-check-type t 'agenda 'timeline)
17262 (require 'diary-lib)
17263 (unless (get-text-property (point) 'day)
17264 (error "Don't know which date to use for calendar command"))
17265 (let* ((oldf (symbol-function 'calendar-cursor-to-date))
17266 (point (point))
17267 (date (calendar-gregorian-from-absolute
17268 (get-text-property point 'day)))
17269 ;; the following 3 vars are needed in the calendar
17270 (displayed-day (extract-calendar-day date))
17271 (displayed-month (extract-calendar-month date))
17272 (displayed-year (extract-calendar-year date)))
17273 (unwind-protect
17274 (progn
17275 (fset 'calendar-cursor-to-date
17276 (lambda (&optional error)
17277 (calendar-gregorian-from-absolute
17278 (get-text-property point 'day))))
17279 (call-interactively cmd))
17280 (fset 'calendar-cursor-to-date oldf))))
17282 (defun org-agenda-phases-of-moon ()
17283 "Display the phases of the moon for the 3 months around the cursor date."
17284 (interactive)
17285 (org-agenda-execute-calendar-command 'calendar-phases-of-moon))
17287 (defun org-agenda-holidays ()
17288 "Display the holidays for the 3 months around the cursor date."
17289 (interactive)
17290 (org-agenda-execute-calendar-command 'list-calendar-holidays))
17292 (defun org-agenda-sunrise-sunset (arg)
17293 "Display sunrise and sunset for the cursor date.
17294 Latitude and longitude can be specified with the variables
17295 `calendar-latitude' and `calendar-longitude'. When called with prefix
17296 argument, latitude and longitude will be prompted for."
17297 (interactive "P")
17298 (let ((calendar-longitude (if arg nil calendar-longitude))
17299 (calendar-latitude (if arg nil calendar-latitude))
17300 (calendar-location-name
17301 (if arg "the given coordinates" calendar-location-name)))
17302 (org-agenda-execute-calendar-command 'calendar-sunrise-sunset)))
17304 (defun org-agenda-goto-calendar ()
17305 "Open the Emacs calendar with the date at the cursor."
17306 (interactive)
17307 (org-agenda-check-type t 'agenda 'timeline)
17308 (let* ((day (or (get-text-property (point) 'day)
17309 (error "Don't know which date to open in calendar")))
17310 (date (calendar-gregorian-from-absolute day))
17311 (calendar-move-hook nil)
17312 (view-calendar-holidays-initially nil)
17313 (view-diary-entries-initially nil))
17314 (calendar)
17315 (calendar-goto-date date)))
17317 (defun org-calendar-goto-agenda ()
17318 "Compute the Org-mode agenda for the calendar date displayed at the cursor.
17319 This is a command that has to be installed in `calendar-mode-map'."
17320 (interactive)
17321 (org-agenda-list nil (calendar-absolute-from-gregorian
17322 (calendar-cursor-to-date))
17323 nil))
17325 (defun org-agenda-convert-date ()
17326 (interactive)
17327 (org-agenda-check-type t 'agenda 'timeline)
17328 (let ((day (get-text-property (point) 'day))
17329 date s)
17330 (unless day
17331 (error "Don't know which date to convert"))
17332 (setq date (calendar-gregorian-from-absolute day))
17333 (setq s (concat
17334 "Gregorian: " (calendar-date-string date) "\n"
17335 "ISO: " (calendar-iso-date-string date) "\n"
17336 "Day of Yr: " (calendar-day-of-year-string date) "\n"
17337 "Julian: " (calendar-julian-date-string date) "\n"
17338 "Astron. JD: " (calendar-astro-date-string date)
17339 " (Julian date number at noon UTC)\n"
17340 "Hebrew: " (calendar-hebrew-date-string date) " (until sunset)\n"
17341 "Islamic: " (calendar-islamic-date-string date) " (until sunset)\n"
17342 "French: " (calendar-french-date-string date) "\n"
17343 "Mayan: " (calendar-mayan-date-string date) "\n"
17344 "Coptic: " (calendar-coptic-date-string date) "\n"
17345 "Ethiopic: " (calendar-ethiopic-date-string date) "\n"
17346 "Persian: " (calendar-persian-date-string date) "\n"
17347 "Chinese: " (calendar-chinese-date-string date) "\n"))
17348 (with-output-to-temp-buffer "*Dates*"
17349 (princ s))
17350 (if (fboundp 'fit-window-to-buffer)
17351 (fit-window-to-buffer (get-buffer-window "*Dates*")))))
17354 ;;;; Embedded LaTeX
17356 (defvar org-cdlatex-mode-map (make-sparse-keymap)
17357 "Keymap for the minor `org-cdlatex-mode'.")
17359 (org-defkey org-cdlatex-mode-map "_" 'org-cdlatex-underscore-caret)
17360 (org-defkey org-cdlatex-mode-map "^" 'org-cdlatex-underscore-caret)
17361 (org-defkey org-cdlatex-mode-map "`" 'cdlatex-math-symbol)
17362 (org-defkey org-cdlatex-mode-map "'" 'org-cdlatex-math-modify)
17363 (org-defkey org-cdlatex-mode-map "\C-c{" 'cdlatex-environment)
17365 (defvar org-cdlatex-texmathp-advice-is-done nil
17366 "Flag remembering if we have applied the advice to texmathp already.")
17368 (define-minor-mode org-cdlatex-mode
17369 "Toggle the minor `org-cdlatex-mode'.
17370 This mode supports entering LaTeX environment and math in LaTeX fragments
17371 in Org-mode.
17372 \\{org-cdlatex-mode-map}"
17373 nil " OCDL" nil
17374 (when org-cdlatex-mode (require 'cdlatex))
17375 (unless org-cdlatex-texmathp-advice-is-done
17376 (setq org-cdlatex-texmathp-advice-is-done t)
17377 (defadvice texmathp (around org-math-always-on activate)
17378 "Always return t in org-mode buffers.
17379 This is because we want to insert math symbols without dollars even outside
17380 the LaTeX math segments. If Orgmode thinks that point is actually inside
17381 en embedded LaTeX fragement, let texmathp do its job.
17382 \\[org-cdlatex-mode-map]"
17383 (interactive)
17384 (let (p)
17385 (cond
17386 ((not (org-mode-p)) ad-do-it)
17387 ((eq this-command 'cdlatex-math-symbol)
17388 (setq ad-return-value t
17389 texmathp-why '("cdlatex-math-symbol in org-mode" . 0)))
17391 (let ((p (org-inside-LaTeX-fragment-p)))
17392 (if (and p (member (car p) (plist-get org-format-latex-options :matchers)))
17393 (setq ad-return-value t
17394 texmathp-why '("Org-mode embedded math" . 0))
17395 (if p ad-do-it)))))))))
17397 (defun turn-on-org-cdlatex ()
17398 "Unconditionally turn on `org-cdlatex-mode'."
17399 (org-cdlatex-mode 1))
17401 (defun org-inside-LaTeX-fragment-p ()
17402 "Test if point is inside a LaTeX fragment.
17403 I.e. after a \\begin, \\(, \\[, $, or $$, without the corresponding closing
17404 sequence appearing also before point.
17405 Even though the matchers for math are configurable, this function assumes
17406 that \\begin, \\(, \\[, and $$ are always used. Only the single dollar
17407 delimiters are skipped when they have been removed by customization.
17408 The return value is nil, or a cons cell with the delimiter and
17409 and the position of this delimiter.
17411 This function does a reasonably good job, but can locally be fooled by
17412 for example currency specifications. For example it will assume being in
17413 inline math after \"$22.34\". The LaTeX fragment formatter will only format
17414 fragments that are properly closed, but during editing, we have to live
17415 with the uncertainty caused by missing closing delimiters. This function
17416 looks only before point, not after."
17417 (catch 'exit
17418 (let ((pos (point))
17419 (dodollar (member "$" (plist-get org-format-latex-options :matchers)))
17420 (lim (progn
17421 (re-search-backward (concat "^\\(" paragraph-start "\\)") nil t)
17422 (point)))
17423 dd-on str (start 0) m re)
17424 (goto-char pos)
17425 (when dodollar
17426 (setq str (concat (buffer-substring lim (point)) "\000 X$.")
17427 re (nth 1 (assoc "$" org-latex-regexps)))
17428 (while (string-match re str start)
17429 (cond
17430 ((= (match-end 0) (length str))
17431 (throw 'exit (cons "$" (+ lim (match-beginning 0) 1))))
17432 ((= (match-end 0) (- (length str) 5))
17433 (throw 'exit nil))
17434 (t (setq start (match-end 0))))))
17435 (when (setq m (re-search-backward "\\(\\\\begin{[^}]*}\\|\\\\(\\|\\\\\\[\\)\\|\\(\\\\end{[^}]*}\\|\\\\)\\|\\\\\\]\\)\\|\\(\\$\\$\\)" lim t))
17436 (goto-char pos)
17437 (and (match-beginning 1) (throw 'exit (cons (match-string 1) m)))
17438 (and (match-beginning 2) (throw 'exit nil))
17439 ;; count $$
17440 (while (re-search-backward "\\$\\$" lim t)
17441 (setq dd-on (not dd-on)))
17442 (goto-char pos)
17443 (if dd-on (cons "$$" m))))))
17446 (defun org-try-cdlatex-tab ()
17447 "Check if it makes sense to execute `cdlatex-tab', and do it if yes.
17448 It makes sense to do so if `org-cdlatex-mode' is active and if the cursor is
17449 - inside a LaTeX fragment, or
17450 - after the first word in a line, where an abbreviation expansion could
17451 insert a LaTeX environment."
17452 (when org-cdlatex-mode
17453 (cond
17454 ((save-excursion
17455 (skip-chars-backward "a-zA-Z0-9*")
17456 (skip-chars-backward " \t")
17457 (bolp))
17458 (cdlatex-tab) t)
17459 ((org-inside-LaTeX-fragment-p)
17460 (cdlatex-tab) t)
17461 (t nil))))
17463 (defun org-cdlatex-underscore-caret (&optional arg)
17464 "Execute `cdlatex-sub-superscript' in LaTeX fragments.
17465 Revert to the normal definition outside of these fragments."
17466 (interactive "P")
17467 (if (org-inside-LaTeX-fragment-p)
17468 (call-interactively 'cdlatex-sub-superscript)
17469 (let (org-cdlatex-mode)
17470 (call-interactively (key-binding (vector last-input-event))))))
17472 (defun org-cdlatex-math-modify (&optional arg)
17473 "Execute `cdlatex-math-modify' in LaTeX fragments.
17474 Revert to the normal definition outside of these fragments."
17475 (interactive "P")
17476 (if (org-inside-LaTeX-fragment-p)
17477 (call-interactively 'cdlatex-math-modify)
17478 (let (org-cdlatex-mode)
17479 (call-interactively (key-binding (vector last-input-event))))))
17481 (defvar org-latex-fragment-image-overlays nil
17482 "List of overlays carrying the images of latex fragments.")
17483 (make-variable-buffer-local 'org-latex-fragment-image-overlays)
17485 (defun org-remove-latex-fragment-image-overlays ()
17486 "Remove all overlays with LaTeX fragment images in current buffer."
17487 (mapc 'org-delete-overlay org-latex-fragment-image-overlays)
17488 (setq org-latex-fragment-image-overlays nil))
17490 (defun org-preview-latex-fragment (&optional subtree)
17491 "Preview the LaTeX fragment at point, or all locally or globally.
17492 If the cursor is in a LaTeX fragment, create the image and overlay
17493 it over the source code. If there is no fragment at point, display
17494 all fragments in the current text, from one headline to the next. With
17495 prefix SUBTREE, display all fragments in the current subtree. With a
17496 double prefix `C-u C-u', or when the cursor is before the first headline,
17497 display all fragments in the buffer.
17498 The images can be removed again with \\[org-ctrl-c-ctrl-c]."
17499 (interactive "P")
17500 (org-remove-latex-fragment-image-overlays)
17501 (save-excursion
17502 (save-restriction
17503 (let (beg end at msg)
17504 (cond
17505 ((or (equal subtree '(16))
17506 (not (save-excursion
17507 (re-search-backward (concat "^" outline-regexp) nil t))))
17508 (setq beg (point-min) end (point-max)
17509 msg "Creating images for buffer...%s"))
17510 ((equal subtree '(4))
17511 (org-back-to-heading)
17512 (setq beg (point) end (org-end-of-subtree t)
17513 msg "Creating images for subtree...%s"))
17515 (if (setq at (org-inside-LaTeX-fragment-p))
17516 (goto-char (max (point-min) (- (cdr at) 2)))
17517 (org-back-to-heading))
17518 (setq beg (point) end (progn (outline-next-heading) (point))
17519 msg (if at "Creating image...%s"
17520 "Creating images for entry...%s"))))
17521 (message msg "")
17522 (narrow-to-region beg end)
17523 (goto-char beg)
17524 (org-format-latex
17525 (concat "ltxpng/" (file-name-sans-extension
17526 (file-name-nondirectory
17527 buffer-file-name)))
17528 default-directory 'overlays msg at 'forbuffer)
17529 (message msg "done. Use `C-c C-c' to remove images.")))))
17531 (defvar org-latex-regexps
17532 '(("begin" "^[ \t]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^\000]+?\\\\end{\\2}\\)" 1 t)
17533 ;; ("$" "\\([ (]\\|^\\)\\(\\(\\([$]\\)\\([^ \r\n,.$].*?\\(\n.*?\\)\\{0,5\\}[^ \r\n,.$]\\)\\4\\)\\)\\([ .,?;:'\")]\\|$\\)" 2 nil)
17534 ;; \000 in the following regex is needed for org-inside-LaTeX-fragment-p
17535 ("$" "\\([^$]\\)\\(\\(\\$\\([^ \r\n,;.$][^$\n\r]*?\\(\n[^$\n\r]*?\\)\\{0,2\\}[^ \r\n,.$]\\)\\$\\)\\)\\([ .,?;:'\")\000]\\|$\\)" 2 nil)
17536 ("\\(" "\\\\([^\000]*?\\\\)" 0 nil)
17537 ("\\[" "\\\\\\[[^\000]*?\\\\\\]" 0 t)
17538 ("$$" "\\$\\$[^\000]*?\\$\\$" 0 t))
17539 "Regular expressions for matching embedded LaTeX.")
17541 (defun org-format-latex (prefix &optional dir overlays msg at forbuffer)
17542 "Replace LaTeX fragments with links to an image, and produce images."
17543 (if (and overlays (fboundp 'clear-image-cache)) (clear-image-cache))
17544 (let* ((prefixnodir (file-name-nondirectory prefix))
17545 (absprefix (expand-file-name prefix dir))
17546 (todir (file-name-directory absprefix))
17547 (opt org-format-latex-options)
17548 (matchers (plist-get opt :matchers))
17549 (re-list org-latex-regexps)
17550 (cnt 0) txt link beg end re e checkdir
17551 m n block linkfile movefile ov)
17552 ;; Check if there are old images files with this prefix, and remove them
17553 (when (file-directory-p todir)
17554 (mapc 'delete-file
17555 (directory-files
17556 todir 'full
17557 (concat (regexp-quote prefixnodir) "_[0-9]+\\.png$"))))
17558 ;; Check the different regular expressions
17559 (while (setq e (pop re-list))
17560 (setq m (car e) re (nth 1 e) n (nth 2 e)
17561 block (if (nth 3 e) "\n\n" ""))
17562 (when (member m matchers)
17563 (goto-char (point-min))
17564 (while (re-search-forward re nil t)
17565 (when (or (not at) (equal (cdr at) (match-beginning n)))
17566 (setq txt (match-string n)
17567 beg (match-beginning n) end (match-end n)
17568 cnt (1+ cnt)
17569 linkfile (format "%s_%04d.png" prefix cnt)
17570 movefile (format "%s_%04d.png" absprefix cnt)
17571 link (concat block "[[file:" linkfile "]]" block))
17572 (if msg (message msg cnt))
17573 (goto-char beg)
17574 (unless checkdir ; make sure the directory exists
17575 (setq checkdir t)
17576 (or (file-directory-p todir) (make-directory todir)))
17577 (org-create-formula-image
17578 txt movefile opt forbuffer)
17579 (if overlays
17580 (progn
17581 (setq ov (org-make-overlay beg end))
17582 (if (featurep 'xemacs)
17583 (progn
17584 (org-overlay-put ov 'invisible t)
17585 (org-overlay-put
17586 ov 'end-glyph
17587 (make-glyph (vector 'png :file movefile))))
17588 (org-overlay-put
17589 ov 'display
17590 (list 'image :type 'png :file movefile :ascent 'center)))
17591 (push ov org-latex-fragment-image-overlays)
17592 (goto-char end))
17593 (delete-region beg end)
17594 (insert link))))))))
17596 ;; This function borrows from Ganesh Swami's latex2png.el
17597 (defun org-create-formula-image (string tofile options buffer)
17598 (let* ((tmpdir (if (featurep 'xemacs)
17599 (temp-directory)
17600 temporary-file-directory))
17601 (texfilebase (make-temp-name
17602 (expand-file-name "orgtex" tmpdir)))
17603 (texfile (concat texfilebase ".tex"))
17604 (dvifile (concat texfilebase ".dvi"))
17605 (pngfile (concat texfilebase ".png"))
17606 (fnh (face-attribute 'default :height nil))
17607 (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0))
17608 (dpi (number-to-string (* scale (floor (* 0.9 (if buffer fnh 140.))))))
17609 (fg (or (plist-get options (if buffer :foreground :html-foreground))
17610 "Black"))
17611 (bg (or (plist-get options (if buffer :background :html-background))
17612 "Transparent")))
17613 (if (eq fg 'default) (setq fg (org-dvipng-color :foreground)))
17614 (if (eq bg 'default) (setq bg (org-dvipng-color :background)))
17615 (with-temp-file texfile
17616 (insert org-format-latex-header
17617 "\n\\begin{document}\n" string "\n\\end{document}\n"))
17618 (let ((dir default-directory))
17619 (condition-case nil
17620 (progn
17621 (cd tmpdir)
17622 (call-process "latex" nil nil nil texfile))
17623 (error nil))
17624 (cd dir))
17625 (if (not (file-exists-p dvifile))
17626 (progn (message "Failed to create dvi file from %s" texfile) nil)
17627 (call-process "dvipng" nil nil nil
17628 "-E" "-fg" fg "-bg" bg
17629 "-D" dpi
17630 ;;"-x" scale "-y" scale
17631 "-T" "tight"
17632 "-o" pngfile
17633 dvifile)
17634 (if (not (file-exists-p pngfile))
17635 (progn (message "Failed to create png file from %s" texfile) nil)
17636 ;; Use the requested file name and clean up
17637 (copy-file pngfile tofile 'replace)
17638 (loop for e in '(".dvi" ".tex" ".aux" ".log" ".png") do
17639 (delete-file (concat texfilebase e)))
17640 pngfile))))
17642 (defun org-dvipng-color (attr)
17643 "Return an rgb color specification for dvipng."
17644 (apply 'format "rgb %s %s %s"
17645 (mapcar 'org-normalize-color
17646 (color-values (face-attribute 'default attr nil)))))
17648 (defun org-normalize-color (value)
17649 "Return string to be used as color value for an RGB component."
17650 (format "%g" (/ value 65535.0)))
17652 ;;;; Exporting
17654 ;;; Variables, constants, and parameter plists
17656 (defconst org-level-max 20)
17658 (defvar org-export-html-preamble nil
17659 "Preamble, to be inserted just after <body>. Set by publishing functions.")
17660 (defvar org-export-html-postamble nil
17661 "Preamble, to be inserted just before </body>. Set by publishing functions.")
17662 (defvar org-export-html-auto-preamble t
17663 "Should default preamble be inserted? Set by publishing functions.")
17664 (defvar org-export-html-auto-postamble t
17665 "Should default postamble be inserted? Set by publishing functions.")
17666 (defvar org-current-export-file nil) ; dynamically scoped parameter
17667 (defvar org-current-export-dir nil) ; dynamically scoped parameter
17670 (defconst org-export-plist-vars
17671 '((:language . org-export-default-language)
17672 (:customtime . org-display-custom-times)
17673 (:headline-levels . org-export-headline-levels)
17674 (:section-numbers . org-export-with-section-numbers)
17675 (:table-of-contents . org-export-with-toc)
17676 (:preserve-breaks . org-export-preserve-breaks)
17677 (:archived-trees . org-export-with-archived-trees)
17678 (:emphasize . org-export-with-emphasize)
17679 (:sub-superscript . org-export-with-sub-superscripts)
17680 (:TeX-macros . org-export-with-TeX-macros)
17681 (:LaTeX-fragments . org-export-with-LaTeX-fragments)
17682 (:skip-before-1st-heading . org-export-skip-text-before-1st-heading)
17683 (:fixed-width . org-export-with-fixed-width)
17684 (:timestamps . org-export-with-timestamps)
17685 (:tables . org-export-with-tables)
17686 (:table-auto-headline . org-export-highlight-first-table-line)
17687 (:style . org-export-html-style)
17688 (:agenda-style . org-agenda-export-html-style) ;; FIXME: Does this work????
17689 (:convert-org-links . org-export-html-link-org-files-as-html)
17690 (:inline-images . org-export-html-inline-images)
17691 (:expand-quoted-html . org-export-html-expand)
17692 (:timestamp . org-export-html-with-timestamp)
17693 (:publishing-directory . org-export-publishing-directory)
17694 (:preamble . org-export-html-preamble)
17695 (:postamble . org-export-html-postamble)
17696 (:auto-preamble . org-export-html-auto-preamble)
17697 (:auto-postamble . org-export-html-auto-postamble)
17698 (:author . user-full-name)
17699 (:email . user-mail-address)))
17701 (defun org-default-export-plist ()
17702 "Return the property list with default settings for the export variables."
17703 (let ((l org-export-plist-vars) rtn e)
17704 (while (setq e (pop l))
17705 (setq rtn (cons (car e) (cons (symbol-value (cdr e)) rtn))))
17706 rtn))
17708 (defun org-infile-export-plist ()
17709 "Return the property list with file-local settings for export."
17710 (save-excursion
17711 (goto-char 0)
17712 (let ((re (org-make-options-regexp
17713 '("TITLE" "AUTHOR" "EMAIL" "TEXT" "OPTIONS" "LANGUAGE")))
17714 p key val text options)
17715 (while (re-search-forward re nil t)
17716 (setq key (org-match-string-no-properties 1)
17717 val (org-match-string-no-properties 2))
17718 (cond
17719 ((string-equal key "TITLE") (setq p (plist-put p :title val)))
17720 ((string-equal key "AUTHOR")(setq p (plist-put p :author val)))
17721 ((string-equal key "EMAIL") (setq p (plist-put p :email val)))
17722 ((string-equal key "LANGUAGE") (setq p (plist-put p :language val)))
17723 ((string-equal key "TEXT")
17724 (setq text (if text (concat text "\n" val) val)))
17725 ((string-equal key "OPTIONS") (setq options val))))
17726 (setq p (plist-put p :text text))
17727 (when options
17728 (let ((op '(("H" . :headline-levels)
17729 ("num" . :section-numbers)
17730 ("toc" . :table-of-contents)
17731 ("\\n" . :preserve-breaks)
17732 ("@" . :expand-quoted-html)
17733 (":" . :fixed-width)
17734 ("|" . :tables)
17735 ("^" . :sub-superscript)
17736 ("*" . :emphasize)
17737 ("TeX" . :TeX-macros)
17738 ("LaTeX" . :LaTeX-fragments)
17739 ("skip" . :skip-before-1st-heading)))
17741 (while (setq o (pop op))
17742 (if (string-match (concat (regexp-quote (car o))
17743 ":\\([^ \t\n\r;,.]*\\)")
17744 options)
17745 (setq p (plist-put p (cdr o)
17746 (car (read-from-string
17747 (match-string 1 options)))))))))
17748 p)))
17750 (defun org-export-directory (type plist)
17751 (let* ((val (plist-get plist :publishing-directory))
17752 (dir (if (listp val)
17753 (or (cdr (assoc type val)) ".")
17754 val)))
17755 dir))
17757 (defun org-skip-comments (lines)
17758 "Skip lines starting with \"#\" and subtrees starting with COMMENT."
17759 (let ((re1 (concat "^\\(\\*+\\)[ \t]+" org-comment-string))
17760 (re2 "^\\(\\*+\\)[ \t\n\r]")
17761 (case-fold-search nil)
17762 rtn line level)
17763 (while (setq line (pop lines))
17764 (cond
17765 ((and (string-match re1 line)
17766 (setq level (- (match-end 1) (match-beginning 1))))
17767 ;; Beginning of a COMMENT subtree. Skip it.
17768 (while (and (setq line (pop lines))
17769 (or (not (string-match re2 line))
17770 (> (- (match-end 1) (match-beginning 1)) level))))
17771 (setq lines (cons line lines)))
17772 ((string-match "^#" line)
17773 ;; an ordinary comment line
17775 ((and org-export-table-remove-special-lines
17776 (string-match "^[ \t]*|" line)
17777 (or (string-match "^[ \t]*| *[!_^] *|" line)
17778 (and (string-match "| *<[0-9]+> *|" line)
17779 (not (string-match "| *[^ <|]" line)))))
17780 ;; a special table line that should be removed
17782 (t (setq rtn (cons line rtn)))))
17783 (nreverse rtn)))
17785 (defun org-export (&optional arg)
17786 (interactive)
17787 (let ((help "[t] insert the export option template
17788 \[v] limit export to visible part of outline tree
17790 \[a] export as ASCII
17791 \[h] export as HTML
17792 \[H] export as HTML to temporary buffer
17793 \[b] export as HTML and browse immediately
17794 \[x] export as XOXO
17796 \[i] export current file as iCalendar file
17797 \[I] export all agenda files as iCalendar files
17798 \[c] export agenda files into combined iCalendar file
17800 \[F] publish current file
17801 \[P] publish current project
17802 \[X] publish... (project will be prompted for)
17803 \[A] publish all projects")
17804 (cmds
17805 '((?t . org-insert-export-options-template)
17806 (?v . org-export-visible)
17807 (?a . org-export-as-ascii)
17808 (?h . org-export-as-html)
17809 (?b . org-export-as-html-and-open)
17810 (?H . org-export-as-html-to-buffer)
17811 (?R . org-export-region-as-html)
17812 (?x . org-export-as-xoxo)
17813 (?i . org-export-icalendar-this-file)
17814 (?I . org-export-icalendar-all-agenda-files)
17815 (?c . org-export-icalendar-combine-agenda-files)
17816 (?F . org-publish-current-file)
17817 (?P . org-publish-current-project)
17818 (?X . org-publish)
17819 (?A . org-publish-all)))
17820 r1 r2 ass)
17821 (save-window-excursion
17822 (delete-other-windows)
17823 (with-output-to-temp-buffer "*Org Export/Publishing Help*"
17824 (princ help))
17825 (message "Select command: ")
17826 (setq r1 (read-char-exclusive)))
17827 (setq r2 (if (< r1 27) (+ r1 96) r1))
17828 (if (setq ass (assq r2 cmds))
17829 (call-interactively (cdr ass))
17830 (error "No command associated with key %c" r1))))
17832 (defconst org-html-entities
17833 '(("nbsp")
17834 ("iexcl")
17835 ("cent")
17836 ("pound")
17837 ("curren")
17838 ("yen")
17839 ("brvbar")
17840 ("vert" . "&#124;")
17841 ("sect")
17842 ("uml")
17843 ("copy")
17844 ("ordf")
17845 ("laquo")
17846 ("not")
17847 ("shy")
17848 ("reg")
17849 ("macr")
17850 ("deg")
17851 ("plusmn")
17852 ("sup2")
17853 ("sup3")
17854 ("acute")
17855 ("micro")
17856 ("para")
17857 ("middot")
17858 ("odot"."o")
17859 ("star"."*")
17860 ("cedil")
17861 ("sup1")
17862 ("ordm")
17863 ("raquo")
17864 ("frac14")
17865 ("frac12")
17866 ("frac34")
17867 ("iquest")
17868 ("Agrave")
17869 ("Aacute")
17870 ("Acirc")
17871 ("Atilde")
17872 ("Auml")
17873 ("Aring") ("AA"."&Aring;")
17874 ("AElig")
17875 ("Ccedil")
17876 ("Egrave")
17877 ("Eacute")
17878 ("Ecirc")
17879 ("Euml")
17880 ("Igrave")
17881 ("Iacute")
17882 ("Icirc")
17883 ("Iuml")
17884 ("ETH")
17885 ("Ntilde")
17886 ("Ograve")
17887 ("Oacute")
17888 ("Ocirc")
17889 ("Otilde")
17890 ("Ouml")
17891 ("times")
17892 ("Oslash")
17893 ("Ugrave")
17894 ("Uacute")
17895 ("Ucirc")
17896 ("Uuml")
17897 ("Yacute")
17898 ("THORN")
17899 ("szlig")
17900 ("agrave")
17901 ("aacute")
17902 ("acirc")
17903 ("atilde")
17904 ("auml")
17905 ("aring")
17906 ("aelig")
17907 ("ccedil")
17908 ("egrave")
17909 ("eacute")
17910 ("ecirc")
17911 ("euml")
17912 ("igrave")
17913 ("iacute")
17914 ("icirc")
17915 ("iuml")
17916 ("eth")
17917 ("ntilde")
17918 ("ograve")
17919 ("oacute")
17920 ("ocirc")
17921 ("otilde")
17922 ("ouml")
17923 ("divide")
17924 ("oslash")
17925 ("ugrave")
17926 ("uacute")
17927 ("ucirc")
17928 ("uuml")
17929 ("yacute")
17930 ("thorn")
17931 ("yuml")
17932 ("fnof")
17933 ("Alpha")
17934 ("Beta")
17935 ("Gamma")
17936 ("Delta")
17937 ("Epsilon")
17938 ("Zeta")
17939 ("Eta")
17940 ("Theta")
17941 ("Iota")
17942 ("Kappa")
17943 ("Lambda")
17944 ("Mu")
17945 ("Nu")
17946 ("Xi")
17947 ("Omicron")
17948 ("Pi")
17949 ("Rho")
17950 ("Sigma")
17951 ("Tau")
17952 ("Upsilon")
17953 ("Phi")
17954 ("Chi")
17955 ("Psi")
17956 ("Omega")
17957 ("alpha")
17958 ("beta")
17959 ("gamma")
17960 ("delta")
17961 ("epsilon")
17962 ("varepsilon"."&epsilon;")
17963 ("zeta")
17964 ("eta")
17965 ("theta")
17966 ("iota")
17967 ("kappa")
17968 ("lambda")
17969 ("mu")
17970 ("nu")
17971 ("xi")
17972 ("omicron")
17973 ("pi")
17974 ("rho")
17975 ("sigmaf") ("varsigma"."&sigmaf;")
17976 ("sigma")
17977 ("tau")
17978 ("upsilon")
17979 ("phi")
17980 ("chi")
17981 ("psi")
17982 ("omega")
17983 ("thetasym") ("vartheta"."&thetasym;")
17984 ("upsih")
17985 ("piv")
17986 ("bull") ("bullet"."&bull;")
17987 ("hellip") ("dots"."&hellip;")
17988 ("prime")
17989 ("Prime")
17990 ("oline")
17991 ("frasl")
17992 ("weierp")
17993 ("image")
17994 ("real")
17995 ("trade")
17996 ("alefsym")
17997 ("larr") ("leftarrow"."&larr;") ("gets"."&larr;")
17998 ("uarr") ("uparrow"."&uarr;")
17999 ("rarr") ("to"."&rarr;") ("rightarrow"."&rarr;")
18000 ("darr")("downarrow"."&darr;")
18001 ("harr") ("leftrightarrow"."&harr;")
18002 ("crarr") ("hookleftarrow"."&crarr;") ; has round hook, not quite CR
18003 ("lArr") ("Leftarrow"."&lArr;")
18004 ("uArr") ("Uparrow"."&uArr;")
18005 ("rArr") ("Rightarrow"."&rArr;")
18006 ("dArr") ("Downarrow"."&dArr;")
18007 ("hArr") ("Leftrightarrow"."&hArr;")
18008 ("forall")
18009 ("part") ("partial"."&part;")
18010 ("exist") ("exists"."&exist;")
18011 ("empty") ("emptyset"."&empty;")
18012 ("nabla")
18013 ("isin") ("in"."&isin;")
18014 ("notin")
18015 ("ni")
18016 ("prod")
18017 ("sum")
18018 ("minus")
18019 ("lowast") ("ast"."&lowast;")
18020 ("radic")
18021 ("prop") ("proptp"."&prop;")
18022 ("infin") ("infty"."&infin;")
18023 ("ang") ("angle"."&ang;")
18024 ("and") ("vee"."&and;")
18025 ("or") ("wedge"."&or;")
18026 ("cap")
18027 ("cup")
18028 ("int")
18029 ("there4")
18030 ("sim")
18031 ("cong") ("simeq"."&cong;")
18032 ("asymp")("approx"."&asymp;")
18033 ("ne") ("neq"."&ne;")
18034 ("equiv")
18035 ("le")
18036 ("ge")
18037 ("sub") ("subset"."&sub;")
18038 ("sup") ("supset"."&sup;")
18039 ("nsub")
18040 ("sube")
18041 ("supe")
18042 ("oplus")
18043 ("otimes")
18044 ("perp")
18045 ("sdot") ("cdot"."&sdot;")
18046 ("lceil")
18047 ("rceil")
18048 ("lfloor")
18049 ("rfloor")
18050 ("lang")
18051 ("rang")
18052 ("loz") ("Diamond"."&loz;")
18053 ("spades") ("spadesuit"."&spades;")
18054 ("clubs") ("clubsuit"."&clubs;")
18055 ("hearts") ("diamondsuit"."&hearts;")
18056 ("diams") ("diamondsuit"."&diams;")
18057 ("quot")
18058 ("amp")
18059 ("lt")
18060 ("gt")
18061 ("OElig")
18062 ("oelig")
18063 ("Scaron")
18064 ("scaron")
18065 ("Yuml")
18066 ("circ")
18067 ("tilde")
18068 ("ensp")
18069 ("emsp")
18070 ("thinsp")
18071 ("zwnj")
18072 ("zwj")
18073 ("lrm")
18074 ("rlm")
18075 ("ndash")
18076 ("mdash")
18077 ("lsquo")
18078 ("rsquo")
18079 ("sbquo")
18080 ("ldquo")
18081 ("rdquo")
18082 ("bdquo")
18083 ("dagger")
18084 ("Dagger")
18085 ("permil")
18086 ("lsaquo")
18087 ("rsaquo")
18088 ("euro")
18090 ("arccos"."arccos")
18091 ("arcsin"."arcsin")
18092 ("arctan"."arctan")
18093 ("arg"."arg")
18094 ("cos"."cos")
18095 ("cosh"."cosh")
18096 ("cot"."cot")
18097 ("coth"."coth")
18098 ("csc"."csc")
18099 ("deg"."deg")
18100 ("det"."det")
18101 ("dim"."dim")
18102 ("exp"."exp")
18103 ("gcd"."gcd")
18104 ("hom"."hom")
18105 ("inf"."inf")
18106 ("ker"."ker")
18107 ("lg"."lg")
18108 ("lim"."lim")
18109 ("liminf"."liminf")
18110 ("limsup"."limsup")
18111 ("ln"."ln")
18112 ("log"."log")
18113 ("max"."max")
18114 ("min"."min")
18115 ("Pr"."Pr")
18116 ("sec"."sec")
18117 ("sin"."sin")
18118 ("sinh"."sinh")
18119 ("sup"."sup")
18120 ("tan"."tan")
18121 ("tanh"."tanh")
18123 "Entities for TeX->HTML translation.
18124 Entries can be like (\"ent\"), in which case \"\\ent\" will be translated to
18125 \"&ent;\". An entry can also be a dotted pair like (\"ent\".\"&other;\").
18126 In that case, \"\\ent\" will be translated to \"&other;\".
18127 The list contains HTML entities for Latin-1, Greek and other symbols.
18128 It is supplemented by a number of commonly used TeX macros with appropriate
18129 translations. There is currently no way for users to extend this.")
18131 ;;; General functions for all backends
18133 (defun org-cleaned-string-for-export (string &rest parameters)
18134 "Cleanup a buffer substring so that links can be created safely."
18135 (interactive)
18136 (let* ((re-radio (and org-target-link-regexp
18137 (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)")))
18138 (re-plain-link (concat "\\([^[<]\\)" org-plain-link-re))
18139 (re-angle-link (concat "\\([^[]\\)" org-angle-link-re))
18140 (re-archive (concat ":" org-archive-tag ":"))
18141 (re-quote (concat "^\\*+[ \t]+" org-quote-string "\\>"))
18142 (htmlp (plist-get parameters :for-html))
18143 (outline-regexp "\\*+")
18145 rtn p)
18146 (save-excursion
18147 (set-buffer (get-buffer-create " org-mode-tmp"))
18148 (erase-buffer)
18149 (insert string)
18150 ;; Remove license-to-kill stuff
18151 (while (setq p (text-property-any (point-min) (point-max)
18152 :org-license-to-kill t))
18153 (delete-region p (next-single-property-change p :org-license-to-kill)))
18155 (let ((org-inhibit-startup t)) (org-mode))
18156 (untabify (point-min) (point-max))
18158 ;; Get the correct stuff before the first headline
18159 (when (plist-get parameters :skip-before-1st-heading)
18160 (goto-char (point-min))
18161 (when (re-search-forward "^\\*+[ \t]" nil t)
18162 (delete-region (point-min) (match-beginning 0))
18163 (goto-char (point-min))
18164 (insert "\n")))
18165 (when (plist-get parameters :add-text)
18166 (goto-char (point-min))
18167 (insert (plist-get parameters :add-text) "\n"))
18169 ;; Get rid of archived trees
18170 (when (not (eq org-export-with-archived-trees t))
18171 (goto-char (point-min))
18172 (while (re-search-forward re-archive nil t)
18173 (if (not (org-on-heading-p t))
18174 (org-end-of-subtree t)
18175 (beginning-of-line 1)
18176 (setq a (if org-export-with-archived-trees
18177 (1+ (point-at-eol)) (point))
18178 b (org-end-of-subtree t))
18179 (if (> b a) (delete-region a b)))))
18181 ;; Protect stuff from HTML processing
18182 (goto-char (point-min))
18183 (while (re-search-forward "^[ \t]*:.*\\(\n[ \t]*:.*\\)*" nil t)
18184 (add-text-properties (match-beginning 0) (match-end 0)
18185 '(org-protected t)))
18186 (when htmlp
18187 (goto-char (point-min))
18188 (while (re-search-forward "^#\\+HTML:[ \t]*\\(.*\\)" nil t)
18189 (replace-match "\\1" t)
18190 (add-text-properties
18191 (point-at-bol) (min (1+ (point-at-eol)) (point-max))
18192 '(org-protected t))))
18193 (goto-char (point-min))
18194 (while (re-search-forward
18195 "^#\\+BEGIN_HTML\\>.*\\(\\(\n.*\\)*?\n\\)#\\+END_HTML\\>.*\n?" nil t)
18196 (if htmlp
18197 (add-text-properties (match-beginning 1) (1+ (match-end 1))
18198 '(org-protected t))
18199 (delete-region (match-beginning 0) (match-end 0))))
18200 (goto-char (point-min))
18201 (while (re-search-forward re-quote nil t)
18202 (goto-char (match-beginning 0))
18203 (end-of-line 1)
18204 (add-text-properties (point) (org-end-of-subtree t)
18205 '(org-protected t)))
18207 ;; Find targets in comments and move them out of comments,
18208 ;; but mark them as targets that should be invisible
18209 (goto-char (point-min))
18210 (while (re-search-forward "^#.*?\\(<<<?[^>\r\n]+>>>?\\).*" nil t)
18211 (replace-match "\\1(INVISIBLE)"))
18213 ;; Remove comments
18214 (goto-char (point-min))
18215 (while (re-search-forward "^#.*\n?" nil t)
18216 (replace-match ""))
18218 ;; Find matches for radio targets and turn them into internal links
18219 (goto-char (point-min))
18220 (when re-radio
18221 (while (re-search-forward re-radio nil t)
18222 (org-if-unprotected
18223 (replace-match "\\1[[\\2]]"))))
18225 ;; Find all links that contain a newline and put them into a single line
18226 (goto-char (point-min))
18227 (while (re-search-forward "\\(\\(\\[\\|\\]\\)\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\(\\[\\|\\]\\)\\)" nil t)
18228 (org-if-unprotected
18229 (replace-match "\\1 \\3")
18230 (goto-char (match-beginning 0))))
18232 ;; Convert LaTeX fragments to images
18233 (when (plist-get parameters :LaTeX-fragments)
18234 (org-format-latex
18235 (concat "ltxpng/" (file-name-sans-extension
18236 (file-name-nondirectory
18237 org-current-export-file)))
18238 org-current-export-dir nil "Creating LaTeX image %s"))
18239 (message "Exporting...")
18241 ;; Normalize links: Convert angle and plain links into bracket links
18242 ;; Expand link abbreviations
18243 (goto-char (point-min))
18244 (while (re-search-forward re-plain-link nil t)
18245 (goto-char (1- (match-end 0)))
18246 (org-if-unprotected
18247 (replace-match
18248 (concat
18249 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
18250 t t)))
18251 (goto-char (point-min))
18252 (while (re-search-forward re-angle-link nil t)
18253 (goto-char (1- (match-end 0)))
18254 (org-if-unprotected
18255 (replace-match
18256 (concat
18257 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
18258 t t)))
18259 (goto-char (point-min))
18260 (while (re-search-forward org-bracket-link-regexp nil t)
18261 (org-if-unprotected
18262 (replace-match
18263 (concat "[[" (save-match-data
18264 (org-link-expand-abbrev (match-string 1)))
18266 (if (match-end 3)
18267 (match-string 2)
18268 (concat "[" (match-string 1) "]"))
18269 "]")
18270 t t)))
18272 ;; Find multiline emphasis and put them into single line
18273 (when (plist-get parameters :emph-multiline)
18274 (goto-char (point-min))
18275 (while (re-search-forward org-emph-re nil t)
18276 (if (not (= (char-after (match-beginning 3))
18277 (char-after (match-beginning 4))))
18278 (org-if-unprotected
18279 (subst-char-in-region (match-beginning 0) (match-end 0)
18280 ?\n ?\ t)
18281 (goto-char (1- (match-end 0))))
18282 (goto-char (1+ (match-beginning 0))))))
18284 (setq rtn (buffer-string)))
18285 (kill-buffer " org-mode-tmp")
18286 rtn))
18288 (defun org-export-grab-title-from-buffer ()
18289 "Get a title for the current document, from looking at the buffer."
18290 (let (buffer-read-only)
18291 (save-excursion
18292 (goto-char (point-min))
18293 (let ((end (save-excursion (outline-next-heading) (point))))
18294 (when (re-search-forward "^[ \t]*[^# \t\r\n].*\n" end t)
18295 ;; Mark the line so that it will not be exported as normal text.
18296 (org-unmodified
18297 (add-text-properties (match-beginning 0) (match-end 0)
18298 (list :org-license-to-kill t)))
18299 ;; Return the title string
18300 (org-trim (match-string 0)))))))
18302 (defun org-solidify-link-text (s &optional alist)
18303 "Take link text and make a safe target out of it."
18304 (save-match-data
18305 (let* ((rtn
18306 (mapconcat
18307 'identity
18308 (org-split-string s "[ \t\r\n]+") "--"))
18309 (a (assoc rtn alist)))
18310 (or (cdr a) rtn))))
18312 ;; Variable holding the vector with section numbers
18313 (defvar org-section-numbers (make-vector org-level-max 0))
18315 (defun org-init-section-numbers ()
18316 "Initialize the vector for the section numbers."
18317 (let* ((level -1)
18318 (numbers (nreverse (org-split-string "" "\\.")))
18319 (depth (1- (length org-section-numbers)))
18320 (i depth) number-string)
18321 (while (>= i 0)
18322 (if (> i level)
18323 (aset org-section-numbers i 0)
18324 (setq number-string (or (car numbers) "0"))
18325 (if (string-match "\\`[A-Z]\\'" number-string)
18326 (aset org-section-numbers i
18327 (- (string-to-char number-string) ?A -1))
18328 (aset org-section-numbers i (string-to-number number-string)))
18329 (pop numbers))
18330 (setq i (1- i)))))
18332 (defun org-section-number (&optional level)
18333 "Return a string with the current section number.
18334 When LEVEL is non-nil, increase section numbers on that level."
18335 (let* ((depth (1- (length org-section-numbers))) idx n (string ""))
18336 (when level
18337 (when (> level -1)
18338 (aset org-section-numbers
18339 level (1+ (aref org-section-numbers level))))
18340 (setq idx (1+ level))
18341 (while (<= idx depth)
18342 (if (not (= idx 1))
18343 (aset org-section-numbers idx 0))
18344 (setq idx (1+ idx))))
18345 (setq idx 0)
18346 (while (<= idx depth)
18347 (setq n (aref org-section-numbers idx))
18348 (setq string (concat string (if (not (string= string "")) "." "")
18349 (int-to-string n)))
18350 (setq idx (1+ idx)))
18351 (save-match-data
18352 (if (string-match "\\`\\([@0]\\.\\)+" string)
18353 (setq string (replace-match "" t nil string)))
18354 (if (string-match "\\(\\.0\\)+\\'" string)
18355 (setq string (replace-match "" t nil string))))
18356 string))
18358 ;;; ASCII export
18360 (defvar org-last-level nil) ; dynamically scoped variable
18361 (defvar org-levels-open nil) ; dynamically scoped parameter
18362 (defvar org-ascii-current-indentation nil) ; For communication
18364 (defun org-export-as-ascii (arg)
18365 "Export the outline as a pretty ASCII file.
18366 If there is an active region, export only the region.
18367 The prefix ARG specifies how many levels of the outline should become
18368 underlined headlines. The default is 3."
18369 (interactive "P")
18370 (setq-default org-todo-line-regexp org-todo-line-regexp)
18371 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
18372 (org-infile-export-plist)))
18373 (custom-times org-display-custom-times)
18374 (org-ascii-current-indentation '(0 . 0))
18375 (level 0) line txt
18376 (umax nil)
18377 (umax-toc nil)
18378 (case-fold-search nil)
18379 (filename (concat (file-name-as-directory
18380 (org-export-directory :ascii opt-plist))
18381 (file-name-sans-extension
18382 (file-name-nondirectory buffer-file-name))
18383 ".txt"))
18384 (buffer (find-file-noselect filename))
18385 (org-levels-open (make-vector org-level-max nil))
18386 (odd org-odd-levels-only)
18387 (date (format-time-string "%Y/%m/%d" (current-time)))
18388 (time (format-time-string "%X" (org-current-time)))
18389 (author (plist-get opt-plist :author))
18390 (title (or (plist-get opt-plist :title)
18391 (and (not
18392 (plist-get opt-plist :skip-before-1st-heading))
18393 (org-export-grab-title-from-buffer))
18394 (file-name-sans-extension
18395 (file-name-nondirectory buffer-file-name))))
18396 (email (plist-get opt-plist :email))
18397 (language (plist-get opt-plist :language))
18398 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
18399 ; (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
18400 (todo nil)
18401 (lang-words nil)
18402 (region
18403 (buffer-substring
18404 (if (org-region-active-p) (region-beginning) (point-min))
18405 (if (org-region-active-p) (region-end) (point-max))))
18406 (lines (org-skip-comments
18407 (org-split-string
18408 (org-cleaned-string-for-export
18409 region
18410 :skip-before-1st-heading
18411 (plist-get opt-plist :skip-before-1st-heading)
18412 :add-text (plist-get opt-plist :text))
18413 "[\r\n]")))
18414 thetoc have-headings first-heading-pos)
18416 (let (buffer-read-only)
18417 (org-unmodified
18418 (remove-text-properties (point-min) (point-max)
18419 '(:org-license-to-kill t))))
18421 (setq org-last-level 1)
18422 (org-init-section-numbers)
18424 (find-file-noselect filename)
18426 (setq lang-words (or (assoc language org-export-language-setup)
18427 (assoc "en" org-export-language-setup)))
18428 (switch-to-buffer-other-window buffer)
18429 (erase-buffer)
18430 (fundamental-mode)
18431 ;; create local variables for all options, to make sure all called
18432 ;; functions get the correct information
18433 (mapcar (lambda (x)
18434 (set (make-local-variable (cdr x))
18435 (plist-get opt-plist (car x))))
18436 org-export-plist-vars)
18437 (org-set-local 'org-odd-levels-only odd)
18438 (setq umax (if arg (prefix-numeric-value arg)
18439 org-export-headline-levels))
18440 (setq umax-toc (if (integerp org-export-with-toc)
18441 (min org-export-with-toc umax)
18442 umax))
18444 ;; File header
18445 (if title (org-insert-centered title ?=))
18446 (insert "\n")
18447 (if (or author email)
18448 (insert (concat (nth 1 lang-words) ": " (or author "")
18449 (if email (concat " <" email ">") "")
18450 "\n")))
18451 (if (and date time)
18452 (insert (concat (nth 2 lang-words) ": " date " " time "\n")))
18454 (insert "\n\n")
18456 (if org-export-with-toc
18457 (progn
18458 (push (concat (nth 3 lang-words) "\n") thetoc)
18459 (push (concat (make-string (length (nth 3 lang-words)) ?=) "\n") thetoc)
18460 (mapcar '(lambda (line)
18461 (if (string-match org-todo-line-regexp
18462 line)
18463 ;; This is a headline
18464 (progn
18465 (setq have-headings t)
18466 (setq level (- (match-end 1) (match-beginning 1))
18467 level (org-tr-level level)
18468 txt (match-string 3 line)
18469 todo
18470 (or (and org-export-mark-todo-in-toc
18471 (match-beginning 2)
18472 (not (member (match-string 2 line)
18473 org-done-keywords)))
18474 ; TODO, not DONE
18475 (and org-export-mark-todo-in-toc
18476 (= level umax-toc)
18477 (org-search-todo-below
18478 line lines level))))
18479 (setq txt (org-html-expand-for-ascii txt))
18481 (if (and (memq org-export-with-tags '(not-in-toc nil))
18482 (string-match "[ \t]+:[a-zA-Z0-9_@:]+:[ \t]*$" txt))
18483 (setq txt (replace-match "" t t txt)))
18484 (if (string-match quote-re0 txt)
18485 (setq txt (replace-match "" t t txt)))
18487 (if org-export-with-section-numbers
18488 (setq txt (concat (org-section-number level)
18489 " " txt)))
18490 (if (<= level umax-toc)
18491 (progn
18492 (push
18493 (concat
18494 (make-string (* (1- level) 4) ?\ )
18495 (format (if todo "%s (*)\n" "%s\n") txt))
18496 thetoc)
18497 (setq org-last-level level))
18498 ))))
18499 lines)
18500 (setq thetoc (if have-headings (nreverse thetoc) nil))))
18502 (org-init-section-numbers)
18503 (while (setq line (pop lines))
18504 ;; Remove the quoted HTML tags.
18505 (setq line (org-html-expand-for-ascii line))
18506 ;; Remove targets
18507 (while (string-match "<<<?[^<>]*>>>?[ \t]*\n?" line)
18508 (setq line (replace-match "" t t line)))
18509 ;; Replace internal links
18510 (while (string-match org-bracket-link-regexp line)
18511 (setq line (replace-match
18512 (if (match-end 3) "[\\3]" "[\\1]")
18513 t nil line)))
18514 (when custom-times
18515 (setq line (org-translate-time line)))
18516 (cond
18517 ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line)
18518 ;; a Headline
18519 (setq first-heading-pos (or first-heading-pos (point)))
18520 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
18521 txt (match-string 2 line))
18522 (org-ascii-level-start level txt umax lines))
18524 (insert (org-fix-indentation line org-ascii-current-indentation) "\n"))))
18525 (normal-mode)
18527 ;; insert the table of contents
18528 (when thetoc
18529 (goto-char (point-min))
18530 (if (re-search-forward "^[ \t]*\\[TABLE-OF-CONTENTS\\][ \t]*$" nil t)
18531 (progn
18532 (goto-char (match-beginning 0))
18533 (replace-match ""))
18534 (goto-char first-heading-pos))
18535 (mapc 'insert thetoc)
18536 (or (looking-at "[ \t]*\n[ \t]*\n")
18537 (insert "\n\n")))
18539 (save-buffer)
18540 ;; remove display and invisible chars
18541 (let (beg end)
18542 (goto-char (point-min))
18543 (while (setq beg (next-single-property-change (point) 'display))
18544 (setq end (next-single-property-change beg 'display))
18545 (delete-region beg end)
18546 (goto-char beg)
18547 (insert "=>"))
18548 (goto-char (point-min))
18549 (while (setq beg (next-single-property-change (point) 'org-cwidth))
18550 (setq end (next-single-property-change beg 'org-cwidth))
18551 (delete-region beg end)
18552 (goto-char beg)))
18553 (goto-char (point-min))))
18555 (defun org-search-todo-below (line lines level)
18556 "Search the subtree below LINE for any TODO entries."
18557 (let ((rest (cdr (memq line lines)))
18558 (re org-todo-line-regexp)
18559 line lv todo)
18560 (catch 'exit
18561 (while (setq line (pop rest))
18562 (if (string-match re line)
18563 (progn
18564 (setq lv (- (match-end 1) (match-beginning 1))
18565 todo (and (match-beginning 2)
18566 (not (member (match-string 2 line)
18567 org-done-keywords))))
18568 ; TODO, not DONE
18569 (if (<= lv level) (throw 'exit nil))
18570 (if todo (throw 'exit t))))))))
18572 (defun org-html-expand-for-ascii (line)
18573 "Handle quoted HTML for ASCII export."
18574 (if org-export-html-expand
18575 (while (string-match "@<[^<>\n]*>" line)
18576 ;; We just remove the tags for now.
18577 (setq line (replace-match "" nil nil line))))
18578 line)
18580 (defun org-insert-centered (s &optional underline)
18581 "Insert the string S centered and underline it with character UNDERLINE."
18582 (let ((ind (max (/ (- 80 (string-width s)) 2) 0)))
18583 (insert (make-string ind ?\ ) s "\n")
18584 (if underline
18585 (insert (make-string ind ?\ )
18586 (make-string (string-width s) underline)
18587 "\n"))))
18589 (defun org-ascii-level-start (level title umax &optional lines)
18590 "Insert a new level in ASCII export."
18591 (let (char (n (- level umax 1)) (ind 0))
18592 (if (> level umax)
18593 (progn
18594 (insert (make-string (* 2 n) ?\ )
18595 (char-to-string (nth (% n (length org-export-ascii-bullets))
18596 org-export-ascii-bullets))
18597 " " title "\n")
18598 ;; find the indentation of the next non-empty line
18599 (catch 'stop
18600 (while lines
18601 (if (string-match "^\\*" (car lines)) (throw 'stop nil))
18602 (if (string-match "^\\([ \t]*\\)\\S-" (car lines))
18603 (throw 'stop (setq ind (org-get-indentation (car lines)))))
18604 (pop lines)))
18605 (setq org-ascii-current-indentation (cons (* 2 (1+ n)) ind)))
18606 (if (or (not (equal (char-before) ?\n))
18607 (not (equal (char-before (1- (point))) ?\n)))
18608 (insert "\n"))
18609 (setq char (nth (- umax level) (reverse org-export-ascii-underline)))
18610 (unless org-export-with-tags
18611 (if (string-match "[ \t]+\\(:[a-zA-Z0-9_@:]+:\\)[ \t]*$" title)
18612 (setq title (replace-match "" t t title))))
18613 (if org-export-with-section-numbers
18614 (setq title (concat (org-section-number level) " " title)))
18615 (insert title "\n" (make-string (string-width title) char) "\n")
18616 (setq org-ascii-current-indentation '(0 . 0)))))
18618 (defun org-export-visible (type arg)
18619 "Create a copy of the visible part of the current buffer, and export it.
18620 The copy is created in a temporary buffer and removed after use.
18621 TYPE is the final key (as a string) that also select the export command in
18622 the `C-c C-e' export dispatcher.
18623 As a special case, if the you type SPC at the prompt, the temporary
18624 org-mode file will not be removed but presented to you so that you can
18625 continue to use it. The prefix arg ARG is passed through to the exporting
18626 command."
18627 (interactive
18628 (list (progn
18629 (message "Export visible: [a]SCII [h]tml [b]rowse HTML [H/R]uffer with HTML [x]OXO [ ]keep buffer")
18630 (read-char-exclusive))
18631 current-prefix-arg))
18632 (if (not (member type '(?a ?\C-a ?b ?\C-b ?h ?x ?\ )))
18633 (error "Invalid export key"))
18634 (let* ((binding (cdr (assoc type
18635 '((?a . org-export-as-ascii)
18636 (?\C-a . org-export-as-ascii)
18637 (?b . org-export-as-html-and-open)
18638 (?\C-b . org-export-as-html-and-open)
18639 (?h . org-export-as-html)
18640 (?H . org-export-as-html-to-buffer)
18641 (?R . org-export-region-as-html)
18642 (?x . org-export-as-xoxo)))))
18643 (keepp (equal type ?\ ))
18644 (file buffer-file-name)
18645 (buffer (get-buffer-create "*Org Export Visible*"))
18646 s e)
18647 (with-current-buffer buffer (erase-buffer))
18648 (save-excursion
18649 (setq s (goto-char (point-min)))
18650 (while (not (= (point) (point-max)))
18651 (goto-char (org-find-invisible))
18652 (append-to-buffer buffer s (point))
18653 (setq s (goto-char (org-find-visible))))
18654 (goto-char (point-min))
18655 (unless keepp
18656 ;; Copy all comment lines to the end, to make sure #+ settings are
18657 ;; still available for the second export step. Kind of a hack, but
18658 ;; does do the trick.
18659 (if (looking-at "#[^\r\n]*")
18660 (append-to-buffer buffer (match-beginning 0) (1+ (match-end 0))))
18661 (while (re-search-forward "[\n\r]#[^\n\r]*" nil t)
18662 (append-to-buffer buffer (1+ (match-beginning 0))
18663 (min (point-max) (1+ (match-end 0))))))
18664 (set-buffer buffer)
18665 (let ((buffer-file-name file)
18666 (org-inhibit-startup t))
18667 (org-mode)
18668 (show-all)
18669 (unless keepp (funcall binding arg))))
18670 (if (not keepp)
18671 (kill-buffer buffer)
18672 (switch-to-buffer-other-window buffer)
18673 (goto-char (point-min)))))
18675 (defun org-find-visible ()
18676 (let ((s (point)))
18677 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
18678 (get-char-property s 'invisible)))
18680 (defun org-find-invisible ()
18681 (let ((s (point)))
18682 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
18683 (not (get-char-property s 'invisible))))
18686 ;;; HTML export
18688 (defun org-get-current-options ()
18689 "Return a string with current options as keyword options.
18690 Does include HTML export options as well as TODO and CATEGORY stuff."
18691 (format
18692 "#+TITLE: %s
18693 #+AUTHOR: %s
18694 #+EMAIL: %s
18695 #+LANGUAGE: %s
18696 #+TEXT: Some descriptive text to be emitted. Several lines OK.
18697 #+OPTIONS: H:%d num:%s toc:%s \\n:%s @:%s ::%s |:%s ^:%s *:%s TeX:%s LaTeX:%s skip:%s
18698 #+CATEGORY: %s
18699 #+SEQ_TODO: %s
18700 #+TYP_TODO: %s
18701 #+PRIORITIES: %c %c %c
18702 #+STARTUP: %s %s %s %s %s
18703 #+TAGS: %s
18704 #+ARCHIVE: %s
18705 #+LINK: %s
18707 (buffer-name) (user-full-name) user-mail-address org-export-default-language
18708 org-export-headline-levels
18709 org-export-with-section-numbers
18710 org-export-with-toc
18711 org-export-preserve-breaks
18712 org-export-html-expand
18713 org-export-with-fixed-width
18714 org-export-with-tables
18715 org-export-with-sub-superscripts
18716 org-export-with-emphasize
18717 org-export-with-TeX-macros
18718 org-export-with-LaTeX-fragments
18719 org-export-skip-text-before-1st-heading
18720 (file-name-nondirectory buffer-file-name)
18721 "TODO FEEDBACK VERIFY DONE"
18722 "Me Jason Marie DONE"
18723 org-highest-priority org-lowest-priority org-default-priority
18724 (cdr (assoc org-startup-folded
18725 '((nil . "showall") (t . "overview") (content . "content"))))
18726 (if org-odd-levels-only "odd" "oddeven")
18727 (if org-hide-leading-stars "hidestars" "showstars")
18728 (if org-startup-align-all-tables "align" "noalign")
18729 (cond ((eq t org-log-done) "logdone")
18730 ((not org-log-done) "nologging")
18731 ((listp org-log-done)
18732 (mapconcat (lambda (x) (concat "lognote" (symbol-name x)))
18733 org-log-done " ")))
18734 (or (mapconcat (lambda (x)
18735 (cond
18736 ((equal '(:startgroup) x) "{")
18737 ((equal '(:endgroup) x) "}")
18738 ((cdr x) (format "%s(%c)" (car x) (cdr x)))
18739 (t (car x))))
18740 (or org-tag-alist (org-get-buffer-tags)) " ") "")
18741 org-archive-location
18742 "org file:~/org/%s.org"
18745 (defun org-insert-export-options-template ()
18746 "Insert into the buffer a template with information for exporting."
18747 (interactive)
18748 (if (not (bolp)) (newline))
18749 (let ((s (org-get-current-options)))
18750 (and (string-match "#\\+CATEGORY" s)
18751 (setq s (substring s 0 (match-beginning 0))))
18752 (insert s)))
18754 (defun org-toggle-fixed-width-section (arg)
18755 "Toggle the fixed-width export.
18756 If there is no active region, the QUOTE keyword at the current headline is
18757 inserted or removed. When present, it causes the text between this headline
18758 and the next to be exported as fixed-width text, and unmodified.
18759 If there is an active region, this command adds or removes a colon as the
18760 first character of this line. If the first character of a line is a colon,
18761 this line is also exported in fixed-width font."
18762 (interactive "P")
18763 (let* ((cc 0)
18764 (regionp (org-region-active-p))
18765 (beg (if regionp (region-beginning) (point)))
18766 (end (if regionp (region-end)))
18767 (nlines (or arg (if (and beg end) (count-lines beg end) 1)))
18768 (re "[ \t]*\\(:\\)")
18769 off)
18770 (if regionp
18771 (save-excursion
18772 (goto-char beg)
18773 (setq cc (current-column))
18774 (beginning-of-line 1)
18775 (setq off (looking-at re))
18776 (while (> nlines 0)
18777 (setq nlines (1- nlines))
18778 (beginning-of-line 1)
18779 (cond
18780 (arg
18781 (move-to-column cc t)
18782 (insert ":\n")
18783 (forward-line -1))
18784 ((and off (looking-at re))
18785 (replace-match "" t t nil 1))
18786 ((not off) (move-to-column cc t) (insert ":")))
18787 (forward-line 1)))
18788 (save-excursion
18789 (org-back-to-heading)
18790 (if (looking-at (concat outline-regexp
18791 "\\( +\\<" org-quote-string "\\>\\)"))
18792 (replace-match "" t t nil 1)
18793 (if (looking-at outline-regexp)
18794 (progn
18795 (goto-char (match-end 0))
18796 (insert " " org-quote-string))))))))
18798 (defun org-export-as-html-and-open (arg)
18799 "Export the outline as HTML and immediately open it with a browser.
18800 If there is an active region, export only the region.
18801 The prefix ARG specifies how many levels of the outline should become
18802 headlines. The default is 3. Lower levels will become bulleted lists."
18803 (interactive "P")
18804 (org-export-as-html arg 'hidden)
18805 (org-open-file buffer-file-name))
18807 (defun org-export-as-html-batch ()
18808 "Call `org-export-as-html', may be used in batch processing as
18809 emacs --batch
18810 --load=$HOME/lib/emacs/org.el
18811 --eval \"(setq org-export-headline-levels 2)\"
18812 --visit=MyFile --funcall org-export-as-html-batch"
18813 (org-export-as-html org-export-headline-levels 'hidden))
18815 (defun org-export-as-html-to-buffer (arg)
18816 "Call `org-exort-as-html` with output to a temporary buffer.
18817 No file is created. The prefix ARG is passed through to `org-export-as-html'."
18818 (interactive "P")
18819 (org-export-as-html arg nil nil "*Org HTML Export*")
18820 (switch-to-buffer-other-window "*Org HTML Export*"))
18822 (defun org-replace-region-by-html (beg end)
18823 "Assume the current region has org-mode syntax, and convert it to HTML.
18824 This can be used in any buffer. For example, you could write an
18825 itemized list in org-mode syntax in an HTML buffer and then use this
18826 command to convert it."
18827 (interactive "r")
18828 (let (reg html buf)
18829 (if (org-mode-p)
18830 (setq html (org-export-region-as-html
18831 beg end t 'string))
18832 (setq reg (buffer-substring beg end)
18833 buf (get-buffer-create "*Org tmp*"))
18834 (save-excursion
18835 (set-buffer buf)
18836 (erase-buffer)
18837 (insert reg)
18838 (org-mode)
18839 (setq html (org-export-region-as-html
18840 (point-min) (point-max) t 'string)))
18841 (kill-buffer buf))
18842 (delete-region beg end)
18843 (insert html)))
18845 (defun org-export-region-as-html (beg end &optional body-only buffer)
18846 "Convert region from BEG to END in org-mode buffer to HTML.
18847 If prefix arg BODY-ONLY is set, omit file header, footer, and table of
18848 contents, and only produce the region of converted text, useful for
18849 cut-and-paste operations.
18850 If BUFFER is a buffer or a string, use/create that buffer as a target
18851 of the converted HTML. If BUFFER is the symbol `string', return the
18852 produced HTML as a string and leave not buffer behind. For example,
18853 a Lisp program could call this function in the following way:
18855 (setq html (org-export-region-as-html beg end t 'string))
18857 When called interactively, the output buffer is selected, and shown
18858 in a window. A non-interactive call will only retunr the buffer."
18859 (interactive "r\nP")
18860 (when (interactive-p)
18861 (setq buffer "*Org HTML EXPORT*"))
18862 (let ((transient-mark-mode t) (zmacs-regions t)
18863 rtn)
18864 (goto-char end)
18865 (set-mark (point)) ;; to activate the region
18866 (goto-char beg)
18867 (setq rtn (org-export-as-html
18868 nil nil nil
18869 buffer body-only))
18870 (if (fboundp 'deactivate-mark) (deactivate-mark))
18871 (if (and (interactive-p) (bufferp rtn))
18872 (switch-to-buffer-other-window rtn)
18873 rtn)))
18875 (defun org-export-as-html (arg &optional hidden ext-plist
18876 to-buffer body-only)
18877 "Export the outline as a pretty HTML file.
18878 If there is an active region, export only the region. The prefix
18879 ARG specifies how many levels of the outline should become
18880 headlines. The default is 3. Lower levels will become bulleted
18881 lists. When HIDDEN is non-nil, don't display the HTML buffer.
18882 EXT-PLIST is a property list with external parameters overriding
18883 org-mode's default settings, but still inferior to file-local
18884 settings. When TO-BUFFER is non-nil, create a buffer with that
18885 name and export to that buffer. If TO-BUFFER is the symbol `string',
18886 don't leave any buffer behind but just return the resulting HTML as
18887 a string. When BODY-ONLY is set, don't produce the file header and footer,
18888 simply return the content of <body>...</body>, without even
18889 the body tags themselves."
18890 (interactive "P")
18892 ;; Make sure we have a file name when we need it.
18893 (when (and (not (or to-buffer body-only))
18894 (not buffer-file-name))
18895 (if (buffer-base-buffer)
18896 (org-set-local 'buffer-file-name
18897 (with-current-buffer (buffer-base-buffer)
18898 buffer-file-name))
18899 (error "Need a file name to be able to export.")))
18901 (message "Exporting...")
18902 (setq-default org-todo-line-regexp org-todo-line-regexp)
18903 (setq-default org-deadline-line-regexp org-deadline-line-regexp)
18904 (setq-default org-done-keywords org-done-keywords)
18905 (setq-default org-maybe-keyword-time-regexp org-maybe-keyword-time-regexp)
18906 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
18907 ext-plist
18908 (org-infile-export-plist)))
18910 (style (plist-get opt-plist :style))
18911 (link-validate (plist-get opt-plist :link-validation-function))
18912 valid thetoc have-headings first-heading-pos
18913 (odd org-odd-levels-only)
18914 (region-p (org-region-active-p))
18915 ;; The following two are dynamically scoped into other
18916 ;; routines below.
18917 (org-current-export-dir (org-export-directory :html opt-plist))
18918 (org-current-export-file buffer-file-name)
18919 (level 0) (line "") (origline "") txt todo
18920 (umax nil)
18921 (umax-toc nil)
18922 (filename (if to-buffer nil
18923 (concat (file-name-as-directory
18924 (org-export-directory :html opt-plist))
18925 (file-name-sans-extension
18926 (file-name-nondirectory buffer-file-name))
18927 ".html")))
18928 (current-dir (if buffer-file-name
18929 (file-name-directory buffer-file-name)
18930 default-directory))
18931 (buffer (if to-buffer
18932 (cond
18933 ((eq to-buffer 'string) (get-buffer-create "*Org HTML Export*"))
18934 (t (get-buffer-create to-buffer)))
18935 (find-file-noselect filename)))
18936 (org-levels-open (make-vector org-level-max nil))
18937 (date (format-time-string "%Y/%m/%d" (current-time)))
18938 (time (format-time-string "%X" (org-current-time)))
18939 (author (plist-get opt-plist :author))
18940 (title (or (plist-get opt-plist :title)
18941 (and (not
18942 (plist-get opt-plist :skip-before-1st-heading))
18943 (org-export-grab-title-from-buffer))
18944 (and buffer-file-name
18945 (file-name-sans-extension
18946 (file-name-nondirectory buffer-file-name)))
18947 "UNTITLED"))
18948 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
18949 (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
18950 (inquote nil)
18951 (infixed nil)
18952 (in-local-list nil)
18953 (local-list-num nil)
18954 (local-list-indent nil)
18955 (llt org-plain-list-ordered-item-terminator)
18956 (email (plist-get opt-plist :email))
18957 (language (plist-get opt-plist :language))
18958 (lang-words nil)
18959 (target-alist nil) tg
18960 (head-count 0) cnt
18961 (start 0)
18962 (coding-system (and (boundp 'buffer-file-coding-system)
18963 buffer-file-coding-system))
18964 (coding-system-for-write coding-system)
18965 (save-buffer-coding-system coding-system)
18966 (charset (and coding-system
18967 (fboundp 'coding-system-get)
18968 (coding-system-get coding-system 'mime-charset)))
18969 (region
18970 (buffer-substring
18971 (if region-p (region-beginning) (point-min))
18972 (if region-p (region-end) (point-max))))
18973 (lines
18974 (org-skip-comments (org-split-string
18975 (org-cleaned-string-for-export
18976 region
18977 :emph-multiline t
18978 :for-html t
18979 :skip-before-1st-heading
18980 (plist-get opt-plist :skip-before-1st-heading)
18981 :add-text
18982 (plist-get opt-plist :text)
18983 :LaTeX-fragments
18984 (plist-get opt-plist :LaTeX-fragments))
18985 "[\r\n]")))
18986 table-open type
18987 table-buffer table-orig-buffer
18988 ind start-is-num starter didclose
18989 rpl path desc descp desc1 desc2 link
18992 (let (buffer-read-only)
18993 (org-unmodified
18994 (remove-text-properties (point-min) (point-max)
18995 '(:org-license-to-kill t))))
18997 (message "Exporting...")
18999 (setq org-last-level 1)
19000 (org-init-section-numbers)
19002 ;; Get the language-dependent settings
19003 (setq lang-words (or (assoc language org-export-language-setup)
19004 (assoc "en" org-export-language-setup)))
19006 ;; Switch to the output buffer
19007 (set-buffer buffer)
19008 (erase-buffer)
19009 (fundamental-mode)
19010 (let ((case-fold-search nil)
19011 (org-odd-levels-only odd))
19012 ;; create local variables for all options, to make sure all called
19013 ;; functions get the correct information
19014 (mapcar (lambda (x)
19015 (set (make-local-variable (cdr x))
19016 (plist-get opt-plist (car x))))
19017 org-export-plist-vars)
19018 (setq umax (if arg (prefix-numeric-value arg)
19019 org-export-headline-levels))
19020 (setq umax-toc (if (integerp org-export-with-toc)
19021 (min org-export-with-toc umax)
19022 umax))
19023 (unless body-only
19024 ;; File header
19025 (insert (format
19026 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
19027 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
19028 <html xmlns=\"http://www.w3.org/1999/xhtml\"
19029 lang=\"%s\" xml:lang=\"%s\">
19030 <head>
19031 <title>%s</title>
19032 <meta http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"/>
19033 <meta name=\"generator\" content=\"Org-mode\"/>
19034 <meta name=\"generated\" content=\"%s %s\"/>
19035 <meta name=\"author\" content=\"%s\"/>
19037 </head><body>
19039 language language (org-html-expand title)
19040 (or charset "iso-8859-1") date time author style))
19042 (insert (or (plist-get opt-plist :preamble) ""))
19044 (when (plist-get opt-plist :auto-preamble)
19045 (if title (insert (format org-export-html-title-format
19046 (org-html-expand title))))))
19048 (if (and org-export-with-toc (not body-only))
19049 (progn
19050 (push (format "<h%d>%s</h%d>\n"
19051 org-export-html-toplevel-hlevel
19052 (nth 3 lang-words)
19053 org-export-html-toplevel-hlevel)
19054 thetoc)
19055 (push "<ul>\n<li>" thetoc)
19056 (setq lines
19057 (mapcar '(lambda (line)
19058 (if (string-match org-todo-line-regexp line)
19059 ;; This is a headline
19060 (progn
19061 (setq have-headings t)
19062 (setq level (- (match-end 1) (match-beginning 1))
19063 level (org-tr-level level)
19064 txt (save-match-data
19065 (org-html-expand
19066 (org-export-cleanup-toc-line
19067 (match-string 3 line))))
19068 todo
19069 (or (and org-export-mark-todo-in-toc
19070 (match-beginning 2)
19071 (not (member (match-string 2 line)
19072 org-done-keywords)))
19073 ; TODO, not DONE
19074 (and org-export-mark-todo-in-toc
19075 (= level umax-toc)
19076 (org-search-todo-below
19077 line lines level))))
19078 (if (and (memq org-export-with-tags '(not-in-toc nil))
19079 (string-match "[ \t]+:[a-zA-Z0-9_@:]+:[ \t]*$" txt))
19080 (setq txt (replace-match "" t t txt)))
19081 (if (string-match quote-re0 txt)
19082 (setq txt (replace-match "" t t txt)))
19083 (if org-export-with-section-numbers
19084 (setq txt (concat (org-section-number level)
19085 " " txt)))
19086 (if (<= level (max umax umax-toc))
19087 (setq head-count (+ head-count 1)))
19088 (if (<= level umax-toc)
19089 (progn
19090 (if (> level org-last-level)
19091 (progn
19092 (setq cnt (- level org-last-level))
19093 (while (>= (setq cnt (1- cnt)) 0)
19094 (push "\n<ul>\n<li>" thetoc))
19095 (push "\n" thetoc)))
19096 (if (< level org-last-level)
19097 (progn
19098 (setq cnt (- org-last-level level))
19099 (while (>= (setq cnt (1- cnt)) 0)
19100 (push "</li>\n</ul>" thetoc))
19101 (push "\n" thetoc)))
19102 ;; Check for targets
19103 (while (string-match org-target-regexp line)
19104 (setq tg (match-string 1 line)
19105 line (replace-match
19106 (concat "@<span class=\"target\">" tg "@</span> ")
19107 t t line))
19108 (push (cons (org-solidify-link-text tg)
19109 (format "sec-%d" head-count))
19110 target-alist))
19111 (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
19112 (setq txt (replace-match "" t t txt)))
19113 (push
19114 (format
19115 (if todo
19116 "</li>\n<li><a href=\"#sec-%d\"><span class=\"todo\">%s</span></a>"
19117 "</li>\n<li><a href=\"#sec-%d\">%s</a>")
19118 head-count txt) thetoc)
19120 (setq org-last-level level))
19122 line)
19123 lines))
19124 (while (> org-last-level 0)
19125 (setq org-last-level (1- org-last-level))
19126 (push "</li>\n</ul>\n" thetoc))
19127 (setq thetoc (if have-headings (nreverse thetoc) nil))))
19129 (setq head-count 0)
19130 (org-init-section-numbers)
19132 (while (setq line (pop lines) origline line)
19133 (catch 'nextline
19135 ;; end of quote section?
19136 (when (and inquote (string-match "^\\*+" line))
19137 (insert "</pre>\n")
19138 (setq inquote nil))
19139 ;; inside a quote section?
19140 (when inquote
19141 (insert (org-html-protect line) "\n")
19142 (throw 'nextline nil))
19144 ;; verbatim lines
19145 (when (and org-export-with-fixed-width
19146 (string-match "^[ \t]*:\\(.*\\)" line))
19147 (when (not infixed)
19148 (setq infixed t)
19149 (insert "<pre>\n"))
19150 (insert (org-html-protect (match-string 1 line)) "\n")
19151 (when (and lines
19152 (not (string-match "^[ \t]*\\(:.*\\)"
19153 (car lines))))
19154 (setq infixed nil)
19155 (insert "</pre>\n"))
19156 (throw 'nextline nil))
19158 ;; Protected HTML
19159 (when (get-text-property 0 'org-protected line)
19160 (let (par)
19161 (when (re-search-backward
19162 "\\(<p>\\)\\([ \t\r\n]*\\)\\=" (- (point) 100) t)
19163 (setq par (match-string 1))
19164 (replace-match "\\2\n"))
19165 (insert line "\n")
19166 (while (and lines
19167 (get-text-property 0 'org-protected (car lines)))
19168 (insert (pop lines) "\n"))
19169 (and par (insert "<p>\n")))
19170 (throw 'nextline nil))
19172 ;; Horizontal line
19173 (when (string-match "^[ \t]*-\\{5,\\}[ \t]*$" line)
19174 (insert "\n<hr/>\n")
19175 (throw 'nextline nil))
19177 ;; make targets to anchors
19178 (while (string-match "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line)
19179 (cond
19180 ((match-end 2)
19181 (setq line (replace-match
19182 (concat "@<a name=\""
19183 (org-solidify-link-text (match-string 1 line))
19184 "\">\\nbsp@</a>")
19185 t t line)))
19186 ((and org-export-with-toc (equal (string-to-char line) ?*))
19187 (setq line (replace-match
19188 (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
19189 ; (concat "@<i>" (match-string 1 line) "@</i> ")
19190 t t line)))
19192 (setq line (replace-match
19193 (concat "@<a name=\""
19194 (org-solidify-link-text (match-string 1 line))
19195 "\" class=\"target\">" (match-string 1 line) "@</a> ")
19196 t t line)))))
19198 (setq line (org-html-handle-time-stamps line))
19200 ;; replace "&" by "&amp;", "<" and ">" by "&lt;" and "&gt;"
19201 ;; handle @<..> HTML tags (replace "@&gt;..&lt;" by "<..>")
19202 ;; Also handle sub_superscripts and checkboxes
19203 (setq line (org-html-expand line))
19205 ;; Format the links
19206 (setq start 0)
19207 (while (string-match org-bracket-link-analytic-regexp line start)
19208 (setq start (match-beginning 0))
19209 (setq type (if (match-end 2) (match-string 2 line) "internal"))
19210 (setq path (match-string 3 line))
19211 (setq desc1 (if (match-end 5) (match-string 5 line))
19212 desc2 (if (match-end 2) (concat type ":" path) path)
19213 descp (and desc1 (not (equal desc1 desc2)))
19214 desc (or desc1 desc2))
19215 ;; Make an image out of the description if that is so wanted
19216 (when (and descp (org-file-image-p desc))
19217 (save-match-data
19218 (if (string-match "^file:" desc)
19219 (setq desc (substring desc (match-end 0)))))
19220 (setq desc (concat "<img src=\"" desc "\"/>")))
19221 ;; FIXME: do we need to unescape here somewhere?
19222 (cond
19223 ((equal type "internal")
19224 (setq rpl
19225 (concat
19226 "<a href=\"#"
19227 (org-solidify-link-text
19228 (save-match-data (org-link-unescape path)) target-alist)
19229 "\">" desc "</a>")))
19230 ((member type '("http" "https")) ; FIXME: need to test this.
19231 ;; standard URL, just check if we need to inline an image
19232 (if (and (or (eq t org-export-html-inline-images)
19233 (and org-export-html-inline-images (not descp)))
19234 (org-file-image-p path))
19235 (setq rpl (concat "<img src=\"" type ":" path "\"/>"))
19236 (setq link (concat type ":" path))
19237 (setq rpl (concat "<a href=\"" link "\">" desc "</a>"))))
19238 ((member type '("ftp" "mailto" "news"))
19239 ;; standard URL
19240 (setq link (concat type ":" path))
19241 (setq rpl (concat "<a href=\"" link "\">" desc "</a>")))
19242 ((string= type "file")
19243 ;; FILE link
19244 (let* ((filename path)
19245 (abs-p (file-name-absolute-p filename))
19246 thefile file-is-image-p search)
19247 (save-match-data
19248 (if (string-match "::\\(.*\\)" filename)
19249 (setq search (match-string 1 filename)
19250 filename (replace-match "" t nil filename)))
19251 (setq valid
19252 (if (functionp link-validate)
19253 (funcall link-validate filename current-dir)
19255 (setq file-is-image-p (org-file-image-p filename))
19256 (setq thefile (if abs-p (expand-file-name filename) filename))
19257 (when (and org-export-html-link-org-files-as-html
19258 (string-match "\\.org$" thefile))
19259 (setq thefile (concat (substring thefile 0
19260 (match-beginning 0))
19261 ".html"))
19262 (if (and search
19263 ;; make sure this is can be used as target search
19264 (not (string-match "^[0-9]*$" search))
19265 (not (string-match "^\\*" search))
19266 (not (string-match "^/.*/$" search)))
19267 (setq thefile (concat thefile "#"
19268 (org-solidify-link-text
19269 (org-link-unescape search)))))
19270 (when (string-match "^file:" desc)
19271 (setq desc (replace-match "" t t desc))
19272 (if (string-match "\\.org$" desc)
19273 (setq desc (replace-match "" t t desc))))))
19274 (setq rpl (if (and file-is-image-p
19275 (or (eq t org-export-html-inline-images)
19276 (and org-export-html-inline-images
19277 (not descp))))
19278 (concat "<img src=\"" thefile "\"/>")
19279 (concat "<a href=\"" thefile "\">" desc "</a>")))
19280 (if (not valid) (setq rpl desc))))
19281 ((member type '("bbdb" "vm" "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
19282 (setq rpl (concat "<i>&lt;" type ":"
19283 (save-match-data (org-link-unescape path))
19284 "&gt;</i>"))))
19285 (setq line (replace-match rpl t t line)
19286 start (+ start (length rpl))))
19287 ;; TODO items
19288 (if (and (string-match org-todo-line-regexp line)
19289 (match-beginning 2))
19290 (if (member (match-string 2 line) org-done-keywords)
19291 (setq line (replace-match
19292 "<span class=\"done\">\\2</span>"
19293 t nil line 2))
19294 (setq line
19295 (concat (substring line 0 (match-beginning 2))
19296 "<span class=\"todo\">" (match-string 2 line)
19297 "</span>" (substring line (match-end 2))))))
19298 (cond
19299 ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line)
19300 ;; This is a headline
19301 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
19302 txt (match-string 2 line))
19303 (if (string-match quote-re0 txt)
19304 (setq txt (replace-match "" t t txt)))
19305 (if (<= level (max umax umax-toc))
19306 (setq head-count (+ head-count 1)))
19307 (when in-local-list
19308 ;; Close any local lists before inserting a new header line
19309 (while local-list-num
19310 (org-close-li)
19311 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
19312 (pop local-list-num))
19313 (setq local-list-indent nil
19314 in-local-list nil))
19315 (setq first-heading-pos (or first-heading-pos (point)))
19316 (org-html-level-start level txt umax
19317 (and org-export-with-toc (<= level umax))
19318 head-count)
19319 ;; QUOTES
19320 (when (string-match quote-re line)
19321 (insert "<pre>")
19322 (setq inquote t)))
19324 ((and org-export-with-tables
19325 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
19326 (if (not table-open)
19327 ;; New table starts
19328 (setq table-open t table-buffer nil table-orig-buffer nil))
19329 ;; Accumulate lines
19330 (setq table-buffer (cons line table-buffer)
19331 table-orig-buffer (cons origline table-orig-buffer))
19332 (when (or (not lines)
19333 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
19334 (car lines))))
19335 (setq table-open nil
19336 table-buffer (nreverse table-buffer)
19337 table-orig-buffer (nreverse table-orig-buffer))
19338 (org-close-par-maybe)
19339 (insert (org-format-table-html table-buffer table-orig-buffer))))
19341 ;; Normal lines
19342 (when (string-match
19343 (cond
19344 ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
19345 ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
19346 ((= llt ?\)) "^\\( \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
19347 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
19348 line)
19349 (setq ind (org-get-string-indentation line)
19350 start-is-num (match-beginning 4)
19351 starter (if (match-beginning 2)
19352 (substring (match-string 2 line) 0 -1))
19353 line (substring line (match-beginning 5)))
19354 (unless (string-match "[^ \t]" line)
19355 ;; empty line. Pretend indentation is large.
19356 (setq ind (if org-empty-line-terminates-plain-lists
19358 (1+ (or (car local-list-indent) 1)))))
19359 (setq didclose nil)
19360 (while (and in-local-list
19361 (or (and (= ind (car local-list-indent))
19362 (not starter))
19363 (< ind (car local-list-indent))))
19364 (setq didclose t)
19365 (org-close-li)
19366 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
19367 (pop local-list-num) (pop local-list-indent)
19368 (setq in-local-list local-list-indent))
19369 (cond
19370 ((and starter
19371 (or (not in-local-list)
19372 (> ind (car local-list-indent))))
19373 ;; Start new (level of) list
19374 (org-close-par-maybe)
19375 (insert (if start-is-num "<ol>\n<li>\n" "<ul>\n<li>\n"))
19376 (push start-is-num local-list-num)
19377 (push ind local-list-indent)
19378 (setq in-local-list t))
19379 (starter
19380 ;; continue current list
19381 (org-close-li)
19382 (insert "<li>\n"))
19383 (didclose
19384 ;; we did close a list, normal text follows: need <p>
19385 (org-open-par)))
19386 (if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
19387 (setq line
19388 (replace-match
19389 (if (equal (match-string 1 line) "X")
19390 "<b>[X]</b>"
19391 "<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
19392 t t line))))
19394 ;; Empty lines start a new paragraph. If hand-formatted lists
19395 ;; are not fully interpreted, lines starting with "-", "+", "*"
19396 ;; also start a new paragraph.
19397 (if (string-match "^ [-+*]-\\|^[ \t]*$" line) (org-open-par))
19398 ;; Is this the start of a footnote?
19399 (when (string-match "^[ \t]*\\[\\([0-9]+\\)\\]" line)
19400 (org-close-par-maybe)
19401 (let ((n (match-string 1 line)))
19402 (setq line (replace-match
19403 (format "<p class=\"footnote\"><sup><a class=\"footnum\"name=\"fn.%s\" href=\"#fnr.%s\">%s</a></sup>" n n n) t t line))))
19404 ;; Does this contain a reference to a footnote?
19405 (while (string-match "\\[\\([0-9]+\\)\\]" line)
19406 (let ((n (match-string 1 line)))
19407 (setq line (replace-match
19408 (format
19409 "<sup><a class=\"footref\" name=\"fnr.%s\" href=\"#fn.%s\">%s</a></sup>"
19410 n n n) t t line))))
19412 ;; Check if the line break needs to be conserved
19413 (cond
19414 ((string-match "\\\\\\\\[ \t]*$" line)
19415 (setq line (replace-match "<br/>" t t line)))
19416 (org-export-preserve-breaks
19417 (setq line (concat line "<br/>"))))
19419 (insert line "\n")))))
19421 ;; Properly close all local lists and other lists
19422 (when inquote (insert "</pre>\n"))
19423 (when in-local-list
19424 ;; Close any local lists before inserting a new header line
19425 (while local-list-num
19426 (org-close-li)
19427 (insert (if (car local-list-num) "</ol>\n" "</ul>\n"))
19428 (pop local-list-num))
19429 (setq local-list-indent nil
19430 in-local-list nil))
19431 (org-html-level-start 1 nil umax
19432 (and org-export-with-toc (<= level umax))
19433 head-count)
19435 (unless body-only
19436 (when (plist-get opt-plist :auto-postamble)
19437 (when author
19438 (insert "<p class=\"author\"> "
19439 (nth 1 lang-words) ": " author "\n")
19440 (when email
19441 (insert "<a href=\"mailto:" email "\">&lt;"
19442 email "&gt;</a>\n"))
19443 (insert "</p>\n"))
19444 (when (and date time)
19445 (insert "<p class=\"date\"> "
19446 (nth 2 lang-words) ": "
19447 date " " time "</p>\n")))
19449 (if org-export-html-with-timestamp
19450 (insert org-export-html-html-helper-timestamp))
19451 (insert (or (plist-get opt-plist :postamble) ""))
19452 (insert "</body>\n</html>\n"))
19454 (normal-mode)
19455 (if (eq major-mode default-major-mode) (html-mode))
19457 ;; insert the table of contents
19458 (goto-char (point-min))
19459 (when thetoc
19460 (if (or (re-search-forward
19461 "<p>\\s-*\\[TABLE-OF-CONTENTS\\]\\s-*</p>" nil t)
19462 (re-search-forward
19463 "\\[TABLE-OF-CONTENTS\\]" nil t))
19464 (progn
19465 (goto-char (match-beginning 0))
19466 (replace-match ""))
19467 (goto-char first-heading-pos)
19468 (when (looking-at "\\s-*</p>")
19469 (goto-char (match-end 0))
19470 (insert "\n")))
19471 (mapc 'insert thetoc))
19472 ;; remove empty paragraphs and lists
19473 (goto-char (point-min))
19474 (while (re-search-forward "<p>[ \r\n\t]*</p>" nil t)
19475 (replace-match ""))
19476 (goto-char (point-min))
19477 (while (re-search-forward "<li>[ \r\n\t]*</li>\n?" nil t)
19478 (replace-match ""))
19479 (or to-buffer (save-buffer))
19480 (goto-char (point-min))
19481 (message "Exporting... done")
19482 (if (eq to-buffer 'string)
19483 (prog1 (buffer-substring (point-min) (point-max))
19484 (kill-buffer (current-buffer)))
19485 (current-buffer)))))
19487 (defun org-format-table-html (lines olines)
19488 "Find out which HTML converter to use and return the HTML code."
19489 (if (stringp lines)
19490 (setq lines (org-split-string lines "\n")))
19491 (if (string-match "^[ \t]*|" (car lines))
19492 ;; A normal org table
19493 (org-format-org-table-html lines)
19494 ;; Table made by table.el - test for spanning
19495 (let* ((hlines (delq nil (mapcar
19496 (lambda (x)
19497 (if (string-match "^[ \t]*\\+-" x) x
19498 nil))
19499 lines)))
19500 (first (car hlines))
19501 (ll (and (string-match "\\S-+" first)
19502 (match-string 0 first)))
19503 (re (concat "^[ \t]*" (regexp-quote ll)))
19504 (spanning (delq nil (mapcar (lambda (x) (not (string-match re x)))
19505 hlines))))
19506 (if (and (not spanning)
19507 (not org-export-prefer-native-exporter-for-tables))
19508 ;; We can use my own converter with HTML conversions
19509 (org-format-table-table-html lines)
19510 ;; Need to use the code generator in table.el, with the original text.
19511 (org-format-table-table-html-using-table-generate-source olines)))))
19513 (defun org-format-org-table-html (lines &optional splice)
19514 "Format a table into HTML."
19515 ;; Get rid of hlines at beginning and end
19516 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
19517 (setq lines (nreverse lines))
19518 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
19519 (setq lines (nreverse lines))
19520 (when org-export-table-remove-special-lines
19521 ;; Check if the table has a marking column. If yes remove the
19522 ;; column and the special lines
19523 (setq lines (org-table-clean-before-export lines)))
19525 (let ((head (and org-export-highlight-first-table-line
19526 (delq nil (mapcar
19527 (lambda (x) (string-match "^[ \t]*|-" x))
19528 (cdr lines)))))
19529 (nlines 0) fnum i
19530 tbopen line fields html)
19531 (if splice (setq head nil))
19532 (unless splice (push (if head "<thead>" "<tbody>") html))
19533 (setq tbopen t)
19534 (while (setq line (pop lines))
19535 (catch 'next-line
19536 (if (string-match "^[ \t]*|-" line)
19537 (progn
19538 (unless splice
19539 (push (if head "</thead>" "</tbody>") html)
19540 (if lines (push "<tbody>" html) (setq tbopen nil)))
19541 (setq head nil) ;; head ends here, first time around
19542 ;; ignore this line
19543 (throw 'next-line t)))
19544 ;; Break the line into fields
19545 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
19546 (unless fnum (setq fnum (make-vector (length fields) 0)))
19547 (setq nlines (1+ nlines) i -1)
19548 (push (concat "<tr>"
19549 (mapconcat
19550 (lambda (x)
19551 (setq i (1+ i))
19552 (if (and (< i nlines)
19553 (string-match org-table-number-regexp x))
19554 (incf (aref fnum i)))
19555 (if head
19556 (concat (car org-export-table-header-tags) x
19557 (cdr org-export-table-header-tags))
19558 (concat (car org-export-table-data-tags) x
19559 (cdr org-export-table-data-tags))))
19560 fields "")
19561 "</tr>")
19562 html)))
19563 (unless splice (if tbopen (push "</tbody>" html)))
19564 (unless splice (push "</table>\n" html))
19565 (setq html (nreverse html))
19566 (unless splice
19567 ;; Put in COL tags with the alignment (unfortuntely often ignored...)
19568 (push (mapconcat
19569 (lambda (x)
19570 (format "<COL align=\"%s\">"
19571 (if (> (/ (float x) nlines) org-table-number-fraction)
19572 "right" "left")))
19573 fnum "")
19574 html)
19575 (push org-export-html-table-tag html))
19576 (concat (mapconcat 'identity html "\n") "\n")))
19578 (defun org-table-clean-before-export (lines)
19579 "Check if the table has a marking column.
19580 If yes remove the column and the special lines."
19581 (if (memq nil
19582 (mapcar
19583 (lambda (x) (or (string-match "^[ \t]*|-" x)
19584 (string-match "^[ \t]*| *\\([#!$*_^ /]\\) *|" x)))
19585 lines))
19586 (progn
19587 (setq org-table-clean-did-remove-column-1 nil)
19588 lines)
19589 (setq org-table-clean-did-remove-column-1 t)
19590 (delq nil
19591 (mapcar
19592 (lambda (x) (if (string-match "^[ \t]*| *[!_^/] *|" x)
19593 nil ; ignore this line
19594 (and (or (string-match "^[ \t]*|-+\\+" x)
19595 (string-match "^[ \t]*|[^|]*|" x))
19596 (replace-match "|" t t x))))
19597 lines))))
19599 (defun org-format-table-table-html (lines)
19600 "Format a table generated by table.el into HTML.
19601 This conversion does *not* use `table-generate-source' from table.el.
19602 This has the advantage that Org-mode's HTML conversions can be used.
19603 But it has the disadvantage, that no cell- or row-spanning is allowed."
19604 (let (line field-buffer
19605 (head org-export-highlight-first-table-line)
19606 fields html empty)
19607 (setq html (concat org-export-html-table-tag "\n"))
19608 (while (setq line (pop lines))
19609 (setq empty "&nbsp;")
19610 (catch 'next-line
19611 (if (string-match "^[ \t]*\\+-" line)
19612 (progn
19613 (if field-buffer
19614 (progn
19615 (setq
19616 html
19617 (concat
19618 html
19619 "<tr>"
19620 (mapconcat
19621 (lambda (x)
19622 (if (equal x "") (setq x empty))
19623 (if head
19624 (concat (car org-export-table-header-tags) x
19625 (cdr org-export-table-header-tags))
19626 (concat (car org-export-table-data-tags) x
19627 (cdr org-export-table-data-tags))))
19628 field-buffer "\n")
19629 "</tr>\n"))
19630 (setq head nil)
19631 (setq field-buffer nil)))
19632 ;; Ignore this line
19633 (throw 'next-line t)))
19634 ;; Break the line into fields and store the fields
19635 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
19636 (if field-buffer
19637 (setq field-buffer (mapcar
19638 (lambda (x)
19639 (concat x "<br/>" (pop fields)))
19640 field-buffer))
19641 (setq field-buffer fields))))
19642 (setq html (concat html "</table>\n"))
19643 html))
19645 (defun org-format-table-table-html-using-table-generate-source (lines)
19646 "Format a table into html, using `table-generate-source' from table.el.
19647 This has the advantage that cell- or row-spanning is allowed.
19648 But it has the disadvantage, that Org-mode's HTML conversions cannot be used."
19649 (require 'table)
19650 (with-current-buffer (get-buffer-create " org-tmp1 ")
19651 (erase-buffer)
19652 (insert (mapconcat 'identity lines "\n"))
19653 (goto-char (point-min))
19654 (if (not (re-search-forward "|[^+]" nil t))
19655 (error "Error processing table"))
19656 (table-recognize-table)
19657 (with-current-buffer (get-buffer-create " org-tmp2 ") (erase-buffer))
19658 (table-generate-source 'html " org-tmp2 ")
19659 (set-buffer " org-tmp2 ")
19660 (buffer-substring (point-min) (point-max))))
19662 (defun org-html-handle-time-stamps (s)
19663 "Format time stamps in string S, or remove them."
19664 (catch 'exit
19665 (let (r b)
19666 (while (string-match org-maybe-keyword-time-regexp s)
19667 (if (and (match-end 1) (equal (match-string 1 s) org-clock-string))
19668 ;; never export CLOCK
19669 (throw 'exit ""))
19670 (or b (setq b (substring s 0 (match-beginning 0))))
19671 (if (not org-export-with-timestamps)
19672 (setq r (concat r (substring s 0 (match-beginning 0)))
19673 s (substring s (match-end 0)))
19674 (setq r (concat
19675 r (substring s 0 (match-beginning 0))
19676 (if (match-end 1)
19677 (format "@<span class=\"timestamp-kwd\">%s @</span>"
19678 (match-string 1 s)))
19679 (format " @<span class=\"timestamp\">%s@</span>"
19680 (substring
19681 (org-translate-time (match-string 3 s)) 1 -1)))
19682 s (substring s (match-end 0)))))
19683 ;; Line break if line started and ended with time stamp stuff
19684 (if (not r)
19686 (setq r (concat r s))
19687 (unless (string-match "\\S-" (concat b s))
19688 (setq r (concat r "@<br/>")))
19689 r))))
19691 (defun org-html-protect (s)
19692 ;; convert & to &amp;, < to &lt; and > to &gt;
19693 (let ((start 0))
19694 (while (string-match "&" s start)
19695 (setq s (replace-match "&amp;" t t s)
19696 start (1+ (match-beginning 0))))
19697 (while (string-match "<" s)
19698 (setq s (replace-match "&lt;" t t s)))
19699 (while (string-match ">" s)
19700 (setq s (replace-match "&gt;" t t s))))
19703 (defun org-export-cleanup-toc-line (s)
19704 "Remove tags and time staps from lines going into the toc."
19705 (if (string-match " +:[a-zA-Z0-9_@:]+: *$" s)
19706 (setq s (replace-match "" t t s)))
19707 (when org-export-remove-timestamps-from-toc
19708 (while (string-match org-maybe-keyword-time-regexp s)
19709 (setq s (replace-match "" t t s))))
19710 (while (string-match org-bracket-link-regexp s)
19711 (setq s (replace-match (match-string (if (match-end 3) 3 1) s)
19712 t t s)))
19715 (defun org-html-expand (string)
19716 "Prepare STRING for HTML export. Applies all active conversions.
19717 If there are links in the string, don't modify these."
19718 (let* (m s l res)
19719 (while (setq m (string-match org-bracket-link-regexp string))
19720 (setq s (substring string 0 m)
19721 l (match-string 0 string)
19722 string (substring string (match-end 0)))
19723 (push (org-html-do-expand s) res)
19724 (push l res))
19725 (push (org-html-do-expand string) res)
19726 (apply 'concat (nreverse res))))
19728 (defun org-html-do-expand (s)
19729 "Apply all active conversions to translate special ASCII to HTML."
19730 (setq s (org-html-protect s))
19731 (if org-export-html-expand
19732 (while (string-match "@&lt;\\([^&]*\\)&gt;" s)
19733 (setq s (replace-match "<\\1>" t nil s))))
19734 (if org-export-with-emphasize
19735 (setq s (org-export-html-convert-emphasize s)))
19736 (if org-export-with-sub-superscripts
19737 (setq s (org-export-html-convert-sub-super s)))
19738 (if org-export-with-TeX-macros
19739 (let ((start 0) wd ass)
19740 (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)" s start))
19741 (setq wd (match-string 1 s))
19742 (if (setq ass (assoc wd org-html-entities))
19743 (setq s (replace-match (or (cdr ass)
19744 (concat "&" (car ass) ";"))
19745 t t s))
19746 (setq start (+ start (length wd)))))))
19749 (defun org-create-multibrace-regexp (left right n)
19750 "Create a regular expression which will match a balanced sexp.
19751 Opening delimiter is LEFT, and closing delimiter is RIGHT, both given
19752 as single character strings.
19753 The regexp returned will match the entire expression including the
19754 delimiters. It will also define a single group which contains the
19755 match except for the outermost delimiters. The maximum depth of
19756 stacked delimiters is N. Escaping delimiters is not possible."
19757 (let* ((nothing (concat "[^" "\\" left "\\" right "]*?"))
19758 (or "\\|")
19759 (re nothing)
19760 (next (concat "\\(?:" nothing left nothing right "\\)+" nothing)))
19761 (while (> n 1)
19762 (setq n (1- n)
19763 re (concat re or next)
19764 next (concat "\\(?:" nothing left next right "\\)+" nothing)))
19765 (concat left "\\(" re "\\)" right)))
19767 (defvar org-match-substring-regexp
19768 (concat
19769 "\\([^\\]\\)\\([_^]\\)\\("
19770 "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
19771 "\\|"
19772 "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
19773 "\\|"
19774 "\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
19775 "The regular expression matching a sub- or superscript.")
19777 ;(let ((s "a\\_b"))
19778 ; (and (string-match org-match-substring-regexp s)
19779 ; (conca t (match-string 1 s) ":::" (match-string 2 s))))
19781 (defun org-export-html-convert-sub-super (string)
19782 "Convert sub- and superscripts in STRING to HTML."
19783 (let (key c (s 0) (requireb (eq org-export-with-sub-superscripts '{})))
19784 (while (string-match org-match-substring-regexp string s)
19785 (if (and requireb (match-end 8))
19786 (setq s (match-end 2))
19787 (setq s (match-end 1)
19788 key (if (string= (match-string 2 string) "_") "sub" "sup")
19789 c (or (match-string 8 string)
19790 (match-string 6 string)
19791 (match-string 5 string))
19792 string (replace-match
19793 (concat (match-string 1 string)
19794 "<" key ">" c "</" key ">")
19795 t t string))))
19796 (while (string-match "\\\\\\([_^]\\)" string)
19797 (setq string (replace-match (match-string 1 string) t t string)))
19798 string))
19800 (defun org-export-html-convert-emphasize (string)
19801 "Apply emphasis."
19802 (let ((s 0))
19803 (while (string-match org-emph-re string s)
19804 (if (not (equal
19805 (substring string (match-beginning 3) (1+ (match-beginning 3)))
19806 (substring string (match-beginning 4) (1+ (match-beginning 4)))))
19807 (setq string (replace-match
19808 (concat "\\1" (nth 2 (assoc (match-string 3 string) org-emphasis-alist))
19809 "\\4" (nth 3 (assoc (match-string 3 string) org-emphasis-alist))
19810 "\\5") t nil string))
19811 (setq s (1+ s))))
19812 string))
19814 (defvar org-par-open nil)
19815 (defun org-open-par ()
19816 "Insert <p>, but first close previous paragraph if any."
19817 (org-close-par-maybe)
19818 (insert "\n<p>")
19819 (setq org-par-open t))
19820 (defun org-close-par-maybe ()
19821 "Close paragraph if there is one open."
19822 (when org-par-open
19823 (insert "</p>")
19824 (setq org-par-open nil)))
19825 (defun org-close-li ()
19826 "Close <li> if necessary."
19827 (org-close-par-maybe)
19828 (insert "</li>\n"))
19830 (defun org-html-level-start (level title umax with-toc head-count)
19831 "Insert a new level in HTML export.
19832 When TITLE is nil, just close all open levels."
19833 (org-close-par-maybe)
19834 (let ((l (1+ (max level umax))))
19835 (while (<= l org-level-max)
19836 (if (aref org-levels-open (1- l))
19837 (progn
19838 (org-html-level-close l)
19839 (aset org-levels-open (1- l) nil)))
19840 (setq l (1+ l)))
19841 (when title
19842 ;; If title is nil, this means this function is called to close
19843 ;; all levels, so the rest is done only if title is given
19844 (when (string-match "\\(:[a-zA-Z0-9_@:]+:\\)[ \t]*$" title)
19845 (setq title (replace-match
19846 (if org-export-with-tags
19847 (save-match-data
19848 (concat
19849 "&nbsp;&nbsp;&nbsp;<span class=\"tag\">"
19850 (mapconcat 'identity (org-split-string
19851 (match-string 1 title) ":")
19852 "&nbsp;")
19853 "</span>"))
19855 t t title)))
19856 (if (> level umax)
19857 (progn
19858 (if (aref org-levels-open (1- level))
19859 (progn
19860 (org-close-li)
19861 (insert "<li>" title "<br/>\n"))
19862 (aset org-levels-open (1- level) t)
19863 (org-close-par-maybe)
19864 (insert "<ul>\n<li>" title "<br/>\n")))
19865 (if org-export-with-section-numbers
19866 (setq title (concat (org-section-number level) " " title)))
19867 (setq level (+ level org-export-html-toplevel-hlevel -1))
19868 (if with-toc
19869 (insert (format "\n<h%d id=\"sec-%d\">%s</h%d>\n"
19870 level head-count title level))
19871 (insert (format "\n<h%d>%s</h%d>\n" level title level)))
19872 (org-open-par)))))
19874 (defun org-html-level-close (&rest args)
19875 "Terminate one level in HTML export."
19876 (org-close-li)
19877 (insert "</ul>\n"))
19879 ;;; iCalendar export
19881 ;;;###autoload
19882 (defun org-export-icalendar-this-file ()
19883 "Export current file as an iCalendar file.
19884 The iCalendar file will be located in the same directory as the Org-mode
19885 file, but with extension `.ics'."
19886 (interactive)
19887 (org-export-icalendar nil buffer-file-name))
19889 ;;;###autoload
19890 (defun org-export-icalendar-all-agenda-files ()
19891 "Export all files in `org-agenda-files' to iCalendar .ics files.
19892 Each iCalendar file will be located in the same directory as the Org-mode
19893 file, but with extension `.ics'."
19894 (interactive)
19895 (apply 'org-export-icalendar nil (org-agenda-files t)))
19897 ;;;###autoload
19898 (defun org-export-icalendar-combine-agenda-files ()
19899 "Export all files in `org-agenda-files' to a single combined iCalendar file.
19900 The file is stored under the name `org-combined-agenda-icalendar-file'."
19901 (interactive)
19902 (apply 'org-export-icalendar t (org-agenda-files t)))
19904 (defun org-export-icalendar (combine &rest files)
19905 "Create iCalendar files for all elements of FILES.
19906 If COMBINE is non-nil, combine all calendar entries into a single large
19907 file and store it under the name `org-combined-agenda-icalendar-file'."
19908 (save-excursion
19909 (org-prepare-agenda-buffers files)
19910 (let* ((dir (org-export-directory
19911 :ical (list :publishing-directory
19912 org-export-publishing-directory)))
19913 file ical-file ical-buffer category started org-agenda-new-buffers)
19915 (and (get-buffer "*ical-tmp*") (kill-buffer "*ical-tmp*"))
19916 (when combine
19917 (setq ical-file
19918 (if (file-name-absolute-p org-combined-agenda-icalendar-file)
19919 org-combined-agenda-icalendar-file
19920 (expand-file-name org-combined-agenda-icalendar-file dir))
19921 ical-buffer (org-get-agenda-file-buffer ical-file))
19922 (set-buffer ical-buffer) (erase-buffer))
19923 (while (setq file (pop files))
19924 (catch 'nextfile
19925 (org-check-agenda-file file)
19926 (set-buffer (org-get-agenda-file-buffer file))
19927 (unless combine
19928 (setq ical-file (concat (file-name-as-directory dir)
19929 (file-name-sans-extension
19930 (file-name-nondirectory buffer-file-name))
19931 ".ics"))
19932 (setq ical-buffer (org-get-agenda-file-buffer ical-file))
19933 (with-current-buffer ical-buffer (erase-buffer)))
19934 (setq category (or org-category
19935 (file-name-sans-extension
19936 (file-name-nondirectory buffer-file-name))))
19937 (if (symbolp category) (setq category (symbol-name category)))
19938 (let ((standard-output ical-buffer))
19939 (if combine
19940 (and (not started) (setq started t)
19941 (org-start-icalendar-file org-icalendar-combined-name))
19942 (org-start-icalendar-file category))
19943 (org-print-icalendar-entries combine)
19944 (when (or (and combine (not files)) (not combine))
19945 (org-finish-icalendar-file)
19946 (set-buffer ical-buffer)
19947 (save-buffer)
19948 (run-hooks 'org-after-save-iCalendar-file-hook)))))
19949 (org-release-buffers org-agenda-new-buffers))))
19951 (defvar org-after-save-iCalendar-file-hook nil
19952 "Hook run after an iCalendar file has been saved.
19953 The iCalendar buffer is still current when this hook is run.
19954 A good way to use this is to tell a desktop calenndar application to re-read
19955 the iCalendar file.")
19957 (defun org-print-icalendar-entries (&optional combine)
19958 "Print iCalendar entries for the current Org-mode file to `standard-output'.
19959 When COMBINE is non nil, add the category to each line."
19960 (let ((re1 (concat org-ts-regexp "\\|<%%([^>\n]+>"))
19961 (re2 (concat "--?-?\\(" org-ts-regexp "\\)"))
19962 (org-category-table (org-get-category-table))
19963 (dts (org-ical-ts-to-string
19964 (format-time-string (cdr org-time-stamp-formats) (current-time))
19965 "DTSTART"))
19966 hd ts ts2 state status (inc t) pos b sexp rrule
19967 scheduledp deadlinep tmp pri category
19968 (sexp-buffer (get-buffer-create "*ical-tmp*")))
19969 (save-excursion
19970 (goto-char (point-min))
19971 (while (re-search-forward re1 nil t)
19972 (catch :skip
19973 (org-agenda-skip)
19974 (setq pos (match-beginning 0)
19975 ts (match-string 0)
19976 inc t
19977 hd (org-get-heading)
19978 category (org-get-category))
19979 (if (looking-at re2)
19980 (progn
19981 (goto-char (match-end 0))
19982 (setq ts2 (match-string 1) inc nil))
19983 (setq ts2 ts
19984 tmp (buffer-substring (max (point-min)
19985 (- pos org-ds-keyword-length))
19986 pos)
19987 deadlinep (string-match org-deadline-regexp tmp)
19988 scheduledp (string-match org-scheduled-regexp tmp)
19989 ;; donep (org-entry-is-done-p)
19991 (if (or (string-match org-tr-regexp hd)
19992 (string-match org-ts-regexp hd))
19993 (setq hd (replace-match "" t t hd)))
19994 (if (string-match "\\+\\([0-9]+\\)\\([dwmy]\\)>" ts)
19995 (setq rrule
19996 (concat "\nRRULE:FREQ="
19997 (cdr (assoc
19998 (match-string 2 ts)
19999 '(("d" . "DAILY")("w" . "WEEKLY")
20000 ("m" . "MONTHLY")("y" . "YEARLY"))))
20001 ";INTERVAL=" (match-string 1 ts)))
20002 (setq rrule ""))
20003 (if (string-match org-bracket-link-regexp hd)
20004 (setq hd (replace-match (if (match-end 3) (match-string 3 hd)
20005 (match-string 1 hd))
20006 t t hd)))
20007 (if deadlinep (setq hd (concat "DL: " hd)))
20008 (if scheduledp (setq hd (concat "S: " hd)))
20009 (if (string-match "\\`<%%" ts)
20010 (with-current-buffer sexp-buffer
20011 (insert (substring ts 1 -1) " " hd "\n"))
20012 (princ (format "BEGIN:VEVENT
20014 %s%s
20015 SUMMARY:%s
20016 CATEGORIES:%s
20017 END:VEVENT\n"
20018 (org-ical-ts-to-string ts "DTSTART")
20019 (org-ical-ts-to-string ts2 "DTEND" inc)
20020 rrule hd category)))))
20022 (when (and org-icalendar-include-sexps
20023 (condition-case nil (require 'icalendar) (error nil))
20024 (fboundp 'icalendar-export-region))
20025 ;; Get all the literal sexps
20026 (goto-char (point-min))
20027 (while (re-search-forward "^&?%%(" nil t)
20028 (catch :skip
20029 (org-agenda-skip)
20030 (setq b (match-beginning 0))
20031 (goto-char (1- (match-end 0)))
20032 (forward-sexp 1)
20033 (end-of-line 1)
20034 (setq sexp (buffer-substring b (point)))
20035 (with-current-buffer sexp-buffer
20036 (insert sexp "\n"))
20037 (princ (org-diary-to-ical-string sexp-buffer)))))
20039 (when org-icalendar-include-todo
20040 (goto-char (point-min))
20041 (while (re-search-forward org-todo-line-regexp nil t)
20042 (catch :skip
20043 (org-agenda-skip)
20044 (setq state (match-string 2))
20045 (setq status (if (member state org-done-keywords)
20046 "COMPLETED" "NEEDS-ACTION"))
20047 (when (and state
20048 (or (not (member state org-done-keywords))
20049 (eq org-icalendar-include-todo 'all))
20050 (not (member org-archive-tag (org-get-tags-at)))
20052 (setq hd (match-string 3))
20053 (if (string-match org-bracket-link-regexp hd)
20054 (setq hd (replace-match (if (match-end 3) (match-string 3 hd)
20055 (match-string 1 hd))
20056 t t hd)))
20057 (if (string-match org-priority-regexp hd)
20058 (setq pri (string-to-char (match-string 2 hd))
20059 hd (concat (substring hd 0 (match-beginning 1))
20060 (substring hd (match-end 1))))
20061 (setq pri org-default-priority))
20062 (setq pri (floor (1+ (* 8. (/ (float (- org-lowest-priority pri))
20063 (- org-lowest-priority org-highest-priority))))))
20065 (princ (format "BEGIN:VTODO
20067 SUMMARY:%s
20068 CATEGORIES:%s
20069 SEQUENCE:1
20070 PRIORITY:%d
20071 STATUS:%s
20072 END:VTODO\n"
20073 dts hd category pri status)))))))))
20075 (defun org-start-icalendar-file (name)
20076 "Start an iCalendar file by inserting the header."
20077 (let ((user user-full-name)
20078 (name (or name "unknown"))
20079 (timezone (cadr (current-time-zone))))
20080 (princ
20081 (format "BEGIN:VCALENDAR
20082 VERSION:2.0
20083 X-WR-CALNAME:%s
20084 PRODID:-//%s//Emacs with Org-mode//EN
20085 X-WR-TIMEZONE:%s
20086 CALSCALE:GREGORIAN\n" name user timezone))))
20088 (defun org-finish-icalendar-file ()
20089 "Finish an iCalendar file by inserting the END statement."
20090 (princ "END:VCALENDAR\n"))
20092 (defun org-ical-ts-to-string (s keyword &optional inc)
20093 "Take a time string S and convert it to iCalendar format.
20094 KEYWORD is added in front, to make a complete line like DTSTART....
20095 When INC is non-nil, increase the hour by two (if time string contains
20096 a time), or the day by one (if it does not contain a time)."
20097 (let ((t1 (org-parse-time-string s 'nodefault))
20098 t2 fmt have-time time)
20099 (if (and (car t1) (nth 1 t1) (nth 2 t1))
20100 (setq t2 t1 have-time t)
20101 (setq t2 (org-parse-time-string s)))
20102 (let ((s (car t2)) (mi (nth 1 t2)) (h (nth 2 t2))
20103 (d (nth 3 t2)) (m (nth 4 t2)) (y (nth 5 t2)))
20104 (when inc
20105 (if have-time (setq h (+ 2 h)) (setq d (1+ d))))
20106 (setq time (encode-time s mi h d m y)))
20107 (setq fmt (if have-time ":%Y%m%dT%H%M%S" ";VALUE=DATE:%Y%m%d"))
20108 (concat keyword (format-time-string fmt time))))
20110 ;;; XOXO export
20112 (defun org-export-as-xoxo-insert-into (buffer &rest output)
20113 (with-current-buffer buffer
20114 (apply 'insert output)))
20115 (put 'org-export-as-xoxo-insert-into 'lisp-indent-function 1)
20117 (defun org-export-as-xoxo (&optional buffer)
20118 "Export the org buffer as XOXO.
20119 The XOXO buffer is named *xoxo-<source buffer name>*"
20120 (interactive (list (current-buffer)))
20121 ;; A quickie abstraction
20123 ;; Output everything as XOXO
20124 (with-current-buffer (get-buffer buffer)
20125 (goto-char (point-min)) ;; CD: beginning-of-buffer is not allowed.
20126 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
20127 (org-infile-export-plist)))
20128 (filename (concat (file-name-as-directory
20129 (org-export-directory :xoxo opt-plist))
20130 (file-name-sans-extension
20131 (file-name-nondirectory buffer-file-name))
20132 ".html"))
20133 (out (find-file-noselect filename))
20134 (last-level 1)
20135 (hanging-li nil))
20136 ;; Check the output buffer is empty.
20137 (with-current-buffer out (erase-buffer))
20138 ;; Kick off the output
20139 (org-export-as-xoxo-insert-into out "<ol class='xoxo'>\n")
20140 (while (re-search-forward "^\\(\\*+\\) \\(.+\\)" (point-max) 't)
20141 (let* ((hd (match-string-no-properties 1))
20142 (level (length hd))
20143 (text (concat
20144 (match-string-no-properties 2)
20145 (save-excursion
20146 (goto-char (match-end 0))
20147 (let ((str ""))
20148 (catch 'loop
20149 (while 't
20150 (forward-line)
20151 (if (looking-at "^[ \t]\\(.*\\)")
20152 (setq str (concat str (match-string-no-properties 1)))
20153 (throw 'loop str)))))))))
20155 ;; Handle level rendering
20156 (cond
20157 ((> level last-level)
20158 (org-export-as-xoxo-insert-into out "\n<ol>\n"))
20160 ((< level last-level)
20161 (dotimes (- (- last-level level) 1)
20162 (if hanging-li
20163 (org-export-as-xoxo-insert-into out "</li>\n"))
20164 (org-export-as-xoxo-insert-into out "</ol>\n"))
20165 (when hanging-li
20166 (org-export-as-xoxo-insert-into out "</li>\n")
20167 (setq hanging-li nil)))
20169 ((equal level last-level)
20170 (if hanging-li
20171 (org-export-as-xoxo-insert-into out "</li>\n")))
20174 (setq last-level level)
20176 ;; And output the new li
20177 (setq hanging-li 't)
20178 (if (equal ?+ (elt text 0))
20179 (org-export-as-xoxo-insert-into out "<li class='" (substring text 1) "'>")
20180 (org-export-as-xoxo-insert-into out "<li>" text))))
20182 ;; Finally finish off the ol
20183 (dotimes (- last-level 1)
20184 (if hanging-li
20185 (org-export-as-xoxo-insert-into out "</li>\n"))
20186 (org-export-as-xoxo-insert-into out "</ol>\n"))
20188 ;; Finish the buffer off and clean it up.
20189 (switch-to-buffer-other-window out)
20190 (indent-region (point-min) (point-max) nil)
20191 (save-buffer)
20192 (goto-char (point-min))
20196 ;;;; Key bindings
20198 ;; Make `C-c C-x' a prefix key
20199 (org-defkey org-mode-map "\C-c\C-x" (make-sparse-keymap))
20201 ;; TAB key with modifiers
20202 (org-defkey org-mode-map "\C-i" 'org-cycle)
20203 (org-defkey org-mode-map [(tab)] 'org-cycle)
20204 (org-defkey org-mode-map [(control tab)] 'org-force-cycle-archived)
20205 (org-defkey org-mode-map [(meta tab)] 'org-complete)
20206 (org-defkey org-mode-map "\M-\t" 'org-complete)
20207 (org-defkey org-mode-map "\M-\C-i" 'org-complete)
20208 ;; The following line is necessary under Suse GNU/Linux
20209 (unless (featurep 'xemacs)
20210 (org-defkey org-mode-map [S-iso-lefttab] 'org-shifttab))
20211 (org-defkey org-mode-map [(shift tab)] 'org-shifttab)
20212 (define-key org-mode-map (kbd "<backtab>") 'org-shifttab)
20214 (org-defkey org-mode-map [(shift return)] 'org-table-copy-down)
20215 (org-defkey org-mode-map [(meta shift return)] 'org-insert-todo-heading)
20216 (org-defkey org-mode-map [(meta return)] 'org-meta-return)
20218 ;; Cursor keys with modifiers
20219 (org-defkey org-mode-map [(meta left)] 'org-metaleft)
20220 (org-defkey org-mode-map [(meta right)] 'org-metaright)
20221 (org-defkey org-mode-map [(meta up)] 'org-metaup)
20222 (org-defkey org-mode-map [(meta down)] 'org-metadown)
20224 (org-defkey org-mode-map [(meta shift left)] 'org-shiftmetaleft)
20225 (org-defkey org-mode-map [(meta shift right)] 'org-shiftmetaright)
20226 (org-defkey org-mode-map [(meta shift up)] 'org-shiftmetaup)
20227 (org-defkey org-mode-map [(meta shift down)] 'org-shiftmetadown)
20229 (org-defkey org-mode-map [(shift up)] 'org-shiftup)
20230 (org-defkey org-mode-map [(shift down)] 'org-shiftdown)
20231 (org-defkey org-mode-map [(shift left)] 'org-shiftleft)
20232 (org-defkey org-mode-map [(shift right)] 'org-shiftright)
20234 (org-defkey org-mode-map [(control shift right)] 'org-shiftcontrolright)
20235 (org-defkey org-mode-map [(control shift left)] 'org-shiftcontrolleft)
20237 ;;; Extra keys for tty access.
20238 ;; We only set them when really needed because otherwise the
20239 ;; menus don't show the simple keys
20241 (when (or (featurep 'xemacs) ;; because XEmacs supports multi-device stuff
20242 (not window-system))
20243 (org-defkey org-mode-map "\C-c\C-xc" 'org-table-copy-down)
20244 (org-defkey org-mode-map "\C-c\C-xM" 'org-insert-todo-heading)
20245 (org-defkey org-mode-map "\C-c\C-xm" 'org-meta-return)
20246 (org-defkey org-mode-map [?\e (return)] 'org-meta-return)
20247 (org-defkey org-mode-map [?\e (left)] 'org-metaleft)
20248 (org-defkey org-mode-map "\C-c\C-xl" 'org-metaleft)
20249 (org-defkey org-mode-map [?\e (right)] 'org-metaright)
20250 (org-defkey org-mode-map "\C-c\C-xr" 'org-metaright)
20251 (org-defkey org-mode-map [?\e (up)] 'org-metaup)
20252 (org-defkey org-mode-map "\C-c\C-xu" 'org-metaup)
20253 (org-defkey org-mode-map [?\e (down)] 'org-metadown)
20254 (org-defkey org-mode-map "\C-c\C-xd" 'org-metadown)
20255 (org-defkey org-mode-map "\C-c\C-xL" 'org-shiftmetaleft)
20256 (org-defkey org-mode-map "\C-c\C-xR" 'org-shiftmetaright)
20257 (org-defkey org-mode-map "\C-c\C-xU" 'org-shiftmetaup)
20258 (org-defkey org-mode-map "\C-c\C-xD" 'org-shiftmetadown)
20259 (org-defkey org-mode-map [?\C-c (up)] 'org-shiftup)
20260 (org-defkey org-mode-map [?\C-c (down)] 'org-shiftdown)
20261 (org-defkey org-mode-map [?\C-c (left)] 'org-shiftleft)
20262 (org-defkey org-mode-map [?\C-c (right)] 'org-shiftright)
20263 (org-defkey org-mode-map [?\C-c ?\C-x (right)] 'org-shiftcontrolright)
20264 (org-defkey org-mode-map [?\C-c ?\C-x (left)] 'org-shiftcontrolleft))
20266 ;; All the other keys
20268 (org-defkey org-mode-map "\C-c\C-a" 'show-all) ; in case allout messed up.
20269 (org-defkey org-mode-map "\C-c\C-r" 'org-reveal)
20270 (org-defkey org-mode-map "\C-xns" 'org-narrow-to-subtree)
20271 (org-defkey org-mode-map "\C-c$" 'org-archive-subtree)
20272 (org-defkey org-mode-map "\C-c\C-x\C-s" 'org-advertized-archive-subtree)
20273 (org-defkey org-mode-map "\C-c\C-x\C-a" 'org-toggle-archive-tag)
20274 (org-defkey org-mode-map "\C-c\C-xb" 'org-tree-to-indirect-buffer)
20275 (org-defkey org-mode-map "\C-c\C-j" 'org-goto)
20276 (org-defkey org-mode-map "\C-c\C-t" 'org-todo)
20277 (org-defkey org-mode-map "\C-c\C-s" 'org-schedule)
20278 (org-defkey org-mode-map "\C-c\C-d" 'org-deadline)
20279 (org-defkey org-mode-map "\C-c;" 'org-toggle-comment)
20280 (org-defkey org-mode-map "\C-c\C-v" 'org-show-todo-tree)
20281 (org-defkey org-mode-map "\C-c\C-w" 'org-check-deadlines)
20282 (org-defkey org-mode-map "\C-c/" 'org-occur) ; Minor-mode reserved
20283 (org-defkey org-mode-map "\C-c\\" 'org-tags-sparse-tree) ; Minor-mode res.
20284 (org-defkey org-mode-map "\C-c\C-m" 'org-ctrl-c-ret)
20285 (org-defkey org-mode-map "\M-\C-m" 'org-insert-heading)
20286 (org-defkey org-mode-map "\C-c\C-x\C-n" 'org-next-link)
20287 (org-defkey org-mode-map "\C-c\C-x\C-p" 'org-previous-link)
20288 (org-defkey org-mode-map "\C-c\C-l" 'org-insert-link)
20289 (org-defkey org-mode-map "\C-c\C-o" 'org-open-at-point)
20290 (org-defkey org-mode-map "\C-c%" 'org-mark-ring-push)
20291 (org-defkey org-mode-map "\C-c&" 'org-mark-ring-goto)
20292 (org-defkey org-mode-map "\C-c\C-z" 'org-time-stamp) ; Alternative binding
20293 (org-defkey org-mode-map "\C-c." 'org-time-stamp) ; Minor-mode reserved
20294 (org-defkey org-mode-map "\C-c!" 'org-time-stamp-inactive) ; Minor-mode r.
20295 (org-defkey org-mode-map "\C-c," 'org-priority) ; Minor-mode reserved
20296 (org-defkey org-mode-map "\C-c\C-y" 'org-evaluate-time-range)
20297 (org-defkey org-mode-map "\C-c>" 'org-goto-calendar)
20298 (org-defkey org-mode-map "\C-c<" 'org-date-from-calendar)
20299 (org-defkey org-mode-map [(control ?,)] 'org-cycle-agenda-files)
20300 (org-defkey org-mode-map [(control ?\')] 'org-cycle-agenda-files)
20301 (org-defkey org-mode-map "\C-c[" 'org-agenda-file-to-front)
20302 (org-defkey org-mode-map "\C-c]" 'org-remove-file)
20303 (org-defkey org-mode-map "\C-c-" 'org-table-insert-hline)
20304 (org-defkey org-mode-map "\C-c^" 'org-sort)
20305 (org-defkey org-mode-map "\C-c\C-c" 'org-ctrl-c-ctrl-c)
20306 (org-defkey org-mode-map "\C-c#" 'org-update-checkbox-count)
20307 (org-defkey org-mode-map "\C-m" 'org-return)
20308 (org-defkey org-mode-map "\C-c?" 'org-table-field-info)
20309 (org-defkey org-mode-map "\C-c " 'org-table-blank-field)
20310 (org-defkey org-mode-map "\C-c+" 'org-table-sum)
20311 (org-defkey org-mode-map "\C-c=" 'org-table-eval-formula)
20312 (org-defkey org-mode-map "\C-c'" 'org-table-edit-formulas)
20313 (org-defkey org-mode-map "\C-c`" 'org-table-edit-field)
20314 (org-defkey org-mode-map "\C-c|" 'org-table-create-or-convert-from-region)
20315 (org-defkey org-mode-map "\C-c*" 'org-table-recalculate)
20316 (org-defkey org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks)
20317 (org-defkey org-mode-map "\C-c~" 'org-table-create-with-table.el)
20318 (org-defkey org-mode-map "\C-c\C-q" 'org-table-wrap-region)
20319 (org-defkey org-mode-map "\C-c}" 'org-table-toggle-coordinate-overlays)
20320 (org-defkey org-mode-map "\C-c{" 'org-table-toggle-formula-debugger)
20321 (org-defkey org-mode-map "\C-c\C-e" 'org-export)
20322 (org-defkey org-mode-map "\C-c:" 'org-toggle-fixed-width-section)
20323 (org-defkey org-mode-map "\C-c\C-x\C-f" 'org-emphasize)
20325 (org-defkey org-mode-map "\C-c\C-x\C-k" 'org-cut-special)
20326 (org-defkey org-mode-map "\C-c\C-x\C-w" 'org-cut-special)
20327 (org-defkey org-mode-map "\C-c\C-x\M-w" 'org-copy-special)
20328 (org-defkey org-mode-map "\C-c\C-x\C-y" 'org-paste-special)
20330 (org-defkey org-mode-map "\C-c\C-x\C-t" 'org-toggle-time-stamp-overlays)
20331 (org-defkey org-mode-map "\C-c\C-x\C-i" 'org-clock-in)
20332 (org-defkey org-mode-map "\C-c\C-x\C-o" 'org-clock-out)
20333 (org-defkey org-mode-map "\C-c\C-x\C-x" 'org-clock-cancel)
20334 (org-defkey org-mode-map "\C-c\C-x\C-d" 'org-clock-display)
20335 (org-defkey org-mode-map "\C-c\C-x\C-r" 'org-clock-report)
20336 (org-defkey org-mode-map "\C-c\C-x\C-u" 'org-dblock-update)
20337 (org-defkey org-mode-map "\C-c\C-x\C-l" 'org-preview-latex-fragment)
20338 (org-defkey org-mode-map "\C-c\C-x\C-b" 'org-toggle-checkbox)
20340 (when (featurep 'xemacs)
20341 (org-defkey org-mode-map 'button3 'popup-mode-menu))
20343 (defsubst org-table-p () (org-at-table-p))
20345 (defun org-self-insert-command (N)
20346 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
20347 If the cursor is in a table looking at whitespace, the whitespace is
20348 overwritten, and the table is not marked as requiring realignment."
20349 (interactive "p")
20350 (if (and (org-table-p)
20351 (progn
20352 ;; check if we blank the field, and if that triggers align
20353 (and org-table-auto-blank-field
20354 (member last-command
20355 '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c))
20356 (if (or (equal (char-after) ?\ ) (looking-at "[^|\n]* |"))
20357 ;; got extra space, this field does not determine column width
20358 (let (org-table-may-need-update) (org-table-blank-field))
20359 ;; no extra space, this field may determine column width
20360 (org-table-blank-field)))
20362 (eq N 1)
20363 (looking-at "[^|\n]* |"))
20364 (let (org-table-may-need-update)
20365 (goto-char (1- (match-end 0)))
20366 (delete-backward-char 1)
20367 (goto-char (match-beginning 0))
20368 (self-insert-command N))
20369 (setq org-table-may-need-update t)
20370 (self-insert-command N)))
20372 (defun org-delete-backward-char (N)
20373 "Like `delete-backward-char', insert whitespace at field end in tables.
20374 When deleting backwards, in tables this function will insert whitespace in
20375 front of the next \"|\" separator, to keep the table aligned. The table will
20376 still be marked for re-alignment if the field did fill the entire column,
20377 because, in this case the deletion might narrow the column."
20378 (interactive "p")
20379 (if (and (org-table-p)
20380 (eq N 1)
20381 (string-match "|" (buffer-substring (point-at-bol) (point)))
20382 (looking-at ".*?|"))
20383 (let ((pos (point))
20384 (noalign (looking-at "[^|\n\r]* |"))
20385 (c org-table-may-need-update))
20386 (backward-delete-char N)
20387 (skip-chars-forward "^|")
20388 (insert " ")
20389 (goto-char (1- pos))
20390 ;; noalign: if there were two spaces at the end, this field
20391 ;; does not determine the width of the column.
20392 (if noalign (setq org-table-may-need-update c)))
20393 (backward-delete-char N)))
20395 (defun org-delete-char (N)
20396 "Like `delete-char', but insert whitespace at field end in tables.
20397 When deleting characters, in tables this function will insert whitespace in
20398 front of the next \"|\" separator, to keep the table aligned. The table will
20399 still be marked for re-alignment if the field did fill the entire column,
20400 because, in this case the deletion might narrow the column."
20401 (interactive "p")
20402 (if (and (org-table-p)
20403 (not (bolp))
20404 (not (= (char-after) ?|))
20405 (eq N 1))
20406 (if (looking-at ".*?|")
20407 (let ((pos (point))
20408 (noalign (looking-at "[^|\n\r]* |"))
20409 (c org-table-may-need-update))
20410 (replace-match (concat
20411 (substring (match-string 0) 1 -1)
20412 " |"))
20413 (goto-char pos)
20414 ;; noalign: if there were two spaces at the end, this field
20415 ;; does not determine the width of the column.
20416 (if noalign (setq org-table-may-need-update c)))
20417 (delete-char N))
20418 (delete-char N)))
20420 ;; Make `delete-selection-mode' work with org-mode and orgtbl-mode
20421 (put 'org-self-insert-command 'delete-selection t)
20422 (put 'orgtbl-self-insert-command 'delete-selection t)
20423 (put 'org-delete-char 'delete-selection 'supersede)
20424 (put 'org-delete-backward-char 'delete-selection 'supersede)
20426 ;; Make `flyspell-mode' delay after some commands
20427 (put 'org-self-insert-command 'flyspell-delayed t)
20428 (put 'orgtbl-self-insert-command 'flyspell-delayed t)
20429 (put 'org-delete-char 'flyspell-delayed t)
20430 (put 'org-delete-backward-char 'flyspell-delayed t)
20432 ;; How to do this: Measure non-white length of current string
20433 ;; If equal to column width, we should realign.
20435 (defun org-remap (map &rest commands)
20436 "In MAP, remap the functions given in COMMANDS.
20437 COMMANDS is a list of alternating OLDDEF NEWDEF command names."
20438 (let (new old)
20439 (while commands
20440 (setq old (pop commands) new (pop commands))
20441 (if (fboundp 'command-remapping)
20442 (org-defkey map (vector 'remap old) new)
20443 (substitute-key-definition old new map global-map)))))
20445 (when (eq org-enable-table-editor 'optimized)
20446 ;; If the user wants maximum table support, we need to hijack
20447 ;; some standard editing functions
20448 (org-remap org-mode-map
20449 'self-insert-command 'org-self-insert-command
20450 'delete-char 'org-delete-char
20451 'delete-backward-char 'org-delete-backward-char)
20452 (org-defkey org-mode-map "|" 'org-force-self-insert))
20454 (defun org-shiftcursor-error ()
20455 "Throw an error because Shift-Cursor command was applied in wrong context."
20456 (error "This command is active in special context like tables, headlines or timestamps"))
20458 (defun org-shifttab (&optional arg)
20459 "Global visibility cycling or move to previous table field.
20460 Calls `org-cycle' with argument t, or `org-table-previous-field', depending
20461 on context.
20462 See the individual commands for more information."
20463 (interactive "P")
20464 (cond
20465 ((org-at-table-p) (call-interactively 'org-table-previous-field))
20466 (arg (message "Content view to level: ")
20467 (org-content (prefix-numeric-value arg))
20468 (setq org-cycle-global-status 'overview))
20469 (t (call-interactively 'org-global-cycle))))
20471 (defun org-shiftmetaleft ()
20472 "Promote subtree or delete table column.
20473 Calls `org-promote-subtree', `org-outdent-item',
20474 or `org-table-delete-column', depending on context.
20475 See the individual commands for more information."
20476 (interactive)
20477 (cond
20478 ((org-at-table-p) (call-interactively 'org-table-delete-column))
20479 ((org-on-heading-p) (call-interactively 'org-promote-subtree))
20480 ((org-at-item-p) (call-interactively 'org-outdent-item))
20481 (t (org-shiftcursor-error))))
20483 (defun org-shiftmetaright ()
20484 "Demote subtree or insert table column.
20485 Calls `org-demote-subtree', `org-indent-item',
20486 or `org-table-insert-column', depending on context.
20487 See the individual commands for more information."
20488 (interactive)
20489 (cond
20490 ((org-at-table-p) (call-interactively 'org-table-insert-column))
20491 ((org-on-heading-p) (call-interactively 'org-demote-subtree))
20492 ((org-at-item-p) (call-interactively 'org-indent-item))
20493 (t (org-shiftcursor-error))))
20495 (defun org-shiftmetaup (&optional arg)
20496 "Move subtree up or kill table row.
20497 Calls `org-move-subtree-up' or `org-table-kill-row' or
20498 `org-move-item-up' depending on context. See the individual commands
20499 for more information."
20500 (interactive "P")
20501 (cond
20502 ((org-at-table-p) (call-interactively 'org-table-kill-row))
20503 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
20504 ((org-at-item-p) (call-interactively 'org-move-item-up))
20505 (t (org-shiftcursor-error))))
20506 (defun org-shiftmetadown (&optional arg)
20507 "Move subtree down or insert table row.
20508 Calls `org-move-subtree-down' or `org-table-insert-row' or
20509 `org-move-item-down', depending on context. See the individual
20510 commands for more information."
20511 (interactive "P")
20512 (cond
20513 ((org-at-table-p) (call-interactively 'org-table-insert-row))
20514 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
20515 ((org-at-item-p) (call-interactively 'org-move-item-down))
20516 (t (org-shiftcursor-error))))
20518 (defun org-metaleft (&optional arg)
20519 "Promote heading or move table column to left.
20520 Calls `org-do-promote' or `org-table-move-column', depending on context.
20521 With no specific context, calls the Emacs default `backward-word'.
20522 See the individual commands for more information."
20523 (interactive "P")
20524 (cond
20525 ((org-at-table-p) (org-call-with-arg 'org-table-move-column 'left))
20526 ((or (org-on-heading-p) (org-region-active-p))
20527 (call-interactively 'org-do-promote))
20528 ((org-at-item-p) (call-interactively 'org-outdent-item))
20529 (t (call-interactively 'backward-word))))
20531 (defun org-metaright (&optional arg)
20532 "Demote subtree or move table column to right.
20533 Calls `org-do-demote' or `org-table-move-column', depending on context.
20534 With no specific context, calls the Emacs default `forward-word'.
20535 See the individual commands for more information."
20536 (interactive "P")
20537 (cond
20538 ((org-at-table-p) (call-interactively 'org-table-move-column))
20539 ((or (org-on-heading-p) (org-region-active-p))
20540 (call-interactively 'org-do-demote))
20541 ((org-at-item-p) (call-interactively 'org-indent-item))
20542 (t (call-interactively 'forward-word))))
20544 (defun org-metaup (&optional arg)
20545 "Move subtree up or move table row up.
20546 Calls `org-move-subtree-up' or `org-table-move-row' or
20547 `org-move-item-up', depending on context. See the individual commands
20548 for more information."
20549 (interactive "P")
20550 (cond
20551 ((org-at-table-p) (org-call-with-arg 'org-table-move-row 'up))
20552 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
20553 ((org-at-item-p) (call-interactively 'org-move-item-up))
20554 (t (org-shiftcursor-error))))
20556 (defun org-metadown (&optional arg)
20557 "Move subtree down or move table row down.
20558 Calls `org-move-subtree-down' or `org-table-move-row' or
20559 `org-move-item-down', depending on context. See the individual
20560 commands for more information."
20561 (interactive "P")
20562 (cond
20563 ((org-at-table-p) (call-interactively 'org-table-move-row))
20564 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
20565 ((org-at-item-p) (call-interactively 'org-move-item-down))
20566 (t (org-shiftcursor-error))))
20568 (defun org-shiftup (&optional arg)
20569 "Increase item in timestamp or increase priority of current headline.
20570 Calls `org-timestamp-up' or `org-priority-up', or `org-previous-item',
20571 depending on context. See the individual commands for more information."
20572 (interactive "P")
20573 (cond
20574 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-up))
20575 ((org-on-heading-p) (call-interactively 'org-priority-up))
20576 ((org-at-item-p) (call-interactively 'org-previous-item))
20577 (t (call-interactively 'org-beginning-of-item) (beginning-of-line 1))))
20579 (defun org-shiftdown (&optional arg)
20580 "Decrease item in timestamp or decrease priority of current headline.
20581 Calls `org-timestamp-down' or `org-priority-down', or `org-next-item'
20582 depending on context. See the individual commands for more information."
20583 (interactive "P")
20584 (cond
20585 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-down))
20586 ((org-on-heading-p) (call-interactively 'org-priority-down))
20587 (t (call-interactively 'org-next-item))))
20589 (defun org-shiftright ()
20590 "Next TODO keyword or timestamp one day later, depending on context."
20591 (interactive)
20592 (cond
20593 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-up-day))
20594 ((org-on-heading-p) (org-call-with-arg 'org-todo 'right))
20595 (t (org-shiftcursor-error))))
20597 (defun org-shiftleft ()
20598 "Previous TODO keyword or timestamp one day earlier, depending on context."
20599 (interactive)
20600 (cond
20601 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-down-day))
20602 ((org-on-heading-p) (org-call-with-arg 'org-todo 'left))
20603 (t (org-shiftcursor-error))))
20605 (defun org-shiftcontrolright ()
20606 "Switch to next TODO set."
20607 (interactive)
20608 (cond
20609 ((org-on-heading-p) (org-call-with-arg 'org-todo 'nextset))
20610 (t (org-shiftcursor-error))))
20612 (defun org-shiftcontrolleft ()
20613 "Switch to previous TODO set."
20614 (interactive)
20615 (cond
20616 ((org-on-heading-p) (org-call-with-arg 'org-todo 'previousset))
20617 (t (org-shiftcursor-error))))
20619 (defun org-ctrl-c-ret ()
20620 "Call `org-table-hline-and-move' or `org-insert-heading' dep. on context."
20621 (interactive)
20622 (cond
20623 ((org-at-table-p) (call-interactively 'org-table-hline-and-move))
20624 (t (call-interactively 'org-insert-heading))))
20626 (defun org-copy-special ()
20627 "Copy region in table or copy current subtree.
20628 Calls `org-table-copy' or `org-copy-subtree', depending on context.
20629 See the individual commands for more information."
20630 (interactive)
20631 (call-interactively
20632 (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree)))
20634 (defun org-cut-special ()
20635 "Cut region in table or cut current subtree.
20636 Calls `org-table-copy' or `org-cut-subtree', depending on context.
20637 See the individual commands for more information."
20638 (interactive)
20639 (call-interactively
20640 (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree)))
20642 (defun org-paste-special (arg)
20643 "Paste rectangular region into table, or past subtree relative to level.
20644 Calls `org-table-paste-rectangle' or `org-paste-subtree', depending on context.
20645 See the individual commands for more information."
20646 (interactive "P")
20647 (if (org-at-table-p)
20648 (org-table-paste-rectangle)
20649 (org-paste-subtree arg)))
20651 (defun org-ctrl-c-ctrl-c (&optional arg)
20652 "Set tags in headline, or update according to changed information at point.
20654 This command does many different things, depending on context:
20656 - If the cursor is in a headline, prompt for tags and insert them
20657 into the current line, aligned to `org-tags-column'. When called
20658 with prefix arg, realign all tags in the current buffer.
20660 - If the cursor is in one of the special #+KEYWORD lines, this
20661 triggers scanning the buffer for these lines and updating the
20662 information.
20664 - If the cursor is inside a table, realign the table. This command
20665 works even if the automatic table editor has been turned off.
20667 - If the cursor is on a #+TBLFM line, re-apply the formulas to
20668 the entire table.
20670 - If the cursor is inside a table created by the table.el package,
20671 activate that table.
20673 - If the current buffer is a remember buffer, close note and file it.
20674 with a prefix argument, file it without further interaction to the default
20675 location.
20677 - If the cursor is on a <<<target>>>, update radio targets and corresponding
20678 links in this buffer.
20680 - If the cursor is on a numbered item in a plain list, renumber the
20681 ordered list."
20682 (interactive "P")
20683 (let ((org-enable-table-editor t))
20684 (cond
20685 ((or org-clock-overlays
20686 org-occur-highlights
20687 org-latex-fragment-image-overlays)
20688 (org-remove-clock-overlays)
20689 (org-remove-occur-highlights)
20690 (org-remove-latex-fragment-image-overlays)
20691 (message "Temporary highlights/overlays removed from current buffer"))
20692 ((and (local-variable-p 'org-finish-function (current-buffer))
20693 (fboundp org-finish-function))
20694 (funcall org-finish-function))
20695 ((org-on-target-p) (call-interactively 'org-update-radio-target-regexp))
20696 ((org-on-heading-p) (call-interactively 'org-set-tags))
20697 ((org-at-table.el-p)
20698 (require 'table)
20699 (beginning-of-line 1)
20700 (re-search-forward "|" (save-excursion (end-of-line 2) (point)))
20701 (call-interactively 'table-recognize-table))
20702 ((org-at-table-p)
20703 (org-table-maybe-eval-formula)
20704 (if arg
20705 (call-interactively 'org-table-recalculate)
20706 (org-table-maybe-recalculate-line))
20707 (call-interactively 'org-table-align))
20708 ((org-at-item-checkbox-p)
20709 (call-interactively 'org-toggle-checkbox))
20710 ((org-at-item-p)
20711 (call-interactively 'org-renumber-ordered-list))
20712 ((save-excursion (beginning-of-line 1) (looking-at "#\\+\\([A-Z]+\\)"))
20713 (cond
20714 ((equal (match-string 1) "TBLFM")
20715 ;; Recalculate the table before this line
20716 (save-excursion
20717 (beginning-of-line 1)
20718 (skip-chars-backward " \r\n\t")
20719 (if (org-at-table-p)
20720 (org-call-with-arg 'org-table-recalculate t))))
20722 (call-interactively 'org-mode-restart))))
20723 (t (error "C-c C-c can do nothing useful at this location.")))))
20725 (defun org-mode-restart ()
20726 "Restart Org-mode, to scan again for special lines.
20727 Also updates the keyword regular expressions."
20728 (interactive)
20729 (let ((org-inhibit-startup t)) (org-mode))
20730 (message "Org-mode restarted to refresh keyword and special line setup"))
20732 (defun org-return ()
20733 "Goto next table row or insert a newline.
20734 Calls `org-table-next-row' or `newline', depending on context.
20735 See the individual commands for more information."
20736 (interactive)
20737 (cond
20738 ((org-at-table-p)
20739 (org-table-justify-field-maybe)
20740 (call-interactively 'org-table-next-row))
20741 (t (newline))))
20743 (defun org-meta-return (&optional arg)
20744 "Insert a new heading or wrap a region in a table.
20745 Calls `org-insert-heading' or `org-table-wrap-region', depending on context.
20746 See the individual commands for more information."
20747 (interactive "P")
20748 (cond
20749 ((org-at-table-p)
20750 (call-interactively 'org-table-wrap-region))
20751 (t (call-interactively 'org-insert-heading))))
20753 ;;; Menu entries
20755 ;; Define the Org-mode menus
20756 (easy-menu-define org-tbl-menu org-mode-map "Tbl menu"
20757 '("Tbl"
20758 ["Align" org-ctrl-c-ctrl-c (org-at-table-p)]
20759 ["Next Field" org-cycle (org-at-table-p)]
20760 ["Previous Field" org-shifttab (org-at-table-p)]
20761 ["Next Row" org-return (org-at-table-p)]
20762 "--"
20763 ["Blank Field" org-table-blank-field (org-at-table-p)]
20764 ["Edit Field" org-table-edit-field (org-at-table-p)]
20765 ["Copy Field from Above" org-table-copy-down (org-at-table-p)]
20766 "--"
20767 ("Column"
20768 ["Move Column Left" org-metaleft (org-at-table-p)]
20769 ["Move Column Right" org-metaright (org-at-table-p)]
20770 ["Delete Column" org-shiftmetaleft (org-at-table-p)]
20771 ["Insert Column" org-shiftmetaright (org-at-table-p)])
20772 ("Row"
20773 ["Move Row Up" org-metaup (org-at-table-p)]
20774 ["Move Row Down" org-metadown (org-at-table-p)]
20775 ["Delete Row" org-shiftmetaup (org-at-table-p)]
20776 ["Insert Row" org-shiftmetadown (org-at-table-p)]
20777 ["Sort lines in region" org-table-sort-lines (org-at-table-p)]
20778 "--"
20779 ["Insert Hline" org-table-insert-hline (org-at-table-p)])
20780 ("Rectangle"
20781 ["Copy Rectangle" org-copy-special (org-at-table-p)]
20782 ["Cut Rectangle" org-cut-special (org-at-table-p)]
20783 ["Paste Rectangle" org-paste-special (org-at-table-p)]
20784 ["Fill Rectangle" org-table-wrap-region (org-at-table-p)])
20785 "--"
20786 ("Calculate"
20787 ["Set Column Formula" org-table-eval-formula (org-at-table-p)]
20788 ["Set Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
20789 ["Edit Formulas" org-table-edit-formulas (org-at-table-p)]
20790 "--"
20791 ["Recalculate line" org-table-recalculate (org-at-table-p)]
20792 ["Recalculate all" (lambda () (interactive) (org-table-recalculate '(4))) :active (org-at-table-p) :keys "C-u C-c *"]
20793 ["Iterate all" (lambda () (interactive) (org-table-recalculate '(16))) :active (org-at-table-p) :keys "C-u C-u C-c *"]
20794 "--"
20795 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks (org-at-table-p)]
20796 "--"
20797 ["Sum Column/Rectangle" org-table-sum
20798 (or (org-at-table-p) (org-region-active-p))]
20799 ["Which Column?" org-table-current-column (org-at-table-p)])
20800 ["Debug Formulas"
20801 org-table-toggle-formula-debugger
20802 :style toggle :selected org-table-formula-debug]
20803 ["Show Col/Row Numbers"
20804 org-table-toggle-coordinate-overlays
20805 :style toggle :selected org-table-overlay-coordinates]
20806 "--"
20807 ["Create" org-table-create (and (not (org-at-table-p))
20808 org-enable-table-editor)]
20809 ["Convert Region" org-table-convert-region (not (org-at-table-p 'any))]
20810 ["Import from File" org-table-import (not (org-at-table-p))]
20811 ["Export to File" org-table-export (org-at-table-p)]
20812 "--"
20813 ["Create/Convert from/to table.el" org-table-create-with-table.el t]))
20815 (easy-menu-define org-org-menu org-mode-map "Org menu"
20816 '("Org"
20817 ("Show/Hide"
20818 ["Cycle Visibility" org-cycle (or (bobp) (outline-on-heading-p))]
20819 ["Cycle Global Visibility" org-shifttab (not (org-at-table-p))]
20820 ["Sparse Tree" org-occur t]
20821 ["Reveal Context" org-reveal t]
20822 ["Show All" show-all t]
20823 "--"
20824 ["Subtree to indirect buffer" org-tree-to-indirect-buffer t])
20825 "--"
20826 ["New Heading" org-insert-heading t]
20827 ("Navigate Headings"
20828 ["Up" outline-up-heading t]
20829 ["Next" outline-next-visible-heading t]
20830 ["Previous" outline-previous-visible-heading t]
20831 ["Next Same Level" outline-forward-same-level t]
20832 ["Previous Same Level" outline-backward-same-level t]
20833 "--"
20834 ["Jump" org-goto t]
20835 "--"
20836 ["C-a finds headline start"
20837 (setq org-special-ctrl-a (not org-special-ctrl-a))
20838 :style toggle :selected org-special-ctrl-a])
20839 ("Edit Structure"
20840 ["Move Subtree Up" org-shiftmetaup (not (org-at-table-p))]
20841 ["Move Subtree Down" org-shiftmetadown (not (org-at-table-p))]
20842 "--"
20843 ["Copy Subtree" org-copy-special (not (org-at-table-p))]
20844 ["Cut Subtree" org-cut-special (not (org-at-table-p))]
20845 ["Paste Subtree" org-paste-special (not (org-at-table-p))]
20846 "--"
20847 ["Promote Heading" org-metaleft (not (org-at-table-p))]
20848 ["Promote Subtree" org-shiftmetaleft (not (org-at-table-p))]
20849 ["Demote Heading" org-metaright (not (org-at-table-p))]
20850 ["Demote Subtree" org-shiftmetaright (not (org-at-table-p))]
20851 "--"
20852 ["Sort Region/Children" org-sort (not (org-at-table-p))]
20853 "--"
20854 ["Convert to odd levels" org-convert-to-odd-levels t]
20855 ["Convert to odd/even levels" org-convert-to-oddeven-levels t])
20856 ("Editing"
20857 ["Emphasis..." org-emphasize t])
20858 ("Archive"
20859 ["Toggle ARCHIVE tag" org-toggle-archive-tag t]
20860 ; ["Check and Tag Children" (org-toggle-archive-tag (4))
20861 ; :active t :keys "C-u C-c C-x C-a"]
20862 ["Sparse trees open ARCHIVE trees"
20863 (setq org-sparse-tree-open-archived-trees
20864 (not org-sparse-tree-open-archived-trees))
20865 :style toggle :selected org-sparse-tree-open-archived-trees]
20866 ["Cycling opens ARCHIVE trees"
20867 (setq org-cycle-open-archived-trees (not org-cycle-open-archived-trees))
20868 :style toggle :selected org-cycle-open-archived-trees]
20869 ["Agenda includes ARCHIVE trees"
20870 (setq org-agenda-skip-archived-trees (not org-agenda-skip-archived-trees))
20871 :style toggle :selected (not org-agenda-skip-archived-trees)]
20872 "--"
20873 ["Move Subtree to Archive" org-advertized-archive-subtree t]
20874 ; ["Check and Move Children" (org-archive-subtree '(4))
20875 ; :active t :keys "C-u C-c C-x C-s"]
20877 "--"
20878 ("TODO Lists"
20879 ["TODO/DONE/-" org-todo t]
20880 ("Select keyword"
20881 ["Next keyword" org-shiftright (org-on-heading-p)]
20882 ["Previous keyword" org-shiftleft (org-on-heading-p)]
20883 ["Complete Keyword" org-complete (assq :todo-keyword (org-context))]
20884 ["Next keyword set" org-shiftcontrolright (and (> (length org-todo-sets) 1) (org-on-heading-p))]
20885 ["Previous keyword set" org-shiftcontrolright (and (> (length org-todo-sets) 1) (org-on-heading-p))])
20886 ["Show TODO Tree" org-show-todo-tree t]
20887 ["Global TODO list" org-todo-list t]
20888 "--"
20889 ["Set Priority" org-priority t]
20890 ["Priority Up" org-shiftup t]
20891 ["Priority Down" org-shiftdown t]
20892 "--"
20893 ;; FIXME: why is this still here????
20894 ; ["Insert Checkbox" org-insert-todo-heading (org-in-item-p)]
20895 ; ["Toggle Checkbox" org-ctrl-c-ctrl-c (org-at-item-checkbox-p)]
20896 ; ["Insert [n/m] cookie" (progn (insert "[/]") (org-update-checkbox-count))
20897 ; (or (org-on-heading-p) (org-at-item-p))]
20898 ; ["Insert [%] cookie" (progn (insert "[%]") (org-update-checkbox-count))
20899 ; (or (org-on-heading-p) (org-at-item-p))]
20900 ; ["Update Statistics" org-update-checkbox-count t]
20902 ("Dates and Scheduling"
20903 ["Timestamp" org-time-stamp t]
20904 ["Timestamp (inactive)" org-time-stamp-inactive t]
20905 ("Change Date"
20906 ["1 Day Later" org-shiftright t]
20907 ["1 Day Earlier" org-shiftleft t]
20908 ["1 ... Later" org-shiftup t]
20909 ["1 ... Earlier" org-shiftdown t])
20910 ["Compute Time Range" org-evaluate-time-range t]
20911 ["Schedule Item" org-schedule t]
20912 ["Deadline" org-deadline t]
20913 "--"
20914 ["Custom time format" org-toggle-time-stamp-overlays
20915 :style radio :selected org-display-custom-times]
20916 "--"
20917 ["Goto Calendar" org-goto-calendar t]
20918 ["Date from Calendar" org-date-from-calendar t])
20919 ("Logging work"
20920 ["Clock in" org-clock-in t]
20921 ["Clock out" org-clock-out t]
20922 ["Clock cancel" org-clock-cancel t]
20923 ["Display times" org-clock-display t]
20924 ["Create clock table" org-clock-report t]
20925 "--"
20926 ["Record DONE time"
20927 (progn (setq org-log-done (not org-log-done))
20928 (message "Switching to %s will %s record a timestamp"
20929 (car org-done-keywords)
20930 (if org-log-done "automatically" "not")))
20931 :style toggle :selected org-log-done])
20932 "--"
20933 ["Agenda Command..." org-agenda t]
20934 ("File List for Agenda")
20935 ("Special views current file"
20936 ["TODO Tree" org-show-todo-tree t]
20937 ["Check Deadlines" org-check-deadlines t]
20938 ["Timeline" org-timeline t]
20939 ["Tags Tree" org-tags-sparse-tree t])
20940 "--"
20941 ("Hyperlinks"
20942 ["Store Link (Global)" org-store-link t]
20943 ["Insert Link" org-insert-link t]
20944 ["Follow Link" org-open-at-point t]
20945 "--"
20946 ["Next link" org-next-link t]
20947 ["Previous link" org-previous-link t]
20948 "--"
20949 ["Descriptive Links"
20950 (progn (org-add-to-invisibility-spec '(org-link)) (org-restart-font-lock))
20951 :style radio :selected (member '(org-link) buffer-invisibility-spec)]
20952 ["Literal Links"
20953 (progn
20954 (org-remove-from-invisibility-spec '(org-link)) (org-restart-font-lock))
20955 :style radio :selected (not (member '(org-link) buffer-invisibility-spec))])
20956 "--"
20957 ["Export/Publish..." org-export t]
20958 ("LaTeX"
20959 ["Org CDLaTeX mode" org-cdlatex-mode :style toggle
20960 :selected org-cdlatex-mode]
20961 ["Insert Environment" cdlatex-environment (fboundp 'cdlatex-environment)]
20962 ["Insert math symbol" cdlatex-math-symbol (fboundp 'cdlatex-math-symbol)]
20963 ["Modify math symbol" org-cdlatex-math-modify
20964 (org-inside-LaTeX-fragment-p)]
20965 ["Export LaTeX fragments as images"
20966 (setq org-export-with-LaTeX-fragments (not org-export-with-LaTeX-fragments))
20967 :style toggle :selected org-export-with-LaTeX-fragments])
20968 "--"
20969 ("Documentation"
20970 ["Show Version" org-version t]
20971 ["Info Documentation" org-info t])
20972 ("Customize"
20973 ["Browse Org Group" org-customize t]
20974 "--"
20975 ["Expand This Menu" org-create-customize-menu
20976 (fboundp 'customize-menu-create)])
20977 "--"
20978 ["Refresh setup" org-mode-restart t]
20981 (defun org-info (&optional node)
20982 "Read documentation for Org-mode in the info system.
20983 With optional NODE, go directly to that node."
20984 (interactive)
20985 (require 'info)
20986 (Info-goto-node (format "(org)%s" (or node ""))))
20988 (defun org-install-agenda-files-menu ()
20989 (let ((bl (buffer-list)))
20990 (save-excursion
20991 (while bl
20992 (set-buffer (pop bl))
20993 (if (org-mode-p) (setq bl nil)))
20994 (when (org-mode-p)
20995 (easy-menu-change
20996 '("Org") "File List for Agenda"
20997 (append
20998 (list
20999 ["Edit File List" (org-edit-agenda-file-list) t]
21000 ["Add/Move Current File to Front of List" org-agenda-file-to-front t]
21001 ["Remove Current File from List" org-remove-file t]
21002 ["Cycle through agenda files" org-cycle-agenda-files t]
21003 "--")
21004 (mapcar 'org-file-menu-entry (org-agenda-files t))))))))
21006 ;;;; Documentation
21008 (defun org-customize ()
21009 "Call the customize function with org as argument."
21010 (interactive)
21011 (customize-browse 'org))
21013 (defun org-create-customize-menu ()
21014 "Create a full customization menu for Org-mode, insert it into the menu."
21015 (interactive)
21016 (if (fboundp 'customize-menu-create)
21017 (progn
21018 (easy-menu-change
21019 '("Org") "Customize"
21020 `(["Browse Org group" org-customize t]
21021 "--"
21022 ,(customize-menu-create 'org)
21023 ["Set" Custom-set t]
21024 ["Save" Custom-save t]
21025 ["Reset to Current" Custom-reset-current t]
21026 ["Reset to Saved" Custom-reset-saved t]
21027 ["Reset to Standard Settings" Custom-reset-standard t]))
21028 (message "\"Org\"-menu now contains full customization menu"))
21029 (error "Cannot expand menu (outdated version of cus-edit.el)")))
21031 ;;;; Miscellaneous stuff
21034 ;;; Generally useful functions
21036 (defun org-context ()
21037 "Return a list of contexts of the current cursor position.
21038 If several contexts apply, all are returned.
21039 Each context entry is a list with a symbol naming the context, and
21040 two positions indicating start and end of the context. Possible
21041 contexts are:
21043 :headline anywhere in a headline
21044 :headline-stars on the leading stars in a headline
21045 :todo-keyword on a TODO keyword (including DONE) in a headline
21046 :tags on the TAGS in a headline
21047 :priority on the priority cookie in a headline
21048 :item on the first line of a plain list item
21049 :item-bullet on the bullet/number of a plain list item
21050 :checkbox on the checkbox in a plain list item
21051 :table in an org-mode table
21052 :table-special on a special filed in a table
21053 :table-table in a table.el table
21054 :link on a hyperlink
21055 :keyword on a keyword: SCHEDULED, DEADLINE, CLOSE,COMMENT, QUOTE.
21056 :target on a <<target>>
21057 :radio-target on a <<<radio-target>>>
21058 :latex-fragment on a LaTeX fragment
21059 :latex-preview on a LaTeX fragment with overlayed preview image
21061 This function expects the position to be visible because it uses font-lock
21062 faces as a help to recognize the following contexts: :table-special, :link,
21063 and :keyword."
21064 (let* ((f (get-text-property (point) 'face))
21065 (faces (if (listp f) f (list f)))
21066 (p (point)) clist o)
21067 ;; First the large context
21068 (cond
21069 ((org-on-heading-p t)
21070 (push (list :headline (point-at-bol) (point-at-eol)) clist)
21071 (when (progn
21072 (beginning-of-line 1)
21073 (looking-at org-todo-line-tags-regexp))
21074 (push (org-point-in-group p 1 :headline-stars) clist)
21075 (push (org-point-in-group p 2 :todo-keyword) clist)
21076 (push (org-point-in-group p 4 :tags) clist))
21077 (goto-char p)
21078 (skip-chars-backward "^[\n\r \t") (or (eobp) (backward-char 1))
21079 (if (looking-at "\\[#[A-Z0-9]\\]")
21080 (push (org-point-in-group p 0 :priority) clist)))
21082 ((org-at-item-p)
21083 (push (org-point-in-group p 2 :item-bullet) clist)
21084 (push (list :item (point-at-bol)
21085 (save-excursion (org-end-of-item) (point)))
21086 clist)
21087 (and (org-at-item-checkbox-p)
21088 (push (org-point-in-group p 0 :checkbox) clist)))
21090 ((org-at-table-p)
21091 (push (list :table (org-table-begin) (org-table-end)) clist)
21092 (if (memq 'org-formula faces)
21093 (push (list :table-special
21094 (previous-single-property-change p 'face)
21095 (next-single-property-change p 'face)) clist)))
21096 ((org-at-table-p 'any)
21097 (push (list :table-table) clist)))
21098 (goto-char p)
21100 ;; Now the small context
21101 (cond
21102 ((org-at-timestamp-p)
21103 (push (org-point-in-group p 0 :timestamp) clist))
21104 ((memq 'org-link faces)
21105 (push (list :link
21106 (previous-single-property-change p 'face)
21107 (next-single-property-change p 'face)) clist))
21108 ((memq 'org-special-keyword faces)
21109 (push (list :keyword
21110 (previous-single-property-change p 'face)
21111 (next-single-property-change p 'face)) clist))
21112 ((org-on-target-p)
21113 (push (org-point-in-group p 0 :target) clist)
21114 (goto-char (1- (match-beginning 0)))
21115 (if (looking-at org-radio-target-regexp)
21116 (push (org-point-in-group p 0 :radio-target) clist))
21117 (goto-char p))
21118 ((setq o (car (delq nil
21119 (mapcar
21120 (lambda (x)
21121 (if (memq x org-latex-fragment-image-overlays) x))
21122 (org-overlays-at (point))))))
21123 (push (list :latex-fragment
21124 (org-overlay-start o) (org-overlay-end o)) clist)
21125 (push (list :latex-preview
21126 (org-overlay-start o) (org-overlay-end o)) clist))
21127 ((org-inside-LaTeX-fragment-p)
21128 ;; FIXME: positions wrong.
21129 (push (list :latex-fragment (point) (point)) clist)))
21131 (setq clist (nreverse (delq nil clist)))
21132 clist))
21134 ;; FIXME Compare with at-regexp-p
21135 (defun org-in-regexp (re &optional nlines visually)
21136 "Check if point is inside a match of regexp.
21137 Normally only the current line is checked, but you can include NLINES extra
21138 lines both before and after point into the search.
21139 If VISUALLY is set, require that the cursor is not after the match but
21140 really on, so that the block visually is on the match."
21141 (catch 'exit
21142 (let ((pos (point))
21143 (eol (point-at-eol (+ 1 (or nlines 0))))
21144 (inc (if visually 1 0)))
21145 (save-excursion
21146 (beginning-of-line (- 1 (or nlines 0)))
21147 (while (re-search-forward re eol t)
21148 (if (and (<= (match-beginning 0) pos)
21149 (>= (+ inc (match-end 0)) pos))
21150 (throw 'exit (cons (match-beginning 0) (match-end 0)))))))))
21152 (defun org-at-regexp-p (regexp)
21153 "Is point inside a match of REGEXP in the current line?"
21154 (catch 'exit
21155 (save-excursion
21156 (let ((pos (point)) (end (point-at-eol)))
21157 (beginning-of-line 1)
21158 (while (re-search-forward regexp end t)
21159 (if (and (<= (match-beginning 0) pos)
21160 (>= (match-end 0) pos))
21161 (throw 'exit t)))
21162 nil))))
21164 (defun org-uniquify (list)
21165 "Remove duplicate elements from LIST."
21166 (let (res)
21167 (mapc (lambda (x) (add-to-list 'res x 'append)) list)
21168 res))
21170 (defun org-delete-all (elts list)
21171 "Remove all elements in ELTS from LIST."
21172 (while elts
21173 (setq list (delete (pop elts) list)))
21174 list)
21176 (defun org-point-in-group (point group &optional context)
21177 "Check if POINT is in match-group GROUP.
21178 If CONTEXT is non-nil, return a list with CONTEXT and the boundaries of the
21179 match. If the match group does ot exist or point is not inside it,
21180 return nil."
21181 (and (match-beginning group)
21182 (>= point (match-beginning group))
21183 (<= point (match-end group))
21184 (if context
21185 (list context (match-beginning group) (match-end group))
21186 t)))
21188 (defun org-combine-plists (&rest plists)
21189 "Create a single property list from all plists in PLISTS.
21190 The process starts by copying the first list, and then setting properties
21191 from the other lists. Settings in the last list are the most significant
21192 ones and overrule settings in the other lists."
21193 (let ((rtn (copy-sequence (pop plists)))
21194 p v ls)
21195 (while plists
21196 (setq ls (pop plists))
21197 (while ls
21198 (setq p (pop ls) v (pop ls))
21199 (setq rtn (plist-put rtn p v))))
21200 rtn))
21202 (defun org-move-line-down (arg)
21203 "Move the current line down. With prefix argument, move it past ARG lines."
21204 (interactive "p")
21205 (let ((col (current-column))
21206 beg end pos)
21207 (beginning-of-line 1) (setq beg (point))
21208 (beginning-of-line 2) (setq end (point))
21209 (beginning-of-line (+ 1 arg))
21210 (setq pos (move-marker (make-marker) (point)))
21211 (insert (delete-and-extract-region beg end))
21212 (goto-char pos)
21213 (move-to-column col)))
21215 (defun org-move-line-up (arg)
21216 "Move the current line up. With prefix argument, move it past ARG lines."
21217 (interactive "p")
21218 (let ((col (current-column))
21219 beg end pos)
21220 (beginning-of-line 1) (setq beg (point))
21221 (beginning-of-line 2) (setq end (point))
21222 (beginning-of-line (- arg))
21223 (setq pos (move-marker (make-marker) (point)))
21224 (insert (delete-and-extract-region beg end))
21225 (goto-char pos)
21226 (move-to-column col)))
21228 (defun org-replace-escapes (string table)
21229 "Replace %-escapes in STRING with values in TABLE.
21230 TABLE is an association list with keys line \"%a\" and string values.
21231 The sequences in STRING may contain normal field width and padding information,
21232 for example \"%-5s\". Replacements happen in the sequence given by TABLE,
21233 so values can contain further %-escapes if they are define later in TABLE."
21234 (let ((case-fold-search nil)
21235 e re rpl)
21236 (while (setq e (pop table))
21237 (setq re (concat "%-?[0-9.]*" (substring (car e) 1)))
21238 (while (string-match re string)
21239 (setq rpl (format (concat (substring (match-string 0 string) 0 -1) "s")
21240 (cdr e)))
21241 (setq string (replace-match rpl t t string))))
21242 string))
21245 (defun org-sublist (list start end)
21246 "Return a section of LIST, from START to END.
21247 Counting starts at 1."
21248 (let (rtn (c start))
21249 (setq list (nthcdr (1- start) list))
21250 (while (and list (<= c end))
21251 (push (pop list) rtn)
21252 (setq c (1+ c)))
21253 (nreverse rtn)))
21255 (defun org-find-base-buffer-visiting (file)
21256 "Like `find-buffer-visiting' but alway return the base buffer and
21257 not an indirect buffer"
21258 (let ((buf (find-buffer-visiting file)))
21259 (or (buffer-base-buffer buf) buf)))
21261 (defun org-image-file-name-regexp ()
21262 "Return regexp matching the file names of images."
21263 (if (fboundp 'image-file-name-regexp)
21264 (image-file-name-regexp)
21265 (let ((image-file-name-extensions
21266 '("png" "jpeg" "jpg" "gif" "tiff" "tif"
21267 "xbm" "xpm" "pbm" "pgm" "ppm")))
21268 (concat "\\."
21269 (regexp-opt (nconc (mapcar 'upcase
21270 image-file-name-extensions)
21271 image-file-name-extensions)
21273 "\\'"))))
21275 (defun org-file-image-p (file)
21276 "Return non-nil if FILE is an image."
21277 (save-match-data
21278 (string-match (org-image-file-name-regexp) file)))
21280 ;;; Paragraph filling stuff.
21281 ;; We want this to be just right, so use the full arsenal.
21283 (defun org-indent-line-function ()
21284 "Indent line like previous, but further if previous was headline or item."
21285 (interactive)
21286 (let ((column (save-excursion
21287 (beginning-of-line)
21288 (if (looking-at "#") 0
21289 (skip-chars-backward "\n \t")
21290 (beginning-of-line)
21291 (if (or (looking-at "\\*+[ \t]+")
21292 (looking-at "[ \t]*\\([-+*][ \t]+\\|[0-9]+[.)][ \t]+\\)"))
21293 (progn (goto-char (match-end 0)) (current-column))
21294 (current-indentation))))))
21295 (if (<= (current-column) (current-indentation))
21296 (indent-line-to column)
21297 (save-excursion (indent-line-to column)))))
21299 (defun org-set-autofill-regexps ()
21300 (interactive)
21301 ;; In the paragraph separator we include headlines, because filling
21302 ;; text in a line directly attached to a headline would otherwise
21303 ;; fill the headline as well.
21304 (org-set-local 'comment-start-skip "^#+[ \t]*")
21305 (org-set-local 'paragraph-separate "\f\\|\\*\\|[ ]*$\\|[ \t]*[:|]")
21306 ;; FIXME!!!!!!! (org-set-local 'paragraph-separate "\f\\|[ ]*$")
21307 ;; The paragraph starter includes hand-formatted lists.
21308 (org-set-local 'paragraph-start
21309 "\f\\|[ ]*$\\|\\([*\f]+\\)\\|[ \t]*\\([-+*][ \t]+\\|[0-9]+[.)][ \t]+\\)\\|[ \t]*[:|]")
21310 ;; Inhibit auto-fill for headers, tables and fixed-width lines.
21311 ;; But only if the user has not turned off tables or fixed-width regions
21312 (org-set-local
21313 'auto-fill-inhibit-regexp
21314 (concat "\\*\\|#\\+"
21315 "\\|[ \t]*" org-keyword-time-regexp
21316 (if (or org-enable-table-editor org-enable-fixed-width-editor)
21317 (concat
21318 "\\|[ \t]*["
21319 (if org-enable-table-editor "|" "")
21320 (if org-enable-fixed-width-editor ":" "")
21321 "]"))))
21322 ;; We use our own fill-paragraph function, to make sure that tables
21323 ;; and fixed-width regions are not wrapped. That function will pass
21324 ;; through to `fill-paragraph' when appropriate.
21325 (org-set-local 'fill-paragraph-function 'org-fill-paragraph)
21326 ; Adaptive filling: To get full control, first make sure that
21327 ;; `adaptive-fill-regexp' never matches. Then install our own matcher.
21328 (org-set-local 'adaptive-fill-regexp "\000")
21329 (org-set-local 'adaptive-fill-function
21330 'org-adaptive-fill-function))
21332 (defun org-fill-paragraph (&optional justify)
21333 "Re-align a table, pass through to fill-paragraph if no table."
21334 (let ((table-p (org-at-table-p))
21335 (table.el-p (org-at-table.el-p)))
21336 (cond ((equal (char-after (point-at-bol)) ?*) t) ; skip headlines
21337 (table.el-p t) ; skip table.el tables
21338 (table-p (org-table-align) t) ; align org-mode tables
21339 (t nil)))) ; call paragraph-fill
21341 ;; For reference, this is the default value of adaptive-fill-regexp
21342 ;; "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*"
21344 (defun org-adaptive-fill-function ()
21345 "Return a fill prefix for org-mode files.
21346 In particular, this makes sure hanging paragraphs for hand-formatted lists
21347 work correctly."
21348 (cond ((looking-at "#[ \t]+")
21349 (match-string 0))
21350 ((looking-at " *\\([-*+] \\|[0-9]+[.)] \\)?")
21351 (make-string (- (match-end 0) (match-beginning 0)) ?\ ))
21352 (t nil)))
21354 ;;;; Functions extending outline functionality
21356 ;; C-a should go to the beginning of a *visible* line, also in the
21357 ;; new outline.el. I guess this should be patched into Emacs?
21358 (defun org-beginning-of-line ()
21359 "Go to the beginning of the current line. If that is invisible, continue
21360 to a visible line beginning. This makes the function of C-a more intuitive."
21361 (interactive)
21362 (let ((pos (point)))
21363 (beginning-of-line 1)
21364 (if (bobp)
21366 (backward-char 1)
21367 (if (org-invisible-p)
21368 (while (and (not (bobp)) (org-invisible-p))
21369 (backward-char 1)
21370 (beginning-of-line 1))
21371 (forward-char 1)))
21372 (when (and org-special-ctrl-a (looking-at org-todo-line-regexp)
21373 (= (char-after (match-end 1)) ?\ ))
21374 (goto-char
21375 (cond ((> pos (match-beginning 3)) (match-beginning 3))
21376 ((= pos (point)) (match-beginning 3))
21377 (t (point)))))))
21379 (define-key org-mode-map "\C-a" 'org-beginning-of-line)
21381 (defun org-invisible-p ()
21382 "Check if point is at a character currently not visible."
21383 ;; Early versions of noutline don't have `outline-invisible-p'.
21384 (if (fboundp 'outline-invisible-p)
21385 (outline-invisible-p)
21386 (get-char-property (point) 'invisible)))
21388 (defun org-invisible-p2 ()
21389 "Check if point is at a character currently not visible."
21390 (save-excursion
21391 (if (and (eolp) (not (bobp))) (backward-char 1))
21392 ;; Early versions of noutline don't have `outline-invisible-p'.
21393 (if (fboundp 'outline-invisible-p)
21394 (outline-invisible-p)
21395 (get-char-property (point) 'invisible))))
21397 (defalias 'org-back-to-heading 'outline-back-to-heading)
21398 (defalias 'org-on-heading-p 'outline-on-heading-p)
21399 (defalias 'org-at-heading-p 'outline-on-heading-p)
21400 (defun org-at-heading-or-item-p ()
21401 (or (org-on-heading-p) (org-at-item-p)))
21403 (defun org-on-target-p ()
21404 (or (org-in-regexp org-radio-target-regexp)
21405 (org-in-regexp org-target-regexp)))
21407 (defun org-up-heading-all (arg)
21408 "Move to the heading line of which the present line is a subheading.
21409 This function considers both visible and invisible heading lines.
21410 With argument, move up ARG levels."
21411 (if (fboundp 'outline-up-heading-all)
21412 (outline-up-heading-all arg) ; emacs 21 version of outline.el
21413 (outline-up-heading arg t))) ; emacs 22 version of outline.el
21415 (defun org-goto-sibling (&optional previous)
21416 "Goto the next sibling, even if it is invisible.
21417 When PREVIOUS is set, go to the previous sibling instead. Returns t
21418 when a sibling was found. When none is found, return nil and don't
21419 move point."
21420 (let ((fun (if previous 're-search-backward 're-search-forward))
21421 (pos (point))
21422 (re (concat "^" outline-regexp))
21423 level l)
21424 (org-back-to-heading t)
21425 (setq level (funcall outline-level))
21426 (catch 'exit
21427 (or previous (forward-char 1))
21428 (while (funcall fun re nil t)
21429 (setq l (funcall outline-level))
21430 (when (< l level) (goto-char pos) (throw 'exit nil))
21431 (when (= l level) (goto-char (match-beginning 0)) (throw 'exit t)))
21432 (goto-char pos)
21433 nil)))
21435 (defun org-show-siblings ()
21436 "Show all siblings of the current headline."
21437 (save-excursion
21438 (while (org-goto-sibling) (org-flag-heading nil)))
21439 (save-excursion
21440 (while (org-goto-sibling 'previous)
21441 (org-flag-heading nil))))
21443 (defun org-show-hidden-entry ()
21444 "Show an entry where even the heading is hidden."
21445 (save-excursion
21446 (org-show-entry)))
21448 (defun org-flag-heading (flag &optional entry)
21449 "Flag the current heading. FLAG non-nil means make invisible.
21450 When ENTRY is non-nil, show the entire entry."
21451 (save-excursion
21452 (org-back-to-heading t)
21453 ;; Check if we should show the entire entry
21454 (if entry
21455 (progn
21456 (org-show-entry)
21457 (save-excursion
21458 (and (outline-next-heading)
21459 (org-flag-heading nil))))
21460 (outline-flag-region (max 1 (1- (point)))
21461 (save-excursion (outline-end-of-heading) (point))
21462 flag))))
21464 (defun org-end-of-subtree (&optional invisible-OK to-heading)
21465 ;; This is an exact copy of the original function, but it uses
21466 ;; `org-back-to-heading', to make it work also in invisible
21467 ;; trees. And is uses an invisible-OK argument.
21468 ;; Under Emacs this is not needed, but the old outline.el needs this fix.
21469 (org-back-to-heading invisible-OK)
21470 (let ((first t)
21471 (level (funcall outline-level)))
21472 (while (and (not (eobp))
21473 (or first (> (funcall outline-level) level)))
21474 (setq first nil)
21475 (outline-next-heading))
21476 (unless to-heading
21477 (if (memq (preceding-char) '(?\n ?\^M))
21478 (progn
21479 ;; Go to end of line before heading
21480 (forward-char -1)
21481 (if (memq (preceding-char) '(?\n ?\^M))
21482 ;; leave blank line before heading
21483 (forward-char -1))))))
21484 (point))
21486 (defun org-show-subtree ()
21487 "Show everything after this heading at deeper levels."
21488 (outline-flag-region
21489 (point)
21490 (save-excursion
21491 (outline-end-of-subtree) (outline-next-heading) (point))
21492 nil))
21494 (defun org-show-entry ()
21495 "Show the body directly following this heading.
21496 Show the heading too, if it is currently invisible."
21497 (interactive)
21498 (save-excursion
21499 (org-back-to-heading t)
21500 (outline-flag-region
21501 (max 1 (1- (point)))
21502 (save-excursion
21503 (re-search-forward (concat "[\r\n]\\(" outline-regexp "\\)") nil 'move)
21504 (or (match-beginning 1) (point-max)))
21505 nil)))
21507 (defun org-make-options-regexp (kwds)
21508 "Make a regular expression for keyword lines."
21509 (concat
21511 "#?[ \t]*\\+\\("
21512 (mapconcat 'regexp-quote kwds "\\|")
21513 "\\):[ \t]*"
21514 "\\(.+\\)"))
21516 ;; Make isearch reveal the necessary context
21517 (defun org-isearch-end ()
21518 "Reveal context after isearch exits."
21519 (when isearch-success ; only if search was successful
21520 (if (featurep 'xemacs)
21521 ;; Under XEmacs, the hook is run in the correct place,
21522 ;; we directly show the context.
21523 (org-show-context 'isearch)
21524 ;; In Emacs the hook runs *before* restoring the overlays.
21525 ;; So we have to use a one-time post-command-hook to do this.
21526 ;; (Emacs 22 has a special variable, see function `org-mode')
21527 (unless (and (boundp 'isearch-mode-end-hook-quit)
21528 isearch-mode-end-hook-quit)
21529 ;; Only when the isearch was not quitted.
21530 (org-add-hook 'post-command-hook 'org-isearch-post-command
21531 'append 'local)))))
21533 (defun org-isearch-post-command ()
21534 "Remove self from hook, and show context."
21535 (remove-hook 'post-command-hook 'org-isearch-post-command 'local)
21536 (org-show-context 'isearch))
21539 ;;;; Address problems with some other packages
21541 ;; Make flyspell not check words in links, to not mess up our keymap
21542 (defun org-mode-flyspell-verify ()
21543 "Don't let flyspell put overlays at active buttons."
21544 (not (get-text-property (point) 'keymap)))
21546 ;; Make `bookmark-jump' show the jump location if it was hidden.
21547 (eval-after-load "bookmark"
21548 '(if (boundp 'bookmark-after-jump-hook)
21549 ;; We can use the hook
21550 (add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide)
21551 ;; Hook not available, use advice
21552 (defadvice bookmark-jump (after org-make-visible activate)
21553 "Make the position visible."
21554 (org-bookmark-jump-unhide))))
21556 (defun org-bookmark-jump-unhide ()
21557 "Unhide the current position, to show the bookmark location."
21558 (and (org-mode-p)
21559 (or (org-invisible-p)
21560 (save-excursion (goto-char (max (point-min) (1- (point))))
21561 (org-invisible-p)))
21562 (org-show-context 'bookmark-jump)))
21564 ;; Make session.el ignore our circular variable
21565 (eval-after-load "session"
21566 '(add-to-list 'session-globals-exclude 'org-mark-ring))
21568 ;;;; Experimental code
21570 (defun org-closed-in-range ()
21571 "Sparse treee of items closed in a certain time range.
21572 Still experimental, may disappear in the furture."
21573 (interactive)
21574 ;; Get the time interval from the user.
21575 (let* ((time1 (time-to-seconds
21576 (org-read-date nil 'to-time nil "Starting date: ")))
21577 (time2 (time-to-seconds
21578 (org-read-date nil 'to-time nil "End date:")))
21579 ;; callback function
21580 (callback (lambda ()
21581 (let ((time
21582 (time-to-seconds
21583 (apply 'encode-time
21584 (org-parse-time-string
21585 (match-string 1))))))
21586 ;; check if time in interval
21587 (and (>= time time1) (<= time time2))))))
21588 ;; make tree, check each match with the callback
21589 (org-occur "CLOSED: +\\[\\(.*?\\)\\]" nil callback)))
21591 ;;;; Finish up
21593 (provide 'org)
21595 (run-hooks 'org-load-hook)
21597 ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
21598 ;;; org.el ends here