Clean up compiler messages.
[org-mode.git] / org.el
blobf63d4e73d28b3fa2a930180f4bab0e70dae66d31
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, 2008 Free Software Foundation, Inc.
4 ;;
5 ;; Author: Carsten Dominik <carsten at orgmode dot org>
6 ;; Keywords: outlines, hypermedia, calendar, wp
7 ;; Homepage: http://orgmode.org
8 ;; Version: 5.23a++
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 3, 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://orgmode.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://orgmode.org/Changes.html
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 (unless (fboundp 'time-subtract) (defalias 'time-subtract 'subtract-time))
81 (require 'easymenu)
83 ;;;; Customization variables
85 ;;; Version
87 (defconst org-version "5.23a++"
88 "The version number of the file org.el.")
90 (defun org-version (&optional here)
91 "Show the org-mode version in the echo area.
92 With prefix arg HERE, insert it at point."
93 (interactive "P")
94 (let ((version (format "Org-mode version %s" org-version)))
95 (message version)
96 (if here
97 (insert version))))
99 ;;; Compatibility constants
100 (defconst org-xemacs-p (featurep 'xemacs)) ; not used by org.el itself
101 (defconst org-format-transports-properties-p
102 (let ((x "a"))
103 (add-text-properties 0 1 '(test t) x)
104 (get-text-property 0 'test (format "%s" x)))
105 "Does format transport text properties?")
107 (defmacro org-bound-and-true-p (var)
108 "Return the value of symbol VAR if it is bound, else nil."
109 `(and (boundp (quote ,var)) ,var))
111 (defmacro org-unmodified (&rest body)
112 "Execute body without changing `buffer-modified-p'."
113 `(set-buffer-modified-p
114 (prog1 (buffer-modified-p) ,@body)))
116 (defmacro org-re (s)
117 "Replace posix classes in regular expression."
118 (if (featurep 'xemacs)
119 (let ((ss s))
120 (save-match-data
121 (while (string-match "\\[:alnum:\\]" ss)
122 (setq ss (replace-match "a-zA-Z0-9" t t ss)))
123 (while (string-match "\\[:alpha:\\]" ss)
124 (setq ss (replace-match "a-zA-Z" t t ss)))
125 ss))
128 (defmacro org-preserve-lc (&rest body)
129 `(let ((_line (org-current-line))
130 (_col (current-column)))
131 (unwind-protect
132 (progn ,@body)
133 (goto-line _line)
134 (move-to-column _col))))
136 (defmacro org-without-partial-completion (&rest body)
137 `(let ((pc-mode (and (boundp 'partial-completion-mode)
138 partial-completion-mode)))
139 (unwind-protect
140 (progn
141 (if pc-mode (partial-completion-mode -1))
142 ,@body)
143 (if pc-mode (partial-completion-mode 1)))))
145 ;;; The custom variables
147 (defgroup org nil
148 "Outline-based notes management and organizer."
149 :tag "Org"
150 :group 'outlines
151 :group 'hypermedia
152 :group 'calendar)
154 (defcustom org-load-hook nil
155 "Hook that is run after org.el has been loaded."
156 :group 'org
157 :type 'hook)
159 (defvar org-modules) ; defined below
160 (defvar org-modules-loaded nil
161 "Have the modules been loaded already?")
163 (defun org-load-modules-maybe (&optional force)
164 "Load all extensions listed in `org-default-extensions'."
165 (when (or force (not org-modules-loaded))
166 (mapc (lambda (ext)
167 (condition-case nil (require ext)
168 (error (message "Problems while trying to load feature `%s'" ext))))
169 org-modules)
170 (setq org-modules-loaded t)))
172 (defun org-set-modules (var value)
173 "Set VAR to VALUE and call `org-load-modules-maybe' with the force flag."
174 (set var value)
175 (when (featurep 'org)
176 (org-load-modules-maybe 'force)))
178 (defcustom org-modules '(org-bbdb org-gnus org-info org-irc org-mhe org-rmail org-vm org-wl)
179 "Modules that should always be loaded together with org.el.
180 If the description starts with <A>, this means the extension
181 will be autoloaded when needed, preloading is not necessary.
182 If a description starts with <C>, the file is not part of emacs
183 and loading it will require that you have downloaded and properly installed
184 the org-mode distribution."
185 :group 'org
186 :set 'org-set-modules
187 :type
188 '(set :greedy t
189 (const :tag " bbdb: Links to BBDB entries" org-bbdb)
190 (const :tag " gnus: Links to GNUS folders/messages" org-gnus)
191 (const :tag " info: Links to Info nodes" org-info)
192 (const :tag " irc: Links to IRC/ERC chat sessions" org-irc)
193 (const :tag " mac-message: Links to messages in Apple Mail" org-mac-message)
194 (const :tag " mhe: Links to MHE folders/messages" org-mhe)
195 (const :tag " rmail: Links to RMAIL folders/messages" org-rmail)
196 (const :tag " vm: Links to VM folders/messages" org-vm)
197 (const :tag " wl: Links to Wanderlust folders/messages" org-wl)
198 (const :tag " mouse: Additional mouse support" org-mouse)
199 ; (const :tag "A export-latex: LaTeX export" org-export-latex)
200 ; (const :tag "A publish: Publishing" org-publish)
202 (const :tag "C annotate-file: Annotate a file with org syntax" org-annotate-file)
203 (const :tag "C bibtex: Org links to BibTeX entries" org-bibtex)
204 (const :tag "C depend: TODO dependencies for Org-mode" org-depend)
205 (const :tag "C elisp-symbol: Org links to emacs-lisp symbols" org-elisp-symbol)
206 (const :tag "C expiry: Expiry mechanism for Org entries" org-expiry)
207 (const :tag "C id: Global id's for identifying entries" org-id)
208 (const :tag "C interactive-query: Interactive modification of tags query" org-interactive-query)
209 (const :tag "C iswitchb: Use iswitchb to select Org buffer" org-iswitchb)
210 (const :tag "C mairix: Hook mairix search into Org for different MUAs" org-mairix)
211 (const :tag "C man: Support for links to manpages in Org-mode" org-man)
212 (const :tag "C mew: Support for links to messages in Mew" org-mew)
213 (const :tag "C panel: Simple routines for us with bad memory" org-panel)
214 (const :tag "C registry: A registry for Org links" org-registry)
215 (const :tag "C org2rem: Convert org appointments into reminders" org2rem)
216 (const :tag "C screen: Visit screen sessions through Org-mode links" org-screen)
217 (const :tag "C toc: Table of contents for Org-mode buffer" org-toc)))
219 ;; FIXME: Needs a separate group...
220 (defcustom org-completion-fallback-command 'hippie-expand
221 "The expansion command called by \\[org-complete] in normal context.
222 Normal means, no org-mode-specific context."
223 :group 'org
224 :type 'function)
226 (defgroup org-startup nil
227 "Options concerning startup of Org-mode."
228 :tag "Org Startup"
229 :group 'org)
231 (defcustom org-startup-folded t
232 "Non-nil means, entering Org-mode will switch to OVERVIEW.
233 This can also be configured on a per-file basis by adding one of
234 the following lines anywhere in the buffer:
236 #+STARTUP: fold
237 #+STARTUP: nofold
238 #+STARTUP: content"
239 :group 'org-startup
240 :type '(choice
241 (const :tag "nofold: show all" nil)
242 (const :tag "fold: overview" t)
243 (const :tag "content: all headlines" content)))
245 (defcustom org-startup-truncated t
246 "Non-nil means, entering Org-mode will set `truncate-lines'.
247 This is useful since some lines containing links can be very long and
248 uninteresting. Also tables look terrible when wrapped."
249 :group 'org-startup
250 :type 'boolean)
252 (defcustom org-startup-align-all-tables nil
253 "Non-nil means, align all tables when visiting a file.
254 This is useful when the column width in tables is forced with <N> cookies
255 in table fields. Such tables will look correct only after the first re-align.
256 This can also be configured on a per-file basis by adding one of
257 the following lines anywhere in the buffer:
258 #+STARTUP: align
259 #+STARTUP: noalign"
260 :group 'org-startup
261 :type 'boolean)
263 (defcustom org-insert-mode-line-in-empty-file nil
264 "Non-nil means insert the first line setting Org-mode in empty files.
265 When the function `org-mode' is called interactively in an empty file, this
266 normally means that the file name does not automatically trigger Org-mode.
267 To ensure that the file will always be in Org-mode in the future, a
268 line enforcing Org-mode will be inserted into the buffer, if this option
269 has been set."
270 :group 'org-startup
271 :type 'boolean)
273 (defcustom org-replace-disputed-keys nil
274 "Non-nil means use alternative key bindings for some keys.
275 Org-mode uses S-<cursor> keys for changing timestamps and priorities.
276 These keys are also used by other packages like `CUA-mode' or `windmove.el'.
277 If you want to use Org-mode together with one of these other modes,
278 or more generally if you would like to move some Org-mode commands to
279 other keys, set this variable and configure the keys with the variable
280 `org-disputed-keys'.
282 This option is only relevant at load-time of Org-mode, and must be set
283 *before* org.el is loaded. Changing it requires a restart of Emacs to
284 become effective."
285 :group 'org-startup
286 :type 'boolean)
288 (if (fboundp 'defvaralias)
289 (defvaralias 'org-CUA-compatible 'org-replace-disputed-keys))
291 (defcustom org-disputed-keys
292 '(([(shift up)] . [(meta p)])
293 ([(shift down)] . [(meta n)])
294 ([(shift left)] . [(meta -)])
295 ([(shift right)] . [(meta +)])
296 ([(control shift right)] . [(meta shift +)])
297 ([(control shift left)] . [(meta shift -)]))
298 "Keys for which Org-mode and other modes compete.
299 This is an alist, cars are the default keys, second element specifies
300 the alternative to use when `org-replace-disputed-keys' is t.
302 Keys can be specified in any syntax supported by `define-key'.
303 The value of this option takes effect only at Org-mode's startup,
304 therefore you'll have to restart Emacs to apply it after changing."
305 :group 'org-startup
306 :type 'alist)
308 (defun org-key (key)
309 "Select key according to `org-replace-disputed-keys' and `org-disputed-keys'.
310 Or return the original if not disputed."
311 (if org-replace-disputed-keys
312 (let* ((nkey (key-description key))
313 (x (org-find-if (lambda (x)
314 (equal (key-description (car x)) nkey))
315 org-disputed-keys)))
316 (if x (cdr x) key))
317 key))
319 (defun org-find-if (predicate seq)
320 (catch 'exit
321 (while seq
322 (if (funcall predicate (car seq))
323 (throw 'exit (car seq))
324 (pop seq)))))
326 (defun org-defkey (keymap key def)
327 "Define a key, possibly translated, as returned by `org-key'."
328 (define-key keymap (org-key key) def))
330 (defcustom org-ellipsis nil
331 "The ellipsis to use in the Org-mode outline.
332 When nil, just use the standard three dots. When a string, use that instead,
333 When a face, use the standart 3 dots, but with the specified face.
334 The change affects only Org-mode (which will then use its own display table).
335 Changing this requires executing `M-x org-mode' in a buffer to become
336 effective."
337 :group 'org-startup
338 :type '(choice (const :tag "Default" nil)
339 (face :tag "Face" :value org-warning)
340 (string :tag "String" :value "...#")))
342 (defvar org-display-table nil
343 "The display table for org-mode, in case `org-ellipsis' is non-nil.")
345 (defgroup org-keywords nil
346 "Keywords in Org-mode."
347 :tag "Org Keywords"
348 :group 'org)
350 (defcustom org-deadline-string "DEADLINE:"
351 "String to mark deadline entries.
352 A deadline is this string, followed by a time stamp. Should be a word,
353 terminated by a colon. You can insert a schedule keyword and
354 a timestamp with \\[org-deadline].
355 Changes become only effective after restarting Emacs."
356 :group 'org-keywords
357 :type 'string)
359 (defcustom org-scheduled-string "SCHEDULED:"
360 "String to mark scheduled TODO entries.
361 A schedule is this string, followed by a time stamp. Should be a word,
362 terminated by a colon. You can insert a schedule keyword and
363 a timestamp with \\[org-schedule].
364 Changes become only effective after restarting Emacs."
365 :group 'org-keywords
366 :type 'string)
368 (defcustom org-closed-string "CLOSED:"
369 "String used as the prefix for timestamps logging closing a TODO entry."
370 :group 'org-keywords
371 :type 'string)
373 (defcustom org-clock-string "CLOCK:"
374 "String used as prefix for timestamps clocking work hours on an item."
375 :group 'org-keywords
376 :type 'string)
378 (defcustom org-comment-string "COMMENT"
379 "Entries starting with this keyword will never be exported.
380 An entry can be toggled between COMMENT and normal with
381 \\[org-toggle-comment].
382 Changes become only effective after restarting Emacs."
383 :group 'org-keywords
384 :type 'string)
386 (defcustom org-quote-string "QUOTE"
387 "Entries starting with this keyword will be exported in fixed-width font.
388 Quoting applies only to the text in the entry following the headline, and does
389 not extend beyond the next headline, even if that is lower level.
390 An entry can be toggled between QUOTE and normal with
391 \\[org-toggle-fixed-width-section]."
392 :group 'org-keywords
393 :type 'string)
395 (defconst org-repeat-re
396 "<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [^>\n]*\\([.+]?\\+[0-9]+[dwmy]\\)"
397 "Regular expression for specifying repeated events.
398 After a match, group 1 contains the repeat expression.")
400 (defgroup org-structure nil
401 "Options concerning the general structure of Org-mode files."
402 :tag "Org Structure"
403 :group 'org)
405 (defgroup org-reveal-location nil
406 "Options about how to make context of a location visible."
407 :tag "Org Reveal Location"
408 :group 'org-structure)
410 (defconst org-context-choice
411 '(choice
412 (const :tag "Always" t)
413 (const :tag "Never" nil)
414 (repeat :greedy t :tag "Individual contexts"
415 (cons
416 (choice :tag "Context"
417 (const agenda)
418 (const org-goto)
419 (const occur-tree)
420 (const tags-tree)
421 (const link-search)
422 (const mark-goto)
423 (const bookmark-jump)
424 (const isearch)
425 (const default))
426 (boolean))))
427 "Contexts for the reveal options.")
429 (defcustom org-show-hierarchy-above '((default . t))
430 "Non-nil means, show full hierarchy when revealing a location.
431 Org-mode often shows locations in an org-mode file which might have
432 been invisible before. When this is set, the hierarchy of headings
433 above the exposed location is shown.
434 Turning this off for example for sparse trees makes them very compact.
435 Instead of t, this can also be an alist specifying this option for different
436 contexts. Valid contexts are
437 agenda when exposing an entry from the agenda
438 org-goto when using the command `org-goto' on key C-c C-j
439 occur-tree when using the command `org-occur' on key C-c /
440 tags-tree when constructing a sparse tree based on tags matches
441 link-search when exposing search matches associated with a link
442 mark-goto when exposing the jump goal of a mark
443 bookmark-jump when exposing a bookmark location
444 isearch when exiting from an incremental search
445 default default for all contexts not set explicitly"
446 :group 'org-reveal-location
447 :type org-context-choice)
449 (defcustom org-show-following-heading '((default . nil))
450 "Non-nil means, show following heading when revealing a location.
451 Org-mode often shows locations in an org-mode file which might have
452 been invisible before. When this is set, the heading following the
453 match is shown.
454 Turning this off for example for sparse trees makes them very compact,
455 but makes it harder to edit the location of the match. In such a case,
456 use the command \\[org-reveal] to show more context.
457 Instead of t, this can also be an alist specifying this option for different
458 contexts. See `org-show-hierarchy-above' for valid contexts."
459 :group 'org-reveal-location
460 :type org-context-choice)
462 (defcustom org-show-siblings '((default . nil) (isearch t))
463 "Non-nil means, show all sibling heading when revealing a location.
464 Org-mode often shows locations in an org-mode file which might have
465 been invisible before. When this is set, the sibling of the current entry
466 heading are all made visible. If `org-show-hierarchy-above' is t,
467 the same happens on each level of the hierarchy above the current entry.
469 By default this is on for the isearch context, off for all other contexts.
470 Turning this off for example for sparse trees makes them very compact,
471 but makes it harder to edit the location of the match. In such a case,
472 use the command \\[org-reveal] to show more context.
473 Instead of t, this can also be an alist specifying this option for different
474 contexts. See `org-show-hierarchy-above' for valid contexts."
475 :group 'org-reveal-location
476 :type org-context-choice)
478 (defcustom org-show-entry-below '((default . nil))
479 "Non-nil means, show the entry below a headline when revealing a location.
480 Org-mode often shows locations in an org-mode file which might have
481 been invisible before. When this is set, the text below the headline that is
482 exposed is also shown.
484 By default this is off for all contexts.
485 Instead of t, this can also be an alist specifying this option for different
486 contexts. See `org-show-hierarchy-above' for valid contexts."
487 :group 'org-reveal-location
488 :type org-context-choice)
490 (defgroup org-cycle nil
491 "Options concerning visibility cycling in Org-mode."
492 :tag "Org Cycle"
493 :group 'org-structure)
495 (defcustom org-drawers '("PROPERTIES" "CLOCK")
496 "Names of drawers. Drawers are not opened by cycling on the headline above.
497 Drawers only open with a TAB on the drawer line itself. A drawer looks like
498 this:
499 :DRAWERNAME:
500 .....
501 :END:
502 The drawer \"PROPERTIES\" is special for capturing properties through
503 the property API.
505 Drawers can be defined on the per-file basis with a line like:
507 #+DRAWERS: HIDDEN STATE PROPERTIES"
508 :group 'org-structure
509 :type '(repeat (string :tag "Drawer Name")))
511 (defcustom org-cycle-global-at-bob nil
512 "Cycle globally if cursor is at beginning of buffer and not at a headline.
513 This makes it possible to do global cycling without having to use S-TAB or
514 C-u TAB. For this special case to work, the first line of the buffer
515 must not be a headline - it may be empty ot some other text. When used in
516 this way, `org-cycle-hook' is disables temporarily, to make sure the
517 cursor stays at the beginning of the buffer.
518 When this option is nil, don't do anything special at the beginning
519 of the buffer."
520 :group 'org-cycle
521 :type 'boolean)
523 (defcustom org-cycle-emulate-tab t
524 "Where should `org-cycle' emulate TAB.
525 nil Never
526 white Only in completely white lines
527 whitestart Only at the beginning of lines, before the first non-white char
528 t Everywhere except in headlines
529 exc-hl-bol Everywhere except at the start of a headline
530 If TAB is used in a place where it does not emulate TAB, the current subtree
531 visibility is cycled."
532 :group 'org-cycle
533 :type '(choice (const :tag "Never" nil)
534 (const :tag "Only in completely white lines" white)
535 (const :tag "Before first char in a line" whitestart)
536 (const :tag "Everywhere except in headlines" t)
537 (const :tag "Everywhere except at bol in headlines" exc-hl-bol)
540 (defcustom org-cycle-separator-lines 2
541 "Number of empty lines needed to keep an empty line between collapsed trees.
542 If you leave an empty line between the end of a subtree and the following
543 headline, this empty line is hidden when the subtree is folded.
544 Org-mode will leave (exactly) one empty line visible if the number of
545 empty lines is equal or larger to the number given in this variable.
546 So the default 2 means, at least 2 empty lines after the end of a subtree
547 are needed to produce free space between a collapsed subtree and the
548 following headline.
550 Special case: when 0, never leave empty lines in collapsed view."
551 :group 'org-cycle
552 :type 'integer)
554 (defcustom org-cycle-hook '(org-cycle-hide-archived-subtrees
555 org-cycle-hide-drawers
556 org-cycle-show-empty-lines
557 org-optimize-window-after-visibility-change)
558 "Hook that is run after `org-cycle' has changed the buffer visibility.
559 The function(s) in this hook must accept a single argument which indicates
560 the new state that was set by the most recent `org-cycle' command. The
561 argument is a symbol. After a global state change, it can have the values
562 `overview', `content', or `all'. After a local state change, it can have
563 the values `folded', `children', or `subtree'."
564 :group 'org-cycle
565 :type 'hook)
567 (defgroup org-edit-structure nil
568 "Options concerning structure editing in Org-mode."
569 :tag "Org Edit Structure"
570 :group 'org-structure)
572 (defcustom org-odd-levels-only nil
573 "Non-nil means, skip even levels and only use odd levels for the outline.
574 This has the effect that two stars are being added/taken away in
575 promotion/demotion commands. It also influences how levels are
576 handled by the exporters.
577 Changing it requires restart of `font-lock-mode' to become effective
578 for fontification also in regions already fontified.
579 You may also set this on a per-file basis by adding one of the following
580 lines to the buffer:
582 #+STARTUP: odd
583 #+STARTUP: oddeven"
584 :group 'org-edit-structure
585 :group 'org-font-lock
586 :type 'boolean)
588 (defcustom org-adapt-indentation t
589 "Non-nil means, adapt indentation when promoting and demoting.
590 When this is set and the *entire* text in an entry is indented, the
591 indentation is increased by one space in a demotion command, and
592 decreased by one in a promotion command. If any line in the entry
593 body starts at column 0, indentation is not changed at all."
594 :group 'org-edit-structure
595 :type 'boolean)
597 (defcustom org-special-ctrl-a/e nil
598 "Non-nil means `C-a' and `C-e' behave specially in headlines and items.
599 When t, `C-a' will bring back the cursor to the beginning of the
600 headline text, i.e. after the stars and after a possible TODO keyword.
601 In an item, this will be the position after the bullet.
602 When the cursor is already at that position, another `C-a' will bring
603 it to the beginning of the line.
604 `C-e' will jump to the end of the headline, ignoring the presence of tags
605 in the headline. A second `C-e' will then jump to the true end of the
606 line, after any tags.
607 When set to the symbol `reversed', the first `C-a' or `C-e' works normally,
608 and only a directly following, identical keypress will bring the cursor
609 to the special positions."
610 :group 'org-edit-structure
611 :type '(choice
612 (const :tag "off" nil)
613 (const :tag "after bullet first" t)
614 (const :tag "border first" reversed)))
616 (if (fboundp 'defvaralias)
617 (defvaralias 'org-special-ctrl-a 'org-special-ctrl-a/e))
619 (defcustom org-special-ctrl-k nil
620 "Non-nil means `C-k' will behave specially in headlines.
621 When nil, `C-k' will call the default `kill-line' command.
622 When t, the following will happen while the cursor is in the headline:
624 - When the cursor is at the beginning of a headline, kill the entire
625 line and possible the folded subtree below the line.
626 - When in the middle of the headline text, kill the headline up to the tags.
627 - When after the headline text, kill the tags."
628 :group 'org-edit-structure
629 :type 'boolean)
631 (defcustom org-M-RET-may-split-line '((default . t))
632 "Non-nil means, M-RET will split the line at the cursor position.
633 When nil, it will go to the end of the line before making a
634 new line.
635 You may also set this option in a different way for different
636 contexts. Valid contexts are:
638 headline when creating a new headline
639 item when creating a new item
640 table in a table field
641 default the value to be used for all contexts not explicitly
642 customized"
643 :group 'org-structure
644 :group 'org-table
645 :type '(choice
646 (const :tag "Always" t)
647 (const :tag "Never" nil)
648 (repeat :greedy t :tag "Individual contexts"
649 (cons
650 (choice :tag "Context"
651 (const headline)
652 (const item)
653 (const table)
654 (const default))
655 (boolean)))))
658 (defcustom org-blank-before-new-entry '((heading . nil)
659 (plain-list-item . nil))
660 "Should `org-insert-heading' leave a blank line before new heading/item?
661 The value is an alist, with `heading' and `plain-list-item' as car,
662 and a boolean flag as cdr."
663 :group 'org-edit-structure
664 :type '(list
665 (cons (const heading) (boolean))
666 (cons (const plain-list-item) (boolean))))
668 (defcustom org-insert-heading-hook nil
669 "Hook being run after inserting a new heading."
670 :group 'org-edit-structure
671 :type 'hook)
673 (defcustom org-enable-fixed-width-editor t
674 "Non-nil means, lines starting with \":\" are treated as fixed-width.
675 This currently only means, they are never auto-wrapped.
676 When nil, such lines will be treated like ordinary lines.
677 See also the QUOTE keyword."
678 :group 'org-edit-structure
679 :type 'boolean)
681 (defcustom org-goto-auto-isearch t
682 "Non-nil means, typing characters in org-goto starts incremental search."
683 :group 'org-edit-structure
684 :type 'boolean)
686 (defgroup org-sparse-trees nil
687 "Options concerning sparse trees in Org-mode."
688 :tag "Org Sparse Trees"
689 :group 'org-structure)
691 (defcustom org-highlight-sparse-tree-matches t
692 "Non-nil means, highlight all matches that define a sparse tree.
693 The highlights will automatically disappear the next time the buffer is
694 changed by an edit command."
695 :group 'org-sparse-trees
696 :type 'boolean)
698 (defcustom org-remove-highlights-with-change t
699 "Non-nil means, any change to the buffer will remove temporary highlights.
700 Such highlights are created by `org-occur' and `org-clock-display'.
701 When nil, `C-c C-c needs to be used to get rid of the highlights.
702 The highlights created by `org-preview-latex-fragment' always need
703 `C-c C-c' to be removed."
704 :group 'org-sparse-trees
705 :group 'org-time
706 :type 'boolean)
709 (defcustom org-occur-hook '(org-first-headline-recenter)
710 "Hook that is run after `org-occur' has constructed a sparse tree.
711 This can be used to recenter the window to show as much of the structure
712 as possible."
713 :group 'org-sparse-trees
714 :type 'hook)
716 (defgroup org-plain-lists nil
717 "Options concerning plain lists in Org-mode."
718 :tag "Org Plain lists"
719 :group 'org-structure)
721 (defcustom org-cycle-include-plain-lists nil
722 "Non-nil means, include plain lists into visibility cycling.
723 This means that during cycling, plain list items will *temporarily* be
724 interpreted as outline headlines with a level given by 1000+i where i is the
725 indentation of the bullet. In all other operations, plain list items are
726 not seen as headlines. For example, you cannot assign a TODO keyword to
727 such an item."
728 :group 'org-plain-lists
729 :type 'boolean)
731 (defcustom org-plain-list-ordered-item-terminator t
732 "The character that makes a line with leading number an ordered list item.
733 Valid values are ?. and ?\). To get both terminators, use t. While
734 ?. may look nicer, it creates the danger that a line with leading
735 number may be incorrectly interpreted as an item. ?\) therefore is
736 the safe choice."
737 :group 'org-plain-lists
738 :type '(choice (const :tag "dot like in \"2.\"" ?.)
739 (const :tag "paren like in \"2)\"" ?\))
740 (const :tab "both" t)))
742 (defcustom org-auto-renumber-ordered-lists t
743 "Non-nil means, automatically renumber ordered plain lists.
744 Renumbering happens when the sequence have been changed with
745 \\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands,
746 use \\[org-ctrl-c-ctrl-c] to trigger renumbering."
747 :group 'org-plain-lists
748 :type 'boolean)
750 (defcustom org-provide-checkbox-statistics t
751 "Non-nil means, update checkbox statistics after insert and toggle.
752 When this is set, checkbox statistics is updated each time you either insert
753 a new checkbox with \\[org-insert-todo-heading] or toggle a checkbox
754 with \\[org-ctrl-c-ctrl-c\\]."
755 :group 'org-plain-lists
756 :type 'boolean)
758 (defgroup org-archive nil
759 "Options concerning archiving in Org-mode."
760 :tag "Org Archive"
761 :group 'org-structure)
763 (defcustom org-archive-tag "ARCHIVE"
764 "The tag that marks a subtree as archived.
765 An archived subtree does not open during visibility cycling, and does
766 not contribute to the agenda listings.
767 After changing this, font-lock must be restarted in the relevant buffers to
768 get the proper fontification."
769 :group 'org-archive
770 :group 'org-keywords
771 :type 'string)
773 (defcustom org-agenda-skip-archived-trees t
774 "Non-nil means, the agenda will skip any items located in archived trees.
775 An archived tree is a tree marked with the tag ARCHIVE."
776 :group 'org-archive
777 :group 'org-agenda-skip
778 :type 'boolean)
780 (defcustom org-cycle-open-archived-trees nil
781 "Non-nil means, `org-cycle' will open archived trees.
782 An archived tree is a tree marked with the tag ARCHIVE.
783 When nil, archived trees will stay folded. You can still open them with
784 normal outline commands like `show-all', but not with the cycling commands."
785 :group 'org-archive
786 :group 'org-cycle
787 :type 'boolean)
789 (defcustom org-sparse-tree-open-archived-trees nil
790 "Non-nil means sparse tree construction shows matches in archived trees.
791 When nil, matches in these trees are highlighted, but the trees are kept in
792 collapsed state."
793 :group 'org-archive
794 :group 'org-sparse-trees
795 :type 'boolean)
797 (defcustom org-archive-location "%s_archive::"
798 "The location where subtrees should be archived.
799 This string consists of two parts, separated by a double-colon.
801 The first part is a file name - when omitted, archiving happens in the same
802 file. %s will be replaced by the current file name (without directory part).
803 Archiving to a different file is useful to keep archived entries from
804 contributing to the Org-mode Agenda.
806 The part after the double colon is a headline. The archived entries will be
807 filed under that headline. When omitted, the subtrees are simply filed away
808 at the end of the file, as top-level entries.
810 Here are a few examples:
811 \"%s_archive::\"
812 If the current file is Projects.org, archive in file
813 Projects.org_archive, as top-level trees. This is the default.
815 \"::* Archived Tasks\"
816 Archive in the current file, under the top-level headline
817 \"* Archived Tasks\".
819 \"~/org/archive.org::\"
820 Archive in file ~/org/archive.org (absolute path), as top-level trees.
822 \"basement::** Finished Tasks\"
823 Archive in file ./basement (relative path), as level 3 trees
824 below the level 2 heading \"** Finished Tasks\".
826 You may set this option on a per-file basis by adding to the buffer a
827 line like
829 #+ARCHIVE: basement::** Finished Tasks"
830 :group 'org-archive
831 :type 'string)
833 (defcustom org-archive-mark-done t
834 "Non-nil means, mark entries as DONE when they are moved to the archive file.
835 This can be a string to set the keyword to use. When t, Org-mode will
836 use the first keyword in its list that means done."
837 :group 'org-archive
838 :type '(choice
839 (const :tag "No" nil)
840 (const :tag "Yes" t)
841 (string :tag "Use this keyword")))
843 (defcustom org-archive-stamp-time t
844 "Non-nil means, add a time stamp to entries moved to an archive file.
845 This variable is obsolete and has no effect anymore, instead add ot remove
846 `time' from the variablle `org-archive-save-context-info'."
847 :group 'org-archive
848 :type 'boolean)
850 (defcustom org-archive-save-context-info '(time file olpath category todo itags)
851 "Parts of context info that should be stored as properties when archiving.
852 When a subtree is moved to an archive file, it looses information given by
853 context, like inherited tags, the category, and possibly also the TODO
854 state (depending on the variable `org-archive-mark-done').
855 This variable can be a list of any of the following symbols:
857 time The time of archiving.
858 file The file where the entry originates.
859 itags The local tags, in the headline of the subtree.
860 ltags The tags the subtree inherits from further up the hierarchy.
861 todo The pre-archive TODO state.
862 category The category, taken from file name or #+CATEGORY lines.
863 olpath The outline path to the item. These are all headlines above
864 the current item, separated by /, like a file path.
866 For each symbol present in the list, a property will be created in
867 the archived entry, with a prefix \"PRE_ARCHIVE_\", to remember this
868 information."
869 :group 'org-archive
870 :type '(set :greedy t
871 (const :tag "Time" time)
872 (const :tag "File" file)
873 (const :tag "Category" category)
874 (const :tag "TODO state" todo)
875 (const :tag "TODO state" priority)
876 (const :tag "Inherited tags" itags)
877 (const :tag "Outline path" olpath)
878 (const :tag "Local tags" ltags)))
880 (defgroup org-imenu-and-speedbar nil
881 "Options concerning imenu and speedbar in Org-mode."
882 :tag "Org Imenu and Speedbar"
883 :group 'org-structure)
885 (defcustom org-imenu-depth 2
886 "The maximum level for Imenu access to Org-mode headlines.
887 This also applied for speedbar access."
888 :group 'org-imenu-and-speedbar
889 :type 'number)
891 (defgroup org-table nil
892 "Options concerning tables in Org-mode."
893 :tag "Org Table"
894 :group 'org)
896 (defcustom org-enable-table-editor 'optimized
897 "Non-nil means, lines starting with \"|\" are handled by the table editor.
898 When nil, such lines will be treated like ordinary lines.
900 When equal to the symbol `optimized', the table editor will be optimized to
901 do the following:
902 - Automatic overwrite mode in front of whitespace in table fields.
903 This makes the structure of the table stay in tact as long as the edited
904 field does not exceed the column width.
905 - Minimize the number of realigns. Normally, the table is aligned each time
906 TAB or RET are pressed to move to another field. With optimization this
907 happens only if changes to a field might have changed the column width.
908 Optimization requires replacing the functions `self-insert-command',
909 `delete-char', and `backward-delete-char' in Org-mode buffers, with a
910 slight (in fact: unnoticeable) speed impact for normal typing. Org-mode is
911 very good at guessing when a re-align will be necessary, but you can always
912 force one with \\[org-ctrl-c-ctrl-c].
914 If you would like to use the optimized version in Org-mode, but the
915 un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'.
917 This variable can be used to turn on and off the table editor during a session,
918 but in order to toggle optimization, a restart is required.
920 See also the variable `org-table-auto-blank-field'."
921 :group 'org-table
922 :type '(choice
923 (const :tag "off" nil)
924 (const :tag "on" t)
925 (const :tag "on, optimized" optimized)))
927 (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized)
928 "Non-nil means, use the optimized table editor version for `orgtbl-mode'.
929 In the optimized version, the table editor takes over all simple keys that
930 normally just insert a character. In tables, the characters are inserted
931 in a way to minimize disturbing the table structure (i.e. in overwrite mode
932 for empty fields). Outside tables, the correct binding of the keys is
933 restored.
935 The default for this option is t if the optimized version is also used in
936 Org-mode. See the variable `org-enable-table-editor' for details. Changing
937 this variable requires a restart of Emacs to become effective."
938 :group 'org-table
939 :type 'boolean)
941 (defcustom orgtbl-radio-table-templates
942 '((latex-mode "% BEGIN RECEIVE ORGTBL %n
943 % END RECEIVE ORGTBL %n
944 \\begin{comment}
945 #+ORGTBL: SEND %n orgtbl-to-latex :splice nil :skip 0
946 | | |
947 \\end{comment}\n")
948 (texinfo-mode "@c BEGIN RECEIVE ORGTBL %n
949 @c END RECEIVE ORGTBL %n
950 @ignore
951 #+ORGTBL: SEND %n orgtbl-to-html :splice nil :skip 0
952 | | |
953 @end ignore\n")
954 (html-mode "<!-- BEGIN RECEIVE ORGTBL %n -->
955 <!-- END RECEIVE ORGTBL %n -->
956 <!--
957 #+ORGTBL: SEND %n orgtbl-to-html :splice nil :skip 0
958 | | |
959 -->\n"))
960 "Templates for radio tables in different major modes.
961 All occurrences of %n in a template will be replaced with the name of the
962 table, obtained by prompting the user."
963 :group 'org-table
964 :type '(repeat
965 (list (symbol :tag "Major mode")
966 (string :tag "Format"))))
968 (defgroup org-table-settings nil
969 "Settings for tables in Org-mode."
970 :tag "Org Table Settings"
971 :group 'org-table)
973 (defcustom org-table-default-size "5x2"
974 "The default size for newly created tables, Columns x Rows."
975 :group 'org-table-settings
976 :type 'string)
978 (defcustom org-table-number-regexp
979 "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%:]*\\|\\(0[xX]\\)[0-9a-fA-F]+\\|nan\\)$"
980 "Regular expression for recognizing numbers in table columns.
981 If a table column contains mostly numbers, it will be aligned to the
982 right. If not, it will be aligned to the left.
984 The default value of this option is a regular expression which allows
985 anything which looks remotely like a number as used in scientific
986 context. For example, all of the following will be considered a
987 number:
988 12 12.2 2.4e-08 2x10^12 4.034+-0.02 2.7(10) >3.5
990 Other options offered by the customize interface are more restrictive."
991 :group 'org-table-settings
992 :type '(choice
993 (const :tag "Positive Integers"
994 "^[0-9]+$")
995 (const :tag "Integers"
996 "^[-+]?[0-9]+$")
997 (const :tag "Floating Point Numbers"
998 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.[0-9]*\\)$")
999 (const :tag "Floating Point Number or Integer"
1000 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.?[0-9]*\\)$")
1001 (const :tag "Exponential, Floating point, Integer"
1002 "^[-+]?[0-9.]+\\([eEdD][-+0-9]+\\)?$")
1003 (const :tag "Very General Number-Like, including hex"
1004 "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*\\|\\(0[xX]\\)[0-9a-fA-F]+\\|nan\\)$")
1005 (string :tag "Regexp:")))
1007 (defcustom org-table-number-fraction 0.5
1008 "Fraction of numbers in a column required to make the column align right.
1009 In a column all non-white fields are considered. If at least this
1010 fraction of fields is matched by `org-table-number-fraction',
1011 alignment to the right border applies."
1012 :group 'org-table-settings
1013 :type 'number)
1015 (defgroup org-table-editing nil
1016 "Behavior of tables during editing in Org-mode."
1017 :tag "Org Table Editing"
1018 :group 'org-table)
1020 (defcustom org-table-automatic-realign t
1021 "Non-nil means, automatically re-align table when pressing TAB or RETURN.
1022 When nil, aligning is only done with \\[org-table-align], or after column
1023 removal/insertion."
1024 :group 'org-table-editing
1025 :type 'boolean)
1027 (defcustom org-table-auto-blank-field t
1028 "Non-nil means, automatically blank table field when starting to type into it.
1029 This only happens when typing immediately after a field motion
1030 command (TAB, S-TAB or RET).
1031 Only relevant when `org-enable-table-editor' is equal to `optimized'."
1032 :group 'org-table-editing
1033 :type 'boolean)
1035 (defcustom org-table-tab-jumps-over-hlines t
1036 "Non-nil means, tab in the last column of a table with jump over a hline.
1037 If a horizontal separator line is following the current line,
1038 `org-table-next-field' can either create a new row before that line, or jump
1039 over the line. When this option is nil, a new line will be created before
1040 this line."
1041 :group 'org-table-editing
1042 :type 'boolean)
1044 (defcustom org-table-tab-recognizes-table.el t
1045 "Non-nil means, TAB will automatically notice a table.el table.
1046 When it sees such a table, it moves point into it and - if necessary -
1047 calls `table-recognize-table'."
1048 :group 'org-table-editing
1049 :type 'boolean)
1051 (defgroup org-table-calculation nil
1052 "Options concerning tables in Org-mode."
1053 :tag "Org Table Calculation"
1054 :group 'org-table)
1056 (defcustom org-table-use-standard-references t
1057 "Should org-mode work with table refrences like B3 instead of @3$2?
1058 Possible values are:
1059 nil never use them
1060 from accept as input, do not present for editing
1061 t: accept as input and present for editing"
1062 :group 'org-table-calculation
1063 :type '(choice
1064 (const :tag "Never, don't even check unser input for them" nil)
1065 (const :tag "Always, both as user input, and when editing" t)
1066 (const :tag "Convert user input, don't offer during editing" 'from)))
1068 (defcustom org-table-copy-increment t
1069 "Non-nil means, increment when copying current field with \\[org-table-copy-down]."
1070 :group 'org-table-calculation
1071 :type 'boolean)
1073 (defcustom org-calc-default-modes
1074 '(calc-internal-prec 12
1075 calc-float-format (float 5)
1076 calc-angle-mode deg
1077 calc-prefer-frac nil
1078 calc-symbolic-mode nil
1079 calc-date-format (YYYY "-" MM "-" DD " " Www (" " HH ":" mm))
1080 calc-display-working-message t
1082 "List with Calc mode settings for use in calc-eval for table formulas.
1083 The list must contain alternating symbols (Calc modes variables and values).
1084 Don't remove any of the default settings, just change the values. Org-mode
1085 relies on the variables to be present in the list."
1086 :group 'org-table-calculation
1087 :type 'plist)
1089 (defcustom org-table-formula-evaluate-inline t
1090 "Non-nil means, TAB and RET evaluate a formula in current table field.
1091 If the current field starts with an equal sign, it is assumed to be a formula
1092 which should be evaluated as described in the manual and in the documentation
1093 string of the command `org-table-eval-formula'. This feature requires the
1094 Emacs calc package.
1095 When this variable is nil, formula calculation is only available through
1096 the command \\[org-table-eval-formula]."
1097 :group 'org-table-calculation
1098 :type 'boolean)
1100 (defcustom org-table-formula-use-constants t
1101 "Non-nil means, interpret constants in formulas in tables.
1102 A constant looks like `$c' or `$Grav' and will be replaced before evaluation
1103 by the value given in `org-table-formula-constants', or by a value obtained
1104 from the `constants.el' package."
1105 :group 'org-table-calculation
1106 :type 'boolean)
1108 (defcustom org-table-formula-constants nil
1109 "Alist with constant names and values, for use in table formulas.
1110 The car of each element is a name of a constant, without the `$' before it.
1111 The cdr is the value as a string. For example, if you'd like to use the
1112 speed of light in a formula, you would configure
1114 (setq org-table-formula-constants '((\"c\" . \"299792458.\")))
1116 and then use it in an equation like `$1*$c'.
1118 Constants can also be defined on a per-file basis using a line like
1120 #+CONSTANTS: c=299792458. pi=3.14 eps=2.4e-6"
1121 :group 'org-table-calculation
1122 :type '(repeat
1123 (cons (string :tag "name")
1124 (string :tag "value"))))
1126 (defvar org-table-formula-constants-local nil
1127 "Local version of `org-table-formula-constants'.")
1128 (make-variable-buffer-local 'org-table-formula-constants-local)
1130 (defcustom org-table-allow-automatic-line-recalculation t
1131 "Non-nil means, lines marked with |#| or |*| will be recomputed automatically.
1132 Automatically means, when TAB or RET or C-c C-c are pressed in the line."
1133 :group 'org-table-calculation
1134 :type 'boolean)
1136 (defgroup org-link nil
1137 "Options concerning links in Org-mode."
1138 :tag "Org Link"
1139 :group 'org)
1141 (defvar org-link-abbrev-alist-local nil
1142 "Buffer-local version of `org-link-abbrev-alist', which see.
1143 The value of this is taken from the #+LINK lines.")
1144 (make-variable-buffer-local 'org-link-abbrev-alist-local)
1146 (defcustom org-link-abbrev-alist nil
1147 "Alist of link abbreviations.
1148 The car of each element is a string, to be replaced at the start of a link.
1149 The cdrs are replacement values, like (\"linkkey\" . REPLACE). Abbreviated
1150 links in Org-mode buffers can have an optional tag after a double colon, e.g.
1152 [[linkkey:tag][description]]
1154 If REPLACE is a string, the tag will simply be appended to create the link.
1155 If the string contains \"%s\", the tag will be inserted there.
1157 REPLACE may also be a function that will be called with the tag as the
1158 only argument to create the link, which should be returned as a string.
1160 See the manual for examples."
1161 :group 'org-link
1162 :type 'alist)
1164 (defcustom org-descriptive-links t
1165 "Non-nil means, hide link part and only show description of bracket links.
1166 Bracket links are like [[link][descritpion]]. This variable sets the initial
1167 state in new org-mode buffers. The setting can then be toggled on a
1168 per-buffer basis from the Org->Hyperlinks menu."
1169 :group 'org-link
1170 :type 'boolean)
1172 (defcustom org-link-file-path-type 'adaptive
1173 "How the path name in file links should be stored.
1174 Valid values are:
1176 relative Relative to the current directory, i.e. the directory of the file
1177 into which the link is being inserted.
1178 absolute Absolute path, if possible with ~ for home directory.
1179 noabbrev Absolute path, no abbreviation of home directory.
1180 adaptive Use relative path for files in the current directory and sub-
1181 directories of it. For other files, use an absolute path."
1182 :group 'org-link
1183 :type '(choice
1184 (const relative)
1185 (const absolute)
1186 (const noabbrev)
1187 (const adaptive)))
1189 (defcustom org-activate-links '(bracket angle plain radio tag date)
1190 "Types of links that should be activated in Org-mode files.
1191 This is a list of symbols, each leading to the activation of a certain link
1192 type. In principle, it does not hurt to turn on most link types - there may
1193 be a small gain when turning off unused link types. The types are:
1195 bracket The recommended [[link][description]] or [[link]] links with hiding.
1196 angular Links in angular brackes that may contain whitespace like
1197 <bbdb:Carsten Dominik>.
1198 plain Plain links in normal text, no whitespace, like http://google.com.
1199 radio Text that is matched by a radio target, see manual for details.
1200 tag Tag settings in a headline (link to tag search).
1201 date Time stamps (link to calendar).
1203 Changing this variable requires a restart of Emacs to become effective."
1204 :group 'org-link
1205 :type '(set (const :tag "Double bracket links (new style)" bracket)
1206 (const :tag "Angular bracket links (old style)" angular)
1207 (const :tag "Plain text links" plain)
1208 (const :tag "Radio target matches" radio)
1209 (const :tag "Tags" tag)
1210 (const :tag "Timestamps" date)))
1212 (defgroup org-link-store nil
1213 "Options concerning storing links in Org-mode."
1214 :tag "Org Store Link"
1215 :group 'org-link)
1217 (defcustom org-email-link-description-format "Email %c: %.30s"
1218 "Format of the description part of a link to an email or usenet message.
1219 The following %-excapes will be replaced by corresponding information:
1221 %F full \"From\" field
1222 %f name, taken from \"From\" field, address if no name
1223 %T full \"To\" field
1224 %t first name in \"To\" field, address if no name
1225 %c correspondent. Unually \"from NAME\", but if you sent it yourself, it
1226 will be \"to NAME\". See also the variable `org-from-is-user-regexp'.
1227 %s subject
1228 %m message-id.
1230 You may use normal field width specification between the % and the letter.
1231 This is for example useful to limit the length of the subject.
1233 Examples: \"%f on: %.30s\", \"Email from %f\", \"Email %c\""
1234 :group 'org-link-store
1235 :type 'string)
1237 (defcustom org-from-is-user-regexp
1238 (let (r1 r2)
1239 (when (and user-mail-address (not (string= user-mail-address "")))
1240 (setq r1 (concat "\\<" (regexp-quote user-mail-address) "\\>")))
1241 (when (and user-full-name (not (string= user-full-name "")))
1242 (setq r2 (concat "\\<" (regexp-quote user-full-name) "\\>")))
1243 (if (and r1 r2) (concat r1 "\\|" r2) (or r1 r2)))
1244 "Regexp mached against the \"From:\" header of an email or usenet message.
1245 It should match if the message is from the user him/herself."
1246 :group 'org-link-store
1247 :type 'regexp)
1249 (defcustom org-context-in-file-links t
1250 "Non-nil means, file links from `org-store-link' contain context.
1251 A search string will be added to the file name with :: as separator and
1252 used to find the context when the link is activated by the command
1253 `org-open-at-point'.
1254 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
1255 negates this setting for the duration of the command."
1256 :group 'org-link-store
1257 :type 'boolean)
1259 (defcustom org-keep-stored-link-after-insertion nil
1260 "Non-nil means, keep link in list for entire session.
1262 The command `org-store-link' adds a link pointing to the current
1263 location to an internal list. These links accumulate during a session.
1264 The command `org-insert-link' can be used to insert links into any
1265 Org-mode file (offering completion for all stored links). When this
1266 option is nil, every link which has been inserted once using \\[org-insert-link]
1267 will be removed from the list, to make completing the unused links
1268 more efficient."
1269 :group 'org-link-store
1270 :type 'boolean)
1272 (defgroup org-link-follow nil
1273 "Options concerning following links in Org-mode."
1274 :tag "Org Follow Link"
1275 :group 'org-link)
1277 (defcustom org-follow-link-hook nil
1278 "Hook that is run after a link has been followed."
1279 :group 'org-link-follow
1280 :type 'hook)
1282 (defcustom org-tab-follows-link nil
1283 "Non-nil means, on links TAB will follow the link.
1284 Needs to be set before org.el is loaded."
1285 :group 'org-link-follow
1286 :type 'boolean)
1288 (defcustom org-return-follows-link nil
1289 "Non-nil means, on links RET will follow the link.
1290 Needs to be set before org.el is loaded."
1291 :group 'org-link-follow
1292 :type 'boolean)
1294 (defcustom org-mouse-1-follows-link
1295 (if (boundp 'mouse-1-click-follows-link) mouse-1-click-follows-link t)
1296 "Non-nil means, mouse-1 on a link will follow the link.
1297 A longer mouse click will still set point. Does not work on XEmacs.
1298 Needs to be set before org.el is loaded."
1299 :group 'org-link-follow
1300 :type 'boolean)
1302 (defcustom org-mark-ring-length 4
1303 "Number of different positions to be recorded in the ring
1304 Changing this requires a restart of Emacs to work correctly."
1305 :group 'org-link-follow
1306 :type 'interger)
1308 (defcustom org-link-frame-setup
1309 '((vm . vm-visit-folder-other-frame)
1310 (gnus . gnus-other-frame)
1311 (file . find-file-other-window))
1312 "Setup the frame configuration for following links.
1313 When following a link with Emacs, it may often be useful to display
1314 this link in another window or frame. This variable can be used to
1315 set this up for the different types of links.
1316 For VM, use any of
1317 `vm-visit-folder'
1318 `vm-visit-folder-other-frame'
1319 For Gnus, use any of
1320 `gnus'
1321 `gnus-other-frame'
1322 For FILE, use any of
1323 `find-file'
1324 `find-file-other-window'
1325 `find-file-other-frame'
1326 For the calendar, use the variable `calendar-setup'.
1327 For BBDB, it is currently only possible to display the matches in
1328 another window."
1329 :group 'org-link-follow
1330 :type '(list
1331 (cons (const vm)
1332 (choice
1333 (const vm-visit-folder)
1334 (const vm-visit-folder-other-window)
1335 (const vm-visit-folder-other-frame)))
1336 (cons (const gnus)
1337 (choice
1338 (const gnus)
1339 (const gnus-other-frame)))
1340 (cons (const file)
1341 (choice
1342 (const find-file)
1343 (const find-file-other-window)
1344 (const find-file-other-frame)))))
1346 (defcustom org-display-internal-link-with-indirect-buffer nil
1347 "Non-nil means, use indirect buffer to display infile links.
1348 Activating internal links (from one location in a file to another location
1349 in the same file) normally just jumps to the location. When the link is
1350 activated with a C-u prefix (or with mouse-3), the link is displayed in
1351 another window. When this option is set, the other window actually displays
1352 an indirect buffer clone of the current buffer, to avoid any visibility
1353 changes to the current buffer."
1354 :group 'org-link-follow
1355 :type 'boolean)
1357 (defcustom org-open-non-existing-files nil
1358 "Non-nil means, `org-open-file' will open non-existing files.
1359 When nil, an error will be generated."
1360 :group 'org-link-follow
1361 :type 'boolean)
1363 (defcustom org-link-mailto-program '(browse-url "mailto:%a?subject=%s")
1364 "Function and arguments to call for following mailto links.
1365 This is a list with the first element being a lisp function, and the
1366 remaining elements being arguments to the function. In string arguments,
1367 %a will be replaced by the address, and %s will be replaced by the subject
1368 if one was given like in <mailto:arthur@galaxy.org::this subject>."
1369 :group 'org-link-follow
1370 :type '(choice
1371 (const :tag "browse-url" (browse-url-mail "mailto:%a?subject=%s"))
1372 (const :tag "compose-mail" (compose-mail "%a" "%s"))
1373 (const :tag "message-mail" (message-mail "%a" "%s"))
1374 (cons :tag "other" (function) (repeat :tag "argument" sexp))))
1376 (defcustom org-confirm-shell-link-function 'yes-or-no-p
1377 "Non-nil means, ask for confirmation before executing shell links.
1378 Shell links can be dangerous: just think about a link
1380 [[shell:rm -rf ~/*][Google Search]]
1382 This link would show up in your Org-mode document as \"Google Search\",
1383 but really it would remove your entire home directory.
1384 Therefore we advise against setting this variable to nil.
1385 Just change it to `y-or-n-p' of you want to confirm with a
1386 single keystroke rather than having to type \"yes\"."
1387 :group 'org-link-follow
1388 :type '(choice
1389 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1390 (const :tag "with y-or-n (faster)" y-or-n-p)
1391 (const :tag "no confirmation (dangerous)" nil)))
1393 (defcustom org-confirm-elisp-link-function 'yes-or-no-p
1394 "Non-nil means, ask for confirmation before executing Emacs Lisp links.
1395 Elisp links can be dangerous: just think about a link
1397 [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]]
1399 This link would show up in your Org-mode document as \"Google Search\",
1400 but really it would remove your entire home directory.
1401 Therefore we advise against setting this variable to nil.
1402 Just change it to `y-or-n-p' of you want to confirm with a
1403 single keystroke rather than having to type \"yes\"."
1404 :group 'org-link-follow
1405 :type '(choice
1406 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1407 (const :tag "with y-or-n (faster)" y-or-n-p)
1408 (const :tag "no confirmation (dangerous)" nil)))
1410 (defconst org-file-apps-defaults-gnu
1411 '((remote . emacs)
1412 (t . mailcap))
1413 "Default file applications on a UNIX or GNU/Linux system.
1414 See `org-file-apps'.")
1416 (defconst org-file-apps-defaults-macosx
1417 '((remote . emacs)
1418 (t . "open %s")
1419 ("ps" . "gv %s")
1420 ("ps.gz" . "gv %s")
1421 ("eps" . "gv %s")
1422 ("eps.gz" . "gv %s")
1423 ("dvi" . "xdvi %s")
1424 ("fig" . "xfig %s"))
1425 "Default file applications on a MacOS X system.
1426 The system \"open\" is known as a default, but we use X11 applications
1427 for some files for which the OS does not have a good default.
1428 See `org-file-apps'.")
1430 (defconst org-file-apps-defaults-windowsnt
1431 (list
1432 '(remote . emacs)
1433 (cons t
1434 (list (if (featurep 'xemacs)
1435 'mswindows-shell-execute
1436 'w32-shell-execute)
1437 "open" 'file)))
1438 "Default file applications on a Windows NT system.
1439 The system \"open\" is used for most files.
1440 See `org-file-apps'.")
1442 (defcustom org-file-apps
1444 ("txt" . emacs)
1445 ("tex" . emacs)
1446 ("ltx" . emacs)
1447 ("org" . emacs)
1448 ("el" . emacs)
1449 ("bib" . emacs)
1451 "External applications for opening `file:path' items in a document.
1452 Org-mode uses system defaults for different file types, but
1453 you can use this variable to set the application for a given file
1454 extension. The entries in this list are cons cells where the car identifies
1455 files and the cdr the corresponding command. Possible values for the
1456 file identifier are
1457 \"ext\" A string identifying an extension
1458 `directory' Matches a directory
1459 `remote' Matches a remote file, accessible through tramp or efs.
1460 Remote files most likely should be visited through Emacs
1461 because external applications cannot handle such paths.
1462 t Default for all remaining files
1464 Possible values for the command are:
1465 `emacs' The file will be visited by the current Emacs process.
1466 `default' Use the default application for this file type.
1467 string A command to be executed by a shell; %s will be replaced
1468 by the path to the file.
1469 sexp A Lisp form which will be evaluated. The file path will
1470 be available in the Lisp variable `file'.
1471 For more examples, see the system specific constants
1472 `org-file-apps-defaults-macosx'
1473 `org-file-apps-defaults-windowsnt'
1474 `org-file-apps-defaults-gnu'."
1475 :group 'org-link-follow
1476 :type '(repeat
1477 (cons (choice :value ""
1478 (string :tag "Extension")
1479 (const :tag "Default for unrecognized files" t)
1480 (const :tag "Remote file" remote)
1481 (const :tag "Links to a directory" directory))
1482 (choice :value ""
1483 (const :tag "Visit with Emacs" emacs)
1484 (const :tag "Use system default" default)
1485 (string :tag "Command")
1486 (sexp :tag "Lisp form")))))
1488 (defgroup org-remember nil
1489 "Options concerning interaction with remember.el."
1490 :tag "Org Remember"
1491 :group 'org)
1493 (defcustom org-directory "~/org"
1494 "Directory with org files.
1495 This directory will be used as default to prompt for org files.
1496 Used by the hooks for remember.el."
1497 :group 'org-remember
1498 :type 'directory)
1500 (defcustom org-default-notes-file "~/.notes"
1501 "Default target for storing notes.
1502 Used by the hooks for remember.el. This can be a string, or nil to mean
1503 the value of `remember-data-file'.
1504 You can set this on a per-template basis with the variable
1505 `org-remember-templates'."
1506 :group 'org-remember
1507 :type '(choice
1508 (const :tag "Default from remember-data-file" nil)
1509 file))
1511 (defcustom org-remember-store-without-prompt t
1512 "Non-nil means, `C-c C-c' stores remember note without further promts.
1513 In this case, you need `C-u C-c C-c' to get the prompts for
1514 note file and headline.
1515 When this variable is nil, `C-c C-c' give you the prompts, and
1516 `C-u C-c C-c' trigger the fasttrack."
1517 :group 'org-remember
1518 :type 'boolean)
1520 (defcustom org-remember-interactive-interface 'refile
1521 "The interface to be used for interactive filing of remember notes.
1522 This is only used when the interactive mode for selecting a filing
1523 location is used (see the variable `org-remember-store-without-prompt').
1524 Allowed vaues are:
1525 outline The interface shows an outline of the relevant file
1526 and the correct heading is found by moving through
1527 the outline or by searching with incremental search.
1528 outline-path-completion Headlines in the current buffer are offered via
1529 completion.
1530 refile Use the refile interface, and offer headlines,
1531 possibly from different buffers."
1532 :group 'org-remember
1533 :type '(choice
1534 (const :tag "Refile" refile)
1535 (const :tag "Outline" outline)
1536 (const :tag "Outline-path-completion" outline-path-completion)))
1538 (defcustom org-goto-interface 'outline
1539 "The default interface to be used for `org-goto'.
1540 Allowed vaues are:
1541 outline The interface shows an outline of the relevant file
1542 and the correct heading is found by moving through
1543 the outline or by searching with incremental search.
1544 outline-path-completion Headlines in the current buffer are offered via
1545 completion."
1546 :group 'org-remember ; FIXME: different group for org-goto and org-refile
1547 :type '(choice
1548 (const :tag "Outline" outline)
1549 (const :tag "Outline-path-completion" outline-path-completion)))
1551 (defcustom org-remember-default-headline ""
1552 "The headline that should be the default location in the notes file.
1553 When filing remember notes, the cursor will start at that position.
1554 You can set this on a per-template basis with the variable
1555 `org-remember-templates'."
1556 :group 'org-remember
1557 :type 'string)
1559 (defcustom org-remember-templates nil
1560 "Templates for the creation of remember buffers.
1561 When nil, just let remember make the buffer.
1562 When not nil, this is a list of 5-element lists. In each entry, the first
1563 element is the name of the template, which should be a single short word.
1564 The second element is a character, a unique key to select this template.
1565 The third element is the template. The fourth element is optional and can
1566 specify a destination file for remember items created with this template.
1567 The default file is given by `org-default-notes-file'. An optional fifth
1568 element can specify the headline in that file that should be offered
1569 first when the user is asked to file the entry. The default headline is
1570 given in the variable `org-remember-default-headline'.
1572 An optional sixth element specifies the contexts in which the user can
1573 select the template. This element can be either a list of major modes
1574 or a function. `org-remember' will first check whether the function
1575 returns `t' or if we are in any of the listed major modes, and select
1576 the template accordingly.
1578 The template specifies the structure of the remember buffer. It should have
1579 a first line starting with a star, to act as the org-mode headline.
1580 Furthermore, the following %-escapes will be replaced with content:
1582 %^{prompt} Prompt the user for a string and replace this sequence with it.
1583 A default value and a completion table ca be specified like this:
1584 %^{prompt|default|completion2|completion3|...}
1585 %t time stamp, date only
1586 %T time stamp with date and time
1587 %u, %U like the above, but inactive time stamps
1588 %^t like %t, but prompt for date. Similarly %^T, %^u, %^U
1589 You may define a prompt like %^{Please specify birthday}t
1590 %n user name (taken from `user-full-name')
1591 %a annotation, normally the link created with org-store-link
1592 %i initial content, the region active. If %i is indented,
1593 the entire inserted text will be indented as well.
1594 %c content of the clipboard, or current kill ring head
1595 %^g prompt for tags, with completion on tags in target file
1596 %^G prompt for tags, with completion all tags in all agenda files
1597 %:keyword specific information for certain link types, see below
1598 %[pathname] insert the contents of the file given by `pathname'
1599 %(sexp) evaluate elisp `(sexp)' and replace with the result
1600 %! Store this note immediately after filling the template
1602 %? After completing the template, position cursor here.
1604 Apart from these general escapes, you can access information specific to the
1605 link type that is created. For example, calling `remember' in emails or gnus
1606 will record the author and the subject of the message, which you can access
1607 with %:author and %:subject, respectively. Here is a complete list of what
1608 is recorded for each link type.
1610 Link type | Available information
1611 -------------------+------------------------------------------------------
1612 bbdb | %:type %:name %:company
1613 vm, wl, mh, rmail | %:type %:subject %:message-id
1614 | %:from %:fromname %:fromaddress
1615 | %:to %:toname %:toaddress
1616 | %:fromto (either \"to NAME\" or \"from NAME\")
1617 gnus | %:group, for messages also all email fields
1618 w3, w3m | %:type %:url
1619 info | %:type %:file %:node
1620 calendar | %:type %:date"
1621 :group 'org-remember
1622 :get (lambda (var) ; Make sure all entries have at least 5 elements
1623 (mapcar (lambda (x)
1624 (if (not (stringp (car x))) (setq x (cons "" x)))
1625 (cond ((= (length x) 4) (append x '("")))
1626 ((= (length x) 3) (append x '("" "")))
1627 (t x)))
1628 (default-value var)))
1629 :type '(repeat
1630 :tag "enabled"
1631 (list :value ("" ?a "\n" nil nil nil)
1632 (string :tag "Name")
1633 (character :tag "Selection Key")
1634 (string :tag "Template")
1635 (choice
1636 (file :tag "Destination file")
1637 (const :tag "Prompt for file" nil))
1638 (choice
1639 (string :tag "Destination headline")
1640 (const :tag "Selection interface for heading"))
1641 (choice
1642 (const :tag "Use by default" nil)
1643 (const :tag "Use in all contexts" t)
1644 (repeat :tag "Use only if in major mode"
1645 (symbol :tag "Major mode"))
1646 (function :tag "Perform a check against function")))))
1648 (defcustom org-reverse-note-order nil
1649 "Non-nil means, store new notes at the beginning of a file or entry.
1650 When nil, new notes will be filed to the end of a file or entry.
1651 This can also be a list with cons cells of regular expressions that
1652 are matched against file names, and values."
1653 :group 'org-remember
1654 :type '(choice
1655 (const :tag "Reverse always" t)
1656 (const :tag "Reverse never" nil)
1657 (repeat :tag "By file name regexp"
1658 (cons regexp boolean))))
1660 (defcustom org-refile-targets nil
1661 "Targets for refiling entries with \\[org-refile].
1662 This is list of cons cells. Each cell contains:
1663 - a specification of the files to be considered, either a list of files,
1664 or a symbol whose function or value fields will be used to retrieve
1665 a file name or a list of file names. Nil means, refile to a different
1666 heading in the current buffer.
1667 - A specification of how to find candidate refile targets. This may be
1668 any of
1669 - a cons cell (:tag . \"TAG\") to identify refile targets by a tag.
1670 This tag has to be present in all target headlines, inheritance will
1671 not be considered.
1672 - a cons cell (:todo . \"KEYWORD\") to identify refile targets by
1673 todo keyword.
1674 - a cons cell (:regexp . \"REGEXP\") with a regular expression matching
1675 headlines that are refiling targets.
1676 - a cons cell (:level . N). Any headline of level N is considered a target.
1677 - a cons cell (:maxlevel . N). Any headline with level <= N is a target."
1678 ;; FIXME: what if there are a var and func with same name???
1679 :group 'org-remember
1680 :type '(repeat
1681 (cons
1682 (choice :value org-agenda-files
1683 (const :tag "All agenda files" org-agenda-files)
1684 (const :tag "Current buffer" nil)
1685 (function) (variable) (file))
1686 (choice :tag "Identify target headline by"
1687 (cons :tag "Specific tag" (const :tag) (string))
1688 (cons :tag "TODO keyword" (const :todo) (string))
1689 (cons :tag "Regular expression" (const :regexp) (regexp))
1690 (cons :tag "Level number" (const :level) (integer))
1691 (cons :tag "Max Level number" (const :maxlevel) (integer))))))
1693 (defcustom org-refile-use-outline-path nil
1694 "Non-nil means, provide refile targets as paths.
1695 So a level 3 headline will be available as level1/level2/level3.
1696 When the value is `file', also include the file name (without directory)
1697 into the path. When `full-file-path', include the full file path."
1698 :group 'org-remember
1699 :type '(choice
1700 (const :tag "Not" nil)
1701 (const :tag "Yes" t)
1702 (const :tag "Start with file name" file)
1703 (const :tag "Start with full file path" full-file-path)))
1705 (defgroup org-todo nil
1706 "Options concerning TODO items in Org-mode."
1707 :tag "Org TODO"
1708 :group 'org)
1710 (defgroup org-progress nil
1711 "Options concerning Progress logging in Org-mode."
1712 :tag "Org Progress"
1713 :group 'org-time)
1715 (defcustom org-todo-keywords '((sequence "TODO" "DONE"))
1716 "List of TODO entry keyword sequences and their interpretation.
1717 \\<org-mode-map>This is a list of sequences.
1719 Each sequence starts with a symbol, either `sequence' or `type',
1720 indicating if the keywords should be interpreted as a sequence of
1721 action steps, or as different types of TODO items. The first
1722 keywords are states requiring action - these states will select a headline
1723 for inclusion into the global TODO list Org-mode produces. If one of
1724 the \"keywords\" is the vertical bat \"|\" the remaining keywords
1725 signify that no further action is necessary. If \"|\" is not found,
1726 the last keyword is treated as the only DONE state of the sequence.
1728 The command \\[org-todo] cycles an entry through these states, and one
1729 additional state where no keyword is present. For details about this
1730 cycling, see the manual.
1732 TODO keywords and interpretation can also be set on a per-file basis with
1733 the special #+SEQ_TODO and #+TYP_TODO lines.
1735 Each keyword can optionally specify a character for fast state selection
1736 \(in combination with the variable `org-use-fast-todo-selection')
1737 and specifiers for state change logging, using the same syntax
1738 that is used in the \"#+TODO:\" lines. For example, \"WAIT(w)\" says
1739 that the WAIT state can be selected with the \"w\" key. \"WAIT(w!)\"
1740 indicates to record a time stamp each time this state is selected.
1742 Each keyword may also specify if a timestamp or a note should be
1743 recorded when entering or leaving the state, by adding additional
1744 characters in the parenthesis after the keyword. This looks like this:
1745 \"WAIT(w@/!)\". \"@\" means to add a note (with time), \"!\" means to
1746 record only the time of the state change. With X and Y being either
1747 \"@\" or \"!\", \"X/Y\" means use X when entering the state, and use
1748 Y when leaving the state if and only if the *target* state does not
1749 define X. You may omit any of the fast-selection key or X or /Y,
1750 so WAIT(w@), WAIT(w/@) and WAIT(@/@) are all valid.
1752 For backward compatibility, this variable may also be just a list
1753 of keywords - in this case the interptetation (sequence or type) will be
1754 taken from the (otherwise obsolete) variable `org-todo-interpretation'."
1755 :group 'org-todo
1756 :group 'org-keywords
1757 :type '(choice
1758 (repeat :tag "Old syntax, just keywords"
1759 (string :tag "Keyword"))
1760 (repeat :tag "New syntax"
1761 (cons
1762 (choice
1763 :tag "Interpretation"
1764 (const :tag "Sequence (cycling hits every state)" sequence)
1765 (const :tag "Type (cycling directly to DONE)" type))
1766 (repeat
1767 (string :tag "Keyword"))))))
1769 (defvar org-todo-keywords-1 nil
1770 "All TODO and DONE keywords active in a buffer.")
1771 (make-variable-buffer-local 'org-todo-keywords-1)
1772 (defvar org-todo-keywords-for-agenda nil)
1773 (defvar org-done-keywords-for-agenda nil)
1774 (defvar org-not-done-keywords nil)
1775 (make-variable-buffer-local 'org-not-done-keywords)
1776 (defvar org-done-keywords nil)
1777 (make-variable-buffer-local 'org-done-keywords)
1778 (defvar org-todo-heads nil)
1779 (make-variable-buffer-local 'org-todo-heads)
1780 (defvar org-todo-sets nil)
1781 (make-variable-buffer-local 'org-todo-sets)
1782 (defvar org-todo-log-states nil)
1783 (make-variable-buffer-local 'org-todo-log-states)
1784 (defvar org-todo-kwd-alist nil)
1785 (make-variable-buffer-local 'org-todo-kwd-alist)
1786 (defvar org-todo-key-alist nil)
1787 (make-variable-buffer-local 'org-todo-key-alist)
1788 (defvar org-todo-key-trigger nil)
1789 (make-variable-buffer-local 'org-todo-key-trigger)
1791 (defcustom org-todo-interpretation 'sequence
1792 "Controls how TODO keywords are interpreted.
1793 This variable is in principle obsolete and is only used for
1794 backward compatibility, if the interpretation of todo keywords is
1795 not given already in `org-todo-keywords'. See that variable for
1796 more information."
1797 :group 'org-todo
1798 :group 'org-keywords
1799 :type '(choice (const sequence)
1800 (const type)))
1802 (defcustom org-use-fast-todo-selection 'prefix
1803 "Non-nil means, use the fast todo selection scheme with C-c C-t.
1804 This variable describes if and under what circumstances the cycling
1805 mechanism for TODO keywords will be replaced by a single-key, direct
1806 selection scheme.
1808 When nil, fast selection is never used.
1810 When the symbol `prefix', it will be used when `org-todo' is called with
1811 a prefix argument, i.e. `C-u C-c C-t' in an Org-mode buffer, and `C-u t'
1812 in an agenda buffer.
1814 When t, fast selection is used by default. In this case, the prefix
1815 argument forces cycling instead.
1817 In all cases, the special interface is only used if access keys have actually
1818 been assigned by the user, i.e. if keywords in the configuration are followed
1819 by a letter in parenthesis, like TODO(t)."
1820 :group 'org-todo
1821 :type '(choice
1822 (const :tag "Never" nil)
1823 (const :tag "By default" t)
1824 (const :tag "Only with C-u C-c C-t" prefix)))
1826 (defcustom org-after-todo-state-change-hook nil
1827 "Hook which is run after the state of a TODO item was changed.
1828 The new state (a string with a TODO keyword, or nil) is available in the
1829 Lisp variable `state'."
1830 :group 'org-todo
1831 :type 'hook)
1833 (defcustom org-log-done nil
1834 "Non-nil means, record a CLOSED timestamp when moving an entry to DONE.
1835 When equal to the list (done), also prompt for a closing note.
1836 This can also be configured on a per-file basis by adding one of
1837 the following lines anywhere in the buffer:
1839 #+STARTUP: logdone
1840 #+STARTUP: lognotedone
1841 #+STARTUP: nologdone"
1842 :group 'org-todo
1843 :group 'org-progress
1844 :type '(choice
1845 (const :tag "No logging" nil)
1846 (const :tag "Record CLOSED timestamp" time)
1847 (const :tag "Record CLOSED timestamp with closing note." note)))
1849 ;; Normalize old uses of org-log-done.
1850 (cond
1851 ((eq org-log-done t) (setq org-log-done 'time))
1852 ((and (listp org-log-done) (memq 'done org-log-done))
1853 (setq org-log-done 'note)))
1855 ;; FIXME: document
1856 (defcustom org-log-note-clock-out nil
1857 "Non-nil means, recored a note when clocking out of an item.
1858 This can also be configured on a per-file basis by adding one of
1859 the following lines anywhere in the buffer:
1861 #+STARTUP: lognoteclock-out
1862 #+STARTUP: nolognoteclock-out"
1863 :group 'org-todo
1864 :group 'org-progress
1865 :type 'boolean)
1867 (defcustom org-log-done-with-time t
1868 "Non-nil means, the CLOSED time stamp will contain date and time.
1869 When nil, only the date will be recorded."
1870 :group 'org-progress
1871 :type 'boolean)
1873 (defcustom org-log-note-headings
1874 '((done . "CLOSING NOTE %t")
1875 (state . "State %-12s %t")
1876 (clock-out . ""))
1877 "Headings for notes added when clocking out or closing TODO items.
1878 The value is an alist, with the car being a symbol indicating the note
1879 context, and the cdr is the heading to be used. The heading may also be the
1880 empty string.
1881 %t in the heading will be replaced by a time stamp.
1882 %s will be replaced by the new TODO state, in double quotes.
1883 %u will be replaced by the user name.
1884 %U will be replaced by the full user name."
1885 :group 'org-todo
1886 :group 'org-progress
1887 :type '(list :greedy t
1888 (cons (const :tag "Heading when closing an item" done) string)
1889 (cons (const :tag
1890 "Heading when changing todo state (todo sequence only)"
1891 state) string)
1892 (cons (const :tag "Heading when clocking out" clock-out) string)))
1894 (defcustom org-log-states-order-reversed t
1895 "Non-nil means, the latest state change note will be directly after heading.
1896 When nil, the notes will be orderer according to time."
1897 :group 'org-todo
1898 :group 'org-progress
1899 :type 'boolean)
1901 (defcustom org-log-repeat 'time
1902 "Non-nil means, record moving through the DONE state when triggering repeat.
1903 An auto-repeating tasks is immediately switched back to TODO when marked
1904 done. If you are not logging state changes (by adding \"@\" or \"!\" to
1905 the TODO keyword definition, or recording a cloing note by setting
1906 `org-log-done', there will be no record of the task moving trhough DONE.
1907 This variable forces taking a note anyway. Possible values are:
1909 nil Don't force a record
1910 time Record a time stamp
1911 note Record a note
1913 This option can also be set with on a per-file-basis with
1915 #+STARTUP: logrepeat
1916 #+STARTUP: lognoterepeat
1917 #+STARTUP: nologrepeat
1919 You can have local logging settings for a subtree by setting the LOGGING
1920 property to one or more of these keywords."
1921 :group 'org-todo
1922 :group 'org-progress
1923 :type '(choice
1924 (const :tag "Don't force a record" nil)
1925 (const :tag "Force recording the DONE state" time)
1926 (const :tag "Force recording a note with the DONE state" note)))
1928 (defcustom org-clock-into-drawer 2
1929 "Should clocking info be wrapped into a drawer?
1930 When t, clocking info will always be inserted into a :CLOCK: drawer.
1931 If necessary, the drawer will be created.
1932 When nil, the drawer will not be created, but used when present.
1933 When an integer and the number of clocking entries in an item
1934 reaches or exceeds this number, a drawer will be created."
1935 :group 'org-todo
1936 :group 'org-progress
1937 :type '(choice
1938 (const :tag "Always" t)
1939 (const :tag "Only when drawer exists" nil)
1940 (integer :tag "When at least N clock entries")))
1942 (defcustom org-clock-out-when-done t
1943 "When t, the clock will be stopped when the relevant entry is marked DONE.
1944 Nil means, clock will keep running until stopped explicitly with
1945 `C-c C-x C-o', or until the clock is started in a different item."
1946 :group 'org-progress
1947 :type 'boolean)
1949 (defcustom org-clock-in-switch-to-state nil
1950 "Set task to a special todo state while clocking it.
1951 The value should be the state to which the entry should be switched."
1952 :group 'org-progress
1953 :group 'org-todo
1954 :type '(choice
1955 (const :tag "Don't force a state" nil)
1956 (string :tag "State")))
1958 (defgroup org-priorities nil
1959 "Priorities in Org-mode."
1960 :tag "Org Priorities"
1961 :group 'org-todo)
1963 (defcustom org-highest-priority ?A
1964 "The highest priority of TODO items. A character like ?A, ?B etc.
1965 Must have a smaller ASCII number than `org-lowest-priority'."
1966 :group 'org-priorities
1967 :type 'character)
1969 (defcustom org-lowest-priority ?C
1970 "The lowest priority of TODO items. A character like ?A, ?B etc.
1971 Must have a larger ASCII number than `org-highest-priority'."
1972 :group 'org-priorities
1973 :type 'character)
1975 (defcustom org-default-priority ?B
1976 "The default priority of TODO items.
1977 This is the priority an item get if no explicit priority is given."
1978 :group 'org-priorities
1979 :type 'character)
1981 (defcustom org-priority-start-cycle-with-default t
1982 "Non-nil means, start with default priority when starting to cycle.
1983 When this is nil, the first step in the cycle will be (depending on the
1984 command used) one higher or lower that the default priority."
1985 :group 'org-priorities
1986 :type 'boolean)
1988 (defgroup org-time nil
1989 "Options concerning time stamps and deadlines in Org-mode."
1990 :tag "Org Time"
1991 :group 'org)
1993 (defcustom org-insert-labeled-timestamps-at-point nil
1994 "Non-nil means, SCHEDULED and DEADLINE timestamps are inserted at point.
1995 When nil, these labeled time stamps are forces into the second line of an
1996 entry, just after the headline. When scheduling from the global TODO list,
1997 the time stamp will always be forced into the second line."
1998 :group 'org-time
1999 :type 'boolean)
2001 (defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
2002 "Formats for `format-time-string' which are used for time stamps.
2003 It is not recommended to change this constant.")
2005 (defcustom org-time-stamp-rounding-minutes '(0 5)
2006 "Number of minutes to round time stamps to.
2007 These are two values, the first applies when first creating a time stamp.
2008 The second applies when changing it with the commands `S-up' and `S-down'.
2009 When changing the time stamp, this means that it will change in steps
2010 of N minutes, as given by the second value.
2012 When a setting is 0 or 1, insert the time unmodified. Useful rounding
2013 numbers should be factors of 60, so for example 5, 10, 15.
2015 When this is larger than 1, you can still force an exact time-stamp by using
2016 a double prefix argument to a time-stamp command like `C-c .' or `C-c !',
2017 and by using a prefix arg to `S-up/down' to specify the exact number
2018 of minutes to shift."
2019 :group 'org-time
2020 :get '(lambda (var) ; Make sure all entries have 5 elements
2021 (if (integerp (default-value var))
2022 (list (default-value var) 5)
2023 (default-value var)))
2024 :type '(list
2025 (integer :tag "when inserting times")
2026 (integer :tag "when modifying times")))
2028 ;; Make sure old customizations of this variable don't lead to problems.
2029 (when (integerp org-time-stamp-rounding-minutes)
2030 (setq org-time-stamp-rounding-minutes
2031 (list org-time-stamp-rounding-minutes
2032 org-time-stamp-rounding-minutes)))
2034 (defcustom org-display-custom-times nil
2035 "Non-nil means, overlay custom formats over all time stamps.
2036 The formats are defined through the variable `org-time-stamp-custom-formats'.
2037 To turn this on on a per-file basis, insert anywhere in the file:
2038 #+STARTUP: customtime"
2039 :group 'org-time
2040 :set 'set-default
2041 :type 'sexp)
2042 (make-variable-buffer-local 'org-display-custom-times)
2044 (defcustom org-time-stamp-custom-formats
2045 '("<%m/%d/%y %a>" . "<%m/%d/%y %a %H:%M>") ; american
2046 "Custom formats for time stamps. See `format-time-string' for the syntax.
2047 These are overlayed over the default ISO format if the variable
2048 `org-display-custom-times' is set. Time like %H:%M should be at the
2049 end of the second format."
2050 :group 'org-time
2051 :type 'sexp)
2053 (defun org-time-stamp-format (&optional long inactive)
2054 "Get the right format for a time string."
2055 (let ((f (if long (cdr org-time-stamp-formats)
2056 (car org-time-stamp-formats))))
2057 (if inactive
2058 (concat "[" (substring f 1 -1) "]")
2059 f)))
2061 (defcustom org-read-date-prefer-future t
2062 "Non-nil means, assume future for incomplete date input from user.
2063 This affects the following situations:
2064 1. The user gives a day, but no month.
2065 For example, if today is the 15th, and you enter \"3\", Org-mode will
2066 read this as the third of *next* month. However, if you enter \"17\",
2067 it will be considered as *this* month.
2068 2. The user gives a month but not a year.
2069 For example, if it is april and you enter \"feb 2\", this will be read
2070 as feb 2, *next* year. \"May 5\", however, will be this year.
2072 Currently this does not work for ISO week specifications.
2074 When this option is nil, the current month and year will always be used
2075 as defaults."
2076 :group 'org-time
2077 :type 'boolean)
2079 (defcustom org-read-date-display-live t
2080 "Non-nil means, display current interpretation of date prompt live.
2081 This display will be in an overlay, in the minibuffer."
2082 :group 'org-time
2083 :type 'boolean)
2085 (defcustom org-read-date-popup-calendar t
2086 "Non-nil means, pop up a calendar when prompting for a date.
2087 In the calendar, the date can be selected with mouse-1. However, the
2088 minibuffer will also be active, and you can simply enter the date as well.
2089 When nil, only the minibuffer will be available."
2090 :group 'org-time
2091 :type 'boolean)
2092 (if (fboundp 'defvaralias)
2093 (defvaralias 'org-popup-calendar-for-date-prompt
2094 'org-read-date-popup-calendar))
2096 (defcustom org-extend-today-until 0
2097 "The hour when your day really ends.
2098 This has influence for the following applications:
2099 - When switching the agenda to \"today\". It it is still earlier than
2100 the time given here, the day recognized as TODAY is actually yesterday.
2101 - When a date is read from the user and it is still before the time given
2102 here, the current date and time will be assumed to be yesterday, 23:59.
2104 FIXME:
2105 IMPORTANT: This is still a very experimental feature, it may disappear
2106 again or it may be extended to mean more things."
2107 :group 'org-time
2108 :type 'number)
2110 (defcustom org-edit-timestamp-down-means-later nil
2111 "Non-nil means, S-down will increase the time in a time stamp.
2112 When nil, S-up will increase."
2113 :group 'org-time
2114 :type 'boolean)
2116 (defcustom org-calendar-follow-timestamp-change t
2117 "Non-nil means, make the calendar window follow timestamp changes.
2118 When a timestamp is modified and the calendar window is visible, it will be
2119 moved to the new date."
2120 :group 'org-time
2121 :type 'boolean)
2123 (defcustom org-clock-heading-function nil
2124 "When non-nil, should be a function to create `org-clock-heading'.
2125 This is the string shown in the mode line when a clock is running.
2126 The function is called with point at the beginning of the headline."
2127 :group 'org-time ; FIXME: Should we have a separate group????
2128 :type 'function)
2130 (defgroup org-tags nil
2131 "Options concerning tags in Org-mode."
2132 :tag "Org Tags"
2133 :group 'org)
2135 (defcustom org-tag-alist nil
2136 "List of tags allowed in Org-mode files.
2137 When this list is nil, Org-mode will base TAG input on what is already in the
2138 buffer.
2139 The value of this variable is an alist, the car of each entry must be a
2140 keyword as a string, the cdr may be a character that is used to select
2141 that tag through the fast-tag-selection interface.
2142 See the manual for details."
2143 :group 'org-tags
2144 :type '(repeat
2145 (choice
2146 (cons (string :tag "Tag name")
2147 (character :tag "Access char"))
2148 (const :tag "Start radio group" (:startgroup))
2149 (const :tag "End radio group" (:endgroup)))))
2151 (defcustom org-use-fast-tag-selection 'auto
2152 "Non-nil means, use fast tag selection scheme.
2153 This is a special interface to select and deselect tags with single keys.
2154 When nil, fast selection is never used.
2155 When the symbol `auto', fast selection is used if and only if selection
2156 characters for tags have been configured, either through the variable
2157 `org-tag-alist' or through a #+TAGS line in the buffer.
2158 When t, fast selection is always used and selection keys are assigned
2159 automatically if necessary."
2160 :group 'org-tags
2161 :type '(choice
2162 (const :tag "Always" t)
2163 (const :tag "Never" nil)
2164 (const :tag "When selection characters are configured" 'auto)))
2166 (defcustom org-fast-tag-selection-single-key nil
2167 "Non-nil means, fast tag selection exits after first change.
2168 When nil, you have to press RET to exit it.
2169 During fast tag selection, you can toggle this flag with `C-c'.
2170 This variable can also have the value `expert'. In this case, the window
2171 displaying the tags menu is not even shown, until you press C-c again."
2172 :group 'org-tags
2173 :type '(choice
2174 (const :tag "No" nil)
2175 (const :tag "Yes" t)
2176 (const :tag "Expert" expert)))
2178 (defvar org-fast-tag-selection-include-todo nil
2179 "Non-nil means, fast tags selection interface will also offer TODO states.
2180 This is an undocumented feature, you should not rely on it.")
2182 (defcustom org-tags-column -80
2183 "The column to which tags should be indented in a headline.
2184 If this number is positive, it specifies the column. If it is negative,
2185 it means that the tags should be flushright to that column. For example,
2186 -80 works well for a normal 80 character screen."
2187 :group 'org-tags
2188 :type 'integer)
2190 (defcustom org-auto-align-tags t
2191 "Non-nil means, realign tags after pro/demotion of TODO state change.
2192 These operations change the length of a headline and therefore shift
2193 the tags around. With this options turned on, after each such operation
2194 the tags are again aligned to `org-tags-column'."
2195 :group 'org-tags
2196 :type 'boolean)
2198 (defcustom org-use-tag-inheritance t
2199 "Non-nil means, tags in levels apply also for sublevels.
2200 When nil, only the tags directly given in a specific line apply there.
2201 If you turn off this option, you very likely want to turn on the
2202 companion option `org-tags-match-list-sublevels'."
2203 :group 'org-tags
2204 :type 'boolean)
2206 (defcustom org-tags-match-list-sublevels nil
2207 "Non-nil means list also sublevels of headlines matching tag search.
2208 Because of tag inheritance (see variable `org-use-tag-inheritance'),
2209 the sublevels of a headline matching a tag search often also match
2210 the same search. Listing all of them can create very long lists.
2211 Setting this variable to nil causes subtrees of a match to be skipped.
2212 This option is off by default, because inheritance in on. If you turn
2213 inheritance off, you very likely want to turn this option on.
2215 As a special case, if the tag search is restricted to TODO items, the
2216 value of this variable is ignored and sublevels are always checked, to
2217 make sure all corresponding TODO items find their way into the list."
2218 :group 'org-tags
2219 :type 'boolean)
2221 (defvar org-tags-history nil
2222 "History of minibuffer reads for tags.")
2223 (defvar org-last-tags-completion-table nil
2224 "The last used completion table for tags.")
2225 (defvar org-after-tags-change-hook nil
2226 "Hook that is run after the tags in a line have changed.")
2228 (defgroup org-properties nil
2229 "Options concerning properties in Org-mode."
2230 :tag "Org Properties"
2231 :group 'org)
2233 (defcustom org-property-format "%-10s %s"
2234 "How property key/value pairs should be formatted by `indent-line'.
2235 When `indent-line' hits a property definition, it will format the line
2236 according to this format, mainly to make sure that the values are
2237 lined-up with respect to each other."
2238 :group 'org-properties
2239 :type 'string)
2241 (defcustom org-use-property-inheritance nil
2242 "Non-nil means, properties apply also for sublevels.
2243 This setting is only relevant during property searches, not when querying
2244 an entry with `org-entry-get'. To retrieve a property with inheritance,
2245 you need to call `org-entry-get' with the inheritance flag.
2246 Turning this on can cause significant overhead when doing a search, so
2247 this is turned off by default.
2248 When nil, only the properties directly given in the current entry count.
2249 The value may also be a list of properties that shouldhave inheritance.
2251 However, note that some special properties use inheritance under special
2252 circumstances (not in searches). Examples are CATEGORY, ARCHIVE, COLUMNS,
2253 and the properties ending in \"_ALL\" when they are used as descriptor
2254 for valid values of a property."
2255 :group 'org-properties
2256 :type '(choice
2257 (const :tag "Not" nil)
2258 (const :tag "Always" nil)
2259 (repeat :tag "Specific properties" (string :tag "Property"))))
2261 (defcustom org-columns-default-format "%25ITEM %TODO %3PRIORITY %TAGS"
2262 "The default column format, if no other format has been defined.
2263 This variable can be set on the per-file basis by inserting a line
2265 #+COLUMNS: %25ITEM ....."
2266 :group 'org-properties
2267 :type 'string)
2269 (defcustom org-global-properties nil
2270 "List of property/value pairs that can be inherited by any entry.
2271 You can set buffer-local values for this by adding lines like
2273 #+PROPERTY: NAME VALUE"
2274 :group 'org-properties
2275 :type '(repeat
2276 (cons (string :tag "Property")
2277 (string :tag "Value"))))
2279 (defvar org-local-properties nil
2280 "List of property/value pairs that can be inherited by any entry.
2281 Valid for the current buffer.
2282 This variable is populated from #+PROPERTY lines.")
2284 (defgroup org-agenda nil
2285 "Options concerning agenda views in Org-mode."
2286 :tag "Org Agenda"
2287 :group 'org)
2289 (defvar org-category nil
2290 "Variable used by org files to set a category for agenda display.
2291 Such files should use a file variable to set it, for example
2293 # -*- mode: org; org-category: \"ELisp\"
2295 or contain a special line
2297 #+CATEGORY: ELisp
2299 If the file does not specify a category, then file's base name
2300 is used instead.")
2301 (make-variable-buffer-local 'org-category)
2303 (defcustom org-agenda-files nil
2304 "The files to be used for agenda display.
2305 Entries may be added to this list with \\[org-agenda-file-to-front] and removed with
2306 \\[org-remove-file]. You can also use customize to edit the list.
2308 If an entry is a directory, all files in that directory that are matched by
2309 `org-agenda-file-regexp' will be part of the file list.
2311 If the value of the variable is not a list but a single file name, then
2312 the list of agenda files is actually stored and maintained in that file, one
2313 agenda file per line."
2314 :group 'org-agenda
2315 :type '(choice
2316 (repeat :tag "List of files and directories" file)
2317 (file :tag "Store list in a file\n" :value "~/.agenda_files")))
2319 (defcustom org-agenda-file-regexp "\\`[^.].*\\.org\\'"
2320 "Regular expression to match files for `org-agenda-files'.
2321 If any element in the list in that variable contains a directory instead
2322 of a normal file, all files in that directory that are matched by this
2323 regular expression will be included."
2324 :group 'org-agenda
2325 :type 'regexp)
2327 (defcustom org-agenda-skip-unavailable-files nil
2328 "t means to just skip non-reachable files in `org-agenda-files'.
2329 Nil means to remove them, after a query, from the list."
2330 :group 'org-agenda
2331 :type 'boolean)
2333 (defcustom org-agenda-text-search-extra-files nil
2334 "List of extra files to be searched by text search commands.
2335 These files will be search in addition to the agenda files bu the
2336 commands `org-search-view' (`C-c a s') and `org-occur-in-agenda-files'.
2337 Note that these files will only be searched for text search commands,
2338 not for the other agenda views like todo lists, tag earches or the weekly
2339 agenda. This variable is intended to list notes and possibly archive files
2340 that should also be searched by these two commands."
2341 :group 'org-agenda
2342 :type '(repeat file))
2344 (if (fboundp 'defvaralias)
2345 (defvaralias 'org-agenda-multi-occur-extra-files
2346 'org-agenda-text-search-extra-files))
2348 (defcustom org-agenda-confirm-kill 1
2349 "When set, remote killing from the agenda buffer needs confirmation.
2350 When t, a confirmation is always needed. When a number N, confirmation is
2351 only needed when the text to be killed contains more than N non-white lines."
2352 :group 'org-agenda
2353 :type '(choice
2354 (const :tag "Never" nil)
2355 (const :tag "Always" t)
2356 (number :tag "When more than N lines")))
2358 (defcustom org-calendar-to-agenda-key [?c]
2359 "The key to be installed in `calendar-mode-map' for switching to the agenda.
2360 The command `org-calendar-goto-agenda' will be bound to this key. The
2361 default is the character `c' because then `c' can be used to switch back and
2362 forth between agenda and calendar."
2363 :group 'org-agenda
2364 :type 'sexp)
2366 (defcustom org-agenda-compact-blocks nil
2367 "Non-nil means, make the block agenda more compact.
2368 This is done by leaving out unnecessary lines."
2369 :group 'org-agenda
2370 :type nil)
2372 (defgroup org-agenda-export nil
2373 "Options concerning exporting agenda views in Org-mode."
2374 :tag "Org Agenda Export"
2375 :group 'org-agenda)
2377 (defcustom org-agenda-with-colors t
2378 "Non-nil means, use colors in agenda views."
2379 :group 'org-agenda-export
2380 :type 'boolean)
2382 (defcustom org-agenda-exporter-settings nil
2383 "Alist of variable/value pairs that should be active during agenda export.
2384 This is a good place to set uptions for ps-print and for htmlize."
2385 :group 'org-agenda-export
2386 :type '(repeat
2387 (list
2388 (variable)
2389 (sexp :tag "Value"))))
2391 (defcustom org-agenda-export-html-style ""
2392 "The style specification for exported HTML Agenda files.
2393 If this variable contains a string, it will replace the default <style>
2394 section as produced by `htmlize'.
2395 Since there are different ways of setting style information, this variable
2396 needs to contain the full HTML structure to provide a style, including the
2397 surrounding HTML tags. The style specifications should include definitions
2398 the fonts used by the agenda, here is an example:
2400 <style type=\"text/css\">
2401 p { font-weight: normal; color: gray; }
2402 .org-agenda-structure {
2403 font-size: 110%;
2404 color: #003399;
2405 font-weight: 600;
2407 .org-todo {
2408 color: #cc6666;
2409 font-weight: bold;
2411 .org-done {
2412 color: #339933;
2414 .title { text-align: center; }
2415 .todo, .deadline { color: red; }
2416 .done { color: green; }
2417 </style>
2419 or, if you want to keep the style in a file,
2421 <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\">
2423 As the value of this option simply gets inserted into the HTML <head> header,
2424 you can \"misuse\" it to also add other text to the header. However,
2425 <style>...</style> is required, if not present the variable will be ignored."
2426 :group 'org-agenda-export
2427 :group 'org-export-html
2428 :type 'string)
2430 (defgroup org-agenda-custom-commands nil
2431 "Options concerning agenda views in Org-mode."
2432 :tag "Org Agenda Custom Commands"
2433 :group 'org-agenda)
2435 (defconst org-sorting-choice
2436 '(choice
2437 (const time-up) (const time-down)
2438 (const category-keep) (const category-up) (const category-down)
2439 (const tag-down) (const tag-up)
2440 (const priority-up) (const priority-down))
2441 "Sorting choices.")
2443 (defconst org-agenda-custom-commands-local-options
2444 `(repeat :tag "Local settings for this command. Remember to quote values"
2445 (choice :tag "Setting"
2446 (list :tag "Any variable"
2447 (variable :tag "Variable")
2448 (sexp :tag "Value"))
2449 (list :tag "Files to be searched"
2450 (const org-agenda-files)
2451 (list
2452 (const :format "" quote)
2453 (repeat
2454 (file))))
2455 (list :tag "Sorting strategy"
2456 (const org-agenda-sorting-strategy)
2457 (list
2458 (const :format "" quote)
2459 (repeat
2460 ,org-sorting-choice)))
2461 (list :tag "Prefix format"
2462 (const org-agenda-prefix-format :value " %-12:c%?-12t% s")
2463 (string))
2464 (list :tag "Number of days in agenda"
2465 (const org-agenda-ndays)
2466 (integer :value 1))
2467 (list :tag "Fixed starting date"
2468 (const org-agenda-start-day)
2469 (string :value "2007-11-01"))
2470 (list :tag "Start on day of week"
2471 (const org-agenda-start-on-weekday)
2472 (choice :value 1
2473 (const :tag "Today" nil)
2474 (number :tag "Weekday No.")))
2475 (list :tag "Include data from diary"
2476 (const org-agenda-include-diary)
2477 (boolean))
2478 (list :tag "Deadline Warning days"
2479 (const org-deadline-warning-days)
2480 (integer :value 1))
2481 (list :tag "Standard skipping condition"
2482 :value (org-agenda-skip-function '(org-agenda-skip-entry-if))
2483 (const org-agenda-skip-function)
2484 (list
2485 (const :format "" quote)
2486 (list
2487 (choice
2488 :tag "Skiping range"
2489 (const :tag "Skip entry" org-agenda-skip-entry-if)
2490 (const :tag "Skip subtree" org-agenda-skip-subtree-if))
2491 (repeat :inline t :tag "Conditions for skipping"
2492 (choice
2493 :tag "Condition type"
2494 (list :tag "Regexp matches" :inline t (const :format "" 'regexp) (regexp))
2495 (list :tag "Regexp does not match" :inline t (const :format "" 'notregexp) (regexp))
2496 (const :tag "scheduled" 'scheduled)
2497 (const :tag "not scheduled" 'notscheduled)
2498 (const :tag "deadline" 'deadline)
2499 (const :tag "no deadline" 'notdeadline))))))
2500 (list :tag "Non-standard skipping condition"
2501 :value (org-agenda-skip-function)
2502 (list
2503 (const org-agenda-skip-function)
2504 (sexp :tag "Function or form (quoted!)")))))
2505 "Selection of examples for agenda command settings.
2506 This will be spliced into the custom type of
2507 `org-agenda-custom-commands'.")
2510 (defcustom org-agenda-custom-commands nil
2511 "Custom commands for the agenda.
2512 These commands will be offered on the splash screen displayed by the
2513 agenda dispatcher \\[org-agenda]. Each entry is a list like this:
2515 (key desc type match settings files)
2517 key The key (one or more characters as a string) to be associated
2518 with the command.
2519 desc A description of the command, when omitted or nil, a default
2520 description is built using MATCH.
2521 type The command type, any of the following symbols:
2522 agenda The daily/weekly agenda.
2523 todo Entries with a specific TODO keyword, in all agenda files.
2524 search Entries containing search words entry or headline.
2525 tags Tags/Property/TODO match in all agenda files.
2526 tags-todo Tags/P/T match in all agenda files, TODO entries only.
2527 todo-tree Sparse tree of specific TODO keyword in *current* file.
2528 tags-tree Sparse tree with all tags matches in *current* file.
2529 occur-tree Occur sparse tree for *current* file.
2530 ... A user-defined function.
2531 match What to search for:
2532 - a single keyword for TODO keyword searches
2533 - a tags match expression for tags searches
2534 - a word search expression for text searches.
2535 - a regular expression for occur searches
2536 For all other commands, this should be the empty string.
2537 settings A list of option settings, similar to that in a let form, so like
2538 this: ((opt1 val1) (opt2 val2) ...). The values will be
2539 evaluated at the moment of execution, so quote them when needed.
2540 files A list of files file to write the produced agenda buffer to
2541 with the command `org-store-agenda-views'.
2542 If a file name ends in \".html\", an HTML version of the buffer
2543 is written out. If it ends in \".ps\", a postscript version is
2544 produced. Otherwide, only the plain text is written to the file.
2546 You can also define a set of commands, to create a composite agenda buffer.
2547 In this case, an entry looks like this:
2549 (key desc (cmd1 cmd2 ...) general-settings-for-whole-set files)
2551 where
2553 desc A description string to be displayed in the dispatcher menu.
2554 cmd An agenda command, similar to the above. However, tree commands
2555 are no allowed, but instead you can get agenda and global todo list.
2556 So valid commands for a set are:
2557 (agenda \"\" settings)
2558 (alltodo \"\" settings)
2559 (stuck \"\" settings)
2560 (todo \"match\" settings files)
2561 (search \"match\" settings files)
2562 (tags \"match\" settings files)
2563 (tags-todo \"match\" settings files)
2565 Each command can carry a list of options, and another set of options can be
2566 given for the whole set of commands. Individual command options take
2567 precedence over the general options.
2569 When using several characters as key to a command, the first characters
2570 are prefix commands. For the dispatcher to display useful information, you
2571 should provide a description for the prefix, like
2573 (setq org-agenda-custom-commands
2574 '((\"h\" . \"HOME + Name tag searches\") ; describe prefix \"h\"
2575 (\"hl\" tags \"+HOME+Lisa\")
2576 (\"hp\" tags \"+HOME+Peter\")
2577 (\"hk\" tags \"+HOME+Kim\")))"
2578 :group 'org-agenda-custom-commands
2579 :type `(repeat
2580 (choice :value ("x" "Describe command here" tags "" nil)
2581 (list :tag "Single command"
2582 (string :tag "Access Key(s) ")
2583 (option (string :tag "Description"))
2584 (choice
2585 (const :tag "Agenda" agenda)
2586 (const :tag "TODO list" alltodo)
2587 (const :tag "Search words" search)
2588 (const :tag "Stuck projects" stuck)
2589 (const :tag "Tags search (all agenda files)" tags)
2590 (const :tag "Tags search of TODO entries (all agenda files)" tags-todo)
2591 (const :tag "TODO keyword search (all agenda files)" todo)
2592 (const :tag "Tags sparse tree (current buffer)" tags-tree)
2593 (const :tag "TODO keyword tree (current buffer)" todo-tree)
2594 (const :tag "Occur tree (current buffer)" occur-tree)
2595 (sexp :tag "Other, user-defined function"))
2596 (string :tag "Match (only for some commands)")
2597 ,org-agenda-custom-commands-local-options
2598 (option (repeat :tag "Export" (file :tag "Export to"))))
2599 (list :tag "Command series, all agenda files"
2600 (string :tag "Access Key(s)")
2601 (string :tag "Description ")
2602 (repeat :tag "Component"
2603 (choice
2604 (list :tag "Agenda"
2605 (const :format "" agenda)
2606 (const :tag "" :format "" "")
2607 ,org-agenda-custom-commands-local-options)
2608 (list :tag "TODO list (all keywords)"
2609 (const :format "" alltodo)
2610 (const :tag "" :format "" "")
2611 ,org-agenda-custom-commands-local-options)
2612 (list :tag "Search words"
2613 (const :format "" search)
2614 (string :tag "Match")
2615 ,org-agenda-custom-commands-local-options)
2616 (list :tag "Stuck projects"
2617 (const :format "" stuck)
2618 (const :tag "" :format "" "")
2619 ,org-agenda-custom-commands-local-options)
2620 (list :tag "Tags search"
2621 (const :format "" tags)
2622 (string :tag "Match")
2623 ,org-agenda-custom-commands-local-options)
2624 (list :tag "Tags search, TODO entries only"
2625 (const :format "" tags-todo)
2626 (string :tag "Match")
2627 ,org-agenda-custom-commands-local-options)
2628 (list :tag "TODO keyword search"
2629 (const :format "" todo)
2630 (string :tag "Match")
2631 ,org-agenda-custom-commands-local-options)
2632 (list :tag "Other, user-defined function"
2633 (symbol :tag "function")
2634 (string :tag "Match")
2635 ,org-agenda-custom-commands-local-options)))
2637 (repeat :tag "Settings for entire command set"
2638 (list (variable :tag "Any variable")
2639 (sexp :tag "Value")))
2640 (option (repeat :tag "Export" (file :tag "Export to"))))
2641 (cons :tag "Prefix key documentation"
2642 (string :tag "Access Key(s)")
2643 (string :tag "Description ")))))
2645 (defcustom org-agenda-query-register ?o
2646 "The register holding the current query string.
2647 The prupose of this is that if you construct a query string interactively,
2648 you can then use it to define a custom command."
2649 :group 'org-agenda-custom-commands
2650 :type 'character)
2652 (defcustom org-stuck-projects
2653 '("+LEVEL=2/-DONE" ("TODO" "NEXT" "NEXTACTION") nil "")
2654 "How to identify stuck projects.
2655 This is a list of four items:
2656 1. A tags/todo matcher string that is used to identify a project.
2657 The entire tree below a headline matched by this is considered one project.
2658 2. A list of TODO keywords identifying non-stuck projects.
2659 If the project subtree contains any headline with one of these todo
2660 keywords, the project is considered to be not stuck. If you specify
2661 \"*\" as a keyword, any TODO keyword will mark the project unstuck.
2662 3. A list of tags identifying non-stuck projects.
2663 If the project subtree contains any headline with one of these tags,
2664 the project is considered to be not stuck. If you specify \"*\" as
2665 a tag, any tag will mark the project unstuck.
2666 4. An arbitrary regular expression matching non-stuck projects.
2668 After defining this variable, you may use \\[org-agenda-list-stuck-projects]
2669 or `C-c a #' to produce the list."
2670 :group 'org-agenda-custom-commands
2671 :type '(list
2672 (string :tag "Tags/TODO match to identify a project")
2673 (repeat :tag "Projects are *not* stuck if they have an entry with TODO keyword any of" (string))
2674 (repeat :tag "Projects are *not* stuck if they have an entry with TAG being any of" (string))
2675 (regexp :tag "Projects are *not* stuck if this regexp matches\ninside the subtree")))
2678 (defgroup org-agenda-skip nil
2679 "Options concerning skipping parts of agenda files."
2680 :tag "Org Agenda Skip"
2681 :group 'org-agenda)
2683 (defcustom org-agenda-todo-list-sublevels t
2684 "Non-nil means, check also the sublevels of a TODO entry for TODO entries.
2685 When nil, the sublevels of a TODO entry are not checked, resulting in
2686 potentially much shorter TODO lists."
2687 :group 'org-agenda-skip
2688 :group 'org-todo
2689 :type 'boolean)
2691 (defcustom org-agenda-todo-ignore-with-date nil
2692 "Non-nil means, don't show entries with a date in the global todo list.
2693 You can use this if you prefer to mark mere appointments with a TODO keyword,
2694 but don't want them to show up in the TODO list.
2695 When this is set, it also covers deadlines and scheduled items, the settings
2696 of `org-agenda-todo-ignore-scheduled' and `org-agenda-todo-ignore-deadlines'
2697 will be ignored."
2698 :group 'org-agenda-skip
2699 :group 'org-todo
2700 :type 'boolean)
2702 (defcustom org-agenda-todo-ignore-scheduled nil
2703 "Non-nil means, don't show scheduled entries in the global todo list.
2704 The idea behind this is that by scheduling it, you have already taken care
2705 of this item.
2706 See also `org-agenda-todo-ignore-with-date'."
2707 :group 'org-agenda-skip
2708 :group 'org-todo
2709 :type 'boolean)
2711 (defcustom org-agenda-todo-ignore-deadlines nil
2712 "Non-nil means, don't show near deadline entries in the global todo list.
2713 Near means closer than `org-deadline-warning-days' days.
2714 The idea behind this is that such items will appear in the agenda anyway.
2715 See also `org-agenda-todo-ignore-with-date'."
2716 :group 'org-agenda-skip
2717 :group 'org-todo
2718 :type 'boolean)
2720 (defcustom org-agenda-skip-scheduled-if-done nil
2721 "Non-nil means don't show scheduled items in agenda when they are done.
2722 This is relevant for the daily/weekly agenda, not for the TODO list. And
2723 it applies only to the actual date of the scheduling. Warnings about
2724 an item with a past scheduling dates are always turned off when the item
2725 is DONE."
2726 :group 'org-agenda-skip
2727 :type 'boolean)
2729 (defcustom org-agenda-skip-deadline-if-done nil
2730 "Non-nil means don't show deadines when the corresponding item is done.
2731 When nil, the deadline is still shown and should give you a happy feeling.
2732 This is relevant for the daily/weekly agenda. And it applied only to the
2733 actualy date of the deadline. Warnings about approching and past-due
2734 deadlines are always turned off when the item is DONE."
2735 :group 'org-agenda-skip
2736 :type 'boolean)
2738 (defcustom org-agenda-skip-timestamp-if-done nil
2739 "Non-nil means don't select item by timestamp or -range if it is DONE."
2740 :group 'org-agenda-skip
2741 :type 'boolean)
2743 (defcustom org-timeline-show-empty-dates 3
2744 "Non-nil means, `org-timeline' also shows dates without an entry.
2745 When nil, only the days which actually have entries are shown.
2746 When t, all days between the first and the last date are shown.
2747 When an integer, show also empty dates, but if there is a gap of more than
2748 N days, just insert a special line indicating the size of the gap."
2749 :group 'org-agenda-skip
2750 :type '(choice
2751 (const :tag "None" nil)
2752 (const :tag "All" t)
2753 (number :tag "at most")))
2756 (defgroup org-agenda-startup nil
2757 "Options concerning initial settings in the Agenda in Org Mode."
2758 :tag "Org Agenda Startup"
2759 :group 'org-agenda)
2761 (defcustom org-finalize-agenda-hook nil
2762 "Hook run just before displaying an agenda buffer."
2763 :group 'org-agenda-startup
2764 :type 'hook)
2766 (defcustom org-agenda-mouse-1-follows-link nil
2767 "Non-nil means, mouse-1 on a link will follow the link in the agenda.
2768 A longer mouse click will still set point. Does not work on XEmacs.
2769 Needs to be set before org.el is loaded."
2770 :group 'org-agenda-startup
2771 :type 'boolean)
2773 (defcustom org-agenda-start-with-follow-mode nil
2774 "The initial value of follow-mode in a newly created agenda window."
2775 :group 'org-agenda-startup
2776 :type 'boolean)
2778 (defgroup org-agenda-windows nil
2779 "Options concerning the windows used by the Agenda in Org Mode."
2780 :tag "Org Agenda Windows"
2781 :group 'org-agenda)
2783 (defcustom org-agenda-window-setup 'reorganize-frame
2784 "How the agenda buffer should be displayed.
2785 Possible values for this option are:
2787 current-window Show agenda in the current window, keeping all other windows.
2788 other-frame Use `switch-to-buffer-other-frame' to display agenda.
2789 other-window Use `switch-to-buffer-other-window' to display agenda.
2790 reorganize-frame Show only two windows on the current frame, the current
2791 window and the agenda.
2792 See also the variable `org-agenda-restore-windows-after-quit'."
2793 :group 'org-agenda-windows
2794 :type '(choice
2795 (const current-window)
2796 (const other-frame)
2797 (const other-window)
2798 (const reorganize-frame)))
2800 (defcustom org-agenda-window-frame-fractions '(0.5 . 0.75)
2801 "The min and max height of the agenda window as a fraction of frame height.
2802 The value of the variable is a cons cell with two numbers between 0 and 1.
2803 It only matters if `org-agenda-window-setup' is `reorganize-frame'."
2804 :group 'org-agenda-windows
2805 :type '(cons (number :tag "Minimum") (number :tag "Maximum")))
2807 (defcustom org-agenda-restore-windows-after-quit nil
2808 "Non-nil means, restore window configuration open exiting agenda.
2809 Before the window configuration is changed for displaying the agenda,
2810 the current status is recorded. When the agenda is exited with
2811 `q' or `x' and this option is set, the old state is restored. If
2812 `org-agenda-window-setup' is `other-frame', the value of this
2813 option will be ignored.."
2814 :group 'org-agenda-windows
2815 :type 'boolean)
2817 (defcustom org-indirect-buffer-display 'other-window
2818 "How should indirect tree buffers be displayed?
2819 This applies to indirect buffers created with the commands
2820 \\[org-tree-to-indirect-buffer] and \\[org-agenda-tree-to-indirect-buffer].
2821 Valid values are:
2822 current-window Display in the current window
2823 other-window Just display in another window.
2824 dedicated-frame Create one new frame, and re-use it each time.
2825 new-frame Make a new frame each time. Note that in this case
2826 previously-made indirect buffers are kept, and you need to
2827 kill these buffers yourself."
2828 :group 'org-structure
2829 :group 'org-agenda-windows
2830 :type '(choice
2831 (const :tag "In current window" current-window)
2832 (const :tag "In current frame, other window" other-window)
2833 (const :tag "Each time a new frame" new-frame)
2834 (const :tag "One dedicated frame" dedicated-frame)))
2836 (defgroup org-agenda-daily/weekly nil
2837 "Options concerning the daily/weekly agenda."
2838 :tag "Org Agenda Daily/Weekly"
2839 :group 'org-agenda)
2841 (defcustom org-agenda-ndays 7
2842 "Number of days to include in overview display.
2843 Should be 1 or 7."
2844 :group 'org-agenda-daily/weekly
2845 :type 'number)
2847 (defcustom org-agenda-start-on-weekday 1
2848 "Non-nil means, start the overview always on the specified weekday.
2849 0 denotes Sunday, 1 denotes Monday etc.
2850 When nil, always start on the current day."
2851 :group 'org-agenda-daily/weekly
2852 :type '(choice (const :tag "Today" nil)
2853 (number :tag "Weekday No.")))
2855 (defcustom org-agenda-show-all-dates t
2856 "Non-nil means, `org-agenda' shows every day in the selected range.
2857 When nil, only the days which actually have entries are shown."
2858 :group 'org-agenda-daily/weekly
2859 :type 'boolean)
2861 (defcustom org-agenda-format-date 'org-agenda-format-date-aligned
2862 "Format string for displaying dates in the agenda.
2863 Used by the daily/weekly agenda and by the timeline. This should be
2864 a format string understood by `format-time-string', or a function returning
2865 the formatted date as a string. The function must take a single argument,
2866 a calendar-style date list like (month day year)."
2867 :group 'org-agenda-daily/weekly
2868 :type '(choice
2869 (string :tag "Format string")
2870 (function :tag "Function")))
2872 (defun org-agenda-format-date-aligned (date)
2873 "Format a date string for display in the daily/weekly agenda, or timeline.
2874 This function makes sure that dates are aligned for easy reading."
2875 (require 'cal-iso)
2876 (let* ((dayname (calendar-day-name date))
2877 (day (extract-calendar-day date))
2878 (day-of-week (calendar-day-of-week date))
2879 (month (extract-calendar-month date))
2880 (monthname (calendar-month-name month))
2881 (year (extract-calendar-year date))
2882 (iso-week (org-days-to-iso-week
2883 (calendar-absolute-from-gregorian date)))
2884 (weekyear (cond ((and (= month 1) (>= iso-week 52))
2885 (1- year))
2886 ((and (= month 12) (<= iso-week 1))
2887 (1+ year))
2888 (t year)))
2889 (weekstring (if (= day-of-week 1)
2890 (format " W%02d" iso-week)
2891 "")))
2892 (format "%-9s %2d %s %4d%s"
2893 dayname day monthname year weekstring)))
2895 (defcustom org-agenda-include-diary nil
2896 "If non-nil, include in the agenda entries from the Emacs Calendar's diary."
2897 :group 'org-agenda-daily/weekly
2898 :type 'boolean)
2900 (defcustom org-agenda-include-all-todo nil
2901 "Set means weekly/daily agenda will always contain all TODO entries.
2902 The TODO entries will be listed at the top of the agenda, before
2903 the entries for specific days."
2904 :group 'org-agenda-daily/weekly
2905 :type 'boolean)
2907 (defcustom org-agenda-repeating-timestamp-show-all t
2908 "Non-nil means, show all occurences of a repeating stamp in the agenda.
2909 When nil, only one occurence is shown, either today or the
2910 nearest into the future."
2911 :group 'org-agenda-daily/weekly
2912 :type 'boolean)
2914 (defcustom org-deadline-warning-days 14
2915 "No. of days before expiration during which a deadline becomes active.
2916 This variable governs the display in sparse trees and in the agenda.
2917 When 0 or negative, it means use this number (the absolute value of it)
2918 even if a deadline has a different individual lead time specified."
2919 :group 'org-time
2920 :group 'org-agenda-daily/weekly
2921 :type 'number)
2923 (defcustom org-scheduled-past-days 10000
2924 "No. of days to continue listing scheduled items that are not marked DONE.
2925 When an item is scheduled on a date, it shows up in the agenda on this
2926 day and will be listed until it is marked done for the number of days
2927 given here."
2928 :group 'org-agenda-daily/weekly
2929 :type 'number)
2931 (defgroup org-agenda-time-grid nil
2932 "Options concerning the time grid in the Org-mode Agenda."
2933 :tag "Org Agenda Time Grid"
2934 :group 'org-agenda)
2936 (defcustom org-agenda-use-time-grid t
2937 "Non-nil means, show a time grid in the agenda schedule.
2938 A time grid is a set of lines for specific times (like every two hours between
2939 8:00 and 20:00). The items scheduled for a day at specific times are
2940 sorted in between these lines.
2941 For details about when the grid will be shown, and what it will look like, see
2942 the variable `org-agenda-time-grid'."
2943 :group 'org-agenda-time-grid
2944 :type 'boolean)
2946 (defcustom org-agenda-time-grid
2947 '((daily today require-timed)
2948 "----------------"
2949 (800 1000 1200 1400 1600 1800 2000))
2951 "The settings for time grid for agenda display.
2952 This is a list of three items. The first item is again a list. It contains
2953 symbols specifying conditions when the grid should be displayed:
2955 daily if the agenda shows a single day
2956 weekly if the agenda shows an entire week
2957 today show grid on current date, independent of daily/weekly display
2958 require-timed show grid only if at least one item has a time specification
2960 The second item is a string which will be places behing the grid time.
2962 The third item is a list of integers, indicating the times that should have
2963 a grid line."
2964 :group 'org-agenda-time-grid
2965 :type
2966 '(list
2967 (set :greedy t :tag "Grid Display Options"
2968 (const :tag "Show grid in single day agenda display" daily)
2969 (const :tag "Show grid in weekly agenda display" weekly)
2970 (const :tag "Always show grid for today" today)
2971 (const :tag "Show grid only if any timed entries are present"
2972 require-timed)
2973 (const :tag "Skip grid times already present in an entry"
2974 remove-match))
2975 (string :tag "Grid String")
2976 (repeat :tag "Grid Times" (integer :tag "Time"))))
2978 (defgroup org-agenda-sorting nil
2979 "Options concerning sorting in the Org-mode Agenda."
2980 :tag "Org Agenda Sorting"
2981 :group 'org-agenda)
2983 (defcustom org-agenda-sorting-strategy
2984 '((agenda time-up category-keep priority-down)
2985 (todo category-keep priority-down)
2986 (tags category-keep priority-down)
2987 (search category-keep))
2988 "Sorting structure for the agenda items of a single day.
2989 This is a list of symbols which will be used in sequence to determine
2990 if an entry should be listed before another entry. The following
2991 symbols are recognized:
2993 time-up Put entries with time-of-day indications first, early first
2994 time-down Put entries with time-of-day indications first, late first
2995 category-keep Keep the default order of categories, corresponding to the
2996 sequence in `org-agenda-files'.
2997 category-up Sort alphabetically by category, A-Z.
2998 category-down Sort alphabetically by category, Z-A.
2999 tag-up Sort alphabetically by last tag, A-Z.
3000 tag-down Sort alphabetically by last tag, Z-A.
3001 priority-up Sort numerically by priority, high priority last.
3002 priority-down Sort numerically by priority, high priority first.
3004 The different possibilities will be tried in sequence, and testing stops
3005 if one comparison returns a \"not-equal\". For example, the default
3006 '(time-up category-keep priority-down)
3007 means: Pull out all entries having a specified time of day and sort them,
3008 in order to make a time schedule for the current day the first thing in the
3009 agenda listing for the day. Of the entries without a time indication, keep
3010 the grouped in categories, don't sort the categories, but keep them in
3011 the sequence given in `org-agenda-files'. Within each category sort by
3012 priority.
3014 Leaving out `category-keep' would mean that items will be sorted across
3015 categories by priority.
3017 Instead of a single list, this can also be a set of list for specific
3018 contents, with a context symbol in the car of the list, any of
3019 `agenda', `todo', `tags' for the corresponding agenda views."
3020 :group 'org-agenda-sorting
3021 :type `(choice
3022 (repeat :tag "General" ,org-sorting-choice)
3023 (list :tag "Individually"
3024 (cons (const :tag "Strategy for Weekly/Daily agenda" agenda)
3025 (repeat ,org-sorting-choice))
3026 (cons (const :tag "Strategy for TODO lists" todo)
3027 (repeat ,org-sorting-choice))
3028 (cons (const :tag "Strategy for Tags matches" tags)
3029 (repeat ,org-sorting-choice)))))
3031 (defcustom org-sort-agenda-notime-is-late t
3032 "Non-nil means, items without time are considered late.
3033 This is only relevant for sorting. When t, items which have no explicit
3034 time like 15:30 will be considered as 99:01, i.e. later than any items which
3035 do have a time. When nil, the default time is before 0:00. You can use this
3036 option to decide if the schedule for today should come before or after timeless
3037 agenda entries."
3038 :group 'org-agenda-sorting
3039 :type 'boolean)
3041 (defgroup org-agenda-line-format nil
3042 "Options concerning the entry prefix in the Org-mode agenda display."
3043 :tag "Org Agenda Line Format"
3044 :group 'org-agenda)
3046 (defcustom org-agenda-prefix-format
3047 '((agenda . " %-12:c%?-12t% s")
3048 (timeline . " % s")
3049 (todo . " %-12:c")
3050 (tags . " %-12:c")
3051 (search . " %-12:c"))
3052 "Format specifications for the prefix of items in the agenda views.
3053 An alist with four entries, for the different agenda types. The keys to the
3054 sublists are `agenda', `timeline', `todo', and `tags'. The values
3055 are format strings.
3056 This format works similar to a printf format, with the following meaning:
3058 %c the category of the item, \"Diary\" for entries from the diary, or
3059 as given by the CATEGORY keyword or derived from the file name.
3060 %T the *last* tag of the item. Last because inherited tags come
3061 first in the list.
3062 %t the time-of-day specification if one applies to the entry, in the
3063 format HH:MM
3064 %s Scheduling/Deadline information, a short string
3066 All specifiers work basically like the standard `%s' of printf, but may
3067 contain two additional characters: A question mark just after the `%' and
3068 a whitespace/punctuation character just before the final letter.
3070 If the first character after `%' is a question mark, the entire field
3071 will only be included if the corresponding value applies to the
3072 current entry. This is useful for fields which should have fixed
3073 width when present, but zero width when absent. For example,
3074 \"%?-12t\" will result in a 12 character time field if a time of the
3075 day is specified, but will completely disappear in entries which do
3076 not contain a time.
3078 If there is punctuation or whitespace character just before the final
3079 format letter, this character will be appended to the field value if
3080 the value is not empty. For example, the format \"%-12:c\" leads to
3081 \"Diary: \" if the category is \"Diary\". If the category were be
3082 empty, no additional colon would be interted.
3084 The default value of this option is \" %-12:c%?-12t% s\", meaning:
3085 - Indent the line with two space characters
3086 - Give the category in a 12 chars wide field, padded with whitespace on
3087 the right (because of `-'). Append a colon if there is a category
3088 (because of `:').
3089 - If there is a time-of-day, put it into a 12 chars wide field. If no
3090 time, don't put in an empty field, just skip it (because of '?').
3091 - Finally, put the scheduling information and append a whitespace.
3093 As another example, if you don't want the time-of-day of entries in
3094 the prefix, you could use:
3096 (setq org-agenda-prefix-format \" %-11:c% s\")
3098 See also the variables `org-agenda-remove-times-when-in-prefix' and
3099 `org-agenda-remove-tags'."
3100 :type '(choice
3101 (string :tag "General format")
3102 (list :greedy t :tag "View dependent"
3103 (cons (const agenda) (string :tag "Format"))
3104 (cons (const timeline) (string :tag "Format"))
3105 (cons (const todo) (string :tag "Format"))
3106 (cons (const tags) (string :tag "Format"))
3107 (cons (const search) (string :tag "Format"))))
3108 :group 'org-agenda-line-format)
3110 (defvar org-prefix-format-compiled nil
3111 "The compiled version of the most recently used prefix format.
3112 See the variable `org-agenda-prefix-format'.")
3114 (defcustom org-agenda-todo-keyword-format "%-1s"
3115 "Format for the TODO keyword in agenda lines.
3116 Set this to something like \"%-12s\" if you want all TODO keywords
3117 to occupy a fixed space in the agenda display."
3118 :group 'org-agenda-line-format
3119 :type 'string)
3121 (defcustom org-agenda-scheduled-leaders '("Scheduled: " "Sched.%2dx: ")
3122 "Text preceeding scheduled items in the agenda view.
3123 This is a list with two strings. The first applies when the item is
3124 scheduled on the current day. The second applies when it has been scheduled
3125 previously, it may contain a %d to capture how many days ago the item was
3126 scheduled."
3127 :group 'org-agenda-line-format
3128 :type '(list
3129 (string :tag "Scheduled today ")
3130 (string :tag "Scheduled previously")))
3132 (defcustom org-agenda-deadline-leaders '("Deadline: " "In %3d d.: ")
3133 "Text preceeding deadline items in the agenda view.
3134 This is a list with two strings. The first applies when the item has its
3135 deadline on the current day. The second applies when it is in the past or
3136 in the future, it may contain %d to capture how many days away the deadline
3137 is (was)."
3138 :group 'org-agenda-line-format
3139 :type '(list
3140 (string :tag "Deadline today ")
3141 (string :tag "Deadline relative")))
3143 (defcustom org-agenda-remove-times-when-in-prefix t
3144 "Non-nil means, remove duplicate time specifications in agenda items.
3145 When the format `org-agenda-prefix-format' contains a `%t' specifier, a
3146 time-of-day specification in a headline or diary entry is extracted and
3147 placed into the prefix. If this option is non-nil, the original specification
3148 \(a timestamp or -range, or just a plain time(range) specification like
3149 11:30-4pm) will be removed for agenda display. This makes the agenda less
3150 cluttered.
3151 The option can be t or nil. It may also be the symbol `beg', indicating
3152 that the time should only be removed what it is located at the beginning of
3153 the headline/diary entry."
3154 :group 'org-agenda-line-format
3155 :type '(choice
3156 (const :tag "Always" t)
3157 (const :tag "Never" nil)
3158 (const :tag "When at beginning of entry" beg)))
3161 (defcustom org-agenda-default-appointment-duration nil
3162 "Default duration for appointments that only have a starting time.
3163 When nil, no duration is specified in such cases.
3164 When non-nil, this must be the number of minutes, e.g. 60 for one hour."
3165 :group 'org-agenda-line-format
3166 :type '(choice
3167 (integer :tag "Minutes")
3168 (const :tag "No default duration")))
3171 (defcustom org-agenda-remove-tags nil
3172 "Non-nil means, remove the tags from the headline copy in the agenda.
3173 When this is the symbol `prefix', only remove tags when
3174 `org-agenda-prefix-format' contains a `%T' specifier."
3175 :group 'org-agenda-line-format
3176 :type '(choice
3177 (const :tag "Always" t)
3178 (const :tag "Never" nil)
3179 (const :tag "When prefix format contains %T" prefix)))
3181 (if (fboundp 'defvaralias)
3182 (defvaralias 'org-agenda-remove-tags-when-in-prefix
3183 'org-agenda-remove-tags))
3185 (defcustom org-agenda-tags-column -80
3186 "Shift tags in agenda items to this column.
3187 If this number is positive, it specifies the column. If it is negative,
3188 it means that the tags should be flushright to that column. For example,
3189 -80 works well for a normal 80 character screen."
3190 :group 'org-agenda-line-format
3191 :type 'integer)
3193 (if (fboundp 'defvaralias)
3194 (defvaralias 'org-agenda-align-tags-to-column 'org-agenda-tags-column))
3196 (defcustom org-agenda-fontify-priorities t
3197 "Non-nil means, highlight low and high priorities in agenda.
3198 When t, the highest priority entries are bold, lowest priority italic.
3199 This may also be an association list of priority faces. The face may be
3200 a names face, or a list like `(:background \"Red\")'."
3201 :group 'org-agenda-line-format
3202 :type '(choice
3203 (const :tag "Never" nil)
3204 (const :tag "Defaults" t)
3205 (repeat :tag "Specify"
3206 (list (character :tag "Priority" :value ?A)
3207 (sexp :tag "face")))))
3209 (defgroup org-latex nil
3210 "Options for embedding LaTeX code into Org-mode."
3211 :tag "Org LaTeX"
3212 :group 'org)
3214 (defcustom org-format-latex-options
3215 '(:foreground default :background default :scale 1.0
3216 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0
3217 :matchers ("begin" "$" "$$" "\\(" "\\["))
3218 "Options for creating images from LaTeX fragments.
3219 This is a property list with the following properties:
3220 :foreground the foreground color for images embedded in emacs, e.g. \"Black\".
3221 `default' means use the forground of the default face.
3222 :background the background color, or \"Transparent\".
3223 `default' means use the background of the default face.
3224 :scale a scaling factor for the size of the images
3225 :html-foreground, :html-background, :html-scale
3226 The same numbers for HTML export.
3227 :matchers a list indicating which matchers should be used to
3228 find LaTeX fragments. Valid members of this list are:
3229 \"begin\" find environments
3230 \"$\" find math expressions surrounded by $...$
3231 \"$$\" find math expressions surrounded by $$....$$
3232 \"\\(\" find math expressions surrounded by \\(...\\)
3233 \"\\ [\" find math expressions surrounded by \\ [...\\]"
3234 :group 'org-latex
3235 :type 'plist)
3237 (defcustom org-format-latex-header "\\documentclass{article}
3238 \\usepackage{fullpage} % do not remove
3239 \\usepackage{amssymb}
3240 \\usepackage[usenames]{color}
3241 \\usepackage{amsmath}
3242 \\usepackage{latexsym}
3243 \\usepackage[mathscr]{eucal}
3244 \\pagestyle{empty} % do not remove"
3245 "The document header used for processing LaTeX fragments."
3246 :group 'org-latex
3247 :type 'string)
3249 (defgroup org-export nil
3250 "Options for exporting org-listings."
3251 :tag "Org Export"
3252 :group 'org)
3254 (defgroup org-export-general nil
3255 "General options for exporting Org-mode files."
3256 :tag "Org Export General"
3257 :group 'org-export)
3259 ;; FIXME
3260 (defvar org-export-publishing-directory nil)
3262 (defcustom org-export-with-special-strings t
3263 "Non-nil means, interpret \"\-\", \"--\" and \"---\" for export.
3264 When this option is turned on, these strings will be exported as:
3266 Org HTML LaTeX
3267 -----+----------+--------
3268 \\- &shy; \\-
3269 -- &ndash; --
3270 --- &mdash; ---
3271 ... &hellip; \ldots
3273 This option can also be set with the +OPTIONS line, e.g. \"-:nil\"."
3274 :group 'org-export-translation
3275 :type 'boolean)
3277 (defcustom org-export-language-setup
3278 '(("en" "Author" "Date" "Table of Contents")
3279 ("cs" "Autor" "Datum" "Obsah")
3280 ("da" "Ophavsmand" "Dato" "Indhold")
3281 ("de" "Autor" "Datum" "Inhaltsverzeichnis")
3282 ("es" "Autor" "Fecha" "\xcdndice")
3283 ("fr" "Auteur" "Date" "Table des mati\xe8res")
3284 ("it" "Autore" "Data" "Indice")
3285 ("nl" "Auteur" "Datum" "Inhoudsopgave")
3286 ("nn" "Forfattar" "Dato" "Innhold") ;; nn = Norsk (nynorsk)
3287 ("sv" "F\xf6rfattarens" "Datum" "Inneh\xe5ll"))
3288 "Terms used in export text, translated to different languages.
3289 Use the variable `org-export-default-language' to set the language,
3290 or use the +OPTION lines for a per-file setting."
3291 :group 'org-export-general
3292 :type '(repeat
3293 (list
3294 (string :tag "HTML language tag")
3295 (string :tag "Author")
3296 (string :tag "Date")
3297 (string :tag "Table of Contents"))))
3299 (defcustom org-export-default-language "en"
3300 "The default language of HTML export, as a string.
3301 This should have an association in `org-export-language-setup'."
3302 :group 'org-export-general
3303 :type 'string)
3305 (defcustom org-export-skip-text-before-1st-heading t
3306 "Non-nil means, skip all text before the first headline when exporting.
3307 When nil, that text is exported as well."
3308 :group 'org-export-general
3309 :type 'boolean)
3311 (defcustom org-export-headline-levels 3
3312 "The last level which is still exported as a headline.
3313 Inferior levels will produce itemize lists when exported.
3314 Note that a numeric prefix argument to an exporter function overrides
3315 this setting.
3317 This option can also be set with the +OPTIONS line, e.g. \"H:2\"."
3318 :group 'org-export-general
3319 :type 'number)
3321 (defcustom org-export-with-section-numbers t
3322 "Non-nil means, add section numbers to headlines when exporting.
3324 This option can also be set with the +OPTIONS line, e.g. \"num:t\"."
3325 :group 'org-export-general
3326 :type 'boolean)
3328 (defcustom org-export-with-toc t
3329 "Non-nil means, create a table of contents in exported files.
3330 The TOC contains headlines with levels up to`org-export-headline-levels'.
3331 When an integer, include levels up to N in the toc, this may then be
3332 different from `org-export-headline-levels', but it will not be allowed
3333 to be larger than the number of headline levels.
3334 When nil, no table of contents is made.
3336 Headlines which contain any TODO items will be marked with \"(*)\" in
3337 ASCII export, and with red color in HTML output, if the option
3338 `org-export-mark-todo-in-toc' is set.
3340 In HTML output, the TOC will be clickable.
3342 This option can also be set with the +OPTIONS line, e.g. \"toc:nil\"
3343 or \"toc:3\"."
3344 :group 'org-export-general
3345 :type '(choice
3346 (const :tag "No Table of Contents" nil)
3347 (const :tag "Full Table of Contents" t)
3348 (integer :tag "TOC to level")))
3350 (defcustom org-export-mark-todo-in-toc nil
3351 "Non-nil means, mark TOC lines that contain any open TODO items."
3352 :group 'org-export-general
3353 :type 'boolean)
3355 (defcustom org-export-preserve-breaks nil
3356 "Non-nil means, preserve all line breaks when exporting.
3357 Normally, in HTML output paragraphs will be reformatted. In ASCII
3358 export, line breaks will always be preserved, regardless of this variable.
3360 This option can also be set with the +OPTIONS line, e.g. \"\\n:t\"."
3361 :group 'org-export-general
3362 :type 'boolean)
3364 (defcustom org-export-with-archived-trees 'headline
3365 "Whether subtrees with the ARCHIVE tag should be exported.
3366 This can have three different values
3367 nil Do not export, pretend this tree is not present
3368 t Do export the entire tree
3369 headline Only export the headline, but skip the tree below it."
3370 :group 'org-export-general
3371 :group 'org-archive
3372 :type '(choice
3373 (const :tag "not at all" nil)
3374 (const :tag "headline only" 'headline)
3375 (const :tag "entirely" t)))
3377 (defcustom org-export-author-info t
3378 "Non-nil means, insert author name and email into the exported file.
3380 This option can also be set with the +OPTIONS line,
3381 e.g. \"author-info:nil\"."
3382 :group 'org-export-general
3383 :type 'boolean)
3385 (defcustom org-export-time-stamp-file t
3386 "Non-nil means, insert a time stamp into the exported file.
3387 The time stamp shows when the file was created.
3389 This option can also be set with the +OPTIONS line,
3390 e.g. \"timestamp:nil\"."
3391 :group 'org-export-general
3392 :type 'boolean)
3394 (defcustom org-export-with-timestamps t
3395 "If nil, do not export time stamps and associated keywords."
3396 :group 'org-export-general
3397 :type 'boolean)
3399 (defcustom org-export-remove-timestamps-from-toc t
3400 "If nil, remove timestamps from the table of contents entries."
3401 :group 'org-export-general
3402 :type 'boolean)
3404 (defcustom org-export-with-tags 'not-in-toc
3405 "If nil, do not export tags, just remove them from headlines.
3406 If this is the symbol `not-in-toc', tags will be removed from table of
3407 contents entries, but still be shown in the headlines of the document.
3409 This option can also be set with the +OPTIONS line, e.g. \"tags:nil\"."
3410 :group 'org-export-general
3411 :type '(choice
3412 (const :tag "Off" nil)
3413 (const :tag "Not in TOC" not-in-toc)
3414 (const :tag "On" t)))
3416 (defcustom org-export-with-drawers nil
3417 "Non-nil means, export with drawers like the property drawer.
3418 When t, all drawers are exported. This may also be a list of
3419 drawer names to export."
3420 :group 'org-export-general
3421 :type '(choice
3422 (const :tag "All drawers" t)
3423 (const :tag "None" nil)
3424 (repeat :tag "Selected drawers"
3425 (string :tag "Drawer name"))))
3427 (defgroup org-export-translation nil
3428 "Options for translating special ascii sequences for the export backends."
3429 :tag "Org Export Translation"
3430 :group 'org-export)
3432 (defcustom org-export-with-emphasize t
3433 "Non-nil means, interpret *word*, /word/, and _word_ as emphasized text.
3434 If the export target supports emphasizing text, the word will be
3435 typeset in bold, italic, or underlined, respectively. Works only for
3436 single words, but you can say: I *really* *mean* *this*.
3437 Not all export backends support this.
3439 This option can also be set with the +OPTIONS line, e.g. \"*:nil\"."
3440 :group 'org-export-translation
3441 :type 'boolean)
3443 (defcustom org-export-with-footnotes t
3444 "If nil, export [1] as a footnote marker.
3445 Lines starting with [1] will be formatted as footnotes.
3447 This option can also be set with the +OPTIONS line, e.g. \"f:nil\"."
3448 :group 'org-export-translation
3449 :type 'boolean)
3451 (defcustom org-export-with-sub-superscripts t
3452 "Non-nil means, interpret \"_\" and \"^\" for export.
3453 When this option is turned on, you can use TeX-like syntax for sub- and
3454 superscripts. Several characters after \"_\" or \"^\" will be
3455 considered as a single item - so grouping with {} is normally not
3456 needed. For example, the following things will be parsed as single
3457 sub- or superscripts.
3459 10^24 or 10^tau several digits will be considered 1 item.
3460 10^-12 or 10^-tau a leading sign with digits or a word
3461 x^2-y^3 will be read as x^2 - y^3, because items are
3462 terminated by almost any nonword/nondigit char.
3463 x_{i^2} or x^(2-i) braces or parenthesis do grouping.
3465 Still, ambiguity is possible - so when in doubt use {} to enclose the
3466 sub/superscript. If you set this variable to the symbol `{}',
3467 the braces are *required* in order to trigger interpretations as
3468 sub/superscript. This can be helpful in documents that need \"_\"
3469 frequently in plain text.
3471 Not all export backends support this, but HTML does.
3473 This option can also be set with the +OPTIONS line, e.g. \"^:nil\"."
3474 :group 'org-export-translation
3475 :type '(choice
3476 (const :tag "Always interpret" t)
3477 (const :tag "Only with braces" {})
3478 (const :tag "Never interpret" nil)))
3480 (defcustom org-export-with-special-strings t
3481 "Non-nil means, interpret \"\-\", \"--\" and \"---\" for export.
3482 When this option is turned on, these strings will be exported as:
3484 \\- : &shy;
3485 -- : &ndash;
3486 --- : &mdash;
3488 Not all export backends support this, but HTML does.
3490 This option can also be set with the +OPTIONS line, e.g. \"-:nil\"."
3491 :group 'org-export-translation
3492 :type 'boolean)
3494 (defcustom org-export-with-TeX-macros t
3495 "Non-nil means, interpret simple TeX-like macros when exporting.
3496 For example, HTML export converts \\alpha to &alpha; and \\AA to &Aring;.
3497 No only real TeX macros will work here, but the standard HTML entities
3498 for math can be used as macro names as well. For a list of supported
3499 names in HTML export, see the constant `org-html-entities'.
3500 Not all export backends support this.
3502 This option can also be set with the +OPTIONS line, e.g. \"TeX:nil\"."
3503 :group 'org-export-translation
3504 :group 'org-export-latex
3505 :type 'boolean)
3507 (defcustom org-export-with-LaTeX-fragments nil
3508 "Non-nil means, convert LaTeX fragments to images when exporting to HTML.
3509 When set, the exporter will find LaTeX environments if the \\begin line is
3510 the first non-white thing on a line. It will also find the math delimiters
3511 like $a=b$ and \\( a=b \\) for inline math, $$a=b$$ and \\[ a=b \\] for
3512 display math.
3514 This option can also be set with the +OPTIONS line, e.g. \"LaTeX:t\"."
3515 :group 'org-export-translation
3516 :group 'org-export-latex
3517 :type 'boolean)
3519 (defcustom org-export-with-fixed-width t
3520 "Non-nil means, lines starting with \":\" will be in fixed width font.
3521 This can be used to have pre-formatted text, fragments of code etc. For
3522 example:
3523 : ;; Some Lisp examples
3524 : (while (defc cnt)
3525 : (ding))
3526 will be looking just like this in also HTML. See also the QUOTE keyword.
3527 Not all export backends support this.
3529 This option can also be set with the +OPTIONS line, e.g. \"::nil\"."
3530 :group 'org-export-translation
3531 :type 'boolean)
3533 (defcustom org-match-sexp-depth 3
3534 "Number of stacked braces for sub/superscript matching.
3535 This has to be set before loading org.el to be effective."
3536 :group 'org-export-translation
3537 :type 'integer)
3539 (defgroup org-export-tables nil
3540 "Options for exporting tables in Org-mode."
3541 :tag "Org Export Tables"
3542 :group 'org-export)
3544 (defcustom org-export-with-tables t
3545 "If non-nil, lines starting with \"|\" define a table.
3546 For example:
3548 | Name | Address | Birthday |
3549 |-------------+----------+-----------|
3550 | Arthur Dent | England | 29.2.2100 |
3552 Not all export backends support this.
3554 This option can also be set with the +OPTIONS line, e.g. \"|:nil\"."
3555 :group 'org-export-tables
3556 :type 'boolean)
3558 (defcustom org-export-highlight-first-table-line t
3559 "Non-nil means, highlight the first table line.
3560 In HTML export, this means use <th> instead of <td>.
3561 In tables created with table.el, this applies to the first table line.
3562 In Org-mode tables, all lines before the first horizontal separator
3563 line will be formatted with <th> tags."
3564 :group 'org-export-tables
3565 :type 'boolean)
3567 (defcustom org-export-table-remove-special-lines t
3568 "Remove special lines and marking characters in calculating tables.
3569 This removes the special marking character column from tables that are set
3570 up for spreadsheet calculations. It also removes the entire lines
3571 marked with `!', `_', or `^'. The lines with `$' are kept, because
3572 the values of constants may be useful to have."
3573 :group 'org-export-tables
3574 :type 'boolean)
3576 (defcustom org-export-prefer-native-exporter-for-tables nil
3577 "Non-nil means, always export tables created with table.el natively.
3578 Natively means, use the HTML code generator in table.el.
3579 When nil, Org-mode's own HTML generator is used when possible (i.e. if
3580 the table does not use row- or column-spanning). This has the
3581 advantage, that the automatic HTML conversions for math symbols and
3582 sub/superscripts can be applied. Org-mode's HTML generator is also
3583 much faster."
3584 :group 'org-export-tables
3585 :type 'boolean)
3587 (defgroup org-export-ascii nil
3588 "Options specific for ASCII export of Org-mode files."
3589 :tag "Org Export ASCII"
3590 :group 'org-export)
3592 (defcustom org-export-ascii-underline '(?\$ ?\# ?^ ?\~ ?\= ?\-)
3593 "Characters for underlining headings in ASCII export.
3594 In the given sequence, these characters will be used for level 1, 2, ..."
3595 :group 'org-export-ascii
3596 :type '(repeat character))
3598 (defcustom org-export-ascii-bullets '(?* ?+ ?-)
3599 "Bullet characters for headlines converted to lists in ASCII export.
3600 The first character is used for the first lest level generated in this
3601 way, and so on. If there are more levels than characters given here,
3602 the list will be repeated.
3603 Note that plain lists will keep the same bullets as the have in the
3604 Org-mode file."
3605 :group 'org-export-ascii
3606 :type '(repeat character))
3608 (defgroup org-export-xml nil
3609 "Options specific for XML export of Org-mode files."
3610 :tag "Org Export XML"
3611 :group 'org-export)
3613 (defgroup org-export-html nil
3614 "Options specific for HTML export of Org-mode files."
3615 :tag "Org Export HTML"
3616 :group 'org-export)
3618 (defcustom org-export-html-coding-system nil
3620 :group 'org-export-html
3621 :type 'coding-system)
3623 (defcustom org-export-html-extension "html"
3624 "The extension for exported HTML files."
3625 :group 'org-export-html
3626 :type 'string)
3628 (defcustom org-export-html-style
3629 "<style type=\"text/css\">
3630 html {
3631 font-family: Times, serif;
3632 font-size: 12pt;
3634 .title { text-align: center; }
3635 .todo { color: red; }
3636 .done { color: green; }
3637 .timestamp { color: grey }
3638 .timestamp-kwd { color: CadetBlue }
3639 .tag { background-color:lightblue; font-weight:normal }
3640 .target { background-color: lavender; }
3641 pre {
3642 border: 1pt solid #AEBDCC;
3643 background-color: #F3F5F7;
3644 padding: 5pt;
3645 font-family: courier, monospace;
3647 table { border-collapse: collapse; }
3648 td, th {
3649 vertical-align: top;
3650 <!--border: 1pt solid #ADB9CC;-->
3652 </style>"
3653 "The default style specification for exported HTML files.
3654 Since there are different ways of setting style information, this variable
3655 needs to contain the full HTML structure to provide a style, including the
3656 surrounding HTML tags. The style specifications should include definitions
3657 for new classes todo, done, title, and deadline. For example, valid values
3658 would be:
3660 <style type=\"text/css\">
3661 p { font-weight: normal; color: gray; }
3662 h1 { color: black; }
3663 .title { text-align: center; }
3664 .todo, .deadline { color: red; }
3665 .done { color: green; }
3666 </style>
3668 or, if you want to keep the style in a file,
3670 <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\">
3672 As the value of this option simply gets inserted into the HTML <head> header,
3673 you can \"misuse\" it to add arbitrary text to the header."
3674 :group 'org-export-html
3675 :type 'string)
3678 (defcustom org-export-html-title-format "<h1 class=\"title\">%s</h1>\n"
3679 "Format for typesetting the document title in HTML export."
3680 :group 'org-export-html
3681 :type 'string)
3683 (defcustom org-export-html-toplevel-hlevel 2
3684 "The <H> level for level 1 headings in HTML export."
3685 :group 'org-export-html
3686 :type 'string)
3688 (defcustom org-export-html-link-org-files-as-html t
3689 "Non-nil means, make file links to `file.org' point to `file.html'.
3690 When org-mode is exporting an org-mode file to HTML, links to
3691 non-html files are directly put into a href tag in HTML.
3692 However, links to other Org-mode files (recognized by the
3693 extension `.org.) should become links to the corresponding html
3694 file, assuming that the linked org-mode file will also be
3695 converted to HTML.
3696 When nil, the links still point to the plain `.org' file."
3697 :group 'org-export-html
3698 :type 'boolean)
3700 (defcustom org-export-html-inline-images 'maybe
3701 "Non-nil means, inline images into exported HTML pages.
3702 This is done using an <img> tag. When nil, an anchor with href is used to
3703 link to the image. If this option is `maybe', then images in links with
3704 an empty description will be inlined, while images with a description will
3705 be linked only."
3706 :group 'org-export-html
3707 :type '(choice (const :tag "Never" nil)
3708 (const :tag "Always" t)
3709 (const :tag "When there is no description" maybe)))
3711 ;; FIXME: rename
3712 (defcustom org-export-html-expand t
3713 "Non-nil means, for HTML export, treat @<...> as HTML tag.
3714 When nil, these tags will be exported as plain text and therefore
3715 not be interpreted by a browser.
3717 This option can also be set with the +OPTIONS line, e.g. \"@:nil\"."
3718 :group 'org-export-html
3719 :type 'boolean)
3721 (defcustom org-export-html-table-tag
3722 "<table border=\"2\" cellspacing=\"0\" cellpadding=\"6\" rules=\"groups\" frame=\"hsides\">"
3723 "The HTML tag that is used to start a table.
3724 This must be a <table> tag, but you may change the options like
3725 borders and spacing."
3726 :group 'org-export-html
3727 :type 'string)
3729 (defcustom org-export-table-header-tags '("<th>" . "</th>")
3730 "The opening tag for table header fields.
3731 This is customizable so that alignment options can be specified."
3732 :group 'org-export-tables
3733 :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
3735 (defcustom org-export-table-data-tags '("<td>" . "</td>")
3736 "The opening tag for table data fields.
3737 This is customizable so that alignment options can be specified."
3738 :group 'org-export-tables
3739 :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
3741 (defcustom org-export-html-with-timestamp nil
3742 "If non-nil, write `org-export-html-html-helper-timestamp'
3743 into the exported HTML text. Otherwise, the buffer will just be saved
3744 to a file."
3745 :group 'org-export-html
3746 :type 'boolean)
3748 (defcustom org-export-html-html-helper-timestamp
3749 "<br/><br/><hr><p><!-- hhmts start --> <!-- hhmts end --></p>\n"
3750 "The HTML tag used as timestamp delimiter for HTML-helper-mode."
3751 :group 'org-export-html
3752 :type 'string)
3754 (defgroup org-export-icalendar nil
3755 "Options specific for iCalendar export of Org-mode files."
3756 :tag "Org Export iCalendar"
3757 :group 'org-export)
3759 (defcustom org-combined-agenda-icalendar-file "~/org.ics"
3760 "The file name for the iCalendar file covering all agenda files.
3761 This file is created with the command \\[org-export-icalendar-all-agenda-files].
3762 The file name should be absolute, the file will be overwritten without warning."
3763 :group 'org-export-icalendar
3764 :type 'file)
3766 (defcustom org-icalendar-include-todo nil
3767 "Non-nil means, export to iCalendar files should also cover TODO items."
3768 :group 'org-export-icalendar
3769 :type '(choice
3770 (const :tag "None" nil)
3771 (const :tag "Unfinished" t)
3772 (const :tag "All" all)))
3774 (defcustom org-icalendar-include-sexps t
3775 "Non-nil means, export to iCalendar files should also cover sexp entries.
3776 These are entries like in the diary, but directly in an Org-mode file."
3777 :group 'org-export-icalendar
3778 :type 'boolean)
3780 (defcustom org-icalendar-include-body 100
3781 "Amount of text below headline to be included in iCalendar export.
3782 This is a number of characters that should maximally be included.
3783 Properties, scheduling and clocking lines will always be removed.
3784 The text will be inserted into the DESCRIPTION field."
3785 :group 'org-export-icalendar
3786 :type '(choice
3787 (const :tag "Nothing" nil)
3788 (const :tag "Everything" t)
3789 (integer :tag "Max characters")))
3791 (defcustom org-icalendar-combined-name "OrgMode"
3792 "Calendar name for the combined iCalendar representing all agenda files."
3793 :group 'org-export-icalendar
3794 :type 'string)
3796 (defgroup org-font-lock nil
3797 "Font-lock settings for highlighting in Org-mode."
3798 :tag "Org Font Lock"
3799 :group 'org)
3801 (defcustom org-level-color-stars-only nil
3802 "Non-nil means fontify only the stars in each headline.
3803 When nil, the entire headline is fontified.
3804 Changing it requires restart of `font-lock-mode' to become effective
3805 also in regions already fontified."
3806 :group 'org-font-lock
3807 :type 'boolean)
3809 (defcustom org-hide-leading-stars nil
3810 "Non-nil means, hide the first N-1 stars in a headline.
3811 This works by using the face `org-hide' for these stars. This
3812 face is white for a light background, and black for a dark
3813 background. You may have to customize the face `org-hide' to
3814 make this work.
3815 Changing it requires restart of `font-lock-mode' to become effective
3816 also in regions already fontified.
3817 You may also set this on a per-file basis by adding one of the following
3818 lines to the buffer:
3820 #+STARTUP: hidestars
3821 #+STARTUP: showstars"
3822 :group 'org-font-lock
3823 :type 'boolean)
3825 (defcustom org-fontify-done-headline nil
3826 "Non-nil means, change the face of a headline if it is marked DONE.
3827 Normally, only the TODO/DONE keyword indicates the state of a headline.
3828 When this is non-nil, the headline after the keyword is set to the
3829 `org-headline-done' as an additional indication."
3830 :group 'org-font-lock
3831 :type 'boolean)
3833 (defcustom org-fontify-emphasized-text t
3834 "Non-nil means fontify *bold*, /italic/ and _underlined_ text.
3835 Changing this variable requires a restart of Emacs to take effect."
3836 :group 'org-font-lock
3837 :type 'boolean)
3839 (defcustom org-highlight-latex-fragments-and-specials nil
3840 "Non-nil means, fontify what is treated specially by the exporters."
3841 :group 'org-font-lock
3842 :type 'boolean)
3844 (defcustom org-hide-emphasis-markers nil
3845 "Non-nil mean font-lock should hide the emphasis marker characters."
3846 :group 'org-font-lock
3847 :type 'boolean)
3849 (defvar org-emph-re nil
3850 "Regular expression for matching emphasis.")
3851 (defvar org-verbatim-re nil
3852 "Regular expression for matching verbatim text.")
3853 (defvar org-emphasis-regexp-components) ; defined just below
3854 (defvar org-emphasis-alist) ; defined just below
3855 (defun org-set-emph-re (var val)
3856 "Set variable and compute the emphasis regular expression."
3857 (set var val)
3858 (when (and (boundp 'org-emphasis-alist)
3859 (boundp 'org-emphasis-regexp-components)
3860 org-emphasis-alist org-emphasis-regexp-components)
3861 (let* ((e org-emphasis-regexp-components)
3862 (pre (car e))
3863 (post (nth 1 e))
3864 (border (nth 2 e))
3865 (body (nth 3 e))
3866 (nl (nth 4 e))
3867 (stacked (and nil (nth 5 e))) ; stacked is no longer allowed, forced to nil
3868 (body1 (concat body "*?"))
3869 (markers (mapconcat 'car org-emphasis-alist ""))
3870 (vmarkers (mapconcat
3871 (lambda (x) (if (eq (nth 4 x) 'verbatim) (car x) ""))
3872 org-emphasis-alist "")))
3873 ;; make sure special characters appear at the right position in the class
3874 (if (string-match "\\^" markers)
3875 (setq markers (concat (replace-match "" t t markers) "^")))
3876 (if (string-match "-" markers)
3877 (setq markers (concat (replace-match "" t t markers) "-")))
3878 (if (string-match "\\^" vmarkers)
3879 (setq vmarkers (concat (replace-match "" t t vmarkers) "^")))
3880 (if (string-match "-" vmarkers)
3881 (setq vmarkers (concat (replace-match "" t t vmarkers) "-")))
3882 (if (> nl 0)
3883 (setq body1 (concat body1 "\\(?:\n" body "*?\\)\\{0,"
3884 (int-to-string nl) "\\}")))
3885 ;; Make the regexp
3886 (setq org-emph-re
3887 (concat "\\([" pre (if (and nil stacked) markers) "]\\|^\\)"
3888 "\\("
3889 "\\([" markers "]\\)"
3890 "\\("
3891 "[^" border "]\\|"
3892 "[^" border (if (and nil stacked) markers) "]"
3893 body1
3894 "[^" border (if (and nil stacked) markers) "]"
3895 "\\)"
3896 "\\3\\)"
3897 "\\([" post (if (and nil stacked) markers) "]\\|$\\)"))
3898 (setq org-verbatim-re
3899 (concat "\\([" pre "]\\|^\\)"
3900 "\\("
3901 "\\([" vmarkers "]\\)"
3902 "\\("
3903 "[^" border "]\\|"
3904 "[^" border "]"
3905 body1
3906 "[^" border "]"
3907 "\\)"
3908 "\\3\\)"
3909 "\\([" post "]\\|$\\)")))))
3911 (defcustom org-emphasis-regexp-components
3912 '(" \t('\"" "- \t.,:?;'\")" " \t\r\n,\"'" "." 1)
3913 "Components used to build the regular expression for emphasis.
3914 This is a list with 6 entries. Terminology: In an emphasis string
3915 like \" *strong word* \", we call the initial space PREMATCH, the final
3916 space POSTMATCH, the stars MARKERS, \"s\" and \"d\" are BORDER characters
3917 and \"trong wor\" is the body. The different components in this variable
3918 specify what is allowed/forbidden in each part:
3920 pre Chars allowed as prematch. Beginning of line will be allowed too.
3921 post Chars allowed as postmatch. End of line will be allowed too.
3922 border The chars *forbidden* as border characters.
3923 body-regexp A regexp like \".\" to match a body character. Don't use
3924 non-shy groups here, and don't allow newline here.
3925 newline The maximum number of newlines allowed in an emphasis exp.
3927 Use customize to modify this, or restart Emacs after changing it."
3928 :group 'org-font-lock
3929 :set 'org-set-emph-re
3930 :type '(list
3931 (sexp :tag "Allowed chars in pre ")
3932 (sexp :tag "Allowed chars in post ")
3933 (sexp :tag "Forbidden chars in border ")
3934 (sexp :tag "Regexp for body ")
3935 (integer :tag "number of newlines allowed")
3936 (option (boolean :tag "Stacking (DISABLED) "))))
3938 (defcustom org-emphasis-alist
3939 '(("*" bold "<b>" "</b>")
3940 ("/" italic "<i>" "</i>")
3941 ("_" underline "<u>" "</u>")
3942 ("=" org-code "<code>" "</code>" verbatim)
3943 ("~" org-verbatim "" "" verbatim)
3944 ("+" (:strike-through t) "<del>" "</del>")
3946 "Special syntax for emphasized text.
3947 Text starting and ending with a special character will be emphasized, for
3948 example *bold*, _underlined_ and /italic/. This variable sets the marker
3949 characters, the face to be used by font-lock for highlighting in Org-mode
3950 Emacs buffers, and the HTML tags to be used for this.
3951 Use customize to modify this, or restart Emacs after changing it."
3952 :group 'org-font-lock
3953 :set 'org-set-emph-re
3954 :type '(repeat
3955 (list
3956 (string :tag "Marker character")
3957 (choice
3958 (face :tag "Font-lock-face")
3959 (plist :tag "Face property list"))
3960 (string :tag "HTML start tag")
3961 (string :tag "HTML end tag")
3962 (option (const verbatim)))))
3964 ;;; The faces
3966 (defgroup org-faces nil
3967 "Faces in Org-mode."
3968 :tag "Org Faces"
3969 :group 'org-font-lock)
3971 (defun org-compatible-face (inherits specs)
3972 "Make a compatible face specification.
3973 If INHERITS is an existing face and if the Emacs version supports it,
3974 just inherit the face. If not, use SPECS to define the face.
3975 XEmacs and Emacs 21 do not know about the `min-colors' attribute.
3976 For them we convert a (min-colors 8) entry to a `tty' entry and move it
3977 to the top of the list. The `min-colors' attribute will be removed from
3978 any other entries, and any resulting duplicates will be removed entirely."
3979 (cond
3980 ((and inherits (facep inherits)
3981 (not (featurep 'xemacs)) (> emacs-major-version 22))
3982 ;; In Emacs 23, we use inheritance where possible.
3983 ;; We only do this in Emacs 23, because only there the outline
3984 ;; faces have been changed to the original org-mode-level-faces.
3985 (list (list t :inherit inherits)))
3986 ((or (featurep 'xemacs) (< emacs-major-version 22))
3987 ;; These do not understand the `min-colors' attribute.
3988 (let (r e a)
3989 (while (setq e (pop specs))
3990 (cond
3991 ((memq (car e) '(t default)) (push e r))
3992 ((setq a (member '(min-colors 8) (car e)))
3993 (nconc r (list (cons (cons '(type tty) (delq (car a) (car e)))
3994 (cdr e)))))
3995 ((setq a (assq 'min-colors (car e)))
3996 (setq e (cons (delq a (car e)) (cdr e)))
3997 (or (assoc (car e) r) (push e r)))
3998 (t (or (assoc (car e) r) (push e r)))))
3999 (nreverse r)))
4000 (t specs)))
4001 (put 'org-compatible-face 'lisp-indent-function 1)
4003 (defface org-hide
4004 '((((background light)) (:foreground "white"))
4005 (((background dark)) (:foreground "black")))
4006 "Face used to hide leading stars in headlines.
4007 The forground color of this face should be equal to the background
4008 color of the frame."
4009 :group 'org-faces)
4011 (defface org-level-1 ;; font-lock-function-name-face
4012 (org-compatible-face 'outline-1
4013 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
4014 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
4015 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
4016 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
4017 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
4018 (t (:bold t))))
4019 "Face used for level 1 headlines."
4020 :group 'org-faces)
4022 (defface org-level-2 ;; font-lock-variable-name-face
4023 (org-compatible-face 'outline-2
4024 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
4025 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
4026 (((class color) (min-colors 8) (background light)) (:foreground "yellow"))
4027 (((class color) (min-colors 8) (background dark)) (:foreground "yellow" :bold t))
4028 (t (:bold t))))
4029 "Face used for level 2 headlines."
4030 :group 'org-faces)
4032 (defface org-level-3 ;; font-lock-keyword-face
4033 (org-compatible-face 'outline-3
4034 '((((class color) (min-colors 88) (background light)) (:foreground "Purple"))
4035 (((class color) (min-colors 88) (background dark)) (:foreground "Cyan1"))
4036 (((class color) (min-colors 16) (background light)) (:foreground "Purple"))
4037 (((class color) (min-colors 16) (background dark)) (:foreground "Cyan"))
4038 (((class color) (min-colors 8) (background light)) (:foreground "purple" :bold t))
4039 (((class color) (min-colors 8) (background dark)) (:foreground "cyan" :bold t))
4040 (t (:bold t))))
4041 "Face used for level 3 headlines."
4042 :group 'org-faces)
4044 (defface org-level-4 ;; font-lock-comment-face
4045 (org-compatible-face 'outline-4
4046 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
4047 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
4048 (((class color) (min-colors 16) (background light)) (:foreground "red"))
4049 (((class color) (min-colors 16) (background dark)) (:foreground "red1"))
4050 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
4051 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
4052 (t (:bold t))))
4053 "Face used for level 4 headlines."
4054 :group 'org-faces)
4056 (defface org-level-5 ;; font-lock-type-face
4057 (org-compatible-face 'outline-5
4058 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
4059 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
4060 (((class color) (min-colors 8)) (:foreground "green"))))
4061 "Face used for level 5 headlines."
4062 :group 'org-faces)
4064 (defface org-level-6 ;; font-lock-constant-face
4065 (org-compatible-face 'outline-6
4066 '((((class color) (min-colors 16) (background light)) (:foreground "CadetBlue"))
4067 (((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine"))
4068 (((class color) (min-colors 8)) (:foreground "magenta"))))
4069 "Face used for level 6 headlines."
4070 :group 'org-faces)
4072 (defface org-level-7 ;; font-lock-builtin-face
4073 (org-compatible-face 'outline-7
4074 '((((class color) (min-colors 16) (background light)) (:foreground "Orchid"))
4075 (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue"))
4076 (((class color) (min-colors 8)) (:foreground "blue"))))
4077 "Face used for level 7 headlines."
4078 :group 'org-faces)
4080 (defface org-level-8 ;; font-lock-string-face
4081 (org-compatible-face 'outline-8
4082 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
4083 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
4084 (((class color) (min-colors 8)) (:foreground "green"))))
4085 "Face used for level 8 headlines."
4086 :group 'org-faces)
4088 (defface org-special-keyword ;; font-lock-string-face
4089 (org-compatible-face nil
4090 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
4091 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
4092 (t (:italic t))))
4093 "Face used for special keywords."
4094 :group 'org-faces)
4096 (defface org-drawer ;; font-lock-function-name-face
4097 (org-compatible-face nil
4098 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
4099 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
4100 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
4101 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
4102 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
4103 (t (:bold t))))
4104 "Face used for drawers."
4105 :group 'org-faces)
4107 (defface org-property-value nil
4108 "Face used for the value of a property."
4109 :group 'org-faces)
4111 (defface org-column
4112 (org-compatible-face nil
4113 '((((class color) (min-colors 16) (background light))
4114 (:background "grey90"))
4115 (((class color) (min-colors 16) (background dark))
4116 (:background "grey30"))
4117 (((class color) (min-colors 8))
4118 (:background "cyan" :foreground "black"))
4119 (t (:inverse-video t))))
4120 "Face for column display of entry properties."
4121 :group 'org-faces)
4123 (when (fboundp 'set-face-attribute)
4124 ;; Make sure that a fixed-width face is used when we have a column table.
4125 (set-face-attribute 'org-column nil
4126 :height (face-attribute 'default :height)
4127 :family (face-attribute 'default :family)))
4129 (defface org-warning
4130 (org-compatible-face 'font-lock-warning-face
4131 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
4132 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
4133 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
4134 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
4135 (t (:bold t))))
4136 "Face for deadlines and TODO keywords."
4137 :group 'org-faces)
4139 (defface org-archived ; similar to shadow
4140 (org-compatible-face 'shadow
4141 '((((class color grayscale) (min-colors 88) (background light))
4142 (:foreground "grey50"))
4143 (((class color grayscale) (min-colors 88) (background dark))
4144 (:foreground "grey70"))
4145 (((class color) (min-colors 8) (background light))
4146 (:foreground "green"))
4147 (((class color) (min-colors 8) (background dark))
4148 (:foreground "yellow"))))
4149 "Face for headline with the ARCHIVE tag."
4150 :group 'org-faces)
4152 (defface org-link
4153 '((((class color) (background light)) (:foreground "Purple" :underline t))
4154 (((class color) (background dark)) (:foreground "Cyan" :underline t))
4155 (t (:underline t)))
4156 "Face for links."
4157 :group 'org-faces)
4159 (defface org-ellipsis
4160 '((((class color) (background light)) (:foreground "DarkGoldenrod" :underline t))
4161 (((class color) (background dark)) (:foreground "LightGoldenrod" :underline t))
4162 (t (:strike-through t)))
4163 "Face for the ellipsis in folded text."
4164 :group 'org-faces)
4166 (defface org-target
4167 '((((class color) (background light)) (:underline t))
4168 (((class color) (background dark)) (:underline t))
4169 (t (:underline t)))
4170 "Face for links."
4171 :group 'org-faces)
4173 (defface org-date
4174 '((((class color) (background light)) (:foreground "Purple" :underline t))
4175 (((class color) (background dark)) (:foreground "Cyan" :underline t))
4176 (t (:underline t)))
4177 "Face for links."
4178 :group 'org-faces)
4180 (defface org-sexp-date
4181 '((((class color) (background light)) (:foreground "Purple"))
4182 (((class color) (background dark)) (:foreground "Cyan"))
4183 (t (:underline t)))
4184 "Face for links."
4185 :group 'org-faces)
4187 (defface org-tag
4188 '((t (:bold t)))
4189 "Face for tags."
4190 :group 'org-faces)
4192 (defface org-todo ; font-lock-warning-face
4193 (org-compatible-face nil
4194 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
4195 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
4196 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
4197 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
4198 (t (:inverse-video t :bold t))))
4199 "Face for TODO keywords."
4200 :group 'org-faces)
4202 (defface org-done ;; font-lock-type-face
4203 (org-compatible-face nil
4204 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen" :bold t))
4205 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen" :bold t))
4206 (((class color) (min-colors 8)) (:foreground "green"))
4207 (t (:bold t))))
4208 "Face used for todo keywords that indicate DONE items."
4209 :group 'org-faces)
4211 (defface org-headline-done ;; font-lock-string-face
4212 (org-compatible-face nil
4213 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
4214 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
4215 (((class color) (min-colors 8) (background light)) (:bold nil))))
4216 "Face used to indicate that a headline is DONE.
4217 This face is only used if `org-fontify-done-headline' is set. If applies
4218 to the part of the headline after the DONE keyword."
4219 :group 'org-faces)
4221 (defcustom org-todo-keyword-faces nil
4222 "Faces for specific TODO keywords.
4223 This is a list of cons cells, with TODO keywords in the car
4224 and faces in the cdr. The face can be a symbol, or a property
4225 list of attributes, like (:foreground \"blue\" :weight bold :underline t)."
4226 :group 'org-faces
4227 :group 'org-todo
4228 :type '(repeat
4229 (cons
4230 (string :tag "keyword")
4231 (sexp :tag "face"))))
4233 (defface org-table ;; font-lock-function-name-face
4234 (org-compatible-face nil
4235 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
4236 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
4237 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
4238 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
4239 (((class color) (min-colors 8) (background light)) (:foreground "blue"))
4240 (((class color) (min-colors 8) (background dark)))))
4241 "Face used for tables."
4242 :group 'org-faces)
4244 (defface org-formula
4245 (org-compatible-face nil
4246 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
4247 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
4248 (((class color) (min-colors 8) (background light)) (:foreground "red"))
4249 (((class color) (min-colors 8) (background dark)) (:foreground "red"))
4250 (t (:bold t :italic t))))
4251 "Face for formulas."
4252 :group 'org-faces)
4254 (defface org-code
4255 (org-compatible-face nil
4256 '((((class color grayscale) (min-colors 88) (background light))
4257 (:foreground "grey50"))
4258 (((class color grayscale) (min-colors 88) (background dark))
4259 (:foreground "grey70"))
4260 (((class color) (min-colors 8) (background light))
4261 (:foreground "green"))
4262 (((class color) (min-colors 8) (background dark))
4263 (:foreground "yellow"))))
4264 "Face for fixed-with text like code snippets."
4265 :group 'org-faces
4266 :version "22.1")
4268 (defface org-verbatim
4269 (org-compatible-face nil
4270 '((((class color grayscale) (min-colors 88) (background light))
4271 (:foreground "grey50" :underline t))
4272 (((class color grayscale) (min-colors 88) (background dark))
4273 (:foreground "grey70" :underline t))
4274 (((class color) (min-colors 8) (background light))
4275 (:foreground "green" :underline t))
4276 (((class color) (min-colors 8) (background dark))
4277 (:foreground "yellow" :underline t))))
4278 "Face for fixed-with text like code snippets."
4279 :group 'org-faces
4280 :version "22.1")
4282 (defface org-agenda-structure ;; font-lock-function-name-face
4283 (org-compatible-face nil
4284 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
4285 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
4286 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
4287 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
4288 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
4289 (t (:bold t))))
4290 "Face used in agenda for captions and dates."
4291 :group 'org-faces)
4293 (defface org-scheduled-today
4294 (org-compatible-face nil
4295 '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen"))
4296 (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen"))
4297 (((class color) (min-colors 8)) (:foreground "green"))
4298 (t (:bold t :italic t))))
4299 "Face for items scheduled for a certain day."
4300 :group 'org-faces)
4302 (defface org-scheduled-previously
4303 (org-compatible-face nil
4304 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
4305 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
4306 (((class color) (min-colors 8) (background light)) (:foreground "red"))
4307 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
4308 (t (:bold t))))
4309 "Face for items scheduled previously, and not yet done."
4310 :group 'org-faces)
4312 (defface org-upcoming-deadline
4313 (org-compatible-face nil
4314 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
4315 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
4316 (((class color) (min-colors 8) (background light)) (:foreground "red"))
4317 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
4318 (t (:bold t))))
4319 "Face for items scheduled previously, and not yet done."
4320 :group 'org-faces)
4322 (defcustom org-agenda-deadline-faces
4323 '((1.0 . org-warning)
4324 (0.5 . org-upcoming-deadline)
4325 (0.0 . default))
4326 "Faces for showing deadlines in the agenda.
4327 This is a list of cons cells. The cdr of each cell is a face to be used,
4328 and it can also just be like '(:foreground \"yellow\").
4329 Each car is a fraction of the head-warning time that must have passed for
4330 this the face in the cdr to be used for display. The numbers must be
4331 given in descending order. The head-warning time is normally taken
4332 from `org-deadline-warning-days', but can also be specified in the deadline
4333 timestamp itself, like this:
4335 DEADLINE: <2007-08-13 Mon -8d>
4337 You may use d for days, w for weeks, m for months and y for years. Months
4338 and years will only be treated in an approximate fashion (30.4 days for a
4339 month and 365.24 days for a year)."
4340 :group 'org-faces
4341 :group 'org-agenda-daily/weekly
4342 :type '(repeat
4343 (cons
4344 (number :tag "Fraction of head-warning time passed")
4345 (sexp :tag "Face"))))
4347 ;; FIXME: this is not a good face yet.
4348 (defface org-agenda-restriction-lock
4349 (org-compatible-face nil
4350 '((((class color) (min-colors 88) (background light)) (:background "yellow1"))
4351 (((class color) (min-colors 88) (background dark)) (:background "skyblue4"))
4352 (((class color) (min-colors 16) (background light)) (:background "yellow1"))
4353 (((class color) (min-colors 16) (background dark)) (:background "skyblue4"))
4354 (((class color) (min-colors 8)) (:background "cyan" :foreground "black"))
4355 (t (:inverse-video t))))
4356 "Face for showing the agenda restriction lock."
4357 :group 'org-faces)
4359 (defface org-time-grid ;; font-lock-variable-name-face
4360 (org-compatible-face nil
4361 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
4362 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
4363 (((class color) (min-colors 8)) (:foreground "yellow" :weight light))))
4364 "Face used for time grids."
4365 :group 'org-faces)
4367 (defconst org-level-faces
4368 '(org-level-1 org-level-2 org-level-3 org-level-4
4369 org-level-5 org-level-6 org-level-7 org-level-8
4372 (defcustom org-n-level-faces (length org-level-faces)
4373 "The number of different faces to be used for headlines.
4374 Org-mode defines 8 different headline faces, so this can be at most 8.
4375 If it is less than 8, the level-1 face gets re-used for level N+1 etc."
4376 :type 'number
4377 :group 'org-faces)
4379 ;;; Functions and variables from ther packages
4380 ;; Declared here to avoid compiler warnings
4382 (eval-and-compile
4383 (unless (fboundp 'declare-function)
4384 (defmacro declare-function (fn file &optional arglist fileonly))))
4386 ;; XEmacs only
4387 (defvar outline-mode-menu-heading)
4388 (defvar outline-mode-menu-show)
4389 (defvar outline-mode-menu-hide)
4390 (defvar zmacs-regions) ; XEmacs regions
4392 ;; Emacs only
4393 (defvar mark-active)
4395 ;; Various packages
4396 ;; FIXME: get the argument lists for the UNKNOWN stuff
4397 (declare-function add-to-diary-list "diary-lib"
4398 (date string specifier &optional marker globcolor literal))
4399 (declare-function table--at-cell-p "table" (position &optional object at-column))
4400 (declare-function bibtex-beginning-of-entry "bibtex" ())
4401 (declare-function bibtex-generate-autokey "bibtex" ())
4402 (declare-function bibtex-parse-entry "bibtex" (&optional content))
4403 (declare-function bibtex-url "bibtex" (&optional pos no-browse))
4404 (defvar calc-embedded-close-formula)
4405 (defvar calc-embedded-open-formula)
4406 (declare-function calendar-astro-date-string "cal-julian" (&optional date))
4407 (declare-function calendar-bahai-date-string "cal-bahai" (&optional date))
4408 (declare-function calendar-check-holidays "holidays" (date))
4409 (declare-function calendar-chinese-date-string "cal-china" (&optional date))
4410 (declare-function calendar-coptic-date-string "cal-coptic" (&optional date))
4411 (declare-function calendar-ethiopic-date-string "cal-coptic" (&optional date))
4412 (declare-function calendar-forward-day "cal-move" (arg))
4413 (declare-function calendar-french-date-string "cal-french" (&optional date))
4414 (declare-function calendar-goto-date "cal-move" (date))
4415 (declare-function calendar-goto-today "cal-move" ())
4416 (declare-function calendar-hebrew-date-string "cal-hebrew" (&optional date))
4417 (declare-function calendar-islamic-date-string "cal-islam" (&optional date))
4418 (declare-function calendar-iso-date-string "cal-iso" (&optional date))
4419 (declare-function calendar-iso-from-absolute "cal-iso" (&optional date))
4420 (declare-function calendar-absolute-from-iso "cal-iso" (&optional date))
4421 (declare-function calendar-julian-date-string "cal-julian" (&optional date))
4422 (declare-function calendar-mayan-date-string "cal-mayan" (&optional date))
4423 (declare-function calendar-persian-date-string "cal-persia" (&optional date))
4424 (defvar calendar-mode-map)
4425 (defvar original-date) ; dynamically scoped in calendar.el does scope this
4426 (declare-function cdlatex-tab "ext:cdlatex" ())
4427 (declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
4428 (defvar font-lock-unfontify-region-function)
4429 (declare-function org-export-latex-cleaned-string "org-export-latex" ())
4430 (declare-function org-gnus-follow-link "org-gnus" (&optional group article))
4431 (declare-function parse-time-string "parse-time" (string))
4432 (declare-function remember "remember" (&optional initial))
4433 (declare-function remember-buffer-desc "remember" ())
4434 (declare-function remember-finalize "remember" ())
4435 (defvar remember-save-after-remembering)
4436 (defvar remember-data-file)
4437 (defvar remember-register)
4438 (defvar remember-buffer)
4439 (defvar remember-handler-functions)
4440 (defvar remember-annotation-functions)
4441 (defvar texmathp-why)
4442 (declare-function speedbar-line-directory "speedbar" (&optional depth))
4444 (defvar w3m-current-url)
4445 (defvar w3m-current-title)
4447 (defvar org-latex-regexps)
4448 (defvar constants-unit-system)
4450 ;;; Variables for pre-computed regular expressions, all buffer local
4452 (defvar org-drawer-regexp nil
4453 "Matches first line of a hidden block.")
4454 (make-variable-buffer-local 'org-drawer-regexp)
4455 (defvar org-todo-regexp nil
4456 "Matches any of the TODO state keywords.")
4457 (make-variable-buffer-local 'org-todo-regexp)
4458 (defvar org-not-done-regexp nil
4459 "Matches any of the TODO state keywords except the last one.")
4460 (make-variable-buffer-local 'org-not-done-regexp)
4461 (defvar org-todo-line-regexp nil
4462 "Matches a headline and puts TODO state into group 2 if present.")
4463 (make-variable-buffer-local 'org-todo-line-regexp)
4464 (defvar org-complex-heading-regexp nil
4465 "Matches a headline and puts everything into groups:
4466 group 1: the stars
4467 group 2: The todo keyword, maybe
4468 group 3: Priority cookie
4469 group 4: True headline
4470 group 5: Tags")
4471 (make-variable-buffer-local 'org-complex-heading-regexp)
4472 (defvar org-todo-line-tags-regexp nil
4473 "Matches a headline and puts TODO state into group 2 if present.
4474 Also put tags into group 4 if tags are present.")
4475 (make-variable-buffer-local 'org-todo-line-tags-regexp)
4476 (defvar org-nl-done-regexp nil
4477 "Matches newline followed by a headline with the DONE keyword.")
4478 (make-variable-buffer-local 'org-nl-done-regexp)
4479 (defvar org-looking-at-done-regexp nil
4480 "Matches the DONE keyword a point.")
4481 (make-variable-buffer-local 'org-looking-at-done-regexp)
4482 (defvar org-ds-keyword-length 12
4483 "Maximum length of the Deadline and SCHEDULED keywords.")
4484 (make-variable-buffer-local 'org-ds-keyword-length)
4485 (defvar org-deadline-regexp nil
4486 "Matches the DEADLINE keyword.")
4487 (make-variable-buffer-local 'org-deadline-regexp)
4488 (defvar org-deadline-time-regexp nil
4489 "Matches the DEADLINE keyword together with a time stamp.")
4490 (make-variable-buffer-local 'org-deadline-time-regexp)
4491 (defvar org-deadline-line-regexp nil
4492 "Matches the DEADLINE keyword and the rest of the line.")
4493 (make-variable-buffer-local 'org-deadline-line-regexp)
4494 (defvar org-scheduled-regexp nil
4495 "Matches the SCHEDULED keyword.")
4496 (make-variable-buffer-local 'org-scheduled-regexp)
4497 (defvar org-scheduled-time-regexp nil
4498 "Matches the SCHEDULED keyword together with a time stamp.")
4499 (make-variable-buffer-local 'org-scheduled-time-regexp)
4500 (defvar org-closed-time-regexp nil
4501 "Matches the CLOSED keyword together with a time stamp.")
4502 (make-variable-buffer-local 'org-closed-time-regexp)
4504 (defvar org-keyword-time-regexp nil
4505 "Matches any of the 4 keywords, together with the time stamp.")
4506 (make-variable-buffer-local 'org-keyword-time-regexp)
4507 (defvar org-keyword-time-not-clock-regexp nil
4508 "Matches any of the 3 keywords, together with the time stamp.")
4509 (make-variable-buffer-local 'org-keyword-time-not-clock-regexp)
4510 (defvar org-maybe-keyword-time-regexp nil
4511 "Matches a timestamp, possibly preceeded by a keyword.")
4512 (make-variable-buffer-local 'org-maybe-keyword-time-regexp)
4513 (defvar org-planning-or-clock-line-re nil
4514 "Matches a line with planning or clock info.")
4515 (make-variable-buffer-local 'org-planning-or-clock-line-re)
4517 (defconst org-rm-props '(invisible t face t keymap t intangible t mouse-face t
4518 rear-nonsticky t mouse-map t fontified t)
4519 "Properties to remove when a string without properties is wanted.")
4521 (defsubst org-match-string-no-properties (num &optional string)
4522 (if (featurep 'xemacs)
4523 (let ((s (match-string num string)))
4524 (remove-text-properties 0 (length s) org-rm-props s)
4526 (match-string-no-properties num string)))
4528 (defsubst org-no-properties (s)
4529 (if (fboundp 'set-text-properties)
4530 (set-text-properties 0 (length s) nil s)
4531 (remove-text-properties 0 (length s) org-rm-props s))
4534 (defsubst org-get-alist-option (option key)
4535 (cond ((eq key t) t)
4536 ((eq option t) t)
4537 ((assoc key option) (cdr (assoc key option)))
4538 (t (cdr (assq 'default option)))))
4540 (defsubst org-inhibit-invisibility ()
4541 "Modified `buffer-invisibility-spec' for Emacs 21.
4542 Some ops with invisible text do not work correctly on Emacs 21. For these
4543 we turn off invisibility temporarily. Use this in a `let' form."
4544 (if (< emacs-major-version 22) nil buffer-invisibility-spec))
4546 (defsubst org-set-local (var value)
4547 "Make VAR local in current buffer and set it to VALUE."
4548 (set (make-variable-buffer-local var) value))
4550 (defsubst org-mode-p ()
4551 "Check if the current buffer is in Org-mode."
4552 (eq major-mode 'org-mode))
4554 (defsubst org-last (list)
4555 "Return the last element of LIST."
4556 (car (last list)))
4558 (defun org-let (list &rest body)
4559 (eval (cons 'let (cons list body))))
4560 (put 'org-let 'lisp-indent-function 1)
4562 (defun org-let2 (list1 list2 &rest body)
4563 (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body)))))))
4564 (put 'org-let2 'lisp-indent-function 2)
4565 (defconst org-startup-options
4566 '(("fold" org-startup-folded t)
4567 ("overview" org-startup-folded t)
4568 ("nofold" org-startup-folded nil)
4569 ("showall" org-startup-folded nil)
4570 ("content" org-startup-folded content)
4571 ("hidestars" org-hide-leading-stars t)
4572 ("showstars" org-hide-leading-stars nil)
4573 ("odd" org-odd-levels-only t)
4574 ("oddeven" org-odd-levels-only nil)
4575 ("align" org-startup-align-all-tables t)
4576 ("noalign" org-startup-align-all-tables nil)
4577 ("customtime" org-display-custom-times t)
4578 ("logdone" org-log-done time)
4579 ("lognotedone" org-log-done note)
4580 ("nologdone" org-log-done nil)
4581 ("lognoteclock-out" org-log-note-clock-out t)
4582 ("nolognoteclock-out" org-log-note-clock-out nil)
4583 ("logrepeat" org-log-repeat state)
4584 ("lognoterepeat" org-log-repeat note)
4585 ("nologrepeat" org-log-repeat nil)
4586 ("constcgs" constants-unit-system cgs)
4587 ("constSI" constants-unit-system SI))
4588 "Variable associated with STARTUP options for org-mode.
4589 Each element is a list of three items: The startup options as written
4590 in the #+STARTUP line, the corresponding variable, and the value to
4591 set this variable to if the option is found. An optional forth element PUSH
4592 means to push this value onto the list in the variable.")
4594 (defun org-set-regexps-and-options ()
4595 "Precompute regular expressions for current buffer."
4596 (when (org-mode-p)
4597 (org-set-local 'org-todo-kwd-alist nil)
4598 (org-set-local 'org-todo-key-alist nil)
4599 (org-set-local 'org-todo-key-trigger nil)
4600 (org-set-local 'org-todo-keywords-1 nil)
4601 (org-set-local 'org-done-keywords nil)
4602 (org-set-local 'org-todo-heads nil)
4603 (org-set-local 'org-todo-sets nil)
4604 (org-set-local 'org-todo-log-states nil)
4605 (let ((re (org-make-options-regexp
4606 '("CATEGORY" "SEQ_TODO" "TYP_TODO" "TODO" "COLUMNS"
4607 "STARTUP" "ARCHIVE" "TAGS" "LINK" "PRIORITIES"
4608 "CONSTANTS" "PROPERTY" "DRAWERS")))
4609 (splitre "[ \t]+")
4610 kwds kws0 kwsa key log value cat arch tags const links hw dws
4611 tail sep kws1 prio props drawers)
4612 (save-excursion
4613 (save-restriction
4614 (widen)
4615 (goto-char (point-min))
4616 (while (re-search-forward re nil t)
4617 (setq key (match-string 1) value (org-match-string-no-properties 2))
4618 (cond
4619 ((equal key "CATEGORY")
4620 (if (string-match "[ \t]+$" value)
4621 (setq value (replace-match "" t t value)))
4622 (setq cat value))
4623 ((member key '("SEQ_TODO" "TODO"))
4624 (push (cons 'sequence (org-split-string value splitre)) kwds))
4625 ((equal key "TYP_TODO")
4626 (push (cons 'type (org-split-string value splitre)) kwds))
4627 ((equal key "TAGS")
4628 (setq tags (append tags (org-split-string value splitre))))
4629 ((equal key "COLUMNS")
4630 (org-set-local 'org-columns-default-format value))
4631 ((equal key "LINK")
4632 (when (string-match "^\\(\\S-+\\)[ \t]+\\(.+\\)" value)
4633 (push (cons (match-string 1 value)
4634 (org-trim (match-string 2 value)))
4635 links)))
4636 ((equal key "PRIORITIES")
4637 (setq prio (org-split-string value " +")))
4638 ((equal key "PROPERTY")
4639 (when (string-match "\\(\\S-+\\)\\s-+\\(.*\\)" value)
4640 (push (cons (match-string 1 value) (match-string 2 value))
4641 props)))
4642 ((equal key "DRAWERS")
4643 (setq drawers (org-split-string value splitre)))
4644 ((equal key "CONSTANTS")
4645 (setq const (append const (org-split-string value splitre))))
4646 ((equal key "STARTUP")
4647 (let ((opts (org-split-string value splitre))
4648 l var val)
4649 (while (setq l (pop opts))
4650 (when (setq l (assoc l org-startup-options))
4651 (setq var (nth 1 l) val (nth 2 l))
4652 (if (not (nth 3 l))
4653 (set (make-local-variable var) val)
4654 (if (not (listp (symbol-value var)))
4655 (set (make-local-variable var) nil))
4656 (set (make-local-variable var) (symbol-value var))
4657 (add-to-list var val))))))
4658 ((equal key "ARCHIVE")
4659 (string-match " *$" value)
4660 (setq arch (replace-match "" t t value))
4661 (remove-text-properties 0 (length arch)
4662 '(face t fontified t) arch)))
4664 (when cat
4665 (org-set-local 'org-category (intern cat))
4666 (push (cons "CATEGORY" cat) props))
4667 (when prio
4668 (if (< (length prio) 3) (setq prio '("A" "C" "B")))
4669 (setq prio (mapcar 'string-to-char prio))
4670 (org-set-local 'org-highest-priority (nth 0 prio))
4671 (org-set-local 'org-lowest-priority (nth 1 prio))
4672 (org-set-local 'org-default-priority (nth 2 prio)))
4673 (and props (org-set-local 'org-local-properties (nreverse props)))
4674 (and drawers (org-set-local 'org-drawers drawers))
4675 (and arch (org-set-local 'org-archive-location arch))
4676 (and links (setq org-link-abbrev-alist-local (nreverse links)))
4677 ;; Process the TODO keywords
4678 (unless kwds
4679 ;; Use the global values as if they had been given locally.
4680 (setq kwds (default-value 'org-todo-keywords))
4681 (if (stringp (car kwds))
4682 (setq kwds (list (cons org-todo-interpretation
4683 (default-value 'org-todo-keywords)))))
4684 (setq kwds (reverse kwds)))
4685 (setq kwds (nreverse kwds))
4686 (let (inter kws kw)
4687 (while (setq kws (pop kwds))
4688 (setq inter (pop kws) sep (member "|" kws)
4689 kws0 (delete "|" (copy-sequence kws))
4690 kwsa nil
4691 kws1 (mapcar
4692 (lambda (x)
4693 ;; 1 2
4694 (if (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?.*?)\\)?$" x)
4695 (progn
4696 (setq kw (match-string 1 x)
4697 key (and (match-end 2) (match-string 2 x))
4698 log (org-extract-log-state-settings x))
4699 (push (cons kw (and key (string-to-char key))) kwsa)
4700 (and log (push log org-todo-log-states))
4702 (error "Invalid TODO keyword %s" x)))
4703 kws0)
4704 kwsa (if kwsa (append '((:startgroup))
4705 (nreverse kwsa)
4706 '((:endgroup))))
4707 hw (car kws1)
4708 dws (if sep (org-remove-keyword-keys (cdr sep)) (last kws1))
4709 tail (list inter hw (car dws) (org-last dws)))
4710 (add-to-list 'org-todo-heads hw 'append)
4711 (push kws1 org-todo-sets)
4712 (setq org-done-keywords (append org-done-keywords dws nil))
4713 (setq org-todo-key-alist (append org-todo-key-alist kwsa))
4714 (mapc (lambda (x) (push (cons x tail) org-todo-kwd-alist)) kws1)
4715 (setq org-todo-keywords-1 (append org-todo-keywords-1 kws1 nil)))
4716 (setq org-todo-sets (nreverse org-todo-sets)
4717 org-todo-kwd-alist (nreverse org-todo-kwd-alist)
4718 org-todo-key-trigger (delq nil (mapcar 'cdr org-todo-key-alist))
4719 org-todo-key-alist (org-assign-fast-keys org-todo-key-alist)))
4720 ;; Process the constants
4721 (when const
4722 (let (e cst)
4723 (while (setq e (pop const))
4724 (if (string-match "^\\([a-zA-Z0][_a-zA-Z0-9]*\\)=\\(.*\\)" e)
4725 (push (cons (match-string 1 e) (match-string 2 e)) cst)))
4726 (setq org-table-formula-constants-local cst)))
4728 ;; Process the tags.
4729 (when tags
4730 (let (e tgs)
4731 (while (setq e (pop tags))
4732 (cond
4733 ((equal e "{") (push '(:startgroup) tgs))
4734 ((equal e "}") (push '(:endgroup) tgs))
4735 ((string-match (org-re "^\\([[:alnum:]_@]+\\)(\\(.\\))$") e)
4736 (push (cons (match-string 1 e)
4737 (string-to-char (match-string 2 e)))
4738 tgs))
4739 (t (push (list e) tgs))))
4740 (org-set-local 'org-tag-alist nil)
4741 (while (setq e (pop tgs))
4742 (or (and (stringp (car e))
4743 (assoc (car e) org-tag-alist))
4744 (push e org-tag-alist))))))
4746 ;; Compute the regular expressions and other local variables
4747 (if (not org-done-keywords)
4748 (setq org-done-keywords (list (org-last org-todo-keywords-1))))
4749 (setq org-ds-keyword-length (+ 2 (max (length org-deadline-string)
4750 (length org-scheduled-string)))
4751 org-drawer-regexp
4752 (concat "^[ \t]*:\\("
4753 (mapconcat 'regexp-quote org-drawers "\\|")
4754 "\\):[ \t]*$")
4755 org-not-done-keywords
4756 (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1))
4757 org-todo-regexp
4758 (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords-1
4759 "\\|") "\\)\\>")
4760 org-not-done-regexp
4761 (concat "\\<\\("
4762 (mapconcat 'regexp-quote org-not-done-keywords "\\|")
4763 "\\)\\>")
4764 org-todo-line-regexp
4765 (concat "^\\(\\*+\\)[ \t]+\\(?:\\("
4766 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
4767 "\\)\\>\\)?[ \t]*\\(.*\\)")
4768 org-complex-heading-regexp
4769 (concat "^\\(\\*+\\)\\(?:[ \t]+\\("
4770 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
4771 "\\)\\>\\)?\\(?:[ \t]*\\(\\[#.\\]\\)\\)?[ \t]*\\(.*?\\)"
4772 "\\(?:[ \t]+\\(:[[:alnum:]_@:]+:\\)\\)?[ \t]*$")
4773 org-nl-done-regexp
4774 (concat "\n\\*+[ \t]+"
4775 "\\(?:" (mapconcat 'regexp-quote org-done-keywords "\\|")
4776 "\\)" "\\>")
4777 org-todo-line-tags-regexp
4778 (concat "^\\(\\*+\\)[ \t]+\\(?:\\("
4779 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
4780 (org-re
4781 "\\)\\>\\)? *\\(.*?\\([ \t]:[[:alnum:]:_@]+:[ \t]*\\)?$\\)"))
4782 org-looking-at-done-regexp
4783 (concat "^" "\\(?:"
4784 (mapconcat 'regexp-quote org-done-keywords "\\|") "\\)"
4785 "\\>")
4786 org-deadline-regexp (concat "\\<" org-deadline-string)
4787 org-deadline-time-regexp
4788 (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
4789 org-deadline-line-regexp
4790 (concat "\\<\\(" org-deadline-string "\\).*")
4791 org-scheduled-regexp
4792 (concat "\\<" org-scheduled-string)
4793 org-scheduled-time-regexp
4794 (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
4795 org-closed-time-regexp
4796 (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
4797 org-keyword-time-regexp
4798 (concat "\\<\\(" org-scheduled-string
4799 "\\|" org-deadline-string
4800 "\\|" org-closed-string
4801 "\\|" org-clock-string "\\)"
4802 " *[[<]\\([^]>]+\\)[]>]")
4803 org-keyword-time-not-clock-regexp
4804 (concat "\\<\\(" org-scheduled-string
4805 "\\|" org-deadline-string
4806 "\\|" org-closed-string
4807 "\\)"
4808 " *[[<]\\([^]>]+\\)[]>]")
4809 org-maybe-keyword-time-regexp
4810 (concat "\\(\\<\\(" org-scheduled-string
4811 "\\|" org-deadline-string
4812 "\\|" org-closed-string
4813 "\\|" org-clock-string "\\)\\)?"
4814 " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^]\r\n>]*?[]>]\\|<%%([^\r\n>]*>\\)")
4815 org-planning-or-clock-line-re
4816 (concat "\\(?:^[ \t]*\\(" org-scheduled-string
4817 "\\|" org-deadline-string
4818 "\\|" org-closed-string "\\|" org-clock-string
4819 "\\)\\>\\)")
4821 (org-compute-latex-and-specials-regexp)
4822 (org-set-font-lock-defaults)))
4824 (defun org-extract-log-state-settings (x)
4825 "Extract the log state setting from a TODO keyword string.
4826 This will extract info from a string like \"WAIT(w@/!)\"."
4827 (let (kw key log1 log2)
4828 (when (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?\\([!@]\\)?\\(?:/\\([!@]\\)\\)?)\\)?$" x)
4829 (setq kw (match-string 1 x)
4830 key (and (match-end 2) (match-string 2 x))
4831 log1 (and (match-end 3) (match-string 3 x))
4832 log2 (and (match-end 4) (match-string 4 x)))
4833 (and (or log1 log2)
4834 (list kw
4835 (and log1 (if (equal log1 "!") 'time 'note))
4836 (and log2 (if (equal log2 "!") 'time 'note)))))))
4838 (defun org-remove-keyword-keys (list)
4839 "Remove a pair of parenthesis at the end of each string in LIST."
4840 (mapcar (lambda (x)
4841 (if (string-match "(.*)$" x)
4842 (substring x 0 (match-beginning 0))
4844 list))
4846 ;; FIXME: this could be done much better, using second characters etc.
4847 (defun org-assign-fast-keys (alist)
4848 "Assign fast keys to a keyword-key alist.
4849 Respect keys that are already there."
4850 (let (new e k c c1 c2 (char ?a))
4851 (while (setq e (pop alist))
4852 (cond
4853 ((equal e '(:startgroup)) (push e new))
4854 ((equal e '(:endgroup)) (push e new))
4856 (setq k (car e) c2 nil)
4857 (if (cdr e)
4858 (setq c (cdr e))
4859 ;; automatically assign a character.
4860 (setq c1 (string-to-char
4861 (downcase (substring
4862 k (if (= (string-to-char k) ?@) 1 0)))))
4863 (if (or (rassoc c1 new) (rassoc c1 alist))
4864 (while (or (rassoc char new) (rassoc char alist))
4865 (setq char (1+ char)))
4866 (setq c2 c1))
4867 (setq c (or c2 char)))
4868 (push (cons k c) new))))
4869 (nreverse new)))
4871 ;;; Some variables ujsed in various places
4873 (defvar org-window-configuration nil
4874 "Used in various places to store a window configuration.")
4875 (defvar org-finish-function nil
4876 "Function to be called when `C-c C-c' is used.
4877 This is for getting out of special buffers like remember.")
4880 ;; FIXME: Occasionally check by commenting these, to make sure
4881 ;; no other functions uses these, forgetting to let-bind them.
4882 (defvar entry)
4883 (defvar state)
4884 (defvar last-state)
4885 (defvar date)
4886 (defvar description)
4888 ;; Defined somewhere in this file, but used before definition.
4889 (defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized
4890 (defvar org-agenda-buffer-name)
4891 (defvar org-agenda-undo-list)
4892 (defvar org-agenda-pending-undo-list)
4893 (defvar org-agenda-overriding-header)
4894 (defvar orgtbl-mode)
4895 (defvar org-html-entities)
4896 (defvar org-struct-menu)
4897 (defvar org-org-menu)
4898 (defvar org-tbl-menu)
4899 (defvar org-agenda-keymap)
4901 ;;;; Emacs/XEmacs compatibility
4903 ;; Overlay compatibility functions
4904 (defun org-make-overlay (beg end &optional buffer)
4905 (if (featurep 'xemacs)
4906 (make-extent beg end buffer)
4907 (make-overlay beg end buffer)))
4908 (defun org-delete-overlay (ovl)
4909 (if (featurep 'xemacs) (delete-extent ovl) (delete-overlay ovl)))
4910 (defun org-detach-overlay (ovl)
4911 (if (featurep 'xemacs) (detach-extent ovl) (delete-overlay ovl)))
4912 (defun org-move-overlay (ovl beg end &optional buffer)
4913 (if (featurep 'xemacs)
4914 (set-extent-endpoints ovl beg end (or buffer (current-buffer)))
4915 (move-overlay ovl beg end buffer)))
4916 (defun org-overlay-put (ovl prop value)
4917 (if (featurep 'xemacs)
4918 (set-extent-property ovl prop value)
4919 (overlay-put ovl prop value)))
4920 (defun org-overlay-display (ovl text &optional face evap)
4921 "Make overlay OVL display TEXT with face FACE."
4922 (if (featurep 'xemacs)
4923 (let ((gl (make-glyph text)))
4924 (and face (set-glyph-face gl face))
4925 (set-extent-property ovl 'invisible t)
4926 (set-extent-property ovl 'end-glyph gl))
4927 (overlay-put ovl 'display text)
4928 (if face (overlay-put ovl 'face face))
4929 (if evap (overlay-put ovl 'evaporate t))))
4930 (defun org-overlay-before-string (ovl text &optional face evap)
4931 "Make overlay OVL display TEXT with face FACE."
4932 (if (featurep 'xemacs)
4933 (let ((gl (make-glyph text)))
4934 (and face (set-glyph-face gl face))
4935 (set-extent-property ovl 'begin-glyph gl))
4936 (if face (org-add-props text nil 'face face))
4937 (overlay-put ovl 'before-string text)
4938 (if evap (overlay-put ovl 'evaporate t))))
4939 (defun org-overlay-get (ovl prop)
4940 (if (featurep 'xemacs)
4941 (extent-property ovl prop)
4942 (overlay-get ovl prop)))
4943 (defun org-overlays-at (pos)
4944 (if (featurep 'xemacs) (extents-at pos) (overlays-at pos)))
4945 (defun org-overlays-in (&optional start end)
4946 (if (featurep 'xemacs)
4947 (extent-list nil start end)
4948 (overlays-in start end)))
4949 (defun org-overlay-start (o)
4950 (if (featurep 'xemacs) (extent-start-position o) (overlay-start o)))
4951 (defun org-overlay-end (o)
4952 (if (featurep 'xemacs) (extent-end-position o) (overlay-end o)))
4953 (defun org-find-overlays (prop &optional pos delete)
4954 "Find all overlays specifying PROP at POS or point.
4955 If DELETE is non-nil, delete all those overlays."
4956 (let ((overlays (org-overlays-at (or pos (point))))
4957 ov found)
4958 (while (setq ov (pop overlays))
4959 (if (org-overlay-get ov prop)
4960 (if delete (org-delete-overlay ov) (push ov found))))
4961 found))
4963 ;; Region compatibility
4965 (defun org-add-hook (hook function &optional append local)
4966 "Add-hook, compatible with both Emacsen."
4967 (if (and local (featurep 'xemacs))
4968 (add-local-hook hook function append)
4969 (add-hook hook function append local)))
4971 (defvar org-ignore-region nil
4972 "To temporarily disable the active region.")
4974 (defun org-region-active-p ()
4975 "Is `transient-mark-mode' on and the region active?
4976 Works on both Emacs and XEmacs."
4977 (if org-ignore-region
4979 (if (featurep 'xemacs)
4980 (and zmacs-regions (region-active-p))
4981 (if (fboundp 'use-region-p)
4982 (use-region-p)
4983 (and transient-mark-mode mark-active))))) ; Emacs 22 and before
4985 ;; Invisibility compatibility
4987 (defun org-add-to-invisibility-spec (arg)
4988 "Add elements to `buffer-invisibility-spec'.
4989 See documentation for `buffer-invisibility-spec' for the kind of elements
4990 that can be added."
4991 (cond
4992 ((fboundp 'add-to-invisibility-spec)
4993 (add-to-invisibility-spec arg))
4994 ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t))
4995 (setq buffer-invisibility-spec (list arg)))
4997 (setq buffer-invisibility-spec
4998 (cons arg buffer-invisibility-spec)))))
5000 (defun org-remove-from-invisibility-spec (arg)
5001 "Remove elements from `buffer-invisibility-spec'."
5002 (if (fboundp 'remove-from-invisibility-spec)
5003 (remove-from-invisibility-spec arg)
5004 (if (consp buffer-invisibility-spec)
5005 (setq buffer-invisibility-spec
5006 (delete arg buffer-invisibility-spec)))))
5008 (defun org-in-invisibility-spec-p (arg)
5009 "Is ARG a member of `buffer-invisibility-spec'?"
5010 (if (consp buffer-invisibility-spec)
5011 (member arg buffer-invisibility-spec)
5012 nil))
5014 ;;;; Define the Org-mode
5016 (if (and (not (keymapp outline-mode-map)) (featurep 'allout))
5017 (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."))
5020 ;; We use a before-change function to check if a table might need
5021 ;; an update.
5022 (defvar org-table-may-need-update t
5023 "Indicates that a table might need an update.
5024 This variable is set by `org-before-change-function'.
5025 `org-table-align' sets it back to nil.")
5026 (defvar org-mode-map)
5027 (defvar org-mode-hook nil)
5028 (defvar org-inhibit-startup nil) ; Dynamically-scoped param.
5029 (defvar org-agenda-keep-modes nil) ; Dynamically-scoped param.
5030 (defvar org-table-buffer-is-an nil)
5031 (defconst org-outline-regexp "\\*+ ")
5033 ;;;###autoload
5034 (define-derived-mode org-mode outline-mode "Org"
5035 "Outline-based notes management and organizer, alias
5036 \"Carsten's outline-mode for keeping track of everything.\"
5038 Org-mode develops organizational tasks around a NOTES file which
5039 contains information about projects as plain text. Org-mode is
5040 implemented on top of outline-mode, which is ideal to keep the content
5041 of large files well structured. It supports ToDo items, deadlines and
5042 time stamps, which magically appear in the diary listing of the Emacs
5043 calendar. Tables are easily created with a built-in table editor.
5044 Plain text URL-like links connect to websites, emails (VM), Usenet
5045 messages (Gnus), BBDB entries, and any files related to the project.
5046 For printing and sharing of notes, an Org-mode file (or a part of it)
5047 can be exported as a structured ASCII or HTML file.
5049 The following commands are available:
5051 \\{org-mode-map}"
5053 ;; Get rid of Outline menus, they are not needed
5054 ;; Need to do this here because define-derived-mode sets up
5055 ;; the keymap so late. Still, it is a waste to call this each time
5056 ;; we switch another buffer into org-mode.
5057 (if (featurep 'xemacs)
5058 (when (boundp 'outline-mode-menu-heading)
5059 ;; Assume this is Greg's port, it used easymenu
5060 (easy-menu-remove outline-mode-menu-heading)
5061 (easy-menu-remove outline-mode-menu-show)
5062 (easy-menu-remove outline-mode-menu-hide))
5063 (define-key org-mode-map [menu-bar headings] 'undefined)
5064 (define-key org-mode-map [menu-bar hide] 'undefined)
5065 (define-key org-mode-map [menu-bar show] 'undefined))
5067 (org-load-modules-maybe)
5068 (easy-menu-add org-org-menu)
5069 (easy-menu-add org-tbl-menu)
5070 (org-install-agenda-files-menu)
5071 (if org-descriptive-links (org-add-to-invisibility-spec '(org-link)))
5072 (org-add-to-invisibility-spec '(org-cwidth))
5073 (when (featurep 'xemacs)
5074 (org-set-local 'line-move-ignore-invisible t))
5075 (org-set-local 'outline-regexp org-outline-regexp)
5076 (org-set-local 'outline-level 'org-outline-level)
5077 (when (and org-ellipsis
5078 (fboundp 'set-display-table-slot) (boundp 'buffer-display-table)
5079 (fboundp 'make-glyph-code))
5080 (unless org-display-table
5081 (setq org-display-table (make-display-table)))
5082 (set-display-table-slot
5083 org-display-table 4
5084 (vconcat (mapcar
5085 (lambda (c) (make-glyph-code c (and (not (stringp org-ellipsis))
5086 org-ellipsis)))
5087 (if (stringp org-ellipsis) org-ellipsis "..."))))
5088 (setq buffer-display-table org-display-table))
5089 (org-set-regexps-and-options)
5090 ;; Calc embedded
5091 (org-set-local 'calc-embedded-open-mode "# ")
5092 (modify-syntax-entry ?# "<")
5093 (modify-syntax-entry ?@ "w")
5094 (if org-startup-truncated (setq truncate-lines t))
5095 (org-set-local 'font-lock-unfontify-region-function
5096 'org-unfontify-region)
5097 ;; Activate before-change-function
5098 (org-set-local 'org-table-may-need-update t)
5099 (org-add-hook 'before-change-functions 'org-before-change-function nil
5100 'local)
5101 ;; Check for running clock before killing a buffer
5102 (org-add-hook 'kill-buffer-hook 'org-check-running-clock nil 'local)
5103 ;; Paragraphs and auto-filling
5104 (org-set-autofill-regexps)
5105 (setq indent-line-function 'org-indent-line-function)
5106 (org-update-radio-target-regexp)
5108 ;; Comment characters
5109 ; (org-set-local 'comment-start "#") ;; FIXME: this breaks wrapping
5110 (org-set-local 'comment-padding " ")
5112 ;; Align options lines
5113 (org-set-local
5114 'align-mode-rules-list
5115 '((org-in-buffer-settings
5116 (regexp . "^#\\+[A-Z_]+:\\(\\s-*\\)\\S-+")
5117 (modes . '(org-mode)))))
5119 ;; Imenu
5120 (org-set-local 'imenu-create-index-function
5121 'org-imenu-get-tree)
5123 ;; Make isearch reveal context
5124 (if (or (featurep 'xemacs)
5125 (not (boundp 'outline-isearch-open-invisible-function)))
5126 ;; Emacs 21 and XEmacs make use of the hook
5127 (org-add-hook 'isearch-mode-end-hook 'org-isearch-end 'append 'local)
5128 ;; Emacs 22 deals with this through a special variable
5129 (org-set-local 'outline-isearch-open-invisible-function
5130 (lambda (&rest ignore) (org-show-context 'isearch))))
5132 ;; If empty file that did not turn on org-mode automatically, make it to.
5133 (if (and org-insert-mode-line-in-empty-file
5134 (interactive-p)
5135 (= (point-min) (point-max)))
5136 (insert "# -*- mode: org -*-\n\n"))
5138 (unless org-inhibit-startup
5139 (when org-startup-align-all-tables
5140 (let ((bmp (buffer-modified-p)))
5141 (org-table-map-tables 'org-table-align)
5142 (set-buffer-modified-p bmp)))
5143 (org-cycle-hide-drawers 'all)
5144 (cond
5145 ((eq org-startup-folded t)
5146 (org-cycle '(4)))
5147 ((eq org-startup-folded 'content)
5148 (let ((this-command 'org-cycle) (last-command 'org-cycle))
5149 (org-cycle '(4)) (org-cycle '(4)))))))
5151 (put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify)
5153 (defsubst org-call-with-arg (command arg)
5154 "Call COMMAND interactively, but pretend prefix are was ARG."
5155 (let ((current-prefix-arg arg)) (call-interactively command)))
5157 (defsubst org-current-line (&optional pos)
5158 (save-excursion
5159 (and pos (goto-char pos))
5160 ;; works also in narrowed buffer, because we start at 1, not point-min
5161 (+ (if (bolp) 1 0) (count-lines 1 (point)))))
5163 (defun org-current-time ()
5164 "Current time, possibly rounded to `org-time-stamp-rounding-minutes'."
5165 (if (> (car org-time-stamp-rounding-minutes) 1)
5166 (let ((r (car org-time-stamp-rounding-minutes))
5167 (time (decode-time)))
5168 (apply 'encode-time
5169 (append (list 0 (* r (floor (+ .5 (/ (float (nth 1 time)) r)))))
5170 (nthcdr 2 time))))
5171 (current-time)))
5173 (defun org-add-props (string plist &rest props)
5174 "Add text properties to entire string, from beginning to end.
5175 PLIST may be a list of properties, PROPS are individual properties and values
5176 that will be added to PLIST. Returns the string that was modified."
5177 (add-text-properties
5178 0 (length string) (if props (append plist props) plist) string)
5179 string)
5180 (put 'org-add-props 'lisp-indent-function 2)
5183 ;;;; Font-Lock stuff, including the activators
5185 (defvar org-mouse-map (make-sparse-keymap))
5186 (org-defkey org-mouse-map
5187 (if (featurep 'xemacs) [button2] [mouse-2]) 'org-open-at-mouse)
5188 (org-defkey org-mouse-map
5189 (if (featurep 'xemacs) [button3] [mouse-3]) 'org-find-file-at-mouse)
5190 (when org-mouse-1-follows-link
5191 (org-defkey org-mouse-map [follow-link] 'mouse-face))
5192 (when org-tab-follows-link
5193 (org-defkey org-mouse-map [(tab)] 'org-open-at-point)
5194 (org-defkey org-mouse-map "\C-i" 'org-open-at-point))
5195 (when org-return-follows-link
5196 (org-defkey org-mouse-map [(return)] 'org-open-at-point)
5197 (org-defkey org-mouse-map "\C-m" 'org-open-at-point))
5199 (require 'font-lock)
5201 (defconst org-non-link-chars "]\t\n\r<>")
5202 (defvar org-link-types '("http" "https" "ftp" "mailto" "file" "news"
5203 "shell" "elisp"))
5204 (defvar org-link-re-with-space nil
5205 "Matches a link with spaces, optional angular brackets around it.")
5206 (defvar org-link-re-with-space2 nil
5207 "Matches a link with spaces, optional angular brackets around it.")
5208 (defvar org-angle-link-re nil
5209 "Matches link with angular brackets, spaces are allowed.")
5210 (defvar org-plain-link-re nil
5211 "Matches plain link, without spaces.")
5212 (defvar org-bracket-link-regexp nil
5213 "Matches a link in double brackets.")
5214 (defvar org-bracket-link-analytic-regexp nil
5215 "Regular expression used to analyze links.
5216 Here is what the match groups contain after a match:
5217 1: http:
5218 2: http
5219 3: path
5220 4: [desc]
5221 5: desc")
5222 (defvar org-any-link-re nil
5223 "Regular expression matching any link.")
5225 (defun org-make-link-regexps ()
5226 "Update the link regular expressions.
5227 This should be called after the variable `org-link-types' has changed."
5228 (setq org-link-re-with-space
5229 (concat
5230 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
5231 "\\([^" org-non-link-chars " ]"
5232 "[^" org-non-link-chars "]*"
5233 "[^" org-non-link-chars " ]\\)>?")
5234 org-link-re-with-space2
5235 (concat
5236 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
5237 "\\([^" org-non-link-chars " ]"
5238 "[^]\t\n\r]*"
5239 "[^" org-non-link-chars " ]\\)>?")
5240 org-angle-link-re
5241 (concat
5242 "<\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
5243 "\\([^" org-non-link-chars " ]"
5244 "[^" org-non-link-chars "]*"
5245 "\\)>")
5246 org-plain-link-re
5247 (concat
5248 "\\<\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
5249 "\\([^]\t\n\r<>() ]+[^]\t\n\r<>,.;() ]\\)")
5250 org-bracket-link-regexp
5251 "\\[\\[\\([^][]+\\)\\]\\(\\[\\([^][]+\\)\\]\\)?\\]"
5252 org-bracket-link-analytic-regexp
5253 (concat
5254 "\\[\\["
5255 "\\(\\(" (mapconcat 'identity org-link-types "\\|") "\\):\\)?"
5256 "\\([^]]+\\)"
5257 "\\]"
5258 "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
5259 "\\]")
5260 org-any-link-re
5261 (concat "\\(" org-bracket-link-regexp "\\)\\|\\("
5262 org-angle-link-re "\\)\\|\\("
5263 org-plain-link-re "\\)")))
5265 (org-make-link-regexps)
5267 (defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)>"
5268 "Regular expression for fast time stamp matching.")
5269 (defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)[]>]"
5270 "Regular expression for fast time stamp matching.")
5271 (defconst org-ts-regexp0 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) *\\([^]-+0-9>\r\n ]*\\)\\( \\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
5272 "Regular expression matching time strings for analysis.
5273 This one does not require the space after the date, so it can be used
5274 on a string that terminates immediately after the date.")
5275 (defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) +\\([^]-+0-9>\r\n ]*\\)\\( \\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
5276 "Regular expression matching time strings for analysis.")
5277 (defconst org-ts-regexp2 (concat "<" org-ts-regexp1 "[^>\n]\\{0,16\\}>")
5278 "Regular expression matching time stamps, with groups.")
5279 (defconst org-ts-regexp3 (concat "[[<]" org-ts-regexp1 "[^]>\n]\\{0,16\\}[]>]")
5280 "Regular expression matching time stamps (also [..]), with groups.")
5281 (defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp)
5282 "Regular expression matching a time stamp range.")
5283 (defconst org-tr-regexp-both
5284 (concat org-ts-regexp-both "--?-?" org-ts-regexp-both)
5285 "Regular expression matching a time stamp range.")
5286 (defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?"
5287 org-ts-regexp "\\)?")
5288 "Regular expression matching a time stamp or time stamp range.")
5289 (defconst org-tsr-regexp-both (concat org-ts-regexp-both "\\(--?-?"
5290 org-ts-regexp-both "\\)?")
5291 "Regular expression matching a time stamp or time stamp range.
5292 The time stamps may be either active or inactive.")
5294 (defvar org-emph-face nil)
5296 (defun org-do-emphasis-faces (limit)
5297 "Run through the buffer and add overlays to links."
5298 (let (rtn)
5299 (while (and (not rtn) (re-search-forward org-emph-re limit t))
5300 (if (not (= (char-after (match-beginning 3))
5301 (char-after (match-beginning 4))))
5302 (progn
5303 (setq rtn t)
5304 (font-lock-prepend-text-property (match-beginning 2) (match-end 2)
5305 'face
5306 (nth 1 (assoc (match-string 3)
5307 org-emphasis-alist)))
5308 (add-text-properties (match-beginning 2) (match-end 2)
5309 '(font-lock-multiline t))
5310 (when org-hide-emphasis-markers
5311 (add-text-properties (match-end 4) (match-beginning 5)
5312 '(invisible org-link))
5313 (add-text-properties (match-beginning 3) (match-end 3)
5314 '(invisible org-link)))))
5315 (backward-char 1))
5316 rtn))
5318 (defun org-emphasize (&optional char)
5319 "Insert or change an emphasis, i.e. a font like bold or italic.
5320 If there is an active region, change that region to a new emphasis.
5321 If there is no region, just insert the marker characters and position
5322 the cursor between them.
5323 CHAR should be either the marker character, or the first character of the
5324 HTML tag associated with that emphasis. If CHAR is a space, the means
5325 to remove the emphasis of the selected region.
5326 If char is not given (for example in an interactive call) it
5327 will be prompted for."
5328 (interactive)
5329 (let ((eal org-emphasis-alist) e det
5330 (erc org-emphasis-regexp-components)
5331 (prompt "")
5332 (string "") beg end move tag c s)
5333 (if (org-region-active-p)
5334 (setq beg (region-beginning) end (region-end)
5335 string (buffer-substring beg end))
5336 (setq move t))
5338 (while (setq e (pop eal))
5339 (setq tag (car (org-split-string (nth 2 e) "[ <>/]+"))
5340 c (aref tag 0))
5341 (push (cons c (string-to-char (car e))) det)
5342 (setq prompt (concat prompt (format " [%s%c]%s" (car e) c
5343 (substring tag 1)))))
5344 (unless char
5345 (message "%s" (concat "Emphasis marker or tag:" prompt))
5346 (setq char (read-char-exclusive)))
5347 (setq char (or (cdr (assoc char det)) char))
5348 (if (equal char ?\ )
5349 (setq s "" move nil)
5350 (unless (assoc (char-to-string char) org-emphasis-alist)
5351 (error "No such emphasis marker: \"%c\"" char))
5352 (setq s (char-to-string char)))
5353 (while (and (> (length string) 1)
5354 (equal (substring string 0 1) (substring string -1))
5355 (assoc (substring string 0 1) org-emphasis-alist))
5356 (setq string (substring string 1 -1)))
5357 (setq string (concat s string s))
5358 (if beg (delete-region beg end))
5359 (unless (or (bolp)
5360 (string-match (concat "[" (nth 0 erc) "\n]")
5361 (char-to-string (char-before (point)))))
5362 (insert " "))
5363 (unless (string-match (concat "[" (nth 1 erc) "\n]")
5364 (char-to-string (char-after (point))))
5365 (insert " ") (backward-char 1))
5366 (insert string)
5367 (and move (backward-char 1))))
5369 (defconst org-nonsticky-props
5370 '(mouse-face highlight keymap invisible intangible help-echo org-linked-text))
5373 (defun org-activate-plain-links (limit)
5374 "Run through the buffer and add overlays to links."
5375 (catch 'exit
5376 (let (f)
5377 (while (re-search-forward org-plain-link-re limit t)
5378 (setq f (get-text-property (match-beginning 0) 'face))
5379 (if (or (eq f 'org-tag)
5380 (and (listp f) (memq 'org-tag f)))
5382 (add-text-properties (match-beginning 0) (match-end 0)
5383 (list 'mouse-face 'highlight
5384 'rear-nonsticky org-nonsticky-props
5385 'keymap org-mouse-map
5387 (throw 'exit t))))))
5389 (defun org-activate-code (limit)
5390 (if (re-search-forward "^[ \t]*\\(:.*\\)" limit t)
5391 (unless (get-text-property (match-beginning 1) 'face)
5392 (remove-text-properties (match-beginning 0) (match-end 0)
5393 '(display t invisible t intangible t))
5394 t)))
5396 (defun org-activate-angle-links (limit)
5397 "Run through the buffer and add overlays to links."
5398 (if (re-search-forward org-angle-link-re limit t)
5399 (progn
5400 (add-text-properties (match-beginning 0) (match-end 0)
5401 (list 'mouse-face 'highlight
5402 'rear-nonsticky org-nonsticky-props
5403 'keymap org-mouse-map
5405 t)))
5407 (defmacro org-maybe-intangible (props)
5408 "Add '(intangigble t) to PROPS if Emacs version is earlier than Emacs 22.
5409 In emacs 21, invisible text is not avoided by the command loop, so the
5410 intangible property is needed to make sure point skips this text.
5411 In Emacs 22, this is not necessary. The intangible text property has
5412 led to problems with flyspell. These problems are fixed in flyspell.el,
5413 but we still avoid setting the property in Emacs 22 and later.
5414 We use a macro so that the test can happen at compilation time."
5415 (if (< emacs-major-version 22)
5416 `(append '(intangible t) ,props)
5417 props))
5419 (defun org-activate-bracket-links (limit)
5420 "Run through the buffer and add overlays to bracketed links."
5421 (if (re-search-forward org-bracket-link-regexp limit t)
5422 (let* ((help (concat "LINK: "
5423 (org-match-string-no-properties 1)))
5424 ;; FIXME: above we should remove the escapes.
5425 ;; but that requires another match, protecting match data,
5426 ;; a lot of overhead for font-lock.
5427 (ip (org-maybe-intangible
5428 (list 'invisible 'org-link 'rear-nonsticky org-nonsticky-props
5429 'keymap org-mouse-map 'mouse-face 'highlight
5430 'font-lock-multiline t 'help-echo help)))
5431 (vp (list 'rear-nonsticky org-nonsticky-props
5432 'keymap org-mouse-map 'mouse-face 'highlight
5433 ' font-lock-multiline t 'help-echo help)))
5434 ;; We need to remove the invisible property here. Table narrowing
5435 ;; may have made some of this invisible.
5436 (remove-text-properties (match-beginning 0) (match-end 0)
5437 '(invisible nil))
5438 (if (match-end 3)
5439 (progn
5440 (add-text-properties (match-beginning 0) (match-beginning 3) ip)
5441 (add-text-properties (match-beginning 3) (match-end 3) vp)
5442 (add-text-properties (match-end 3) (match-end 0) ip))
5443 (add-text-properties (match-beginning 0) (match-beginning 1) ip)
5444 (add-text-properties (match-beginning 1) (match-end 1) vp)
5445 (add-text-properties (match-end 1) (match-end 0) ip))
5446 t)))
5448 (defun org-activate-dates (limit)
5449 "Run through the buffer and add overlays to dates."
5450 (if (re-search-forward org-tsr-regexp-both limit t)
5451 (progn
5452 (add-text-properties (match-beginning 0) (match-end 0)
5453 (list 'mouse-face 'highlight
5454 'rear-nonsticky org-nonsticky-props
5455 'keymap org-mouse-map))
5456 (when org-display-custom-times
5457 (if (match-end 3)
5458 (org-display-custom-time (match-beginning 3) (match-end 3)))
5459 (org-display-custom-time (match-beginning 1) (match-end 1)))
5460 t)))
5462 (defvar org-target-link-regexp nil
5463 "Regular expression matching radio targets in plain text.")
5464 (defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>"
5465 "Regular expression matching a link target.")
5466 (defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>"
5467 "Regular expression matching a radio target.")
5468 (defvar org-any-target-regexp "<<<?\\([^<>\n\r]+\\)>>>?" ; FIXME, not exact, would match <<<aaa>> as a radio target.
5469 "Regular expression matching any target.")
5471 (defun org-activate-target-links (limit)
5472 "Run through the buffer and add overlays to target matches."
5473 (when org-target-link-regexp
5474 (let ((case-fold-search t))
5475 (if (re-search-forward org-target-link-regexp limit t)
5476 (progn
5477 (add-text-properties (match-beginning 0) (match-end 0)
5478 (list 'mouse-face 'highlight
5479 'rear-nonsticky org-nonsticky-props
5480 'keymap org-mouse-map
5481 'help-echo "Radio target link"
5482 'org-linked-text t))
5483 t)))))
5485 (defun org-update-radio-target-regexp ()
5486 "Find all radio targets in this file and update the regular expression."
5487 (interactive)
5488 (when (memq 'radio org-activate-links)
5489 (setq org-target-link-regexp
5490 (org-make-target-link-regexp (org-all-targets 'radio)))
5491 (org-restart-font-lock)))
5493 (defun org-hide-wide-columns (limit)
5494 (let (s e)
5495 (setq s (text-property-any (point) (or limit (point-max))
5496 'org-cwidth t))
5497 (when s
5498 (setq e (next-single-property-change s 'org-cwidth))
5499 (add-text-properties s e (org-maybe-intangible '(invisible org-cwidth)))
5500 (goto-char e)
5501 t)))
5503 (defvar org-latex-and-specials-regexp nil
5504 "Regular expression for highlighting export special stuff.")
5505 (defvar org-match-substring-regexp)
5506 (defvar org-match-substring-with-braces-regexp)
5507 (defvar org-export-html-special-string-regexps)
5509 (defun org-compute-latex-and-specials-regexp ()
5510 "Compute regular expression for stuff treated specially by exporters."
5511 (if (not org-highlight-latex-fragments-and-specials)
5512 (org-set-local 'org-latex-and-specials-regexp nil)
5513 (let*
5514 ((matchers (plist-get org-format-latex-options :matchers))
5515 (latexs (delq nil (mapcar (lambda (x) (if (member (car x) matchers) x))
5516 org-latex-regexps)))
5517 (options (org-combine-plists (org-default-export-plist)
5518 (org-infile-export-plist)))
5519 (org-export-with-sub-superscripts (plist-get options :sub-superscript))
5520 (org-export-with-LaTeX-fragments (plist-get options :LaTeX-fragments))
5521 (org-export-with-TeX-macros (plist-get options :TeX-macros))
5522 (org-export-html-expand (plist-get options :expand-quoted-html))
5523 (org-export-with-special-strings (plist-get options :special-strings))
5524 (re-sub
5525 (cond
5526 ((equal org-export-with-sub-superscripts '{})
5527 (list org-match-substring-with-braces-regexp))
5528 (org-export-with-sub-superscripts
5529 (list org-match-substring-regexp))
5530 (t nil)))
5531 (re-latex
5532 (if org-export-with-LaTeX-fragments
5533 (mapcar (lambda (x) (nth 1 x)) latexs)))
5534 (re-macros
5535 (if org-export-with-TeX-macros
5536 (list (concat "\\\\"
5537 (regexp-opt
5538 (append (mapcar 'car org-html-entities)
5539 (if (boundp 'org-latex-entities)
5540 org-latex-entities nil))
5541 'words))) ; FIXME
5543 ;; (list "\\\\\\(?:[a-zA-Z]+\\)")))
5544 (re-special (if org-export-with-special-strings
5545 (mapcar (lambda (x) (car x))
5546 org-export-html-special-string-regexps)))
5547 (re-rest
5548 (delq nil
5549 (list
5550 (if org-export-html-expand "@<[^>\n]+>")
5551 ))))
5552 (org-set-local
5553 'org-latex-and-specials-regexp
5554 (mapconcat 'identity (append re-latex re-sub re-macros re-special
5555 re-rest) "\\|")))))
5557 (defface org-latex-and-export-specials
5558 (let ((font (cond ((assq :inherit custom-face-attributes)
5559 '(:inherit underline))
5560 (t '(:underline t)))))
5561 `((((class grayscale) (background light))
5562 (:foreground "DimGray" ,@font))
5563 (((class grayscale) (background dark))
5564 (:foreground "LightGray" ,@font))
5565 (((class color) (background light))
5566 (:foreground "SaddleBrown"))
5567 (((class color) (background dark))
5568 (:foreground "burlywood"))
5569 (t (,@font))))
5570 "Face used to highlight math latex and other special exporter stuff."
5571 :group 'org-faces)
5573 (defun org-do-latex-and-special-faces (limit)
5574 "Run through the buffer and add overlays to links."
5575 (when org-latex-and-specials-regexp
5576 (let (rtn d)
5577 (while (and (not rtn) (re-search-forward org-latex-and-specials-regexp
5578 limit t))
5579 (if (not (memq (car-safe (get-text-property (1+ (match-beginning 0))
5580 'face))
5581 '(org-code org-verbatim underline)))
5582 (progn
5583 (setq rtn t
5584 d (cond ((member (char-after (1+ (match-beginning 0)))
5585 '(?_ ?^)) 1)
5586 (t 0)))
5587 (font-lock-prepend-text-property
5588 (+ d (match-beginning 0)) (match-end 0)
5589 'face 'org-latex-and-export-specials)
5590 (add-text-properties (+ d (match-beginning 0)) (match-end 0)
5591 '(font-lock-multiline t)))))
5592 rtn)))
5594 (defun org-restart-font-lock ()
5595 "Restart font-lock-mode, to force refontification."
5596 (when (and (boundp 'font-lock-mode) font-lock-mode)
5597 (font-lock-mode -1)
5598 (font-lock-mode 1)))
5600 (defun org-all-targets (&optional radio)
5601 "Return a list of all targets in this file.
5602 With optional argument RADIO, only find radio targets."
5603 (let ((re (if radio org-radio-target-regexp org-target-regexp))
5604 rtn)
5605 (save-excursion
5606 (goto-char (point-min))
5607 (while (re-search-forward re nil t)
5608 (add-to-list 'rtn (downcase (org-match-string-no-properties 1))))
5609 rtn)))
5611 (defun org-make-target-link-regexp (targets)
5612 "Make regular expression matching all strings in TARGETS.
5613 The regular expression finds the targets also if there is a line break
5614 between words."
5615 (and targets
5616 (concat
5617 "\\<\\("
5618 (mapconcat
5619 (lambda (x)
5620 (while (string-match " +" x)
5621 (setq x (replace-match "\\s-+" t t x)))
5623 targets
5624 "\\|")
5625 "\\)\\>")))
5627 (defun org-activate-tags (limit)
5628 (if (re-search-forward (org-re "^\\*+.*[ \t]\\(:[[:alnum:]_@:]+:\\)[ \r\n]") limit t)
5629 (progn
5630 (add-text-properties (match-beginning 1) (match-end 1)
5631 (list 'mouse-face 'highlight
5632 'rear-nonsticky org-nonsticky-props
5633 'keymap org-mouse-map))
5634 t)))
5636 (defun org-outline-level ()
5637 (save-excursion
5638 (looking-at outline-regexp)
5639 (if (match-beginning 1)
5640 (+ (org-get-string-indentation (match-string 1)) 1000)
5641 (1- (- (match-end 0) (match-beginning 0))))))
5643 (defvar org-font-lock-keywords nil)
5645 (defconst org-property-re (org-re "^[ \t]*\\(:\\([[:alnum:]_]+\\):\\)[ \t]*\\(\\S-.*\\)")
5646 "Regular expression matching a property line.")
5648 (defun org-set-font-lock-defaults ()
5649 (let* ((em org-fontify-emphasized-text)
5650 (lk org-activate-links)
5651 (org-font-lock-extra-keywords
5652 (list
5653 ;; Headlines
5654 '("^\\(\\**\\)\\(\\* \\)\\(.*\\)" (1 (org-get-level-face 1))
5655 (2 (org-get-level-face 2)) (3 (org-get-level-face 3)))
5656 ;; Table lines
5657 '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)"
5658 (1 'org-table t))
5659 ;; Table internals
5660 '("^[ \t]*|\\(?:.*?|\\)? *\\(:?=[^|\n]*\\)" (1 'org-formula t))
5661 '("^[ \t]*| *\\([#*]\\) *|" (1 'org-formula t))
5662 '("^[ \t]*|\\( *\\([$!_^/]\\) *|.*\\)|" (1 'org-formula t))
5663 ;; Drawers
5664 (list org-drawer-regexp '(0 'org-special-keyword t))
5665 (list "^[ \t]*:END:" '(0 'org-special-keyword t))
5666 ;; Properties
5667 (list org-property-re
5668 '(1 'org-special-keyword t)
5669 '(3 'org-property-value t))
5670 (if org-format-transports-properties-p
5671 '("| *\\(<[0-9]+>\\) *" (1 'org-formula t)))
5672 ;; Links
5673 (if (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
5674 (if (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
5675 (if (memq 'plain lk) '(org-activate-plain-links (0 'org-link t)))
5676 (if (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
5677 (if (memq 'radio lk) '(org-activate-target-links (0 'org-link t)))
5678 (if (memq 'date lk) '(org-activate-dates (0 'org-date t)))
5679 '("^&?%%(.*\\|<%%([^>\n]*?>" (0 'org-sexp-date t))
5680 '(org-hide-wide-columns (0 nil append))
5681 ;; TODO lines
5682 (list (concat "^\\*+[ \t]+" org-todo-regexp)
5683 '(1 (org-get-todo-face 1) t))
5684 ;; DONE
5685 (if org-fontify-done-headline
5686 (list (concat "^[*]+ +\\<\\("
5687 (mapconcat 'regexp-quote org-done-keywords "\\|")
5688 "\\)\\(.*\\)")
5689 '(2 'org-headline-done t))
5690 nil)
5691 ;; Priorities
5692 (list (concat "\\[#[A-Z0-9]\\]") '(0 'org-special-keyword t))
5693 ;; Special keywords
5694 (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t))
5695 (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword t))
5696 (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t))
5697 (list (concat "\\<" org-clock-string) '(0 'org-special-keyword t))
5698 ;; Emphasis
5699 (if em
5700 (if (featurep 'xemacs)
5701 '(org-do-emphasis-faces (0 nil append))
5702 '(org-do-emphasis-faces)))
5703 ;; Checkboxes
5704 '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[- X]\\]\\)"
5705 2 'bold prepend)
5706 (if org-provide-checkbox-statistics
5707 '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
5708 (0 (org-get-checkbox-statistics-face) t)))
5709 (list (concat "^\\*+ \\(.*:" org-archive-tag ":.*\\)")
5710 '(1 'org-archived prepend))
5711 ;; Specials
5712 '(org-do-latex-and-special-faces)
5713 ;; Code
5714 '(org-activate-code (1 'org-code t))
5715 ;; COMMENT
5716 (list (concat "^\\*+[ \t]+\\<\\(" org-comment-string
5717 "\\|" org-quote-string "\\)\\>")
5718 '(1 'org-special-keyword t))
5719 '("^#.*" (0 'font-lock-comment-face t))
5721 (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords))
5722 ;; Now set the full font-lock-keywords
5723 (org-set-local 'org-font-lock-keywords org-font-lock-extra-keywords)
5724 (org-set-local 'font-lock-defaults
5725 '(org-font-lock-keywords t nil nil backward-paragraph))
5726 (kill-local-variable 'font-lock-keywords) nil))
5728 (defvar org-m nil)
5729 (defvar org-l nil)
5730 (defvar org-f nil)
5731 (defun org-get-level-face (n)
5732 "Get the right face for match N in font-lock matching of healdines."
5733 (setq org-l (- (match-end 2) (match-beginning 1) 1))
5734 (if org-odd-levels-only (setq org-l (1+ (/ org-l 2))))
5735 (setq org-f (nth (% (1- org-l) org-n-level-faces) org-level-faces))
5736 (cond
5737 ((eq n 1) (if org-hide-leading-stars 'org-hide org-f))
5738 ((eq n 2) org-f)
5739 (t (if org-level-color-stars-only nil org-f))))
5741 (defun org-get-todo-face (kwd)
5742 "Get the right face for a TODO keyword KWD.
5743 If KWD is a number, get the corresponding match group."
5744 (if (numberp kwd) (setq kwd (match-string kwd)))
5745 (or (cdr (assoc kwd org-todo-keyword-faces))
5746 (and (member kwd org-done-keywords) 'org-done)
5747 'org-todo))
5749 (defun org-unfontify-region (beg end &optional maybe_loudly)
5750 "Remove fontification and activation overlays from links."
5751 (font-lock-default-unfontify-region beg end)
5752 (let* ((buffer-undo-list t)
5753 (inhibit-read-only t) (inhibit-point-motion-hooks t)
5754 (inhibit-modification-hooks t)
5755 deactivate-mark buffer-file-name buffer-file-truename)
5756 (remove-text-properties beg end
5757 '(mouse-face t keymap t org-linked-text t
5758 invisible t intangible t))))
5760 ;;;; Visibility cycling, including org-goto and indirect buffer
5762 ;;; Cycling
5764 (defvar org-cycle-global-status nil)
5765 (make-variable-buffer-local 'org-cycle-global-status)
5766 (defvar org-cycle-subtree-status nil)
5767 (make-variable-buffer-local 'org-cycle-subtree-status)
5769 ;;;###autoload
5770 (defun org-cycle (&optional arg)
5771 "Visibility cycling for Org-mode.
5773 - When this function is called with a prefix argument, rotate the entire
5774 buffer through 3 states (global cycling)
5775 1. OVERVIEW: Show only top-level headlines.
5776 2. CONTENTS: Show all headlines of all levels, but no body text.
5777 3. SHOW ALL: Show everything.
5779 - When point is at the beginning of a headline, rotate the subtree started
5780 by this line through 3 different states (local cycling)
5781 1. FOLDED: Only the main headline is shown.
5782 2. CHILDREN: The main headline and the direct children are shown.
5783 From this state, you can move to one of the children
5784 and zoom in further.
5785 3. SUBTREE: Show the entire subtree, including body text.
5787 - When there is a numeric prefix, go up to a heading with level ARG, do
5788 a `show-subtree' and return to the previous cursor position. If ARG
5789 is negative, go up that many levels.
5791 - When point is not at the beginning of a headline, execute
5792 `indent-relative', like TAB normally does. See the option
5793 `org-cycle-emulate-tab' for details.
5795 - Special case: if point is at the beginning of the buffer and there is
5796 no headline in line 1, this function will act as if called with prefix arg.
5797 But only if also the variable `org-cycle-global-at-bob' is t."
5798 (interactive "P")
5799 (org-load-modules-maybe)
5800 (let* ((outline-regexp
5801 (if (and (org-mode-p) org-cycle-include-plain-lists)
5802 "\\(?:\\*+ \\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) \\)"
5803 outline-regexp))
5804 (bob-special (and org-cycle-global-at-bob (bobp)
5805 (not (looking-at outline-regexp))))
5806 (org-cycle-hook
5807 (if bob-special
5808 (delq 'org-optimize-window-after-visibility-change
5809 (copy-sequence org-cycle-hook))
5810 org-cycle-hook))
5811 (pos (point)))
5813 (if (or bob-special (equal arg '(4)))
5814 ;; special case: use global cycling
5815 (setq arg t))
5817 (cond
5819 ((org-at-table-p 'any)
5820 ;; Enter the table or move to the next field in the table
5821 (or (org-table-recognize-table.el)
5822 (progn
5823 (if arg (org-table-edit-field t)
5824 (org-table-justify-field-maybe)
5825 (call-interactively 'org-table-next-field)))))
5827 ((eq arg t) ;; Global cycling
5829 (cond
5830 ((and (eq last-command this-command)
5831 (eq org-cycle-global-status 'overview))
5832 ;; We just created the overview - now do table of contents
5833 ;; This can be slow in very large buffers, so indicate action
5834 (message "CONTENTS...")
5835 (org-content)
5836 (message "CONTENTS...done")
5837 (setq org-cycle-global-status 'contents)
5838 (run-hook-with-args 'org-cycle-hook 'contents))
5840 ((and (eq last-command this-command)
5841 (eq org-cycle-global-status 'contents))
5842 ;; We just showed the table of contents - now show everything
5843 (show-all)
5844 (message "SHOW ALL")
5845 (setq org-cycle-global-status 'all)
5846 (run-hook-with-args 'org-cycle-hook 'all))
5849 ;; Default action: go to overview
5850 (org-overview)
5851 (message "OVERVIEW")
5852 (setq org-cycle-global-status 'overview)
5853 (run-hook-with-args 'org-cycle-hook 'overview))))
5855 ((and org-drawers org-drawer-regexp
5856 (save-excursion
5857 (beginning-of-line 1)
5858 (looking-at org-drawer-regexp)))
5859 ;; Toggle block visibility
5860 (org-flag-drawer
5861 (not (get-char-property (match-end 0) 'invisible))))
5863 ((integerp arg)
5864 ;; Show-subtree, ARG levels up from here.
5865 (save-excursion
5866 (org-back-to-heading)
5867 (outline-up-heading (if (< arg 0) (- arg)
5868 (- (funcall outline-level) arg)))
5869 (org-show-subtree)))
5871 ((and (save-excursion (beginning-of-line 1) (looking-at outline-regexp))
5872 (or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
5873 ;; At a heading: rotate between three different views
5874 (org-back-to-heading)
5875 (let ((goal-column 0) eoh eol eos)
5876 ;; First, some boundaries
5877 (save-excursion
5878 (org-back-to-heading)
5879 (save-excursion
5880 (beginning-of-line 2)
5881 (while (and (not (eobp)) ;; this is like `next-line'
5882 (get-char-property (1- (point)) 'invisible))
5883 (beginning-of-line 2)) (setq eol (point)))
5884 (outline-end-of-heading) (setq eoh (point))
5885 (org-end-of-subtree t)
5886 (unless (eobp)
5887 (skip-chars-forward " \t\n")
5888 (beginning-of-line 1) ; in case this is an item
5890 (setq eos (1- (point))))
5891 ;; Find out what to do next and set `this-command'
5892 (cond
5893 ((= eos eoh)
5894 ;; Nothing is hidden behind this heading
5895 (message "EMPTY ENTRY")
5896 (setq org-cycle-subtree-status nil)
5897 (save-excursion
5898 (goto-char eos)
5899 (outline-next-heading)
5900 (if (org-invisible-p) (org-flag-heading nil))))
5901 ((or (>= eol eos)
5902 (not (string-match "\\S-" (buffer-substring eol eos))))
5903 ;; Entire subtree is hidden in one line: open it
5904 (org-show-entry)
5905 (show-children)
5906 (message "CHILDREN")
5907 (save-excursion
5908 (goto-char eos)
5909 (outline-next-heading)
5910 (if (org-invisible-p) (org-flag-heading nil)))
5911 (setq org-cycle-subtree-status 'children)
5912 (run-hook-with-args 'org-cycle-hook 'children))
5913 ((and (eq last-command this-command)
5914 (eq org-cycle-subtree-status 'children))
5915 ;; We just showed the children, now show everything.
5916 (org-show-subtree)
5917 (message "SUBTREE")
5918 (setq org-cycle-subtree-status 'subtree)
5919 (run-hook-with-args 'org-cycle-hook 'subtree))
5921 ;; Default action: hide the subtree.
5922 (hide-subtree)
5923 (message "FOLDED")
5924 (setq org-cycle-subtree-status 'folded)
5925 (run-hook-with-args 'org-cycle-hook 'folded)))))
5927 ;; TAB emulation
5928 (buffer-read-only (org-back-to-heading))
5930 ((org-try-cdlatex-tab))
5932 ((and (eq org-cycle-emulate-tab 'exc-hl-bol)
5933 (or (not (bolp))
5934 (not (looking-at outline-regexp))))
5935 (call-interactively (global-key-binding "\t")))
5937 ((if (and (memq org-cycle-emulate-tab '(white whitestart))
5938 (save-excursion (beginning-of-line 1) (looking-at "[ \t]*"))
5939 (or (and (eq org-cycle-emulate-tab 'white)
5940 (= (match-end 0) (point-at-eol)))
5941 (and (eq org-cycle-emulate-tab 'whitestart)
5942 (>= (match-end 0) pos))))
5944 (eq org-cycle-emulate-tab t))
5945 ; (if (and (looking-at "[ \n\r\t]")
5946 ; (string-match "^[ \t]*$" (buffer-substring
5947 ; (point-at-bol) (point))))
5948 ; (progn
5949 ; (beginning-of-line 1)
5950 ; (and (looking-at "[ \t]+") (replace-match ""))))
5951 (call-interactively (global-key-binding "\t")))
5953 (t (save-excursion
5954 (org-back-to-heading)
5955 (org-cycle))))))
5957 ;;;###autoload
5958 (defun org-global-cycle (&optional arg)
5959 "Cycle the global visibility. For details see `org-cycle'."
5960 (interactive "P")
5961 (let ((org-cycle-include-plain-lists
5962 (if (org-mode-p) org-cycle-include-plain-lists nil)))
5963 (if (integerp arg)
5964 (progn
5965 (show-all)
5966 (hide-sublevels arg)
5967 (setq org-cycle-global-status 'contents))
5968 (org-cycle '(4)))))
5970 (defun org-overview ()
5971 "Switch to overview mode, shoing only top-level headlines.
5972 Really, this shows all headlines with level equal or greater than the level
5973 of the first headline in the buffer. This is important, because if the
5974 first headline is not level one, then (hide-sublevels 1) gives confusing
5975 results."
5976 (interactive)
5977 (let ((level (save-excursion
5978 (goto-char (point-min))
5979 (if (re-search-forward (concat "^" outline-regexp) nil t)
5980 (progn
5981 (goto-char (match-beginning 0))
5982 (funcall outline-level))))))
5983 (and level (hide-sublevels level))))
5985 (defun org-content (&optional arg)
5986 "Show all headlines in the buffer, like a table of contents.
5987 With numerical argument N, show content up to level N."
5988 (interactive "P")
5989 (save-excursion
5990 ;; Visit all headings and show their offspring
5991 (and (integerp arg) (org-overview))
5992 (goto-char (point-max))
5993 (catch 'exit
5994 (while (and (progn (condition-case nil
5995 (outline-previous-visible-heading 1)
5996 (error (goto-char (point-min))))
5998 (looking-at outline-regexp))
5999 (if (integerp arg)
6000 (show-children (1- arg))
6001 (show-branches))
6002 (if (bobp) (throw 'exit nil))))))
6005 (defun org-optimize-window-after-visibility-change (state)
6006 "Adjust the window after a change in outline visibility.
6007 This function is the default value of the hook `org-cycle-hook'."
6008 (when (get-buffer-window (current-buffer))
6009 (cond
6010 ; ((eq state 'overview) (org-first-headline-recenter 1))
6011 ; ((eq state 'overview) (org-beginning-of-line))
6012 ((eq state 'content) nil)
6013 ((eq state 'all) nil)
6014 ((eq state 'folded) nil)
6015 ((eq state 'children) (or (org-subtree-end-visible-p) (recenter 1)))
6016 ((eq state 'subtree) (or (org-subtree-end-visible-p) (recenter 1))))))
6018 (defun org-compact-display-after-subtree-move ()
6019 (let (beg end)
6020 (save-excursion
6021 (if (org-up-heading-safe)
6022 (progn
6023 (hide-subtree)
6024 (show-entry)
6025 (show-children)
6026 (org-cycle-show-empty-lines 'children)
6027 (org-cycle-hide-drawers 'children))
6028 (org-overview)))))
6030 (defun org-cycle-show-empty-lines (state)
6031 "Show empty lines above all visible headlines.
6032 The region to be covered depends on STATE when called through
6033 `org-cycle-hook'. Lisp program can use t for STATE to get the
6034 entire buffer covered. Note that an empty line is only shown if there
6035 are at least `org-cycle-separator-lines' empty lines before the headeline."
6036 (when (> org-cycle-separator-lines 0)
6037 (save-excursion
6038 (let* ((n org-cycle-separator-lines)
6039 (re (cond
6040 ((= n 1) "\\(\n[ \t]*\n\\*+\\) ")
6041 ((= n 2) "^[ \t]*\\(\n[ \t]*\n\\*+\\) ")
6042 (t (let ((ns (number-to-string (- n 2))))
6043 (concat "^\\(?:[ \t]*\n\\)\\{" ns "," ns "\\}"
6044 "[ \t]*\\(\n[ \t]*\n\\*+\\) ")))))
6045 beg end)
6046 (cond
6047 ((memq state '(overview contents t))
6048 (setq beg (point-min) end (point-max)))
6049 ((memq state '(children folded))
6050 (setq beg (point) end (progn (org-end-of-subtree t t)
6051 (beginning-of-line 2)
6052 (point)))))
6053 (when beg
6054 (goto-char beg)
6055 (while (re-search-forward re end t)
6056 (if (not (get-char-property (match-end 1) 'invisible))
6057 (outline-flag-region
6058 (match-beginning 1) (match-end 1) nil)))))))
6059 ;; Never hide empty lines at the end of the file.
6060 (save-excursion
6061 (goto-char (point-max))
6062 (outline-previous-heading)
6063 (outline-end-of-heading)
6064 (if (and (looking-at "[ \t\n]+")
6065 (= (match-end 0) (point-max)))
6066 (outline-flag-region (point) (match-end 0) nil))))
6068 (defun org-subtree-end-visible-p ()
6069 "Is the end of the current subtree visible?"
6070 (pos-visible-in-window-p
6071 (save-excursion (org-end-of-subtree t) (point))))
6073 (defun org-first-headline-recenter (&optional N)
6074 "Move cursor to the first headline and recenter the headline.
6075 Optional argument N means, put the headline into the Nth line of the window."
6076 (goto-char (point-min))
6077 (when (re-search-forward (concat "^\\(" outline-regexp "\\)") nil t)
6078 (beginning-of-line)
6079 (recenter (prefix-numeric-value N))))
6081 ;;; Org-goto
6083 (defvar org-goto-window-configuration nil)
6084 (defvar org-goto-marker nil)
6085 (defvar org-goto-map
6086 (let ((map (make-sparse-keymap)))
6087 (let ((cmds '(isearch-forward isearch-backward kill-ring-save set-mark-command mouse-drag-region universal-argument org-occur)) cmd)
6088 (while (setq cmd (pop cmds))
6089 (substitute-key-definition cmd cmd map global-map)))
6090 (suppress-keymap map)
6091 (org-defkey map "\C-m" 'org-goto-ret)
6092 (org-defkey map [(return)] 'org-goto-ret)
6093 (org-defkey map [(left)] 'org-goto-left)
6094 (org-defkey map [(right)] 'org-goto-right)
6095 (org-defkey map [(control ?g)] 'org-goto-quit)
6096 (org-defkey map "\C-i" 'org-cycle)
6097 (org-defkey map [(tab)] 'org-cycle)
6098 (org-defkey map [(down)] 'outline-next-visible-heading)
6099 (org-defkey map [(up)] 'outline-previous-visible-heading)
6100 (if org-goto-auto-isearch
6101 (if (fboundp 'define-key-after)
6102 (define-key-after map [t] 'org-goto-local-auto-isearch)
6103 nil)
6104 (org-defkey map "q" 'org-goto-quit)
6105 (org-defkey map "n" 'outline-next-visible-heading)
6106 (org-defkey map "p" 'outline-previous-visible-heading)
6107 (org-defkey map "f" 'outline-forward-same-level)
6108 (org-defkey map "b" 'outline-backward-same-level)
6109 (org-defkey map "u" 'outline-up-heading))
6110 (org-defkey map "/" 'org-occur)
6111 (org-defkey map "\C-c\C-n" 'outline-next-visible-heading)
6112 (org-defkey map "\C-c\C-p" 'outline-previous-visible-heading)
6113 (org-defkey map "\C-c\C-f" 'outline-forward-same-level)
6114 (org-defkey map "\C-c\C-b" 'outline-backward-same-level)
6115 (org-defkey map "\C-c\C-u" 'outline-up-heading)
6116 map))
6118 (defconst org-goto-help
6119 "Browse buffer copy, to find location or copy text. Just type for auto-isearch.
6120 RET=jump to location [Q]uit and return to previous location
6121 \[Up]/[Down]=next/prev headline TAB=cycle visibility [/] org-occur")
6123 (defvar org-goto-start-pos) ; dynamically scoped parameter
6125 (defun org-goto (&optional alternative-interface)
6126 "Look up a different location in the current file, keeping current visibility.
6128 When you want look-up or go to a different location in a document, the
6129 fastest way is often to fold the entire buffer and then dive into the tree.
6130 This method has the disadvantage, that the previous location will be folded,
6131 which may not be what you want.
6133 This command works around this by showing a copy of the current buffer
6134 in an indirect buffer, in overview mode. You can dive into the tree in
6135 that copy, use org-occur and incremental search to find a location.
6136 When pressing RET or `Q', the command returns to the original buffer in
6137 which the visibility is still unchanged. After RET is will also jump to
6138 the location selected in the indirect buffer and expose the
6139 the headline hierarchy above."
6140 (interactive "P")
6141 (let* ((org-refile-targets '((nil . (:maxlevel . 10))))
6142 (org-refile-use-outline-path t)
6143 (interface
6144 (if (not alternative-interface)
6145 org-goto-interface
6146 (if (eq org-goto-interface 'outline)
6147 'outline-path-completion
6148 'outline)))
6149 (org-goto-start-pos (point))
6150 (selected-point
6151 (if (eq interface 'outline)
6152 (car (org-get-location (current-buffer) org-goto-help))
6153 (nth 3 (org-refile-get-location "Goto: ")))))
6154 (if selected-point
6155 (progn
6156 (org-mark-ring-push org-goto-start-pos)
6157 (goto-char selected-point)
6158 (if (or (org-invisible-p) (org-invisible-p2))
6159 (org-show-context 'org-goto)))
6160 (message "Quit"))))
6162 (defvar org-goto-selected-point nil) ; dynamically scoped parameter
6163 (defvar org-goto-exit-command nil) ; dynamically scoped parameter
6164 (defvar org-goto-local-auto-isearch-map) ; defined below
6166 (defun org-get-location (buf help)
6167 "Let the user select a location in the Org-mode buffer BUF.
6168 This function uses a recursive edit. It returns the selected position
6169 or nil."
6170 (let ((isearch-mode-map org-goto-local-auto-isearch-map)
6171 (isearch-hide-immediately nil)
6172 (isearch-search-fun-function
6173 (lambda () 'org-goto-local-search-forward-headings))
6174 (org-goto-selected-point org-goto-exit-command))
6175 (save-excursion
6176 (save-window-excursion
6177 (delete-other-windows)
6178 (and (get-buffer "*org-goto*") (kill-buffer "*org-goto*"))
6179 (switch-to-buffer
6180 (condition-case nil
6181 (make-indirect-buffer (current-buffer) "*org-goto*")
6182 (error (make-indirect-buffer (current-buffer) "*org-goto*"))))
6183 (with-output-to-temp-buffer "*Help*"
6184 (princ help))
6185 (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*"))
6186 (setq buffer-read-only nil)
6187 (let ((org-startup-truncated t)
6188 (org-startup-folded nil)
6189 (org-startup-align-all-tables nil))
6190 (org-mode)
6191 (org-overview))
6192 (setq buffer-read-only t)
6193 (if (and (boundp 'org-goto-start-pos)
6194 (integer-or-marker-p org-goto-start-pos))
6195 (let ((org-show-hierarchy-above t)
6196 (org-show-siblings t)
6197 (org-show-following-heading t))
6198 (goto-char org-goto-start-pos)
6199 (and (org-invisible-p) (org-show-context)))
6200 (goto-char (point-min)))
6201 (org-beginning-of-line)
6202 (message "Select location and press RET")
6203 (use-local-map org-goto-map)
6204 (recursive-edit)
6206 (kill-buffer "*org-goto*")
6207 (cons org-goto-selected-point org-goto-exit-command)))
6209 (defvar org-goto-local-auto-isearch-map (make-sparse-keymap))
6210 (set-keymap-parent org-goto-local-auto-isearch-map isearch-mode-map)
6211 (define-key org-goto-local-auto-isearch-map "\C-i" 'isearch-other-control-char)
6212 (define-key org-goto-local-auto-isearch-map "\C-m" 'isearch-other-control-char)
6214 (defun org-goto-local-search-forward-headings (string bound noerror)
6215 "Search and make sure that anu matches are in headlines."
6216 (catch 'return
6217 (while (search-forward string bound noerror)
6218 (when (let ((context (mapcar 'car (save-match-data (org-context)))))
6219 (and (member :headline context)
6220 (not (member :tags context))))
6221 (throw 'return (point))))))
6223 (defun org-goto-local-auto-isearch ()
6224 "Start isearch."
6225 (interactive)
6226 (goto-char (point-min))
6227 (let ((keys (this-command-keys)))
6228 (when (eq (lookup-key isearch-mode-map keys) 'isearch-printing-char)
6229 (isearch-mode t)
6230 (isearch-process-search-char (string-to-char keys)))))
6232 (defun org-goto-ret (&optional arg)
6233 "Finish `org-goto' by going to the new location."
6234 (interactive "P")
6235 (setq org-goto-selected-point (point)
6236 org-goto-exit-command 'return)
6237 (throw 'exit nil))
6239 (defun org-goto-left ()
6240 "Finish `org-goto' by going to the new location."
6241 (interactive)
6242 (if (org-on-heading-p)
6243 (progn
6244 (beginning-of-line 1)
6245 (setq org-goto-selected-point (point)
6246 org-goto-exit-command 'left)
6247 (throw 'exit nil))
6248 (error "Not on a heading")))
6250 (defun org-goto-right ()
6251 "Finish `org-goto' by going to the new location."
6252 (interactive)
6253 (if (org-on-heading-p)
6254 (progn
6255 (setq org-goto-selected-point (point)
6256 org-goto-exit-command 'right)
6257 (throw 'exit nil))
6258 (error "Not on a heading")))
6260 (defun org-goto-quit ()
6261 "Finish `org-goto' without cursor motion."
6262 (interactive)
6263 (setq org-goto-selected-point nil)
6264 (setq org-goto-exit-command 'quit)
6265 (throw 'exit nil))
6267 ;;; Indirect buffer display of subtrees
6269 (defvar org-indirect-dedicated-frame nil
6270 "This is the frame being used for indirect tree display.")
6271 (defvar org-last-indirect-buffer nil)
6273 (defun org-tree-to-indirect-buffer (&optional arg)
6274 "Create indirect buffer and narrow it to current subtree.
6275 With numerical prefix ARG, go up to this level and then take that tree.
6276 If ARG is negative, go up that many levels.
6277 If `org-indirect-buffer-display' is not `new-frame', the command removes the
6278 indirect buffer previously made with this command, to avoid proliferation of
6279 indirect buffers. However, when you call the command with a `C-u' prefix, or
6280 when `org-indirect-buffer-display' is `new-frame', the last buffer
6281 is kept so that you can work with several indirect buffers at the same time.
6282 If `org-indirect-buffer-display' is `dedicated-frame', the C-u prefix also
6283 requests that a new frame be made for the new buffer, so that the dedicated
6284 frame is not changed."
6285 (interactive "P")
6286 (let ((cbuf (current-buffer))
6287 (cwin (selected-window))
6288 (pos (point))
6289 beg end level heading ibuf)
6290 (save-excursion
6291 (org-back-to-heading t)
6292 (when (numberp arg)
6293 (setq level (org-outline-level))
6294 (if (< arg 0) (setq arg (+ level arg)))
6295 (while (> (setq level (org-outline-level)) arg)
6296 (outline-up-heading 1 t)))
6297 (setq beg (point)
6298 heading (org-get-heading))
6299 (org-end-of-subtree t) (setq end (point)))
6300 (if (and (buffer-live-p org-last-indirect-buffer)
6301 (not (eq org-indirect-buffer-display 'new-frame))
6302 (not arg))
6303 (kill-buffer org-last-indirect-buffer))
6304 (setq ibuf (org-get-indirect-buffer cbuf)
6305 org-last-indirect-buffer ibuf)
6306 (cond
6307 ((or (eq org-indirect-buffer-display 'new-frame)
6308 (and arg (eq org-indirect-buffer-display 'dedicated-frame)))
6309 (select-frame (make-frame))
6310 (delete-other-windows)
6311 (switch-to-buffer ibuf)
6312 (org-set-frame-title heading))
6313 ((eq org-indirect-buffer-display 'dedicated-frame)
6314 (raise-frame
6315 (select-frame (or (and org-indirect-dedicated-frame
6316 (frame-live-p org-indirect-dedicated-frame)
6317 org-indirect-dedicated-frame)
6318 (setq org-indirect-dedicated-frame (make-frame)))))
6319 (delete-other-windows)
6320 (switch-to-buffer ibuf)
6321 (org-set-frame-title (concat "Indirect: " heading)))
6322 ((eq org-indirect-buffer-display 'current-window)
6323 (switch-to-buffer ibuf))
6324 ((eq org-indirect-buffer-display 'other-window)
6325 (pop-to-buffer ibuf))
6326 (t (error "Invalid value.")))
6327 (if (featurep 'xemacs)
6328 (save-excursion (org-mode) (turn-on-font-lock)))
6329 (narrow-to-region beg end)
6330 (show-all)
6331 (goto-char pos)
6332 (and (window-live-p cwin) (select-window cwin))))
6334 (defun org-get-indirect-buffer (&optional buffer)
6335 (setq buffer (or buffer (current-buffer)))
6336 (let ((n 1) (base (buffer-name buffer)) bname)
6337 (while (buffer-live-p
6338 (get-buffer (setq bname (concat base "-" (number-to-string n)))))
6339 (setq n (1+ n)))
6340 (condition-case nil
6341 (make-indirect-buffer buffer bname 'clone)
6342 (error (make-indirect-buffer buffer bname)))))
6344 (defun org-set-frame-title (title)
6345 "Set the title of the current frame to the string TITLE."
6346 ;; FIXME: how to name a single frame in XEmacs???
6347 (unless (featurep 'xemacs)
6348 (modify-frame-parameters (selected-frame) (list (cons 'name title)))))
6350 ;;;; Structure editing
6352 ;;; Inserting headlines
6354 (defun org-insert-heading (&optional force-heading)
6355 "Insert a new heading or item with same depth at point.
6356 If point is in a plain list and FORCE-HEADING is nil, create a new list item.
6357 If point is at the beginning of a headline, insert a sibling before the
6358 current headline. If point is not at the beginning, do not split the line,
6359 but create the new hedline after the current line."
6360 (interactive "P")
6361 (if (= (buffer-size) 0)
6362 (insert "\n* ")
6363 (when (or force-heading (not (org-insert-item)))
6364 (let* ((head (save-excursion
6365 (condition-case nil
6366 (progn
6367 (org-back-to-heading)
6368 (match-string 0))
6369 (error "*"))))
6370 (blank (cdr (assq 'heading org-blank-before-new-entry)))
6371 pos)
6372 (cond
6373 ((and (org-on-heading-p) (bolp)
6374 (or (bobp)
6375 (save-excursion (backward-char 1) (not (org-invisible-p)))))
6376 ;; insert before the current line
6377 (open-line (if blank 2 1)))
6378 ((and (bolp)
6379 (or (bobp)
6380 (save-excursion
6381 (backward-char 1) (not (org-invisible-p)))))
6382 ;; insert right here
6383 nil)
6385 ; ;; in the middle of the line
6386 ; (org-show-entry)
6387 ; (if (org-get-alist-option org-M-RET-may-split-line 'headline)
6388 ; (if (and
6389 ; (org-on-heading-p)
6390 ; (looking-at ".*?\\([ \t]+\\(:[[:alnum:]_@:]+:\\)\\)[ \r\n]"))
6391 ; ;; protect the tags
6392 ;; (let ((tags (match-string 2)) pos)
6393 ; (delete-region (match-beginning 1) (match-end 1))
6394 ; (setq pos (point-at-bol))
6395 ; (newline (if blank 2 1))
6396 ; (save-excursion
6397 ; (goto-char pos)
6398 ; (end-of-line 1)
6399 ; (insert " " tags)
6400 ; (org-set-tags nil 'align)))
6401 ; (newline (if blank 2 1)))
6402 ; (newline (if blank 2 1))))
6405 ;; in the middle of the line
6406 (org-show-entry)
6407 (let ((split
6408 (org-get-alist-option org-M-RET-may-split-line 'headline))
6409 tags pos)
6410 (if (org-on-heading-p)
6411 (progn
6412 (looking-at ".*?\\([ \t]+\\(:[[:alnum:]_@:]+:\\)\\)?[ \t]*$")
6413 (setq tags (and (match-end 2) (match-string 2)))
6414 (and (match-end 1)
6415 (delete-region (match-beginning 1) (match-end 1)))
6416 (setq pos (point-at-bol))
6417 (or split (end-of-line 1))
6418 (delete-horizontal-space)
6419 (newline (if blank 2 1))
6420 (when tags
6421 (save-excursion
6422 (goto-char pos)
6423 (end-of-line 1)
6424 (insert " " tags)
6425 (org-set-tags nil 'align))))
6426 (or split (end-of-line 1))
6427 (newline (if blank 2 1))))))
6428 (insert head) (just-one-space)
6429 (setq pos (point))
6430 (end-of-line 1)
6431 (unless (= (point) pos) (just-one-space) (backward-delete-char 1))
6432 (run-hooks 'org-insert-heading-hook)))))
6434 (defun org-insert-heading-after-current ()
6435 "Insert a new heading with same level as current, after current subtree."
6436 (interactive)
6437 (org-back-to-heading)
6438 (org-insert-heading)
6439 (org-move-subtree-down)
6440 (end-of-line 1))
6442 (defun org-insert-todo-heading (arg)
6443 "Insert a new heading with the same level and TODO state as current heading.
6444 If the heading has no TODO state, or if the state is DONE, use the first
6445 state (TODO by default). Also with prefix arg, force first state."
6446 (interactive "P")
6447 (when (not (org-insert-item 'checkbox))
6448 (org-insert-heading)
6449 (save-excursion
6450 (org-back-to-heading)
6451 (outline-previous-heading)
6452 (looking-at org-todo-line-regexp))
6453 (if (or arg
6454 (not (match-beginning 2))
6455 (member (match-string 2) org-done-keywords))
6456 (insert (car org-todo-keywords-1) " ")
6457 (insert (match-string 2) " "))))
6459 (defun org-insert-subheading (arg)
6460 "Insert a new subheading and demote it.
6461 Works for outline headings and for plain lists alike."
6462 (interactive "P")
6463 (org-insert-heading arg)
6464 (cond
6465 ((org-on-heading-p) (org-do-demote))
6466 ((org-at-item-p) (org-indent-item 1))))
6468 (defun org-insert-todo-subheading (arg)
6469 "Insert a new subheading with TODO keyword or checkbox and demote it.
6470 Works for outline headings and for plain lists alike."
6471 (interactive "P")
6472 (org-insert-todo-heading arg)
6473 (cond
6474 ((org-on-heading-p) (org-do-demote))
6475 ((org-at-item-p) (org-indent-item 1))))
6477 ;;; Promotion and Demotion
6479 (defun org-promote-subtree ()
6480 "Promote the entire subtree.
6481 See also `org-promote'."
6482 (interactive)
6483 (save-excursion
6484 (org-map-tree 'org-promote))
6485 (org-fix-position-after-promote))
6487 (defun org-demote-subtree ()
6488 "Demote the entire subtree. See `org-demote'.
6489 See also `org-promote'."
6490 (interactive)
6491 (save-excursion
6492 (org-map-tree 'org-demote))
6493 (org-fix-position-after-promote))
6496 (defun org-do-promote ()
6497 "Promote the current heading higher up the tree.
6498 If the region is active in `transient-mark-mode', promote all headings
6499 in the region."
6500 (interactive)
6501 (save-excursion
6502 (if (org-region-active-p)
6503 (org-map-region 'org-promote (region-beginning) (region-end))
6504 (org-promote)))
6505 (org-fix-position-after-promote))
6507 (defun org-do-demote ()
6508 "Demote the current heading lower down the tree.
6509 If the region is active in `transient-mark-mode', demote all headings
6510 in the region."
6511 (interactive)
6512 (save-excursion
6513 (if (org-region-active-p)
6514 (org-map-region 'org-demote (region-beginning) (region-end))
6515 (org-demote)))
6516 (org-fix-position-after-promote))
6518 (defun org-fix-position-after-promote ()
6519 "Make sure that after pro/demotion cursor position is right."
6520 (let ((pos (point)))
6521 (when (save-excursion
6522 (beginning-of-line 1)
6523 (looking-at org-todo-line-regexp)
6524 (or (equal pos (match-end 1)) (equal pos (match-end 2))))
6525 (cond ((eobp) (insert " "))
6526 ((eolp) (insert " "))
6527 ((equal (char-after) ?\ ) (forward-char 1))))))
6529 (defun org-reduced-level (l)
6530 (if org-odd-levels-only (1+ (floor (/ l 2))) l))
6532 (defun org-get-valid-level (level &optional change)
6533 "Rectify a level change under the influence of `org-odd-levels-only'
6534 LEVEL is a current level, CHANGE is by how much the level should be
6535 modified. Even if CHANGE is nil, LEVEL may be returned modified because
6536 even level numbers will become the next higher odd number."
6537 (if org-odd-levels-only
6538 (cond ((or (not change) (= 0 change)) (1+ (* 2 (/ level 2))))
6539 ((> change 0) (1+ (* 2 (/ (+ level (* 2 change)) 2))))
6540 ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2))))))
6541 (max 1 (+ level change))))
6543 (if (featurep 'xemacs)
6544 (define-obsolete-function-alias 'org-get-legal-level
6545 'org-get-valid-level)
6546 (define-obsolete-function-alias 'org-get-legal-level
6547 'org-get-valid-level "23.1"))
6549 (defun org-promote ()
6550 "Promote the current heading higher up the tree.
6551 If the region is active in `transient-mark-mode', promote all headings
6552 in the region."
6553 (org-back-to-heading t)
6554 (let* ((level (save-match-data (funcall outline-level)))
6555 (up-head (concat (make-string (org-get-valid-level level -1) ?*) " "))
6556 (diff (abs (- level (length up-head) -1))))
6557 (if (= level 1) (error "Cannot promote to level 0. UNDO to recover if necessary"))
6558 (replace-match up-head nil t)
6559 ;; Fixup tag positioning
6560 (and org-auto-align-tags (org-set-tags nil t))
6561 (if org-adapt-indentation (org-fixup-indentation (- diff)))))
6563 (defun org-demote ()
6564 "Demote the current heading lower down the tree.
6565 If the region is active in `transient-mark-mode', demote all headings
6566 in the region."
6567 (org-back-to-heading t)
6568 (let* ((level (save-match-data (funcall outline-level)))
6569 (down-head (concat (make-string (org-get-valid-level level 1) ?*) " "))
6570 (diff (abs (- level (length down-head) -1))))
6571 (replace-match down-head nil t)
6572 ;; Fixup tag positioning
6573 (and org-auto-align-tags (org-set-tags nil t))
6574 (if org-adapt-indentation (org-fixup-indentation diff))))
6576 (defun org-map-tree (fun)
6577 "Call FUN for every heading underneath the current one."
6578 (org-back-to-heading)
6579 (let ((level (funcall outline-level)))
6580 (save-excursion
6581 (funcall fun)
6582 (while (and (progn
6583 (outline-next-heading)
6584 (> (funcall outline-level) level))
6585 (not (eobp)))
6586 (funcall fun)))))
6588 (defun org-map-region (fun beg end)
6589 "Call FUN for every heading between BEG and END."
6590 (let ((org-ignore-region t))
6591 (save-excursion
6592 (setq end (copy-marker end))
6593 (goto-char beg)
6594 (if (and (re-search-forward (concat "^" outline-regexp) nil t)
6595 (< (point) end))
6596 (funcall fun))
6597 (while (and (progn
6598 (outline-next-heading)
6599 (< (point) end))
6600 (not (eobp)))
6601 (funcall fun)))))
6603 (defun org-fixup-indentation (diff)
6604 "Change the indentation in the current entry by DIFF
6605 However, if any line in the current entry has no indentation, or if it
6606 would end up with no indentation after the change, nothing at all is done."
6607 (save-excursion
6608 (let ((end (save-excursion (outline-next-heading)
6609 (point-marker)))
6610 (prohibit (if (> diff 0)
6611 "^\\S-"
6612 (concat "^ \\{0," (int-to-string (- diff)) "\\}\\S-")))
6613 col)
6614 (unless (save-excursion (end-of-line 1)
6615 (re-search-forward prohibit end t))
6616 (while (and (< (point) end)
6617 (re-search-forward "^[ \t]+" end t))
6618 (goto-char (match-end 0))
6619 (setq col (current-column))
6620 (if (< diff 0) (replace-match ""))
6621 (indent-to (+ diff col))))
6622 (move-marker end nil))))
6624 (defun org-convert-to-odd-levels ()
6625 "Convert an org-mode file with all levels allowed to one with odd levels.
6626 This will leave level 1 alone, convert level 2 to level 3, level 3 to
6627 level 5 etc."
6628 (interactive)
6629 (when (yes-or-no-p "Are you sure you want to globally change levels to odd? ")
6630 (let ((org-odd-levels-only nil) n)
6631 (save-excursion
6632 (goto-char (point-min))
6633 (while (re-search-forward "^\\*\\*+ " nil t)
6634 (setq n (- (length (match-string 0)) 2))
6635 (while (>= (setq n (1- n)) 0)
6636 (org-demote))
6637 (end-of-line 1))))))
6640 (defun org-convert-to-oddeven-levels ()
6641 "Convert an org-mode file with only odd levels to one with odd and even levels.
6642 This promotes level 3 to level 2, level 5 to level 3 etc. If the file contains a
6643 section with an even level, conversion would destroy the structure of the file. An error
6644 is signaled in this case."
6645 (interactive)
6646 (goto-char (point-min))
6647 ;; First check if there are no even levels
6648 (when (re-search-forward "^\\(\\*\\*\\)+ " nil t)
6649 (org-show-context t)
6650 (error "Not all levels are odd in this file. Conversion not possible."))
6651 (when (yes-or-no-p "Are you sure you want to globally change levels to odd-even? ")
6652 (let ((org-odd-levels-only nil) n)
6653 (save-excursion
6654 (goto-char (point-min))
6655 (while (re-search-forward "^\\*\\*+ " nil t)
6656 (setq n (/ (1- (length (match-string 0))) 2))
6657 (while (>= (setq n (1- n)) 0)
6658 (org-promote))
6659 (end-of-line 1))))))
6661 (defun org-tr-level (n)
6662 "Make N odd if required."
6663 (if org-odd-levels-only (1+ (/ n 2)) n))
6665 ;;; Vertical tree motion, cutting and pasting of subtrees
6667 (defun org-move-subtree-up (&optional arg)
6668 "Move the current subtree up past ARG headlines of the same level."
6669 (interactive "p")
6670 (org-move-subtree-down (- (prefix-numeric-value arg))))
6672 (defun org-move-subtree-down (&optional arg)
6673 "Move the current subtree down past ARG headlines of the same level."
6674 (interactive "p")
6675 (setq arg (prefix-numeric-value arg))
6676 (let ((movfunc (if (> arg 0) 'outline-get-next-sibling
6677 'outline-get-last-sibling))
6678 (ins-point (make-marker))
6679 (cnt (abs arg))
6680 beg beg0 end txt folded ne-beg ne-end ne-ins ins-end)
6681 ;; Select the tree
6682 (org-back-to-heading)
6683 (setq beg0 (point))
6684 (save-excursion
6685 (setq ne-beg (org-back-over-empty-lines))
6686 (setq beg (point)))
6687 (save-match-data
6688 (save-excursion (outline-end-of-heading)
6689 (setq folded (org-invisible-p)))
6690 (outline-end-of-subtree))
6691 (outline-next-heading)
6692 (setq ne-end (org-back-over-empty-lines))
6693 (setq end (point))
6694 (goto-char beg0)
6695 (when (and (> arg 0) (org-first-sibling-p) (< ne-end ne-beg))
6696 ;; include less whitespace
6697 (save-excursion
6698 (goto-char beg)
6699 (forward-line (- ne-beg ne-end))
6700 (setq beg (point))))
6701 ;; Find insertion point, with error handling
6702 (while (> cnt 0)
6703 (or (and (funcall movfunc) (looking-at outline-regexp))
6704 (progn (goto-char beg0)
6705 (error "Cannot move past superior level or buffer limit")))
6706 (setq cnt (1- cnt)))
6707 (if (> arg 0)
6708 ;; Moving forward - still need to move over subtree
6709 (progn (org-end-of-subtree t t)
6710 (save-excursion
6711 (org-back-over-empty-lines)
6712 (or (bolp) (newline)))))
6713 (setq ne-ins (org-back-over-empty-lines))
6714 (move-marker ins-point (point))
6715 (setq txt (buffer-substring beg end))
6716 (delete-region beg end)
6717 (outline-flag-region (1- beg) beg nil)
6718 (outline-flag-region (1- (point)) (point) nil)
6719 (insert txt)
6720 (or (bolp) (insert "\n"))
6721 (setq ins-end (point))
6722 (goto-char ins-point)
6723 (org-skip-whitespace)
6724 (when (and (< arg 0)
6725 (org-first-sibling-p)
6726 (> ne-ins ne-beg))
6727 ;; Move whitespace back to beginning
6728 (save-excursion
6729 (goto-char ins-end)
6730 (let ((kill-whole-line t))
6731 (kill-line (- ne-ins ne-beg)) (point)))
6732 (insert (make-string (- ne-ins ne-beg) ?\n)))
6733 (move-marker ins-point nil)
6734 (org-compact-display-after-subtree-move)
6735 (unless folded
6736 (org-show-entry)
6737 (show-children)
6738 (org-cycle-hide-drawers 'children))))
6740 (defvar org-subtree-clip ""
6741 "Clipboard for cut and paste of subtrees.
6742 This is actually only a copy of the kill, because we use the normal kill
6743 ring. We need it to check if the kill was created by `org-copy-subtree'.")
6745 (defvar org-subtree-clip-folded nil
6746 "Was the last copied subtree folded?
6747 This is used to fold the tree back after pasting.")
6749 (defun org-cut-subtree (&optional n)
6750 "Cut the current subtree into the clipboard.
6751 With prefix arg N, cut this many sequential subtrees.
6752 This is a short-hand for marking the subtree and then cutting it."
6753 (interactive "p")
6754 (org-copy-subtree n 'cut))
6756 (defun org-copy-subtree (&optional n cut)
6757 "Cut the current subtree into the clipboard.
6758 With prefix arg N, cut this many sequential subtrees.
6759 This is a short-hand for marking the subtree and then copying it.
6760 If CUT is non-nil, actually cut the subtree."
6761 (interactive "p")
6762 (let (beg end folded (beg0 (point)))
6763 (if (interactive-p)
6764 (org-back-to-heading nil) ; take what looks like a subtree
6765 (org-back-to-heading t)) ; take what is really there
6766 (org-back-over-empty-lines)
6767 (setq beg (point))
6768 (skip-chars-forward " \t\r\n")
6769 (save-match-data
6770 (save-excursion (outline-end-of-heading)
6771 (setq folded (org-invisible-p)))
6772 (condition-case nil
6773 (outline-forward-same-level (1- n))
6774 (error nil))
6775 (org-end-of-subtree t t))
6776 (org-back-over-empty-lines)
6777 (setq end (point))
6778 (goto-char beg0)
6779 (when (> end beg)
6780 (setq org-subtree-clip-folded folded)
6781 (if cut (kill-region beg end) (copy-region-as-kill beg end))
6782 (setq org-subtree-clip (current-kill 0))
6783 (message "%s: Subtree(s) with %d characters"
6784 (if cut "Cut" "Copied")
6785 (length org-subtree-clip)))))
6787 (defun org-paste-subtree (&optional level tree)
6788 "Paste the clipboard as a subtree, with modification of headline level.
6789 The entire subtree is promoted or demoted in order to match a new headline
6790 level. By default, the new level is derived from the visible headings
6791 before and after the insertion point, and taken to be the inferior headline
6792 level of the two. So if the previous visible heading is level 3 and the
6793 next is level 4 (or vice versa), level 4 will be used for insertion.
6794 This makes sure that the subtree remains an independent subtree and does
6795 not swallow low level entries.
6797 You can also force a different level, either by using a numeric prefix
6798 argument, or by inserting the heading marker by hand. For example, if the
6799 cursor is after \"*****\", then the tree will be shifted to level 5.
6801 If you want to insert the tree as is, just use \\[yank].
6803 If optional TREE is given, use this text instead of the kill ring."
6804 (interactive "P")
6805 (unless (org-kill-is-subtree-p tree)
6806 (error "%s"
6807 (substitute-command-keys
6808 "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway")))
6809 (let* ((txt (or tree (and kill-ring (current-kill 0))))
6810 (^re (concat "^\\(" outline-regexp "\\)"))
6811 (re (concat "\\(" outline-regexp "\\)"))
6812 (^re_ (concat "\\(\\*+\\)[ \t]*"))
6814 (old-level (if (string-match ^re txt)
6815 (- (match-end 0) (match-beginning 0) 1)
6816 -1))
6817 (force-level (cond (level (prefix-numeric-value level))
6818 ((string-match
6819 ^re_ (buffer-substring (point-at-bol) (point)))
6820 (- (match-end 1) (match-beginning 1)))
6821 (t nil)))
6822 (previous-level (save-excursion
6823 (condition-case nil
6824 (progn
6825 (outline-previous-visible-heading 1)
6826 (if (looking-at re)
6827 (- (match-end 0) (match-beginning 0) 1)
6829 (error 1))))
6830 (next-level (save-excursion
6831 (condition-case nil
6832 (progn
6833 (or (looking-at outline-regexp)
6834 (outline-next-visible-heading 1))
6835 (if (looking-at re)
6836 (- (match-end 0) (match-beginning 0) 1)
6838 (error 1))))
6839 (new-level (or force-level (max previous-level next-level)))
6840 (shift (if (or (= old-level -1)
6841 (= new-level -1)
6842 (= old-level new-level))
6844 (- new-level old-level)))
6845 (delta (if (> shift 0) -1 1))
6846 (func (if (> shift 0) 'org-demote 'org-promote))
6847 (org-odd-levels-only nil)
6848 beg end)
6849 ;; Remove the forced level indicator
6850 (if force-level
6851 (delete-region (point-at-bol) (point)))
6852 ;; Paste
6853 (beginning-of-line 1)
6854 (org-back-over-empty-lines) ;; FIXME: correct fix????
6855 (setq beg (point))
6856 (insert-before-markers txt) ;; FIXME: correct fix????
6857 (unless (string-match "\n\\'" txt) (insert "\n"))
6858 (setq end (point))
6859 (goto-char beg)
6860 (skip-chars-forward " \t\n\r")
6861 (setq beg (point))
6862 ;; Shift if necessary
6863 (unless (= shift 0)
6864 (save-restriction
6865 (narrow-to-region beg end)
6866 (while (not (= shift 0))
6867 (org-map-region func (point-min) (point-max))
6868 (setq shift (+ delta shift)))
6869 (goto-char (point-min))))
6870 (when (interactive-p)
6871 (message "Clipboard pasted as level %d subtree" new-level))
6872 (if (and kill-ring
6873 (eq org-subtree-clip (current-kill 0))
6874 org-subtree-clip-folded)
6875 ;; The tree was folded before it was killed/copied
6876 (hide-subtree))))
6878 (defun org-kill-is-subtree-p (&optional txt)
6879 "Check if the current kill is an outline subtree, or a set of trees.
6880 Returns nil if kill does not start with a headline, or if the first
6881 headline level is not the largest headline level in the tree.
6882 So this will actually accept several entries of equal levels as well,
6883 which is OK for `org-paste-subtree'.
6884 If optional TXT is given, check this string instead of the current kill."
6885 (let* ((kill (or txt (and kill-ring (current-kill 0)) ""))
6886 (start-level (and kill
6887 (string-match (concat "\\`\\([ \t\n\r]*?\n\\)?\\("
6888 org-outline-regexp "\\)")
6889 kill)
6890 (- (match-end 2) (match-beginning 2) 1)))
6891 (re (concat "^" org-outline-regexp))
6892 (start (1+ (match-beginning 2))))
6893 (if (not start-level)
6894 (progn
6895 nil) ;; does not even start with a heading
6896 (catch 'exit
6897 (while (setq start (string-match re kill (1+ start)))
6898 (when (< (- (match-end 0) (match-beginning 0) 1) start-level)
6899 (throw 'exit nil)))
6900 t))))
6902 (defun org-narrow-to-subtree ()
6903 "Narrow buffer to the current subtree."
6904 (interactive)
6905 (save-excursion
6906 (save-match-data
6907 (narrow-to-region
6908 (progn (org-back-to-heading) (point))
6909 (progn (org-end-of-subtree t t) (point))))))
6912 ;;; Outline Sorting
6914 (defun org-sort (with-case)
6915 "Call `org-sort-entries-or-items' or `org-table-sort-lines'.
6916 Optional argument WITH-CASE means sort case-sensitively."
6917 (interactive "P")
6918 (if (org-at-table-p)
6919 (org-call-with-arg 'org-table-sort-lines with-case)
6920 (org-call-with-arg 'org-sort-entries-or-items with-case)))
6922 (defvar org-priority-regexp) ; defined later in the file
6924 (defun org-sort-entries-or-items (&optional with-case sorting-type getkey-func property)
6925 "Sort entries on a certain level of an outline tree.
6926 If there is an active region, the entries in the region are sorted.
6927 Else, if the cursor is before the first entry, sort the top-level items.
6928 Else, the children of the entry at point are sorted.
6930 Sorting can be alphabetically, numerically, and by date/time as given by
6931 the first time stamp in the entry. The command prompts for the sorting
6932 type unless it has been given to the function through the SORTING-TYPE
6933 argument, which needs to a character, any of (?n ?N ?a ?A ?t ?T ?p ?P ?f ?F).
6934 If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies a function to be
6935 called with point at the beginning of the record. It must return either
6936 a string or a number that should serve as the sorting key for that record.
6938 Comparing entries ignores case by default. However, with an optional argument
6939 WITH-CASE, the sorting considers case as well."
6940 (interactive "P")
6941 (let ((case-func (if with-case 'identity 'downcase))
6942 start beg end stars re re2
6943 txt what tmp plain-list-p)
6944 ;; Find beginning and end of region to sort
6945 (cond
6946 ((org-region-active-p)
6947 ;; we will sort the region
6948 (setq end (region-end)
6949 what "region")
6950 (goto-char (region-beginning))
6951 (if (not (org-on-heading-p)) (outline-next-heading))
6952 (setq start (point)))
6953 ((org-at-item-p)
6954 ;; we will sort this plain list
6955 (org-beginning-of-item-list) (setq start (point))
6956 (org-end-of-item-list) (setq end (point))
6957 (goto-char start)
6958 (setq plain-list-p t
6959 what "plain list"))
6960 ((or (org-on-heading-p)
6961 (condition-case nil (progn (org-back-to-heading) t) (error nil)))
6962 ;; we will sort the children of the current headline
6963 (org-back-to-heading)
6964 (setq start (point)
6965 end (progn (org-end-of-subtree t t)
6966 (org-back-over-empty-lines)
6967 (point))
6968 what "children")
6969 (goto-char start)
6970 (show-subtree)
6971 (outline-next-heading))
6973 ;; we will sort the top-level entries in this file
6974 (goto-char (point-min))
6975 (or (org-on-heading-p) (outline-next-heading))
6976 (setq start (point) end (point-max) what "top-level")
6977 (goto-char start)
6978 (show-all)))
6980 (setq beg (point))
6981 (if (>= beg end) (error "Nothing to sort"))
6983 (unless plain-list-p
6984 (looking-at "\\(\\*+\\)")
6985 (setq stars (match-string 1)
6986 re (concat "^" (regexp-quote stars) " +")
6987 re2 (concat "^" (regexp-quote (substring stars 0 -1)) "[^*]")
6988 txt (buffer-substring beg end))
6989 (if (not (equal (substring txt -1) "\n")) (setq txt (concat txt "\n")))
6990 (if (and (not (equal stars "*")) (string-match re2 txt))
6991 (error "Region to sort contains a level above the first entry")))
6993 (unless sorting-type
6994 (message
6995 (if plain-list-p
6996 "Sort %s: [a]lpha [n]umeric [t]ime [f]unc A/N/T/F means reversed:"
6997 "Sort %s: [a]lpha [n]umeric [t]ime [p]riority p[r]operty [f]unc A/N/T/P/F means reversed:")
6998 what)
6999 (setq sorting-type (read-char-exclusive))
7001 (and (= (downcase sorting-type) ?f)
7002 (setq getkey-func
7003 (completing-read "Sort using function: "
7004 obarray 'fboundp t nil nil))
7005 (setq getkey-func (intern getkey-func)))
7007 (and (= (downcase sorting-type) ?r)
7008 (setq property
7009 (completing-read "Property: "
7010 (mapcar 'list (org-buffer-property-keys t))
7011 nil t))))
7013 (message "Sorting entries...")
7015 (save-restriction
7016 (narrow-to-region start end)
7018 (let ((dcst (downcase sorting-type))
7019 (now (current-time)))
7020 (sort-subr
7021 (/= dcst sorting-type)
7022 ;; This function moves to the beginning character of the "record" to
7023 ;; be sorted.
7024 (if plain-list-p
7025 (lambda nil
7026 (if (org-at-item-p) t (goto-char (point-max))))
7027 (lambda nil
7028 (if (re-search-forward re nil t)
7029 (goto-char (match-beginning 0))
7030 (goto-char (point-max)))))
7031 ;; This function moves to the last character of the "record" being
7032 ;; sorted.
7033 (if plain-list-p
7034 'org-end-of-item
7035 (lambda nil
7036 (save-match-data
7037 (condition-case nil
7038 (outline-forward-same-level 1)
7039 (error
7040 (goto-char (point-max)))))))
7042 ;; This function returns the value that gets sorted against.
7043 (if plain-list-p
7044 (lambda nil
7045 (when (looking-at "[ \t]*[-+*0-9.)]+[ \t]+")
7046 (cond
7047 ((= dcst ?n)
7048 (string-to-number (buffer-substring (match-end 0)
7049 (point-at-eol))))
7050 ((= dcst ?a)
7051 (buffer-substring (match-end 0) (point-at-eol)))
7052 ((= dcst ?t)
7053 (if (re-search-forward org-ts-regexp
7054 (point-at-eol) t)
7055 (org-time-string-to-time (match-string 0))
7056 now))
7057 ((= dcst ?f)
7058 (if getkey-func
7059 (progn
7060 (setq tmp (funcall getkey-func))
7061 (if (stringp tmp) (setq tmp (funcall case-func tmp)))
7062 tmp)
7063 (error "Invalid key function `%s'" getkey-func)))
7064 (t (error "Invalid sorting type `%c'" sorting-type)))))
7065 (lambda nil
7066 (cond
7067 ((= dcst ?n)
7068 (if (looking-at outline-regexp)
7069 (string-to-number (buffer-substring (match-end 0)
7070 (point-at-eol)))
7071 nil))
7072 ((= dcst ?a)
7073 (funcall case-func (buffer-substring (point-at-bol)
7074 (point-at-eol))))
7075 ((= dcst ?t)
7076 (if (re-search-forward org-ts-regexp
7077 (save-excursion
7078 (forward-line 2)
7079 (point)) t)
7080 (org-time-string-to-time (match-string 0))
7081 now))
7082 ((= dcst ?p)
7083 (if (re-search-forward org-priority-regexp (point-at-eol) t)
7084 (string-to-char (match-string 2))
7085 org-default-priority))
7086 ((= dcst ?r)
7087 (or (org-entry-get nil property) ""))
7088 ((= dcst ?f)
7089 (if getkey-func
7090 (progn
7091 (setq tmp (funcall getkey-func))
7092 (if (stringp tmp) (setq tmp (funcall case-func tmp)))
7093 tmp)
7094 (error "Invalid key function `%s'" getkey-func)))
7095 (t (error "Invalid sorting type `%c'" sorting-type)))))
7097 (cond
7098 ((= dcst ?a) 'string<)
7099 ((= dcst ?t) 'time-less-p)
7100 (t nil)))))
7101 (message "Sorting entries...done")))
7103 (defun org-do-sort (table what &optional with-case sorting-type)
7104 "Sort TABLE of WHAT according to SORTING-TYPE.
7105 The user will be prompted for the SORTING-TYPE if the call to this
7106 function does not specify it. WHAT is only for the prompt, to indicate
7107 what is being sorted. The sorting key will be extracted from
7108 the car of the elements of the table.
7109 If WITH-CASE is non-nil, the sorting will be case-sensitive."
7110 (unless sorting-type
7111 (message
7112 "Sort %s: [a]lphabetic. [n]umeric. [t]ime. A/N/T means reversed:"
7113 what)
7114 (setq sorting-type (read-char-exclusive)))
7115 (let ((dcst (downcase sorting-type))
7116 extractfun comparefun)
7117 ;; Define the appropriate functions
7118 (cond
7119 ((= dcst ?n)
7120 (setq extractfun 'string-to-number
7121 comparefun (if (= dcst sorting-type) '< '>)))
7122 ((= dcst ?a)
7123 (setq extractfun (if with-case (lambda(x) (org-sort-remove-invisible x))
7124 (lambda(x) (downcase (org-sort-remove-invisible x))))
7125 comparefun (if (= dcst sorting-type)
7126 'string<
7127 (lambda (a b) (and (not (string< a b))
7128 (not (string= a b)))))))
7129 ((= dcst ?t)
7130 (setq extractfun
7131 (lambda (x)
7132 (if (string-match org-ts-regexp x)
7133 (time-to-seconds
7134 (org-time-string-to-time (match-string 0 x)))
7136 comparefun (if (= dcst sorting-type) '< '>)))
7137 (t (error "Invalid sorting type `%c'" sorting-type)))
7139 (sort (mapcar (lambda (x) (cons (funcall extractfun (car x)) (cdr x)))
7140 table)
7141 (lambda (a b) (funcall comparefun (car a) (car b))))))
7143 ;;;; Plain list items, including checkboxes
7145 ;;; Plain list items
7147 (defun org-at-item-p ()
7148 "Is point in a line starting a hand-formatted item?"
7149 (let ((llt org-plain-list-ordered-item-terminator))
7150 (save-excursion
7151 (goto-char (point-at-bol))
7152 (looking-at
7153 (cond
7154 ((eq llt t) "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
7155 ((= llt ?.) "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
7156 ((= llt ?\)) "\\([ \t]*\\([-+]\\|\\([0-9]+))\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
7157 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))))))
7159 (defun org-in-item-p ()
7160 "It the cursor inside a plain list item.
7161 Does not have to be the first line."
7162 (save-excursion
7163 (condition-case nil
7164 (progn
7165 (org-beginning-of-item)
7166 (org-at-item-p)
7168 (error nil))))
7170 (defun org-insert-item (&optional checkbox)
7171 "Insert a new item at the current level.
7172 Return t when things worked, nil when we are not in an item."
7173 (when (save-excursion
7174 (condition-case nil
7175 (progn
7176 (org-beginning-of-item)
7177 (org-at-item-p)
7178 (if (org-invisible-p) (error "Invisible item"))
7180 (error nil)))
7181 (let* ((bul (match-string 0))
7182 (eow (save-excursion (beginning-of-line 1) (looking-at "[ \t]*")
7183 (match-end 0)))
7184 (blank (cdr (assq 'plain-list-item org-blank-before-new-entry)))
7185 pos)
7186 (cond
7187 ((and (org-at-item-p) (<= (point) eow))
7188 ;; before the bullet
7189 (beginning-of-line 1)
7190 (open-line (if blank 2 1)))
7191 ((<= (point) eow)
7192 (beginning-of-line 1))
7194 (unless (org-get-alist-option org-M-RET-may-split-line 'item)
7195 (end-of-line 1)
7196 (delete-horizontal-space))
7197 (newline (if blank 2 1))))
7198 (insert bul (if checkbox "[ ]" ""))
7199 (just-one-space)
7200 (setq pos (point))
7201 (end-of-line 1)
7202 (unless (= (point) pos) (just-one-space) (backward-delete-char 1)))
7203 (org-maybe-renumber-ordered-list)
7204 (and checkbox (org-update-checkbox-count-maybe))
7207 ;;; Checkboxes
7209 (defun org-at-item-checkbox-p ()
7210 "Is point at a line starting a plain-list item with a checklet?"
7211 (and (org-at-item-p)
7212 (save-excursion
7213 (goto-char (match-end 0))
7214 (skip-chars-forward " \t")
7215 (looking-at "\\[[- X]\\]"))))
7217 (defun org-toggle-checkbox (&optional arg)
7218 "Toggle the checkbox in the current line."
7219 (interactive "P")
7220 (catch 'exit
7221 (let (beg end status (firstnew 'unknown))
7222 (cond
7223 ((org-region-active-p)
7224 (setq beg (region-beginning) end (region-end)))
7225 ((org-on-heading-p)
7226 (setq beg (point) end (save-excursion (outline-next-heading) (point))))
7227 ((org-at-item-checkbox-p)
7228 (let ((pos (point)))
7229 (replace-match
7230 (cond (arg "[-]")
7231 ((member (match-string 0) '("[ ]" "[-]")) "[X]")
7232 (t "[ ]"))
7233 t t)
7234 (goto-char pos))
7235 (throw 'exit t))
7236 (t (error "Not at a checkbox or heading, and no active region")))
7237 (save-excursion
7238 (goto-char beg)
7239 (while (< (point) end)
7240 (when (org-at-item-checkbox-p)
7241 (setq status (equal (match-string 0) "[X]"))
7242 (when (eq firstnew 'unknown)
7243 (setq firstnew (not status)))
7244 (replace-match
7245 (if (if arg (not status) firstnew) "[X]" "[ ]") t t))
7246 (beginning-of-line 2)))))
7247 (org-update-checkbox-count-maybe))
7249 (defun org-update-checkbox-count-maybe ()
7250 "Update checkbox statistics unless turned off by user."
7251 (when org-provide-checkbox-statistics
7252 (org-update-checkbox-count)))
7254 (defun org-update-checkbox-count (&optional all)
7255 "Update the checkbox statistics in the current section.
7256 This will find all statistic cookies like [57%] and [6/12] and update them
7257 with the current numbers. With optional prefix argument ALL, do this for
7258 the whole buffer."
7259 (interactive "P")
7260 (save-excursion
7261 (let* ((buffer-invisibility-spec (org-inhibit-invisibility)) ; Emacs 21
7262 (beg (condition-case nil
7263 (progn (outline-back-to-heading) (point))
7264 (error (point-min))))
7265 (end (move-marker (make-marker)
7266 (progn (outline-next-heading) (point))))
7267 (re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)")
7268 (re-box "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[- X]\\]\\)")
7269 (re-find (concat re "\\|" re-box))
7270 beg-cookie end-cookie is-percent c-on c-off lim
7271 eline curr-ind next-ind continue-from startsearch
7272 (cstat 0)
7274 (when all
7275 (goto-char (point-min))
7276 (outline-next-heading)
7277 (setq beg (point) end (point-max)))
7278 (goto-char end)
7279 ;; find each statistic cookie
7280 (while (re-search-backward re-find beg t)
7281 (setq beg-cookie (match-beginning 1)
7282 end-cookie (match-end 1)
7283 cstat (+ cstat (if end-cookie 1 0))
7284 startsearch (point-at-eol)
7285 continue-from (point-at-bol)
7286 is-percent (match-beginning 2)
7287 lim (cond
7288 ((org-on-heading-p) (outline-next-heading) (point))
7289 ((org-at-item-p) (org-end-of-item) (point))
7290 (t nil))
7291 c-on 0
7292 c-off 0)
7293 (when lim
7294 ;; find first checkbox for this cookie and gather
7295 ;; statistics from all that are at this indentation level
7296 (goto-char startsearch)
7297 (if (re-search-forward re-box lim t)
7298 (progn
7299 (org-beginning-of-item)
7300 (setq curr-ind (org-get-indentation))
7301 (setq next-ind curr-ind)
7302 (while (= curr-ind next-ind)
7303 (save-excursion (end-of-line) (setq eline (point)))
7304 (if (re-search-forward re-box eline t)
7305 (if (member (match-string 2) '("[ ]" "[-]"))
7306 (setq c-off (1+ c-off))
7307 (setq c-on (1+ c-on))
7310 (org-end-of-item)
7311 (setq next-ind (org-get-indentation))
7313 (goto-char continue-from)
7314 ;; update cookie
7315 (when end-cookie
7316 (delete-region beg-cookie end-cookie)
7317 (goto-char beg-cookie)
7318 (insert
7319 (if is-percent
7320 (format "[%d%%]" (/ (* 100 c-on) (max 1 (+ c-on c-off))))
7321 (format "[%d/%d]" c-on (+ c-on c-off)))))
7322 ;; update items checkbox if it has one
7323 (when (org-at-item-p)
7324 (org-beginning-of-item)
7325 (when (and (> (+ c-on c-off) 0)
7326 (re-search-forward re-box (point-at-eol) t))
7327 (setq beg-cookie (match-beginning 2)
7328 end-cookie (match-end 2))
7329 (delete-region beg-cookie end-cookie)
7330 (goto-char beg-cookie)
7331 (cond ((= c-off 0) (insert "[X]"))
7332 ((= c-on 0) (insert "[ ]"))
7333 (t (insert "[-]")))
7335 (goto-char continue-from))
7336 (when (interactive-p)
7337 (message "Checkbox satistics updated %s (%d places)"
7338 (if all "in entire file" "in current outline entry") cstat)))))
7340 (defun org-get-checkbox-statistics-face ()
7341 "Select the face for checkbox statistics.
7342 The face will be `org-done' when all relevant boxes are checked. Otherwise
7343 it will be `org-todo'."
7344 (if (match-end 1)
7345 (if (equal (match-string 1) "100%") 'org-done 'org-todo)
7346 (if (and (> (match-end 2) (match-beginning 2))
7347 (equal (match-string 2) (match-string 3)))
7348 'org-done
7349 'org-todo)))
7351 (defun org-get-indentation (&optional line)
7352 "Get the indentation of the current line, interpreting tabs.
7353 When LINE is given, assume it represents a line and compute its indentation."
7354 (if line
7355 (if (string-match "^ *" (org-remove-tabs line))
7356 (match-end 0))
7357 (save-excursion
7358 (beginning-of-line 1)
7359 (skip-chars-forward " \t")
7360 (current-column))))
7362 (defun org-remove-tabs (s &optional width)
7363 "Replace tabulators in S with spaces.
7364 Assumes that s is a single line, starting in column 0."
7365 (setq width (or width tab-width))
7366 (while (string-match "\t" s)
7367 (setq s (replace-match
7368 (make-string
7369 (- (* width (/ (+ (match-beginning 0) width) width))
7370 (match-beginning 0)) ?\ )
7371 t t s)))
7374 (defun org-fix-indentation (line ind)
7375 "Fix indentation in LINE.
7376 IND is a cons cell with target and minimum indentation.
7377 If the current indenation in LINE is smaller than the minimum,
7378 leave it alone. If it is larger than ind, set it to the target."
7379 (let* ((l (org-remove-tabs line))
7380 (i (org-get-indentation l))
7381 (i1 (car ind)) (i2 (cdr ind)))
7382 (if (>= i i2) (setq l (substring line i2)))
7383 (if (> i1 0)
7384 (concat (make-string i1 ?\ ) l)
7385 l)))
7387 (defcustom org-empty-line-terminates-plain-lists nil
7388 "Non-nil means, an empty line ends all plain list levels.
7389 When nil, empty lines are part of the preceeding item."
7390 :group 'org-plain-lists
7391 :type 'boolean)
7393 (defun org-beginning-of-item ()
7394 "Go to the beginning of the current hand-formatted item.
7395 If the cursor is not in an item, throw an error."
7396 (interactive)
7397 (let ((pos (point))
7398 (limit (save-excursion
7399 (condition-case nil
7400 (progn
7401 (org-back-to-heading)
7402 (beginning-of-line 2) (point))
7403 (error (point-min)))))
7404 (ind-empty (if org-empty-line-terminates-plain-lists 0 10000))
7405 ind ind1)
7406 (if (org-at-item-p)
7407 (beginning-of-line 1)
7408 (beginning-of-line 1)
7409 (skip-chars-forward " \t")
7410 (setq ind (current-column))
7411 (if (catch 'exit
7412 (while t
7413 (beginning-of-line 0)
7414 (if (or (bobp) (< (point) limit)) (throw 'exit nil))
7416 (if (looking-at "[ \t]*$")
7417 (setq ind1 ind-empty)
7418 (skip-chars-forward " \t")
7419 (setq ind1 (current-column)))
7420 (if (< ind1 ind)
7421 (progn (beginning-of-line 1) (throw 'exit (org-at-item-p))))))
7423 (goto-char pos)
7424 (error "Not in an item")))))
7426 (defun org-end-of-item ()
7427 "Go to the end of the current hand-formatted item.
7428 If the cursor is not in an item, throw an error."
7429 (interactive)
7430 (let* ((pos (point))
7431 ind1
7432 (ind-empty (if org-empty-line-terminates-plain-lists 0 10000))
7433 (limit (save-excursion (outline-next-heading) (point)))
7434 (ind (save-excursion
7435 (org-beginning-of-item)
7436 (skip-chars-forward " \t")
7437 (current-column)))
7438 (end (catch 'exit
7439 (while t
7440 (beginning-of-line 2)
7441 (if (eobp) (throw 'exit (point)))
7442 (if (>= (point) limit) (throw 'exit (point-at-bol)))
7443 (if (looking-at "[ \t]*$")
7444 (setq ind1 ind-empty)
7445 (skip-chars-forward " \t")
7446 (setq ind1 (current-column)))
7447 (if (<= ind1 ind)
7448 (throw 'exit (point-at-bol)))))))
7449 (if end
7450 (goto-char end)
7451 (goto-char pos)
7452 (error "Not in an item"))))
7454 (defun org-next-item ()
7455 "Move to the beginning of the next item in the current plain list.
7456 Error if not at a plain list, or if this is the last item in the list."
7457 (interactive)
7458 (let (ind ind1 (pos (point)))
7459 (org-beginning-of-item)
7460 (setq ind (org-get-indentation))
7461 (org-end-of-item)
7462 (setq ind1 (org-get-indentation))
7463 (unless (and (org-at-item-p) (= ind ind1))
7464 (goto-char pos)
7465 (error "On last item"))))
7467 (defun org-previous-item ()
7468 "Move to the beginning of the previous item in the current plain list.
7469 Error if not at a plain list, or if this is the first item in the list."
7470 (interactive)
7471 (let (beg ind ind1 (pos (point)))
7472 (org-beginning-of-item)
7473 (setq beg (point))
7474 (setq ind (org-get-indentation))
7475 (goto-char beg)
7476 (catch 'exit
7477 (while t
7478 (beginning-of-line 0)
7479 (if (looking-at "[ \t]*$")
7481 (if (<= (setq ind1 (org-get-indentation)) ind)
7482 (throw 'exit t)))))
7483 (condition-case nil
7484 (if (or (not (org-at-item-p))
7485 (< ind1 (1- ind)))
7486 (error "")
7487 (org-beginning-of-item))
7488 (error (goto-char pos)
7489 (error "On first item")))))
7491 (defun org-first-list-item-p ()
7492 "Is this heading the item in a plain list?"
7493 (unless (org-at-item-p)
7494 (error "Not at a plain list item"))
7495 (org-beginning-of-item)
7496 (= (point) (save-excursion (org-beginning-of-item-list))))
7498 (defun org-move-item-down ()
7499 "Move the plain list item at point down, i.e. swap with following item.
7500 Subitems (items with larger indentation) are considered part of the item,
7501 so this really moves item trees."
7502 (interactive)
7503 (let (beg beg0 end end0 ind ind1 (pos (point)) txt ne-end ne-beg)
7504 (org-beginning-of-item)
7505 (setq beg0 (point))
7506 (save-excursion
7507 (setq ne-beg (org-back-over-empty-lines))
7508 (setq beg (point)))
7509 (goto-char beg0)
7510 (setq ind (org-get-indentation))
7511 (org-end-of-item)
7512 (setq end0 (point))
7513 (setq ind1 (org-get-indentation))
7514 (setq ne-end (org-back-over-empty-lines))
7515 (setq end (point))
7516 (goto-char beg0)
7517 (when (and (org-first-list-item-p) (< ne-end ne-beg))
7518 ;; include less whitespace
7519 (save-excursion
7520 (goto-char beg)
7521 (forward-line (- ne-beg ne-end))
7522 (setq beg (point))))
7523 (goto-char end0)
7524 (if (and (org-at-item-p) (= ind ind1))
7525 (progn
7526 (org-end-of-item)
7527 (org-back-over-empty-lines)
7528 (setq txt (buffer-substring beg end))
7529 (save-excursion
7530 (delete-region beg end))
7531 (setq pos (point))
7532 (insert txt)
7533 (goto-char pos) (org-skip-whitespace)
7534 (org-maybe-renumber-ordered-list))
7535 (goto-char pos)
7536 (error "Cannot move this item further down"))))
7538 (defun org-move-item-up (arg)
7539 "Move the plain list item at point up, i.e. swap with previous item.
7540 Subitems (items with larger indentation) are considered part of the item,
7541 so this really moves item trees."
7542 (interactive "p")
7543 (let (beg beg0 end ind ind1 (pos (point)) txt
7544 ne-beg ne-ins ins-end)
7545 (org-beginning-of-item)
7546 (setq beg0 (point))
7547 (setq ind (org-get-indentation))
7548 (save-excursion
7549 (setq ne-beg (org-back-over-empty-lines))
7550 (setq beg (point)))
7551 (goto-char beg0)
7552 (org-end-of-item)
7553 (setq end (point))
7554 (goto-char beg0)
7555 (catch 'exit
7556 (while t
7557 (beginning-of-line 0)
7558 (if (looking-at "[ \t]*$")
7559 (if org-empty-line-terminates-plain-lists
7560 (progn
7561 (goto-char pos)
7562 (error "Cannot move this item further up"))
7563 nil)
7564 (if (<= (setq ind1 (org-get-indentation)) ind)
7565 (throw 'exit t)))))
7566 (condition-case nil
7567 (org-beginning-of-item)
7568 (error (goto-char beg)
7569 (error "Cannot move this item further up")))
7570 (setq ind1 (org-get-indentation))
7571 (if (and (org-at-item-p) (= ind ind1))
7572 (progn
7573 (setq ne-ins (org-back-over-empty-lines))
7574 (setq txt (buffer-substring beg end))
7575 (save-excursion
7576 (delete-region beg end))
7577 (setq pos (point))
7578 (insert txt)
7579 (setq ins-end (point))
7580 (goto-char pos) (org-skip-whitespace)
7582 (when (and (org-first-list-item-p) (> ne-ins ne-beg))
7583 ;; Move whitespace back to beginning
7584 (save-excursion
7585 (goto-char ins-end)
7586 (let ((kill-whole-line t))
7587 (kill-line (- ne-ins ne-beg)) (point)))
7588 (insert (make-string (- ne-ins ne-beg) ?\n)))
7590 (org-maybe-renumber-ordered-list))
7591 (goto-char pos)
7592 (error "Cannot move this item further up"))))
7594 (defun org-maybe-renumber-ordered-list ()
7595 "Renumber the ordered list at point if setup allows it.
7596 This tests the user option `org-auto-renumber-ordered-lists' before
7597 doing the renumbering."
7598 (interactive)
7599 (when (and org-auto-renumber-ordered-lists
7600 (org-at-item-p))
7601 (if (match-beginning 3)
7602 (org-renumber-ordered-list 1)
7603 (org-fix-bullet-type))))
7605 (defun org-maybe-renumber-ordered-list-safe ()
7606 (condition-case nil
7607 (save-excursion
7608 (org-maybe-renumber-ordered-list))
7609 (error nil)))
7611 (defun org-cycle-list-bullet (&optional which)
7612 "Cycle through the different itemize/enumerate bullets.
7613 This cycle the entire list level through the sequence:
7615 `-' -> `+' -> `*' -> `1.' -> `1)'
7617 If WHICH is a string, use that as the new bullet. If WHICH is an integer,
7618 0 meand `-', 1 means `+' etc."
7619 (interactive "P")
7620 (org-preserve-lc
7621 (org-beginning-of-item-list)
7622 (org-at-item-p)
7623 (beginning-of-line 1)
7624 (let ((current (match-string 0))
7625 (prevp (eq which 'previous))
7626 new)
7627 (setq new (cond
7628 ((and (numberp which)
7629 (nth (1- which) '("-" "+" "*" "1." "1)"))))
7630 ((string-match "-" current) (if prevp "1)" "+"))
7631 ((string-match "\\+" current)
7632 (if prevp "-" (if (looking-at "\\S-") "1." "*")))
7633 ((string-match "\\*" current) (if prevp "+" "1."))
7634 ((string-match "\\." current) (if prevp "*" "1)"))
7635 ((string-match ")" current) (if prevp "1." "-"))
7636 (t (error "This should not happen"))))
7637 (and (looking-at "\\([ \t]*\\)\\S-+") (replace-match (concat "\\1" new)))
7638 (org-fix-bullet-type)
7639 (org-maybe-renumber-ordered-list))))
7641 (defun org-get-string-indentation (s)
7642 "What indentation has S due to SPACE and TAB at the beginning of the string?"
7643 (let ((n -1) (i 0) (w tab-width) c)
7644 (catch 'exit
7645 (while (< (setq n (1+ n)) (length s))
7646 (setq c (aref s n))
7647 (cond ((= c ?\ ) (setq i (1+ i)))
7648 ((= c ?\t) (setq i (* (/ (+ w i) w) w)))
7649 (t (throw 'exit t)))))
7652 (defun org-renumber-ordered-list (arg)
7653 "Renumber an ordered plain list.
7654 Cursor needs to be in the first line of an item, the line that starts
7655 with something like \"1.\" or \"2)\"."
7656 (interactive "p")
7657 (unless (and (org-at-item-p)
7658 (match-beginning 3))
7659 (error "This is not an ordered list"))
7660 (let ((line (org-current-line))
7661 (col (current-column))
7662 (ind (org-get-string-indentation
7663 (buffer-substring (point-at-bol) (match-beginning 3))))
7664 ;; (term (substring (match-string 3) -1))
7665 ind1 (n (1- arg))
7666 fmt)
7667 ;; find where this list begins
7668 (org-beginning-of-item-list)
7669 (looking-at "[ \t]*[0-9]+\\([.)]\\)")
7670 (setq fmt (concat "%d" (match-string 1)))
7671 (beginning-of-line 0)
7672 ;; walk forward and replace these numbers
7673 (catch 'exit
7674 (while t
7675 (catch 'next
7676 (beginning-of-line 2)
7677 (if (eobp) (throw 'exit nil))
7678 (if (looking-at "[ \t]*$") (throw 'next nil))
7679 (skip-chars-forward " \t") (setq ind1 (current-column))
7680 (if (> ind1 ind) (throw 'next t))
7681 (if (< ind1 ind) (throw 'exit t))
7682 (if (not (org-at-item-p)) (throw 'exit nil))
7683 (delete-region (match-beginning 2) (match-end 2))
7684 (goto-char (match-beginning 2))
7685 (insert (format fmt (setq n (1+ n)))))))
7686 (goto-line line)
7687 (move-to-column col)))
7689 (defun org-fix-bullet-type ()
7690 "Make sure all items in this list have the same bullet as the firsst item."
7691 (interactive)
7692 (unless (org-at-item-p) (error "This is not a list"))
7693 (let ((line (org-current-line))
7694 (col (current-column))
7695 (ind (current-indentation))
7696 ind1 bullet)
7697 ;; find where this list begins
7698 (org-beginning-of-item-list)
7699 (beginning-of-line 1)
7700 ;; find out what the bullet type is
7701 (looking-at "[ \t]*\\(\\S-+\\)")
7702 (setq bullet (match-string 1))
7703 ;; walk forward and replace these numbers
7704 (beginning-of-line 0)
7705 (catch 'exit
7706 (while t
7707 (catch 'next
7708 (beginning-of-line 2)
7709 (if (eobp) (throw 'exit nil))
7710 (if (looking-at "[ \t]*$") (throw 'next nil))
7711 (skip-chars-forward " \t") (setq ind1 (current-column))
7712 (if (> ind1 ind) (throw 'next t))
7713 (if (< ind1 ind) (throw 'exit t))
7714 (if (not (org-at-item-p)) (throw 'exit nil))
7715 (skip-chars-forward " \t")
7716 (looking-at "\\S-+")
7717 (replace-match bullet))))
7718 (goto-line line)
7719 (move-to-column col)
7720 (if (string-match "[0-9]" bullet)
7721 (org-renumber-ordered-list 1))))
7723 (defun org-beginning-of-item-list ()
7724 "Go to the beginning of the current item list.
7725 I.e. to the first item in this list."
7726 (interactive)
7727 (org-beginning-of-item)
7728 (let ((pos (point-at-bol))
7729 (ind (org-get-indentation))
7730 ind1)
7731 ;; find where this list begins
7732 (catch 'exit
7733 (while t
7734 (catch 'next
7735 (beginning-of-line 0)
7736 (if (looking-at "[ \t]*$")
7737 (throw (if (bobp) 'exit 'next) t))
7738 (skip-chars-forward " \t") (setq ind1 (current-column))
7739 (if (or (< ind1 ind)
7740 (and (= ind1 ind)
7741 (not (org-at-item-p)))
7742 (bobp))
7743 (throw 'exit t)
7744 (when (org-at-item-p) (setq pos (point-at-bol)))))))
7745 (goto-char pos)))
7748 (defun org-end-of-item-list ()
7749 "Go to the end of the current item list.
7750 I.e. to the text after the last item."
7751 (interactive)
7752 (org-beginning-of-item)
7753 (let ((pos (point-at-bol))
7754 (ind (org-get-indentation))
7755 ind1)
7756 ;; find where this list begins
7757 (catch 'exit
7758 (while t
7759 (catch 'next
7760 (beginning-of-line 2)
7761 (if (looking-at "[ \t]*$")
7762 (throw (if (eobp) 'exit 'next) t))
7763 (skip-chars-forward " \t") (setq ind1 (current-column))
7764 (if (or (< ind1 ind)
7765 (and (= ind1 ind)
7766 (not (org-at-item-p)))
7767 (eobp))
7768 (progn
7769 (setq pos (point-at-bol))
7770 (throw 'exit t))))))
7771 (goto-char pos)))
7774 (defvar org-last-indent-begin-marker (make-marker))
7775 (defvar org-last-indent-end-marker (make-marker))
7777 (defun org-outdent-item (arg)
7778 "Outdent a local list item."
7779 (interactive "p")
7780 (org-indent-item (- arg)))
7782 (defun org-indent-item (arg)
7783 "Indent a local list item."
7784 (interactive "p")
7785 (unless (org-at-item-p)
7786 (error "Not on an item"))
7787 (save-excursion
7788 (let (beg end ind ind1 tmp delta ind-down ind-up)
7789 (if (memq last-command '(org-shiftmetaright org-shiftmetaleft))
7790 (setq beg org-last-indent-begin-marker
7791 end org-last-indent-end-marker)
7792 (org-beginning-of-item)
7793 (setq beg (move-marker org-last-indent-begin-marker (point)))
7794 (org-end-of-item)
7795 (setq end (move-marker org-last-indent-end-marker (point))))
7796 (goto-char beg)
7797 (setq tmp (org-item-indent-positions)
7798 ind (car tmp)
7799 ind-down (nth 2 tmp)
7800 ind-up (nth 1 tmp)
7801 delta (if (> arg 0)
7802 (if ind-down (- ind-down ind) 2)
7803 (if ind-up (- ind-up ind) -2)))
7804 (if (< (+ delta ind) 0) (error "Cannot outdent beyond margin"))
7805 (while (< (point) end)
7806 (beginning-of-line 1)
7807 (skip-chars-forward " \t") (setq ind1 (current-column))
7808 (delete-region (point-at-bol) (point))
7809 (or (eolp) (indent-to-column (+ ind1 delta)))
7810 (beginning-of-line 2))))
7811 (org-fix-bullet-type)
7812 (org-maybe-renumber-ordered-list-safe)
7813 (save-excursion
7814 (beginning-of-line 0)
7815 (condition-case nil (org-beginning-of-item) (error nil))
7816 (org-maybe-renumber-ordered-list-safe)))
7818 (defun org-item-indent-positions ()
7819 "Return indentation for plain list items.
7820 This returns a list with three values: The current indentation, the
7821 parent indentation and the indentation a child should habe.
7822 Assumes cursor in item line."
7823 (let* ((bolpos (point-at-bol))
7824 (ind (org-get-indentation))
7825 ind-down ind-up pos)
7826 (save-excursion
7827 (org-beginning-of-item-list)
7828 (skip-chars-backward "\n\r \t")
7829 (when (org-in-item-p)
7830 (org-beginning-of-item)
7831 (setq ind-up (org-get-indentation))))
7832 (setq pos (point))
7833 (save-excursion
7834 (cond
7835 ((and (condition-case nil (progn (org-previous-item) t)
7836 (error nil))
7837 (or (forward-char 1) t)
7838 (re-search-forward "^\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)" bolpos t))
7839 (setq ind-down (org-get-indentation)))
7840 ((and (goto-char pos)
7841 (org-at-item-p))
7842 (goto-char (match-end 0))
7843 (skip-chars-forward " \t")
7844 (setq ind-down (current-column)))))
7845 (list ind ind-up ind-down)))
7847 ;;; The orgstruct minor mode
7849 ;; Define a minor mode which can be used in other modes in order to
7850 ;; integrate the org-mode structure editing commands.
7852 ;; This is really a hack, because the org-mode structure commands use
7853 ;; keys which normally belong to the major mode. Here is how it
7854 ;; works: The minor mode defines all the keys necessary to operate the
7855 ;; structure commands, but wraps the commands into a function which
7856 ;; tests if the cursor is currently at a headline or a plain list
7857 ;; item. If that is the case, the structure command is used,
7858 ;; temporarily setting many Org-mode variables like regular
7859 ;; expressions for filling etc. However, when any of those keys is
7860 ;; used at a different location, function uses `key-binding' to look
7861 ;; up if the key has an associated command in another currently active
7862 ;; keymap (minor modes, major mode, global), and executes that
7863 ;; command. There might be problems if any of the keys is otherwise
7864 ;; used as a prefix key.
7866 ;; Another challenge is that the key binding for TAB can be tab or \C-i,
7867 ;; likewise the binding for RET can be return or \C-m. Orgtbl-mode
7868 ;; addresses this by checking explicitly for both bindings.
7870 (defvar orgstruct-mode-map (make-sparse-keymap)
7871 "Keymap for the minor `orgstruct-mode'.")
7873 (defvar org-local-vars nil
7874 "List of local variables, for use by `orgstruct-mode'")
7876 ;;;###autoload
7877 (define-minor-mode orgstruct-mode
7878 "Toggle the minor more `orgstruct-mode'.
7879 This mode is for using Org-mode structure commands in other modes.
7880 The following key behave as if Org-mode was active, if the cursor
7881 is on a headline, or on a plain list item (both in the definition
7882 of Org-mode).
7884 M-up Move entry/item up
7885 M-down Move entry/item down
7886 M-left Promote
7887 M-right Demote
7888 M-S-up Move entry/item up
7889 M-S-down Move entry/item down
7890 M-S-left Promote subtree
7891 M-S-right Demote subtree
7892 M-q Fill paragraph and items like in Org-mode
7893 C-c ^ Sort entries
7894 C-c - Cycle list bullet
7895 TAB Cycle item visibility
7896 M-RET Insert new heading/item
7897 S-M-RET Insert new TODO heading / Chekbox item
7898 C-c C-c Set tags / toggle checkbox"
7899 nil " OrgStruct" nil
7900 (org-load-modules-maybe)
7901 (and (orgstruct-setup) (defun orgstruct-setup () nil)))
7903 ;;;###autoload
7904 (defun turn-on-orgstruct ()
7905 "Unconditionally turn on `orgstruct-mode'."
7906 (orgstruct-mode 1))
7908 ;;;###autoload
7909 (defun turn-on-orgstruct++ ()
7910 "Unconditionally turn on `orgstruct-mode', and force org-mode indentations.
7911 In addition to setting orgstruct-mode, this also exports all indentation and
7912 autofilling variables from org-mode into the buffer. Note that turning
7913 off orgstruct-mode will *not* remove these additional settings."
7914 (orgstruct-mode 1)
7915 (let (var val)
7916 (mapc
7917 (lambda (x)
7918 (when (string-match
7919 "^\\(paragraph-\\|auto-fill\\|fill-paragraph\\|adaptive-fill\\|indent-\\)"
7920 (symbol-name (car x)))
7921 (setq var (car x) val (nth 1 x))
7922 (org-set-local var (if (eq (car-safe val) 'quote) (nth 1 val) val))))
7923 org-local-vars)))
7925 (defun orgstruct-error ()
7926 "Error when there is no default binding for a structure key."
7927 (interactive)
7928 (error "This key has no function outside structure elements"))
7930 (defun orgstruct-setup ()
7931 "Setup orgstruct keymaps."
7932 (let ((nfunc 0)
7933 (bindings
7934 (list
7935 '([(meta up)] org-metaup)
7936 '([(meta down)] org-metadown)
7937 '([(meta left)] org-metaleft)
7938 '([(meta right)] org-metaright)
7939 '([(meta shift up)] org-shiftmetaup)
7940 '([(meta shift down)] org-shiftmetadown)
7941 '([(meta shift left)] org-shiftmetaleft)
7942 '([(meta shift right)] org-shiftmetaright)
7943 '([(shift up)] org-shiftup)
7944 '([(shift down)] org-shiftdown)
7945 '("\C-c\C-c" org-ctrl-c-ctrl-c)
7946 '("\M-q" fill-paragraph)
7947 '("\C-c^" org-sort)
7948 '("\C-c-" org-cycle-list-bullet)))
7949 elt key fun cmd)
7950 (while (setq elt (pop bindings))
7951 (setq nfunc (1+ nfunc))
7952 (setq key (org-key (car elt))
7953 fun (nth 1 elt)
7954 cmd (orgstruct-make-binding fun nfunc key))
7955 (org-defkey orgstruct-mode-map key cmd))
7957 ;; Special treatment needed for TAB and RET
7958 (org-defkey orgstruct-mode-map [(tab)]
7959 (orgstruct-make-binding 'org-cycle 102 [(tab)] "\C-i"))
7960 (org-defkey orgstruct-mode-map "\C-i"
7961 (orgstruct-make-binding 'org-cycle 103 "\C-i" [(tab)]))
7963 (org-defkey orgstruct-mode-map "\M-\C-m"
7964 (orgstruct-make-binding 'org-insert-heading 105
7965 "\M-\C-m" [(meta return)]))
7966 (org-defkey orgstruct-mode-map [(meta return)]
7967 (orgstruct-make-binding 'org-insert-heading 106
7968 [(meta return)] "\M-\C-m"))
7970 (org-defkey orgstruct-mode-map [(shift meta return)]
7971 (orgstruct-make-binding 'org-insert-todo-heading 107
7972 [(meta return)] "\M-\C-m"))
7974 (unless org-local-vars
7975 (setq org-local-vars (org-get-local-variables)))
7979 (defun orgstruct-make-binding (fun n &rest keys)
7980 "Create a function for binding in the structure minor mode.
7981 FUN is the command to call inside a table. N is used to create a unique
7982 command name. KEYS are keys that should be checked in for a command
7983 to execute outside of tables."
7984 (eval
7985 (list 'defun
7986 (intern (concat "orgstruct-hijacker-command-" (int-to-string n)))
7987 '(arg)
7988 (concat "In Structure, run `" (symbol-name fun) "'.\n"
7989 "Outside of structure, run the binding of `"
7990 (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
7991 "'.")
7992 '(interactive "p")
7993 (list 'if
7994 '(org-context-p 'headline 'item)
7995 (list 'org-run-like-in-org-mode (list 'quote fun))
7996 (list 'let '(orgstruct-mode)
7997 (list 'call-interactively
7998 (append '(or)
7999 (mapcar (lambda (k)
8000 (list 'key-binding k))
8001 keys)
8002 '('orgstruct-error))))))))
8004 (defun org-context-p (&rest contexts)
8005 "Check if local context is and of CONTEXTS.
8006 Possible values in the list of contexts are `table', `headline', and `item'."
8007 (let ((pos (point)))
8008 (goto-char (point-at-bol))
8009 (prog1 (or (and (memq 'table contexts)
8010 (looking-at "[ \t]*|"))
8011 (and (memq 'headline contexts)
8012 (looking-at "\\*+"))
8013 (and (memq 'item contexts)
8014 (looking-at "[ \t]*\\([-+*] \\|[0-9]+[.)] \\)")))
8015 (goto-char pos))))
8017 (defun org-get-local-variables ()
8018 "Return a list of all local variables in an org-mode buffer."
8019 (let (varlist)
8020 (with-current-buffer (get-buffer-create "*Org tmp*")
8021 (erase-buffer)
8022 (org-mode)
8023 (setq varlist (buffer-local-variables)))
8024 (kill-buffer "*Org tmp*")
8025 (delq nil
8026 (mapcar
8027 (lambda (x)
8028 (setq x
8029 (if (symbolp x)
8030 (list x)
8031 (list (car x) (list 'quote (cdr x)))))
8032 (if (string-match
8033 "^\\(org-\\|orgtbl-\\|outline-\\|comment-\\|paragraph-\\|auto-fill\\|fill-paragraph\\|adaptive-fill\\|indent-\\)"
8034 (symbol-name (car x)))
8035 x nil))
8036 varlist))))
8038 ;;;###autoload
8039 (defun org-run-like-in-org-mode (cmd)
8040 (org-load-modules-maybe)
8041 (unless org-local-vars
8042 (setq org-local-vars (org-get-local-variables)))
8043 (eval (list 'let org-local-vars
8044 (list 'call-interactively (list 'quote cmd)))))
8046 ;;;; Archiving
8048 (defalias 'org-advertized-archive-subtree 'org-archive-subtree)
8050 (defun org-archive-subtree (&optional find-done)
8051 "Move the current subtree to the archive.
8052 The archive can be a certain top-level heading in the current file, or in
8053 a different file. The tree will be moved to that location, the subtree
8054 heading be marked DONE, and the current time will be added.
8056 When called with prefix argument FIND-DONE, find whole trees without any
8057 open TODO items and archive them (after getting confirmation from the user).
8058 If the cursor is not at a headline when this comand is called, try all level
8059 1 trees. If the cursor is on a headline, only try the direct children of
8060 this heading."
8061 (interactive "P")
8062 (if find-done
8063 (org-archive-all-done)
8064 ;; Save all relevant TODO keyword-relatex variables
8066 (let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler
8067 (tr-org-todo-keywords-1 org-todo-keywords-1)
8068 (tr-org-todo-kwd-alist org-todo-kwd-alist)
8069 (tr-org-done-keywords org-done-keywords)
8070 (tr-org-todo-regexp org-todo-regexp)
8071 (tr-org-todo-line-regexp org-todo-line-regexp)
8072 (tr-org-odd-levels-only org-odd-levels-only)
8073 (this-buffer (current-buffer))
8074 (org-archive-location org-archive-location)
8075 (re "^#\\+ARCHIVE:[ \t]+\\(\\S-.*\\S-\\)[ \t]*$")
8076 ;; start of variables that will be used for saving context
8077 ;; The compiler complains about them - keep them anyway!
8078 (file (abbreviate-file-name (buffer-file-name)))
8079 (olpath (mapconcat 'identity (org-get-outline-path) "/"))
8080 (time (format-time-string
8081 (substring (cdr org-time-stamp-formats) 1 -1)
8082 (current-time)))
8083 afile heading buffer level newfile-p
8084 category todo priority
8085 ;; start of variables that will be used for savind context
8086 ltags itags prop)
8088 ;; Try to find a local archive location
8089 (save-excursion
8090 (save-restriction
8091 (widen)
8092 (setq prop (org-entry-get nil "ARCHIVE" 'inherit))
8093 (if (and prop (string-match "\\S-" prop))
8094 (setq org-archive-location prop)
8095 (if (or (re-search-backward re nil t)
8096 (re-search-forward re nil t))
8097 (setq org-archive-location (match-string 1))))))
8099 (if (string-match "\\(.*\\)::\\(.*\\)" org-archive-location)
8100 (progn
8101 (setq afile (format (match-string 1 org-archive-location)
8102 (file-name-nondirectory buffer-file-name))
8103 heading (match-string 2 org-archive-location)))
8104 (error "Invalid `org-archive-location'"))
8105 (if (> (length afile) 0)
8106 (setq newfile-p (not (file-exists-p afile))
8107 buffer (find-file-noselect afile))
8108 (setq buffer (current-buffer)))
8109 (unless buffer
8110 (error "Cannot access file \"%s\"" afile))
8111 (if (and (> (length heading) 0)
8112 (string-match "^\\*+" heading))
8113 (setq level (match-end 0))
8114 (setq heading nil level 0))
8115 (save-excursion
8116 (org-back-to-heading t)
8117 ;; Get context information that will be lost by moving the tree
8118 (org-refresh-category-properties)
8119 (setq category (org-get-category)
8120 todo (and (looking-at org-todo-line-regexp)
8121 (match-string 2))
8122 priority (org-get-priority (if (match-end 3) (match-string 3) ""))
8123 ltags (org-get-tags)
8124 itags (org-delete-all ltags (org-get-tags-at)))
8125 (setq ltags (mapconcat 'identity ltags " ")
8126 itags (mapconcat 'identity itags " "))
8127 ;; We first only copy, in case something goes wrong
8128 ;; we need to protect this-command, to avoid kill-region sets it,
8129 ;; which would lead to duplication of subtrees
8130 (let (this-command) (org-copy-subtree))
8131 (set-buffer buffer)
8132 ;; Enforce org-mode for the archive buffer
8133 (if (not (org-mode-p))
8134 ;; Force the mode for future visits.
8135 (let ((org-insert-mode-line-in-empty-file t)
8136 (org-inhibit-startup t))
8137 (call-interactively 'org-mode)))
8138 (when newfile-p
8139 (goto-char (point-max))
8140 (insert (format "\nArchived entries from file %s\n\n"
8141 (buffer-file-name this-buffer))))
8142 ;; Force the TODO keywords of the original buffer
8143 (let ((org-todo-line-regexp tr-org-todo-line-regexp)
8144 (org-todo-keywords-1 tr-org-todo-keywords-1)
8145 (org-todo-kwd-alist tr-org-todo-kwd-alist)
8146 (org-done-keywords tr-org-done-keywords)
8147 (org-todo-regexp tr-org-todo-regexp)
8148 (org-todo-line-regexp tr-org-todo-line-regexp)
8149 (org-odd-levels-only
8150 (if (local-variable-p 'org-odd-levels-only (current-buffer))
8151 org-odd-levels-only
8152 tr-org-odd-levels-only)))
8153 (goto-char (point-min))
8154 (show-all)
8155 (if heading
8156 (progn
8157 (if (re-search-forward
8158 (concat "^" (regexp-quote heading)
8159 (org-re "[ \t]*\\(:[[:alnum:]_@:]+:\\)?[ \t]*\\($\\|\r\\)"))
8160 nil t)
8161 (goto-char (match-end 0))
8162 ;; Heading not found, just insert it at the end
8163 (goto-char (point-max))
8164 (or (bolp) (insert "\n"))
8165 (insert "\n" heading "\n")
8166 (end-of-line 0))
8167 ;; Make the subtree visible
8168 (show-subtree)
8169 (org-end-of-subtree t)
8170 (skip-chars-backward " \t\r\n")
8171 (and (looking-at "[ \t\r\n]*")
8172 (replace-match "\n\n")))
8173 ;; No specific heading, just go to end of file.
8174 (goto-char (point-max)) (insert "\n"))
8175 ;; Paste
8176 (org-paste-subtree (org-get-valid-level level 1))
8178 ;; Mark the entry as done
8179 (when (and org-archive-mark-done
8180 (looking-at org-todo-line-regexp)
8181 (or (not (match-end 2))
8182 (not (member (match-string 2) org-done-keywords))))
8183 (let (org-log-done org-todo-log-states)
8184 (org-todo
8185 (car (or (member org-archive-mark-done org-done-keywords)
8186 org-done-keywords)))))
8188 ;; Add the context info
8189 (when org-archive-save-context-info
8190 (let ((l org-archive-save-context-info) e n v)
8191 (while (setq e (pop l))
8192 (when (and (setq v (symbol-value e))
8193 (stringp v) (string-match "\\S-" v))
8194 (setq n (concat "ARCHIVE_" (upcase (symbol-name e))))
8195 (org-entry-put (point) n v)))))
8197 ;; Save and kill the buffer, if it is not the same buffer.
8198 (if (not (eq this-buffer buffer))
8199 (progn (save-buffer) (kill-buffer buffer)))))
8200 ;; Here we are back in the original buffer. Everything seems to have
8201 ;; worked. So now cut the tree and finish up.
8202 (let (this-command) (org-cut-subtree))
8203 (if (and (not (eobp)) (looking-at "[ \t]*$")) (kill-line))
8204 (message "Subtree archived %s"
8205 (if (eq this-buffer buffer)
8206 (concat "under heading: " heading)
8207 (concat "in file: " (abbreviate-file-name afile)))))))
8209 (defun org-refresh-category-properties ()
8210 "Refresh category text properties in teh buffer."
8211 (let ((def-cat (cond
8212 ((null org-category)
8213 (if buffer-file-name
8214 (file-name-sans-extension
8215 (file-name-nondirectory buffer-file-name))
8216 "???"))
8217 ((symbolp org-category) (symbol-name org-category))
8218 (t org-category)))
8219 beg end cat pos optionp)
8220 (org-unmodified
8221 (save-excursion
8222 (save-restriction
8223 (widen)
8224 (goto-char (point-min))
8225 (put-text-property (point) (point-max) 'org-category def-cat)
8226 (while (re-search-forward
8227 "^\\(#\\+CATEGORY:\\|[ \t]*:CATEGORY:\\)\\(.*\\)" nil t)
8228 (setq pos (match-end 0)
8229 optionp (equal (char-after (match-beginning 0)) ?#)
8230 cat (org-trim (match-string 2)))
8231 (if optionp
8232 (setq beg (point-at-bol) end (point-max))
8233 (org-back-to-heading t)
8234 (setq beg (point) end (org-end-of-subtree t t)))
8235 (put-text-property beg end 'org-category cat)
8236 (goto-char pos)))))))
8238 (defun org-archive-all-done (&optional tag)
8239 "Archive sublevels of the current tree without open TODO items.
8240 If the cursor is not on a headline, try all level 1 trees. If
8241 it is on a headline, try all direct children.
8242 When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag."
8243 (let ((re (concat "^\\*+ +" org-not-done-regexp)) re1
8244 (rea (concat ".*:" org-archive-tag ":"))
8245 (begm (make-marker))
8246 (endm (make-marker))
8247 (question (if tag "Set ARCHIVE tag (no open TODO items)? "
8248 "Move subtree to archive (no open TODO items)? "))
8249 beg end (cntarch 0))
8250 (if (org-on-heading-p)
8251 (progn
8252 (setq re1 (concat "^" (regexp-quote
8253 (make-string
8254 (1+ (- (match-end 0) (match-beginning 0) 1))
8255 ?*))
8256 " "))
8257 (move-marker begm (point))
8258 (move-marker endm (org-end-of-subtree t)))
8259 (setq re1 "^* ")
8260 (move-marker begm (point-min))
8261 (move-marker endm (point-max)))
8262 (save-excursion
8263 (goto-char begm)
8264 (while (re-search-forward re1 endm t)
8265 (setq beg (match-beginning 0)
8266 end (save-excursion (org-end-of-subtree t) (point)))
8267 (goto-char beg)
8268 (if (re-search-forward re end t)
8269 (goto-char end)
8270 (goto-char beg)
8271 (if (and (or (not tag) (not (looking-at rea)))
8272 (y-or-n-p question))
8273 (progn
8274 (if tag
8275 (org-toggle-tag org-archive-tag 'on)
8276 (org-archive-subtree))
8277 (setq cntarch (1+ cntarch)))
8278 (goto-char end)))))
8279 (message "%d trees archived" cntarch)))
8281 (defun org-cycle-hide-drawers (state)
8282 "Re-hide all drawers after a visibility state change."
8283 (when (and (org-mode-p)
8284 (not (memq state '(overview folded))))
8285 (save-excursion
8286 (let* ((globalp (memq state '(contents all)))
8287 (beg (if globalp (point-min) (point)))
8288 (end (if globalp (point-max) (org-end-of-subtree t))))
8289 (goto-char beg)
8290 (while (re-search-forward org-drawer-regexp end t)
8291 (org-flag-drawer t))))))
8293 (defun org-flag-drawer (flag)
8294 (save-excursion
8295 (beginning-of-line 1)
8296 (when (looking-at "^[ \t]*:[a-zA-Z][a-zA-Z0-9]*:")
8297 (let ((b (match-end 0))
8298 (outline-regexp org-outline-regexp))
8299 (if (re-search-forward
8300 "^[ \t]*:END:"
8301 (save-excursion (outline-next-heading) (point)) t)
8302 (outline-flag-region b (point-at-eol) flag)
8303 (error ":END: line missing"))))))
8305 (defun org-cycle-hide-archived-subtrees (state)
8306 "Re-hide all archived subtrees after a visibility state change."
8307 (when (and (not org-cycle-open-archived-trees)
8308 (not (memq state '(overview folded))))
8309 (save-excursion
8310 (let* ((globalp (memq state '(contents all)))
8311 (beg (if globalp (point-min) (point)))
8312 (end (if globalp (point-max) (org-end-of-subtree t))))
8313 (org-hide-archived-subtrees beg end)
8314 (goto-char beg)
8315 (if (looking-at (concat ".*:" org-archive-tag ":"))
8316 (message "%s" (substitute-command-keys
8317 "Subtree is archived and stays closed. Use \\[org-force-cycle-archived] to cycle it anyway.")))))))
8319 (defun org-force-cycle-archived ()
8320 "Cycle subtree even if it is archived."
8321 (interactive)
8322 (setq this-command 'org-cycle)
8323 (let ((org-cycle-open-archived-trees t))
8324 (call-interactively 'org-cycle)))
8326 (defun org-hide-archived-subtrees (beg end)
8327 "Re-hide all archived subtrees after a visibility state change."
8328 (save-excursion
8329 (let* ((re (concat ":" org-archive-tag ":")))
8330 (goto-char beg)
8331 (while (re-search-forward re end t)
8332 (and (org-on-heading-p) (hide-subtree))
8333 (org-end-of-subtree t)))))
8335 (defun org-toggle-tag (tag &optional onoff)
8336 "Toggle the tag TAG for the current line.
8337 If ONOFF is `on' or `off', don't toggle but set to this state."
8338 (unless (org-on-heading-p t) (error "Not on headling"))
8339 (let (res current)
8340 (save-excursion
8341 (beginning-of-line)
8342 (if (re-search-forward (org-re "[ \t]:\\([[:alnum:]_@:]+\\):[ \t]*$")
8343 (point-at-eol) t)
8344 (progn
8345 (setq current (match-string 1))
8346 (replace-match ""))
8347 (setq current ""))
8348 (setq current (nreverse (org-split-string current ":")))
8349 (cond
8350 ((eq onoff 'on)
8351 (setq res t)
8352 (or (member tag current) (push tag current)))
8353 ((eq onoff 'off)
8354 (or (not (member tag current)) (setq current (delete tag current))))
8355 (t (if (member tag current)
8356 (setq current (delete tag current))
8357 (setq res t)
8358 (push tag current))))
8359 (end-of-line 1)
8360 (if current
8361 (progn
8362 (insert " :" (mapconcat 'identity (nreverse current) ":") ":")
8363 (org-set-tags nil t))
8364 (delete-horizontal-space))
8365 (run-hooks 'org-after-tags-change-hook))
8366 res))
8368 (defun org-toggle-archive-tag (&optional arg)
8369 "Toggle the archive tag for the current headline.
8370 With prefix ARG, check all children of current headline and offer tagging
8371 the children that do not contain any open TODO items."
8372 (interactive "P")
8373 (if arg
8374 (org-archive-all-done 'tag)
8375 (let (set)
8376 (save-excursion
8377 (org-back-to-heading t)
8378 (setq set (org-toggle-tag org-archive-tag))
8379 (when set (hide-subtree)))
8380 (and set (beginning-of-line 1))
8381 (message "Subtree %s" (if set "archived" "unarchived")))))
8384 ;;;; Tables
8386 ;;; The table editor
8388 ;; Watch out: Here we are talking about two different kind of tables.
8389 ;; Most of the code is for the tables created with the Org-mode table editor.
8390 ;; Sometimes, we talk about tables created and edited with the table.el
8391 ;; Emacs package. We call the former org-type tables, and the latter
8392 ;; table.el-type tables.
8394 (defun org-before-change-function (beg end)
8395 "Every change indicates that a table might need an update."
8396 (setq org-table-may-need-update t))
8398 (defconst org-table-line-regexp "^[ \t]*|"
8399 "Detects an org-type table line.")
8400 (defconst org-table-dataline-regexp "^[ \t]*|[^-]"
8401 "Detects an org-type table line.")
8402 (defconst org-table-auto-recalculate-regexp "^[ \t]*| *# *\\(|\\|$\\)"
8403 "Detects a table line marked for automatic recalculation.")
8404 (defconst org-table-recalculate-regexp "^[ \t]*| *[#*] *\\(|\\|$\\)"
8405 "Detects a table line marked for automatic recalculation.")
8406 (defconst org-table-calculate-mark-regexp "^[ \t]*| *[!$^_#*] *\\(|\\|$\\)"
8407 "Detects a table line marked for automatic recalculation.")
8408 (defconst org-table-hline-regexp "^[ \t]*|-"
8409 "Detects an org-type table hline.")
8410 (defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]"
8411 "Detects a table-type table hline.")
8412 (defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)"
8413 "Detects an org-type or table-type table.")
8414 (defconst org-table-border-regexp "^[ \t]*[^| \t]"
8415 "Searching from within a table (any type) this finds the first line
8416 outside the table.")
8417 (defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]"
8418 "Searching from within a table (any type) this finds the first line
8419 outside the table.")
8421 (defvar org-table-last-highlighted-reference nil)
8422 (defvar org-table-formula-history nil)
8424 (defvar org-table-column-names nil
8425 "Alist with column names, derived from the `!' line.")
8426 (defvar org-table-column-name-regexp nil
8427 "Regular expression matching the current column names.")
8428 (defvar org-table-local-parameters nil
8429 "Alist with parameter names, derived from the `$' line.")
8430 (defvar org-table-named-field-locations nil
8431 "Alist with locations of named fields.")
8433 (defvar org-table-current-line-types nil
8434 "Table row types, non-nil only for the duration of a comand.")
8435 (defvar org-table-current-begin-line nil
8436 "Table begin line, non-nil only for the duration of a comand.")
8437 (defvar org-table-current-begin-pos nil
8438 "Table begin position, non-nil only for the duration of a comand.")
8439 (defvar org-table-dlines nil
8440 "Vector of data line line numbers in the current table.")
8441 (defvar org-table-hlines nil
8442 "Vector of hline line numbers in the current table.")
8444 (defconst org-table-range-regexp
8445 "@\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\(\\.\\.@?\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\)?"
8446 ;; 1 2 3 4 5
8447 "Regular expression for matching ranges in formulas.")
8449 (defconst org-table-range-regexp2
8450 (concat
8451 "\\(" "@[-0-9I$&]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\|" "\\$[a-zA-Z0-9]+" "\\)"
8452 "\\.\\."
8453 "\\(" "@?[-0-9I$&]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\|" "\\$[a-zA-Z0-9]+" "\\)")
8454 "Match a range for reference display.")
8456 (defconst org-table-translate-regexp
8457 (concat "\\(" "@[-0-9I$]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\)")
8458 "Match a reference that needs translation, for reference display.")
8460 (defvar org-inhibit-highlight-removal nil) ; dynamically scoped param
8462 (defun org-table-create-with-table.el ()
8463 "Use the table.el package to insert a new table.
8464 If there is already a table at point, convert between Org-mode tables
8465 and table.el tables."
8466 (interactive)
8467 (require 'table)
8468 (cond
8469 ((org-at-table.el-p)
8470 (if (y-or-n-p "Convert table to Org-mode table? ")
8471 (org-table-convert)))
8472 ((org-at-table-p)
8473 (if (y-or-n-p "Convert table to table.el table? ")
8474 (org-table-convert)))
8475 (t (call-interactively 'table-insert))))
8477 (defun org-table-create-or-convert-from-region (arg)
8478 "Convert region to table, or create an empty table.
8479 If there is an active region, convert it to a table, using the function
8480 `org-table-convert-region'. See the documentation of that function
8481 to learn how the prefix argument is interpreted to determine the field
8482 separator.
8483 If there is no such region, create an empty table with `org-table-create'."
8484 (interactive "P")
8485 (if (org-region-active-p)
8486 (org-table-convert-region (region-beginning) (region-end) arg)
8487 (org-table-create arg)))
8489 (defun org-table-create (&optional size)
8490 "Query for a size and insert a table skeleton.
8491 SIZE is a string Columns x Rows like for example \"3x2\"."
8492 (interactive "P")
8493 (unless size
8494 (setq size (read-string
8495 (concat "Table size Columns x Rows [e.g. "
8496 org-table-default-size "]: ")
8497 "" nil org-table-default-size)))
8499 (let* ((pos (point))
8500 (indent (make-string (current-column) ?\ ))
8501 (split (org-split-string size " *x *"))
8502 (rows (string-to-number (nth 1 split)))
8503 (columns (string-to-number (car split)))
8504 (line (concat (apply 'concat indent "|" (make-list columns " |"))
8505 "\n")))
8506 (if (string-match "^[ \t]*$" (buffer-substring-no-properties
8507 (point-at-bol) (point)))
8508 (beginning-of-line 1)
8509 (newline))
8510 ;; (mapcar (lambda (x) (insert line)) (make-list rows t))
8511 (dotimes (i rows) (insert line))
8512 (goto-char pos)
8513 (if (> rows 1)
8514 ;; Insert a hline after the first row.
8515 (progn
8516 (end-of-line 1)
8517 (insert "\n|-")
8518 (goto-char pos)))
8519 (org-table-align)))
8521 (defun org-table-convert-region (beg0 end0 &optional separator)
8522 "Convert region to a table.
8523 The region goes from BEG0 to END0, but these borders will be moved
8524 slightly, to make sure a beginning of line in the first line is included.
8526 SEPARATOR specifies the field separator in the lines. It can have the
8527 following values:
8529 '(4) Use the comma as a field separator
8530 '(16) Use a TAB as field separator
8531 integer When a number, use that many spaces as field separator
8532 nil When nil, the command tries to be smart and figure out the
8533 separator in the following way:
8534 - when each line contains a TAB, assume TAB-separated material
8535 - when each line contains a comme, assume CSV material
8536 - else, assume one or more SPACE charcters as separator."
8537 (interactive "rP")
8538 (let* ((beg (min beg0 end0))
8539 (end (max beg0 end0))
8541 (goto-char beg)
8542 (beginning-of-line 1)
8543 (setq beg (move-marker (make-marker) (point)))
8544 (goto-char end)
8545 (if (bolp) (backward-char 1) (end-of-line 1))
8546 (setq end (move-marker (make-marker) (point)))
8547 ;; Get the right field separator
8548 (unless separator
8549 (goto-char beg)
8550 (setq separator
8551 (cond
8552 ((not (re-search-forward "^[^\n\t]+$" end t)) '(16))
8553 ((not (re-search-forward "^[^\n,]+$" end t)) '(4))
8554 (t 1))))
8555 (setq re (cond
8556 ((equal separator '(4)) "^\\|\"?[ \t]*,[ \t]*\"?")
8557 ((equal separator '(16)) "^\\|\t")
8558 ((integerp separator)
8559 (format "^ *\\| *\t *\\| \\{%d,\\}" separator))
8560 (t (error "This should not happen"))))
8561 (goto-char beg)
8562 (while (re-search-forward re end t)
8563 (replace-match "| " t t))
8564 (goto-char beg)
8565 (insert " ")
8566 (org-table-align)))
8568 (defun org-table-import (file arg)
8569 "Import FILE as a table.
8570 The file is assumed to be tab-separated. Such files can be produced by most
8571 spreadsheet and database applications. If no tabs (at least one per line)
8572 are found, lines will be split on whitespace into fields."
8573 (interactive "f\nP")
8574 (or (bolp) (newline))
8575 (let ((beg (point))
8576 (pm (point-max)))
8577 (insert-file-contents file)
8578 (org-table-convert-region beg (+ (point) (- (point-max) pm)) arg)))
8580 (defun org-table-export ()
8581 "Export table as a tab-separated file.
8582 Such a file can be imported into a spreadsheet program like Excel."
8583 (interactive)
8584 (let* ((beg (org-table-begin))
8585 (end (org-table-end))
8586 (table (buffer-substring beg end))
8587 (file (read-file-name "Export table to: "))
8588 buf)
8589 (unless (or (not (file-exists-p file))
8590 (y-or-n-p (format "Overwrite file %s? " file)))
8591 (error "Abort"))
8592 (with-current-buffer (find-file-noselect file)
8593 (setq buf (current-buffer))
8594 (erase-buffer)
8595 (fundamental-mode)
8596 (insert table)
8597 (goto-char (point-min))
8598 (while (re-search-forward "^[ \t]*|[ \t]*" nil t)
8599 (replace-match "" t t)
8600 (end-of-line 1))
8601 (goto-char (point-min))
8602 (while (re-search-forward "[ \t]*|[ \t]*$" nil t)
8603 (replace-match "" t t)
8604 (goto-char (min (1+ (point)) (point-max))))
8605 (goto-char (point-min))
8606 (while (re-search-forward "^-[-+]*$" nil t)
8607 (replace-match "")
8608 (if (looking-at "\n")
8609 (delete-char 1)))
8610 (goto-char (point-min))
8611 (while (re-search-forward "[ \t]*|[ \t]*" nil t)
8612 (replace-match "\t" t t))
8613 (save-buffer))
8614 (kill-buffer buf)))
8616 (defvar org-table-aligned-begin-marker (make-marker)
8617 "Marker at the beginning of the table last aligned.
8618 Used to check if cursor still is in that table, to minimize realignment.")
8619 (defvar org-table-aligned-end-marker (make-marker)
8620 "Marker at the end of the table last aligned.
8621 Used to check if cursor still is in that table, to minimize realignment.")
8622 (defvar org-table-last-alignment nil
8623 "List of flags for flushright alignment, from the last re-alignment.
8624 This is being used to correctly align a single field after TAB or RET.")
8625 (defvar org-table-last-column-widths nil
8626 "List of max width of fields in each column.
8627 This is being used to correctly align a single field after TAB or RET.")
8628 (defvar org-table-overlay-coordinates nil
8629 "Overlay coordinates after each align of a table.")
8630 (make-variable-buffer-local 'org-table-overlay-coordinates)
8632 (defvar org-last-recalc-line nil)
8633 (defconst org-narrow-column-arrow "=>"
8634 "Used as display property in narrowed table columns.")
8636 (defun org-table-align ()
8637 "Align the table at point by aligning all vertical bars."
8638 (interactive)
8639 (let* (
8640 ;; Limits of table
8641 (beg (org-table-begin))
8642 (end (org-table-end))
8643 ;; Current cursor position
8644 (linepos (org-current-line))
8645 (colpos (org-table-current-column))
8646 (winstart (window-start))
8647 (winstartline (org-current-line (min winstart (1- (point-max)))))
8648 lines (new "") lengths l typenums ty fields maxfields i
8649 column
8650 (indent "") cnt frac
8651 rfmt hfmt
8652 (spaces '(1 . 1))
8653 (sp1 (car spaces))
8654 (sp2 (cdr spaces))
8655 (rfmt1 (concat
8656 (make-string sp2 ?\ ) "%%%s%ds" (make-string sp1 ?\ ) "|"))
8657 (hfmt1 (concat
8658 (make-string sp2 ?-) "%s" (make-string sp1 ?-) "+"))
8659 emptystrings links dates emph narrow fmax f1 len c e)
8660 (untabify beg end)
8661 (remove-text-properties beg end '(org-cwidth t org-dwidth t display t))
8662 ;; Check if we have links or dates
8663 (goto-char beg)
8664 (setq links (re-search-forward org-bracket-link-regexp end t))
8665 (goto-char beg)
8666 (setq emph (and org-hide-emphasis-markers
8667 (re-search-forward org-emph-re end t)))
8668 (goto-char beg)
8669 (setq dates (and org-display-custom-times
8670 (re-search-forward org-ts-regexp-both end t)))
8671 ;; Make sure the link properties are right
8672 (when links (goto-char beg) (while (org-activate-bracket-links end)))
8673 ;; Make sure the date properties are right
8674 (when dates (goto-char beg) (while (org-activate-dates end)))
8675 (when emph (goto-char beg) (while (org-do-emphasis-faces end)))
8677 ;; Check if we are narrowing any columns
8678 (goto-char beg)
8679 (setq narrow (and org-format-transports-properties-p
8680 (re-search-forward "<[0-9]+>" end t)))
8681 ;; Get the rows
8682 (setq lines (org-split-string
8683 (buffer-substring beg end) "\n"))
8684 ;; Store the indentation of the first line
8685 (if (string-match "^ *" (car lines))
8686 (setq indent (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
8687 ;; Mark the hlines by setting the corresponding element to nil
8688 ;; At the same time, we remove trailing space.
8689 (setq lines (mapcar (lambda (l)
8690 (if (string-match "^ *|-" l)
8692 (if (string-match "[ \t]+$" l)
8693 (substring l 0 (match-beginning 0))
8694 l)))
8695 lines))
8696 ;; Get the data fields by splitting the lines.
8697 (setq fields (mapcar
8698 (lambda (l)
8699 (org-split-string l " *| *"))
8700 (delq nil (copy-sequence lines))))
8701 ;; How many fields in the longest line?
8702 (condition-case nil
8703 (setq maxfields (apply 'max (mapcar 'length fields)))
8704 (error
8705 (kill-region beg end)
8706 (org-table-create org-table-default-size)
8707 (error "Empty table - created default table")))
8708 ;; A list of empty strings to fill any short rows on output
8709 (setq emptystrings (make-list maxfields ""))
8710 ;; Check for special formatting.
8711 (setq i -1)
8712 (while (< (setq i (1+ i)) maxfields) ;; Loop over all columns
8713 (setq column (mapcar (lambda (x) (or (nth i x) "")) fields))
8714 ;; Check if there is an explicit width specified
8715 (when narrow
8716 (setq c column fmax nil)
8717 (while c
8718 (setq e (pop c))
8719 (if (and (stringp e) (string-match "^<\\([0-9]+\\)>$" e))
8720 (setq fmax (string-to-number (match-string 1 e)) c nil)))
8721 ;; Find fields that are wider than fmax, and shorten them
8722 (when fmax
8723 (loop for xx in column do
8724 (when (and (stringp xx)
8725 (> (org-string-width xx) fmax))
8726 (org-add-props xx nil
8727 'help-echo
8728 (concat "Clipped table field, use C-c ` to edit. Full value is:\n" (org-no-properties (copy-sequence xx))))
8729 (setq f1 (min fmax (or (string-match org-bracket-link-regexp xx) fmax)))
8730 (unless (> f1 1)
8731 (error "Cannot narrow field starting with wide link \"%s\""
8732 (match-string 0 xx)))
8733 (add-text-properties f1 (length xx) (list 'org-cwidth t) xx)
8734 (add-text-properties (- f1 2) f1
8735 (list 'display org-narrow-column-arrow)
8736 xx)))))
8737 ;; Get the maximum width for each column
8738 (push (apply 'max 1 (mapcar 'org-string-width column)) lengths)
8739 ;; Get the fraction of numbers, to decide about alignment of the column
8740 (setq cnt 0 frac 0.0)
8741 (loop for x in column do
8742 (if (equal x "")
8744 (setq frac ( / (+ (* frac cnt)
8745 (if (string-match org-table-number-regexp x) 1 0))
8746 (setq cnt (1+ cnt))))))
8747 (push (>= frac org-table-number-fraction) typenums))
8748 (setq lengths (nreverse lengths) typenums (nreverse typenums))
8750 ;; Store the alignment of this table, for later editing of single fields
8751 (setq org-table-last-alignment typenums
8752 org-table-last-column-widths lengths)
8754 ;; With invisible characters, `format' does not get the field width right
8755 ;; So we need to make these fields wide by hand.
8756 (when (or links emph)
8757 (loop for i from 0 upto (1- maxfields) do
8758 (setq len (nth i lengths))
8759 (loop for j from 0 upto (1- (length fields)) do
8760 (setq c (nthcdr i (car (nthcdr j fields))))
8761 (if (and (stringp (car c))
8762 (text-property-any 0 (length (car c)) 'invisible 'org-link (car c))
8763 ; (string-match org-bracket-link-regexp (car c))
8764 (< (org-string-width (car c)) len))
8765 (setcar c (concat (car c) (make-string (- len (org-string-width (car c))) ?\ )))))))
8767 ;; Compute the formats needed for output of the table
8768 (setq rfmt (concat indent "|") hfmt (concat indent "|"))
8769 (while (setq l (pop lengths))
8770 (setq ty (if (pop typenums) "" "-")) ; number types flushright
8771 (setq rfmt (concat rfmt (format rfmt1 ty l))
8772 hfmt (concat hfmt (format hfmt1 (make-string l ?-)))))
8773 (setq rfmt (concat rfmt "\n")
8774 hfmt (concat (substring hfmt 0 -1) "|\n"))
8776 (setq new (mapconcat
8777 (lambda (l)
8778 (if l (apply 'format rfmt
8779 (append (pop fields) emptystrings))
8780 hfmt))
8781 lines ""))
8782 ;; Replace the old one
8783 (delete-region beg end)
8784 (move-marker end nil)
8785 (move-marker org-table-aligned-begin-marker (point))
8786 (insert new)
8787 (move-marker org-table-aligned-end-marker (point))
8788 (when (and orgtbl-mode (not (org-mode-p)))
8789 (goto-char org-table-aligned-begin-marker)
8790 (while (org-hide-wide-columns org-table-aligned-end-marker)))
8791 ;; Try to move to the old location
8792 (goto-line winstartline)
8793 (setq winstart (point-at-bol))
8794 (goto-line linepos)
8795 (set-window-start (selected-window) winstart 'noforce)
8796 (org-table-goto-column colpos)
8797 (and org-table-overlay-coordinates (org-table-overlay-coordinates))
8798 (setq org-table-may-need-update nil)
8801 (defun org-string-width (s)
8802 "Compute width of string, ignoring invisible characters.
8803 This ignores character with invisibility property `org-link', and also
8804 characters with property `org-cwidth', because these will become invisible
8805 upon the next fontification round."
8806 (let (b l)
8807 (when (or (eq t buffer-invisibility-spec)
8808 (assq 'org-link buffer-invisibility-spec))
8809 (while (setq b (text-property-any 0 (length s)
8810 'invisible 'org-link s))
8811 (setq s (concat (substring s 0 b)
8812 (substring s (or (next-single-property-change
8813 b 'invisible s) (length s)))))))
8814 (while (setq b (text-property-any 0 (length s) 'org-cwidth t s))
8815 (setq s (concat (substring s 0 b)
8816 (substring s (or (next-single-property-change
8817 b 'org-cwidth s) (length s))))))
8818 (setq l (string-width s) b -1)
8819 (while (setq b (text-property-any (1+ b) (length s) 'org-dwidth t s))
8820 (setq l (- l (get-text-property b 'org-dwidth-n s))))
8823 (defun org-table-begin (&optional table-type)
8824 "Find the beginning of the table and return its position.
8825 With argument TABLE-TYPE, go to the beginning of a table.el-type table."
8826 (save-excursion
8827 (if (not (re-search-backward
8828 (if table-type org-table-any-border-regexp
8829 org-table-border-regexp)
8830 nil t))
8831 (progn (goto-char (point-min)) (point))
8832 (goto-char (match-beginning 0))
8833 (beginning-of-line 2)
8834 (point))))
8836 (defun org-table-end (&optional table-type)
8837 "Find the end of the table and return its position.
8838 With argument TABLE-TYPE, go to the end of a table.el-type table."
8839 (save-excursion
8840 (if (not (re-search-forward
8841 (if table-type org-table-any-border-regexp
8842 org-table-border-regexp)
8843 nil t))
8844 (goto-char (point-max))
8845 (goto-char (match-beginning 0)))
8846 (point-marker)))
8848 (defun org-table-justify-field-maybe (&optional new)
8849 "Justify the current field, text to left, number to right.
8850 Optional argument NEW may specify text to replace the current field content."
8851 (cond
8852 ((and (not new) org-table-may-need-update)) ; Realignment will happen anyway
8853 ((org-at-table-hline-p))
8854 ((and (not new)
8855 (or (not (equal (marker-buffer org-table-aligned-begin-marker)
8856 (current-buffer)))
8857 (< (point) org-table-aligned-begin-marker)
8858 (>= (point) org-table-aligned-end-marker)))
8859 ;; This is not the same table, force a full re-align
8860 (setq org-table-may-need-update t))
8861 (t ;; realign the current field, based on previous full realign
8862 (let* ((pos (point)) s
8863 (col (org-table-current-column))
8864 (num (if (> col 0) (nth (1- col) org-table-last-alignment)))
8865 l f n o e)
8866 (when (> col 0)
8867 (skip-chars-backward "^|\n")
8868 (if (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)")
8869 (progn
8870 (setq s (match-string 1)
8871 o (match-string 0)
8872 l (max 1 (- (match-end 0) (match-beginning 0) 3))
8873 e (not (= (match-beginning 2) (match-end 2))))
8874 (setq f (format (if num " %%%ds %s" " %%-%ds %s")
8875 l (if e "|" (setq org-table-may-need-update t) ""))
8876 n (format f s))
8877 (if new
8878 (if (<= (length new) l) ;; FIXME: length -> str-width?
8879 (setq n (format f new))
8880 (setq n (concat new "|") org-table-may-need-update t)))
8881 (or (equal n o)
8882 (let (org-table-may-need-update)
8883 (replace-match n t t))))
8884 (setq org-table-may-need-update t))
8885 (goto-char pos))))))
8887 (defun org-table-next-field ()
8888 "Go to the next field in the current table, creating new lines as needed.
8889 Before doing so, re-align the table if necessary."
8890 (interactive)
8891 (org-table-maybe-eval-formula)
8892 (org-table-maybe-recalculate-line)
8893 (if (and org-table-automatic-realign
8894 org-table-may-need-update)
8895 (org-table-align))
8896 (let ((end (org-table-end)))
8897 (if (org-at-table-hline-p)
8898 (end-of-line 1))
8899 (condition-case nil
8900 (progn
8901 (re-search-forward "|" end)
8902 (if (looking-at "[ \t]*$")
8903 (re-search-forward "|" end))
8904 (if (and (looking-at "-")
8905 org-table-tab-jumps-over-hlines
8906 (re-search-forward "^[ \t]*|\\([^-]\\)" end t))
8907 (goto-char (match-beginning 1)))
8908 (if (looking-at "-")
8909 (progn
8910 (beginning-of-line 0)
8911 (org-table-insert-row 'below))
8912 (if (looking-at " ") (forward-char 1))))
8913 (error
8914 (org-table-insert-row 'below)))))
8916 (defun org-table-previous-field ()
8917 "Go to the previous field in the table.
8918 Before doing so, re-align the table if necessary."
8919 (interactive)
8920 (org-table-justify-field-maybe)
8921 (org-table-maybe-recalculate-line)
8922 (if (and org-table-automatic-realign
8923 org-table-may-need-update)
8924 (org-table-align))
8925 (if (org-at-table-hline-p)
8926 (end-of-line 1))
8927 (re-search-backward "|" (org-table-begin))
8928 (re-search-backward "|" (org-table-begin))
8929 (while (looking-at "|\\(-\\|[ \t]*$\\)")
8930 (re-search-backward "|" (org-table-begin)))
8931 (if (looking-at "| ?")
8932 (goto-char (match-end 0))))
8934 (defun org-table-next-row ()
8935 "Go to the next row (same column) in the current table.
8936 Before doing so, re-align the table if necessary."
8937 (interactive)
8938 (org-table-maybe-eval-formula)
8939 (org-table-maybe-recalculate-line)
8940 (if (or (looking-at "[ \t]*$")
8941 (save-excursion (skip-chars-backward " \t") (bolp)))
8942 (newline)
8943 (if (and org-table-automatic-realign
8944 org-table-may-need-update)
8945 (org-table-align))
8946 (let ((col (org-table-current-column)))
8947 (beginning-of-line 2)
8948 (if (or (not (org-at-table-p))
8949 (org-at-table-hline-p))
8950 (progn
8951 (beginning-of-line 0)
8952 (org-table-insert-row 'below)))
8953 (org-table-goto-column col)
8954 (skip-chars-backward "^|\n\r")
8955 (if (looking-at " ") (forward-char 1)))))
8957 (defun org-table-copy-down (n)
8958 "Copy a field down in the current column.
8959 If the field at the cursor is empty, copy into it the content of the nearest
8960 non-empty field above. With argument N, use the Nth non-empty field.
8961 If the current field is not empty, it is copied down to the next row, and
8962 the cursor is moved with it. Therefore, repeating this command causes the
8963 column to be filled row-by-row.
8964 If the variable `org-table-copy-increment' is non-nil and the field is an
8965 integer or a timestamp, it will be incremented while copying. In the case of
8966 a timestamp, if the cursor is on the year, change the year. If it is on the
8967 month or the day, change that. Point will stay on the current date field
8968 in order to easily repeat the interval."
8969 (interactive "p")
8970 (let* ((colpos (org-table-current-column))
8971 (col (current-column))
8972 (field (org-table-get-field))
8973 (non-empty (string-match "[^ \t]" field))
8974 (beg (org-table-begin))
8975 txt)
8976 (org-table-check-inside-data-field)
8977 (if non-empty
8978 (progn
8979 (setq txt (org-trim field))
8980 (org-table-next-row)
8981 (org-table-blank-field))
8982 (save-excursion
8983 (setq txt
8984 (catch 'exit
8985 (while (progn (beginning-of-line 1)
8986 (re-search-backward org-table-dataline-regexp
8987 beg t))
8988 (org-table-goto-column colpos t)
8989 (if (and (looking-at
8990 "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|")
8991 (= (setq n (1- n)) 0))
8992 (throw 'exit (match-string 1))))))))
8993 (if txt
8994 (progn
8995 (if (and org-table-copy-increment
8996 (string-match "^[0-9]+$" txt))
8997 (setq txt (format "%d" (+ (string-to-number txt) 1))))
8998 (insert txt)
8999 (move-to-column col)
9000 (if (and org-table-copy-increment (org-at-timestamp-p t))
9001 (org-timestamp-up 1)
9002 (org-table-maybe-recalculate-line))
9003 (org-table-align)
9004 (move-to-column col))
9005 (error "No non-empty field found"))))
9007 (defun org-table-check-inside-data-field ()
9008 "Is point inside a table data field?
9009 I.e. not on a hline or before the first or after the last column?
9010 This actually throws an error, so it aborts the current command."
9011 (if (or (not (org-at-table-p))
9012 (= (org-table-current-column) 0)
9013 (org-at-table-hline-p)
9014 (looking-at "[ \t]*$"))
9015 (error "Not in table data field")))
9017 (defvar org-table-clip nil
9018 "Clipboard for table regions.")
9020 (defun org-table-blank-field ()
9021 "Blank the current table field or active region."
9022 (interactive)
9023 (org-table-check-inside-data-field)
9024 (if (and (interactive-p) (org-region-active-p))
9025 (let (org-table-clip)
9026 (org-table-cut-region (region-beginning) (region-end)))
9027 (skip-chars-backward "^|")
9028 (backward-char 1)
9029 (if (looking-at "|[^|\n]+")
9030 (let* ((pos (match-beginning 0))
9031 (match (match-string 0))
9032 (len (org-string-width match)))
9033 (replace-match (concat "|" (make-string (1- len) ?\ )))
9034 (goto-char (+ 2 pos))
9035 (substring match 1)))))
9037 (defun org-table-get-field (&optional n replace)
9038 "Return the value of the field in column N of current row.
9039 N defaults to current field.
9040 If REPLACE is a string, replace field with this value. The return value
9041 is always the old value."
9042 (and n (org-table-goto-column n))
9043 (skip-chars-backward "^|\n")
9044 (backward-char 1)
9045 (if (looking-at "|[^|\r\n]*")
9046 (let* ((pos (match-beginning 0))
9047 (val (buffer-substring (1+ pos) (match-end 0))))
9048 (if replace
9049 (replace-match (concat "|" replace) t t))
9050 (goto-char (min (point-at-eol) (+ 2 pos)))
9051 val)
9052 (forward-char 1) ""))
9054 (defun org-table-field-info (arg)
9055 "Show info about the current field, and highlight any reference at point."
9056 (interactive "P")
9057 (org-table-get-specials)
9058 (save-excursion
9059 (let* ((pos (point))
9060 (col (org-table-current-column))
9061 (cname (car (rassoc (int-to-string col) org-table-column-names)))
9062 (name (car (rassoc (list (org-current-line) col)
9063 org-table-named-field-locations)))
9064 (eql (org-table-get-stored-formulas))
9065 (dline (org-table-current-dline))
9066 (ref (format "@%d$%d" dline col))
9067 (ref1 (org-table-convert-refs-to-an ref))
9068 (fequation (or (assoc name eql) (assoc ref eql)))
9069 (cequation (assoc (int-to-string col) eql))
9070 (eqn (or fequation cequation)))
9071 (goto-char pos)
9072 (condition-case nil
9073 (org-table-show-reference 'local)
9074 (error nil))
9075 (message "line @%d, col $%s%s, ref @%d$%d or %s%s%s"
9076 dline col
9077 (if cname (concat " or $" cname) "")
9078 dline col ref1
9079 (if name (concat " or $" name) "")
9080 ;; FIXME: formula info not correct if special table line
9081 (if eqn
9082 (concat ", formula: "
9083 (org-table-formula-to-user
9084 (concat
9085 (if (string-match "^[$@]"(car eqn)) "" "$")
9086 (car eqn) "=" (cdr eqn))))
9087 "")))))
9089 (defun org-table-current-column ()
9090 "Find out which column we are in.
9091 When called interactively, column is also displayed in echo area."
9092 (interactive)
9093 (if (interactive-p) (org-table-check-inside-data-field))
9094 (save-excursion
9095 (let ((cnt 0) (pos (point)))
9096 (beginning-of-line 1)
9097 (while (search-forward "|" pos t)
9098 (setq cnt (1+ cnt)))
9099 (if (interactive-p) (message "This is table column %d" cnt))
9100 cnt)))
9102 (defun org-table-current-dline ()
9103 "Find out what table data line we are in.
9104 Only datalins count for this."
9105 (interactive)
9106 (if (interactive-p) (org-table-check-inside-data-field))
9107 (save-excursion
9108 (let ((cnt 0) (pos (point)))
9109 (goto-char (org-table-begin))
9110 (while (<= (point) pos)
9111 (if (looking-at org-table-dataline-regexp) (setq cnt (1+ cnt)))
9112 (beginning-of-line 2))
9113 (if (interactive-p) (message "This is table line %d" cnt))
9114 cnt)))
9116 (defun org-table-goto-column (n &optional on-delim force)
9117 "Move the cursor to the Nth column in the current table line.
9118 With optional argument ON-DELIM, stop with point before the left delimiter
9119 of the field.
9120 If there are less than N fields, just go to after the last delimiter.
9121 However, when FORCE is non-nil, create new columns if necessary."
9122 (interactive "p")
9123 (let ((pos (point-at-eol)))
9124 (beginning-of-line 1)
9125 (when (> n 0)
9126 (while (and (> (setq n (1- n)) -1)
9127 (or (search-forward "|" pos t)
9128 (and force
9129 (progn (end-of-line 1)
9130 (skip-chars-backward "^|")
9131 (insert " | "))))))
9132 ; (backward-char 2) t)))))
9133 (when (and force (not (looking-at ".*|")))
9134 (save-excursion (end-of-line 1) (insert " | ")))
9135 (if on-delim
9136 (backward-char 1)
9137 (if (looking-at " ") (forward-char 1))))))
9139 (defun org-at-table-p (&optional table-type)
9140 "Return t if the cursor is inside an org-type table.
9141 If TABLE-TYPE is non-nil, also check for table.el-type tables."
9142 (if org-enable-table-editor
9143 (save-excursion
9144 (beginning-of-line 1)
9145 (looking-at (if table-type org-table-any-line-regexp
9146 org-table-line-regexp)))
9147 nil))
9149 (defun org-at-table.el-p ()
9150 "Return t if and only if we are at a table.el table."
9151 (and (org-at-table-p 'any)
9152 (save-excursion
9153 (goto-char (org-table-begin 'any))
9154 (looking-at org-table1-hline-regexp))))
9156 (defun org-table-recognize-table.el ()
9157 "If there is a table.el table nearby, recognize it and move into it."
9158 (if org-table-tab-recognizes-table.el
9159 (if (org-at-table.el-p)
9160 (progn
9161 (beginning-of-line 1)
9162 (if (looking-at org-table-dataline-regexp)
9164 (if (looking-at org-table1-hline-regexp)
9165 (progn
9166 (beginning-of-line 2)
9167 (if (looking-at org-table-any-border-regexp)
9168 (beginning-of-line -1)))))
9169 (if (re-search-forward "|" (org-table-end t) t)
9170 (progn
9171 (require 'table)
9172 (if (table--at-cell-p (point))
9174 (message "recognizing table.el table...")
9175 (table-recognize-table)
9176 (message "recognizing table.el table...done")))
9177 (error "This should not happen..."))
9179 nil)
9180 nil))
9182 (defun org-at-table-hline-p ()
9183 "Return t if the cursor is inside a hline in a table."
9184 (if org-enable-table-editor
9185 (save-excursion
9186 (beginning-of-line 1)
9187 (looking-at org-table-hline-regexp))
9188 nil))
9190 (defun org-table-insert-column ()
9191 "Insert a new column into the table."
9192 (interactive)
9193 (if (not (org-at-table-p))
9194 (error "Not at a table"))
9195 (org-table-find-dataline)
9196 (let* ((col (max 1 (org-table-current-column)))
9197 (beg (org-table-begin))
9198 (end (org-table-end))
9199 ;; Current cursor position
9200 (linepos (org-current-line))
9201 (colpos col))
9202 (goto-char beg)
9203 (while (< (point) end)
9204 (if (org-at-table-hline-p)
9206 (org-table-goto-column col t)
9207 (insert "| "))
9208 (beginning-of-line 2))
9209 (move-marker end nil)
9210 (goto-line linepos)
9211 (org-table-goto-column colpos)
9212 (org-table-align)
9213 (org-table-fix-formulas "$" nil (1- col) 1)))
9215 (defun org-table-find-dataline ()
9216 "Find a dataline in the current table, which is needed for column commands."
9217 (if (and (org-at-table-p)
9218 (not (org-at-table-hline-p)))
9220 (let ((col (current-column))
9221 (end (org-table-end)))
9222 (move-to-column col)
9223 (while (and (< (point) end)
9224 (or (not (= (current-column) col))
9225 (org-at-table-hline-p)))
9226 (beginning-of-line 2)
9227 (move-to-column col))
9228 (if (and (org-at-table-p)
9229 (not (org-at-table-hline-p)))
9231 (error
9232 "Please position cursor in a data line for column operations")))))
9234 (defun org-table-delete-column ()
9235 "Delete a column from the table."
9236 (interactive)
9237 (if (not (org-at-table-p))
9238 (error "Not at a table"))
9239 (org-table-find-dataline)
9240 (org-table-check-inside-data-field)
9241 (let* ((col (org-table-current-column))
9242 (beg (org-table-begin))
9243 (end (org-table-end))
9244 ;; Current cursor position
9245 (linepos (org-current-line))
9246 (colpos col))
9247 (goto-char beg)
9248 (while (< (point) end)
9249 (if (org-at-table-hline-p)
9251 (org-table-goto-column col t)
9252 (and (looking-at "|[^|\n]+|")
9253 (replace-match "|")))
9254 (beginning-of-line 2))
9255 (move-marker end nil)
9256 (goto-line linepos)
9257 (org-table-goto-column colpos)
9258 (org-table-align)
9259 (org-table-fix-formulas "$" (list (cons (number-to-string col) "INVALID"))
9260 col -1 col)))
9262 (defun org-table-move-column-right ()
9263 "Move column to the right."
9264 (interactive)
9265 (org-table-move-column nil))
9266 (defun org-table-move-column-left ()
9267 "Move column to the left."
9268 (interactive)
9269 (org-table-move-column 'left))
9271 (defun org-table-move-column (&optional left)
9272 "Move the current column to the right. With arg LEFT, move to the left."
9273 (interactive "P")
9274 (if (not (org-at-table-p))
9275 (error "Not at a table"))
9276 (org-table-find-dataline)
9277 (org-table-check-inside-data-field)
9278 (let* ((col (org-table-current-column))
9279 (col1 (if left (1- col) col))
9280 (beg (org-table-begin))
9281 (end (org-table-end))
9282 ;; Current cursor position
9283 (linepos (org-current-line))
9284 (colpos (if left (1- col) (1+ col))))
9285 (if (and left (= col 1))
9286 (error "Cannot move column further left"))
9287 (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$"))
9288 (error "Cannot move column further right"))
9289 (goto-char beg)
9290 (while (< (point) end)
9291 (if (org-at-table-hline-p)
9293 (org-table-goto-column col1 t)
9294 (and (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|")
9295 (replace-match "|\\2|\\1|")))
9296 (beginning-of-line 2))
9297 (move-marker end nil)
9298 (goto-line linepos)
9299 (org-table-goto-column colpos)
9300 (org-table-align)
9301 (org-table-fix-formulas
9302 "$" (list (cons (number-to-string col) (number-to-string colpos))
9303 (cons (number-to-string colpos) (number-to-string col))))))
9305 (defun org-table-move-row-down ()
9306 "Move table row down."
9307 (interactive)
9308 (org-table-move-row nil))
9309 (defun org-table-move-row-up ()
9310 "Move table row up."
9311 (interactive)
9312 (org-table-move-row 'up))
9314 (defun org-table-move-row (&optional up)
9315 "Move the current table line down. With arg UP, move it up."
9316 (interactive "P")
9317 (let* ((col (current-column))
9318 (pos (point))
9319 (hline1p (save-excursion (beginning-of-line 1)
9320 (looking-at org-table-hline-regexp)))
9321 (dline1 (org-table-current-dline))
9322 (dline2 (+ dline1 (if up -1 1)))
9323 (tonew (if up 0 2))
9324 txt hline2p)
9325 (beginning-of-line tonew)
9326 (unless (org-at-table-p)
9327 (goto-char pos)
9328 (error "Cannot move row further"))
9329 (setq hline2p (looking-at org-table-hline-regexp))
9330 (goto-char pos)
9331 (beginning-of-line 1)
9332 (setq pos (point))
9333 (setq txt (buffer-substring (point) (1+ (point-at-eol))))
9334 (delete-region (point) (1+ (point-at-eol)))
9335 (beginning-of-line tonew)
9336 (insert txt)
9337 (beginning-of-line 0)
9338 (move-to-column col)
9339 (unless (or hline1p hline2p)
9340 (org-table-fix-formulas
9341 "@" (list (cons (number-to-string dline1) (number-to-string dline2))
9342 (cons (number-to-string dline2) (number-to-string dline1)))))))
9344 (defun org-table-insert-row (&optional arg)
9345 "Insert a new row above the current line into the table.
9346 With prefix ARG, insert below the current line."
9347 (interactive "P")
9348 (if (not (org-at-table-p))
9349 (error "Not at a table"))
9350 (let* ((line (buffer-substring (point-at-bol) (point-at-eol)))
9351 (new (org-table-clean-line line)))
9352 ;; Fix the first field if necessary
9353 (if (string-match "^[ \t]*| *[#$] *|" line)
9354 (setq new (replace-match (match-string 0 line) t t new)))
9355 (beginning-of-line (if arg 2 1))
9356 (let (org-table-may-need-update) (insert-before-markers new "\n"))
9357 (beginning-of-line 0)
9358 (re-search-forward "| ?" (point-at-eol) t)
9359 (and (or org-table-may-need-update org-table-overlay-coordinates)
9360 (org-table-align))
9361 (org-table-fix-formulas "@" nil (1- (org-table-current-dline)) 1)))
9363 (defun org-table-insert-hline (&optional above)
9364 "Insert a horizontal-line below the current line into the table.
9365 With prefix ABOVE, insert above the current line."
9366 (interactive "P")
9367 (if (not (org-at-table-p))
9368 (error "Not at a table"))
9369 (let ((line (org-table-clean-line
9370 (buffer-substring (point-at-bol) (point-at-eol))))
9371 (col (current-column)))
9372 (while (string-match "|\\( +\\)|" line)
9373 (setq line (replace-match
9374 (concat "+" (make-string (- (match-end 1) (match-beginning 1))
9375 ?-) "|") t t line)))
9376 (and (string-match "\\+" line) (setq line (replace-match "|" t t line)))
9377 (beginning-of-line (if above 1 2))
9378 (insert line "\n")
9379 (beginning-of-line (if above 1 -1))
9380 (move-to-column col)
9381 (and org-table-overlay-coordinates (org-table-align))))
9383 (defun org-table-hline-and-move (&optional same-column)
9384 "Insert a hline and move to the row below that line."
9385 (interactive "P")
9386 (let ((col (org-table-current-column)))
9387 (org-table-maybe-eval-formula)
9388 (org-table-maybe-recalculate-line)
9389 (org-table-insert-hline)
9390 (end-of-line 2)
9391 (if (looking-at "\n[ \t]*|-")
9392 (progn (insert "\n|") (org-table-align))
9393 (org-table-next-field))
9394 (if same-column (org-table-goto-column col))))
9396 (defun org-table-clean-line (s)
9397 "Convert a table line S into a string with only \"|\" and space.
9398 In particular, this does handle wide and invisible characters."
9399 (if (string-match "^[ \t]*|-" s)
9400 ;; It's a hline, just map the characters
9401 (setq s (mapconcat (lambda (x) (if (member x '(?| ?+)) "|" " ")) s ""))
9402 (while (string-match "|\\([ \t]*?[^ \t\r\n|][^\r\n|]*\\)|" s)
9403 (setq s (replace-match
9404 (concat "|" (make-string (org-string-width (match-string 1 s))
9405 ?\ ) "|")
9406 t t s)))
9409 (defun org-table-kill-row ()
9410 "Delete the current row or horizontal line from the table."
9411 (interactive)
9412 (if (not (org-at-table-p))
9413 (error "Not at a table"))
9414 (let ((col (current-column))
9415 (dline (org-table-current-dline)))
9416 (kill-region (point-at-bol) (min (1+ (point-at-eol)) (point-max)))
9417 (if (not (org-at-table-p)) (beginning-of-line 0))
9418 (move-to-column col)
9419 (org-table-fix-formulas "@" (list (cons (number-to-string dline) "INVALID"))
9420 dline -1 dline)))
9422 (defun org-table-sort-lines (with-case &optional sorting-type)
9423 "Sort table lines according to the column at point.
9425 The position of point indicates the column to be used for
9426 sorting, and the range of lines is the range between the nearest
9427 horizontal separator lines, or the entire table of no such lines
9428 exist. If point is before the first column, you will be prompted
9429 for the sorting column. If there is an active region, the mark
9430 specifies the first line and the sorting column, while point
9431 should be in the last line to be included into the sorting.
9433 The command then prompts for the sorting type which can be
9434 alphabetically, numerically, or by time (as given in a time stamp
9435 in the field). Sorting in reverse order is also possible.
9437 With prefix argument WITH-CASE, alphabetic sorting will be case-sensitive.
9439 If SORTING-TYPE is specified when this function is called from a Lisp
9440 program, no prompting will take place. SORTING-TYPE must be a character,
9441 any of (?a ?A ?n ?N ?t ?T) where the capital letter indicate that sorting
9442 should be done in reverse order."
9443 (interactive "P")
9444 (let* ((thisline (org-current-line))
9445 (thiscol (org-table-current-column))
9446 beg end bcol ecol tend tbeg column lns pos)
9447 (when (equal thiscol 0)
9448 (if (interactive-p)
9449 (setq thiscol
9450 (string-to-number
9451 (read-string "Use column N for sorting: ")))
9452 (setq thiscol 1))
9453 (org-table-goto-column thiscol))
9454 (org-table-check-inside-data-field)
9455 (if (org-region-active-p)
9456 (progn
9457 (setq beg (region-beginning) end (region-end))
9458 (goto-char beg)
9459 (setq column (org-table-current-column)
9460 beg (point-at-bol))
9461 (goto-char end)
9462 (setq end (point-at-bol 2)))
9463 (setq column (org-table-current-column)
9464 pos (point)
9465 tbeg (org-table-begin)
9466 tend (org-table-end))
9467 (if (re-search-backward org-table-hline-regexp tbeg t)
9468 (setq beg (point-at-bol 2))
9469 (goto-char tbeg)
9470 (setq beg (point-at-bol 1)))
9471 (goto-char pos)
9472 (if (re-search-forward org-table-hline-regexp tend t)
9473 (setq end (point-at-bol 1))
9474 (goto-char tend)
9475 (setq end (point-at-bol))))
9476 (setq beg (move-marker (make-marker) beg)
9477 end (move-marker (make-marker) end))
9478 (untabify beg end)
9479 (goto-char beg)
9480 (org-table-goto-column column)
9481 (skip-chars-backward "^|")
9482 (setq bcol (current-column))
9483 (org-table-goto-column (1+ column))
9484 (skip-chars-backward "^|")
9485 (setq ecol (1- (current-column)))
9486 (org-table-goto-column column)
9487 (setq lns (mapcar (lambda(x) (cons
9488 (org-sort-remove-invisible
9489 (nth (1- column)
9490 (org-split-string x "[ \t]*|[ \t]*")))
9492 (org-split-string (buffer-substring beg end) "\n")))
9493 (setq lns (org-do-sort lns "Table" with-case sorting-type))
9494 (delete-region beg end)
9495 (move-marker beg nil)
9496 (move-marker end nil)
9497 (insert (mapconcat 'cdr lns "\n") "\n")
9498 (goto-line thisline)
9499 (org-table-goto-column thiscol)
9500 (message "%d lines sorted, based on column %d" (length lns) column)))
9502 ;; FIXME: maybe we will not need this? Table sorting is broken....
9503 (defun org-sort-remove-invisible (s)
9504 (remove-text-properties 0 (length s) org-rm-props s)
9505 (while (string-match org-bracket-link-regexp s)
9506 (setq s (replace-match (if (match-end 2)
9507 (match-string 3 s)
9508 (match-string 1 s)) t t s)))
9511 (defun org-table-cut-region (beg end)
9512 "Copy region in table to the clipboard and blank all relevant fields."
9513 (interactive "r")
9514 (org-table-copy-region beg end 'cut))
9516 (defun org-table-copy-region (beg end &optional cut)
9517 "Copy rectangular region in table to clipboard.
9518 A special clipboard is used which can only be accessed
9519 with `org-table-paste-rectangle'."
9520 (interactive "rP")
9521 (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2
9522 region cols
9523 (rpl (if cut " " nil)))
9524 (goto-char beg)
9525 (org-table-check-inside-data-field)
9526 (setq l01 (org-current-line)
9527 c01 (org-table-current-column))
9528 (goto-char end)
9529 (org-table-check-inside-data-field)
9530 (setq l02 (org-current-line)
9531 c02 (org-table-current-column))
9532 (setq l1 (min l01 l02) l2 (max l01 l02)
9533 c1 (min c01 c02) c2 (max c01 c02))
9534 (catch 'exit
9535 (while t
9536 (catch 'nextline
9537 (if (> l1 l2) (throw 'exit t))
9538 (goto-line l1)
9539 (if (org-at-table-hline-p) (throw 'nextline (setq l1 (1+ l1))))
9540 (setq cols nil ic1 c1 ic2 c2)
9541 (while (< ic1 (1+ ic2))
9542 (push (org-table-get-field ic1 rpl) cols)
9543 (setq ic1 (1+ ic1)))
9544 (push (nreverse cols) region)
9545 (setq l1 (1+ l1)))))
9546 (setq org-table-clip (nreverse region))
9547 (if cut (org-table-align))
9548 org-table-clip))
9550 (defun org-table-paste-rectangle ()
9551 "Paste a rectangular region into a table.
9552 The upper right corner ends up in the current field. All involved fields
9553 will be overwritten. If the rectangle does not fit into the present table,
9554 the table is enlarged as needed. The process ignores horizontal separator
9555 lines."
9556 (interactive)
9557 (unless (and org-table-clip (listp org-table-clip))
9558 (error "First cut/copy a region to paste!"))
9559 (org-table-check-inside-data-field)
9560 (let* ((clip org-table-clip)
9561 (line (org-current-line))
9562 (col (org-table-current-column))
9563 (org-enable-table-editor t)
9564 (org-table-automatic-realign nil)
9565 c cols field)
9566 (while (setq cols (pop clip))
9567 (while (org-at-table-hline-p) (beginning-of-line 2))
9568 (if (not (org-at-table-p))
9569 (progn (end-of-line 0) (org-table-next-field)))
9570 (setq c col)
9571 (while (setq field (pop cols))
9572 (org-table-goto-column c nil 'force)
9573 (org-table-get-field nil field)
9574 (setq c (1+ c)))
9575 (beginning-of-line 2))
9576 (goto-line line)
9577 (org-table-goto-column col)
9578 (org-table-align)))
9580 (defun org-table-convert ()
9581 "Convert from `org-mode' table to table.el and back.
9582 Obviously, this only works within limits. When an Org-mode table is
9583 converted to table.el, all horizontal separator lines get lost, because
9584 table.el uses these as cell boundaries and has no notion of horizontal lines.
9585 A table.el table can be converted to an Org-mode table only if it does not
9586 do row or column spanning. Multiline cells will become multiple cells.
9587 Beware, Org-mode does not test if the table can be successfully converted - it
9588 blindly applies a recipe that works for simple tables."
9589 (interactive)
9590 (require 'table)
9591 (if (org-at-table.el-p)
9592 ;; convert to Org-mode table
9593 (let ((beg (move-marker (make-marker) (org-table-begin t)))
9594 (end (move-marker (make-marker) (org-table-end t))))
9595 (table-unrecognize-region beg end)
9596 (goto-char beg)
9597 (while (re-search-forward "^\\([ \t]*\\)\\+-.*\n" end t)
9598 (replace-match ""))
9599 (goto-char beg))
9600 (if (org-at-table-p)
9601 ;; convert to table.el table
9602 (let ((beg (move-marker (make-marker) (org-table-begin)))
9603 (end (move-marker (make-marker) (org-table-end))))
9604 ;; first, get rid of all horizontal lines
9605 (goto-char beg)
9606 (while (re-search-forward "^\\([ \t]*\\)|-.*\n" end t)
9607 (replace-match ""))
9608 ;; insert a hline before first
9609 (goto-char beg)
9610 (org-table-insert-hline 'above)
9611 (beginning-of-line -1)
9612 ;; insert a hline after each line
9613 (while (progn (beginning-of-line 3) (< (point) end))
9614 (org-table-insert-hline))
9615 (goto-char beg)
9616 (setq end (move-marker end (org-table-end)))
9617 ;; replace "+" at beginning and ending of hlines
9618 (while (re-search-forward "^\\([ \t]*\\)|-" end t)
9619 (replace-match "\\1+-"))
9620 (goto-char beg)
9621 (while (re-search-forward "-|[ \t]*$" end t)
9622 (replace-match "-+"))
9623 (goto-char beg)))))
9625 (defun org-table-wrap-region (arg)
9626 "Wrap several fields in a column like a paragraph.
9627 This is useful if you'd like to spread the contents of a field over several
9628 lines, in order to keep the table compact.
9630 If there is an active region, and both point and mark are in the same column,
9631 the text in the column is wrapped to minimum width for the given number of
9632 lines. Generally, this makes the table more compact. A prefix ARG may be
9633 used to change the number of desired lines. For example, `C-2 \\[org-table-wrap]'
9634 formats the selected text to two lines. If the region was longer than two
9635 lines, the remaining lines remain empty. A negative prefix argument reduces
9636 the current number of lines by that amount. The wrapped text is pasted back
9637 into the table. If you formatted it to more lines than it was before, fields
9638 further down in the table get overwritten - so you might need to make space in
9639 the table first.
9641 If there is no region, the current field is split at the cursor position and
9642 the text fragment to the right of the cursor is prepended to the field one
9643 line down.
9645 If there is no region, but you specify a prefix ARG, the current field gets
9646 blank, and the content is appended to the field above."
9647 (interactive "P")
9648 (org-table-check-inside-data-field)
9649 (if (org-region-active-p)
9650 ;; There is a region: fill as a paragraph
9651 (let* ((beg (region-beginning))
9652 (cline (save-excursion (goto-char beg) (org-current-line)))
9653 (ccol (save-excursion (goto-char beg) (org-table-current-column)))
9654 nlines)
9655 (org-table-cut-region (region-beginning) (region-end))
9656 (if (> (length (car org-table-clip)) 1)
9657 (error "Region must be limited to single column"))
9658 (setq nlines (if arg
9659 (if (< arg 1)
9660 (+ (length org-table-clip) arg)
9661 arg)
9662 (length org-table-clip)))
9663 (setq org-table-clip
9664 (mapcar 'list (org-wrap (mapconcat 'car org-table-clip " ")
9665 nil nlines)))
9666 (goto-line cline)
9667 (org-table-goto-column ccol)
9668 (org-table-paste-rectangle))
9669 ;; No region, split the current field at point
9670 (unless (org-get-alist-option org-M-RET-may-split-line 'table)
9671 (skip-chars-forward "^\r\n|"))
9672 (if arg
9673 ;; combine with field above
9674 (let ((s (org-table-blank-field))
9675 (col (org-table-current-column)))
9676 (beginning-of-line 0)
9677 (while (org-at-table-hline-p) (beginning-of-line 0))
9678 (org-table-goto-column col)
9679 (skip-chars-forward "^|")
9680 (skip-chars-backward " ")
9681 (insert " " (org-trim s))
9682 (org-table-align))
9683 ;; split field
9684 (if (looking-at "\\([^|]+\\)+|")
9685 (let ((s (match-string 1)))
9686 (replace-match " |")
9687 (goto-char (match-beginning 0))
9688 (org-table-next-row)
9689 (insert (org-trim s) " ")
9690 (org-table-align))
9691 (org-table-next-row)))))
9693 (defvar org-field-marker nil)
9695 (defun org-table-edit-field (arg)
9696 "Edit table field in a different window.
9697 This is mainly useful for fields that contain hidden parts.
9698 When called with a \\[universal-argument] prefix, just make the full field visible so that
9699 it can be edited in place."
9700 (interactive "P")
9701 (if arg
9702 (let ((b (save-excursion (skip-chars-backward "^|") (point)))
9703 (e (save-excursion (skip-chars-forward "^|\r\n") (point))))
9704 (remove-text-properties b e '(org-cwidth t invisible t
9705 display t intangible t))
9706 (if (and (boundp 'font-lock-mode) font-lock-mode)
9707 (font-lock-fontify-block)))
9708 (let ((pos (move-marker (make-marker) (point)))
9709 (field (org-table-get-field))
9710 (cw (current-window-configuration))
9712 (org-switch-to-buffer-other-window "*Org tmp*")
9713 (erase-buffer)
9714 (insert "#\n# Edit field and finish with C-c C-c\n#\n")
9715 (let ((org-inhibit-startup t)) (org-mode))
9716 (goto-char (setq p (point-max)))
9717 (insert (org-trim field))
9718 (remove-text-properties p (point-max)
9719 '(invisible t org-cwidth t display t
9720 intangible t))
9721 (goto-char p)
9722 (org-set-local 'org-finish-function 'org-table-finish-edit-field)
9723 (org-set-local 'org-window-configuration cw)
9724 (org-set-local 'org-field-marker pos)
9725 (message "Edit and finish with C-c C-c"))))
9727 (defun org-table-finish-edit-field ()
9728 "Finish editing a table data field.
9729 Remove all newline characters, insert the result into the table, realign
9730 the table and kill the editing buffer."
9731 (let ((pos org-field-marker)
9732 (cw org-window-configuration)
9733 (cb (current-buffer))
9734 text)
9735 (goto-char (point-min))
9736 (while (re-search-forward "^#.*\n?" nil t) (replace-match ""))
9737 (while (re-search-forward "\\([ \t]*\n[ \t]*\\)+" nil t)
9738 (replace-match " "))
9739 (setq text (org-trim (buffer-string)))
9740 (set-window-configuration cw)
9741 (kill-buffer cb)
9742 (select-window (get-buffer-window (marker-buffer pos)))
9743 (goto-char pos)
9744 (move-marker pos nil)
9745 (org-table-check-inside-data-field)
9746 (org-table-get-field nil text)
9747 (org-table-align)
9748 (message "New field value inserted")))
9750 (defun org-trim (s)
9751 "Remove whitespace at beginning and end of string."
9752 (if (string-match "\\`[ \t\n\r]+" s) (setq s (replace-match "" t t s)))
9753 (if (string-match "[ \t\n\r]+\\'" s) (setq s (replace-match "" t t s)))
9756 (defun org-wrap (string &optional width lines)
9757 "Wrap string to either a number of lines, or a width in characters.
9758 If WIDTH is non-nil, the string is wrapped to that width, however many lines
9759 that costs. If there is a word longer than WIDTH, the text is actually
9760 wrapped to the length of that word.
9761 IF WIDTH is nil and LINES is non-nil, the string is forced into at most that
9762 many lines, whatever width that takes.
9763 The return value is a list of lines, without newlines at the end."
9764 (let* ((words (org-split-string string "[ \t\n]+"))
9765 (maxword (apply 'max (mapcar 'org-string-width words)))
9766 w ll)
9767 (cond (width
9768 (org-do-wrap words (max maxword width)))
9769 (lines
9770 (setq w maxword)
9771 (setq ll (org-do-wrap words maxword))
9772 (if (<= (length ll) lines)
9774 (setq ll words)
9775 (while (> (length ll) lines)
9776 (setq w (1+ w))
9777 (setq ll (org-do-wrap words w)))
9778 ll))
9779 (t (error "Cannot wrap this")))))
9782 (defun org-do-wrap (words width)
9783 "Create lines of maximum width WIDTH (in characters) from word list WORDS."
9784 (let (lines line)
9785 (while words
9786 (setq line (pop words))
9787 (while (and words (< (+ (length line) (length (car words))) width))
9788 (setq line (concat line " " (pop words))))
9789 (setq lines (push line lines)))
9790 (nreverse lines)))
9792 (defun org-split-string (string &optional separators)
9793 "Splits STRING into substrings at SEPARATORS.
9794 No empty strings are returned if there are matches at the beginning
9795 and end of string."
9796 (let ((rexp (or separators "[ \f\t\n\r\v]+"))
9797 (start 0)
9798 notfirst
9799 (list nil))
9800 (while (and (string-match rexp string
9801 (if (and notfirst
9802 (= start (match-beginning 0))
9803 (< start (length string)))
9804 (1+ start) start))
9805 (< (match-beginning 0) (length string)))
9806 (setq notfirst t)
9807 (or (eq (match-beginning 0) 0)
9808 (and (eq (match-beginning 0) (match-end 0))
9809 (eq (match-beginning 0) start))
9810 (setq list
9811 (cons (substring string start (match-beginning 0))
9812 list)))
9813 (setq start (match-end 0)))
9814 (or (eq start (length string))
9815 (setq list
9816 (cons (substring string start)
9817 list)))
9818 (nreverse list)))
9820 (defun org-table-map-tables (function)
9821 "Apply FUNCTION to the start of all tables in the buffer."
9822 (save-excursion
9823 (save-restriction
9824 (widen)
9825 (goto-char (point-min))
9826 (while (re-search-forward org-table-any-line-regexp nil t)
9827 (message "Mapping tables: %d%%" (/ (* 100.0 (point)) (buffer-size)))
9828 (beginning-of-line 1)
9829 (if (looking-at org-table-line-regexp)
9830 (save-excursion (funcall function)))
9831 (re-search-forward org-table-any-border-regexp nil 1))))
9832 (message "Mapping tables: done"))
9834 (defvar org-timecnt) ; dynamically scoped parameter
9836 (defun org-table-sum (&optional beg end nlast)
9837 "Sum numbers in region of current table column.
9838 The result will be displayed in the echo area, and will be available
9839 as kill to be inserted with \\[yank].
9841 If there is an active region, it is interpreted as a rectangle and all
9842 numbers in that rectangle will be summed. If there is no active
9843 region and point is located in a table column, sum all numbers in that
9844 column.
9846 If at least one number looks like a time HH:MM or HH:MM:SS, all other
9847 numbers are assumed to be times as well (in decimal hours) and the
9848 numbers are added as such.
9850 If NLAST is a number, only the NLAST fields will actually be summed."
9851 (interactive)
9852 (save-excursion
9853 (let (col (org-timecnt 0) diff h m s org-table-clip)
9854 (cond
9855 ((and beg end)) ; beg and end given explicitly
9856 ((org-region-active-p)
9857 (setq beg (region-beginning) end (region-end)))
9859 (setq col (org-table-current-column))
9860 (goto-char (org-table-begin))
9861 (unless (re-search-forward "^[ \t]*|[^-]" nil t)
9862 (error "No table data"))
9863 (org-table-goto-column col)
9864 (setq beg (point))
9865 (goto-char (org-table-end))
9866 (unless (re-search-backward "^[ \t]*|[^-]" nil t)
9867 (error "No table data"))
9868 (org-table-goto-column col)
9869 (setq end (point))))
9870 (let* ((items (apply 'append (org-table-copy-region beg end)))
9871 (items1 (cond ((not nlast) items)
9872 ((>= nlast (length items)) items)
9873 (t (setq items (reverse items))
9874 (setcdr (nthcdr (1- nlast) items) nil)
9875 (nreverse items))))
9876 (numbers (delq nil (mapcar 'org-table-get-number-for-summing
9877 items1)))
9878 (res (apply '+ numbers))
9879 (sres (if (= org-timecnt 0)
9880 (format "%g" res)
9881 (setq diff (* 3600 res)
9882 h (floor (/ diff 3600)) diff (mod diff 3600)
9883 m (floor (/ diff 60)) diff (mod diff 60)
9884 s diff)
9885 (format "%d:%02d:%02d" h m s))))
9886 (kill-new sres)
9887 (if (interactive-p)
9888 (message "%s"
9889 (substitute-command-keys
9890 (format "Sum of %d items: %-20s (\\[yank] will insert result into buffer)"
9891 (length numbers) sres))))
9892 sres))))
9894 (defun org-table-get-number-for-summing (s)
9895 (let (n)
9896 (if (string-match "^ *|? *" s)
9897 (setq s (replace-match "" nil nil s)))
9898 (if (string-match " *|? *$" s)
9899 (setq s (replace-match "" nil nil s)))
9900 (setq n (string-to-number s))
9901 (cond
9902 ((and (string-match "0" s)
9903 (string-match "\\`[-+ \t0.edED]+\\'" s)) 0)
9904 ((string-match "\\`[ \t]+\\'" s) nil)
9905 ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?\\'" s)
9906 (let ((h (string-to-number (or (match-string 1 s) "0")))
9907 (m (string-to-number (or (match-string 2 s) "0")))
9908 (s (string-to-number (or (match-string 4 s) "0"))))
9909 (if (boundp 'org-timecnt) (setq org-timecnt (1+ org-timecnt)))
9910 (* 1.0 (+ h (/ m 60.0) (/ s 3600.0)))))
9911 ((equal n 0) nil)
9912 (t n))))
9914 (defun org-table-current-field-formula (&optional key noerror)
9915 "Return the formula active for the current field.
9916 Assumes that specials are in place.
9917 If KEY is given, return the key to this formula.
9918 Otherwise return the formula preceeded with \"=\" or \":=\"."
9919 (let* ((name (car (rassoc (list (org-current-line)
9920 (org-table-current-column))
9921 org-table-named-field-locations)))
9922 (col (org-table-current-column))
9923 (scol (int-to-string col))
9924 (ref (format "@%d$%d" (org-table-current-dline) col))
9925 (stored-list (org-table-get-stored-formulas noerror))
9926 (ass (or (assoc name stored-list)
9927 (assoc ref stored-list)
9928 (assoc scol stored-list))))
9929 (if key
9930 (car ass)
9931 (if ass (concat (if (string-match "^[0-9]+$" (car ass)) "=" ":=")
9932 (cdr ass))))))
9934 (defun org-table-get-formula (&optional equation named)
9935 "Read a formula from the minibuffer, offer stored formula as default.
9936 When NAMED is non-nil, look for a named equation."
9937 (let* ((stored-list (org-table-get-stored-formulas))
9938 (name (car (rassoc (list (org-current-line)
9939 (org-table-current-column))
9940 org-table-named-field-locations)))
9941 (ref (format "@%d$%d" (org-table-current-dline)
9942 (org-table-current-column)))
9943 (refass (assoc ref stored-list))
9944 (scol (if named
9945 (if name name ref)
9946 (int-to-string (org-table-current-column))))
9947 (dummy (and (or name refass) (not named)
9948 (not (y-or-n-p "Replace field formula with column formula? " ))
9949 (error "Abort")))
9950 (name (or name ref))
9951 (org-table-may-need-update nil)
9952 (stored (cdr (assoc scol stored-list)))
9953 (eq (cond
9954 ((and stored equation (string-match "^ *=? *$" equation))
9955 stored)
9956 ((stringp equation)
9957 equation)
9958 (t (org-table-formula-from-user
9959 (read-string
9960 (org-table-formula-to-user
9961 (format "%s formula %s%s="
9962 (if named "Field" "Column")
9963 (if (member (string-to-char scol) '(?$ ?@)) "" "$")
9964 scol))
9965 (if stored (org-table-formula-to-user stored) "")
9966 'org-table-formula-history
9967 )))))
9968 mustsave)
9969 (when (not (string-match "\\S-" eq))
9970 ;; remove formula
9971 (setq stored-list (delq (assoc scol stored-list) stored-list))
9972 (org-table-store-formulas stored-list)
9973 (error "Formula removed"))
9974 (if (string-match "^ *=?" eq) (setq eq (replace-match "" t t eq)))
9975 (if (string-match " *$" eq) (setq eq (replace-match "" t t eq)))
9976 (if (and name (not named))
9977 ;; We set the column equation, delete the named one.
9978 (setq stored-list (delq (assoc name stored-list) stored-list)
9979 mustsave t))
9980 (if stored
9981 (setcdr (assoc scol stored-list) eq)
9982 (setq stored-list (cons (cons scol eq) stored-list)))
9983 (if (or mustsave (not (equal stored eq)))
9984 (org-table-store-formulas stored-list))
9985 eq))
9987 (defun org-table-store-formulas (alist)
9988 "Store the list of formulas below the current table."
9989 (setq alist (sort alist 'org-table-formula-less-p))
9990 (save-excursion
9991 (goto-char (org-table-end))
9992 (if (looking-at "\\([ \t]*\n\\)*#\\+TBLFM:\\(.*\n?\\)")
9993 (progn
9994 ;; don't overwrite TBLFM, we might use text properties to store stuff
9995 (goto-char (match-beginning 2))
9996 (delete-region (match-beginning 2) (match-end 0)))
9997 (insert "#+TBLFM:"))
9998 (insert " "
9999 (mapconcat (lambda (x)
10000 (concat
10001 (if (equal (string-to-char (car x)) ?@) "" "$")
10002 (car x) "=" (cdr x)))
10003 alist "::")
10004 "\n")))
10006 (defsubst org-table-formula-make-cmp-string (a)
10007 (when (string-match "^\\(@\\([0-9]+\\)\\)?\\(\\$?\\([0-9]+\\)\\)?\\(\\$?[a-zA-Z0-9]+\\)?" a)
10008 (concat
10009 (if (match-end 2) (format "@%05d" (string-to-number (match-string 2 a))) "")
10010 (if (match-end 4) (format "$%05d" (string-to-number (match-string 4 a))) "")
10011 (if (match-end 5) (concat "@@" (match-string 5 a))))))
10013 (defun org-table-formula-less-p (a b)
10014 "Compare two formulas for sorting."
10015 (let ((as (org-table-formula-make-cmp-string (car a)))
10016 (bs (org-table-formula-make-cmp-string (car b))))
10017 (and as bs (string< as bs))))
10019 (defun org-table-get-stored-formulas (&optional noerror)
10020 "Return an alist with the stored formulas directly after current table."
10021 (interactive)
10022 (let (scol eq eq-alist strings string seen)
10023 (save-excursion
10024 (goto-char (org-table-end))
10025 (when (looking-at "\\([ \t]*\n\\)*#\\+TBLFM: *\\(.*\\)")
10026 (setq strings (org-split-string (match-string 2) " *:: *"))
10027 (while (setq string (pop strings))
10028 (when (string-match "\\(@[0-9]+\\$[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*[^ \t]\\)" string)
10029 (setq scol (if (match-end 2)
10030 (match-string 2 string)
10031 (match-string 1 string))
10032 eq (match-string 3 string)
10033 eq-alist (cons (cons scol eq) eq-alist))
10034 (if (member scol seen)
10035 (if noerror
10036 (progn
10037 (message "Double definition `$%s=' in TBLFM line, please fix by hand" scol)
10038 (ding)
10039 (sit-for 2))
10040 (error "Double definition `$%s=' in TBLFM line, please fix by hand" scol))
10041 (push scol seen))))))
10042 (nreverse eq-alist)))
10044 (defun org-table-fix-formulas (key replace &optional limit delta remove)
10045 "Modify the equations after the table structure has been edited.
10046 KEY is \"@\" or \"$\". REPLACE is an alist of numbers to replace.
10047 For all numbers larger than LIMIT, shift them by DELTA."
10048 (save-excursion
10049 (goto-char (org-table-end))
10050 (when (looking-at "#\\+TBLFM:")
10051 (let ((re (concat key "\\([0-9]+\\)"))
10052 (re2
10053 (when remove
10054 (if (equal key "$")
10055 (format "\\(@[0-9]+\\)?\\$%d=.*?\\(::\\|$\\)" remove)
10056 (format "@%d\\$[0-9]+=.*?\\(::\\|$\\)" remove))))
10057 s n a)
10058 (when remove
10059 (while (re-search-forward re2 (point-at-eol) t)
10060 (replace-match "")))
10061 (while (re-search-forward re (point-at-eol) t)
10062 (setq s (match-string 1) n (string-to-number s))
10063 (cond
10064 ((setq a (assoc s replace))
10065 (replace-match (concat key (cdr a)) t t))
10066 ((and limit (> n limit))
10067 (replace-match (concat key (int-to-string (+ n delta))) t t))))))))
10069 (defun org-table-get-specials ()
10070 "Get the column names and local parameters for this table."
10071 (save-excursion
10072 (let ((beg (org-table-begin)) (end (org-table-end))
10073 names name fields fields1 field cnt
10074 c v l line col types dlines hlines)
10075 (setq org-table-column-names nil
10076 org-table-local-parameters nil
10077 org-table-named-field-locations nil
10078 org-table-current-begin-line nil
10079 org-table-current-begin-pos nil
10080 org-table-current-line-types nil)
10081 (goto-char beg)
10082 (when (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t)
10083 (setq names (org-split-string (match-string 1) " *| *")
10084 cnt 1)
10085 (while (setq name (pop names))
10086 (setq cnt (1+ cnt))
10087 (if (string-match "^[a-zA-Z][a-zA-Z0-9]*$" name)
10088 (push (cons name (int-to-string cnt)) org-table-column-names))))
10089 (setq org-table-column-names (nreverse org-table-column-names))
10090 (setq org-table-column-name-regexp
10091 (concat "\\$\\(" (mapconcat 'car org-table-column-names "\\|") "\\)\\>"))
10092 (goto-char beg)
10093 (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t)
10094 (setq fields (org-split-string (match-string 1) " *| *"))
10095 (while (setq field (pop fields))
10096 (if (string-match "^\\([a-zA-Z][_a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field)
10097 (push (cons (match-string 1 field) (match-string 2 field))
10098 org-table-local-parameters))))
10099 (goto-char beg)
10100 (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t)
10101 (setq c (match-string 1)
10102 fields (org-split-string (match-string 2) " *| *"))
10103 (save-excursion
10104 (beginning-of-line (if (equal c "_") 2 0))
10105 (setq line (org-current-line) col 1)
10106 (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)")
10107 (setq fields1 (org-split-string (match-string 1) " *| *"))))
10108 (while (and fields1 (setq field (pop fields)))
10109 (setq v (pop fields1) col (1+ col))
10110 (when (and (stringp field) (stringp v)
10111 (string-match "^[a-zA-Z][a-zA-Z0-9]*$" field))
10112 (push (cons field v) org-table-local-parameters)
10113 (push (list field line col) org-table-named-field-locations))))
10114 ;; Analyse the line types
10115 (goto-char beg)
10116 (setq org-table-current-begin-line (org-current-line)
10117 org-table-current-begin-pos (point)
10118 l org-table-current-begin-line)
10119 (while (looking-at "[ \t]*|\\(-\\)?")
10120 (push (if (match-end 1) 'hline 'dline) types)
10121 (if (match-end 1) (push l hlines) (push l dlines))
10122 (beginning-of-line 2)
10123 (setq l (1+ l)))
10124 (setq org-table-current-line-types (apply 'vector (nreverse types))
10125 org-table-dlines (apply 'vector (cons nil (nreverse dlines)))
10126 org-table-hlines (apply 'vector (cons nil (nreverse hlines)))))))
10128 (defun org-table-maybe-eval-formula ()
10129 "Check if the current field starts with \"=\" or \":=\".
10130 If yes, store the formula and apply it."
10131 ;; We already know we are in a table. Get field will only return a formula
10132 ;; when appropriate. It might return a separator line, but no problem.
10133 (when org-table-formula-evaluate-inline
10134 (let* ((field (org-trim (or (org-table-get-field) "")))
10135 named eq)
10136 (when (string-match "^:?=\\(.*\\)" field)
10137 (setq named (equal (string-to-char field) ?:)
10138 eq (match-string 1 field))
10139 (if (or (fboundp 'calc-eval)
10140 (equal (substring eq 0 (min 2 (length eq))) "'("))
10141 (org-table-eval-formula (if named '(4) nil)
10142 (org-table-formula-from-user eq))
10143 (error "Calc does not seem to be installed, and is needed to evaluate the formula"))))))
10145 (defvar org-recalc-commands nil
10146 "List of commands triggering the recalculation of a line.
10147 Will be filled automatically during use.")
10149 (defvar org-recalc-marks
10150 '((" " . "Unmarked: no special line, no automatic recalculation")
10151 ("#" . "Automatically recalculate this line upon TAB, RET, and C-c C-c in the line")
10152 ("*" . "Recalculate only when entire table is recalculated with `C-u C-c *'")
10153 ("!" . "Column name definition line. Reference in formula as $name.")
10154 ("$" . "Parameter definition line name=value. Reference in formula as $name.")
10155 ("_" . "Names for values in row below this one.")
10156 ("^" . "Names for values in row above this one.")))
10158 (defun org-table-rotate-recalc-marks (&optional newchar)
10159 "Rotate the recalculation mark in the first column.
10160 If in any row, the first field is not consistent with a mark,
10161 insert a new column for the markers.
10162 When there is an active region, change all the lines in the region,
10163 after prompting for the marking character.
10164 After each change, a message will be displayed indicating the meaning
10165 of the new mark."
10166 (interactive)
10167 (unless (org-at-table-p) (error "Not at a table"))
10168 (let* ((marks (append (mapcar 'car org-recalc-marks) '(" ")))
10169 (beg (org-table-begin))
10170 (end (org-table-end))
10171 (l (org-current-line))
10172 (l1 (if (org-region-active-p) (org-current-line (region-beginning))))
10173 (l2 (if (org-region-active-p) (org-current-line (region-end))))
10174 (have-col
10175 (save-excursion
10176 (goto-char beg)
10177 (not (re-search-forward "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" end t))))
10178 (col (org-table-current-column))
10179 (forcenew (car (assoc newchar org-recalc-marks)))
10180 epos new)
10181 (when l1
10182 (message "Change region to what mark? Type # * ! $ or SPC: ")
10183 (setq newchar (char-to-string (read-char-exclusive))
10184 forcenew (car (assoc newchar org-recalc-marks))))
10185 (if (and newchar (not forcenew))
10186 (error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'"
10187 newchar))
10188 (if l1 (goto-line l1))
10189 (save-excursion
10190 (beginning-of-line 1)
10191 (unless (looking-at org-table-dataline-regexp)
10192 (error "Not at a table data line")))
10193 (unless have-col
10194 (org-table-goto-column 1)
10195 (org-table-insert-column)
10196 (org-table-goto-column (1+ col)))
10197 (setq epos (point-at-eol))
10198 (save-excursion
10199 (beginning-of-line 1)
10200 (org-table-get-field
10201 1 (if (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|")
10202 (concat " "
10203 (setq new (or forcenew
10204 (cadr (member (match-string 1) marks))))
10205 " ")
10206 " # ")))
10207 (if (and l1 l2)
10208 (progn
10209 (goto-line l1)
10210 (while (progn (beginning-of-line 2) (not (= (org-current-line) l2)))
10211 (and (looking-at org-table-dataline-regexp)
10212 (org-table-get-field 1 (concat " " new " "))))
10213 (goto-line l1)))
10214 (if (not (= epos (point-at-eol))) (org-table-align))
10215 (goto-line l)
10216 (and (interactive-p) (message "%s" (cdr (assoc new org-recalc-marks))))))
10218 (defun org-table-maybe-recalculate-line ()
10219 "Recompute the current line if marked for it, and if we haven't just done it."
10220 (interactive)
10221 (and org-table-allow-automatic-line-recalculation
10222 (not (and (memq last-command org-recalc-commands)
10223 (equal org-last-recalc-line (org-current-line))))
10224 (save-excursion (beginning-of-line 1)
10225 (looking-at org-table-auto-recalculate-regexp))
10226 (org-table-recalculate) t))
10228 (defvar org-table-formula-debug nil
10229 "Non-nil means, debug table formulas.
10230 When nil, simply write \"#ERROR\" in corrupted fields.")
10231 (make-variable-buffer-local 'org-table-formula-debug)
10233 (defvar modes)
10234 (defsubst org-set-calc-mode (var &optional value)
10235 (if (stringp var)
10236 (setq var (assoc var '(("D" calc-angle-mode deg)
10237 ("R" calc-angle-mode rad)
10238 ("F" calc-prefer-frac t)
10239 ("S" calc-symbolic-mode t)))
10240 value (nth 2 var) var (nth 1 var)))
10241 (if (memq var modes)
10242 (setcar (cdr (memq var modes)) value)
10243 (cons var (cons value modes)))
10244 modes)
10246 (defun org-table-eval-formula (&optional arg equation
10247 suppress-align suppress-const
10248 suppress-store suppress-analysis)
10249 "Replace the table field value at the cursor by the result of a calculation.
10251 This function makes use of Dave Gillespie's Calc package, in my view the
10252 most exciting program ever written for GNU Emacs. So you need to have Calc
10253 installed in order to use this function.
10255 In a table, this command replaces the value in the current field with the
10256 result of a formula. It also installs the formula as the \"current\" column
10257 formula, by storing it in a special line below the table. When called
10258 with a `C-u' prefix, the current field must ba a named field, and the
10259 formula is installed as valid in only this specific field.
10261 When called with two `C-u' prefixes, insert the active equation
10262 for the field back into the current field, so that it can be
10263 edited there. This is useful in order to use \\[org-table-show-reference]
10264 to check the referenced fields.
10266 When called, the command first prompts for a formula, which is read in
10267 the minibuffer. Previously entered formulas are available through the
10268 history list, and the last used formula is offered as a default.
10269 These stored formulas are adapted correctly when moving, inserting, or
10270 deleting columns with the corresponding commands.
10272 The formula can be any algebraic expression understood by the Calc package.
10273 For details, see the Org-mode manual.
10275 This function can also be called from Lisp programs and offers
10276 additional arguments: EQUATION can be the formula to apply. If this
10277 argument is given, the user will not be prompted. SUPPRESS-ALIGN is
10278 used to speed-up recursive calls by by-passing unnecessary aligns.
10279 SUPPRESS-CONST suppresses the interpretation of constants in the
10280 formula, assuming that this has been done already outside the function.
10281 SUPPRESS-STORE means the formula should not be stored, either because
10282 it is already stored, or because it is a modified equation that should
10283 not overwrite the stored one."
10284 (interactive "P")
10285 (org-table-check-inside-data-field)
10286 (or suppress-analysis (org-table-get-specials))
10287 (if (equal arg '(16))
10288 (let ((eq (org-table-current-field-formula)))
10289 (or eq (error "No equation active for current field"))
10290 (org-table-get-field nil eq)
10291 (org-table-align)
10292 (setq org-table-may-need-update t))
10293 (let* (fields
10294 (ndown (if (integerp arg) arg 1))
10295 (org-table-automatic-realign nil)
10296 (case-fold-search nil)
10297 (down (> ndown 1))
10298 (formula (if (and equation suppress-store)
10299 equation
10300 (org-table-get-formula equation (equal arg '(4)))))
10301 (n0 (org-table-current-column))
10302 (modes (copy-sequence org-calc-default-modes))
10303 (numbers nil) ; was a variable, now fixed default
10304 (keep-empty nil)
10305 n form form0 bw fmt x ev orig c lispp literal)
10306 ;; Parse the format string. Since we have a lot of modes, this is
10307 ;; a lot of work. However, I think calc still uses most of the time.
10308 (if (string-match ";" formula)
10309 (let ((tmp (org-split-string formula ";")))
10310 (setq formula (car tmp)
10311 fmt (concat (cdr (assoc "%" org-table-local-parameters))
10312 (nth 1 tmp)))
10313 (while (string-match "\\([pnfse]\\)\\(-?[0-9]+\\)" fmt)
10314 (setq c (string-to-char (match-string 1 fmt))
10315 n (string-to-number (match-string 2 fmt)))
10316 (if (= c ?p)
10317 (setq modes (org-set-calc-mode 'calc-internal-prec n))
10318 (setq modes (org-set-calc-mode
10319 'calc-float-format
10320 (list (cdr (assoc c '((?n . float) (?f . fix)
10321 (?s . sci) (?e . eng))))
10322 n))))
10323 (setq fmt (replace-match "" t t fmt)))
10324 (if (string-match "[NT]" fmt)
10325 (setq numbers (equal (match-string 0 fmt) "N")
10326 fmt (replace-match "" t t fmt)))
10327 (if (string-match "L" fmt)
10328 (setq literal t
10329 fmt (replace-match "" t t fmt)))
10330 (if (string-match "E" fmt)
10331 (setq keep-empty t
10332 fmt (replace-match "" t t fmt)))
10333 (while (string-match "[DRFS]" fmt)
10334 (setq modes (org-set-calc-mode (match-string 0 fmt)))
10335 (setq fmt (replace-match "" t t fmt)))
10336 (unless (string-match "\\S-" fmt)
10337 (setq fmt nil))))
10338 (if (and (not suppress-const) org-table-formula-use-constants)
10339 (setq formula (org-table-formula-substitute-names formula)))
10340 (setq orig (or (get-text-property 1 :orig-formula formula) "?"))
10341 (while (> ndown 0)
10342 (setq fields (org-split-string
10343 (org-no-properties
10344 (buffer-substring (point-at-bol) (point-at-eol)))
10345 " *| *"))
10346 (if (eq numbers t)
10347 (setq fields (mapcar
10348 (lambda (x) (number-to-string (string-to-number x)))
10349 fields)))
10350 (setq ndown (1- ndown))
10351 (setq form (copy-sequence formula)
10352 lispp (and (> (length form) 2)(equal (substring form 0 2) "'(")))
10353 (if (and lispp literal) (setq lispp 'literal))
10354 ;; Check for old vertical references
10355 (setq form (org-rewrite-old-row-references form))
10356 ;; Insert complex ranges
10357 (while (string-match org-table-range-regexp form)
10358 (setq form
10359 (replace-match
10360 (save-match-data
10361 (org-table-make-reference
10362 (org-table-get-range (match-string 0 form) nil n0)
10363 keep-empty numbers lispp))
10364 t t form)))
10365 ;; Insert simple ranges
10366 (while (string-match "\\$\\([0-9]+\\)\\.\\.\\$\\([0-9]+\\)" form)
10367 (setq form
10368 (replace-match
10369 (save-match-data
10370 (org-table-make-reference
10371 (org-sublist
10372 fields (string-to-number (match-string 1 form))
10373 (string-to-number (match-string 2 form)))
10374 keep-empty numbers lispp))
10375 t t form)))
10376 (setq form0 form)
10377 ;; Insert the references to fields in same row
10378 (while (string-match "\\$\\([0-9]+\\)" form)
10379 (setq n (string-to-number (match-string 1 form))
10380 x (nth (1- (if (= n 0) n0 n)) fields))
10381 (unless x (error "Invalid field specifier \"%s\""
10382 (match-string 0 form)))
10383 (setq form (replace-match
10384 (save-match-data
10385 (org-table-make-reference x nil numbers lispp))
10386 t t form)))
10388 (if lispp
10389 (setq ev (condition-case nil
10390 (eval (eval (read form)))
10391 (error "#ERROR"))
10392 ev (if (numberp ev) (number-to-string ev) ev))
10393 (or (fboundp 'calc-eval)
10394 (error "Calc does not seem to be installed, and is needed to evaluate the formula"))
10395 (setq ev (calc-eval (cons form modes)
10396 (if numbers 'num))))
10398 (when org-table-formula-debug
10399 (with-output-to-temp-buffer "*Substitution History*"
10400 (princ (format "Substitution history of formula
10401 Orig: %s
10402 $xyz-> %s
10403 @r$c-> %s
10404 $1-> %s\n" orig formula form0 form))
10405 (if (listp ev)
10406 (princ (format " %s^\nError: %s"
10407 (make-string (car ev) ?\-) (nth 1 ev)))
10408 (princ (format "Result: %s\nFormat: %s\nFinal: %s"
10409 ev (or fmt "NONE")
10410 (if fmt (format fmt (string-to-number ev)) ev)))))
10411 (setq bw (get-buffer-window "*Substitution History*"))
10412 (shrink-window-if-larger-than-buffer bw)
10413 (unless (and (interactive-p) (not ndown))
10414 (unless (let (inhibit-redisplay)
10415 (y-or-n-p "Debugging Formula. Continue to next? "))
10416 (org-table-align)
10417 (error "Abort"))
10418 (delete-window bw)
10419 (message "")))
10420 (if (listp ev) (setq fmt nil ev "#ERROR"))
10421 (org-table-justify-field-maybe
10422 (if fmt (format fmt (string-to-number ev)) ev))
10423 (if (and down (> ndown 0) (looking-at ".*\n[ \t]*|[^-]"))
10424 (call-interactively 'org-return)
10425 (setq ndown 0)))
10426 (and down (org-table-maybe-recalculate-line))
10427 (or suppress-align (and org-table-may-need-update
10428 (org-table-align))))))
10430 (defun org-table-put-field-property (prop value)
10431 (save-excursion
10432 (put-text-property (progn (skip-chars-backward "^|") (point))
10433 (progn (skip-chars-forward "^|") (point))
10434 prop value)))
10436 (defun org-table-get-range (desc &optional tbeg col highlight)
10437 "Get a calc vector from a column, accorting to descriptor DESC.
10438 Optional arguments TBEG and COL can give the beginning of the table and
10439 the current column, to avoid unnecessary parsing.
10440 HIGHLIGHT means, just highlight the range."
10441 (if (not (equal (string-to-char desc) ?@))
10442 (setq desc (concat "@" desc)))
10443 (save-excursion
10444 (or tbeg (setq tbeg (org-table-begin)))
10445 (or col (setq col (org-table-current-column)))
10446 (let ((thisline (org-current-line))
10447 beg end c1 c2 r1 r2 rangep tmp)
10448 (unless (string-match org-table-range-regexp desc)
10449 (error "Invalid table range specifier `%s'" desc))
10450 (setq rangep (match-end 3)
10451 r1 (and (match-end 1) (match-string 1 desc))
10452 r2 (and (match-end 4) (match-string 4 desc))
10453 c1 (and (match-end 2) (substring (match-string 2 desc) 1))
10454 c2 (and (match-end 5) (substring (match-string 5 desc) 1)))
10456 (and c1 (setq c1 (+ (string-to-number c1)
10457 (if (memq (string-to-char c1) '(?- ?+)) col 0))))
10458 (and c2 (setq c2 (+ (string-to-number c2)
10459 (if (memq (string-to-char c2) '(?- ?+)) col 0))))
10460 (if (equal r1 "") (setq r1 nil))
10461 (if (equal r2 "") (setq r2 nil))
10462 (if r1 (setq r1 (org-table-get-descriptor-line r1)))
10463 (if r2 (setq r2 (org-table-get-descriptor-line r2)))
10464 ; (setq r2 (or r2 r1) c2 (or c2 c1))
10465 (if (not r1) (setq r1 thisline))
10466 (if (not r2) (setq r2 thisline))
10467 (if (not c1) (setq c1 col))
10468 (if (not c2) (setq c2 col))
10469 (if (or (not rangep) (and (= r1 r2) (= c1 c2)))
10470 ;; just one field
10471 (progn
10472 (goto-line r1)
10473 (while (not (looking-at org-table-dataline-regexp))
10474 (beginning-of-line 2))
10475 (prog1 (org-trim (org-table-get-field c1))
10476 (if highlight (org-table-highlight-rectangle (point) (point)))))
10477 ;; A range, return a vector
10478 ;; First sort the numbers to get a regular ractangle
10479 (if (< r2 r1) (setq tmp r1 r1 r2 r2 tmp))
10480 (if (< c2 c1) (setq tmp c1 c1 c2 c2 tmp))
10481 (goto-line r1)
10482 (while (not (looking-at org-table-dataline-regexp))
10483 (beginning-of-line 2))
10484 (org-table-goto-column c1)
10485 (setq beg (point))
10486 (goto-line r2)
10487 (while (not (looking-at org-table-dataline-regexp))
10488 (beginning-of-line 0))
10489 (org-table-goto-column c2)
10490 (setq end (point))
10491 (if highlight
10492 (org-table-highlight-rectangle
10493 beg (progn (skip-chars-forward "^|\n") (point))))
10494 ;; return string representation of calc vector
10495 (mapcar 'org-trim
10496 (apply 'append (org-table-copy-region beg end)))))))
10498 (defun org-table-get-descriptor-line (desc &optional cline bline table)
10499 "Analyze descriptor DESC and retrieve the corresponding line number.
10500 The cursor is currently in line CLINE, the table begins in line BLINE,
10501 and TABLE is a vector with line types."
10502 (if (string-match "^[0-9]+$" desc)
10503 (aref org-table-dlines (string-to-number desc))
10504 (setq cline (or cline (org-current-line))
10505 bline (or bline org-table-current-begin-line)
10506 table (or table org-table-current-line-types))
10507 (if (or
10508 (not (string-match "^\\(\\([-+]\\)?\\(I+\\)\\)?\\(\\([-+]\\)?\\([0-9]+\\)\\)?" desc))
10509 ;; 1 2 3 4 5 6
10510 (and (not (match-end 3)) (not (match-end 6)))
10511 (and (match-end 3) (match-end 6) (not (match-end 5))))
10512 (error "invalid row descriptor `%s'" desc))
10513 (let* ((hdir (and (match-end 2) (match-string 2 desc)))
10514 (hn (if (match-end 3) (- (match-end 3) (match-beginning 3)) nil))
10515 (odir (and (match-end 5) (match-string 5 desc)))
10516 (on (if (match-end 6) (string-to-number (match-string 6 desc))))
10517 (i (- cline bline))
10518 (rel (and (match-end 6)
10519 (or (and (match-end 1) (not (match-end 3)))
10520 (match-end 5)))))
10521 (if (and hn (not hdir))
10522 (progn
10523 (setq i 0 hdir "+")
10524 (if (eq (aref table 0) 'hline) (setq hn (1- hn)))))
10525 (if (and (not hn) on (not odir))
10526 (error "should never happen");;(aref org-table-dlines on)
10527 (if (and hn (> hn 0))
10528 (setq i (org-find-row-type table i 'hline (equal hdir "-") nil hn)))
10529 (if on
10530 (setq i (org-find-row-type table i 'dline (equal odir "-") rel on)))
10531 (+ bline i)))))
10533 (defun org-find-row-type (table i type backwards relative n)
10534 (let ((l (length table)))
10535 (while (> n 0)
10536 (while (and (setq i (+ i (if backwards -1 1)))
10537 (>= i 0) (< i l)
10538 (not (eq (aref table i) type))
10539 (if (and relative (eq (aref table i) 'hline))
10540 (progn (setq i (- i (if backwards -1 1)) n 1) nil)
10541 t)))
10542 (setq n (1- n)))
10543 (if (or (< i 0) (>= i l))
10544 (error "Row descriptor leads outside table")
10545 i)))
10547 (defun org-rewrite-old-row-references (s)
10548 (if (string-match "&[-+0-9I]" s)
10549 (error "Formula contains old &row reference, please rewrite using @-syntax")
10552 (defun org-table-make-reference (elements keep-empty numbers lispp)
10553 "Convert list ELEMENTS to something appropriate to insert into formula.
10554 KEEP-EMPTY indicated to keep empty fields, default is to skip them.
10555 NUMBERS indicates that everything should be converted to numbers.
10556 LISPP means to return something appropriate for a Lisp list."
10557 (if (stringp elements) ; just a single val
10558 (if lispp
10559 (if (eq lispp 'literal)
10560 elements
10561 (prin1-to-string (if numbers (string-to-number elements) elements)))
10562 (if (equal elements "") (setq elements "0"))
10563 (if numbers (number-to-string (string-to-number elements)) elements))
10564 (unless keep-empty
10565 (setq elements
10566 (delq nil
10567 (mapcar (lambda (x) (if (string-match "\\S-" x) x nil))
10568 elements))))
10569 (setq elements (or elements '("0")))
10570 (if lispp
10571 (mapconcat
10572 (lambda (x)
10573 (if (eq lispp 'literal)
10575 (prin1-to-string (if numbers (string-to-number x) x))))
10576 elements " ")
10577 (concat "[" (mapconcat
10578 (lambda (x)
10579 (if numbers (number-to-string (string-to-number x)) x))
10580 elements
10581 ",") "]"))))
10583 (defun org-table-recalculate (&optional all noalign)
10584 "Recalculate the current table line by applying all stored formulas.
10585 With prefix arg ALL, do this for all lines in the table."
10586 (interactive "P")
10587 (or (memq this-command org-recalc-commands)
10588 (setq org-recalc-commands (cons this-command org-recalc-commands)))
10589 (unless (org-at-table-p) (error "Not at a table"))
10590 (if (equal all '(16))
10591 (org-table-iterate)
10592 (org-table-get-specials)
10593 (let* ((eqlist (sort (org-table-get-stored-formulas)
10594 (lambda (a b) (string< (car a) (car b)))))
10595 (inhibit-redisplay (not debug-on-error))
10596 (line-re org-table-dataline-regexp)
10597 (thisline (org-current-line))
10598 (thiscol (org-table-current-column))
10599 beg end entry eqlnum eqlname eqlname1 eql (cnt 0) eq a name)
10600 ;; Insert constants in all formulas
10601 (setq eqlist
10602 (mapcar (lambda (x)
10603 (setcdr x (org-table-formula-substitute-names (cdr x)))
10605 eqlist))
10606 ;; Split the equation list
10607 (while (setq eq (pop eqlist))
10608 (if (<= (string-to-char (car eq)) ?9)
10609 (push eq eqlnum)
10610 (push eq eqlname)))
10611 (setq eqlnum (nreverse eqlnum) eqlname (nreverse eqlname))
10612 (if all
10613 (progn
10614 (setq end (move-marker (make-marker) (1+ (org-table-end))))
10615 (goto-char (setq beg (org-table-begin)))
10616 (if (re-search-forward org-table-calculate-mark-regexp end t)
10617 ;; This is a table with marked lines, compute selected lines
10618 (setq line-re org-table-recalculate-regexp)
10619 ;; Move forward to the first non-header line
10620 (if (and (re-search-forward org-table-dataline-regexp end t)
10621 (re-search-forward org-table-hline-regexp end t)
10622 (re-search-forward org-table-dataline-regexp end t))
10623 (setq beg (match-beginning 0))
10624 nil))) ;; just leave beg where it is
10625 (setq beg (point-at-bol)
10626 end (move-marker (make-marker) (1+ (point-at-eol)))))
10627 (goto-char beg)
10628 (and all (message "Re-applying formulas to full table..."))
10630 ;; First find the named fields, and mark them untouchanble
10631 (remove-text-properties beg end '(org-untouchable t))
10632 (while (setq eq (pop eqlname))
10633 (setq name (car eq)
10634 a (assoc name org-table-named-field-locations))
10635 (and (not a)
10636 (string-match "@\\([0-9]+\\)\\$\\([0-9]+\\)" name)
10637 (setq a (list name
10638 (aref org-table-dlines
10639 (string-to-number (match-string 1 name)))
10640 (string-to-number (match-string 2 name)))))
10641 (when (and a (or all (equal (nth 1 a) thisline)))
10642 (message "Re-applying formula to field: %s" name)
10643 (goto-line (nth 1 a))
10644 (org-table-goto-column (nth 2 a))
10645 (push (append a (list (cdr eq))) eqlname1)
10646 (org-table-put-field-property :org-untouchable t)))
10648 ;; Now evauluate the column formulas, but skip fields covered by
10649 ;; field formulas
10650 (goto-char beg)
10651 (while (re-search-forward line-re end t)
10652 (unless (string-match "^ *[_^!$/] *$" (org-table-get-field 1))
10653 ;; Unprotected line, recalculate
10654 (and all (message "Re-applying formulas to full table...(line %d)"
10655 (setq cnt (1+ cnt))))
10656 (setq org-last-recalc-line (org-current-line))
10657 (setq eql eqlnum)
10658 (while (setq entry (pop eql))
10659 (goto-line org-last-recalc-line)
10660 (org-table-goto-column (string-to-number (car entry)) nil 'force)
10661 (unless (get-text-property (point) :org-untouchable)
10662 (org-table-eval-formula nil (cdr entry)
10663 'noalign 'nocst 'nostore 'noanalysis)))))
10665 ;; Now evaluate the field formulas
10666 (while (setq eq (pop eqlname1))
10667 (message "Re-applying formula to field: %s" (car eq))
10668 (goto-line (nth 1 eq))
10669 (org-table-goto-column (nth 2 eq))
10670 (org-table-eval-formula nil (nth 3 eq) 'noalign 'nocst
10671 'nostore 'noanalysis))
10673 (goto-line thisline)
10674 (org-table-goto-column thiscol)
10675 (remove-text-properties (point-min) (point-max) '(org-untouchable t))
10676 (or noalign (and org-table-may-need-update (org-table-align))
10677 (and all (message "Re-applying formulas to %d lines...done" cnt)))
10679 ;; back to initial position
10680 (message "Re-applying formulas...done")
10681 (goto-line thisline)
10682 (org-table-goto-column thiscol)
10683 (or noalign (and org-table-may-need-update (org-table-align))
10684 (and all (message "Re-applying formulas...done"))))))
10686 (defun org-table-iterate (&optional arg)
10687 "Recalculate the table until it does not change anymore."
10688 (interactive "P")
10689 (let ((imax (if arg (prefix-numeric-value arg) 10))
10690 (i 0)
10691 (lasttbl (buffer-substring (org-table-begin) (org-table-end)))
10692 thistbl)
10693 (catch 'exit
10694 (while (< i imax)
10695 (setq i (1+ i))
10696 (org-table-recalculate 'all)
10697 (setq thistbl (buffer-substring (org-table-begin) (org-table-end)))
10698 (if (not (string= lasttbl thistbl))
10699 (setq lasttbl thistbl)
10700 (if (> i 1)
10701 (message "Convergence after %d iterations" i)
10702 (message "Table was already stable"))
10703 (throw 'exit t)))
10704 (error "No convergence after %d iterations" i))))
10706 (defun org-table-formula-substitute-names (f)
10707 "Replace $const with values in string F."
10708 (let ((start 0) a (f1 f) (pp (/= (string-to-char f) ?')))
10709 ;; First, check for column names
10710 (while (setq start (string-match org-table-column-name-regexp f start))
10711 (setq start (1+ start))
10712 (setq a (assoc (match-string 1 f) org-table-column-names))
10713 (setq f (replace-match (concat "$" (cdr a)) t t f)))
10714 ;; Parameters and constants
10715 (setq start 0)
10716 (while (setq start (string-match "\\$\\([a-zA-Z][_a-zA-Z0-9]*\\)" f start))
10717 (setq start (1+ start))
10718 (if (setq a (save-match-data
10719 (org-table-get-constant (match-string 1 f))))
10720 (setq f (replace-match
10721 (concat (if pp "(") a (if pp ")")) t t f))))
10722 (if org-table-formula-debug
10723 (put-text-property 0 (length f) :orig-formula f1 f))
10726 (defun org-table-get-constant (const)
10727 "Find the value for a parameter or constant in a formula.
10728 Parameters get priority."
10729 (or (cdr (assoc const org-table-local-parameters))
10730 (cdr (assoc const org-table-formula-constants-local))
10731 (cdr (assoc const org-table-formula-constants))
10732 (and (fboundp 'constants-get) (constants-get const))
10733 (and (string= (substring const 0 (min 5 (length const))) "PROP_")
10734 (org-entry-get nil (substring const 5) 'inherit))
10735 "#UNDEFINED_NAME"))
10737 (defvar org-table-fedit-map
10738 (let ((map (make-sparse-keymap)))
10739 (org-defkey map "\C-x\C-s" 'org-table-fedit-finish)
10740 (org-defkey map "\C-c\C-s" 'org-table-fedit-finish)
10741 (org-defkey map "\C-c\C-c" 'org-table-fedit-finish)
10742 (org-defkey map "\C-c\C-q" 'org-table-fedit-abort)
10743 (org-defkey map "\C-c?" 'org-table-show-reference)
10744 (org-defkey map [(meta shift up)] 'org-table-fedit-line-up)
10745 (org-defkey map [(meta shift down)] 'org-table-fedit-line-down)
10746 (org-defkey map [(shift up)] 'org-table-fedit-ref-up)
10747 (org-defkey map [(shift down)] 'org-table-fedit-ref-down)
10748 (org-defkey map [(shift left)] 'org-table-fedit-ref-left)
10749 (org-defkey map [(shift right)] 'org-table-fedit-ref-right)
10750 (org-defkey map [(meta up)] 'org-table-fedit-scroll-down)
10751 (org-defkey map [(meta down)] 'org-table-fedit-scroll)
10752 (org-defkey map [(meta tab)] 'lisp-complete-symbol)
10753 (org-defkey map "\M-\C-i" 'lisp-complete-symbol)
10754 (org-defkey map [(tab)] 'org-table-fedit-lisp-indent)
10755 (org-defkey map "\C-i" 'org-table-fedit-lisp-indent)
10756 (org-defkey map "\C-c\C-r" 'org-table-fedit-toggle-ref-type)
10757 (org-defkey map "\C-c}" 'org-table-fedit-toggle-coordinates)
10758 map))
10760 (easy-menu-define org-table-fedit-menu org-table-fedit-map "Org Edit Formulas Menu"
10761 '("Edit-Formulas"
10762 ["Finish and Install" org-table-fedit-finish t]
10763 ["Finish, Install, and Apply" (org-table-fedit-finish t) :keys "C-u C-c C-c"]
10764 ["Abort" org-table-fedit-abort t]
10765 "--"
10766 ["Pretty-Print Lisp Formula" org-table-fedit-lisp-indent t]
10767 ["Complete Lisp Symbol" lisp-complete-symbol t]
10768 "--"
10769 "Shift Reference at Point"
10770 ["Up" org-table-fedit-ref-up t]
10771 ["Down" org-table-fedit-ref-down t]
10772 ["Left" org-table-fedit-ref-left t]
10773 ["Right" org-table-fedit-ref-right t]
10775 "Change Test Row for Column Formulas"
10776 ["Up" org-table-fedit-line-up t]
10777 ["Down" org-table-fedit-line-down t]
10778 "--"
10779 ["Scroll Table Window" org-table-fedit-scroll t]
10780 ["Scroll Table Window down" org-table-fedit-scroll-down t]
10781 ["Show Table Grid" org-table-fedit-toggle-coordinates
10782 :style toggle :selected (with-current-buffer (marker-buffer org-pos)
10783 org-table-overlay-coordinates)]
10784 "--"
10785 ["Standard Refs (B3 instead of @3$2)" org-table-fedit-toggle-ref-type
10786 :style toggle :selected org-table-buffer-is-an]))
10788 (defvar org-pos)
10790 (defun org-table-edit-formulas ()
10791 "Edit the formulas of the current table in a separate buffer."
10792 (interactive)
10793 (when (save-excursion (beginning-of-line 1) (looking-at "#\\+TBLFM"))
10794 (beginning-of-line 0))
10795 (unless (org-at-table-p) (error "Not at a table"))
10796 (org-table-get-specials)
10797 (let ((key (org-table-current-field-formula 'key 'noerror))
10798 (eql (sort (org-table-get-stored-formulas 'noerror)
10799 'org-table-formula-less-p))
10800 (pos (move-marker (make-marker) (point)))
10801 (startline 1)
10802 (wc (current-window-configuration))
10803 (titles '((column . "# Column Formulas\n")
10804 (field . "# Field Formulas\n")
10805 (named . "# Named Field Formulas\n")))
10806 entry s type title)
10807 (org-switch-to-buffer-other-window "*Edit Formulas*")
10808 (erase-buffer)
10809 ;; Keep global-font-lock-mode from turning on font-lock-mode
10810 (let ((font-lock-global-modes '(not fundamental-mode)))
10811 (fundamental-mode))
10812 (org-set-local 'font-lock-global-modes (list 'not major-mode))
10813 (org-set-local 'org-pos pos)
10814 (org-set-local 'org-window-configuration wc)
10815 (use-local-map org-table-fedit-map)
10816 (org-add-hook 'post-command-hook 'org-table-fedit-post-command t t)
10817 (easy-menu-add org-table-fedit-menu)
10818 (setq startline (org-current-line))
10819 (while (setq entry (pop eql))
10820 (setq type (cond
10821 ((equal (string-to-char (car entry)) ?@) 'field)
10822 ((string-match "^[0-9]" (car entry)) 'column)
10823 (t 'named)))
10824 (when (setq title (assq type titles))
10825 (or (bobp) (insert "\n"))
10826 (insert (org-add-props (cdr title) nil 'face font-lock-comment-face))
10827 (setq titles (delq title titles)))
10828 (if (equal key (car entry)) (setq startline (org-current-line)))
10829 (setq s (concat (if (equal (string-to-char (car entry)) ?@) "" "$")
10830 (car entry) " = " (cdr entry) "\n"))
10831 (remove-text-properties 0 (length s) '(face nil) s)
10832 (insert s))
10833 (if (eq org-table-use-standard-references t)
10834 (org-table-fedit-toggle-ref-type))
10835 (goto-line startline)
10836 (message "Edit formulas and finish with `C-c C-c'. See menu for more commands.")))
10838 (defun org-table-fedit-post-command ()
10839 (when (not (memq this-command '(lisp-complete-symbol)))
10840 (let ((win (selected-window)))
10841 (save-excursion
10842 (condition-case nil
10843 (org-table-show-reference)
10844 (error nil))
10845 (select-window win)))))
10847 (defun org-table-formula-to-user (s)
10848 "Convert a formula from internal to user representation."
10849 (if (eq org-table-use-standard-references t)
10850 (org-table-convert-refs-to-an s)
10853 (defun org-table-formula-from-user (s)
10854 "Convert a formula from user to internal representation."
10855 (if org-table-use-standard-references
10856 (org-table-convert-refs-to-rc s)
10859 (defun org-table-convert-refs-to-rc (s)
10860 "Convert spreadsheet references from AB7 to @7$28.
10861 Works for single references, but also for entire formulas and even the
10862 full TBLFM line."
10863 (let ((start 0))
10864 (while (string-match "\\<\\([a-zA-Z]+\\)\\([0-9]+\\>\\|&\\)\\|\\(;[^\r\n:]+\\)" s start)
10865 (cond
10866 ((match-end 3)
10867 ;; format match, just advance
10868 (setq start (match-end 0)))
10869 ((and (> (match-beginning 0) 0)
10870 (equal ?. (aref s (max (1- (match-beginning 0)) 0)))
10871 (not (equal ?. (aref s (max (- (match-beginning 0) 2) 0)))))
10872 ;; 3.e5 or something like this.
10873 (setq start (match-end 0)))
10875 (setq start (match-beginning 0)
10876 s (replace-match
10877 (if (equal (match-string 2 s) "&")
10878 (format "$%d" (org-letters-to-number (match-string 1 s)))
10879 (format "@%d$%d"
10880 (string-to-number (match-string 2 s))
10881 (org-letters-to-number (match-string 1 s))))
10882 t t s)))))
10885 (defun org-table-convert-refs-to-an (s)
10886 "Convert spreadsheet references from to @7$28 to AB7.
10887 Works for single references, but also for entire formulas and even the
10888 full TBLFM line."
10889 (while (string-match "@\\([0-9]+\\)\\$\\([0-9]+\\)" s)
10890 (setq s (replace-match
10891 (format "%s%d"
10892 (org-number-to-letters
10893 (string-to-number (match-string 2 s)))
10894 (string-to-number (match-string 1 s)))
10895 t t s)))
10896 (while (string-match "\\(^\\|[^0-9a-zA-Z]\\)\\$\\([0-9]+\\)" s)
10897 (setq s (replace-match (concat "\\1"
10898 (org-number-to-letters
10899 (string-to-number (match-string 2 s))) "&")
10900 t nil s)))
10903 (defun org-letters-to-number (s)
10904 "Convert a base 26 number represented by letters into an integer.
10905 For example: AB -> 28."
10906 (let ((n 0))
10907 (setq s (upcase s))
10908 (while (> (length s) 0)
10909 (setq n (+ (* n 26) (string-to-char s) (- ?A) 1)
10910 s (substring s 1)))
10913 (defun org-number-to-letters (n)
10914 "Convert an integer into a base 26 number represented by letters.
10915 For example: 28 -> AB."
10916 (let ((s ""))
10917 (while (> n 0)
10918 (setq s (concat (char-to-string (+ (mod (1- n) 26) ?A)) s)
10919 n (/ (1- n) 26)))
10922 (defun org-table-fedit-convert-buffer (function)
10923 "Convert all references in this buffer, using FUNTION."
10924 (let ((line (org-current-line)))
10925 (goto-char (point-min))
10926 (while (not (eobp))
10927 (insert (funcall function (buffer-substring (point) (point-at-eol))))
10928 (delete-region (point) (point-at-eol))
10929 (or (eobp) (forward-char 1)))
10930 (goto-line line)))
10932 (defun org-table-fedit-toggle-ref-type ()
10933 "Convert all references in the buffer from B3 to @3$2 and back."
10934 (interactive)
10935 (org-set-local 'org-table-buffer-is-an (not org-table-buffer-is-an))
10936 (org-table-fedit-convert-buffer
10937 (if org-table-buffer-is-an
10938 'org-table-convert-refs-to-an 'org-table-convert-refs-to-rc))
10939 (message "Reference type switched to %s"
10940 (if org-table-buffer-is-an "A1 etc" "@row$column")))
10942 (defun org-table-fedit-ref-up ()
10943 "Shift the reference at point one row/hline up."
10944 (interactive)
10945 (org-table-fedit-shift-reference 'up))
10946 (defun org-table-fedit-ref-down ()
10947 "Shift the reference at point one row/hline down."
10948 (interactive)
10949 (org-table-fedit-shift-reference 'down))
10950 (defun org-table-fedit-ref-left ()
10951 "Shift the reference at point one field to the left."
10952 (interactive)
10953 (org-table-fedit-shift-reference 'left))
10954 (defun org-table-fedit-ref-right ()
10955 "Shift the reference at point one field to the right."
10956 (interactive)
10957 (org-table-fedit-shift-reference 'right))
10959 (defun org-table-fedit-shift-reference (dir)
10960 (cond
10961 ((org-at-regexp-p "\\(\\<[a-zA-Z]\\)&")
10962 (if (memq dir '(left right))
10963 (org-rematch-and-replace 1 (eq dir 'left))
10964 (error "Cannot shift reference in this direction")))
10965 ((org-at-regexp-p "\\(\\<[a-zA-Z]\\{1,2\\}\\)\\([0-9]+\\)")
10966 ;; A B3-like reference
10967 (if (memq dir '(up down))
10968 (org-rematch-and-replace 2 (eq dir 'up))
10969 (org-rematch-and-replace 1 (eq dir 'left))))
10970 ((org-at-regexp-p
10971 "\\(@\\|\\.\\.\\)\\([-+]?\\(I+\\>\\|[0-9]+\\)\\)\\(\\$\\([-+]?[0-9]+\\)\\)?")
10972 ;; An internal reference
10973 (if (memq dir '(up down))
10974 (org-rematch-and-replace 2 (eq dir 'up) (match-end 3))
10975 (org-rematch-and-replace 5 (eq dir 'left))))))
10977 (defun org-rematch-and-replace (n &optional decr hline)
10978 "Re-match the group N, and replace it with the shifted refrence."
10979 (or (match-end n) (error "Cannot shift reference in this direction"))
10980 (goto-char (match-beginning n))
10981 (and (looking-at (regexp-quote (match-string n)))
10982 (replace-match (org-shift-refpart (match-string 0) decr hline)
10983 t t)))
10985 (defun org-shift-refpart (ref &optional decr hline)
10986 "Shift a refrence part REF.
10987 If DECR is set, decrease the references row/column, else increase.
10988 If HLINE is set, this may be a hline reference, it certainly is not
10989 a translation reference."
10990 (save-match-data
10991 (let* ((sign (string-match "^[-+]" ref)) n)
10993 (if sign (setq sign (substring ref 0 1) ref (substring ref 1)))
10994 (cond
10995 ((and hline (string-match "^I+" ref))
10996 (setq n (string-to-number (concat sign (number-to-string (length ref)))))
10997 (setq n (+ n (if decr -1 1)))
10998 (if (= n 0) (setq n (+ n (if decr -1 1))))
10999 (if sign
11000 (setq sign (if (< n 0) "-" "+") n (abs n))
11001 (setq n (max 1 n)))
11002 (concat sign (make-string n ?I)))
11004 ((string-match "^[0-9]+" ref)
11005 (setq n (string-to-number (concat sign ref)))
11006 (setq n (+ n (if decr -1 1)))
11007 (if sign
11008 (concat (if (< n 0) "-" "+") (number-to-string (abs n)))
11009 (number-to-string (max 1 n))))
11011 ((string-match "^[a-zA-Z]+" ref)
11012 (org-number-to-letters
11013 (max 1 (+ (org-letters-to-number ref) (if decr -1 1)))))
11015 (t (error "Cannot shift reference"))))))
11017 (defun org-table-fedit-toggle-coordinates ()
11018 "Toggle the display of coordinates in the refrenced table."
11019 (interactive)
11020 (let ((pos (marker-position org-pos)))
11021 (with-current-buffer (marker-buffer org-pos)
11022 (save-excursion
11023 (goto-char pos)
11024 (org-table-toggle-coordinate-overlays)))))
11026 (defun org-table-fedit-finish (&optional arg)
11027 "Parse the buffer for formula definitions and install them.
11028 With prefix ARG, apply the new formulas to the table."
11029 (interactive "P")
11030 (org-table-remove-rectangle-highlight)
11031 (if org-table-use-standard-references
11032 (progn
11033 (org-table-fedit-convert-buffer 'org-table-convert-refs-to-rc)
11034 (setq org-table-buffer-is-an nil)))
11035 (let ((pos org-pos) eql var form)
11036 (goto-char (point-min))
11037 (while (re-search-forward
11038 "^\\(@[0-9]+\\$[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*\\(\n[ \t]+.*$\\)*\\)"
11039 nil t)
11040 (setq var (if (match-end 2) (match-string 2) (match-string 1))
11041 form (match-string 3))
11042 (setq form (org-trim form))
11043 (when (not (equal form ""))
11044 (while (string-match "[ \t]*\n[ \t]*" form)
11045 (setq form (replace-match " " t t form)))
11046 (when (assoc var eql)
11047 (error "Double formulas for %s" var))
11048 (push (cons var form) eql)))
11049 (setq org-pos nil)
11050 (set-window-configuration org-window-configuration)
11051 (select-window (get-buffer-window (marker-buffer pos)))
11052 (goto-char pos)
11053 (unless (org-at-table-p)
11054 (error "Lost table position - cannot install formulae"))
11055 (org-table-store-formulas eql)
11056 (move-marker pos nil)
11057 (kill-buffer "*Edit Formulas*")
11058 (if arg
11059 (org-table-recalculate 'all)
11060 (message "New formulas installed - press C-u C-c C-c to apply."))))
11062 (defun org-table-fedit-abort ()
11063 "Abort editing formulas, without installing the changes."
11064 (interactive)
11065 (org-table-remove-rectangle-highlight)
11066 (let ((pos org-pos))
11067 (set-window-configuration org-window-configuration)
11068 (select-window (get-buffer-window (marker-buffer pos)))
11069 (goto-char pos)
11070 (move-marker pos nil)
11071 (message "Formula editing aborted without installing changes")))
11073 (defun org-table-fedit-lisp-indent ()
11074 "Pretty-print and re-indent Lisp expressions in the Formula Editor."
11075 (interactive)
11076 (let ((pos (point)) beg end ind)
11077 (beginning-of-line 1)
11078 (cond
11079 ((looking-at "[ \t]")
11080 (goto-char pos)
11081 (call-interactively 'lisp-indent-line))
11082 ((looking-at "[$&@0-9a-zA-Z]+ *= *[^ \t\n']") (goto-char pos))
11083 ((not (fboundp 'pp-buffer))
11084 (error "Cannot pretty-print. Command `pp-buffer' is not available."))
11085 ((looking-at "[$&@0-9a-zA-Z]+ *= *'(")
11086 (goto-char (- (match-end 0) 2))
11087 (setq beg (point))
11088 (setq ind (make-string (current-column) ?\ ))
11089 (condition-case nil (forward-sexp 1)
11090 (error
11091 (error "Cannot pretty-print Lisp expression: Unbalanced parenthesis")))
11092 (setq end (point))
11093 (save-restriction
11094 (narrow-to-region beg end)
11095 (if (eq last-command this-command)
11096 (progn
11097 (goto-char (point-min))
11098 (setq this-command nil)
11099 (while (re-search-forward "[ \t]*\n[ \t]*" nil t)
11100 (replace-match " ")))
11101 (pp-buffer)
11102 (untabify (point-min) (point-max))
11103 (goto-char (1+ (point-min)))
11104 (while (re-search-forward "^." nil t)
11105 (beginning-of-line 1)
11106 (insert ind))
11107 (goto-char (point-max))
11108 (backward-delete-char 1)))
11109 (goto-char beg))
11110 (t nil))))
11112 (defvar org-show-positions nil)
11114 (defun org-table-show-reference (&optional local)
11115 "Show the location/value of the $ expression at point."
11116 (interactive)
11117 (org-table-remove-rectangle-highlight)
11118 (catch 'exit
11119 (let ((pos (if local (point) org-pos))
11120 (face2 'highlight)
11121 (org-inhibit-highlight-removal t)
11122 (win (selected-window))
11123 (org-show-positions nil)
11124 var name e what match dest)
11125 (if local (org-table-get-specials))
11126 (setq what (cond
11127 ((or (org-at-regexp-p org-table-range-regexp2)
11128 (org-at-regexp-p org-table-translate-regexp)
11129 (org-at-regexp-p org-table-range-regexp))
11130 (setq match
11131 (save-match-data
11132 (org-table-convert-refs-to-rc (match-string 0))))
11133 'range)
11134 ((org-at-regexp-p "\\$[a-zA-Z][a-zA-Z0-9]*") 'name)
11135 ((org-at-regexp-p "\\$[0-9]+") 'column)
11136 ((not local) nil)
11137 (t (error "No reference at point")))
11138 match (and what (or match (match-string 0))))
11139 (when (and match (not (equal (match-beginning 0) (point-at-bol))))
11140 (org-table-add-rectangle-overlay (match-beginning 0) (match-end 0)
11141 'secondary-selection))
11142 (org-add-hook 'before-change-functions
11143 'org-table-remove-rectangle-highlight)
11144 (if (eq what 'name) (setq var (substring match 1)))
11145 (when (eq what 'range)
11146 (or (equal (string-to-char match) ?@) (setq match (concat "@" match)))
11147 (setq match (org-table-formula-substitute-names match)))
11148 (unless local
11149 (save-excursion
11150 (end-of-line 1)
11151 (re-search-backward "^\\S-" nil t)
11152 (beginning-of-line 1)
11153 (when (looking-at "\\(\\$[0-9a-zA-Z]+\\|@[0-9]+\\$[0-9]+\\|[a-zA-Z]+\\([0-9]+\\|&\\)\\) *=")
11154 (setq dest
11155 (save-match-data
11156 (org-table-convert-refs-to-rc (match-string 1))))
11157 (org-table-add-rectangle-overlay
11158 (match-beginning 1) (match-end 1) face2))))
11159 (if (and (markerp pos) (marker-buffer pos))
11160 (if (get-buffer-window (marker-buffer pos))
11161 (select-window (get-buffer-window (marker-buffer pos)))
11162 (org-switch-to-buffer-other-window (get-buffer-window
11163 (marker-buffer pos)))))
11164 (goto-char pos)
11165 (org-table-force-dataline)
11166 (when dest
11167 (setq name (substring dest 1))
11168 (cond
11169 ((string-match "^\\$[a-zA-Z][a-zA-Z0-9]*" dest)
11170 (setq e (assoc name org-table-named-field-locations))
11171 (goto-line (nth 1 e))
11172 (org-table-goto-column (nth 2 e)))
11173 ((string-match "^@\\([0-9]+\\)\\$\\([0-9]+\\)" dest)
11174 (let ((l (string-to-number (match-string 1 dest)))
11175 (c (string-to-number (match-string 2 dest))))
11176 (goto-line (aref org-table-dlines l))
11177 (org-table-goto-column c)))
11178 (t (org-table-goto-column (string-to-number name))))
11179 (move-marker pos (point))
11180 (org-table-highlight-rectangle nil nil face2))
11181 (cond
11182 ((equal dest match))
11183 ((not match))
11184 ((eq what 'range)
11185 (condition-case nil
11186 (save-excursion
11187 (org-table-get-range match nil nil 'highlight))
11188 (error nil)))
11189 ((setq e (assoc var org-table-named-field-locations))
11190 (goto-line (nth 1 e))
11191 (org-table-goto-column (nth 2 e))
11192 (org-table-highlight-rectangle (point) (point))
11193 (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e)))
11194 ((setq e (assoc var org-table-column-names))
11195 (org-table-goto-column (string-to-number (cdr e)))
11196 (org-table-highlight-rectangle (point) (point))
11197 (goto-char (org-table-begin))
11198 (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|")
11199 (org-table-end) t)
11200 (progn
11201 (goto-char (match-beginning 1))
11202 (org-table-highlight-rectangle)
11203 (message "Named column (column %s)" (cdr e)))
11204 (error "Column name not found")))
11205 ((eq what 'column)
11206 ;; column number
11207 (org-table-goto-column (string-to-number (substring match 1)))
11208 (org-table-highlight-rectangle (point) (point))
11209 (message "Column %s" (substring match 1)))
11210 ((setq e (assoc var org-table-local-parameters))
11211 (goto-char (org-table-begin))
11212 (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") nil t)
11213 (progn
11214 (goto-char (match-beginning 1))
11215 (org-table-highlight-rectangle)
11216 (message "Local parameter."))
11217 (error "Parameter not found")))
11219 (cond
11220 ((not var) (error "No reference at point"))
11221 ((setq e (assoc var org-table-formula-constants-local))
11222 (message "Local Constant: $%s=%s in #+CONSTANTS line."
11223 var (cdr e)))
11224 ((setq e (assoc var org-table-formula-constants))
11225 (message "Constant: $%s=%s in `org-table-formula-constants'."
11226 var (cdr e)))
11227 ((setq e (and (fboundp 'constants-get) (constants-get var)))
11228 (message "Constant: $%s=%s, from `constants.el'%s."
11229 var e (format " (%s units)" constants-unit-system)))
11230 (t (error "Undefined name $%s" var)))))
11231 (goto-char pos)
11232 (when (and org-show-positions
11233 (not (memq this-command '(org-table-fedit-scroll
11234 org-table-fedit-scroll-down))))
11235 (push pos org-show-positions)
11236 (push org-table-current-begin-pos org-show-positions)
11237 (let ((min (apply 'min org-show-positions))
11238 (max (apply 'max org-show-positions)))
11239 (goto-char min) (recenter 0)
11240 (goto-char max)
11241 (or (pos-visible-in-window-p max) (recenter -1))))
11242 (select-window win))))
11244 (defun org-table-force-dataline ()
11245 "Make sure the cursor is in a dataline in a table."
11246 (unless (save-excursion
11247 (beginning-of-line 1)
11248 (looking-at org-table-dataline-regexp))
11249 (let* ((re org-table-dataline-regexp)
11250 (p1 (save-excursion (re-search-forward re nil 'move)))
11251 (p2 (save-excursion (re-search-backward re nil 'move))))
11252 (cond ((and p1 p2)
11253 (goto-char (if (< (abs (- p1 (point))) (abs (- p2 (point))))
11254 p1 p2)))
11255 ((or p1 p2) (goto-char (or p1 p2)))
11256 (t (error "No table dataline around here"))))))
11258 (defun org-table-fedit-line-up ()
11259 "Move cursor one line up in the window showing the table."
11260 (interactive)
11261 (org-table-fedit-move 'previous-line))
11263 (defun org-table-fedit-line-down ()
11264 "Move cursor one line down in the window showing the table."
11265 (interactive)
11266 (org-table-fedit-move 'next-line))
11268 (defun org-table-fedit-move (command)
11269 "Move the cursor in the window shoinw the table.
11270 Use COMMAND to do the motion, repeat if necessary to end up in a data line."
11271 (let ((org-table-allow-automatic-line-recalculation nil)
11272 (pos org-pos) (win (selected-window)) p)
11273 (select-window (get-buffer-window (marker-buffer org-pos)))
11274 (setq p (point))
11275 (call-interactively command)
11276 (while (and (org-at-table-p)
11277 (org-at-table-hline-p))
11278 (call-interactively command))
11279 (or (org-at-table-p) (goto-char p))
11280 (move-marker pos (point))
11281 (select-window win)))
11283 (defun org-table-fedit-scroll (N)
11284 (interactive "p")
11285 (let ((other-window-scroll-buffer (marker-buffer org-pos)))
11286 (scroll-other-window N)))
11288 (defun org-table-fedit-scroll-down (N)
11289 (interactive "p")
11290 (org-table-fedit-scroll (- N)))
11292 (defvar org-table-rectangle-overlays nil)
11294 (defun org-table-add-rectangle-overlay (beg end &optional face)
11295 "Add a new overlay."
11296 (let ((ov (org-make-overlay beg end)))
11297 (org-overlay-put ov 'face (or face 'secondary-selection))
11298 (push ov org-table-rectangle-overlays)))
11300 (defun org-table-highlight-rectangle (&optional beg end face)
11301 "Highlight rectangular region in a table."
11302 (setq beg (or beg (point)) end (or end (point)))
11303 (let ((b (min beg end))
11304 (e (max beg end))
11305 l1 c1 l2 c2 tmp)
11306 (and (boundp 'org-show-positions)
11307 (setq org-show-positions (cons b (cons e org-show-positions))))
11308 (goto-char (min beg end))
11309 (setq l1 (org-current-line)
11310 c1 (org-table-current-column))
11311 (goto-char (max beg end))
11312 (setq l2 (org-current-line)
11313 c2 (org-table-current-column))
11314 (if (> c1 c2) (setq tmp c1 c1 c2 c2 tmp))
11315 (goto-line l1)
11316 (beginning-of-line 1)
11317 (loop for line from l1 to l2 do
11318 (when (looking-at org-table-dataline-regexp)
11319 (org-table-goto-column c1)
11320 (skip-chars-backward "^|\n") (setq beg (point))
11321 (org-table-goto-column c2)
11322 (skip-chars-forward "^|\n") (setq end (point))
11323 (org-table-add-rectangle-overlay beg end face))
11324 (beginning-of-line 2))
11325 (goto-char b))
11326 (add-hook 'before-change-functions 'org-table-remove-rectangle-highlight))
11328 (defun org-table-remove-rectangle-highlight (&rest ignore)
11329 "Remove the rectangle overlays."
11330 (unless org-inhibit-highlight-removal
11331 (remove-hook 'before-change-functions 'org-table-remove-rectangle-highlight)
11332 (mapc 'org-delete-overlay org-table-rectangle-overlays)
11333 (setq org-table-rectangle-overlays nil)))
11335 (defvar org-table-coordinate-overlays nil
11336 "Collects the cooordinate grid overlays, so that they can be removed.")
11337 (make-variable-buffer-local 'org-table-coordinate-overlays)
11339 (defun org-table-overlay-coordinates ()
11340 "Add overlays to the table at point, to show row/column coordinates."
11341 (interactive)
11342 (mapc 'org-delete-overlay org-table-coordinate-overlays)
11343 (setq org-table-coordinate-overlays nil)
11344 (save-excursion
11345 (let ((id 0) (ih 0) hline eol s1 s2 str ic ov beg)
11346 (goto-char (org-table-begin))
11347 (while (org-at-table-p)
11348 (setq eol (point-at-eol))
11349 (setq ov (org-make-overlay (point-at-bol) (1+ (point-at-bol))))
11350 (push ov org-table-coordinate-overlays)
11351 (setq hline (looking-at org-table-hline-regexp))
11352 (setq str (if hline (format "I*%-2d" (setq ih (1+ ih)))
11353 (format "%4d" (setq id (1+ id)))))
11354 (org-overlay-before-string ov str 'org-special-keyword 'evaporate)
11355 (when hline
11356 (setq ic 0)
11357 (while (re-search-forward "[+|]\\(-+\\)" eol t)
11358 (setq beg (1+ (match-beginning 0))
11359 ic (1+ ic)
11360 s1 (concat "$" (int-to-string ic))
11361 s2 (org-number-to-letters ic)
11362 str (if (eq org-table-use-standard-references t) s2 s1))
11363 (setq ov (org-make-overlay beg (+ beg (length str))))
11364 (push ov org-table-coordinate-overlays)
11365 (org-overlay-display ov str 'org-special-keyword 'evaporate)))
11366 (beginning-of-line 2)))))
11368 (defun org-table-toggle-coordinate-overlays ()
11369 "Toggle the display of Row/Column numbers in tables."
11370 (interactive)
11371 (setq org-table-overlay-coordinates (not org-table-overlay-coordinates))
11372 (message "Row/Column number display turned %s"
11373 (if org-table-overlay-coordinates "on" "off"))
11374 (if (and (org-at-table-p) org-table-overlay-coordinates)
11375 (org-table-align))
11376 (unless org-table-overlay-coordinates
11377 (mapc 'org-delete-overlay org-table-coordinate-overlays)
11378 (setq org-table-coordinate-overlays nil)))
11380 (defun org-table-toggle-formula-debugger ()
11381 "Toggle the formula debugger in tables."
11382 (interactive)
11383 (setq org-table-formula-debug (not org-table-formula-debug))
11384 (message "Formula debugging has been turned %s"
11385 (if org-table-formula-debug "on" "off")))
11387 ;;; The orgtbl minor mode
11389 ;; Define a minor mode which can be used in other modes in order to
11390 ;; integrate the org-mode table editor.
11392 ;; This is really a hack, because the org-mode table editor uses several
11393 ;; keys which normally belong to the major mode, for example the TAB and
11394 ;; RET keys. Here is how it works: The minor mode defines all the keys
11395 ;; necessary to operate the table editor, but wraps the commands into a
11396 ;; function which tests if the cursor is currently inside a table. If that
11397 ;; is the case, the table editor command is executed. However, when any of
11398 ;; those keys is used outside a table, the function uses `key-binding' to
11399 ;; look up if the key has an associated command in another currently active
11400 ;; keymap (minor modes, major mode, global), and executes that command.
11401 ;; There might be problems if any of the keys used by the table editor is
11402 ;; otherwise used as a prefix key.
11404 ;; Another challenge is that the key binding for TAB can be tab or \C-i,
11405 ;; likewise the binding for RET can be return or \C-m. Orgtbl-mode
11406 ;; addresses this by checking explicitly for both bindings.
11408 ;; The optimized version (see variable `orgtbl-optimized') takes over
11409 ;; all keys which are bound to `self-insert-command' in the *global map*.
11410 ;; Some modes bind other commands to simple characters, for example
11411 ;; AUCTeX binds the double quote to `Tex-insert-quote'. With orgtbl-mode
11412 ;; active, this binding is ignored inside tables and replaced with a
11413 ;; modified self-insert.
11415 (defvar orgtbl-mode nil
11416 "Variable controlling `orgtbl-mode', a minor mode enabling the `org-mode'
11417 table editor in arbitrary modes.")
11418 (make-variable-buffer-local 'orgtbl-mode)
11420 (defvar orgtbl-mode-map (make-keymap)
11421 "Keymap for `orgtbl-mode'.")
11423 ;;;###autoload
11424 (defun turn-on-orgtbl ()
11425 "Unconditionally turn on `orgtbl-mode'."
11426 (orgtbl-mode 1))
11428 (defvar org-old-auto-fill-inhibit-regexp nil
11429 "Local variable used by `orgtbl-mode'")
11431 (defconst orgtbl-line-start-regexp "[ \t]*\\(|\\|#\\+\\(TBLFM\\|ORGTBL\\):\\)"
11432 "Matches a line belonging to an orgtbl.")
11434 (defconst orgtbl-extra-font-lock-keywords
11435 (list (list (concat "^" orgtbl-line-start-regexp ".*")
11436 0 (quote 'org-table) 'prepend))
11437 "Extra font-lock-keywords to be added when orgtbl-mode is active.")
11439 ;;;###autoload
11440 (defun orgtbl-mode (&optional arg)
11441 "The `org-mode' table editor as a minor mode for use in other modes."
11442 (interactive)
11443 (org-load-modules-maybe)
11444 (if (org-mode-p)
11445 ;; Exit without error, in case some hook functions calls this
11446 ;; by accident in org-mode.
11447 (message "Orgtbl-mode is not useful in org-mode, command ignored")
11448 (setq orgtbl-mode
11449 (if arg (> (prefix-numeric-value arg) 0) (not orgtbl-mode)))
11450 (if orgtbl-mode
11451 (progn
11452 (and (orgtbl-setup) (defun orgtbl-setup () nil))
11453 ;; Make sure we are first in minor-mode-map-alist
11454 (let ((c (assq 'orgtbl-mode minor-mode-map-alist)))
11455 (and c (setq minor-mode-map-alist
11456 (cons c (delq c minor-mode-map-alist)))))
11457 (org-set-local (quote org-table-may-need-update) t)
11458 (org-add-hook 'before-change-functions 'org-before-change-function
11459 nil 'local)
11460 (org-set-local 'org-old-auto-fill-inhibit-regexp
11461 auto-fill-inhibit-regexp)
11462 (org-set-local 'auto-fill-inhibit-regexp
11463 (if auto-fill-inhibit-regexp
11464 (concat orgtbl-line-start-regexp "\\|"
11465 auto-fill-inhibit-regexp)
11466 orgtbl-line-start-regexp))
11467 (org-add-to-invisibility-spec '(org-cwidth))
11468 (when (fboundp 'font-lock-add-keywords)
11469 (font-lock-add-keywords nil orgtbl-extra-font-lock-keywords)
11470 (org-restart-font-lock))
11471 (easy-menu-add orgtbl-mode-menu)
11472 (run-hooks 'orgtbl-mode-hook))
11473 (setq auto-fill-inhibit-regexp org-old-auto-fill-inhibit-regexp)
11474 (org-cleanup-narrow-column-properties)
11475 (org-remove-from-invisibility-spec '(org-cwidth))
11476 (remove-hook 'before-change-functions 'org-before-change-function t)
11477 (when (fboundp 'font-lock-remove-keywords)
11478 (font-lock-remove-keywords nil orgtbl-extra-font-lock-keywords)
11479 (org-restart-font-lock))
11480 (easy-menu-remove orgtbl-mode-menu)
11481 (force-mode-line-update 'all))))
11483 (defun org-cleanup-narrow-column-properties ()
11484 "Remove all properties related to narrow-column invisibility."
11485 (let ((s 1))
11486 (while (setq s (text-property-any s (point-max)
11487 'display org-narrow-column-arrow))
11488 (remove-text-properties s (1+ s) '(display t)))
11489 (setq s 1)
11490 (while (setq s (text-property-any s (point-max) 'org-cwidth 1))
11491 (remove-text-properties s (1+ s) '(org-cwidth t)))
11492 (setq s 1)
11493 (while (setq s (text-property-any s (point-max) 'invisible 'org-cwidth))
11494 (remove-text-properties s (1+ s) '(invisible t)))))
11496 ;; Install it as a minor mode.
11497 (put 'orgtbl-mode :included t)
11498 (put 'orgtbl-mode :menu-tag "Org Table Mode")
11499 (add-minor-mode 'orgtbl-mode " OrgTbl" orgtbl-mode-map)
11501 (defun orgtbl-make-binding (fun n &rest keys)
11502 "Create a function for binding in the table minor mode.
11503 FUN is the command to call inside a table. N is used to create a unique
11504 command name. KEYS are keys that should be checked in for a command
11505 to execute outside of tables."
11506 (eval
11507 (list 'defun
11508 (intern (concat "orgtbl-hijacker-command-" (int-to-string n)))
11509 '(arg)
11510 (concat "In tables, run `" (symbol-name fun) "'.\n"
11511 "Outside of tables, run the binding of `"
11512 (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
11513 "'.")
11514 '(interactive "p")
11515 (list 'if
11516 '(org-at-table-p)
11517 (list 'call-interactively (list 'quote fun))
11518 (list 'let '(orgtbl-mode)
11519 (list 'call-interactively
11520 (append '(or)
11521 (mapcar (lambda (k)
11522 (list 'key-binding k))
11523 keys)
11524 '('orgtbl-error))))))))
11526 (defun orgtbl-error ()
11527 "Error when there is no default binding for a table key."
11528 (interactive)
11529 (error "This key has no function outside tables"))
11531 (defun orgtbl-setup ()
11532 "Setup orgtbl keymaps."
11533 (let ((nfunc 0)
11534 (bindings
11535 (list
11536 '([(meta shift left)] org-table-delete-column)
11537 '([(meta left)] org-table-move-column-left)
11538 '([(meta right)] org-table-move-column-right)
11539 '([(meta shift right)] org-table-insert-column)
11540 '([(meta shift up)] org-table-kill-row)
11541 '([(meta shift down)] org-table-insert-row)
11542 '([(meta up)] org-table-move-row-up)
11543 '([(meta down)] org-table-move-row-down)
11544 '("\C-c\C-w" org-table-cut-region)
11545 '("\C-c\M-w" org-table-copy-region)
11546 '("\C-c\C-y" org-table-paste-rectangle)
11547 '("\C-c-" org-table-insert-hline)
11548 '("\C-c}" org-table-toggle-coordinate-overlays)
11549 '("\C-c{" org-table-toggle-formula-debugger)
11550 '("\C-m" org-table-next-row)
11551 '([(shift return)] org-table-copy-down)
11552 '("\C-c\C-q" org-table-wrap-region)
11553 '("\C-c?" org-table-field-info)
11554 '("\C-c " org-table-blank-field)
11555 '("\C-c+" org-table-sum)
11556 '("\C-c=" org-table-eval-formula)
11557 '("\C-c'" org-table-edit-formulas)
11558 '("\C-c`" org-table-edit-field)
11559 '("\C-c*" org-table-recalculate)
11560 '("\C-c|" org-table-create-or-convert-from-region)
11561 '("\C-c^" org-table-sort-lines)
11562 '([(control ?#)] org-table-rotate-recalc-marks)))
11563 elt key fun cmd)
11564 (while (setq elt (pop bindings))
11565 (setq nfunc (1+ nfunc))
11566 (setq key (org-key (car elt))
11567 fun (nth 1 elt)
11568 cmd (orgtbl-make-binding fun nfunc key))
11569 (org-defkey orgtbl-mode-map key cmd))
11571 ;; Special treatment needed for TAB and RET
11572 (org-defkey orgtbl-mode-map [(return)]
11573 (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m"))
11574 (org-defkey orgtbl-mode-map "\C-m"
11575 (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)]))
11577 (org-defkey orgtbl-mode-map [(tab)]
11578 (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i"))
11579 (org-defkey orgtbl-mode-map "\C-i"
11580 (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)]))
11582 (org-defkey orgtbl-mode-map [(shift tab)]
11583 (orgtbl-make-binding 'org-table-previous-field 104
11584 [(shift tab)] [(tab)] "\C-i"))
11586 (org-defkey orgtbl-mode-map "\M-\C-m"
11587 (orgtbl-make-binding 'org-table-wrap-region 105
11588 "\M-\C-m" [(meta return)]))
11589 (org-defkey orgtbl-mode-map [(meta return)]
11590 (orgtbl-make-binding 'org-table-wrap-region 106
11591 [(meta return)] "\M-\C-m"))
11593 (org-defkey orgtbl-mode-map "\C-c\C-c" 'orgtbl-ctrl-c-ctrl-c)
11594 (when orgtbl-optimized
11595 ;; If the user wants maximum table support, we need to hijack
11596 ;; some standard editing functions
11597 (org-remap orgtbl-mode-map
11598 'self-insert-command 'orgtbl-self-insert-command
11599 'delete-char 'org-delete-char
11600 'delete-backward-char 'org-delete-backward-char)
11601 (org-defkey orgtbl-mode-map "|" 'org-force-self-insert))
11602 (easy-menu-define orgtbl-mode-menu orgtbl-mode-map "OrgTbl menu"
11603 '("OrgTbl"
11604 ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p) :keys "C-c C-c"]
11605 ["Next Field" org-cycle :active (org-at-table-p) :keys "TAB"]
11606 ["Previous Field" org-shifttab :active (org-at-table-p) :keys "S-TAB"]
11607 ["Next Row" org-return :active (org-at-table-p) :keys "RET"]
11608 "--"
11609 ["Blank Field" org-table-blank-field :active (org-at-table-p) :keys "C-c SPC"]
11610 ["Edit Field" org-table-edit-field :active (org-at-table-p) :keys "C-c ` "]
11611 ["Copy Field from Above"
11612 org-table-copy-down :active (org-at-table-p) :keys "S-RET"]
11613 "--"
11614 ("Column"
11615 ["Move Column Left" org-metaleft :active (org-at-table-p) :keys "M-<left>"]
11616 ["Move Column Right" org-metaright :active (org-at-table-p) :keys "M-<right>"]
11617 ["Delete Column" org-shiftmetaleft :active (org-at-table-p) :keys "M-S-<left>"]
11618 ["Insert Column" org-shiftmetaright :active (org-at-table-p) :keys "M-S-<right>"])
11619 ("Row"
11620 ["Move Row Up" org-metaup :active (org-at-table-p) :keys "M-<up>"]
11621 ["Move Row Down" org-metadown :active (org-at-table-p) :keys "M-<down>"]
11622 ["Delete Row" org-shiftmetaup :active (org-at-table-p) :keys "M-S-<up>"]
11623 ["Insert Row" org-shiftmetadown :active (org-at-table-p) :keys "M-S-<down>"]
11624 ["Sort lines in region" org-table-sort-lines :active (org-at-table-p) :keys "C-c ^"]
11625 "--"
11626 ["Insert Hline" org-table-insert-hline :active (org-at-table-p) :keys "C-c -"])
11627 ("Rectangle"
11628 ["Copy Rectangle" org-copy-special :active (org-at-table-p)]
11629 ["Cut Rectangle" org-cut-special :active (org-at-table-p)]
11630 ["Paste Rectangle" org-paste-special :active (org-at-table-p)]
11631 ["Fill Rectangle" org-table-wrap-region :active (org-at-table-p)])
11632 "--"
11633 ("Radio tables"
11634 ["Insert table template" orgtbl-insert-radio-table
11635 (assq major-mode orgtbl-radio-table-templates)]
11636 ["Comment/uncomment table" orgtbl-toggle-comment t])
11637 "--"
11638 ["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="]
11639 ["Set Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
11640 ["Edit Formulas" org-table-edit-formulas :active (org-at-table-p) :keys "C-c '"]
11641 ["Recalculate line" org-table-recalculate :active (org-at-table-p) :keys "C-c *"]
11642 ["Recalculate all" (org-table-recalculate '(4)) :active (org-at-table-p) :keys "C-u C-c *"]
11643 ["Iterate all" (org-table-recalculate '(16)) :active (org-at-table-p) :keys "C-u C-u C-c *"]
11644 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks :active (org-at-table-p) :keys "C-c #"]
11645 ["Sum Column/Rectangle" org-table-sum
11646 :active (or (org-at-table-p) (org-region-active-p)) :keys "C-c +"]
11647 ["Which Column?" org-table-current-column :active (org-at-table-p) :keys "C-c ?"]
11648 ["Debug Formulas"
11649 org-table-toggle-formula-debugger :active (org-at-table-p)
11650 :keys "C-c {"
11651 :style toggle :selected org-table-formula-debug]
11652 ["Show Col/Row Numbers"
11653 org-table-toggle-coordinate-overlays :active (org-at-table-p)
11654 :keys "C-c }"
11655 :style toggle :selected org-table-overlay-coordinates]
11659 (defun orgtbl-ctrl-c-ctrl-c (arg)
11660 "If the cursor is inside a table, realign the table.
11661 It it is a table to be sent away to a receiver, do it.
11662 With prefix arg, also recompute table."
11663 (interactive "P")
11664 (let ((pos (point)) action)
11665 (save-excursion
11666 (beginning-of-line 1)
11667 (setq action (cond ((looking-at "#\\+ORGTBL:.*\n[ \t]*|") (match-end 0))
11668 ((looking-at "[ \t]*|") pos)
11669 ((looking-at "#\\+TBLFM:") 'recalc))))
11670 (cond
11671 ((integerp action)
11672 (goto-char action)
11673 (org-table-maybe-eval-formula)
11674 (if arg
11675 (call-interactively 'org-table-recalculate)
11676 (org-table-maybe-recalculate-line))
11677 (call-interactively 'org-table-align)
11678 (orgtbl-send-table 'maybe))
11679 ((eq action 'recalc)
11680 (save-excursion
11681 (beginning-of-line 1)
11682 (skip-chars-backward " \r\n\t")
11683 (if (org-at-table-p)
11684 (org-call-with-arg 'org-table-recalculate t))))
11685 (t (let (orgtbl-mode)
11686 (call-interactively (key-binding "\C-c\C-c")))))))
11688 (defun orgtbl-tab (arg)
11689 "Justification and field motion for `orgtbl-mode'."
11690 (interactive "P")
11691 (if arg (org-table-edit-field t)
11692 (org-table-justify-field-maybe)
11693 (org-table-next-field)))
11695 (defun orgtbl-ret ()
11696 "Justification and field motion for `orgtbl-mode'."
11697 (interactive)
11698 (org-table-justify-field-maybe)
11699 (org-table-next-row))
11701 (defun orgtbl-self-insert-command (N)
11702 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
11703 If the cursor is in a table looking at whitespace, the whitespace is
11704 overwritten, and the table is not marked as requiring realignment."
11705 (interactive "p")
11706 (if (and (org-at-table-p)
11708 (and org-table-auto-blank-field
11709 (member last-command
11710 '(orgtbl-hijacker-command-100
11711 orgtbl-hijacker-command-101
11712 orgtbl-hijacker-command-102
11713 orgtbl-hijacker-command-103
11714 orgtbl-hijacker-command-104
11715 orgtbl-hijacker-command-105))
11716 (org-table-blank-field))
11718 (eq N 1)
11719 (looking-at "[^|\n]* +|"))
11720 (let (org-table-may-need-update)
11721 (goto-char (1- (match-end 0)))
11722 (delete-backward-char 1)
11723 (goto-char (match-beginning 0))
11724 (self-insert-command N))
11725 (setq org-table-may-need-update t)
11726 (let (orgtbl-mode)
11727 (call-interactively (key-binding (vector last-input-event))))))
11729 (defun org-force-self-insert (N)
11730 "Needed to enforce self-insert under remapping."
11731 (interactive "p")
11732 (self-insert-command N))
11734 (defvar orgtbl-exp-regexp "^\\([-+]?[0-9][0-9.]*\\)[eE]\\([-+]?[0-9]+\\)$"
11735 "Regula expression matching exponentials as produced by calc.")
11737 (defvar org-table-clean-did-remove-column nil)
11739 (defun orgtbl-export (table target)
11740 (let ((func (intern (concat "orgtbl-to-" (symbol-name target))))
11741 (lines (org-split-string table "[ \t]*\n[ \t]*"))
11742 org-table-last-alignment org-table-last-column-widths
11743 maxcol column)
11744 (if (not (fboundp func))
11745 (error "Cannot export orgtbl table to %s" target))
11746 (setq lines (org-table-clean-before-export lines))
11747 (setq table
11748 (mapcar
11749 (lambda (x)
11750 (if (string-match org-table-hline-regexp x)
11751 'hline
11752 (org-split-string (org-trim x) "\\s-*|\\s-*")))
11753 lines))
11754 (setq maxcol (apply 'max (mapcar (lambda (x) (if (listp x) (length x) 0))
11755 table)))
11756 (loop for i from (1- maxcol) downto 0 do
11757 (setq column (mapcar (lambda (x) (if (listp x) (nth i x) nil)) table))
11758 (setq column (delq nil column))
11759 (push (apply 'max (mapcar 'string-width column)) org-table-last-column-widths)
11760 (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))
11761 (funcall func table nil)))
11763 (defun orgtbl-send-table (&optional maybe)
11764 "Send a tranformed version of this table to the receiver position.
11765 With argument MAYBE, fail quietly if no transformation is defined for
11766 this table."
11767 (interactive)
11768 (catch 'exit
11769 (unless (org-at-table-p) (error "Not at a table"))
11770 ;; when non-interactive, we assume align has just happened.
11771 (when (interactive-p) (org-table-align))
11772 (save-excursion
11773 (goto-char (org-table-begin))
11774 (beginning-of-line 0)
11775 (unless (looking-at "#\\+ORGTBL: *SEND +\\([a-zA-Z0-9_]+\\) +\\([^ \t\r\n]+\\)\\( +.*\\)?")
11776 (if maybe
11777 (throw 'exit nil)
11778 (error "Don't know how to transform this table."))))
11779 (let* ((name (match-string 1))
11781 (transform (intern (match-string 2)))
11782 (params (if (match-end 3) (read (concat "(" (match-string 3) ")"))))
11783 (skip (plist-get params :skip))
11784 (skipcols (plist-get params :skipcols))
11785 (txt (buffer-substring-no-properties
11786 (org-table-begin) (org-table-end)))
11787 (lines (nthcdr (or skip 0) (org-split-string txt "[ \t]*\n[ \t]*")))
11788 (lines (org-table-clean-before-export lines))
11789 (i0 (if org-table-clean-did-remove-column 2 1))
11790 (table (mapcar
11791 (lambda (x)
11792 (if (string-match org-table-hline-regexp x)
11793 'hline
11794 (org-remove-by-index
11795 (org-split-string (org-trim x) "\\s-*|\\s-*")
11796 skipcols i0)))
11797 lines))
11798 (fun (if (= i0 2) 'cdr 'identity))
11799 (org-table-last-alignment
11800 (org-remove-by-index (funcall fun org-table-last-alignment)
11801 skipcols i0))
11802 (org-table-last-column-widths
11803 (org-remove-by-index (funcall fun org-table-last-column-widths)
11804 skipcols i0)))
11806 (unless (fboundp transform)
11807 (error "No such transformation function %s" transform))
11808 (setq txt (funcall transform table params))
11809 ;; Find the insertion place
11810 (save-excursion
11811 (goto-char (point-min))
11812 (unless (re-search-forward
11813 (concat "BEGIN RECEIVE ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
11814 (error "Don't know where to insert translated table"))
11815 (goto-char (match-beginning 0))
11816 (beginning-of-line 2)
11817 (setq beg (point))
11818 (unless (re-search-forward (concat "END RECEIVE ORGTBL +" name) nil t)
11819 (error "Cannot find end of insertion region"))
11820 (beginning-of-line 1)
11821 (delete-region beg (point))
11822 (goto-char beg)
11823 (insert txt "\n"))
11824 (message "Table converted and installed at receiver location"))))
11826 (defun org-remove-by-index (list indices &optional i0)
11827 "Remove the elements in LIST with indices in INDICES.
11828 First element has index 0, or I0 if given."
11829 (if (not indices)
11830 list
11831 (if (integerp indices) (setq indices (list indices)))
11832 (setq i0 (1- (or i0 0)))
11833 (delq :rm (mapcar (lambda (x)
11834 (setq i0 (1+ i0))
11835 (if (memq i0 indices) :rm x))
11836 list))))
11838 (defun orgtbl-toggle-comment ()
11839 "Comment or uncomment the orgtbl at point."
11840 (interactive)
11841 (let* ((re1 (concat "^" (regexp-quote comment-start) orgtbl-line-start-regexp))
11842 (re2 (concat "^" orgtbl-line-start-regexp))
11843 (commented (save-excursion (beginning-of-line 1)
11844 (cond ((looking-at re1) t)
11845 ((looking-at re2) nil)
11846 (t (error "Not at an org table")))))
11847 (re (if commented re1 re2))
11848 beg end)
11849 (save-excursion
11850 (beginning-of-line 1)
11851 (while (looking-at re) (beginning-of-line 0))
11852 (beginning-of-line 2)
11853 (setq beg (point))
11854 (while (looking-at re) (beginning-of-line 2))
11855 (setq end (point)))
11856 (comment-region beg end (if commented '(4) nil))))
11858 (defun orgtbl-insert-radio-table ()
11859 "Insert a radio table template appropriate for this major mode."
11860 (interactive)
11861 (let* ((e (assq major-mode orgtbl-radio-table-templates))
11862 (txt (nth 1 e))
11863 name pos)
11864 (unless e (error "No radio table setup defined for %s" major-mode))
11865 (setq name (read-string "Table name: "))
11866 (while (string-match "%n" txt)
11867 (setq txt (replace-match name t t txt)))
11868 (or (bolp) (insert "\n"))
11869 (setq pos (point))
11870 (insert txt)
11871 (goto-char pos)))
11873 (defun org-get-param (params header i sym &optional hsym)
11874 "Get parameter value for symbol SYM.
11875 If this is a header line, actually get the value for the symbol with an
11876 additional \"h\" inserted after the colon.
11877 If the value is a protperty list, get the element for the current column.
11878 Assumes variables VAL, PARAMS, HEAD and I to be scoped into the function."
11879 (let ((val (plist-get params sym)))
11880 (and hsym header (setq val (or (plist-get params hsym) val)))
11881 (if (consp val) (plist-get val i) val)))
11883 (defun orgtbl-to-generic (table params)
11884 "Convert the orgtbl-mode TABLE to some other format.
11885 This generic routine can be used for many standard cases.
11886 TABLE is a list, each entry either the symbol `hline' for a horizontal
11887 separator line, or a list of fields for that line.
11888 PARAMS is a property list of parameters that can influence the conversion.
11889 For the generic converter, some parameters are obligatory: You need to
11890 specify either :lfmt, or all of (:lstart :lend :sep). If you do not use
11891 :splice, you must have :tstart and :tend.
11893 Valid parameters are
11895 :tstart String to start the table. Ignored when :splice is t.
11896 :tend String to end the table. Ignored when :splice is t.
11898 :splice When set to t, return only table body lines, don't wrap
11899 them into :tstart and :tend. Default is nil.
11901 :hline String to be inserted on horizontal separation lines.
11902 May be nil to ignore hlines.
11904 :lstart String to start a new table line.
11905 :lend String to end a table line
11906 :sep Separator between two fields
11907 :lfmt Format for entire line, with enough %s to capture all fields.
11908 If this is present, :lstart, :lend, and :sep are ignored.
11909 :fmt A format to be used to wrap the field, should contain
11910 %s for the original field value. For example, to wrap
11911 everything in dollars, you could use :fmt \"$%s$\".
11912 This may also be a property list with column numbers and
11913 formats. For example :fmt (2 \"$%s$\" 4 \"%s%%\")
11915 :hlstart :hlend :hlsep :hlfmt :hfmt
11916 Same as above, specific for the header lines in the table.
11917 All lines before the first hline are treated as header.
11918 If any of these is not present, the data line value is used.
11920 :efmt Use this format to print numbers with exponentials.
11921 The format should have %s twice for inserting mantissa
11922 and exponent, for example \"%s\\\\times10^{%s}\". This
11923 may also be a property list with column numbers and
11924 formats. :fmt will still be applied after :efmt.
11926 In addition to this, the parameters :skip and :skipcols are always handled
11927 directly by `orgtbl-send-table'. See manual."
11928 (interactive)
11929 (let* ((p params)
11930 (splicep (plist-get p :splice))
11931 (hline (plist-get p :hline))
11932 rtn line i fm efm lfmt h)
11934 ;; Do we have a header?
11935 (if (and (not splicep) (listp (car table)) (memq 'hline table))
11936 (setq h t))
11938 ;; Put header
11939 (unless splicep
11940 (push (or (plist-get p :tstart) "ERROR: no :tstart") rtn))
11942 ;; Now loop over all lines
11943 (while (setq line (pop table))
11944 (if (eq line 'hline)
11945 ;; A horizontal separator line
11946 (progn (if hline (push hline rtn))
11947 (setq h nil)) ; no longer in header
11948 ;; A normal line. Convert the fields, push line onto the result list
11949 (setq i 0)
11950 (setq line
11951 (mapcar
11952 (lambda (f)
11953 (setq i (1+ i)
11954 fm (org-get-param p h i :fmt :hfmt)
11955 efm (org-get-param p h i :efmt))
11956 (if (and efm (string-match orgtbl-exp-regexp f))
11957 (setq f (format
11958 efm (match-string 1 f) (match-string 2 f))))
11959 (if fm (setq f (format fm f)))
11961 line))
11962 (if (setq lfmt (org-get-param p h i :lfmt :hlfmt))
11963 (push (apply 'format lfmt line) rtn)
11964 (push (concat
11965 (org-get-param p h i :lstart :hlstart)
11966 (mapconcat 'identity line (org-get-param p h i :sep :hsep))
11967 (org-get-param p h i :lend :hlend))
11968 rtn))))
11970 (unless splicep
11971 (push (or (plist-get p :tend) "ERROR: no :tend") rtn))
11973 (mapconcat 'identity (nreverse rtn) "\n")))
11975 (defun orgtbl-to-latex (table params)
11976 "Convert the orgtbl-mode TABLE to LaTeX.
11977 TABLE is a list, each entry either the symbol `hline' for a horizontal
11978 separator line, or a list of fields for that line.
11979 PARAMS is a property list of parameters that can influence the conversion.
11980 Supports all parameters from `orgtbl-to-generic'. Most important for
11981 LaTeX are:
11983 :splice When set to t, return only table body lines, don't wrap
11984 them into a tabular environment. Default is nil.
11986 :fmt A format to be used to wrap the field, should contain %s for the
11987 original field value. For example, to wrap everything in dollars,
11988 use :fmt \"$%s$\". This may also be a property list with column
11989 numbers and formats. For example :fmt (2 \"$%s$\" 4 \"%s%%\")
11991 :efmt Format for transforming numbers with exponentials. The format
11992 should have %s twice for inserting mantissa and exponent, for
11993 example \"%s\\\\times10^{%s}\". LaTeX default is \"%s\\\\,(%s)\".
11994 This may also be a property list with column numbers and formats.
11996 The general parameters :skip and :skipcols have already been applied when
11997 this function is called."
11998 (let* ((alignment (mapconcat (lambda (x) (if x "r" "l"))
11999 org-table-last-alignment ""))
12000 (params2
12001 (list
12002 :tstart (concat "\\begin{tabular}{" alignment "}")
12003 :tend "\\end{tabular}"
12004 :lstart "" :lend " \\\\" :sep " & "
12005 :efmt "%s\\,(%s)" :hline "\\hline")))
12006 (orgtbl-to-generic table (org-combine-plists params2 params))))
12008 (defun orgtbl-to-html (table params)
12009 "Convert the orgtbl-mode TABLE to LaTeX.
12010 TABLE is a list, each entry either the symbol `hline' for a horizontal
12011 separator line, or a list of fields for that line.
12012 PARAMS is a property list of parameters that can influence the conversion.
12013 Currently this function recognizes the following parameters:
12015 :splice When set to t, return only table body lines, don't wrap
12016 them into a <table> environment. Default is nil.
12018 The general parameters :skip and :skipcols have already been applied when
12019 this function is called. The function does *not* use `orgtbl-to-generic',
12020 so you cannot specify parameters for it."
12021 (let* ((splicep (plist-get params :splice))
12022 html)
12023 ;; Just call the formatter we already have
12024 ;; We need to make text lines for it, so put the fields back together.
12025 (setq html (org-format-org-table-html
12026 (mapcar
12027 (lambda (x)
12028 (if (eq x 'hline)
12029 "|----+----|"
12030 (concat "| " (mapconcat 'identity x " | ") " |")))
12031 table)
12032 splicep))
12033 (if (string-match "\n+\\'" html)
12034 (setq html (replace-match "" t t html)))
12035 html))
12037 (defun orgtbl-to-texinfo (table params)
12038 "Convert the orgtbl-mode TABLE to TeXInfo.
12039 TABLE is a list, each entry either the symbol `hline' for a horizontal
12040 separator line, or a list of fields for that line.
12041 PARAMS is a property list of parameters that can influence the conversion.
12042 Supports all parameters from `orgtbl-to-generic'. Most important for
12043 TeXInfo are:
12045 :splice nil/t When set to t, return only table body lines, don't wrap
12046 them into a multitable environment. Default is nil.
12048 :fmt fmt A format to be used to wrap the field, should contain
12049 %s for the original field value. For example, to wrap
12050 everything in @kbd{}, you could use :fmt \"@kbd{%s}\".
12051 This may also be a property list with column numbers and
12052 formats. For example :fmt (2 \"@kbd{%s}\" 4 \"@code{%s}\").
12054 :cf \"f1 f2..\" The column fractions for the table. By default these
12055 are computed automatically from the width of the columns
12056 under org-mode.
12058 The general parameters :skip and :skipcols have already been applied when
12059 this function is called."
12060 (let* ((total (float (apply '+ org-table-last-column-widths)))
12061 (colfrac (or (plist-get params :cf)
12062 (mapconcat
12063 (lambda (x) (format "%.3f" (/ (float x) total)))
12064 org-table-last-column-widths " ")))
12065 (params2
12066 (list
12067 :tstart (concat "@multitable @columnfractions " colfrac)
12068 :tend "@end multitable"
12069 :lstart "@item " :lend "" :sep " @tab "
12070 :hlstart "@headitem ")))
12071 (orgtbl-to-generic table (org-combine-plists params2 params))))
12073 ;;;; Link Stuff
12075 ;;; Link abbreviations
12077 (defun org-link-expand-abbrev (link)
12078 "Apply replacements as defined in `org-link-abbrev-alist."
12079 (if (string-match "^\\([a-zA-Z][-_a-zA-Z0-9]*\\)\\(::?\\(.*\\)\\)?$" link)
12080 (let* ((key (match-string 1 link))
12081 (as (or (assoc key org-link-abbrev-alist-local)
12082 (assoc key org-link-abbrev-alist)))
12083 (tag (and (match-end 2) (match-string 3 link)))
12084 rpl)
12085 (if (not as)
12086 link
12087 (setq rpl (cdr as))
12088 (cond
12089 ((symbolp rpl) (funcall rpl tag))
12090 ((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
12091 (t (concat rpl tag)))))
12092 link))
12094 ;;; Storing and inserting links
12096 (defvar org-insert-link-history nil
12097 "Minibuffer history for links inserted with `org-insert-link'.")
12099 (defvar org-stored-links nil
12100 "Contains the links stored with `org-store-link'.")
12102 (defvar org-store-link-plist nil
12103 "Plist with info about the most recently link created with `org-store-link'.")
12105 (defvar org-link-protocols nil
12106 "Link protocols added to Org-mode using `org-add-link-type'.")
12108 (defvar org-store-link-functions nil
12109 "List of functions that are called to create and store a link.
12110 Each function will be called in turn until one returns a non-nil
12111 value. Each function should check if it is responsible for creating
12112 this link (for example by looking at the major mode).
12113 If not, it must exit and return nil.
12114 If yes, it should return a non-nil value after a calling
12115 `org-store-link-props' with a list of properties and values.
12116 Special properties are:
12118 :type The link prefix. like \"http\". This must be given.
12119 :link The link, like \"http://www.astro.uva.nl/~dominik\".
12120 This is obligatory as well.
12121 :description Optional default description for the second pair
12122 of brackets in an Org-mode link. The user can still change
12123 this when inserting this link into an Org-mode buffer.
12125 In addition to these, any additional properties can be specified
12126 and then used in remember templates.")
12128 (defun org-add-link-type (type &optional follow export)
12129 "Add TYPE to the list of `org-link-types'.
12130 Re-compute all regular expressions depending on `org-link-types'
12132 FOLLOW and EXPORT are two functions.
12134 FOLLOW should take the link path as the single argument and do whatever
12135 is necessary to follow the link, for example find a file or display
12136 a mail message.
12138 EXPORT should format the link path for export to one of the export formats.
12139 It should be a function accepting three arguments:
12141 path the path of the link, the text after the prefix (like \"http:\")
12142 desc the description of the link, if any, nil if there was no descripton
12143 format the export format, a symbol like `html' or `latex'.
12145 The function may use the FORMAT information to return different values
12146 depending on the format. The return value will be put literally into
12147 the exported file.
12148 Org-mode has a built-in default for exporting links. If you are happy with
12149 this default, there is no need to define an export function for the link
12150 type. For a simple example of an export function, see `org-bbdb.el'."
12151 (add-to-list 'org-link-types type t)
12152 (org-make-link-regexps)
12153 (if (assoc type org-link-protocols)
12154 (setcdr (assoc type org-link-protocols) (list follow export))
12155 (push (list type follow export) org-link-protocols)))
12158 (defun org-add-agenda-custom-command (entry)
12159 "Replace or add a command in `org-agenda-custom-commands'.
12160 This is mostly for hacking and trying a new command - once the command
12161 works you probably want to add it to `org-agenda-custom-commands' for good."
12162 (let ((ass (assoc (car entry) org-agenda-custom-commands)))
12163 (if ass
12164 (setcdr ass (cdr entry))
12165 (push entry org-agenda-custom-commands))))
12167 ;;;###autoload
12168 (defun org-store-link (arg)
12169 "\\<org-mode-map>Store an org-link to the current location.
12170 This link is added to `org-stored-links' and can later be inserted
12171 into an org-buffer with \\[org-insert-link].
12173 For some link types, a prefix arg is interpreted:
12174 For links to usenet articles, arg negates `org-usenet-links-prefer-google'.
12175 For file links, arg negates `org-context-in-file-links'."
12176 (interactive "P")
12177 (org-load-modules-maybe)
12178 (setq org-store-link-plist nil) ; reset
12179 (let (link cpltxt desc description search txt)
12180 (cond
12182 ((run-hook-with-args-until-success 'org-store-link-functions)
12183 (setq link (plist-get org-store-link-plist :link)
12184 desc (or (plist-get org-store-link-plist :description) link)))
12186 ((eq major-mode 'calendar-mode)
12187 (let ((cd (calendar-cursor-to-date)))
12188 (setq link
12189 (format-time-string
12190 (car org-time-stamp-formats)
12191 (apply 'encode-time
12192 (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
12193 nil nil nil))))
12194 (org-store-link-props :type "calendar" :date cd)))
12196 ((eq major-mode 'w3-mode)
12197 (setq cpltxt (url-view-url t)
12198 link (org-make-link cpltxt))
12199 (org-store-link-props :type "w3" :url (url-view-url t)))
12201 ((eq major-mode 'w3m-mode)
12202 (setq cpltxt (or w3m-current-title w3m-current-url)
12203 link (org-make-link w3m-current-url))
12204 (org-store-link-props :type "w3m" :url (url-view-url t)))
12206 ((setq search (run-hook-with-args-until-success
12207 'org-create-file-search-functions))
12208 (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
12209 "::" search))
12210 (setq cpltxt (or description link)))
12212 ((eq major-mode 'image-mode)
12213 (setq cpltxt (concat "file:"
12214 (abbreviate-file-name buffer-file-name))
12215 link (org-make-link cpltxt))
12216 (org-store-link-props :type "image" :file buffer-file-name))
12218 ((eq major-mode 'dired-mode)
12219 ;; link to the file in the current line
12220 (setq cpltxt (concat "file:"
12221 (abbreviate-file-name
12222 (expand-file-name
12223 (dired-get-filename nil t))))
12224 link (org-make-link cpltxt)))
12226 ((and buffer-file-name (org-mode-p))
12227 ;; Just link to current headline
12228 (setq cpltxt (concat "file:"
12229 (abbreviate-file-name buffer-file-name)))
12230 ;; Add a context search string
12231 (when (org-xor org-context-in-file-links arg)
12232 ;; Check if we are on a target
12233 (if (org-in-regexp "<<\\(.*?\\)>>")
12234 (setq cpltxt (concat cpltxt "::" (match-string 1)))
12235 (setq txt (cond
12236 ((org-on-heading-p) nil)
12237 ((org-region-active-p)
12238 (buffer-substring (region-beginning) (region-end)))
12239 (t (buffer-substring (point-at-bol) (point-at-eol)))))
12240 (when (or (null txt) (string-match "\\S-" txt))
12241 (setq cpltxt
12242 (concat cpltxt "::" (org-make-org-heading-search-string txt))
12243 desc "NONE"))))
12244 (if (string-match "::\\'" cpltxt)
12245 (setq cpltxt (substring cpltxt 0 -2)))
12246 (setq link (org-make-link cpltxt)))
12248 ((buffer-file-name (buffer-base-buffer))
12249 ;; Just link to this file here.
12250 (setq cpltxt (concat "file:"
12251 (abbreviate-file-name
12252 (buffer-file-name (buffer-base-buffer)))))
12253 ;; Add a context string
12254 (when (org-xor org-context-in-file-links arg)
12255 (setq txt (if (org-region-active-p)
12256 (buffer-substring (region-beginning) (region-end))
12257 (buffer-substring (point-at-bol) (point-at-eol))))
12258 ;; Only use search option if there is some text.
12259 (when (string-match "\\S-" txt)
12260 (setq cpltxt
12261 (concat cpltxt "::" (org-make-org-heading-search-string txt))
12262 desc "NONE")))
12263 (setq link (org-make-link cpltxt)))
12265 ((interactive-p)
12266 (error "Cannot link to a buffer which is not visiting a file"))
12268 (t (setq link nil)))
12270 (if (consp link) (setq cpltxt (car link) link (cdr link)))
12271 (setq link (or link cpltxt)
12272 desc (or desc cpltxt))
12273 (if (equal desc "NONE") (setq desc nil))
12275 (if (and (interactive-p) link)
12276 (progn
12277 (setq org-stored-links
12278 (cons (list link desc) org-stored-links))
12279 (message "Stored: %s" (or desc link)))
12280 (and link (org-make-link-string link desc)))))
12282 (defun org-store-link-props (&rest plist)
12283 "Store link properties, extract names and addresses."
12284 (let (x adr)
12285 (when (setq x (plist-get plist :from))
12286 (setq adr (mail-extract-address-components x))
12287 (plist-put plist :fromname (car adr))
12288 (plist-put plist :fromaddress (nth 1 adr)))
12289 (when (setq x (plist-get plist :to))
12290 (setq adr (mail-extract-address-components x))
12291 (plist-put plist :toname (car adr))
12292 (plist-put plist :toaddress (nth 1 adr))))
12293 (let ((from (plist-get plist :from))
12294 (to (plist-get plist :to)))
12295 (when (and from to org-from-is-user-regexp)
12296 (plist-put plist :fromto
12297 (if (string-match org-from-is-user-regexp from)
12298 (concat "to %t")
12299 (concat "from %f")))))
12300 (setq org-store-link-plist plist))
12302 (defun org-add-link-props (&rest plist)
12303 "Add these properties to the link property list."
12304 (let (key value)
12305 (while plist
12306 (setq key (pop plist) value (pop plist))
12307 (setq org-store-link-plist
12308 (plist-put org-store-link-plist key value)))))
12310 (defun org-email-link-description (&optional fmt)
12311 "Return the description part of an email link.
12312 This takes information from `org-store-link-plist' and formats it
12313 according to FMT (default from `org-email-link-description-format')."
12314 (setq fmt (or fmt org-email-link-description-format))
12315 (let* ((p org-store-link-plist)
12316 (to (plist-get p :toaddress))
12317 (from (plist-get p :fromaddress))
12318 (table
12319 (list
12320 (cons "%c" (plist-get p :fromto))
12321 (cons "%F" (plist-get p :from))
12322 (cons "%f" (or (plist-get p :fromname) (plist-get p :fromaddress) "?"))
12323 (cons "%T" (plist-get p :to))
12324 (cons "%t" (or (plist-get p :toname) (plist-get p :toaddress) "?"))
12325 (cons "%s" (plist-get p :subject))
12326 (cons "%m" (plist-get p :message-id)))))
12327 (when (string-match "%c" fmt)
12328 ;; Check if the user wrote this message
12329 (if (and org-from-is-user-regexp from to
12330 (save-match-data (string-match org-from-is-user-regexp from)))
12331 (setq fmt (replace-match "to %t" t t fmt))
12332 (setq fmt (replace-match "from %f" t t fmt))))
12333 (org-replace-escapes fmt table)))
12335 (defun org-make-org-heading-search-string (&optional string heading)
12336 "Make search string for STRING or current headline."
12337 (interactive)
12338 (let ((s (or string (org-get-heading))))
12339 (unless (and string (not heading))
12340 ;; We are using a headline, clean up garbage in there.
12341 (if (string-match org-todo-regexp s)
12342 (setq s (replace-match "" t t s)))
12343 (if (string-match (org-re ":[[:alnum:]_@:]+:[ \t]*$") s)
12344 (setq s (replace-match "" t t s)))
12345 (setq s (org-trim s))
12346 (if (string-match (concat "^\\(" org-quote-string "\\|"
12347 org-comment-string "\\)") s)
12348 (setq s (replace-match "" t t s)))
12349 (while (string-match org-ts-regexp s)
12350 (setq s (replace-match "" t t s))))
12351 (while (string-match "[^a-zA-Z_0-9 \t]+" s)
12352 (setq s (replace-match " " t t s)))
12353 (or string (setq s (concat "*" s))) ; Add * for headlines
12354 (mapconcat 'identity (org-split-string s "[ \t]+") " ")))
12356 (defun org-make-link (&rest strings)
12357 "Concatenate STRINGS."
12358 (apply 'concat strings))
12360 (defun org-make-link-string (link &optional description)
12361 "Make a link with brackets, consisting of LINK and DESCRIPTION."
12362 (unless (string-match "\\S-" link)
12363 (error "Empty link"))
12364 (when (stringp description)
12365 ;; Remove brackets from the description, they are fatal.
12366 (while (string-match "\\[" description)
12367 (setq description (replace-match "{" t t description)))
12368 (while (string-match "\\]" description)
12369 (setq description (replace-match "}" t t description))))
12370 (when (equal (org-link-escape link) description)
12371 ;; No description needed, it is identical
12372 (setq description nil))
12373 (when (and (not description)
12374 (not (equal link (org-link-escape link))))
12375 (setq description link))
12376 (concat "[[" (org-link-escape link) "]"
12377 (if description (concat "[" description "]") "")
12378 "]"))
12380 (defconst org-link-escape-chars
12381 '((?\ . "%20")
12382 (?\[ . "%5B")
12383 (?\] . "%5D")
12384 (?\340 . "%E0") ; `a
12385 (?\342 . "%E2") ; ^a
12386 (?\347 . "%E7") ; ,c
12387 (?\350 . "%E8") ; `e
12388 (?\351 . "%E9") ; 'e
12389 (?\352 . "%EA") ; ^e
12390 (?\356 . "%EE") ; ^i
12391 (?\364 . "%F4") ; ^o
12392 (?\371 . "%F9") ; `u
12393 (?\373 . "%FB") ; ^u
12394 (?\; . "%3B")
12395 (?? . "%3F")
12396 (?= . "%3D")
12397 (?+ . "%2B")
12399 "Association list of escapes for some characters problematic in links.
12400 This is the list that is used for internal purposes.")
12402 (defconst org-link-escape-chars-browser
12403 '((?\ . "%20")) ; 32 for the SPC char
12404 "Association list of escapes for some characters problematic in links.
12405 This is the list that is used before handing over to the browser.")
12407 (defun org-link-escape (text &optional table)
12408 "Escape charaters in TEXT that are problematic for links."
12409 (setq table (or table org-link-escape-chars))
12410 (when text
12411 (let ((re (mapconcat (lambda (x) (regexp-quote
12412 (char-to-string (car x))))
12413 table "\\|")))
12414 (while (string-match re text)
12415 (setq text
12416 (replace-match
12417 (cdr (assoc (string-to-char (match-string 0 text))
12418 table))
12419 t t text)))
12420 text)))
12422 (defun org-link-unescape (text &optional table)
12423 "Reverse the action of `org-link-escape'."
12424 (setq table (or table org-link-escape-chars))
12425 (when text
12426 (let ((re (mapconcat (lambda (x) (regexp-quote (cdr x)))
12427 table "\\|")))
12428 (while (string-match re text)
12429 (setq text
12430 (replace-match
12431 (char-to-string (car (rassoc (match-string 0 text) table)))
12432 t t text)))
12433 text)))
12435 (defun org-xor (a b)
12436 "Exclusive or."
12437 (if a (not b) b))
12439 (defun org-get-header (header)
12440 "Find a header field in the current buffer."
12441 (save-excursion
12442 (goto-char (point-min))
12443 (let ((case-fold-search t) s)
12444 (cond
12445 ((eq header 'from)
12446 (if (re-search-forward "^From:\\s-+\\(.*\\)" nil t)
12447 (setq s (match-string 1)))
12448 (while (string-match "\"" s)
12449 (setq s (replace-match "" t t s)))
12450 (if (string-match "[<(].*" s)
12451 (setq s (replace-match "" t t s))))
12452 ((eq header 'message-id)
12453 (if (re-search-forward "^message-id:\\s-+\\(.*\\)" nil t)
12454 (setq s (match-string 1))))
12455 ((eq header 'subject)
12456 (if (re-search-forward "^subject:\\s-+\\(.*\\)" nil t)
12457 (setq s (match-string 1)))))
12458 (if (string-match "\\`[ \t\]+" s) (setq s (replace-match "" t t s)))
12459 (if (string-match "[ \t\]+\\'" s) (setq s (replace-match "" t t s)))
12460 s)))
12463 (defun org-fixup-message-id-for-http (s)
12464 "Replace special characters in a message id, so it can be used in an http query."
12465 (while (string-match "<" s)
12466 (setq s (replace-match "%3C" t t s)))
12467 (while (string-match ">" s)
12468 (setq s (replace-match "%3E" t t s)))
12469 (while (string-match "@" s)
12470 (setq s (replace-match "%40" t t s)))
12473 ;;;###autoload
12474 (defun org-insert-link-global ()
12475 "Insert a link like Org-mode does.
12476 This command can be called in any mode to insert a link in Org-mode syntax."
12477 (interactive)
12478 (org-load-modules-maybe)
12479 (org-run-like-in-org-mode 'org-insert-link))
12481 (defun org-insert-link (&optional complete-file)
12482 "Insert a link. At the prompt, enter the link.
12484 Completion can be used to select a link previously stored with
12485 `org-store-link'. When the empty string is entered (i.e. if you just
12486 press RET at the prompt), the link defaults to the most recently
12487 stored link. As SPC triggers completion in the minibuffer, you need to
12488 use M-SPC or C-q SPC to force the insertion of a space character.
12490 You will also be prompted for a description, and if one is given, it will
12491 be displayed in the buffer instead of the link.
12493 If there is already a link at point, this command will allow you to edit link
12494 and description parts.
12496 With a \\[universal-argument] prefix, prompts for a file to link to. The file name can be
12497 selected using completion. The path to the file will be relative to
12498 the current directory if the file is in the current directory or a
12499 subdirectory. Otherwise, the link will be the absolute path as
12500 completed in the minibuffer (i.e. normally ~/path/to/file).
12502 With two \\[universal-argument] prefixes, enforce an absolute path even if the file
12503 is in the current directory or below.
12504 With three \\[universal-argument] prefixes, negate the meaning of
12505 `org-keep-stored-link-after-insertion'."
12506 (interactive "P")
12507 (let* ((wcf (current-window-configuration))
12508 (region (if (org-region-active-p)
12509 (buffer-substring (region-beginning) (region-end))))
12510 (remove (and region (list (region-beginning) (region-end))))
12511 (desc region)
12512 tmphist ; byte-compile incorrectly complains about this
12513 link entry file)
12514 (cond
12515 ((org-in-regexp org-bracket-link-regexp 1)
12516 ;; We do have a link at point, and we are going to edit it.
12517 (setq remove (list (match-beginning 0) (match-end 0)))
12518 (setq desc (if (match-end 3) (org-match-string-no-properties 3)))
12519 (setq link (read-string "Link: "
12520 (org-link-unescape
12521 (org-match-string-no-properties 1)))))
12522 ((or (org-in-regexp org-angle-link-re)
12523 (org-in-regexp org-plain-link-re))
12524 ;; Convert to bracket link
12525 (setq remove (list (match-beginning 0) (match-end 0))
12526 link (read-string "Link: "
12527 (org-remove-angle-brackets (match-string 0)))))
12528 ((equal complete-file '(4))
12529 ;; Completing read for file names.
12530 (setq file (read-file-name "File: "))
12531 (let ((pwd (file-name-as-directory (expand-file-name ".")))
12532 (pwd1 (file-name-as-directory (abbreviate-file-name
12533 (expand-file-name ".")))))
12534 (cond
12535 ((equal complete-file '(16))
12536 (setq link (org-make-link
12537 "file:"
12538 (abbreviate-file-name (expand-file-name file)))))
12539 ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
12540 (setq link (org-make-link "file:" (match-string 1 file))))
12541 ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
12542 (expand-file-name file))
12543 (setq link (org-make-link
12544 "file:" (match-string 1 (expand-file-name file)))))
12545 (t (setq link (org-make-link "file:" file))))))
12547 ;; Read link, with completion for stored links.
12548 (with-output-to-temp-buffer "*Org Links*"
12549 (princ "Insert a link. Use TAB to complete valid link prefixes.\n")
12550 (when org-stored-links
12551 (princ "\nStored links are available with <up>/<down> or M-p/n (most recent with RET):\n\n")
12552 (princ (mapconcat
12553 (lambda (x)
12554 (if (nth 1 x) (concat (car x) " (" (nth 1 x) ")") (car x)))
12555 (reverse org-stored-links) "\n"))))
12556 (let ((cw (selected-window)))
12557 (select-window (get-buffer-window "*Org Links*"))
12558 (shrink-window-if-larger-than-buffer)
12559 (setq truncate-lines t)
12560 (select-window cw))
12561 ;; Fake a link history, containing the stored links.
12562 (setq tmphist (append (mapcar 'car org-stored-links)
12563 org-insert-link-history))
12564 (unwind-protect
12565 (setq link (org-completing-read
12566 "Link: "
12567 (append
12568 (mapcar (lambda (x) (list (concat (car x) ":")))
12569 (append org-link-abbrev-alist-local org-link-abbrev-alist))
12570 (mapcar (lambda (x) (list (concat x ":")))
12571 org-link-types))
12572 nil nil nil
12573 'tmphist
12574 (or (car (car org-stored-links)))))
12575 (set-window-configuration wcf)
12576 (kill-buffer "*Org Links*"))
12577 (setq entry (assoc link org-stored-links))
12578 (or entry (push link org-insert-link-history))
12579 (if (funcall (if (equal complete-file '(64)) 'not 'identity)
12580 (not org-keep-stored-link-after-insertion))
12581 (setq org-stored-links (delq (assoc link org-stored-links)
12582 org-stored-links)))
12583 (setq desc (or desc (nth 1 entry)))))
12585 (if (string-match org-plain-link-re link)
12586 ;; URL-like link, normalize the use of angular brackets.
12587 (setq link (org-make-link (org-remove-angle-brackets link))))
12589 ;; Check if we are linking to the current file with a search option
12590 ;; If yes, simplify the link by using only the search option.
12591 (when (and buffer-file-name
12592 (string-match "\\<file:\\(.+?\\)::\\([^>]+\\)" link))
12593 (let* ((path (match-string 1 link))
12594 (case-fold-search nil)
12595 (search (match-string 2 link)))
12596 (save-match-data
12597 (if (equal (file-truename buffer-file-name) (file-truename path))
12598 ;; We are linking to this same file, with a search option
12599 (setq link search)))))
12601 ;; Check if we can/should use a relative path. If yes, simplify the link
12602 (when (string-match "\\<file:\\(.*\\)" link)
12603 (let* ((path (match-string 1 link))
12604 (origpath path)
12605 (case-fold-search nil))
12606 (cond
12607 ((eq org-link-file-path-type 'absolute)
12608 (setq path (abbreviate-file-name (expand-file-name path))))
12609 ((eq org-link-file-path-type 'noabbrev)
12610 (setq path (expand-file-name path)))
12611 ((eq org-link-file-path-type 'relative)
12612 (setq path (file-relative-name path)))
12614 (save-match-data
12615 (if (string-match (concat "^" (regexp-quote
12616 (file-name-as-directory
12617 (expand-file-name "."))))
12618 (expand-file-name path))
12619 ;; We are linking a file with relative path name.
12620 (setq path (substring (expand-file-name path)
12621 (match-end 0)))))))
12622 (setq link (concat "file:" path))
12623 (if (equal desc origpath)
12624 (setq desc path))))
12626 (setq desc (read-string "Description: " desc))
12627 (unless (string-match "\\S-" desc) (setq desc nil))
12628 (if remove (apply 'delete-region remove))
12629 (insert (org-make-link-string link desc))))
12631 (defun org-completing-read (&rest args)
12632 (let ((minibuffer-local-completion-map
12633 (copy-keymap minibuffer-local-completion-map)))
12634 (org-defkey minibuffer-local-completion-map " " 'self-insert-command)
12635 (apply 'completing-read args)))
12637 ;;; Opening/following a link
12638 (defvar org-link-search-failed nil)
12640 (defun org-next-link ()
12641 "Move forward to the next link.
12642 If the link is in hidden text, expose it."
12643 (interactive)
12644 (when (and org-link-search-failed (eq this-command last-command))
12645 (goto-char (point-min))
12646 (message "Link search wrapped back to beginning of buffer"))
12647 (setq org-link-search-failed nil)
12648 (let* ((pos (point))
12649 (ct (org-context))
12650 (a (assoc :link ct)))
12651 (if a (goto-char (nth 2 a)))
12652 (if (re-search-forward org-any-link-re nil t)
12653 (progn
12654 (goto-char (match-beginning 0))
12655 (if (org-invisible-p) (org-show-context)))
12656 (goto-char pos)
12657 (setq org-link-search-failed t)
12658 (error "No further link found"))))
12660 (defun org-previous-link ()
12661 "Move backward to the previous link.
12662 If the link is in hidden text, expose it."
12663 (interactive)
12664 (when (and org-link-search-failed (eq this-command last-command))
12665 (goto-char (point-max))
12666 (message "Link search wrapped back to end of buffer"))
12667 (setq org-link-search-failed nil)
12668 (let* ((pos (point))
12669 (ct (org-context))
12670 (a (assoc :link ct)))
12671 (if a (goto-char (nth 1 a)))
12672 (if (re-search-backward org-any-link-re nil t)
12673 (progn
12674 (goto-char (match-beginning 0))
12675 (if (org-invisible-p) (org-show-context)))
12676 (goto-char pos)
12677 (setq org-link-search-failed t)
12678 (error "No further link found"))))
12680 (defun org-find-file-at-mouse (ev)
12681 "Open file link or URL at mouse."
12682 (interactive "e")
12683 (mouse-set-point ev)
12684 (org-open-at-point 'in-emacs))
12686 (defun org-open-at-mouse (ev)
12687 "Open file link or URL at mouse."
12688 (interactive "e")
12689 (mouse-set-point ev)
12690 (org-open-at-point))
12692 (defvar org-window-config-before-follow-link nil
12693 "The window configuration before following a link.
12694 This is saved in case the need arises to restore it.")
12696 (defvar org-open-link-marker (make-marker)
12697 "Marker pointing to the location where `org-open-at-point; was called.")
12699 ;;;###autoload
12700 (defun org-open-at-point-global ()
12701 "Follow a link like Org-mode does.
12702 This command can be called in any mode to follow a link that has
12703 Org-mode syntax."
12704 (interactive)
12705 (org-run-like-in-org-mode 'org-open-at-point))
12707 (defun org-open-at-point (&optional in-emacs)
12708 "Open link at or after point.
12709 If there is no link at point, this function will search forward up to
12710 the end of the current subtree.
12711 Normally, files will be opened by an appropriate application. If the
12712 optional argument IN-EMACS is non-nil, Emacs will visit the file."
12713 (interactive "P")
12714 (org-load-modules-maybe)
12715 (move-marker org-open-link-marker (point))
12716 (setq org-window-config-before-follow-link (current-window-configuration))
12717 (org-remove-occur-highlights nil nil t)
12718 (if (org-at-timestamp-p t)
12719 (org-follow-timestamp-link)
12720 (let (type path link line search (pos (point)))
12721 (catch 'match
12722 (save-excursion
12723 (skip-chars-forward "^]\n\r")
12724 (when (org-in-regexp org-bracket-link-regexp)
12725 (setq link (org-link-unescape (org-match-string-no-properties 1)))
12726 (while (string-match " *\n *" link)
12727 (setq link (replace-match " " t t link)))
12728 (setq link (org-link-expand-abbrev link))
12729 (if (string-match org-link-re-with-space2 link)
12730 (setq type (match-string 1 link) path (match-string 2 link))
12731 (setq type "thisfile" path link))
12732 (throw 'match t)))
12734 (when (get-text-property (point) 'org-linked-text)
12735 (setq type "thisfile"
12736 pos (if (get-text-property (1+ (point)) 'org-linked-text)
12737 (1+ (point)) (point))
12738 path (buffer-substring
12739 (previous-single-property-change pos 'org-linked-text)
12740 (next-single-property-change pos 'org-linked-text)))
12741 (throw 'match t))
12743 (save-excursion
12744 (when (or (org-in-regexp org-angle-link-re)
12745 (org-in-regexp org-plain-link-re))
12746 (setq type (match-string 1) path (match-string 2))
12747 (throw 'match t)))
12748 (when (org-in-regexp "\\<\\([^><\n]+\\)\\>")
12749 (setq type "tree-match"
12750 path (match-string 1))
12751 (throw 'match t))
12752 (save-excursion
12753 (when (org-in-regexp (org-re "\\(:[[:alnum:]_@:]+\\):[ \t]*$"))
12754 (setq type "tags"
12755 path (match-string 1))
12756 (while (string-match ":" path)
12757 (setq path (replace-match "+" t t path)))
12758 (throw 'match t))))
12759 (unless path
12760 (error "No link found"))
12761 ;; Remove any trailing spaces in path
12762 (if (string-match " +\\'" path)
12763 (setq path (replace-match "" t t path)))
12765 (cond
12767 ((assoc type org-link-protocols)
12768 (funcall (nth 1 (assoc type org-link-protocols)) path))
12770 ((equal type "mailto")
12771 (let ((cmd (car org-link-mailto-program))
12772 (args (cdr org-link-mailto-program)) args1
12773 (address path) (subject "") a)
12774 (if (string-match "\\(.*\\)::\\(.*\\)" path)
12775 (setq address (match-string 1 path)
12776 subject (org-link-escape (match-string 2 path))))
12777 (while args
12778 (cond
12779 ((not (stringp (car args))) (push (pop args) args1))
12780 (t (setq a (pop args))
12781 (if (string-match "%a" a)
12782 (setq a (replace-match address t t a)))
12783 (if (string-match "%s" a)
12784 (setq a (replace-match subject t t a)))
12785 (push a args1))))
12786 (apply cmd (nreverse args1))))
12788 ((member type '("http" "https" "ftp" "news"))
12789 (browse-url (concat type ":" (org-link-escape
12790 path org-link-escape-chars-browser))))
12792 ((member type '("message"))
12793 (browse-url (concat type ":" path)))
12795 ((string= type "tags")
12796 (org-tags-view in-emacs path))
12797 ((string= type "thisfile")
12798 (if in-emacs
12799 (switch-to-buffer-other-window
12800 (org-get-buffer-for-internal-link (current-buffer)))
12801 (org-mark-ring-push))
12802 (let ((cmd `(org-link-search
12803 ,path
12804 ,(cond ((equal in-emacs '(4)) 'occur)
12805 ((equal in-emacs '(16)) 'org-occur)
12806 (t nil))
12807 ,pos)))
12808 (condition-case nil (eval cmd)
12809 (error (progn (widen) (eval cmd))))))
12811 ((string= type "tree-match")
12812 (org-occur (concat "\\[" (regexp-quote path) "\\]")))
12814 ((string= type "file")
12815 (if (string-match "::\\([0-9]+\\)\\'" path)
12816 (setq line (string-to-number (match-string 1 path))
12817 path (substring path 0 (match-beginning 0)))
12818 (if (string-match "::\\(.+\\)\\'" path)
12819 (setq search (match-string 1 path)
12820 path (substring path 0 (match-beginning 0)))))
12821 (if (string-match "[*?{]" (file-name-nondirectory path))
12822 (dired path)
12823 (org-open-file path in-emacs line search)))
12825 ((string= type "news")
12826 (require 'org-gnus)
12827 (org-gnus-follow-link path))
12829 ((string= type "shell")
12830 (let ((cmd path))
12831 (if (or (not org-confirm-shell-link-function)
12832 (funcall org-confirm-shell-link-function
12833 (format "Execute \"%s\" in shell? "
12834 (org-add-props cmd nil
12835 'face 'org-warning))))
12836 (progn
12837 (message "Executing %s" cmd)
12838 (shell-command cmd))
12839 (error "Abort"))))
12841 ((string= type "elisp")
12842 (let ((cmd path))
12843 (if (or (not org-confirm-elisp-link-function)
12844 (funcall org-confirm-elisp-link-function
12845 (format "Execute \"%s\" as elisp? "
12846 (org-add-props cmd nil
12847 'face 'org-warning))))
12848 (message "%s => %s" cmd (eval (read cmd)))
12849 (error "Abort"))))
12852 (browse-url-at-point)))))
12853 (move-marker org-open-link-marker nil)
12854 (run-hook-with-args 'org-follow-link-hook))
12856 ;;; File search
12858 (defvar org-create-file-search-functions nil
12859 "List of functions to construct the right search string for a file link.
12860 These functions are called in turn with point at the location to
12861 which the link should point.
12863 A function in the hook should first test if it would like to
12864 handle this file type, for example by checking the major-mode or
12865 the file extension. If it decides not to handle this file, it
12866 should just return nil to give other functions a chance. If it
12867 does handle the file, it must return the search string to be used
12868 when following the link. The search string will be part of the
12869 file link, given after a double colon, and `org-open-at-point'
12870 will automatically search for it. If special measures must be
12871 taken to make the search successful, another function should be
12872 added to the companion hook `org-execute-file-search-functions',
12873 which see.
12875 A function in this hook may also use `setq' to set the variable
12876 `description' to provide a suggestion for the descriptive text to
12877 be used for this link when it gets inserted into an Org-mode
12878 buffer with \\[org-insert-link].")
12880 (defvar org-execute-file-search-functions nil
12881 "List of functions to execute a file search triggered by a link.
12883 Functions added to this hook must accept a single argument, the
12884 search string that was part of the file link, the part after the
12885 double colon. The function must first check if it would like to
12886 handle this search, for example by checking the major-mode or the
12887 file extension. If it decides not to handle this search, it
12888 should just return nil to give other functions a chance. If it
12889 does handle the search, it must return a non-nil value to keep
12890 other functions from trying.
12892 Each function can access the current prefix argument through the
12893 variable `current-prefix-argument'. Note that a single prefix is
12894 used to force opening a link in Emacs, so it may be good to only
12895 use a numeric or double prefix to guide the search function.
12897 In case this is needed, a function in this hook can also restore
12898 the window configuration before `org-open-at-point' was called using:
12900 (set-window-configuration org-window-config-before-follow-link)")
12902 (defun org-link-search (s &optional type avoid-pos)
12903 "Search for a link search option.
12904 If S is surrounded by forward slashes, it is interpreted as a
12905 regular expression. In org-mode files, this will create an `org-occur'
12906 sparse tree. In ordinary files, `occur' will be used to list matches.
12907 If the current buffer is in `dired-mode', grep will be used to search
12908 in all files. If AVOID-POS is given, ignore matches near that position."
12909 (let ((case-fold-search t)
12910 (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " "))
12911 (markers (concat "\\(?:" (mapconcat (lambda (x) (regexp-quote (car x)))
12912 (append '(("") (" ") ("\t") ("\n"))
12913 org-emphasis-alist)
12914 "\\|") "\\)"))
12915 (pos (point))
12916 (pre "") (post "")
12917 words re0 re1 re2 re3 re4 re5 re2a reall)
12918 (cond
12919 ;; First check if there are any special
12920 ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
12921 ;; Now try the builtin stuff
12922 ((save-excursion
12923 (goto-char (point-min))
12924 (and
12925 (re-search-forward
12926 (concat "<<" (regexp-quote s0) ">>") nil t)
12927 (setq pos (match-beginning 0))))
12928 ;; There is an exact target for this
12929 (goto-char pos))
12930 ((string-match "^/\\(.*\\)/$" s)
12931 ;; A regular expression
12932 (cond
12933 ((org-mode-p)
12934 (org-occur (match-string 1 s)))
12935 ;;((eq major-mode 'dired-mode)
12936 ;; (grep (concat "grep -n -e '" (match-string 1 s) "' *")))
12937 (t (org-do-occur (match-string 1 s)))))
12939 ;; A normal search strings
12940 (when (equal (string-to-char s) ?*)
12941 ;; Anchor on headlines, post may include tags.
12942 (setq pre "^\\*+[ \t]+\\(?:\\sw+\\)?[ \t]*"
12943 post (org-re "[ \t]*\\(?:[ \t]+:[[:alnum:]_@:+]:[ \t]*\\)?$")
12944 s (substring s 1)))
12945 (remove-text-properties
12946 0 (length s)
12947 '(face nil mouse-face nil keymap nil fontified nil) s)
12948 ;; Make a series of regular expressions to find a match
12949 (setq words (org-split-string s "[ \n\r\t]+")
12950 re0 (concat "\\(<<" (regexp-quote s0) ">>\\)")
12951 re2 (concat markers "\\(" (mapconcat 'downcase words "[ \t]+")
12952 "\\)" markers)
12953 re2a (concat "[ \t\r\n]\\(" (mapconcat 'downcase words "[ \t\r\n]+") "\\)[ \t\r\n]")
12954 re4 (concat "[^a-zA-Z_]\\(" (mapconcat 'downcase words "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
12955 re1 (concat pre re2 post)
12956 re3 (concat pre re4 post)
12957 re5 (concat pre ".*" re4)
12958 re2 (concat pre re2)
12959 re2a (concat pre re2a)
12960 re4 (concat pre re4)
12961 reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2
12962 "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\("
12963 re5 "\\)"
12965 (cond
12966 ((eq type 'org-occur) (org-occur reall))
12967 ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
12968 (t (goto-char (point-min))
12969 (if (or (org-search-not-self 1 re0 nil t)
12970 (org-search-not-self 1 re1 nil t)
12971 (org-search-not-self 1 re2 nil t)
12972 (org-search-not-self 1 re2a nil t)
12973 (org-search-not-self 1 re3 nil t)
12974 (org-search-not-self 1 re4 nil t)
12975 (org-search-not-self 1 re5 nil t)
12977 (goto-char (match-beginning 1))
12978 (goto-char pos)
12979 (error "No match")))))
12981 ;; Normal string-search
12982 (goto-char (point-min))
12983 (if (search-forward s nil t)
12984 (goto-char (match-beginning 0))
12985 (error "No match"))))
12986 (and (org-mode-p) (org-show-context 'link-search))))
12988 (defun org-search-not-self (group &rest args)
12989 "Execute `re-search-forward', but only accept matches that do not
12990 enclose the position of `org-open-link-marker'."
12991 (let ((m org-open-link-marker))
12992 (catch 'exit
12993 (while (apply 're-search-forward args)
12994 (unless (get-text-property (match-end group) 'intangible) ; Emacs 21
12995 (goto-char (match-end group))
12996 (if (and (or (not (eq (marker-buffer m) (current-buffer)))
12997 (> (match-beginning 0) (marker-position m))
12998 (< (match-end 0) (marker-position m)))
12999 (save-match-data
13000 (or (not (org-in-regexp
13001 org-bracket-link-analytic-regexp 1))
13002 (not (match-end 4)) ; no description
13003 (and (<= (match-beginning 4) (point))
13004 (>= (match-end 4) (point))))))
13005 (throw 'exit (point))))))))
13007 (defun org-get-buffer-for-internal-link (buffer)
13008 "Return a buffer to be used for displaying the link target of internal links."
13009 (cond
13010 ((not org-display-internal-link-with-indirect-buffer)
13011 buffer)
13012 ((string-match "(Clone)$" (buffer-name buffer))
13013 (message "Buffer is already a clone, not making another one")
13014 ;; we also do not modify visibility in this case
13015 buffer)
13016 (t ; make a new indirect buffer for displaying the link
13017 (let* ((bn (buffer-name buffer))
13018 (ibn (concat bn "(Clone)"))
13019 (ib (or (get-buffer ibn) (make-indirect-buffer buffer ibn 'clone))))
13020 (with-current-buffer ib (org-overview))
13021 ib))))
13023 (defun org-do-occur (regexp &optional cleanup)
13024 "Call the Emacs command `occur'.
13025 If CLEANUP is non-nil, remove the printout of the regular expression
13026 in the *Occur* buffer. This is useful if the regex is long and not useful
13027 to read."
13028 (occur regexp)
13029 (when cleanup
13030 (let ((cwin (selected-window)) win beg end)
13031 (when (setq win (get-buffer-window "*Occur*"))
13032 (select-window win))
13033 (goto-char (point-min))
13034 (when (re-search-forward "match[a-z]+" nil t)
13035 (setq beg (match-end 0))
13036 (if (re-search-forward "^[ \t]*[0-9]+" nil t)
13037 (setq end (1- (match-beginning 0)))))
13038 (and beg end (let ((inhibit-read-only t)) (delete-region beg end)))
13039 (goto-char (point-min))
13040 (select-window cwin))))
13042 ;;; The mark ring for links jumps
13044 (defvar org-mark-ring nil
13045 "Mark ring for positions before jumps in Org-mode.")
13046 (defvar org-mark-ring-last-goto nil
13047 "Last position in the mark ring used to go back.")
13048 ;; Fill and close the ring
13049 (setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is reloaded
13050 (loop for i from 1 to org-mark-ring-length do
13051 (push (make-marker) org-mark-ring))
13052 (setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring)
13053 org-mark-ring)
13055 (defun org-mark-ring-push (&optional pos buffer)
13056 "Put the current position or POS into the mark ring and rotate it."
13057 (interactive)
13058 (setq pos (or pos (point)))
13059 (setq org-mark-ring (nthcdr (1- org-mark-ring-length) org-mark-ring))
13060 (move-marker (car org-mark-ring)
13061 (or pos (point))
13062 (or buffer (current-buffer)))
13063 (message "%s"
13064 (substitute-command-keys
13065 "Position saved to mark ring, go back with \\[org-mark-ring-goto].")))
13067 (defun org-mark-ring-goto (&optional n)
13068 "Jump to the previous position in the mark ring.
13069 With prefix arg N, jump back that many stored positions. When
13070 called several times in succession, walk through the entire ring.
13071 Org-mode commands jumping to a different position in the current file,
13072 or to another Org-mode file, automatically push the old position
13073 onto the ring."
13074 (interactive "p")
13075 (let (p m)
13076 (if (eq last-command this-command)
13077 (setq p (nthcdr n (or org-mark-ring-last-goto org-mark-ring)))
13078 (setq p org-mark-ring))
13079 (setq org-mark-ring-last-goto p)
13080 (setq m (car p))
13081 (switch-to-buffer (marker-buffer m))
13082 (goto-char m)
13083 (if (or (org-invisible-p) (org-invisible-p2)) (org-show-context 'mark-goto))))
13085 (defun org-remove-angle-brackets (s)
13086 (if (equal (substring s 0 1) "<") (setq s (substring s 1)))
13087 (if (equal (substring s -1) ">") (setq s (substring s 0 -1)))
13089 (defun org-add-angle-brackets (s)
13090 (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s)))
13091 (if (equal (substring s -1) ">") nil (setq s (concat s ">")))
13094 ;;; Following specific links
13096 (defun org-follow-timestamp-link ()
13097 (cond
13098 ((org-at-date-range-p t)
13099 (let ((org-agenda-start-on-weekday)
13100 (t1 (match-string 1))
13101 (t2 (match-string 2)))
13102 (setq t1 (time-to-days (org-time-string-to-time t1))
13103 t2 (time-to-days (org-time-string-to-time t2)))
13104 (org-agenda-list nil t1 (1+ (- t2 t1)))))
13105 ((org-at-timestamp-p t)
13106 (org-agenda-list nil (time-to-days (org-time-string-to-time
13107 (substring (match-string 1) 0 10)))
13109 (t (error "This should not happen"))))
13112 ;;; BibTeX links
13114 ;; Use the custom search meachnism to construct and use search strings for
13115 ;; file links to BibTeX database entries.
13117 (defun org-create-file-search-in-bibtex ()
13118 "Create the search string and description for a BibTeX database entry."
13119 (when (eq major-mode 'bibtex-mode)
13120 ;; yes, we want to construct this search string.
13121 ;; Make a good description for this entry, using names, year and the title
13122 ;; Put it into the `description' variable which is dynamically scoped.
13123 (let ((bibtex-autokey-names 1)
13124 (bibtex-autokey-names-stretch 1)
13125 (bibtex-autokey-name-case-convert-function 'identity)
13126 (bibtex-autokey-name-separator " & ")
13127 (bibtex-autokey-additional-names " et al.")
13128 (bibtex-autokey-year-length 4)
13129 (bibtex-autokey-name-year-separator " ")
13130 (bibtex-autokey-titlewords 3)
13131 (bibtex-autokey-titleword-separator " ")
13132 (bibtex-autokey-titleword-case-convert-function 'identity)
13133 (bibtex-autokey-titleword-length 'infty)
13134 (bibtex-autokey-year-title-separator ": "))
13135 (setq description (bibtex-generate-autokey)))
13136 ;; Now parse the entry, get the key and return it.
13137 (save-excursion
13138 (bibtex-beginning-of-entry)
13139 (cdr (assoc "=key=" (bibtex-parse-entry))))))
13141 (defun org-execute-file-search-in-bibtex (s)
13142 "Find the link search string S as a key for a database entry."
13143 (when (eq major-mode 'bibtex-mode)
13144 ;; Yes, we want to do the search in this file.
13145 ;; We construct a regexp that searches for "@entrytype{" followed by the key
13146 (goto-char (point-min))
13147 (and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*"
13148 (regexp-quote s) "[ \t\n]*,") nil t)
13149 (goto-char (match-beginning 0)))
13150 (if (and (match-beginning 0) (equal current-prefix-arg '(16)))
13151 ;; Use double prefix to indicate that any web link should be browsed
13152 (let ((b (current-buffer)) (p (point)))
13153 ;; Restore the window configuration because we just use the web link
13154 (set-window-configuration org-window-config-before-follow-link)
13155 (save-excursion (set-buffer b) (goto-char p)
13156 (bibtex-url)))
13157 (recenter 0)) ; Move entry start to beginning of window
13158 ;; return t to indicate that the search is done.
13161 ;; Finally add the functions to the right hooks.
13162 (add-hook 'org-create-file-search-functions 'org-create-file-search-in-bibtex)
13163 (add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-bibtex)
13165 ;; end of Bibtex link setup
13167 ;;; Following file links
13169 (defun org-open-file (path &optional in-emacs line search)
13170 "Open the file at PATH.
13171 First, this expands any special file name abbreviations. Then the
13172 configuration variable `org-file-apps' is checked if it contains an
13173 entry for this file type, and if yes, the corresponding command is launched.
13174 If no application is found, Emacs simply visits the file.
13175 With optional argument IN-EMACS, Emacs will visit the file.
13176 Optional LINE specifies a line to go to, optional SEARCH a string to
13177 search for. If LINE or SEARCH is given, the file will always be
13178 opened in Emacs.
13179 If the file does not exist, an error is thrown."
13180 (setq in-emacs (or in-emacs line search))
13181 (let* ((file (if (equal path "")
13182 buffer-file-name
13183 (substitute-in-file-name (expand-file-name path))))
13184 (apps (append org-file-apps (org-default-apps)))
13185 (remp (and (assq 'remote apps) (org-file-remote-p file)))
13186 (dirp (if remp nil (file-directory-p file)))
13187 (dfile (downcase file))
13188 (old-buffer (current-buffer))
13189 (old-pos (point))
13190 (old-mode major-mode)
13191 ext cmd)
13192 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
13193 (setq ext (match-string 1 dfile))
13194 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
13195 (setq ext (match-string 1 dfile))))
13196 (if in-emacs
13197 (setq cmd 'emacs)
13198 (setq cmd (or (and remp (cdr (assoc 'remote apps)))
13199 (and dirp (cdr (assoc 'directory apps)))
13200 (cdr (assoc ext apps))
13201 (cdr (assoc t apps)))))
13202 (when (eq cmd 'mailcap)
13203 (require 'mailcap)
13204 (mailcap-parse-mailcaps)
13205 (let* ((mime-type (mailcap-extension-to-mime (or ext "")))
13206 (command (mailcap-mime-info mime-type)))
13207 (if (stringp command)
13208 (setq cmd command)
13209 (setq cmd 'emacs))))
13210 (if (and (not (eq cmd 'emacs)) ; Emacs has no problems with non-ex files
13211 (not (file-exists-p file))
13212 (not org-open-non-existing-files))
13213 (error "No such file: %s" file))
13214 (cond
13215 ((and (stringp cmd) (not (string-match "^\\s-*$" cmd)))
13216 ;; Remove quotes around the file name - we'll use shell-quote-argument.
13217 (while (string-match "['\"]%s['\"]" cmd)
13218 (setq cmd (replace-match "%s" t t cmd)))
13219 (while (string-match "%s" cmd)
13220 (setq cmd (replace-match
13221 (save-match-data (shell-quote-argument file))
13222 t t cmd)))
13223 (save-window-excursion
13224 (start-process-shell-command cmd nil cmd)))
13225 ((or (stringp cmd)
13226 (eq cmd 'emacs))
13227 (funcall (cdr (assq 'file org-link-frame-setup)) file)
13228 (widen)
13229 (if line (goto-line line)
13230 (if search (org-link-search search))))
13231 ((consp cmd)
13232 (eval cmd))
13233 (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
13234 (and (org-mode-p) (eq old-mode 'org-mode)
13235 (or (not (equal old-buffer (current-buffer)))
13236 (not (equal old-pos (point))))
13237 (org-mark-ring-push old-pos old-buffer))))
13239 (defun org-default-apps ()
13240 "Return the default applications for this operating system."
13241 (cond
13242 ((eq system-type 'darwin)
13243 org-file-apps-defaults-macosx)
13244 ((eq system-type 'windows-nt)
13245 org-file-apps-defaults-windowsnt)
13246 (t org-file-apps-defaults-gnu)))
13248 (defvar ange-ftp-name-format) ; to silence the XEmacs compiler.
13249 (defun org-file-remote-p (file)
13250 "Test whether FILE specifies a location on a remote system.
13251 Return non-nil if the location is indeed remote.
13253 For example, the filename \"/user@host:/foo\" specifies a location
13254 on the system \"/user@host:\"."
13255 (cond ((fboundp 'file-remote-p)
13256 (file-remote-p file))
13257 ((fboundp 'tramp-handle-file-remote-p)
13258 (tramp-handle-file-remote-p file))
13259 ((and (boundp 'ange-ftp-name-format)
13260 (string-match (car ange-ftp-name-format) file))
13262 (t nil)))
13265 ;;;; Hooks for remember.el, and refiling
13267 (defvar annotation) ; from remember.el, dynamically scoped in `remember-mode'
13268 (defvar initial) ; from remember.el, dynamically scoped in `remember-mode'
13270 ;;;###autoload
13271 (defun org-remember-insinuate ()
13272 "Setup remember.el for use wiht Org-mode."
13273 (require 'remember)
13274 (setq remember-annotation-functions '(org-remember-annotation))
13275 (setq remember-handler-functions '(org-remember-handler))
13276 (add-hook 'remember-mode-hook 'org-remember-apply-template))
13278 ;;;###autoload
13279 (defun org-remember-annotation ()
13280 "Return a link to the current location as an annotation for remember.el.
13281 If you are using Org-mode files as target for data storage with
13282 remember.el, then the annotations should include a link compatible with the
13283 conventions in Org-mode. This function returns such a link."
13284 (org-store-link nil))
13286 (defconst org-remember-help
13287 "Select a destination location for the note.
13288 UP/DOWN=headline TAB=cycle visibility [Q]uit RET/<left>/<right>=Store
13289 RET on headline -> Store as sublevel entry to current headline
13290 RET at beg-of-buf -> Append to file as level 2 headline
13291 <left>/<right> -> before/after current headline, same headings level")
13293 (defvar org-remember-previous-location nil)
13294 (defvar org-force-remember-template-char) ;; dynamically scoped
13296 ;; Save the major mode of the buffer we called remember from
13297 (defvar org-select-template-temp-major-mode nil)
13299 ;; Temporary store the buffer where remember was called from
13300 (defvar org-select-template-original-buffer nil)
13302 (defun org-select-remember-template (&optional use-char)
13303 (when org-remember-templates
13304 (let* ((pre-selected-templates
13305 (mapcar
13306 (lambda (tpl)
13307 (let ((ctxt (nth 5 tpl))
13308 (mode org-select-template-temp-major-mode)
13309 (buf org-select-template-original-buffer))
13310 (and (or (not ctxt) (eq ctxt t)
13311 (and (listp ctxt) (memq mode ctxt))
13312 (and (functionp ctxt)
13313 (with-current-buffer buf
13314 ;; Protect the user-defined function from error
13315 (condition-case nil (funcall ctxt) (error nil)))))
13316 tpl)))
13317 org-remember-templates))
13318 ;; If no template at this point, add the default templates:
13319 (pre-selected-templates1
13320 (if (not (delq nil pre-selected-templates))
13321 (mapcar (lambda(x) (if (not (nth 5 x)) x))
13322 org-remember-templates)
13323 pre-selected-templates))
13324 ;; Then unconditionnally add template for any contexts
13325 (pre-selected-templates2
13326 (append (mapcar (lambda(x) (if (eq (nth 5 x) t) x))
13327 org-remember-templates)
13328 (delq nil pre-selected-templates1)))
13329 (templates (mapcar (lambda (x)
13330 (if (stringp (car x))
13331 (append (list (nth 1 x) (car x)) (cddr x))
13332 (append (list (car x) "") (cdr x))))
13333 (delq nil pre-selected-templates2)))
13334 (char (or use-char
13335 (cond
13336 ((= (length templates) 1)
13337 (caar templates))
13338 ((and (boundp 'org-force-remember-template-char)
13339 org-force-remember-template-char)
13340 (if (stringp org-force-remember-template-char)
13341 (string-to-char org-force-remember-template-char)
13342 org-force-remember-template-char))
13344 (message "Select template: %s"
13345 (mapconcat
13346 (lambda (x)
13347 (cond
13348 ((not (string-match "\\S-" (nth 1 x)))
13349 (format "[%c]" (car x)))
13350 ((equal (downcase (car x))
13351 (downcase (aref (nth 1 x) 0)))
13352 (format "[%c]%s" (car x)
13353 (substring (nth 1 x) 1)))
13354 (t (format "[%c]%s" (car x) (nth 1 x)))))
13355 templates " "))
13356 (let ((inhibit-quit t) (char0 (read-char-exclusive)))
13357 (when (equal char0 ?\C-g)
13358 (jump-to-register remember-register)
13359 (kill-buffer remember-buffer))
13360 char0))))))
13361 (cddr (assoc char templates)))))
13363 (defvar x-last-selected-text)
13364 (defvar x-last-selected-text-primary)
13366 ;;;###autoload
13367 (defun org-remember-apply-template (&optional use-char skip-interactive)
13368 "Initialize *remember* buffer with template, invoke `org-mode'.
13369 This function should be placed into `remember-mode-hook' and in fact requires
13370 to be run from that hook to function properly."
13371 (if org-remember-templates
13372 (let* ((entry (org-select-remember-template use-char))
13373 (tpl (car entry))
13374 (plist-p (if org-store-link-plist t nil))
13375 (file (if (and (nth 1 entry) (stringp (nth 1 entry))
13376 (string-match "\\S-" (nth 1 entry)))
13377 (nth 1 entry)
13378 org-default-notes-file))
13379 (headline (nth 2 entry))
13380 (v-c (or (and (eq window-system 'x)
13381 (fboundp 'x-cut-buffer-or-selection-value)
13382 (x-cut-buffer-or-selection-value))
13383 (org-bound-and-true-p x-last-selected-text)
13384 (org-bound-and-true-p x-last-selected-text-primary)
13385 (and (> (length kill-ring) 0) (current-kill 0))))
13386 (v-t (format-time-string (car org-time-stamp-formats) (org-current-time)))
13387 (v-T (format-time-string (cdr org-time-stamp-formats) (org-current-time)))
13388 (v-u (concat "[" (substring v-t 1 -1) "]"))
13389 (v-U (concat "[" (substring v-T 1 -1) "]"))
13390 ;; `initial' and `annotation' are bound in `remember'
13391 (v-i (if (boundp 'initial) initial))
13392 (v-a (if (and (boundp 'annotation) annotation)
13393 (if (equal annotation "[[]]") "" annotation)
13394 ""))
13395 (v-A (if (and v-a
13396 (string-match "\\[\\(\\[.*?\\]\\)\\(\\[.*?\\]\\)?\\]" v-a))
13397 (replace-match "[\\1[%^{Link description}]]" nil nil v-a)
13398 v-a))
13399 (v-n user-full-name)
13400 (org-startup-folded nil)
13401 org-time-was-given org-end-time-was-given x
13402 prompt completions char time pos default histvar)
13403 (setq org-store-link-plist
13404 (append (list :annotation v-a :initial v-i)
13405 org-store-link-plist))
13406 (unless tpl (setq tpl "") (message "No template") (ding) (sit-for 1))
13407 (erase-buffer)
13408 (insert (substitute-command-keys
13409 (format
13410 "## Filing location: Select interactively, default, or last used:
13411 ## %s to select file and header location interactively.
13412 ## %s \"%s\" -> \"* %s\"
13413 ## C-u C-u C-c C-c \"%s\" -> \"* %s\"
13414 ## To switch templates, use `\\[org-remember]'. To abort use `C-c C-k'.\n\n"
13415 (if org-remember-store-without-prompt " C-u C-c C-c" " C-c C-c")
13416 (if org-remember-store-without-prompt " C-c C-c" " C-u C-c C-c")
13417 (abbreviate-file-name (or file org-default-notes-file))
13418 (or headline "")
13419 (or (car org-remember-previous-location) "???")
13420 (or (cdr org-remember-previous-location) "???"))))
13421 (insert tpl) (goto-char (point-min))
13422 ;; Simple %-escapes
13423 (while (re-search-forward "%\\([tTuUaiAc]\\)" nil t)
13424 (when (and initial (equal (match-string 0) "%i"))
13425 (save-match-data
13426 (let* ((lead (buffer-substring
13427 (point-at-bol) (match-beginning 0))))
13428 (setq v-i (mapconcat 'identity
13429 (org-split-string initial "\n")
13430 (concat "\n" lead))))))
13431 (replace-match
13432 (or (eval (intern (concat "v-" (match-string 1)))) "")
13433 t t))
13435 ;; %[] Insert contents of a file.
13436 (goto-char (point-min))
13437 (while (re-search-forward "%\\[\\(.+\\)\\]" nil t)
13438 (let ((start (match-beginning 0))
13439 (end (match-end 0))
13440 (filename (expand-file-name (match-string 1))))
13441 (goto-char start)
13442 (delete-region start end)
13443 (condition-case error
13444 (insert-file-contents filename)
13445 (error (insert (format "%%![Couldn't insert %s: %s]"
13446 filename error))))))
13447 ;; %() embedded elisp
13448 (goto-char (point-min))
13449 (while (re-search-forward "%\\((.+)\\)" nil t)
13450 (goto-char (match-beginning 0))
13451 (let ((template-start (point)))
13452 (forward-char 1)
13453 (let ((result
13454 (condition-case error
13455 (eval (read (current-buffer)))
13456 (error (format "%%![Error: %s]" error)))))
13457 (delete-region template-start (point))
13458 (insert result))))
13460 ;; From the property list
13461 (when plist-p
13462 (goto-char (point-min))
13463 (while (re-search-forward "%\\(:[-a-zA-Z]+\\)" nil t)
13464 (and (setq x (or (plist-get org-store-link-plist
13465 (intern (match-string 1))) ""))
13466 (replace-match x t t))))
13468 ;; Turn on org-mode in the remember buffer, set local variables
13469 (org-mode)
13470 (org-set-local 'org-finish-function 'org-remember-finalize)
13471 (if (and file (string-match "\\S-" file) (not (file-directory-p file)))
13472 (org-set-local 'org-default-notes-file file))
13473 (if (and headline (stringp headline) (string-match "\\S-" headline))
13474 (org-set-local 'org-remember-default-headline headline))
13475 ;; Interactive template entries
13476 (goto-char (point-min))
13477 (while (re-search-forward "%^\\({\\([^}]*\\)}\\)?\\([gGuUtT]\\)?" nil t)
13478 (setq char (if (match-end 3) (match-string 3))
13479 prompt (if (match-end 2) (match-string 2)))
13480 (goto-char (match-beginning 0))
13481 (replace-match "")
13482 (setq completions nil default nil)
13483 (when prompt
13484 (setq completions (org-split-string prompt "|")
13485 prompt (pop completions)
13486 default (car completions)
13487 histvar (intern (concat
13488 "org-remember-template-prompt-history::"
13489 (or prompt "")))
13490 completions (mapcar 'list completions)))
13491 (cond
13492 ((member char '("G" "g"))
13493 (let* ((org-last-tags-completion-table
13494 (org-global-tags-completion-table
13495 (if (equal char "G") (org-agenda-files) (and file (list file)))))
13496 (org-add-colon-after-tag-completion t)
13497 (ins (completing-read
13498 (if prompt (concat prompt ": ") "Tags: ")
13499 'org-tags-completion-function nil nil nil
13500 'org-tags-history)))
13501 (setq ins (mapconcat 'identity
13502 (org-split-string ins (org-re "[^[:alnum:]_@]+"))
13503 ":"))
13504 (when (string-match "\\S-" ins)
13505 (or (equal (char-before) ?:) (insert ":"))
13506 (insert ins)
13507 (or (equal (char-after) ?:) (insert ":")))))
13508 (char
13509 (setq org-time-was-given (equal (upcase char) char))
13510 (setq time (org-read-date (equal (upcase char) "U") t nil
13511 prompt))
13512 (org-insert-time-stamp time org-time-was-given
13513 (member char '("u" "U"))
13514 nil nil (list org-end-time-was-given)))
13516 (insert (org-completing-read
13517 (concat (if prompt prompt "Enter string")
13518 (if default (concat " [" default "]"))
13519 ": ")
13520 completions nil nil nil histvar default)))))
13521 (goto-char (point-min))
13522 (if (re-search-forward "%\\?" nil t)
13523 (replace-match "")
13524 (and (re-search-forward "^[^#\n]" nil t) (backward-char 1))))
13525 (org-mode)
13526 (org-set-local 'org-finish-function 'org-remember-finalize))
13527 (when (save-excursion
13528 (goto-char (point-min))
13529 (re-search-forward "%!" nil t))
13530 (replace-match "")
13531 (add-hook 'post-command-hook 'org-remember-finish-immediately 'append)))
13533 (defun org-remember-finish-immediately ()
13534 "File remember note immediately.
13535 This should be run in `post-command-hook' and will remove itself
13536 from that hook."
13537 (remove-hook 'post-command-hook 'org-remember-finish-immediately)
13538 (when org-finish-function
13539 (funcall org-finish-function)))
13541 (defvar org-clock-marker) ; Defined below
13542 (defun org-remember-finalize ()
13543 "Finalize the remember process."
13544 (unless (fboundp 'remember-finalize)
13545 (defalias 'remember-finalize 'remember-buffer))
13546 (when (and org-clock-marker
13547 (equal (marker-buffer org-clock-marker) (current-buffer)))
13548 ;; FIXME: test this, this is w/o notetaking!
13549 (let (org-log-note-clock-out) (org-clock-out)))
13550 (when buffer-file-name
13551 (save-buffer)
13552 (setq buffer-file-name nil))
13553 (remember-finalize))
13555 ;;;###autoload
13556 (defun org-remember (&optional goto org-force-remember-template-char)
13557 "Call `remember'. If this is already a remember buffer, re-apply template.
13558 If there is an active region, make sure remember uses it as initial content
13559 of the remember buffer.
13561 When called interactively with a `C-u' prefix argument GOTO, don't remember
13562 anything, just go to the file/headline where the selected template usually
13563 stores its notes. With a double prefix arg `C-u C-u', go to the last
13564 note stored by remember.
13566 Lisp programs can set ORG-FORCE-REMEMBER-TEMPLATE-CHAR to a character
13567 associated with a template in `org-remember-templates'."
13568 (interactive "P")
13569 (cond
13570 ((equal goto '(4)) (org-go-to-remember-target))
13571 ((equal goto '(16)) (org-remember-goto-last-stored))
13573 ;; set temporary variables that will be needed in
13574 ;; `org-select-remember-template'
13575 (setq org-select-template-temp-major-mode major-mode)
13576 (setq org-select-template-original-buffer (current-buffer))
13577 (if (memq org-finish-function '(remember-buffer remember-finalize))
13578 (progn
13579 (when (< (length org-remember-templates) 2)
13580 (error "No other template available"))
13581 (erase-buffer)
13582 (let ((annotation (plist-get org-store-link-plist :annotation))
13583 (initial (plist-get org-store-link-plist :initial)))
13584 (org-remember-apply-template))
13585 (message "Press C-c C-c to remember data"))
13586 (if (org-region-active-p)
13587 (remember (buffer-substring (point) (mark)))
13588 (call-interactively 'remember))))))
13590 (defun org-remember-goto-last-stored ()
13591 "Go to the location where the last remember note was stored."
13592 (interactive)
13593 (bookmark-jump "org-remember-last-stored")
13594 (message "This is the last note stored by remember"))
13596 (defun org-go-to-remember-target (&optional template-key)
13597 "Go to the target location of a remember template.
13598 The user is queried for the template."
13599 (interactive)
13600 (let* (org-select-template-temp-major-mode
13601 (entry (org-select-remember-template template-key))
13602 (file (nth 1 entry))
13603 (heading (nth 2 entry))
13604 visiting)
13605 (unless (and file (stringp file) (string-match "\\S-" file))
13606 (setq file org-default-notes-file))
13607 (unless (and heading (stringp heading) (string-match "\\S-" heading))
13608 (setq heading org-remember-default-headline))
13609 (setq visiting (org-find-base-buffer-visiting file))
13610 (if (not visiting) (find-file-noselect file))
13611 (switch-to-buffer (or visiting (get-file-buffer file)))
13612 (widen)
13613 (goto-char (point-min))
13614 (if (re-search-forward
13615 (concat "^\\*+[ \t]+" (regexp-quote heading)
13616 (org-re "\\([ \t]+:[[:alnum:]@_:]*\\)?[ \t]*$"))
13617 nil t)
13618 (goto-char (match-beginning 0))
13619 (error "Target headline not found: %s" heading))))
13621 (defvar org-note-abort nil) ; dynamically scoped
13623 ;;;###autoload
13624 (defun org-remember-handler ()
13625 "Store stuff from remember.el into an org file.
13626 First prompts for an org file. If the user just presses return, the value
13627 of `org-default-notes-file' is used.
13628 Then the command offers the headings tree of the selected file in order to
13629 file the text at a specific location.
13630 You can either immediately press RET to get the note appended to the
13631 file, or you can use vertical cursor motion and visibility cycling (TAB) to
13632 find a better place. Then press RET or <left> or <right> in insert the note.
13634 Key Cursor position Note gets inserted
13635 -----------------------------------------------------------------------------
13636 RET buffer-start as level 1 heading at end of file
13637 RET on headline as sublevel of the heading at cursor
13638 RET no heading at cursor position, level taken from context.
13639 Or use prefix arg to specify level manually.
13640 <left> on headline as same level, before current heading
13641 <right> on headline as same level, after current heading
13643 So the fastest way to store the note is to press RET RET to append it to
13644 the default file. This way your current train of thought is not
13645 interrupted, in accordance with the principles of remember.el.
13646 You can also get the fast execution without prompting by using
13647 C-u C-c C-c to exit the remember buffer. See also the variable
13648 `org-remember-store-without-prompt'.
13650 Before being stored away, the function ensures that the text has a
13651 headline, i.e. a first line that starts with a \"*\". If not, a headline
13652 is constructed from the current date and some additional data.
13654 If the variable `org-adapt-indentation' is non-nil, the entire text is
13655 also indented so that it starts in the same column as the headline
13656 \(i.e. after the stars).
13658 See also the variable `org-reverse-note-order'."
13659 (goto-char (point-min))
13660 (while (looking-at "^[ \t]*\n\\|^##.*\n")
13661 (replace-match ""))
13662 (goto-char (point-max))
13663 (beginning-of-line 1)
13664 (while (looking-at "[ \t]*$\\|##.*")
13665 (delete-region (1- (point)) (point-max))
13666 (beginning-of-line 1))
13667 (catch 'quit
13668 (if org-note-abort (throw 'quit nil))
13669 (let* ((txt (buffer-substring (point-min) (point-max)))
13670 (fastp (org-xor (equal current-prefix-arg '(4))
13671 org-remember-store-without-prompt))
13672 (file (cond
13673 (fastp org-default-notes-file)
13674 ((and (eq org-remember-interactive-interface 'refile)
13675 org-refile-targets)
13676 org-default-notes-file)
13677 ((not (and (equal current-prefix-arg '(16))
13678 org-remember-previous-location))
13679 (org-get-org-file))))
13680 (heading org-remember-default-headline)
13681 (visiting (and file (org-find-base-buffer-visiting file)))
13682 (org-startup-folded nil)
13683 (org-startup-align-all-tables nil)
13684 (org-goto-start-pos 1)
13685 spos exitcmd level indent reversed)
13686 (if (and (equal current-prefix-arg '(16)) org-remember-previous-location)
13687 (setq file (car org-remember-previous-location)
13688 heading (cdr org-remember-previous-location)
13689 fastp t))
13690 (setq current-prefix-arg nil)
13691 (if (string-match "[ \t\n]+\\'" txt)
13692 (setq txt (replace-match "" t t txt)))
13693 ;; Modify text so that it becomes a nice subtree which can be inserted
13694 ;; into an org tree.
13695 (let* ((lines (split-string txt "\n"))
13696 first)
13697 (setq first (car lines) lines (cdr lines))
13698 (if (string-match "^\\*+ " first)
13699 ;; Is already a headline
13700 (setq indent nil)
13701 ;; We need to add a headline: Use time and first buffer line
13702 (setq lines (cons first lines)
13703 first (concat "* " (current-time-string)
13704 " (" (remember-buffer-desc) ")")
13705 indent " "))
13706 (if (and org-adapt-indentation indent)
13707 (setq lines (mapcar
13708 (lambda (x)
13709 (if (string-match "\\S-" x)
13710 (concat indent x) x))
13711 lines)))
13712 (setq txt (concat first "\n"
13713 (mapconcat 'identity lines "\n"))))
13714 (if (string-match "\n[ \t]*\n[ \t\n]*\\'" txt)
13715 (setq txt (replace-match "\n\n" t t txt))
13716 (if (string-match "[ \t\n]*\\'" txt)
13717 (setq txt (replace-match "\n" t t txt))))
13718 ;; Put the modified text back into the remember buffer, for refile.
13719 (erase-buffer)
13720 (insert txt)
13721 (goto-char (point-min))
13722 (when (and (eq org-remember-interactive-interface 'refile)
13723 (not fastp))
13724 (org-refile nil (or visiting (find-file-noselect file)))
13725 (throw 'quit t))
13726 ;; Find the file
13727 (if (not visiting) (find-file-noselect file))
13728 (with-current-buffer (or visiting (get-file-buffer file))
13729 (unless (org-mode-p)
13730 (error "Target files for remember notes must be in Org-mode"))
13731 (save-excursion
13732 (save-restriction
13733 (widen)
13734 (and (goto-char (point-min))
13735 (not (re-search-forward "^\\* " nil t))
13736 (insert "\n* " (or heading "Notes") "\n"))
13737 (setq reversed (org-notes-order-reversed-p))
13739 ;; Find the default location
13740 (when (and heading (stringp heading) (string-match "\\S-" heading))
13741 (goto-char (point-min))
13742 (if (re-search-forward
13743 (concat "^\\*+[ \t]+" (regexp-quote heading)
13744 (org-re "\\([ \t]+:[[:alnum:]@_:]*\\)?[ \t]*$"))
13745 nil t)
13746 (setq org-goto-start-pos (match-beginning 0))
13747 (when fastp
13748 (goto-char (point-max))
13749 (unless (bolp) (newline))
13750 (insert "* " heading "\n")
13751 (setq org-goto-start-pos (point-at-bol 0)))))
13753 ;; Ask the User for a location, using the appropriate interface
13754 (cond
13755 (fastp (setq spos org-goto-start-pos
13756 exitcmd 'return))
13757 ((eq org-remember-interactive-interface 'outline)
13758 (setq spos (org-get-location (current-buffer)
13759 org-remember-help)
13760 exitcmd (cdr spos)
13761 spos (car spos)))
13762 ((eq org-remember-interactive-interface 'outline-path-completion)
13763 (let ((org-refile-targets '((nil . (:maxlevel . 10))))
13764 (org-refile-use-outline-path t))
13765 (setq spos (org-refile-get-location "Heading: ")
13766 exitcmd 'return
13767 spos (nth 3 spos))))
13768 (t (error "this should not hapen")))
13769 (if (not spos) (throw 'quit nil)) ; return nil to show we did
13770 ; not handle this note
13771 (goto-char spos)
13772 (cond ((org-on-heading-p t)
13773 (org-back-to-heading t)
13774 (setq level (funcall outline-level))
13775 (cond
13776 ((eq exitcmd 'return)
13777 ;; sublevel of current
13778 (setq org-remember-previous-location
13779 (cons (abbreviate-file-name file)
13780 (org-get-heading 'notags)))
13781 (if reversed
13782 (outline-next-heading)
13783 (org-end-of-subtree t)
13784 (if (not (bolp))
13785 (if (looking-at "[ \t]*\n")
13786 (beginning-of-line 2)
13787 (end-of-line 1)
13788 (insert "\n"))))
13789 (bookmark-set "org-remember-last-stored")
13790 (org-paste-subtree (org-get-valid-level level 1) txt))
13791 ((eq exitcmd 'left)
13792 ;; before current
13793 (bookmark-set "org-remember-last-stored")
13794 (org-paste-subtree level txt))
13795 ((eq exitcmd 'right)
13796 ;; after current
13797 (org-end-of-subtree t)
13798 (bookmark-set "org-remember-last-stored")
13799 (org-paste-subtree level txt))
13800 (t (error "This should not happen"))))
13802 ((and (bobp) (not reversed))
13803 ;; Put it at the end, one level below level 1
13804 (save-restriction
13805 (widen)
13806 (goto-char (point-max))
13807 (if (not (bolp)) (newline))
13808 (bookmark-set "org-remember-last-stored")
13809 (org-paste-subtree (org-get-valid-level 1 1) txt)))
13811 ((and (bobp) reversed)
13812 ;; Put it at the start, as level 1
13813 (save-restriction
13814 (widen)
13815 (goto-char (point-min))
13816 (re-search-forward "^\\*+ " nil t)
13817 (beginning-of-line 1)
13818 (bookmark-set "org-remember-last-stored")
13819 (org-paste-subtree 1 txt)))
13821 ;; Put it right there, with automatic level determined by
13822 ;; org-paste-subtree or from prefix arg
13823 (bookmark-set "org-remember-last-stored")
13824 (org-paste-subtree
13825 (if (numberp current-prefix-arg) current-prefix-arg)
13826 txt)))
13827 (when remember-save-after-remembering
13828 (save-buffer)
13829 (if (not visiting) (kill-buffer (current-buffer)))))))))
13831 t) ;; return t to indicate that we took care of this note.
13833 (defun org-get-org-file ()
13834 "Read a filename, with default directory `org-directory'."
13835 (let ((default (or org-default-notes-file remember-data-file)))
13836 (read-file-name (format "File name [%s]: " default)
13837 (file-name-as-directory org-directory)
13838 default)))
13840 (defun org-notes-order-reversed-p ()
13841 "Check if the current file should receive notes in reversed order."
13842 (cond
13843 ((not org-reverse-note-order) nil)
13844 ((eq t org-reverse-note-order) t)
13845 ((not (listp org-reverse-note-order)) nil)
13846 (t (catch 'exit
13847 (let ((all org-reverse-note-order)
13848 entry)
13849 (while (setq entry (pop all))
13850 (if (string-match (car entry) buffer-file-name)
13851 (throw 'exit (cdr entry))))
13852 nil)))))
13854 ;;; Refiling
13856 (defvar org-refile-target-table nil
13857 "The list of refile targets, created by `org-refile'.")
13859 (defvar org-agenda-new-buffers nil
13860 "Buffers created to visit agenda files.")
13862 (defun org-get-refile-targets (&optional default-buffer)
13863 "Produce a table with refile targets."
13864 (let ((entries (or org-refile-targets '((nil . (:level . 1)))))
13865 targets txt re files f desc descre)
13866 (with-current-buffer (or default-buffer (current-buffer))
13867 (while (setq entry (pop entries))
13868 (setq files (car entry) desc (cdr entry))
13869 (cond
13870 ((null files) (setq files (list (current-buffer))))
13871 ((eq files 'org-agenda-files)
13872 (setq files (org-agenda-files 'unrestricted)))
13873 ((and (symbolp files) (fboundp files))
13874 (setq files (funcall files)))
13875 ((and (symbolp files) (boundp files))
13876 (setq files (symbol-value files))))
13877 (if (stringp files) (setq files (list files)))
13878 (cond
13879 ((eq (car desc) :tag)
13880 (setq descre (concat "^\\*+[ \t]+.*?:" (regexp-quote (cdr desc)) ":")))
13881 ((eq (car desc) :todo)
13882 (setq descre (concat "^\\*+[ \t]+" (regexp-quote (cdr desc)) "[ \t]")))
13883 ((eq (car desc) :regexp)
13884 (setq descre (cdr desc)))
13885 ((eq (car desc) :level)
13886 (setq descre (concat "^\\*\\{" (number-to-string
13887 (if org-odd-levels-only
13888 (1- (* 2 (cdr desc)))
13889 (cdr desc)))
13890 "\\}[ \t]")))
13891 ((eq (car desc) :maxlevel)
13892 (setq descre (concat "^\\*\\{1," (number-to-string
13893 (if org-odd-levels-only
13894 (1- (* 2 (cdr desc)))
13895 (cdr desc)))
13896 "\\}[ \t]")))
13897 (t (error "Bad refiling target description %s" desc)))
13898 (while (setq f (pop files))
13899 (save-excursion
13900 (set-buffer (if (bufferp f) f (org-get-agenda-file-buffer f)))
13901 (if (bufferp f) (setq f (buffer-file-name (buffer-base-buffer f))))
13902 (save-excursion
13903 (save-restriction
13904 (widen)
13905 (goto-char (point-min))
13906 (while (re-search-forward descre nil t)
13907 (goto-char (point-at-bol))
13908 (when (looking-at org-complex-heading-regexp)
13909 (setq txt (match-string 4)
13910 re (concat "^" (regexp-quote
13911 (buffer-substring (match-beginning 1)
13912 (match-end 4)))))
13913 (if (match-end 5) (setq re (concat re "[ \t]+"
13914 (regexp-quote
13915 (match-string 5)))))
13916 (setq re (concat re "[ \t]*$"))
13917 (when org-refile-use-outline-path
13918 (setq txt (mapconcat 'identity
13919 (append
13920 (if (eq org-refile-use-outline-path 'file)
13921 (list (file-name-nondirectory
13922 (buffer-file-name (buffer-base-buffer))))
13923 (if (eq org-refile-use-outline-path 'full-file-path)
13924 (list (buffer-file-name (buffer-base-buffer)))))
13925 (org-get-outline-path)
13926 (list txt))
13927 "/")))
13928 (push (list txt f re (point)) targets))
13929 (goto-char (point-at-eol))))))))
13930 (nreverse targets))))
13932 (defun org-get-outline-path ()
13933 "Return the outline path to the current entry, as a list."
13934 (let (rtn)
13935 (save-excursion
13936 (while (org-up-heading-safe)
13937 (when (looking-at org-complex-heading-regexp)
13938 (push (org-match-string-no-properties 4) rtn)))
13939 rtn)))
13941 (defvar org-refile-history nil
13942 "History for refiling operations.")
13944 (defun org-refile (&optional goto default-buffer)
13945 "Move the entry at point to another heading.
13946 The list of target headings is compiled using the information in
13947 `org-refile-targets', which see. This list is created upon first use, and
13948 you can update it by calling this command with a double prefix (`C-u C-u').
13949 FIXME: Can we find a better way of updating?
13951 At the target location, the entry is filed as a subitem of the target heading.
13952 Depending on `org-reverse-note-order', the new subitem will either be the
13953 first of the last subitem.
13955 With prefix arg GOTO, the command will only visit the target location,
13956 not actually move anything.
13957 With a double prefix `C-c C-c', go to the location where the last refiling
13958 operation has put the subtree.
13960 With a double prefix argument, the command can be used to jump to any
13961 heading in the current buffer."
13962 (interactive "P")
13963 (let* ((cbuf (current-buffer))
13964 (filename (buffer-file-name (buffer-base-buffer cbuf)))
13965 pos it nbuf file re level reversed)
13966 (if (equal goto '(16))
13967 (org-refile-goto-last-stored)
13968 (when (setq it (org-refile-get-location
13969 (if goto "Goto: " "Refile to: ") default-buffer))
13970 (setq file (nth 1 it)
13971 re (nth 2 it)
13972 pos (nth 3 it))
13973 (setq nbuf (or (find-buffer-visiting file)
13974 (find-file-noselect file)))
13975 (if goto
13976 (progn
13977 (switch-to-buffer nbuf)
13978 (goto-char pos)
13979 (org-show-context 'org-goto))
13980 (org-copy-special)
13981 (save-excursion
13982 (set-buffer (setq nbuf (or (find-buffer-visiting file)
13983 (find-file-noselect file))))
13984 (setq reversed (org-notes-order-reversed-p))
13985 (save-excursion
13986 (save-restriction
13987 (widen)
13988 (goto-char pos)
13989 (looking-at outline-regexp)
13990 (setq level (org-get-valid-level (funcall outline-level) 1))
13991 (goto-char
13992 (if reversed
13993 (outline-next-heading)
13994 (or (save-excursion (outline-get-next-sibling))
13995 (org-end-of-subtree t t)
13996 (point-max))))
13997 (bookmark-set "org-refile-last-stored")
13998 (org-paste-subtree level))))
13999 (org-cut-special)
14000 (message "Entry refiled to \"%s\"" (car it)))))))
14002 (defun org-refile-goto-last-stored ()
14003 "Go to the location where the last refile was stored."
14004 (interactive)
14005 (bookmark-jump "org-refile-last-stored")
14006 (message "This is the location of the last refile"))
14008 (defun org-refile-get-location (&optional prompt default-buffer)
14009 "Prompt the user for a refile location, using PROMPT."
14010 (let ((org-refile-targets org-refile-targets)
14011 (org-refile-use-outline-path org-refile-use-outline-path))
14012 (setq org-refile-target-table (org-get-refile-targets default-buffer)))
14013 (unless org-refile-target-table
14014 (error "No refile targets"))
14015 (let* ((cbuf (current-buffer))
14016 (filename (buffer-file-name (buffer-base-buffer cbuf)))
14017 (fname (and filename (file-truename filename)))
14018 (tbl (mapcar
14019 (lambda (x)
14020 (if (not (equal fname (file-truename (nth 1 x))))
14021 (cons (concat (car x) " (" (file-name-nondirectory
14022 (nth 1 x)) ")")
14023 (cdr x))
14025 org-refile-target-table))
14026 (completion-ignore-case t))
14027 (assoc (completing-read prompt tbl nil t nil 'org-refile-history)
14028 tbl)))
14030 ;;;; Dynamic blocks
14032 (defun org-find-dblock (name)
14033 "Find the first dynamic block with name NAME in the buffer.
14034 If not found, stay at current position and return nil."
14035 (let (pos)
14036 (save-excursion
14037 (goto-char (point-min))
14038 (setq pos (and (re-search-forward (concat "^#\\+BEGIN:[ \t]+" name "\\>")
14039 nil t)
14040 (match-beginning 0))))
14041 (if pos (goto-char pos))
14042 pos))
14044 (defconst org-dblock-start-re
14045 "^#\\+BEGIN:[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?"
14046 "Matches the startline of a dynamic block, with parameters.")
14048 (defconst org-dblock-end-re "^#\\+END\\([: \t\r\n]\\|$\\)"
14049 "Matches the end of a dyhamic block.")
14051 (defun org-create-dblock (plist)
14052 "Create a dynamic block section, with parameters taken from PLIST.
14053 PLIST must containe a :name entry which is used as name of the block."
14054 (unless (bolp) (newline))
14055 (let ((name (plist-get plist :name)))
14056 (insert "#+BEGIN: " name)
14057 (while plist
14058 (if (eq (car plist) :name)
14059 (setq plist (cddr plist))
14060 (insert " " (prin1-to-string (pop plist)))))
14061 (insert "\n\n#+END:\n")
14062 (beginning-of-line -2)))
14064 (defun org-prepare-dblock ()
14065 "Prepare dynamic block for refresh.
14066 This empties the block, puts the cursor at the insert position and returns
14067 the property list including an extra property :name with the block name."
14068 (unless (looking-at org-dblock-start-re)
14069 (error "Not at a dynamic block"))
14070 (let* ((begdel (1+ (match-end 0)))
14071 (name (org-no-properties (match-string 1)))
14072 (params (append (list :name name)
14073 (read (concat "(" (match-string 3) ")")))))
14074 (unless (re-search-forward org-dblock-end-re nil t)
14075 (error "Dynamic block not terminated"))
14076 (setq params
14077 (append params
14078 (list :content (buffer-substring
14079 begdel (match-beginning 0)))))
14080 (delete-region begdel (match-beginning 0))
14081 (goto-char begdel)
14082 (open-line 1)
14083 params))
14085 (defun org-map-dblocks (&optional command)
14086 "Apply COMMAND to all dynamic blocks in the current buffer.
14087 If COMMAND is not given, use `org-update-dblock'."
14088 (let ((cmd (or command 'org-update-dblock))
14089 pos)
14090 (save-excursion
14091 (goto-char (point-min))
14092 (while (re-search-forward org-dblock-start-re nil t)
14093 (goto-char (setq pos (match-beginning 0)))
14094 (condition-case nil
14095 (funcall cmd)
14096 (error (message "Error during update of dynamic block")))
14097 (goto-char pos)
14098 (unless (re-search-forward org-dblock-end-re nil t)
14099 (error "Dynamic block not terminated"))))))
14101 (defun org-dblock-update (&optional arg)
14102 "User command for updating dynamic blocks.
14103 Update the dynamic block at point. With prefix ARG, update all dynamic
14104 blocks in the buffer."
14105 (interactive "P")
14106 (if arg
14107 (org-update-all-dblocks)
14108 (or (looking-at org-dblock-start-re)
14109 (org-beginning-of-dblock))
14110 (org-update-dblock)))
14112 (defun org-update-dblock ()
14113 "Update the dynamic block at point
14114 This means to empty the block, parse for parameters and then call
14115 the correct writing function."
14116 (save-window-excursion
14117 (let* ((pos (point))
14118 (line (org-current-line))
14119 (params (org-prepare-dblock))
14120 (name (plist-get params :name))
14121 (cmd (intern (concat "org-dblock-write:" name))))
14122 (message "Updating dynamic block `%s' at line %d..." name line)
14123 (funcall cmd params)
14124 (message "Updating dynamic block `%s' at line %d...done" name line)
14125 (goto-char pos))))
14127 (defun org-beginning-of-dblock ()
14128 "Find the beginning of the dynamic block at point.
14129 Error if there is no scuh block at point."
14130 (let ((pos (point))
14131 beg)
14132 (end-of-line 1)
14133 (if (and (re-search-backward org-dblock-start-re nil t)
14134 (setq beg (match-beginning 0))
14135 (re-search-forward org-dblock-end-re nil t)
14136 (> (match-end 0) pos))
14137 (goto-char beg)
14138 (goto-char pos)
14139 (error "Not in a dynamic block"))))
14141 (defun org-update-all-dblocks ()
14142 "Update all dynamic blocks in the buffer.
14143 This function can be used in a hook."
14144 (when (org-mode-p)
14145 (org-map-dblocks 'org-update-dblock)))
14148 ;;;; Completion
14150 (defconst org-additional-option-like-keywords
14151 '("BEGIN_HTML" "BEGIN_LaTeX" "END_HTML" "END_LaTeX"
14152 "ORGTBL" "HTML:" "LaTeX:" "BEGIN:" "END:" "TBLFM"
14153 "BEGIN_EXAMPLE" "END_EXAMPLE"))
14155 (defun org-complete (&optional arg)
14156 "Perform completion on word at point.
14157 At the beginning of a headline, this completes TODO keywords as given in
14158 `org-todo-keywords'.
14159 If the current word is preceded by a backslash, completes the TeX symbols
14160 that are supported for HTML support.
14161 If the current word is preceded by \"#+\", completes special words for
14162 setting file options.
14163 In the line after \"#+STARTUP:, complete valid keywords.\"
14164 At all other locations, this simply calls the value of
14165 `org-completion-fallback-command'."
14166 (interactive "P")
14167 (org-without-partial-completion
14168 (catch 'exit
14169 (let* ((end (point))
14170 (beg1 (save-excursion
14171 (skip-chars-backward (org-re "[:alnum:]_@"))
14172 (point)))
14173 (beg (save-excursion
14174 (skip-chars-backward "a-zA-Z0-9_:$")
14175 (point)))
14176 (confirm (lambda (x) (stringp (car x))))
14177 (searchhead (equal (char-before beg) ?*))
14178 (tag (and (equal (char-before beg1) ?:)
14179 (equal (char-after (point-at-bol)) ?*)))
14180 (prop (and (equal (char-before beg1) ?:)
14181 (not (equal (char-after (point-at-bol)) ?*))))
14182 (texp (equal (char-before beg) ?\\))
14183 (link (equal (char-before beg) ?\[))
14184 (opt (equal (buffer-substring (max (point-at-bol) (- beg 2))
14185 beg)
14186 "#+"))
14187 (startup (string-match "^#\\+STARTUP:.*"
14188 (buffer-substring (point-at-bol) (point))))
14189 (completion-ignore-case opt)
14190 (type nil)
14191 (tbl nil)
14192 (table (cond
14193 (opt
14194 (setq type :opt)
14195 (append
14196 (mapcar
14197 (lambda (x)
14198 (string-match "^#\\+\\(\\([A-Z_]+:?\\).*\\)" x)
14199 (cons (match-string 2 x) (match-string 1 x)))
14200 (org-split-string (org-get-current-options) "\n"))
14201 (mapcar 'list org-additional-option-like-keywords)))
14202 (startup
14203 (setq type :startup)
14204 org-startup-options)
14205 (link (append org-link-abbrev-alist-local
14206 org-link-abbrev-alist))
14207 (texp
14208 (setq type :tex)
14209 org-html-entities)
14210 ((string-match "\\`\\*+[ \t]+\\'"
14211 (buffer-substring (point-at-bol) beg))
14212 (setq type :todo)
14213 (mapcar 'list org-todo-keywords-1))
14214 (searchhead
14215 (setq type :searchhead)
14216 (save-excursion
14217 (goto-char (point-min))
14218 (while (re-search-forward org-todo-line-regexp nil t)
14219 (push (list
14220 (org-make-org-heading-search-string
14221 (match-string 3) t))
14222 tbl)))
14223 tbl)
14224 (tag (setq type :tag beg beg1)
14225 (or org-tag-alist (org-get-buffer-tags)))
14226 (prop (setq type :prop beg beg1)
14227 (mapcar 'list (org-buffer-property-keys nil t t)))
14228 (t (progn
14229 (call-interactively org-completion-fallback-command)
14230 (throw 'exit nil)))))
14231 (pattern (buffer-substring-no-properties beg end))
14232 (completion (try-completion pattern table confirm)))
14233 (cond ((eq completion t)
14234 (if (not (assoc (upcase pattern) table))
14235 (message "Already complete")
14236 (if (and (equal type :opt)
14237 (not (member (car (assoc (upcase pattern) table))
14238 org-additional-option-like-keywords)))
14239 (insert (substring (cdr (assoc (upcase pattern) table))
14240 (length pattern)))
14241 (if (memq type '(:tag :prop)) (insert ":")))))
14242 ((null completion)
14243 (message "Can't find completion for \"%s\"" pattern)
14244 (ding))
14245 ((not (string= pattern completion))
14246 (delete-region beg end)
14247 (if (string-match " +$" completion)
14248 (setq completion (replace-match "" t t completion)))
14249 (insert completion)
14250 (if (get-buffer-window "*Completions*")
14251 (delete-window (get-buffer-window "*Completions*")))
14252 (if (assoc completion table)
14253 (if (eq type :todo) (insert " ")
14254 (if (memq type '(:tag :prop)) (insert ":"))))
14255 (if (and (equal type :opt) (assoc completion table))
14256 (message "%s" (substitute-command-keys
14257 "Press \\[org-complete] again to insert example settings"))))
14259 (message "Making completion list...")
14260 (let ((list (sort (all-completions pattern table confirm)
14261 'string<)))
14262 (with-output-to-temp-buffer "*Completions*"
14263 (condition-case nil
14264 ;; Protection needed for XEmacs and emacs 21
14265 (display-completion-list list pattern)
14266 (error (display-completion-list list)))))
14267 (message "Making completion list...%s" "done")))))))
14269 ;;;; TODO, DEADLINE, Comments
14271 (defun org-toggle-comment ()
14272 "Change the COMMENT state of an entry."
14273 (interactive)
14274 (save-excursion
14275 (org-back-to-heading)
14276 (let (case-fold-search)
14277 (if (looking-at (concat outline-regexp
14278 "\\( *\\<" org-comment-string "\\>[ \t]*\\)"))
14279 (replace-match "" t t nil 1)
14280 (if (looking-at outline-regexp)
14281 (progn
14282 (goto-char (match-end 0))
14283 (insert org-comment-string " ")))))))
14285 (defvar org-last-todo-state-is-todo nil
14286 "This is non-nil when the last TODO state change led to a TODO state.
14287 If the last change removed the TODO tag or switched to DONE, then
14288 this is nil.")
14290 (defvar org-setting-tags nil) ; dynamically skiped
14292 ;; FIXME: better place
14293 (defun org-property-or-variable-value (var &optional inherit)
14294 "Check if there is a property fixing the value of VAR.
14295 If yes, return this value. If not, return the current value of the variable."
14296 (let ((prop (org-entry-get nil (symbol-name var) inherit)))
14297 (if (and prop (stringp prop) (string-match "\\S-" prop))
14298 (read prop)
14299 (symbol-value var))))
14301 (defun org-parse-local-options (string var)
14302 "Parse STRING for startup setting relevant for variable VAR."
14303 (let ((rtn (symbol-value var))
14304 e opts)
14305 (save-match-data
14306 (if (or (not string) (not (string-match "\\S-" string)))
14308 (setq opts (delq nil (mapcar (lambda (x)
14309 (setq e (assoc x org-startup-options))
14310 (if (eq (nth 1 e) var) e nil))
14311 (org-split-string string "[ \t]+"))))
14312 (if (not opts)
14314 (setq rtn nil)
14315 (while (setq e (pop opts))
14316 (if (not (nth 3 e))
14317 (setq rtn (nth 2 e))
14318 (if (not (listp rtn)) (setq rtn nil))
14319 (push (nth 2 e) rtn)))
14320 rtn)))))
14322 (defvar org-blocker-hook nil
14323 "Hook for functions that are allowed to block a state change.
14325 Each function gets as its single argument a property list, see
14326 `org-trigger-hook' for more information about this list.
14328 If any of the functions in this hook returns nil, the state change
14329 is blocked.")
14331 (defvar org-trigger-hook nil
14332 "Hook for functions that are triggered by a state change.
14334 Each function gets as its single argument a property list with at least
14335 the following elements:
14337 (:type type-of-change :position pos-at-entry-start
14338 :from old-state :to new-state)
14340 Depending on the type, more properties may be present.
14342 This mechanism is currently implemented for:
14344 TODO state changes
14345 ------------------
14346 :type todo-state-change
14347 :from previous state (keyword as a string), or nil
14348 :to new state (keyword as a string), or nil")
14351 (defun org-todo (&optional arg)
14352 "Change the TODO state of an item.
14353 The state of an item is given by a keyword at the start of the heading,
14354 like
14355 *** TODO Write paper
14356 *** DONE Call mom
14358 The different keywords are specified in the variable `org-todo-keywords'.
14359 By default the available states are \"TODO\" and \"DONE\".
14360 So for this example: when the item starts with TODO, it is changed to DONE.
14361 When it starts with DONE, the DONE is removed. And when neither TODO nor
14362 DONE are present, add TODO at the beginning of the heading.
14364 With C-u prefix arg, use completion to determine the new state.
14365 With numeric prefix arg, switch to that state.
14367 For calling through lisp, arg is also interpreted in the following way:
14368 'none -> empty state
14369 \"\"(empty string) -> switch to empty state
14370 'done -> switch to DONE
14371 'nextset -> switch to the next set of keywords
14372 'previousset -> switch to the previous set of keywords
14373 \"WAITING\" -> switch to the specified keyword, but only if it
14374 really is a member of `org-todo-keywords'."
14375 (interactive "P")
14376 (save-excursion
14377 (catch 'exit
14378 (org-back-to-heading)
14379 (if (looking-at outline-regexp) (goto-char (1- (match-end 0))))
14380 (or (looking-at (concat " +" org-todo-regexp " *"))
14381 (looking-at " *"))
14382 (let* ((match-data (match-data))
14383 (startpos (point-at-bol))
14384 (logging (save-match-data (org-entry-get nil "LOGGING" t)))
14385 (org-log-done org-log-done)
14386 (org-log-repeat org-log-repeat)
14387 (org-todo-log-states org-todo-log-states)
14388 (this (match-string 1))
14389 (hl-pos (match-beginning 0))
14390 (head (org-get-todo-sequence-head this))
14391 (ass (assoc head org-todo-kwd-alist))
14392 (interpret (nth 1 ass))
14393 (done-word (nth 3 ass))
14394 (final-done-word (nth 4 ass))
14395 (last-state (or this ""))
14396 (completion-ignore-case t)
14397 (member (member this org-todo-keywords-1))
14398 (tail (cdr member))
14399 (state (cond
14400 ((and org-todo-key-trigger
14401 (or (and (equal arg '(4)) (eq org-use-fast-todo-selection 'prefix))
14402 (and (not arg) org-use-fast-todo-selection
14403 (not (eq org-use-fast-todo-selection 'prefix)))))
14404 ;; Use fast selection
14405 (org-fast-todo-selection))
14406 ((and (equal arg '(4))
14407 (or (not org-use-fast-todo-selection)
14408 (not org-todo-key-trigger)))
14409 ;; Read a state with completion
14410 (completing-read "State: " (mapcar (lambda(x) (list x))
14411 org-todo-keywords-1)
14412 nil t))
14413 ((eq arg 'right)
14414 (if this
14415 (if tail (car tail) nil)
14416 (car org-todo-keywords-1)))
14417 ((eq arg 'left)
14418 (if (equal member org-todo-keywords-1)
14420 (if this
14421 (nth (- (length org-todo-keywords-1) (length tail) 2)
14422 org-todo-keywords-1)
14423 (org-last org-todo-keywords-1))))
14424 ((and (eq org-use-fast-todo-selection t) (equal arg '(4))
14425 (setq arg nil))) ; hack to fall back to cycling
14426 (arg
14427 ;; user or caller requests a specific state
14428 (cond
14429 ((equal arg "") nil)
14430 ((eq arg 'none) nil)
14431 ((eq arg 'done) (or done-word (car org-done-keywords)))
14432 ((eq arg 'nextset)
14433 (or (car (cdr (member head org-todo-heads)))
14434 (car org-todo-heads)))
14435 ((eq arg 'previousset)
14436 (let ((org-todo-heads (reverse org-todo-heads)))
14437 (or (car (cdr (member head org-todo-heads)))
14438 (car org-todo-heads))))
14439 ((car (member arg org-todo-keywords-1)))
14440 ((nth (1- (prefix-numeric-value arg))
14441 org-todo-keywords-1))))
14442 ((null member) (or head (car org-todo-keywords-1)))
14443 ((equal this final-done-word) nil) ;; -> make empty
14444 ((null tail) nil) ;; -> first entry
14445 ((eq interpret 'sequence)
14446 (car tail))
14447 ((memq interpret '(type priority))
14448 (if (eq this-command last-command)
14449 (car tail)
14450 (if (> (length tail) 0)
14451 (or done-word (car org-done-keywords))
14452 nil)))
14453 (t nil)))
14454 (next (if state (concat " " state " ") " "))
14455 (change-plist (list :type 'todo-state-change :from this :to state
14456 :position startpos))
14457 dolog now-done-p)
14458 (when org-blocker-hook
14459 (unless (save-excursion
14460 (save-match-data
14461 (run-hook-with-args-until-failure
14462 'org-blocker-hook change-plist)))
14463 (if (interactive-p)
14464 (error "TODO state change from %s to %s blocked" this state)
14465 ;; fail silently
14466 (message "TODO state change from %s to %s blocked" this state)
14467 (throw 'exit nil))))
14468 (store-match-data match-data)
14469 (replace-match next t t)
14470 (unless (pos-visible-in-window-p hl-pos)
14471 (message "TODO state changed to %s" (org-trim next)))
14472 (unless head
14473 (setq head (org-get-todo-sequence-head state)
14474 ass (assoc head org-todo-kwd-alist)
14475 interpret (nth 1 ass)
14476 done-word (nth 3 ass)
14477 final-done-word (nth 4 ass)))
14478 (when (memq arg '(nextset previousset))
14479 (message "Keyword-Set %d/%d: %s"
14480 (- (length org-todo-sets) -1
14481 (length (memq (assoc state org-todo-sets) org-todo-sets)))
14482 (length org-todo-sets)
14483 (mapconcat 'identity (assoc state org-todo-sets) " ")))
14484 (setq org-last-todo-state-is-todo
14485 (not (member state org-done-keywords)))
14486 (setq now-done-p (and (member state org-done-keywords)
14487 (not (member this org-done-keywords))))
14488 (and logging (org-local-logging logging))
14489 (when (and (or org-todo-log-states org-log-done)
14490 (not (memq arg '(nextset previousset))))
14491 ;; we need to look at recording a time and note
14492 (setq dolog (or (nth 1 (assoc state org-todo-log-states))
14493 (nth 2 (assoc this org-todo-log-states))))
14494 (when (and state
14495 (member state org-not-done-keywords)
14496 (not (member this org-not-done-keywords)))
14497 ;; This is now a todo state and was not one before
14498 ;; If there was a CLOSED time stamp, get rid of it.
14499 (org-add-planning-info nil nil 'closed))
14500 (when (and now-done-p org-log-done)
14501 ;; It is now done, and it was not done before
14502 (org-add-planning-info 'closed (org-current-time))
14503 (if (and (not dolog) (eq 'note org-log-done))
14504 (org-add-log-maybe 'done state 'findpos 'note)))
14505 (when (and state dolog)
14506 ;; This is a non-nil state, and we need to log it
14507 (org-add-log-maybe 'state state 'findpos dolog)))
14508 ;; Fixup tag positioning
14509 (and org-auto-align-tags (not org-setting-tags) (org-set-tags nil t))
14510 (run-hooks 'org-after-todo-state-change-hook)
14511 (if (and arg (not (member state org-done-keywords)))
14512 (setq head (org-get-todo-sequence-head state)))
14513 (put-text-property (point-at-bol) (point-at-eol) 'org-todo-head head)
14514 ;; Do we need to trigger a repeat?
14515 (when now-done-p (org-auto-repeat-maybe state))
14516 ;; Fixup cursor location if close to the keyword
14517 (if (and (outline-on-heading-p)
14518 (not (bolp))
14519 (save-excursion (beginning-of-line 1)
14520 (looking-at org-todo-line-regexp))
14521 (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
14522 (progn
14523 (goto-char (or (match-end 2) (match-end 1)))
14524 (just-one-space)))
14525 (when org-trigger-hook
14526 (save-excursion
14527 (run-hook-with-args 'org-trigger-hook change-plist)))))))
14529 (defun org-local-logging (value)
14530 "Get logging settings from a property VALUE."
14531 (let* (words w a)
14532 ;; directly set the variables, they are already local.
14533 (setq org-log-done nil
14534 org-log-repeat nil
14535 org-todo-log-states nil)
14536 (setq words (org-split-string value))
14537 (while (setq w (pop words))
14538 (cond
14539 ((setq a (assoc w org-startup-options))
14540 (and (member (nth 1 a) '(org-log-done org-log-repeat))
14541 (set (nth 1 a) (nth 2 a))))
14542 ((setq a (org-extract-log-state-settings w))
14543 (and (member (car a) org-todo-keywords-1)
14544 (push a org-todo-log-states)))))))
14546 (defun org-get-todo-sequence-head (kwd)
14547 "Return the head of the TODO sequence to which KWD belongs.
14548 If KWD is not set, check if there is a text property remembering the
14549 right sequence."
14550 (let (p)
14551 (cond
14552 ((not kwd)
14553 (or (get-text-property (point-at-bol) 'org-todo-head)
14554 (progn
14555 (setq p (next-single-property-change (point-at-bol) 'org-todo-head
14556 nil (point-at-eol)))
14557 (get-text-property p 'org-todo-head))))
14558 ((not (member kwd org-todo-keywords-1))
14559 (car org-todo-keywords-1))
14560 (t (nth 2 (assoc kwd org-todo-kwd-alist))))))
14562 (defun org-fast-todo-selection ()
14563 "Fast TODO keyword selection with single keys.
14564 Returns the new TODO keyword, or nil if no state change should occur."
14565 (let* ((fulltable org-todo-key-alist)
14566 (done-keywords org-done-keywords) ;; needed for the faces.
14567 (maxlen (apply 'max (mapcar
14568 (lambda (x)
14569 (if (stringp (car x)) (string-width (car x)) 0))
14570 fulltable)))
14571 (expert nil)
14572 (fwidth (+ maxlen 3 1 3))
14573 (ncol (/ (- (window-width) 4) fwidth))
14574 tg cnt e c tbl
14575 groups ingroup)
14576 (save-window-excursion
14577 (if expert
14578 (set-buffer (get-buffer-create " *Org todo*"))
14579 (org-switch-to-buffer-other-window (get-buffer-create " *Org todo*")))
14580 (erase-buffer)
14581 (org-set-local 'org-done-keywords done-keywords)
14582 (setq tbl fulltable cnt 0)
14583 (while (setq e (pop tbl))
14584 (cond
14585 ((equal e '(:startgroup))
14586 (push '() groups) (setq ingroup t)
14587 (when (not (= cnt 0))
14588 (setq cnt 0)
14589 (insert "\n"))
14590 (insert "{ "))
14591 ((equal e '(:endgroup))
14592 (setq ingroup nil cnt 0)
14593 (insert "}\n"))
14595 (setq tg (car e) c (cdr e))
14596 (if ingroup (push tg (car groups)))
14597 (setq tg (org-add-props tg nil 'face
14598 (org-get-todo-face tg)))
14599 (if (and (= cnt 0) (not ingroup)) (insert " "))
14600 (insert "[" c "] " tg (make-string
14601 (- fwidth 4 (length tg)) ?\ ))
14602 (when (= (setq cnt (1+ cnt)) ncol)
14603 (insert "\n")
14604 (if ingroup (insert " "))
14605 (setq cnt 0)))))
14606 (insert "\n")
14607 (goto-char (point-min))
14608 (if (and (not expert) (fboundp 'fit-window-to-buffer))
14609 (fit-window-to-buffer))
14610 (message "[a-z..]:Set [SPC]:clear")
14611 (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
14612 (cond
14613 ((or (= c ?\C-g)
14614 (and (= c ?q) (not (rassoc c fulltable))))
14615 (setq quit-flag t))
14616 ((= c ?\ ) nil)
14617 ((setq e (rassoc c fulltable) tg (car e))
14619 (t (setq quit-flag t))))))
14621 (defun org-get-repeat ()
14622 "Check if tere is a deadline/schedule with repeater in this entry."
14623 (save-match-data
14624 (save-excursion
14625 (org-back-to-heading t)
14626 (if (re-search-forward
14627 org-repeat-re (save-excursion (outline-next-heading) (point)) t)
14628 (match-string 1)))))
14630 (defvar org-last-changed-timestamp)
14631 (defvar org-log-post-message)
14632 (defvar org-log-note-purpose)
14633 (defun org-auto-repeat-maybe (done-word)
14634 "Check if the current headline contains a repeated deadline/schedule.
14635 If yes, set TODO state back to what it was and change the base date
14636 of repeating deadline/scheduled time stamps to new date.
14637 This function is run automatically after each state change to a DONE state."
14638 ;; last-state is dynamically scoped into this function
14639 (let* ((repeat (org-get-repeat))
14640 (aa (assoc last-state org-todo-kwd-alist))
14641 (interpret (nth 1 aa))
14642 (head (nth 2 aa))
14643 (whata '(("d" . day) ("m" . month) ("y" . year)))
14644 (msg "Entry repeats: ")
14645 (org-log-done nil)
14646 (org-todo-log-states nil)
14647 (nshiftmax 10) (nshift 0)
14648 re type n what ts mb0 time)
14649 (when repeat
14650 (if (eq org-log-repeat t) (setq org-log-repeat 'state))
14651 (org-todo (if (eq interpret 'type) last-state head))
14652 (when (and org-log-repeat
14653 (or (not (memq 'org-add-log-note
14654 (default-value 'post-command-hook)))
14655 (eq org-log-note-purpose 'done)))
14656 ;; Make sure a note is taken;
14657 (org-add-log-maybe 'state (or done-word (car org-done-keywords))
14658 'findpos org-log-repeat))
14659 (org-back-to-heading t)
14660 (org-add-planning-info nil nil 'closed)
14661 (setq re (concat "\\(" org-scheduled-time-regexp "\\)\\|\\("
14662 org-deadline-time-regexp "\\)\\|\\("
14663 org-ts-regexp "\\)"))
14664 (while (re-search-forward
14665 re (save-excursion (outline-next-heading) (point)) t)
14666 (setq type (if (match-end 1) org-scheduled-string
14667 (if (match-end 3) org-deadline-string "Plain:"))
14668 ts (match-string (if (match-end 2) 2 (if (match-end 4) 4 0)))
14669 mb0 (match-beginning 0))
14670 (when (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([dwmy]\\)" ts)
14671 (setq n (string-to-number (match-string 2 ts))
14672 what (match-string 3 ts))
14673 (if (equal what "w") (setq n (* n 7) what "d"))
14674 ;; Preparation, see if we need to modify the start date for the change
14675 (when (match-end 1)
14676 (setq time (save-match-data (org-time-string-to-time ts)))
14677 (cond
14678 ((equal (match-string 1 ts) ".")
14679 ;; Shift starting date to today
14680 (org-timestamp-change
14681 (- (time-to-days (current-time)) (time-to-days time))
14682 'day))
14683 ((equal (match-string 1 ts) "+")
14684 (while (< (time-to-days time) (time-to-days (current-time)))
14685 (when (= (incf nshift) nshiftmax)
14686 (or (y-or-n-p (message "%d repeater intervals were not enough to shift date past today. Continue? " nshift))
14687 (error "Abort")))
14688 (org-timestamp-change n (cdr (assoc what whata)))
14689 (sit-for .0001) ;; so we can watch the date shifting
14690 (org-at-timestamp-p t)
14691 (setq ts (match-string 1))
14692 (setq time (save-match-data (org-time-string-to-time ts))))
14693 (org-timestamp-change (- n) (cdr (assoc what whata)))
14694 ;; rematch, so that we have everything in place for the real shift
14695 (org-at-timestamp-p t)
14696 (setq ts (match-string 1))
14697 (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([dwmy]\\)" ts))))
14698 (org-timestamp-change n (cdr (assoc what whata)))
14699 (setq msg (concat msg type org-last-changed-timestamp " "))))
14700 (setq org-log-post-message msg)
14701 (message "%s" msg))))
14703 (defun org-show-todo-tree (arg)
14704 "Make a compact tree which shows all headlines marked with TODO.
14705 The tree will show the lines where the regexp matches, and all higher
14706 headlines above the match.
14707 With a \\[universal-argument] prefix, also show the DONE entries.
14708 With a numeric prefix N, construct a sparse tree for the Nth element
14709 of `org-todo-keywords-1'."
14710 (interactive "P")
14711 (let ((case-fold-search nil)
14712 (kwd-re
14713 (cond ((null arg) org-not-done-regexp)
14714 ((equal arg '(4))
14715 (let ((kwd (completing-read "Keyword (or KWD1|KWD2|...): "
14716 (mapcar 'list org-todo-keywords-1))))
14717 (concat "\\("
14718 (mapconcat 'identity (org-split-string kwd "|") "\\|")
14719 "\\)\\>")))
14720 ((<= (prefix-numeric-value arg) (length org-todo-keywords-1))
14721 (regexp-quote (nth (1- (prefix-numeric-value arg))
14722 org-todo-keywords-1)))
14723 (t (error "Invalid prefix argument: %s" arg)))))
14724 (message "%d TODO entries found"
14725 (org-occur (concat "^" outline-regexp " *" kwd-re )))))
14727 (defun org-deadline (&optional remove)
14728 "Insert the \"DEADLINE:\" string with a timestamp to make a deadline.
14729 With argument REMOVE, remove any deadline from the item."
14730 (interactive "P")
14731 (if remove
14732 (progn
14733 (org-remove-timestamp-with-keyword org-deadline-string)
14734 (message "Item no longer has a deadline."))
14735 (org-add-planning-info 'deadline nil 'closed)))
14737 (defun org-schedule (&optional remove)
14738 "Insert the SCHEDULED: string with a timestamp to schedule a TODO item.
14739 With argument REMOVE, remove any scheduling date from the item."
14740 (interactive "P")
14741 (if remove
14742 (progn
14743 (org-remove-timestamp-with-keyword org-scheduled-string)
14744 (message "Item is no longer scheduled."))
14745 (org-add-planning-info 'scheduled nil 'closed)))
14747 (defun org-remove-timestamp-with-keyword (keyword)
14748 "Remove all time stamps with KEYWORD in the current entry."
14749 (let ((re (concat "\\<" (regexp-quote keyword) " +<[^>\n]+>[ \t]*"))
14750 beg)
14751 (save-excursion
14752 (org-back-to-heading t)
14753 (setq beg (point))
14754 (org-end-of-subtree t t)
14755 (while (re-search-backward re beg t)
14756 (replace-match "")
14757 (unless (string-match "\\S-" (buffer-substring (point-at-bol) (point)))
14758 (delete-region (point-at-bol) (min (1+ (point)) (point-max))))))))
14760 (defun org-add-planning-info (what &optional time &rest remove)
14761 "Insert new timestamp with keyword in the line directly after the headline.
14762 WHAT indicates what kind of time stamp to add. TIME indicated the time to use.
14763 If non is given, the user is prompted for a date.
14764 REMOVE indicates what kind of entries to remove. An old WHAT entry will also
14765 be removed."
14766 (interactive)
14767 (let (org-time-was-given org-end-time-was-given ts
14768 end default-time default-input)
14770 (when (and (not time) (memq what '(scheduled deadline)))
14771 ;; Try to get a default date/time from existing timestamp
14772 (save-excursion
14773 (org-back-to-heading t)
14774 (setq end (save-excursion (outline-next-heading) (point)))
14775 (when (re-search-forward (if (eq what 'scheduled)
14776 org-scheduled-time-regexp
14777 org-deadline-time-regexp)
14778 end t)
14779 (setq ts (match-string 1)
14780 default-time
14781 (apply 'encode-time (org-parse-time-string ts))
14782 default-input (and ts (org-get-compact-tod ts))))))
14783 (when what
14784 ;; If necessary, get the time from the user
14785 (setq time (or time (org-read-date nil 'to-time nil nil
14786 default-time default-input))))
14788 (when (and org-insert-labeled-timestamps-at-point
14789 (member what '(scheduled deadline)))
14790 (insert
14791 (if (eq what 'scheduled) org-scheduled-string org-deadline-string) " ")
14792 (org-insert-time-stamp time org-time-was-given
14793 nil nil nil (list org-end-time-was-given))
14794 (setq what nil))
14795 (save-excursion
14796 (save-restriction
14797 (let (col list elt ts buffer-invisibility-spec)
14798 (org-back-to-heading t)
14799 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"))
14800 (goto-char (match-end 1))
14801 (setq col (current-column))
14802 (goto-char (match-end 0))
14803 (if (eobp) (insert "\n") (forward-char 1))
14804 (if (and (not (looking-at outline-regexp))
14805 (looking-at (concat "[^\r\n]*?" org-keyword-time-regexp
14806 "[^\r\n]*"))
14807 (not (equal (match-string 1) org-clock-string)))
14808 (narrow-to-region (match-beginning 0) (match-end 0))
14809 (insert-before-markers "\n")
14810 (backward-char 1)
14811 (narrow-to-region (point) (point))
14812 (indent-to-column col))
14813 ;; Check if we have to remove something.
14814 (setq list (cons what remove))
14815 (while list
14816 (setq elt (pop list))
14817 (goto-char (point-min))
14818 (when (or (and (eq elt 'scheduled)
14819 (re-search-forward org-scheduled-time-regexp nil t))
14820 (and (eq elt 'deadline)
14821 (re-search-forward org-deadline-time-regexp nil t))
14822 (and (eq elt 'closed)
14823 (re-search-forward org-closed-time-regexp nil t)))
14824 (replace-match "")
14825 (if (looking-at "--+<[^>]+>") (replace-match ""))
14826 (if (looking-at " +") (replace-match ""))))
14827 (goto-char (point-max))
14828 (when what
14829 (insert
14830 (if (not (equal (char-before) ?\ )) " " "")
14831 (cond ((eq what 'scheduled) org-scheduled-string)
14832 ((eq what 'deadline) org-deadline-string)
14833 ((eq what 'closed) org-closed-string))
14834 " ")
14835 (setq ts (org-insert-time-stamp
14836 time
14837 (or org-time-was-given
14838 (and (eq what 'closed) org-log-done-with-time))
14839 (eq what 'closed)
14840 nil nil (list org-end-time-was-given)))
14841 (end-of-line 1))
14842 (goto-char (point-min))
14843 (widen)
14844 (if (looking-at "[ \t]+\r?\n")
14845 (replace-match ""))
14846 ts)))))
14848 (defvar org-log-note-marker (make-marker))
14849 (defvar org-log-note-purpose nil)
14850 (defvar org-log-note-state nil)
14851 (defvar org-log-note-how nil)
14852 (defvar org-log-note-window-configuration nil)
14853 (defvar org-log-note-return-to (make-marker))
14854 (defvar org-log-post-message nil
14855 "Message to be displayed after a log note has been stored.
14856 The auto-repeater uses this.")
14858 (defun org-add-log-maybe (&optional purpose state findpos how)
14859 "Set up the post command hook to take a note.
14860 If this is about to TODO state change, the new state is expected in STATE.
14861 When FINDPOS is non-nil, find the correct position for the note in
14862 the current entry. If not, assume that it can be inserted at point."
14863 (save-excursion
14864 (when findpos
14865 (org-back-to-heading t)
14866 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"
14867 "\\(\n[^\r\n]*?" org-keyword-time-not-clock-regexp
14868 "[^\r\n]*\\)?"))
14869 (goto-char (match-end 0))
14870 (unless org-log-states-order-reversed
14871 (and (= (char-after) ?\n) (forward-char 1))
14872 (org-skip-over-state-notes)
14873 (skip-chars-backward " \t\n\r")))
14874 (move-marker org-log-note-marker (point))
14875 (setq org-log-note-purpose purpose
14876 org-log-note-state state
14877 org-log-note-how how)
14878 (add-hook 'post-command-hook 'org-add-log-note 'append)))
14880 (defun org-skip-over-state-notes ()
14881 "Skip past the list of State notes in an entry."
14882 (if (looking-at "\n[ \t]*- State") (forward-char 1))
14883 (while (looking-at "[ \t]*- State")
14884 (condition-case nil
14885 (org-next-item)
14886 (error (org-end-of-item)))))
14888 (defun org-add-log-note (&optional purpose)
14889 "Pop up a window for taking a note, and add this note later at point."
14890 (remove-hook 'post-command-hook 'org-add-log-note)
14891 (setq org-log-note-window-configuration (current-window-configuration))
14892 (delete-other-windows)
14893 (move-marker org-log-note-return-to (point))
14894 (switch-to-buffer (marker-buffer org-log-note-marker))
14895 (goto-char org-log-note-marker)
14896 (org-switch-to-buffer-other-window "*Org Note*")
14897 (erase-buffer)
14898 (if (memq org-log-note-how '(time state)) ; FIXME: time or state????????????
14899 (org-store-log-note)
14900 (let ((org-inhibit-startup t)) (org-mode))
14901 (insert (format "# Insert note for %s.
14902 # Finish with C-c C-c, or cancel with C-c C-k.\n\n"
14903 (cond
14904 ((eq org-log-note-purpose 'clock-out) "stopped clock")
14905 ((eq org-log-note-purpose 'done) "closed todo item")
14906 ((eq org-log-note-purpose 'state)
14907 (format "state change to \"%s\"" org-log-note-state))
14908 (t (error "This should not happen")))))
14909 (org-set-local 'org-finish-function 'org-store-log-note)))
14911 (defun org-store-log-note ()
14912 "Finish taking a log note, and insert it to where it belongs."
14913 (let ((txt (buffer-string))
14914 (note (cdr (assq org-log-note-purpose org-log-note-headings)))
14915 lines ind)
14916 (kill-buffer (current-buffer))
14917 (while (string-match "\\`#.*\n[ \t\n]*" txt)
14918 (setq txt (replace-match "" t t txt)))
14919 (if (string-match "\\s-+\\'" txt)
14920 (setq txt (replace-match "" t t txt)))
14921 (setq lines (org-split-string txt "\n"))
14922 (when (and note (string-match "\\S-" note))
14923 (setq note
14924 (org-replace-escapes
14925 note
14926 (list (cons "%u" (user-login-name))
14927 (cons "%U" user-full-name)
14928 (cons "%t" (format-time-string
14929 (org-time-stamp-format 'long 'inactive)
14930 (current-time)))
14931 (cons "%s" (if org-log-note-state
14932 (concat "\"" org-log-note-state "\"")
14933 "")))))
14934 (if lines (setq note (concat note " \\\\")))
14935 (push note lines))
14936 (when (or current-prefix-arg org-note-abort) (setq lines nil))
14937 (when lines
14938 (save-excursion
14939 (set-buffer (marker-buffer org-log-note-marker))
14940 (save-excursion
14941 (goto-char org-log-note-marker)
14942 (move-marker org-log-note-marker nil)
14943 (end-of-line 1)
14944 (if (not (bolp)) (let ((inhibit-read-only t)) (insert "\n")))
14945 (indent-relative nil)
14946 (insert "- " (pop lines))
14947 (org-indent-line-function)
14948 (beginning-of-line 1)
14949 (looking-at "[ \t]*")
14950 (setq ind (concat (match-string 0) " "))
14951 (end-of-line 1)
14952 (while lines (insert "\n" ind (pop lines)))))))
14953 (set-window-configuration org-log-note-window-configuration)
14954 (with-current-buffer (marker-buffer org-log-note-return-to)
14955 (goto-char org-log-note-return-to))
14956 (move-marker org-log-note-return-to nil)
14957 (and org-log-post-message (message "%s" org-log-post-message)))
14959 ;; FIXME: what else would be useful?
14960 ;; - priority
14961 ;; - date
14963 (defun org-sparse-tree (&optional arg)
14964 "Create a sparse tree, prompt for the details.
14965 This command can create sparse trees. You first need to select the type
14966 of match used to create the tree:
14968 t Show entries with a specific TODO keyword.
14969 T Show entries selected by a tags match.
14970 p Enter a property name and its value (both with completion on existing
14971 names/values) and show entries with that property.
14972 r Show entries matching a regular expression
14973 d Show deadlines due within `org-deadline-warning-days'."
14974 (interactive "P")
14975 (let (ans kwd value)
14976 (message "Sparse tree: [/]regexp [t]odo-kwd [T]ag [p]roperty [d]eadlines [b]efore-date")
14977 (setq ans (read-char-exclusive))
14978 (cond
14979 ((equal ans ?d)
14980 (call-interactively 'org-check-deadlines))
14981 ((equal ans ?b)
14982 (call-interactively 'org-check-before-date))
14983 ((equal ans ?t)
14984 (org-show-todo-tree '(4)))
14985 ((equal ans ?T)
14986 (call-interactively 'org-tags-sparse-tree))
14987 ((member ans '(?p ?P))
14988 (setq kwd (completing-read "Property: "
14989 (mapcar 'list (org-buffer-property-keys))))
14990 (setq value (completing-read "Value: "
14991 (mapcar 'list (org-property-values kwd))))
14992 (unless (string-match "\\`{.*}\\'" value)
14993 (setq value (concat "\"" value "\"")))
14994 (org-tags-sparse-tree arg (concat kwd "=" value)))
14995 ((member ans '(?r ?R ?/))
14996 (call-interactively 'org-occur))
14997 (t (error "No such sparse tree command \"%c\"" ans)))))
14999 (defvar org-occur-highlights nil
15000 "List of overlays used for occur matches.")
15001 (make-variable-buffer-local 'org-occur-highlights)
15002 (defvar org-occur-parameters nil
15003 "Parameters of the active org-occur calls.
15004 This is a list, each call to org-occur pushes as cons cell,
15005 containing the regular expression and the callback, onto the list.
15006 The list can contain several entries if `org-occur' has been called
15007 several time with the KEEP-PREVIOUS argument. Otherwise, this list
15008 will only contain one set of parameters. When the highlights are
15009 removed (for example with `C-c C-c', or with the next edit (depending
15010 on `org-remove-highlights-with-change'), this variable is emptied
15011 as well.")
15012 (make-variable-buffer-local 'org-occur-parameters)
15014 (defun org-occur (regexp &optional keep-previous callback)
15015 "Make a compact tree which shows all matches of REGEXP.
15016 The tree will show the lines where the regexp matches, and all higher
15017 headlines above the match. It will also show the heading after the match,
15018 to make sure editing the matching entry is easy.
15019 If KEEP-PREVIOUS is non-nil, highlighting and exposing done by a previous
15020 call to `org-occur' will be kept, to allow stacking of calls to this
15021 command.
15022 If CALLBACK is non-nil, it is a function which is called to confirm
15023 that the match should indeed be shown."
15024 (interactive "sRegexp: \nP")
15025 (unless keep-previous
15026 (org-remove-occur-highlights nil nil t))
15027 (push (cons regexp callback) org-occur-parameters)
15028 (let ((cnt 0))
15029 (save-excursion
15030 (goto-char (point-min))
15031 (if (or (not keep-previous) ; do not want to keep
15032 (not org-occur-highlights)) ; no previous matches
15033 ;; hide everything
15034 (org-overview))
15035 (while (re-search-forward regexp nil t)
15036 (when (or (not callback)
15037 (save-match-data (funcall callback)))
15038 (setq cnt (1+ cnt))
15039 (when org-highlight-sparse-tree-matches
15040 (org-highlight-new-match (match-beginning 0) (match-end 0)))
15041 (org-show-context 'occur-tree))))
15042 (when org-remove-highlights-with-change
15043 (org-add-hook 'before-change-functions 'org-remove-occur-highlights
15044 nil 'local))
15045 (unless org-sparse-tree-open-archived-trees
15046 (org-hide-archived-subtrees (point-min) (point-max)))
15047 (run-hooks 'org-occur-hook)
15048 (if (interactive-p)
15049 (message "%d match(es) for regexp %s" cnt regexp))
15050 cnt))
15052 (defun org-show-context (&optional key)
15053 "Make sure point and context and visible.
15054 How much context is shown depends upon the variables
15055 `org-show-hierarchy-above', `org-show-following-heading'. and
15056 `org-show-siblings'."
15057 (let ((heading-p (org-on-heading-p t))
15058 (hierarchy-p (org-get-alist-option org-show-hierarchy-above key))
15059 (following-p (org-get-alist-option org-show-following-heading key))
15060 (entry-p (org-get-alist-option org-show-entry-below key))
15061 (siblings-p (org-get-alist-option org-show-siblings key)))
15062 (catch 'exit
15063 ;; Show heading or entry text
15064 (if (and heading-p (not entry-p))
15065 (org-flag-heading nil) ; only show the heading
15066 (and (or entry-p (org-invisible-p) (org-invisible-p2))
15067 (org-show-hidden-entry))) ; show entire entry
15068 (when following-p
15069 ;; Show next sibling, or heading below text
15070 (save-excursion
15071 (and (if heading-p (org-goto-sibling) (outline-next-heading))
15072 (org-flag-heading nil))))
15073 (when siblings-p (org-show-siblings))
15074 (when hierarchy-p
15075 ;; show all higher headings, possibly with siblings
15076 (save-excursion
15077 (while (and (condition-case nil
15078 (progn (org-up-heading-all 1) t)
15079 (error nil))
15080 (not (bobp)))
15081 (org-flag-heading nil)
15082 (when siblings-p (org-show-siblings))))))))
15084 (defun org-reveal (&optional siblings)
15085 "Show current entry, hierarchy above it, and the following headline.
15086 This can be used to show a consistent set of context around locations
15087 exposed with `org-show-hierarchy-above' or `org-show-following-heading'
15088 not t for the search context.
15090 With optional argument SIBLINGS, on each level of the hierarchy all
15091 siblings are shown. This repairs the tree structure to what it would
15092 look like when opened with hierarchical calls to `org-cycle'."
15093 (interactive "P")
15094 (let ((org-show-hierarchy-above t)
15095 (org-show-following-heading t)
15096 (org-show-siblings (if siblings t org-show-siblings)))
15097 (org-show-context nil)))
15099 (defun org-highlight-new-match (beg end)
15100 "Highlight from BEG to END and mark the highlight is an occur headline."
15101 (let ((ov (org-make-overlay beg end)))
15102 (org-overlay-put ov 'face 'secondary-selection)
15103 (push ov org-occur-highlights)))
15105 (defun org-remove-occur-highlights (&optional beg end noremove)
15106 "Remove the occur highlights from the buffer.
15107 BEG and END are ignored. If NOREMOVE is nil, remove this function
15108 from the `before-change-functions' in the current buffer."
15109 (interactive)
15110 (unless org-inhibit-highlight-removal
15111 (mapc 'org-delete-overlay org-occur-highlights)
15112 (setq org-occur-highlights nil)
15113 (setq org-occur-parameters nil)
15114 (unless noremove
15115 (remove-hook 'before-change-functions
15116 'org-remove-occur-highlights 'local))))
15118 ;;;; Priorities
15120 (defvar org-priority-regexp ".*?\\(\\[#\\([A-Z0-9]\\)\\] ?\\)"
15121 "Regular expression matching the priority indicator.")
15123 (defvar org-remove-priority-next-time nil)
15125 (defun org-priority-up ()
15126 "Increase the priority of the current item."
15127 (interactive)
15128 (org-priority 'up))
15130 (defun org-priority-down ()
15131 "Decrease the priority of the current item."
15132 (interactive)
15133 (org-priority 'down))
15135 (defun org-priority (&optional action)
15136 "Change the priority of an item by ARG.
15137 ACTION can be `set', `up', `down', or a character."
15138 (interactive)
15139 (setq action (or action 'set))
15140 (let (current new news have remove)
15141 (save-excursion
15142 (org-back-to-heading)
15143 (if (looking-at org-priority-regexp)
15144 (setq current (string-to-char (match-string 2))
15145 have t)
15146 (setq current org-default-priority))
15147 (cond
15148 ((or (eq action 'set) (integerp action))
15149 (if (integerp action)
15150 (setq new action)
15151 (message "Priority %c-%c, SPC to remove: " org-highest-priority org-lowest-priority)
15152 (setq new (read-char-exclusive)))
15153 (if (and (= (upcase org-highest-priority) org-highest-priority)
15154 (= (upcase org-lowest-priority) org-lowest-priority))
15155 (setq new (upcase new)))
15156 (cond ((equal new ?\ ) (setq remove t))
15157 ((or (< (upcase new) org-highest-priority) (> (upcase new) org-lowest-priority))
15158 (error "Priority must be between `%c' and `%c'"
15159 org-highest-priority org-lowest-priority))))
15160 ((eq action 'up)
15161 (if (and (not have) (eq last-command this-command))
15162 (setq new org-lowest-priority)
15163 (setq new (if (and org-priority-start-cycle-with-default (not have))
15164 org-default-priority (1- current)))))
15165 ((eq action 'down)
15166 (if (and (not have) (eq last-command this-command))
15167 (setq new org-highest-priority)
15168 (setq new (if (and org-priority-start-cycle-with-default (not have))
15169 org-default-priority (1+ current)))))
15170 (t (error "Invalid action")))
15171 (if (or (< (upcase new) org-highest-priority)
15172 (> (upcase new) org-lowest-priority))
15173 (setq remove t))
15174 (setq news (format "%c" new))
15175 (if have
15176 (if remove
15177 (replace-match "" t t nil 1)
15178 (replace-match news t t nil 2))
15179 (if remove
15180 (error "No priority cookie found in line")
15181 (looking-at org-todo-line-regexp)
15182 (if (match-end 2)
15183 (progn
15184 (goto-char (match-end 2))
15185 (insert " [#" news "]"))
15186 (goto-char (match-beginning 3))
15187 (insert "[#" news "] ")))))
15188 (org-preserve-lc (org-set-tags nil 'align))
15189 (if remove
15190 (message "Priority removed")
15191 (message "Priority of current item set to %s" news))))
15194 (defun org-get-priority (s)
15195 "Find priority cookie and return priority."
15196 (save-match-data
15197 (if (not (string-match org-priority-regexp s))
15198 (* 1000 (- org-lowest-priority org-default-priority))
15199 (* 1000 (- org-lowest-priority
15200 (string-to-char (match-string 2 s)))))))
15202 ;;;; Tags
15204 (defun org-scan-tags (action matcher &optional todo-only)
15205 "Scan headline tags with inheritance and produce output ACTION.
15206 ACTION can be `sparse-tree' or `agenda'. MATCHER is a Lisp form to be
15207 evaluated, testing if a given set of tags qualifies a headline for
15208 inclusion. When TODO-ONLY is non-nil, only lines with a TODO keyword
15209 are included in the output."
15210 (let* ((re (concat "[\n\r]" outline-regexp " *\\(\\<\\("
15211 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
15212 (org-re
15213 "\\>\\)\\)? *\\(.*?\\)\\(:[[:alnum:]_@:]+:\\)?[ \t]*$")))
15214 (props (list 'face nil
15215 'done-face 'org-done
15216 'undone-face nil
15217 'mouse-face 'highlight
15218 'org-not-done-regexp org-not-done-regexp
15219 'org-todo-regexp org-todo-regexp
15220 'keymap org-agenda-keymap
15221 'help-echo
15222 (format "mouse-2 or RET jump to org file %s"
15223 (abbreviate-file-name
15224 (or (buffer-file-name (buffer-base-buffer))
15225 (buffer-name (buffer-base-buffer)))))))
15226 (case-fold-search nil)
15227 lspos
15228 tags tags-list tags-alist (llast 0) rtn level category i txt
15229 todo marker entry priority)
15230 (save-excursion
15231 (goto-char (point-min))
15232 (when (eq action 'sparse-tree)
15233 (org-overview)
15234 (org-remove-occur-highlights))
15235 (while (re-search-forward re nil t)
15236 (catch :skip
15237 (setq todo (if (match-end 1) (match-string 2))
15238 tags (if (match-end 4) (match-string 4)))
15239 (goto-char (setq lspos (1+ (match-beginning 0))))
15240 (setq level (org-reduced-level (funcall outline-level))
15241 category (org-get-category))
15242 (setq i llast llast level)
15243 ;; remove tag lists from same and sublevels
15244 (while (>= i level)
15245 (when (setq entry (assoc i tags-alist))
15246 (setq tags-alist (delete entry tags-alist)))
15247 (setq i (1- i)))
15248 ;; add the nex tags
15249 (when tags
15250 (setq tags (mapcar 'downcase (org-split-string tags ":"))
15251 tags-alist
15252 (cons (cons level tags) tags-alist)))
15253 ;; compile tags for current headline
15254 (setq tags-list
15255 (if org-use-tag-inheritance
15256 (apply 'append (mapcar 'cdr tags-alist))
15257 tags))
15258 (when (and (or (not todo-only) (member todo org-not-done-keywords))
15259 (eval matcher)
15260 (or (not org-agenda-skip-archived-trees)
15261 (not (member org-archive-tag tags-list))))
15262 (and (eq action 'agenda) (org-agenda-skip))
15263 ;; list this headline
15265 (if (eq action 'sparse-tree)
15266 (progn
15267 (and org-highlight-sparse-tree-matches
15268 (org-get-heading) (match-end 0)
15269 (org-highlight-new-match
15270 (match-beginning 0) (match-beginning 1)))
15271 (org-show-context 'tags-tree))
15272 (setq txt (org-format-agenda-item
15274 (concat
15275 (if org-tags-match-list-sublevels
15276 (make-string (1- level) ?.) "")
15277 (org-get-heading))
15278 category tags-list)
15279 priority (org-get-priority txt))
15280 (goto-char lspos)
15281 (setq marker (org-agenda-new-marker))
15282 (org-add-props txt props
15283 'org-marker marker 'org-hd-marker marker 'org-category category
15284 'priority priority 'type "tagsmatch")
15285 (push txt rtn))
15286 ;; if we are to skip sublevels, jump to end of subtree
15287 (or org-tags-match-list-sublevels (org-end-of-subtree t))))))
15288 (when (and (eq action 'sparse-tree)
15289 (not org-sparse-tree-open-archived-trees))
15290 (org-hide-archived-subtrees (point-min) (point-max)))
15291 (nreverse rtn)))
15293 (defvar todo-only) ;; dynamically scoped
15295 (defun org-tags-sparse-tree (&optional todo-only match)
15296 "Create a sparse tree according to tags string MATCH.
15297 MATCH can contain positive and negative selection of tags, like
15298 \"+WORK+URGENT-WITHBOSS\".
15299 If optional argument TODO_ONLY is non-nil, only select lines that are
15300 also TODO lines."
15301 (interactive "P")
15302 (org-prepare-agenda-buffers (list (current-buffer)))
15303 (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match)) todo-only))
15305 (defvar org-cached-props nil)
15306 (defun org-cached-entry-get (pom property)
15307 (if (or (eq t org-use-property-inheritance)
15308 (member property org-use-property-inheritance))
15309 ;; Caching is not possible, check it directly
15310 (org-entry-get pom property 'inherit)
15311 ;; Get all properties, so that we can do complicated checks easily
15312 (cdr (assoc property (or org-cached-props
15313 (setq org-cached-props
15314 (org-entry-properties pom)))))))
15316 (defun org-global-tags-completion-table (&optional files)
15317 "Return the list of all tags in all agenda buffer/files."
15318 (save-excursion
15319 (org-uniquify
15320 (delq nil
15321 (apply 'append
15322 (mapcar
15323 (lambda (file)
15324 (set-buffer (find-file-noselect file))
15325 (append (org-get-buffer-tags)
15326 (mapcar (lambda (x) (if (stringp (car-safe x))
15327 (list (car-safe x)) nil))
15328 org-tag-alist)))
15329 (if (and files (car files))
15330 files
15331 (org-agenda-files))))))))
15333 (defun org-make-tags-matcher (match)
15334 "Create the TAGS//TODO matcher form for the selection string MATCH."
15335 ;; todo-only is scoped dynamically into this function, and the function
15336 ;; may change it it the matcher asksk for it.
15337 (unless match
15338 ;; Get a new match request, with completion
15339 (let ((org-last-tags-completion-table
15340 (org-global-tags-completion-table)))
15341 (setq match (completing-read
15342 "Match: " 'org-tags-completion-function nil nil nil
15343 'org-tags-history))))
15345 ;; Parse the string and create a lisp form
15346 (let ((match0 match)
15347 (re (org-re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL=\\([0-9]+\\)\\|\\([[:alnum:]_]+\\)=\\({[^}]+}\\|\"[^\"]*\"\\)\\|[[:alnum:]_@]+\\)"))
15348 minus tag mm
15349 tagsmatch todomatch tagsmatcher todomatcher kwd matcher
15350 orterms term orlist re-p level-p prop-p pn pv cat-p gv)
15351 (if (string-match "/+" match)
15352 ;; match contains also a todo-matching request
15353 (progn
15354 (setq tagsmatch (substring match 0 (match-beginning 0))
15355 todomatch (substring match (match-end 0)))
15356 (if (string-match "^!" todomatch)
15357 (setq todo-only t todomatch (substring todomatch 1)))
15358 (if (string-match "^\\s-*$" todomatch)
15359 (setq todomatch nil)))
15360 ;; only matching tags
15361 (setq tagsmatch match todomatch nil))
15363 ;; Make the tags matcher
15364 (if (or (not tagsmatch) (not (string-match "\\S-" tagsmatch)))
15365 (setq tagsmatcher t)
15366 (setq orterms (org-split-string tagsmatch "|") orlist nil)
15367 (while (setq term (pop orterms))
15368 (while (and (equal (substring term -1) "\\") orterms)
15369 (setq term (concat term "|" (pop orterms)))) ; repair bad split
15370 (while (string-match re term)
15371 (setq minus (and (match-end 1)
15372 (equal (match-string 1 term) "-"))
15373 tag (match-string 2 term)
15374 re-p (equal (string-to-char tag) ?{)
15375 level-p (match-end 3)
15376 prop-p (match-end 4)
15377 mm (cond
15378 (re-p `(org-match-any-p ,(substring tag 1 -1) tags-list))
15379 (level-p `(= level ,(string-to-number
15380 (match-string 3 term))))
15381 (prop-p
15382 (setq pn (match-string 4 term)
15383 pv (match-string 5 term)
15384 cat-p (equal pn "CATEGORY")
15385 re-p (equal (string-to-char pv) ?{)
15386 pv (substring pv 1 -1))
15387 (if (equal pn "CATEGORY")
15388 (setq gv '(get-text-property (point) 'org-category))
15389 (setq gv `(org-cached-entry-get nil ,pn)))
15390 (if re-p
15391 `(string-match ,pv (or ,gv ""))
15392 `(equal ,pv (or ,gv ""))))
15393 (t `(member ,(downcase tag) tags-list)))
15394 mm (if minus (list 'not mm) mm)
15395 term (substring term (match-end 0)))
15396 (push mm tagsmatcher))
15397 (push (if (> (length tagsmatcher) 1)
15398 (cons 'and tagsmatcher)
15399 (car tagsmatcher))
15400 orlist)
15401 (setq tagsmatcher nil))
15402 (setq tagsmatcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist)))
15403 (setq tagsmatcher
15404 (list 'progn '(setq org-cached-props nil) tagsmatcher)))
15406 ;; Make the todo matcher
15407 (if (or (not todomatch) (not (string-match "\\S-" todomatch)))
15408 (setq todomatcher t)
15409 (setq orterms (org-split-string todomatch "|") orlist nil)
15410 (while (setq term (pop orterms))
15411 (while (string-match re term)
15412 (setq minus (and (match-end 1)
15413 (equal (match-string 1 term) "-"))
15414 kwd (match-string 2 term)
15415 re-p (equal (string-to-char kwd) ?{)
15416 term (substring term (match-end 0))
15417 mm (if re-p
15418 `(string-match ,(substring kwd 1 -1) todo)
15419 (list 'equal 'todo kwd))
15420 mm (if minus (list 'not mm) mm))
15421 (push mm todomatcher))
15422 (push (if (> (length todomatcher) 1)
15423 (cons 'and todomatcher)
15424 (car todomatcher))
15425 orlist)
15426 (setq todomatcher nil))
15427 (setq todomatcher (if (> (length orlist) 1)
15428 (cons 'or orlist) (car orlist))))
15430 ;; Return the string and lisp forms of the matcher
15431 (setq matcher (if todomatcher
15432 (list 'and tagsmatcher todomatcher)
15433 tagsmatcher))
15434 (cons match0 matcher)))
15436 (defun org-match-any-p (re list)
15437 "Does re match any element of list?"
15438 (setq list (mapcar (lambda (x) (string-match re x)) list))
15439 (delq nil list))
15441 (defvar org-add-colon-after-tag-completion nil) ;; dynamically skoped param
15442 (defvar org-tags-overlay (org-make-overlay 1 1))
15443 (org-detach-overlay org-tags-overlay)
15445 (defun org-align-tags-here (to-col)
15446 ;; Assumes that this is a headline
15447 (let ((pos (point)) (col (current-column)) tags)
15448 (beginning-of-line 1)
15449 (if (and (looking-at (org-re ".*?\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$"))
15450 (< pos (match-beginning 2)))
15451 (progn
15452 (setq tags (match-string 2))
15453 (goto-char (match-beginning 1))
15454 (insert " ")
15455 (delete-region (point) (1+ (match-end 0)))
15456 (backward-char 1)
15457 (move-to-column
15458 (max (1+ (current-column))
15459 (1+ col)
15460 (if (> to-col 0)
15461 to-col
15462 (- (abs to-col) (length tags))))
15464 (insert tags)
15465 (move-to-column (min (current-column) col) t))
15466 (goto-char pos))))
15468 (defun org-set-tags (&optional arg just-align)
15469 "Set the tags for the current headline.
15470 With prefix ARG, realign all tags in headings in the current buffer."
15471 (interactive "P")
15472 (let* ((re (concat "^" outline-regexp))
15473 (current (org-get-tags-string))
15474 (col (current-column))
15475 (org-setting-tags t)
15476 table current-tags inherited-tags ; computed below when needed
15477 tags p0 c0 c1 rpl)
15478 (if arg
15479 (save-excursion
15480 (goto-char (point-min))
15481 (let ((buffer-invisibility-spec (org-inhibit-invisibility)))
15482 (while (re-search-forward re nil t)
15483 (org-set-tags nil t)
15484 (end-of-line 1)))
15485 (message "All tags realigned to column %d" org-tags-column))
15486 (if just-align
15487 (setq tags current)
15488 ;; Get a new set of tags from the user
15489 (save-excursion
15490 (setq table (or org-tag-alist (org-get-buffer-tags))
15491 org-last-tags-completion-table table
15492 current-tags (org-split-string current ":")
15493 inherited-tags (nreverse
15494 (nthcdr (length current-tags)
15495 (nreverse (org-get-tags-at))))
15496 tags
15497 (if (or (eq t org-use-fast-tag-selection)
15498 (and org-use-fast-tag-selection
15499 (delq nil (mapcar 'cdr table))))
15500 (org-fast-tag-selection
15501 current-tags inherited-tags table
15502 (if org-fast-tag-selection-include-todo org-todo-key-alist))
15503 (let ((org-add-colon-after-tag-completion t))
15504 (org-trim
15505 (org-without-partial-completion
15506 (completing-read "Tags: " 'org-tags-completion-function
15507 nil nil current 'org-tags-history)))))))
15508 (while (string-match "[-+&]+" tags)
15509 ;; No boolean logic, just a list
15510 (setq tags (replace-match ":" t t tags))))
15512 (if (string-match "\\`[\t ]*\\'" tags)
15513 (setq tags "")
15514 (unless (string-match ":$" tags) (setq tags (concat tags ":")))
15515 (unless (string-match "^:" tags) (setq tags (concat ":" tags))))
15517 ;; Insert new tags at the correct column
15518 (beginning-of-line 1)
15519 (cond
15520 ((and (equal current "") (equal tags "")))
15521 ((re-search-forward
15522 (concat "\\([ \t]*" (regexp-quote current) "\\)[ \t]*$")
15523 (point-at-eol) t)
15524 (if (equal tags "")
15525 (setq rpl "")
15526 (goto-char (match-beginning 0))
15527 (setq c0 (current-column) p0 (point)
15528 c1 (max (1+ c0) (if (> org-tags-column 0)
15529 org-tags-column
15530 (- (- org-tags-column) (length tags))))
15531 rpl (concat (make-string (max 0 (- c1 c0)) ?\ ) tags)))
15532 (replace-match rpl t t)
15533 (and (not (featurep 'xemacs)) c0 indent-tabs-mode (tabify p0 (point)))
15534 tags)
15535 (t (error "Tags alignment failed")))
15536 (move-to-column col)
15537 (unless just-align
15538 (run-hooks 'org-after-tags-change-hook)))))
15540 (defun org-change-tag-in-region (beg end tag off)
15541 "Add or remove TAG for each entry in the region.
15542 This works in the agenda, and also in an org-mode buffer."
15543 (interactive
15544 (list (region-beginning) (region-end)
15545 (let ((org-last-tags-completion-table
15546 (if (org-mode-p)
15547 (org-get-buffer-tags)
15548 (org-global-tags-completion-table))))
15549 (completing-read
15550 "Tag: " 'org-tags-completion-function nil nil nil
15551 'org-tags-history))
15552 (progn
15553 (message "[s]et or [r]emove? ")
15554 (equal (read-char-exclusive) ?r))))
15555 (if (fboundp 'deactivate-mark) (deactivate-mark))
15556 (let ((agendap (equal major-mode 'org-agenda-mode))
15557 l1 l2 m buf pos newhead (cnt 0))
15558 (goto-char end)
15559 (setq l2 (1- (org-current-line)))
15560 (goto-char beg)
15561 (setq l1 (org-current-line))
15562 (loop for l from l1 to l2 do
15563 (goto-line l)
15564 (setq m (get-text-property (point) 'org-hd-marker))
15565 (when (or (and (org-mode-p) (org-on-heading-p))
15566 (and agendap m))
15567 (setq buf (if agendap (marker-buffer m) (current-buffer))
15568 pos (if agendap m (point)))
15569 (with-current-buffer buf
15570 (save-excursion
15571 (save-restriction
15572 (goto-char pos)
15573 (setq cnt (1+ cnt))
15574 (org-toggle-tag tag (if off 'off 'on))
15575 (setq newhead (org-get-heading)))))
15576 (and agendap (org-agenda-change-all-lines newhead m))))
15577 (message "Tag :%s: %s in %d headings" tag (if off "removed" "set") cnt)))
15579 (defun org-tags-completion-function (string predicate &optional flag)
15580 (let (s1 s2 rtn (ctable org-last-tags-completion-table)
15581 (confirm (lambda (x) (stringp (car x)))))
15582 (if (string-match "^\\(.*[-+:&|]\\)\\([^-+:&|]*\\)$" string)
15583 (setq s1 (match-string 1 string)
15584 s2 (match-string 2 string))
15585 (setq s1 "" s2 string))
15586 (cond
15587 ((eq flag nil)
15588 ;; try completion
15589 (setq rtn (try-completion s2 ctable confirm))
15590 (if (stringp rtn)
15591 (setq rtn
15592 (concat s1 s2 (substring rtn (length s2))
15593 (if (and org-add-colon-after-tag-completion
15594 (assoc rtn ctable))
15595 ":" ""))))
15596 rtn)
15597 ((eq flag t)
15598 ;; all-completions
15599 (all-completions s2 ctable confirm)
15601 ((eq flag 'lambda)
15602 ;; exact match?
15603 (assoc s2 ctable)))
15606 (defun org-fast-tag-insert (kwd tags face &optional end)
15607 "Insert KDW, and the TAGS, the latter with face FACE. Also inser END."
15608 (insert (format "%-12s" (concat kwd ":"))
15609 (org-add-props (mapconcat 'identity tags " ") nil 'face face)
15610 (or end "")))
15612 (defun org-fast-tag-show-exit (flag)
15613 (save-excursion
15614 (goto-line 3)
15615 (if (re-search-forward "[ \t]+Next change exits" (point-at-eol) t)
15616 (replace-match ""))
15617 (when flag
15618 (end-of-line 1)
15619 (move-to-column (- (window-width) 19) t)
15620 (insert (org-add-props " Next change exits" nil 'face 'org-warning)))))
15622 (defun org-set-current-tags-overlay (current prefix)
15623 (let ((s (concat ":" (mapconcat 'identity current ":") ":")))
15624 (if (featurep 'xemacs)
15625 (org-overlay-display org-tags-overlay (concat prefix s)
15626 'secondary-selection)
15627 (put-text-property 0 (length s) 'face '(secondary-selection org-tag) s)
15628 (org-overlay-display org-tags-overlay (concat prefix s)))))
15630 (defun org-fast-tag-selection (current inherited table &optional todo-table)
15631 "Fast tag selection with single keys.
15632 CURRENT is the current list of tags in the headline, INHERITED is the
15633 list of inherited tags, and TABLE is an alist of tags and corresponding keys,
15634 possibly with grouping information. TODO-TABLE is a similar table with
15635 TODO keywords, should these have keys assigned to them.
15636 If the keys are nil, a-z are automatically assigned.
15637 Returns the new tags string, or nil to not change the current settings."
15638 (let* ((fulltable (append table todo-table))
15639 (maxlen (apply 'max (mapcar
15640 (lambda (x)
15641 (if (stringp (car x)) (string-width (car x)) 0))
15642 fulltable)))
15643 (buf (current-buffer))
15644 (expert (eq org-fast-tag-selection-single-key 'expert))
15645 (buffer-tags nil)
15646 (fwidth (+ maxlen 3 1 3))
15647 (ncol (/ (- (window-width) 4) fwidth))
15648 (i-face 'org-done)
15649 (c-face 'org-todo)
15650 tg cnt e c char c1 c2 ntable tbl rtn
15651 ov-start ov-end ov-prefix
15652 (exit-after-next org-fast-tag-selection-single-key)
15653 (done-keywords org-done-keywords)
15654 groups ingroup)
15655 (save-excursion
15656 (beginning-of-line 1)
15657 (if (looking-at
15658 (org-re ".*[ \t]\\(:[[:alnum:]_@:]+:\\)[ \t]*$"))
15659 (setq ov-start (match-beginning 1)
15660 ov-end (match-end 1)
15661 ov-prefix "")
15662 (setq ov-start (1- (point-at-eol))
15663 ov-end (1+ ov-start))
15664 (skip-chars-forward "^\n\r")
15665 (setq ov-prefix
15666 (concat
15667 (buffer-substring (1- (point)) (point))
15668 (if (> (current-column) org-tags-column)
15670 (make-string (- org-tags-column (current-column)) ?\ ))))))
15671 (org-move-overlay org-tags-overlay ov-start ov-end)
15672 (save-window-excursion
15673 (if expert
15674 (set-buffer (get-buffer-create " *Org tags*"))
15675 (delete-other-windows)
15676 (split-window-vertically)
15677 (org-switch-to-buffer-other-window (get-buffer-create " *Org tags*")))
15678 (erase-buffer)
15679 (org-set-local 'org-done-keywords done-keywords)
15680 (org-fast-tag-insert "Inherited" inherited i-face "\n")
15681 (org-fast-tag-insert "Current" current c-face "\n\n")
15682 (org-fast-tag-show-exit exit-after-next)
15683 (org-set-current-tags-overlay current ov-prefix)
15684 (setq tbl fulltable char ?a cnt 0)
15685 (while (setq e (pop tbl))
15686 (cond
15687 ((equal e '(:startgroup))
15688 (push '() groups) (setq ingroup t)
15689 (when (not (= cnt 0))
15690 (setq cnt 0)
15691 (insert "\n"))
15692 (insert "{ "))
15693 ((equal e '(:endgroup))
15694 (setq ingroup nil cnt 0)
15695 (insert "}\n"))
15697 (setq tg (car e) c2 nil)
15698 (if (cdr e)
15699 (setq c (cdr e))
15700 ;; automatically assign a character.
15701 (setq c1 (string-to-char
15702 (downcase (substring
15703 tg (if (= (string-to-char tg) ?@) 1 0)))))
15704 (if (or (rassoc c1 ntable) (rassoc c1 table))
15705 (while (or (rassoc char ntable) (rassoc char table))
15706 (setq char (1+ char)))
15707 (setq c2 c1))
15708 (setq c (or c2 char)))
15709 (if ingroup (push tg (car groups)))
15710 (setq tg (org-add-props tg nil 'face
15711 (cond
15712 ((not (assoc tg table))
15713 (org-get-todo-face tg))
15714 ((member tg current) c-face)
15715 ((member tg inherited) i-face)
15716 (t nil))))
15717 (if (and (= cnt 0) (not ingroup)) (insert " "))
15718 (insert "[" c "] " tg (make-string
15719 (- fwidth 4 (length tg)) ?\ ))
15720 (push (cons tg c) ntable)
15721 (when (= (setq cnt (1+ cnt)) ncol)
15722 (insert "\n")
15723 (if ingroup (insert " "))
15724 (setq cnt 0)))))
15725 (setq ntable (nreverse ntable))
15726 (insert "\n")
15727 (goto-char (point-min))
15728 (if (and (not expert) (fboundp 'fit-window-to-buffer))
15729 (fit-window-to-buffer))
15730 (setq rtn
15731 (catch 'exit
15732 (while t
15733 (message "[a-z..]:Toggle [SPC]:clear [RET]:accept [TAB]:free%s%s"
15734 (if groups " [!] no groups" " [!]groups")
15735 (if expert " [C-c]:window" (if exit-after-next " [C-c]:single" " [C-c]:multi")))
15736 (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
15737 (cond
15738 ((= c ?\r) (throw 'exit t))
15739 ((= c ?!)
15740 (setq groups (not groups))
15741 (goto-char (point-min))
15742 (while (re-search-forward "[{}]" nil t) (replace-match " ")))
15743 ((= c ?\C-c)
15744 (if (not expert)
15745 (org-fast-tag-show-exit
15746 (setq exit-after-next (not exit-after-next)))
15747 (setq expert nil)
15748 (delete-other-windows)
15749 (split-window-vertically)
15750 (org-switch-to-buffer-other-window " *Org tags*")
15751 (and (fboundp 'fit-window-to-buffer)
15752 (fit-window-to-buffer))))
15753 ((or (= c ?\C-g)
15754 (and (= c ?q) (not (rassoc c ntable))))
15755 (org-detach-overlay org-tags-overlay)
15756 (setq quit-flag t))
15757 ((= c ?\ )
15758 (setq current nil)
15759 (if exit-after-next (setq exit-after-next 'now)))
15760 ((= c ?\t)
15761 (condition-case nil
15762 (setq tg (completing-read
15763 "Tag: "
15764 (or buffer-tags
15765 (with-current-buffer buf
15766 (org-get-buffer-tags)))))
15767 (quit (setq tg "")))
15768 (when (string-match "\\S-" tg)
15769 (add-to-list 'buffer-tags (list tg))
15770 (if (member tg current)
15771 (setq current (delete tg current))
15772 (push tg current)))
15773 (if exit-after-next (setq exit-after-next 'now)))
15774 ((setq e (rassoc c todo-table) tg (car e))
15775 (with-current-buffer buf
15776 (save-excursion (org-todo tg)))
15777 (if exit-after-next (setq exit-after-next 'now)))
15778 ((setq e (rassoc c ntable) tg (car e))
15779 (if (member tg current)
15780 (setq current (delete tg current))
15781 (loop for g in groups do
15782 (if (member tg g)
15783 (mapc (lambda (x)
15784 (setq current (delete x current)))
15785 g)))
15786 (push tg current))
15787 (if exit-after-next (setq exit-after-next 'now))))
15789 ;; Create a sorted list
15790 (setq current
15791 (sort current
15792 (lambda (a b)
15793 (assoc b (cdr (memq (assoc a ntable) ntable))))))
15794 (if (eq exit-after-next 'now) (throw 'exit t))
15795 (goto-char (point-min))
15796 (beginning-of-line 2)
15797 (delete-region (point) (point-at-eol))
15798 (org-fast-tag-insert "Current" current c-face)
15799 (org-set-current-tags-overlay current ov-prefix)
15800 (while (re-search-forward
15801 (org-re "\\[.\\] \\([[:alnum:]_@]+\\)") nil t)
15802 (setq tg (match-string 1))
15803 (add-text-properties
15804 (match-beginning 1) (match-end 1)
15805 (list 'face
15806 (cond
15807 ((member tg current) c-face)
15808 ((member tg inherited) i-face)
15809 (t (get-text-property (match-beginning 1) 'face))))))
15810 (goto-char (point-min)))))
15811 (org-detach-overlay org-tags-overlay)
15812 (if rtn
15813 (mapconcat 'identity current ":")
15814 nil))))
15816 (defun org-get-tags-string ()
15817 "Get the TAGS string in the current headline."
15818 (unless (org-on-heading-p t)
15819 (error "Not on a heading"))
15820 (save-excursion
15821 (beginning-of-line 1)
15822 (if (looking-at (org-re ".*[ \t]\\(:[[:alnum:]_@:]+:\\)[ \t]*$"))
15823 (org-match-string-no-properties 1)
15824 "")))
15826 (defun org-get-tags ()
15827 "Get the list of tags specified in the current headline."
15828 (org-split-string (org-get-tags-string) ":"))
15830 (defun org-get-buffer-tags ()
15831 "Get a table of all tags used in the buffer, for completion."
15832 (let (tags)
15833 (save-excursion
15834 (goto-char (point-min))
15835 (while (re-search-forward
15836 (org-re "[ \t]:\\([[:alnum:]_@:]+\\):[ \t\r\n]") nil t)
15837 (when (equal (char-after (point-at-bol 0)) ?*)
15838 (mapc (lambda (x) (add-to-list 'tags x))
15839 (org-split-string (org-match-string-no-properties 1) ":")))))
15840 (mapcar 'list tags)))
15843 ;;;; Properties
15845 ;;; Setting and retrieving properties
15847 (defconst org-special-properties
15848 '("TODO" "TAGS" "ALLTAGS" "DEADLINE" "SCHEDULED" "CLOCK" "PRIORITY"
15849 "TIMESTAMP" "TIMESTAMP_IA")
15850 "The special properties valid in Org-mode.
15852 These are properties that are not defined in the property drawer,
15853 but in some other way.")
15855 (defconst org-default-properties
15856 '("ARCHIVE" "CATEGORY" "SUMMARY" "DESCRIPTION"
15857 "LOCATION" "LOGGING" "COLUMNS")
15858 "Some properties that are used by Org-mode for various purposes.
15859 Being in this list makes sure that they are offered for completion.")
15861 (defconst org-property-start-re "^[ \t]*:PROPERTIES:[ \t]*$"
15862 "Regular expression matching the first line of a property drawer.")
15864 (defconst org-property-end-re "^[ \t]*:END:[ \t]*$"
15865 "Regular expression matching the first line of a property drawer.")
15867 (defun org-property-action ()
15868 "Do an action on properties."
15869 (interactive)
15870 (let (c)
15871 (org-at-property-p)
15872 (message "Property Action: [s]et [d]elete [D]elete globally [c]ompute")
15873 (setq c (read-char-exclusive))
15874 (cond
15875 ((equal c ?s)
15876 (call-interactively 'org-set-property))
15877 ((equal c ?d)
15878 (call-interactively 'org-delete-property))
15879 ((equal c ?D)
15880 (call-interactively 'org-delete-property-globally))
15881 ((equal c ?c)
15882 (call-interactively 'org-compute-property-at-point))
15883 (t (error "No such property action %c" c)))))
15885 (defun org-at-property-p ()
15886 "Is the cursor in a property line?"
15887 ;; FIXME: Does not check if we are actually in the drawer.
15888 ;; FIXME: also returns true on any drawers.....
15889 ;; This is used by C-c C-c for property action.
15890 (save-excursion
15891 (beginning-of-line 1)
15892 (looking-at (org-re "^[ \t]*\\(:\\([[:alpha:]][[:alnum:]_-]*\\):\\)[ \t]*\\(.*\\)"))))
15894 (defmacro org-with-point-at (pom &rest body)
15895 "Move to buffer and point of point-or-marker POM for the duration of BODY."
15896 (declare (indent 1) (debug t))
15897 `(save-excursion
15898 (if (markerp pom) (set-buffer (marker-buffer pom)))
15899 (save-excursion
15900 (goto-char (or pom (point)))
15901 ,@body)))
15903 (defun org-get-property-block (&optional beg end force)
15904 "Return the (beg . end) range of the body of the property drawer.
15905 BEG and END can be beginning and end of subtree, if not given
15906 they will be found.
15907 If the drawer does not exist and FORCE is non-nil, create the drawer."
15908 (catch 'exit
15909 (save-excursion
15910 (let* ((beg (or beg (progn (org-back-to-heading t) (point))))
15911 (end (or end (progn (outline-next-heading) (point)))))
15912 (goto-char beg)
15913 (if (re-search-forward org-property-start-re end t)
15914 (setq beg (1+ (match-end 0)))
15915 (if force
15916 (save-excursion
15917 (org-insert-property-drawer)
15918 (setq end (progn (outline-next-heading) (point))))
15919 (throw 'exit nil))
15920 (goto-char beg)
15921 (if (re-search-forward org-property-start-re end t)
15922 (setq beg (1+ (match-end 0)))))
15923 (if (re-search-forward org-property-end-re end t)
15924 (setq end (match-beginning 0))
15925 (or force (throw 'exit nil))
15926 (goto-char beg)
15927 (setq end beg)
15928 (org-indent-line-function)
15929 (insert ":END:\n"))
15930 (cons beg end)))))
15932 (defun org-entry-properties (&optional pom which)
15933 "Get all properties of the entry at point-or-marker POM.
15934 This includes the TODO keyword, the tags, time strings for deadline,
15935 scheduled, and clocking, and any additional properties defined in the
15936 entry. The return value is an alist, keys may occur multiple times
15937 if the property key was used several times.
15938 POM may also be nil, in which case the current entry is used.
15939 If WHICH is nil or `all', get all properties. If WHICH is
15940 `special' or `standard', only get that subclass."
15941 (setq which (or which 'all))
15942 (org-with-point-at pom
15943 (let ((clockstr (substring org-clock-string 0 -1))
15944 (excluded '("TODO" "TAGS" "ALLTAGS" "PRIORITY"))
15945 beg end range props sum-props key value string clocksum)
15946 (save-excursion
15947 (when (condition-case nil (org-back-to-heading t) (error nil))
15948 (setq beg (point))
15949 (setq sum-props (get-text-property (point) 'org-summaries))
15950 (setq clocksum (get-text-property (point) :org-clock-minutes))
15951 (outline-next-heading)
15952 (setq end (point))
15953 (when (memq which '(all special))
15954 ;; Get the special properties, like TODO and tags
15955 (goto-char beg)
15956 (when (and (looking-at org-todo-line-regexp) (match-end 2))
15957 (push (cons "TODO" (org-match-string-no-properties 2)) props))
15958 (when (looking-at org-priority-regexp)
15959 (push (cons "PRIORITY" (org-match-string-no-properties 2)) props))
15960 (when (and (setq value (org-get-tags-string))
15961 (string-match "\\S-" value))
15962 (push (cons "TAGS" value) props))
15963 (when (setq value (org-get-tags-at))
15964 (push (cons "ALLTAGS" (concat ":" (mapconcat 'identity value ":") ":"))
15965 props))
15966 (while (re-search-forward org-maybe-keyword-time-regexp end t)
15967 (setq key (if (match-end 1) (substring (org-match-string-no-properties 1) 0 -1))
15968 string (if (equal key clockstr)
15969 (org-no-properties
15970 (org-trim
15971 (buffer-substring
15972 (match-beginning 3) (goto-char (point-at-eol)))))
15973 (substring (org-match-string-no-properties 3) 1 -1)))
15974 (unless key
15975 (if (= (char-after (match-beginning 3)) ?\[)
15976 (setq key "TIMESTAMP_IA")
15977 (setq key "TIMESTAMP")))
15978 (when (or (equal key clockstr) (not (assoc key props)))
15979 (push (cons key string) props)))
15983 (when (memq which '(all standard))
15984 ;; Get the standard properties, like :PORP: ...
15985 (setq range (org-get-property-block beg end))
15986 (when range
15987 (goto-char (car range))
15988 (while (re-search-forward
15989 (org-re "^[ \t]*:\\([[:alpha:]][[:alnum:]_-]*\\):[ \t]*\\(\\S-.*\\)?")
15990 (cdr range) t)
15991 (setq key (org-match-string-no-properties 1)
15992 value (org-trim (or (org-match-string-no-properties 2) "")))
15993 (unless (member key excluded)
15994 (push (cons key (or value "")) props)))))
15995 (if clocksum
15996 (push (cons "CLOCKSUM"
15997 (org-column-number-to-string (/ (float clocksum) 60.)
15998 'add_times))
15999 props))
16000 (append sum-props (nreverse props)))))))
16002 (defun org-entry-get (pom property &optional inherit)
16003 "Get value of PROPERTY for entry at point-or-marker POM.
16004 If INHERIT is non-nil and the entry does not have the property,
16005 then also check higher levels of the hierarchy.
16006 If the property is present but empty, the return value is the empty string.
16007 If the property is not present at all, nil is returned."
16008 (org-with-point-at pom
16009 (if inherit
16010 (org-entry-get-with-inheritance property)
16011 (if (member property org-special-properties)
16012 ;; We need a special property. Use brute force, get all properties.
16013 (cdr (assoc property (org-entry-properties nil 'special)))
16014 (let ((range (org-get-property-block)))
16015 (if (and range
16016 (goto-char (car range))
16017 (re-search-forward
16018 (concat "^[ \t]*:" property ":[ \t]*\\(.*\\S-\\)?")
16019 (cdr range) t))
16020 ;; Found the property, return it.
16021 (if (match-end 1)
16022 (org-match-string-no-properties 1)
16023 "")))))))
16025 (defun org-entry-delete (pom property)
16026 "Delete the property PROPERTY from entry at point-or-marker POM."
16027 (org-with-point-at pom
16028 (if (member property org-special-properties)
16029 nil ; cannot delete these properties.
16030 (let ((range (org-get-property-block)))
16031 (if (and range
16032 (goto-char (car range))
16033 (re-search-forward
16034 (concat "^[ \t]*:" property ":[ \t]*\\(.*\\S-\\)")
16035 (cdr range) t))
16036 (progn
16037 (delete-region (match-beginning 0) (1+ (point-at-eol)))
16039 nil)))))
16041 ;; Multi-values properties are properties that contain multiple values
16042 ;; These values are assumed to be single words, separated by whitespace.
16043 (defun org-entry-add-to-multivalued-property (pom property value)
16044 "Add VALUE to the words in the PROPERTY in entry at point-or-marker POM."
16045 (let* ((old (org-entry-get pom property))
16046 (values (and old (org-split-string old "[ \t]"))))
16047 (unless (member value values)
16048 (setq values (cons value values))
16049 (org-entry-put pom property
16050 (mapconcat 'identity values " ")))))
16052 (defun org-entry-remove-from-multivalued-property (pom property value)
16053 "Remove VALUE from words in the PROPERTY in entry at point-or-marker POM."
16054 (let* ((old (org-entry-get pom property))
16055 (values (and old (org-split-string old "[ \t]"))))
16056 (when (member value values)
16057 (setq values (delete value values))
16058 (org-entry-put pom property
16059 (mapconcat 'identity values " ")))))
16061 (defun org-entry-member-in-multivalued-property (pom property value)
16062 "Is VALUE one of the words in the PROPERTY in entry at point-or-marker POM?"
16063 (let* ((old (org-entry-get pom property))
16064 (values (and old (org-split-string old "[ \t]"))))
16065 (member value values)))
16067 (defvar org-entry-property-inherited-from (make-marker))
16069 (defun org-entry-get-with-inheritance (property)
16070 "Get entry property, and search higher levels if not present."
16071 (let (tmp)
16072 (save-excursion
16073 (save-restriction
16074 (widen)
16075 (catch 'ex
16076 (while t
16077 (when (setq tmp (org-entry-get nil property))
16078 (org-back-to-heading t)
16079 (move-marker org-entry-property-inherited-from (point))
16080 (throw 'ex tmp))
16081 (or (org-up-heading-safe) (throw 'ex nil)))))
16082 (or tmp (cdr (assoc property org-local-properties))
16083 (cdr (assoc property org-global-properties))))))
16085 (defun org-entry-put (pom property value)
16086 "Set PROPERTY to VALUE for entry at point-or-marker POM."
16087 (org-with-point-at pom
16088 (org-back-to-heading t)
16089 (let ((beg (point)) (end (save-excursion (outline-next-heading) (point)))
16090 range)
16091 (cond
16092 ((equal property "TODO")
16093 (when (and (stringp value) (string-match "\\S-" value)
16094 (not (member value org-todo-keywords-1)))
16095 (error "\"%s\" is not a valid TODO state" value))
16096 (if (or (not value)
16097 (not (string-match "\\S-" value)))
16098 (setq value 'none))
16099 (org-todo value)
16100 (org-set-tags nil 'align))
16101 ((equal property "PRIORITY")
16102 (org-priority (if (and value (stringp value) (string-match "\\S-" value))
16103 (string-to-char value) ?\ ))
16104 (org-set-tags nil 'align))
16105 ((equal property "SCHEDULED")
16106 (if (re-search-forward org-scheduled-time-regexp end t)
16107 (cond
16108 ((eq value 'earlier) (org-timestamp-change -1 'day))
16109 ((eq value 'later) (org-timestamp-change 1 'day))
16110 (t (call-interactively 'org-schedule)))
16111 (call-interactively 'org-schedule)))
16112 ((equal property "DEADLINE")
16113 (if (re-search-forward org-deadline-time-regexp end t)
16114 (cond
16115 ((eq value 'earlier) (org-timestamp-change -1 'day))
16116 ((eq value 'later) (org-timestamp-change 1 'day))
16117 (t (call-interactively 'org-deadline)))
16118 (call-interactively 'org-deadline)))
16119 ((member property org-special-properties)
16120 (error "The %s property can not yet be set with `org-entry-put'"
16121 property))
16122 (t ; a non-special property
16123 (let ((buffer-invisibility-spec (org-inhibit-invisibility))) ; Emacs 21
16124 (setq range (org-get-property-block beg end 'force))
16125 (goto-char (car range))
16126 (if (re-search-forward
16127 (concat "^[ \t]*:" property ":\\(.*\\)") (cdr range) t)
16128 (progn
16129 (delete-region (match-beginning 1) (match-end 1))
16130 (goto-char (match-beginning 1)))
16131 (goto-char (cdr range))
16132 (insert "\n")
16133 (backward-char 1)
16134 (org-indent-line-function)
16135 (insert ":" property ":"))
16136 (and value (insert " " value))
16137 (org-indent-line-function)))))))
16139 (defun org-buffer-property-keys (&optional include-specials include-defaults include-columns)
16140 "Get all property keys in the current buffer.
16141 With INCLUDE-SPECIALS, also list the special properties that relect things
16142 like tags and TODO state.
16143 With INCLUDE-DEFAULTS, also include properties that has special meaning
16144 internally: ARCHIVE, CATEGORY, SUMMARY, DESCRIPTION, LOCATION, and LOGGING.
16145 With INCLUDE-COLUMNS, also include property names given in COLUMN
16146 formats in the current buffer."
16147 (let (rtn range cfmt cols s p)
16148 (save-excursion
16149 (save-restriction
16150 (widen)
16151 (goto-char (point-min))
16152 (while (re-search-forward org-property-start-re nil t)
16153 (setq range (org-get-property-block))
16154 (goto-char (car range))
16155 (while (re-search-forward
16156 (org-re "^[ \t]*:\\([-[:alnum:]_]+\\):")
16157 (cdr range) t)
16158 (add-to-list 'rtn (org-match-string-no-properties 1)))
16159 (outline-next-heading))))
16161 (when include-specials
16162 (setq rtn (append org-special-properties rtn)))
16164 (when include-defaults
16165 (mapc (lambda (x) (add-to-list 'rtn x)) org-default-properties))
16167 (when include-columns
16168 (save-excursion
16169 (save-restriction
16170 (widen)
16171 (goto-char (point-min))
16172 (while (re-search-forward
16173 "^\\(#\\+COLUMNS:\\|[ \t]*:COLUMNS:\\)[ \t]*\\(.*\\)"
16174 nil t)
16175 (setq cfmt (match-string 2) s 0)
16176 (while (string-match (org-re "%[0-9]*\\([-[:alnum:]_]+\\)")
16177 cfmt s)
16178 (setq s (match-end 0)
16179 p (match-string 1 cfmt))
16180 (unless (or (equal p "ITEM")
16181 (member p org-special-properties))
16182 (add-to-list 'rtn (match-string 1 cfmt))))))))
16184 (sort rtn (lambda (a b) (string< (upcase a) (upcase b))))))
16186 (defun org-property-values (key)
16187 "Return a list of all values of property KEY."
16188 (save-excursion
16189 (save-restriction
16190 (widen)
16191 (goto-char (point-min))
16192 (let ((re (concat "^[ \t]*:" key ":[ \t]*\\(\\S-.*\\)"))
16193 values)
16194 (while (re-search-forward re nil t)
16195 (add-to-list 'values (org-trim (match-string 1))))
16196 (delete "" values)))))
16198 (defun org-insert-property-drawer ()
16199 "Insert a property drawer into the current entry."
16200 (interactive)
16201 (org-back-to-heading t)
16202 (looking-at outline-regexp)
16203 (let ((indent (- (match-end 0)(match-beginning 0)))
16204 (beg (point))
16205 (re (concat "^[ \t]*" org-keyword-time-regexp))
16206 end hiddenp)
16207 (outline-next-heading)
16208 (setq end (point))
16209 (goto-char beg)
16210 (while (re-search-forward re end t))
16211 (setq hiddenp (org-invisible-p))
16212 (end-of-line 1)
16213 (and (equal (char-after) ?\n) (forward-char 1))
16214 (org-skip-over-state-notes)
16215 (skip-chars-backward " \t\n\r")
16216 (if (eq (char-before) ?*) (forward-char 1))
16217 (let ((inhibit-read-only t)) (insert "\n:PROPERTIES:\n:END:"))
16218 (beginning-of-line 0)
16219 (indent-to-column indent)
16220 (beginning-of-line 2)
16221 (indent-to-column indent)
16222 (beginning-of-line 0)
16223 (if hiddenp
16224 (save-excursion
16225 (org-back-to-heading t)
16226 (hide-entry))
16227 (org-flag-drawer t))))
16229 (defun org-set-property (property value)
16230 "In the current entry, set PROPERTY to VALUE.
16231 When called interactively, this will prompt for a property name, offering
16232 completion on existing and default properties. And then it will prompt
16233 for a value, offering competion either on allowed values (via an inherited
16234 xxx_ALL property) or on existing values in other instances of this property
16235 in the current file."
16236 (interactive
16237 (let* ((prop (completing-read
16238 "Property: " (mapcar 'list (org-buffer-property-keys nil t t))))
16239 (cur (org-entry-get nil prop))
16240 (allowed (org-property-get-allowed-values nil prop 'table))
16241 (existing (mapcar 'list (org-property-values prop)))
16242 (val (if allowed
16243 (completing-read "Value: " allowed nil 'req-match)
16244 (completing-read
16245 (concat "Value" (if (and cur (string-match "\\S-" cur))
16246 (concat "[" cur "]") "")
16247 ": ")
16248 existing nil nil "" nil cur))))
16249 (list prop (if (equal val "") cur val))))
16250 (unless (equal (org-entry-get nil property) value)
16251 (org-entry-put nil property value)))
16253 (defun org-delete-property (property)
16254 "In the current entry, delete PROPERTY."
16255 (interactive
16256 (let* ((prop (completing-read
16257 "Property: " (org-entry-properties nil 'standard))))
16258 (list prop)))
16259 (message "Property %s %s" property
16260 (if (org-entry-delete nil property)
16261 "deleted"
16262 "was not present in the entry")))
16264 (defun org-delete-property-globally (property)
16265 "Remove PROPERTY globally, from all entries."
16266 (interactive
16267 (let* ((prop (completing-read
16268 "Globally remove property: "
16269 (mapcar 'list (org-buffer-property-keys)))))
16270 (list prop)))
16271 (save-excursion
16272 (save-restriction
16273 (widen)
16274 (goto-char (point-min))
16275 (let ((cnt 0))
16276 (while (re-search-forward
16277 (concat "^[ \t]*:" (regexp-quote property) ":.*\n?")
16278 nil t)
16279 (setq cnt (1+ cnt))
16280 (replace-match ""))
16281 (message "Property \"%s\" removed from %d entries" property cnt)))))
16283 (defvar org-columns-current-fmt-compiled) ; defined below
16285 (defun org-compute-property-at-point ()
16286 "Compute the property at point.
16287 This looks for an enclosing column format, extracts the operator and
16288 then applies it to the proerty in the column format's scope."
16289 (interactive)
16290 (unless (org-at-property-p)
16291 (error "Not at a property"))
16292 (let ((prop (org-match-string-no-properties 2)))
16293 (org-columns-get-format-and-top-level)
16294 (unless (nth 3 (assoc prop org-columns-current-fmt-compiled))
16295 (error "No operator defined for property %s" prop))
16296 (org-columns-compute prop)))
16298 (defun org-property-get-allowed-values (pom property &optional table)
16299 "Get allowed values for the property PROPERTY.
16300 When TABLE is non-nil, return an alist that can directly be used for
16301 completion."
16302 (let (vals)
16303 (cond
16304 ((equal property "TODO")
16305 (setq vals (org-with-point-at pom
16306 (append org-todo-keywords-1 '("")))))
16307 ((equal property "PRIORITY")
16308 (let ((n org-lowest-priority))
16309 (while (>= n org-highest-priority)
16310 (push (char-to-string n) vals)
16311 (setq n (1- n)))))
16312 ((member property org-special-properties))
16314 (setq vals (org-entry-get pom (concat property "_ALL") 'inherit))
16316 (when (and vals (string-match "\\S-" vals))
16317 (setq vals (car (read-from-string (concat "(" vals ")"))))
16318 (setq vals (mapcar (lambda (x)
16319 (cond ((stringp x) x)
16320 ((numberp x) (number-to-string x))
16321 ((symbolp x) (symbol-name x))
16322 (t "???")))
16323 vals)))))
16324 (if table (mapcar 'list vals) vals)))
16326 (defun org-property-previous-allowed-value (&optional previous)
16327 "Switch to the next allowed value for this property."
16328 (interactive)
16329 (org-property-next-allowed-value t))
16331 (defun org-property-next-allowed-value (&optional previous)
16332 "Switch to the next allowed value for this property."
16333 (interactive)
16334 (unless (org-at-property-p)
16335 (error "Not at a property"))
16336 (let* ((key (match-string 2))
16337 (value (match-string 3))
16338 (allowed (or (org-property-get-allowed-values (point) key)
16339 (and (member value '("[ ]" "[-]" "[X]"))
16340 '("[ ]" "[X]"))))
16341 nval)
16342 (unless allowed
16343 (error "Allowed values for this property have not been defined"))
16344 (if previous (setq allowed (reverse allowed)))
16345 (if (member value allowed)
16346 (setq nval (car (cdr (member value allowed)))))
16347 (setq nval (or nval (car allowed)))
16348 (if (equal nval value)
16349 (error "Only one allowed value for this property"))
16350 (org-at-property-p)
16351 (replace-match (concat " :" key ": " nval) t t)
16352 (org-indent-line-function)
16353 (beginning-of-line 1)
16354 (skip-chars-forward " \t")))
16356 (defun org-find-entry-with-id (ident)
16357 "Locate the entry that contains the ID property with exact value IDENT.
16358 IDENT can be a string, a symbol or a number, this function will search for
16359 the string representation of it.
16360 Return the position where this entry starts, or nil if there is no such entry."
16361 (let ((id (cond
16362 ((stringp ident) ident)
16363 ((symbol-name ident) (symbol-name ident))
16364 ((numberp ident) (number-to-string ident))
16365 (t (error "IDENT %s must be a string, symbol or number" ident))))
16366 (case-fold-search nil))
16367 (save-excursion
16368 (save-restriction
16369 (widen)
16370 (goto-char (point-min))
16371 (when (re-search-forward
16372 (concat "^[ \t]*:ID:[ \t]+" (regexp-quote id) "[ \t]*$")
16373 nil t)
16374 (org-back-to-heading)
16375 (point))))))
16377 ;;; Column View
16379 (defvar org-columns-overlays nil
16380 "Holds the list of current column overlays.")
16382 (defvar org-columns-current-fmt nil
16383 "Local variable, holds the currently active column format.")
16384 (defvar org-columns-current-fmt-compiled nil
16385 "Local variable, holds the currently active column format.
16386 This is the compiled version of the format.")
16387 (defvar org-columns-current-widths nil
16388 "Loval variable, holds the currently widths of fields.")
16389 (defvar org-columns-current-maxwidths nil
16390 "Loval variable, holds the currently active maximum column widths.")
16391 (defvar org-columns-begin-marker (make-marker)
16392 "Points to the position where last a column creation command was called.")
16393 (defvar org-columns-top-level-marker (make-marker)
16394 "Points to the position where current columns region starts.")
16396 (defvar org-columns-map (make-sparse-keymap)
16397 "The keymap valid in column display.")
16399 (defun org-columns-content ()
16400 "Switch to contents view while in columns view."
16401 (interactive)
16402 (org-overview)
16403 (org-content))
16405 (org-defkey org-columns-map "c" 'org-columns-content)
16406 (org-defkey org-columns-map "o" 'org-overview)
16407 (org-defkey org-columns-map "e" 'org-columns-edit-value)
16408 (org-defkey org-columns-map "\C-c\C-t" 'org-columns-todo)
16409 (org-defkey org-columns-map "\C-c\C-c" 'org-columns-set-tags-or-toggle)
16410 (org-defkey org-columns-map "\C-c\C-o" 'org-columns-open-link)
16411 (org-defkey org-columns-map "v" 'org-columns-show-value)
16412 (org-defkey org-columns-map "q" 'org-columns-quit)
16413 (org-defkey org-columns-map "r" 'org-columns-redo)
16414 (org-defkey org-columns-map "g" 'org-columns-redo)
16415 (org-defkey org-columns-map [left] 'backward-char)
16416 (org-defkey org-columns-map "\M-b" 'backward-char)
16417 (org-defkey org-columns-map "a" 'org-columns-edit-allowed)
16418 (org-defkey org-columns-map "s" 'org-columns-edit-attributes)
16419 (org-defkey org-columns-map "\M-f" (lambda () (interactive) (goto-char (1+ (point)))))
16420 (org-defkey org-columns-map [right] (lambda () (interactive) (goto-char (1+ (point)))))
16421 (org-defkey org-columns-map [(shift right)] 'org-columns-next-allowed-value)
16422 (org-defkey org-columns-map "n" 'org-columns-next-allowed-value)
16423 (org-defkey org-columns-map [(shift left)] 'org-columns-previous-allowed-value)
16424 (org-defkey org-columns-map "p" 'org-columns-previous-allowed-value)
16425 (org-defkey org-columns-map "<" 'org-columns-narrow)
16426 (org-defkey org-columns-map ">" 'org-columns-widen)
16427 (org-defkey org-columns-map [(meta right)] 'org-columns-move-right)
16428 (org-defkey org-columns-map [(meta left)] 'org-columns-move-left)
16429 (org-defkey org-columns-map [(shift meta right)] 'org-columns-new)
16430 (org-defkey org-columns-map [(shift meta left)] 'org-columns-delete)
16432 (easy-menu-define org-columns-menu org-columns-map "Org Column Menu"
16433 '("Column"
16434 ["Edit property" org-columns-edit-value t]
16435 ["Next allowed value" org-columns-next-allowed-value t]
16436 ["Previous allowed value" org-columns-previous-allowed-value t]
16437 ["Show full value" org-columns-show-value t]
16438 ["Edit allowed values" org-columns-edit-allowed t]
16439 "--"
16440 ["Edit column attributes" org-columns-edit-attributes t]
16441 ["Increase column width" org-columns-widen t]
16442 ["Decrease column width" org-columns-narrow t]
16443 "--"
16444 ["Move column right" org-columns-move-right t]
16445 ["Move column left" org-columns-move-left t]
16446 ["Add column" org-columns-new t]
16447 ["Delete column" org-columns-delete t]
16448 "--"
16449 ["CONTENTS" org-columns-content t]
16450 ["OVERVIEW" org-overview t]
16451 ["Refresh columns display" org-columns-redo t]
16452 "--"
16453 ["Open link" org-columns-open-link t]
16454 "--"
16455 ["Quit" org-columns-quit t]))
16457 (defun org-columns-new-overlay (beg end &optional string face)
16458 "Create a new column overlay and add it to the list."
16459 (let ((ov (org-make-overlay beg end)))
16460 (org-overlay-put ov 'face (or face 'secondary-selection))
16461 (org-overlay-display ov string face)
16462 (push ov org-columns-overlays)
16463 ov))
16465 (defun org-columns-display-here (&optional props)
16466 "Overlay the current line with column display."
16467 (interactive)
16468 (let* ((fmt org-columns-current-fmt-compiled)
16469 (beg (point-at-bol))
16470 (level-face (save-excursion
16471 (beginning-of-line 1)
16472 (and (looking-at "\\(\\**\\)\\(\\* \\)")
16473 (org-get-level-face 2))))
16474 (color (list :foreground
16475 (face-attribute (or level-face 'default) :foreground)))
16476 props pom property ass width f string ov column val modval)
16477 ;; Check if the entry is in another buffer.
16478 (unless props
16479 (if (eq major-mode 'org-agenda-mode)
16480 (setq pom (or (get-text-property (point) 'org-hd-marker)
16481 (get-text-property (point) 'org-marker))
16482 props (if pom (org-entry-properties pom) nil))
16483 (setq props (org-entry-properties nil))))
16484 ;; Walk the format
16485 (while (setq column (pop fmt))
16486 (setq property (car column)
16487 ass (if (equal property "ITEM")
16488 (cons "ITEM"
16489 (save-match-data
16490 (org-no-properties
16491 (org-remove-tabs
16492 (buffer-substring-no-properties
16493 (point-at-bol) (point-at-eol))))))
16494 (assoc property props))
16495 width (or (cdr (assoc property org-columns-current-maxwidths))
16496 (nth 2 column)
16497 (length property))
16498 f (format "%%-%d.%ds | " width width)
16499 val (or (cdr ass) "")
16500 modval (if (equal property "ITEM")
16501 (org-columns-cleanup-item val org-columns-current-fmt-compiled))
16502 string (format f (or modval val)))
16503 ;; Create the overlay
16504 (org-unmodified
16505 (setq ov (org-columns-new-overlay
16506 beg (setq beg (1+ beg)) string
16507 (list color 'org-column)))
16508 ;;; (list (get-text-property (point-at-bol) 'face) 'org-column)))
16509 (org-overlay-put ov 'keymap org-columns-map)
16510 (org-overlay-put ov 'org-columns-key property)
16511 (org-overlay-put ov 'org-columns-value (cdr ass))
16512 (org-overlay-put ov 'org-columns-value-modified modval)
16513 (org-overlay-put ov 'org-columns-pom pom)
16514 (org-overlay-put ov 'org-columns-format f))
16515 (if (or (not (char-after beg))
16516 (equal (char-after beg) ?\n))
16517 (let ((inhibit-read-only t))
16518 (save-excursion
16519 (goto-char beg)
16520 (org-unmodified (insert " ")))))) ;; FIXME: add props and remove later?
16521 ;; Make the rest of the line disappear.
16522 (org-unmodified
16523 (setq ov (org-columns-new-overlay beg (point-at-eol)))
16524 (org-overlay-put ov 'invisible t)
16525 (org-overlay-put ov 'keymap org-columns-map)
16526 (org-overlay-put ov 'intangible t)
16527 (push ov org-columns-overlays)
16528 (setq ov (org-make-overlay (1- (point-at-eol)) (1+ (point-at-eol))))
16529 (org-overlay-put ov 'keymap org-columns-map)
16530 (push ov org-columns-overlays)
16531 (let ((inhibit-read-only t))
16532 (put-text-property (max (point-min) (1- (point-at-bol)))
16533 (min (point-max) (1+ (point-at-eol)))
16534 'read-only "Type `e' to edit property")))))
16536 (defvar org-previous-header-line-format nil
16537 "The header line format before column view was turned on.")
16538 (defvar org-columns-inhibit-recalculation nil
16539 "Inhibit recomputing of columns on column view startup.")
16542 (defvar header-line-format)
16543 (defun org-columns-display-here-title ()
16544 "Overlay the newline before the current line with the table title."
16545 (interactive)
16546 (let ((fmt org-columns-current-fmt-compiled)
16547 string (title "")
16548 property width f column str widths)
16549 (while (setq column (pop fmt))
16550 (setq property (car column)
16551 str (or (nth 1 column) property)
16552 width (or (cdr (assoc property org-columns-current-maxwidths))
16553 (nth 2 column)
16554 (length str))
16555 widths (push width widths)
16556 f (format "%%-%d.%ds | " width width)
16557 string (format f str)
16558 title (concat title string)))
16559 (setq title (concat
16560 (org-add-props " " nil 'display '(space :align-to 0))
16561 (org-add-props title nil 'face '(:weight bold :underline t))))
16562 (org-set-local 'org-previous-header-line-format header-line-format)
16563 (org-set-local 'org-columns-current-widths (nreverse widths))
16564 (setq header-line-format title)))
16566 (defun org-columns-remove-overlays ()
16567 "Remove all currently active column overlays."
16568 (interactive)
16569 (when (marker-buffer org-columns-begin-marker)
16570 (with-current-buffer (marker-buffer org-columns-begin-marker)
16571 (when (local-variable-p 'org-previous-header-line-format)
16572 (setq header-line-format org-previous-header-line-format)
16573 (kill-local-variable 'org-previous-header-line-format))
16574 (move-marker org-columns-begin-marker nil)
16575 (move-marker org-columns-top-level-marker nil)
16576 (org-unmodified
16577 (mapc 'org-delete-overlay org-columns-overlays)
16578 (setq org-columns-overlays nil)
16579 (let ((inhibit-read-only t))
16580 (remove-text-properties (point-min) (point-max) '(read-only t)))))))
16582 (defun org-columns-cleanup-item (item fmt)
16583 "Remove from ITEM what is a column in the format FMT."
16584 (if (not org-complex-heading-regexp)
16585 item
16586 (when (string-match org-complex-heading-regexp item)
16587 (concat
16588 (org-add-props (concat (match-string 1 item) " ") nil
16589 'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) (match-beginning 1))))))
16590 (and (match-end 2) (not (assoc "TODO" fmt)) (concat " " (match-string 2 item)))
16591 (and (match-end 3) (not (assoc "PRIORITY" fmt)) (concat " " (match-string 3 item)))
16592 " " (match-string 4 item)
16593 (and (match-end 5) (not (assoc "TAGS" fmt)) (concat " " (match-string 5 item)))))))
16595 (defun org-columns-show-value ()
16596 "Show the full value of the property."
16597 (interactive)
16598 (let ((value (get-char-property (point) 'org-columns-value)))
16599 (message "Value is: %s" (or value ""))))
16601 (defun org-columns-quit ()
16602 "Remove the column overlays and in this way exit column editing."
16603 (interactive)
16604 (org-unmodified
16605 (org-columns-remove-overlays)
16606 (let ((inhibit-read-only t))
16607 (remove-text-properties (point-min) (point-max) '(read-only t))))
16608 (when (eq major-mode 'org-agenda-mode)
16609 (message
16610 "Modification not yet reflected in Agenda buffer, use `r' to refresh")))
16612 (defun org-columns-check-computed ()
16613 "Check if this column value is computed.
16614 If yes, throw an error indicating that changing it does not make sense."
16615 (let ((val (get-char-property (point) 'org-columns-value)))
16616 (when (and (stringp val)
16617 (get-char-property 0 'org-computed val))
16618 (error "This value is computed from the entry's children"))))
16620 (defun org-columns-todo (&optional arg)
16621 "Change the TODO state during column view."
16622 (interactive "P")
16623 (org-columns-edit-value "TODO"))
16625 (defun org-columns-set-tags-or-toggle (&optional arg)
16626 "Toggle checkbox at point, or set tags for current headline."
16627 (interactive "P")
16628 (if (string-match "\\`\\[[ xX-]\\]\\'"
16629 (get-char-property (point) 'org-columns-value))
16630 (org-columns-next-allowed-value)
16631 (org-columns-edit-value "TAGS")))
16633 (defun org-columns-edit-value (&optional key)
16634 "Edit the value of the property at point in column view.
16635 Where possible, use the standard interface for changing this line."
16636 (interactive)
16637 (org-columns-check-computed)
16638 (let* ((external-key key)
16639 (col (current-column))
16640 (key (or key (get-char-property (point) 'org-columns-key)))
16641 (value (get-char-property (point) 'org-columns-value))
16642 (bol (point-at-bol)) (eol (point-at-eol))
16643 (pom (or (get-text-property bol 'org-hd-marker)
16644 (point))) ; keep despite of compiler waring
16645 (line-overlays
16646 (delq nil (mapcar (lambda (x)
16647 (and (eq (overlay-buffer x) (current-buffer))
16648 (>= (overlay-start x) bol)
16649 (<= (overlay-start x) eol)
16651 org-columns-overlays)))
16652 nval eval allowed)
16653 (cond
16654 ((equal key "CLOCKSUM")
16655 (error "This special column cannot be edited"))
16656 ((equal key "ITEM")
16657 (setq eval '(org-with-point-at pom
16658 (org-edit-headline))))
16659 ((equal key "TODO")
16660 (setq eval '(org-with-point-at pom
16661 (let ((current-prefix-arg
16662 (if external-key current-prefix-arg '(4))))
16663 (call-interactively 'org-todo)))))
16664 ((equal key "PRIORITY")
16665 (setq eval '(org-with-point-at pom
16666 (call-interactively 'org-priority))))
16667 ((equal key "TAGS")
16668 (setq eval '(org-with-point-at pom
16669 (let ((org-fast-tag-selection-single-key
16670 (if (eq org-fast-tag-selection-single-key 'expert)
16671 t org-fast-tag-selection-single-key)))
16672 (call-interactively 'org-set-tags)))))
16673 ((equal key "DEADLINE")
16674 (setq eval '(org-with-point-at pom
16675 (call-interactively 'org-deadline))))
16676 ((equal key "SCHEDULED")
16677 (setq eval '(org-with-point-at pom
16678 (call-interactively 'org-schedule))))
16680 (setq allowed (org-property-get-allowed-values pom key 'table))
16681 (if allowed
16682 (setq nval (completing-read "Value: " allowed nil t))
16683 (setq nval (read-string "Edit: " value)))
16684 (setq nval (org-trim nval))
16685 (when (not (equal nval value))
16686 (setq eval '(org-entry-put pom key nval)))))
16687 (when eval
16688 (let ((inhibit-read-only t))
16689 (remove-text-properties (max (point-min) (1- bol)) eol '(read-only t))
16690 (unwind-protect
16691 (progn
16692 (setq org-columns-overlays
16693 (org-delete-all line-overlays org-columns-overlays))
16694 (mapc 'org-delete-overlay line-overlays)
16695 (org-columns-eval eval))
16696 (org-columns-display-here))))
16697 (move-to-column col)
16698 (if (and (org-mode-p)
16699 (nth 3 (assoc key org-columns-current-fmt-compiled)))
16700 (org-columns-update key))))
16702 (defun org-edit-headline () ; FIXME: this is not columns specific
16703 "Edit the current headline, the part without TODO keyword, TAGS."
16704 (org-back-to-heading)
16705 (when (looking-at org-todo-line-regexp)
16706 (let ((pre (buffer-substring (match-beginning 0) (match-beginning 3)))
16707 (txt (match-string 3))
16708 (post "")
16709 txt2)
16710 (if (string-match (org-re "[ \t]+:[[:alnum:]:_@]+:[ \t]*$") txt)
16711 (setq post (match-string 0 txt)
16712 txt (substring txt 0 (match-beginning 0))))
16713 (setq txt2 (read-string "Edit: " txt))
16714 (when (not (equal txt txt2))
16715 (beginning-of-line 1)
16716 (insert pre txt2 post)
16717 (delete-region (point) (point-at-eol))
16718 (org-set-tags nil t)))))
16720 (defun org-columns-edit-allowed ()
16721 "Edit the list of allowed values for the current property."
16722 (interactive)
16723 (let* ((key (get-char-property (point) 'org-columns-key))
16724 (key1 (concat key "_ALL"))
16725 (allowed (org-entry-get (point) key1 t))
16726 nval)
16727 ;; FIXME: Cover editing TODO, TAGS etc in-buffer settings.????
16728 (setq nval (read-string "Allowed: " allowed))
16729 (org-entry-put
16730 (cond ((marker-position org-entry-property-inherited-from)
16731 org-entry-property-inherited-from)
16732 ((marker-position org-columns-top-level-marker)
16733 org-columns-top-level-marker))
16734 key1 nval)))
16736 (defmacro org-no-warnings (&rest body)
16737 (cons (if (fboundp 'with-no-warnings) 'with-no-warnings 'progn) body))
16739 (defun org-columns-eval (form)
16740 (let (hidep)
16741 (save-excursion
16742 (beginning-of-line 1)
16743 ;; `next-line' is needed here, because it skips invisible line.
16744 (condition-case nil (org-no-warnings (next-line 1)) (error nil))
16745 (setq hidep (org-on-heading-p 1)))
16746 (eval form)
16747 (and hidep (hide-entry))))
16749 (defun org-columns-previous-allowed-value ()
16750 "Switch to the previous allowed value for this column."
16751 (interactive)
16752 (org-columns-next-allowed-value t))
16754 (defun org-columns-next-allowed-value (&optional previous)
16755 "Switch to the next allowed value for this column."
16756 (interactive)
16757 (org-columns-check-computed)
16758 (let* ((col (current-column))
16759 (key (get-char-property (point) 'org-columns-key))
16760 (value (get-char-property (point) 'org-columns-value))
16761 (bol (point-at-bol)) (eol (point-at-eol))
16762 (pom (or (get-text-property bol 'org-hd-marker)
16763 (point))) ; keep despite of compiler waring
16764 (line-overlays
16765 (delq nil (mapcar (lambda (x)
16766 (and (eq (overlay-buffer x) (current-buffer))
16767 (>= (overlay-start x) bol)
16768 (<= (overlay-start x) eol)
16770 org-columns-overlays)))
16771 (allowed (or (org-property-get-allowed-values pom key)
16772 (and (memq
16773 (nth 4 (assoc key org-columns-current-fmt-compiled))
16774 '(checkbox checkbox-n-of-m checkbox-percent))
16775 '("[ ]" "[X]"))))
16776 nval)
16777 (when (equal key "ITEM")
16778 (error "Cannot edit item headline from here"))
16779 (unless (or allowed (member key '("SCHEDULED" "DEADLINE")))
16780 (error "Allowed values for this property have not been defined"))
16781 (if (member key '("SCHEDULED" "DEADLINE"))
16782 (setq nval (if previous 'earlier 'later))
16783 (if previous (setq allowed (reverse allowed)))
16784 (if (member value allowed)
16785 (setq nval (car (cdr (member value allowed)))))
16786 (setq nval (or nval (car allowed)))
16787 (if (equal nval value)
16788 (error "Only one allowed value for this property")))
16789 (let ((inhibit-read-only t))
16790 (remove-text-properties (1- bol) eol '(read-only t))
16791 (unwind-protect
16792 (progn
16793 (setq org-columns-overlays
16794 (org-delete-all line-overlays org-columns-overlays))
16795 (mapc 'org-delete-overlay line-overlays)
16796 (org-columns-eval '(org-entry-put pom key nval)))
16797 (org-columns-display-here)))
16798 (move-to-column col)
16799 (if (and (org-mode-p)
16800 (nth 3 (assoc key org-columns-current-fmt-compiled)))
16801 (org-columns-update key))))
16803 (defun org-verify-version (task)
16804 (cond
16805 ((eq task 'columns)
16806 (if (or (featurep 'xemacs)
16807 (< emacs-major-version 22))
16808 (error "Emacs 22 is required for the columns feature")))))
16810 (defun org-columns-open-link (&optional arg)
16811 (interactive "P")
16812 (let ((value (get-char-property (point) 'org-columns-value)))
16813 (org-open-link-from-string value arg)))
16815 (defun org-open-link-from-string (s &optional arg)
16816 "Open a link in the string S, as if it was in Org-mode."
16817 (interactive)
16818 (with-temp-buffer
16819 (let ((org-inhibit-startup t))
16820 (org-mode)
16821 (insert s)
16822 (goto-char (point-min))
16823 (org-open-at-point arg))))
16825 (defun org-columns-get-format-and-top-level ()
16826 (let (fmt)
16827 (when (condition-case nil (org-back-to-heading) (error nil))
16828 (move-marker org-entry-property-inherited-from nil)
16829 (setq fmt (org-entry-get nil "COLUMNS" t)))
16830 (setq fmt (or fmt org-columns-default-format))
16831 (org-set-local 'org-columns-current-fmt fmt)
16832 (org-columns-compile-format fmt)
16833 (if (marker-position org-entry-property-inherited-from)
16834 (move-marker org-columns-top-level-marker
16835 org-entry-property-inherited-from)
16836 (move-marker org-columns-top-level-marker (point)))
16837 fmt))
16839 (defun org-columns ()
16840 "Turn on column view on an org-mode file."
16841 (interactive)
16842 (org-verify-version 'columns)
16843 (org-columns-remove-overlays)
16844 (move-marker org-columns-begin-marker (point))
16845 (let (beg end fmt cache maxwidths)
16846 (setq fmt (org-columns-get-format-and-top-level))
16847 (save-excursion
16848 (goto-char org-columns-top-level-marker)
16849 (setq beg (point))
16850 (unless org-columns-inhibit-recalculation
16851 (org-columns-compute-all))
16852 (setq end (or (condition-case nil (org-end-of-subtree t t) (error nil))
16853 (point-max)))
16854 ;; Get and cache the properties
16855 (goto-char beg)
16856 (when (assoc "CLOCKSUM" org-columns-current-fmt-compiled)
16857 (save-excursion
16858 (save-restriction
16859 (narrow-to-region beg end)
16860 (org-clock-sum))))
16861 (while (re-search-forward (concat "^" outline-regexp) end t)
16862 (push (cons (org-current-line) (org-entry-properties)) cache))
16863 (when cache
16864 (setq maxwidths (org-columns-get-autowidth-alist fmt cache))
16865 (org-set-local 'org-columns-current-maxwidths maxwidths)
16866 (org-columns-display-here-title)
16867 (mapc (lambda (x)
16868 (goto-line (car x))
16869 (org-columns-display-here (cdr x)))
16870 cache)))))
16872 (defun org-columns-new (&optional prop title width op fmt &rest rest)
16873 "Insert a new column, to the left of the current column."
16874 (interactive)
16875 (let ((editp (and prop (assoc prop org-columns-current-fmt-compiled)))
16876 cell)
16877 (setq prop (completing-read
16878 "Property: " (mapcar 'list (org-buffer-property-keys t nil t))
16879 nil nil prop))
16880 (setq title (read-string (concat "Column title [" prop "]: ") (or title prop)))
16881 (setq width (read-string "Column width: " (if width (number-to-string width))))
16882 (if (string-match "\\S-" width)
16883 (setq width (string-to-number width))
16884 (setq width nil))
16885 (setq fmt (completing-read "Summary [none]: "
16886 '(("none") ("add_numbers") ("currency") ("add_times") ("checkbox") ("checkbox-n-of-m") ("checkbox-percent"))
16887 nil t))
16888 (if (string-match "\\S-" fmt)
16889 (setq fmt (intern fmt))
16890 (setq fmt nil))
16891 (if (eq fmt 'none) (setq fmt nil))
16892 (if editp
16893 (progn
16894 (setcar editp prop)
16895 (setcdr editp (list title width nil fmt)))
16896 (setq cell (nthcdr (1- (current-column))
16897 org-columns-current-fmt-compiled))
16898 (setcdr cell (cons (list prop title width nil fmt)
16899 (cdr cell))))
16900 (org-columns-store-format)
16901 (org-columns-redo)))
16903 (defun org-columns-delete ()
16904 "Delete the column at point from columns view."
16905 (interactive)
16906 (let* ((n (current-column))
16907 (title (nth 1 (nth n org-columns-current-fmt-compiled))))
16908 (when (y-or-n-p
16909 (format "Are you sure you want to remove column \"%s\"? " title))
16910 (setq org-columns-current-fmt-compiled
16911 (delq (nth n org-columns-current-fmt-compiled)
16912 org-columns-current-fmt-compiled))
16913 (org-columns-store-format)
16914 (org-columns-redo)
16915 (if (>= (current-column) (length org-columns-current-fmt-compiled))
16916 (backward-char 1)))))
16918 (defun org-columns-edit-attributes ()
16919 "Edit the attributes of the current column."
16920 (interactive)
16921 (let* ((n (current-column))
16922 (info (nth n org-columns-current-fmt-compiled)))
16923 (apply 'org-columns-new info)))
16925 (defun org-columns-widen (arg)
16926 "Make the column wider by ARG characters."
16927 (interactive "p")
16928 (let* ((n (current-column))
16929 (entry (nth n org-columns-current-fmt-compiled))
16930 (width (or (nth 2 entry)
16931 (cdr (assoc (car entry) org-columns-current-maxwidths)))))
16932 (setq width (max 1 (+ width arg)))
16933 (setcar (nthcdr 2 entry) width)
16934 (org-columns-store-format)
16935 (org-columns-redo)))
16937 (defun org-columns-narrow (arg)
16938 "Make the column nrrower by ARG characters."
16939 (interactive "p")
16940 (org-columns-widen (- arg)))
16942 (defun org-columns-move-right ()
16943 "Swap this column with the one to the right."
16944 (interactive)
16945 (let* ((n (current-column))
16946 (cell (nthcdr n org-columns-current-fmt-compiled))
16948 (when (>= n (1- (length org-columns-current-fmt-compiled)))
16949 (error "Cannot shift this column further to the right"))
16950 (setq e (car cell))
16951 (setcar cell (car (cdr cell)))
16952 (setcdr cell (cons e (cdr (cdr cell))))
16953 (org-columns-store-format)
16954 (org-columns-redo)
16955 (forward-char 1)))
16957 (defun org-columns-move-left ()
16958 "Swap this column with the one to the left."
16959 (interactive)
16960 (let* ((n (current-column)))
16961 (when (= n 0)
16962 (error "Cannot shift this column further to the left"))
16963 (backward-char 1)
16964 (org-columns-move-right)
16965 (backward-char 1)))
16967 (defun org-columns-store-format ()
16968 "Store the text version of the current columns format in appropriate place.
16969 This is either in the COLUMNS property of the node starting the current column
16970 display, or in the #+COLUMNS line of the current buffer."
16971 (let (fmt (cnt 0))
16972 (setq fmt (org-columns-uncompile-format org-columns-current-fmt-compiled))
16973 (org-set-local 'org-columns-current-fmt fmt)
16974 (if (marker-position org-columns-top-level-marker)
16975 (save-excursion
16976 (goto-char org-columns-top-level-marker)
16977 (if (and (org-at-heading-p)
16978 (org-entry-get nil "COLUMNS"))
16979 (org-entry-put nil "COLUMNS" fmt)
16980 (goto-char (point-min))
16981 ;; Overwrite all #+COLUMNS lines....
16982 (while (re-search-forward "^#\\+COLUMNS:.*" nil t)
16983 (setq cnt (1+ cnt))
16984 (replace-match (concat "#+COLUMNS: " fmt) t t))
16985 (unless (> cnt 0)
16986 (goto-char (point-min))
16987 (or (org-on-heading-p t) (outline-next-heading))
16988 (let ((inhibit-read-only t))
16989 (insert-before-markers "#+COLUMNS: " fmt "\n")))
16990 (org-set-local 'org-columns-default-format fmt))))))
16992 (defvar org-overriding-columns-format nil
16993 "When set, overrides any other definition.")
16994 (defvar org-agenda-view-columns-initially nil
16995 "When set, switch to columns view immediately after creating the agenda.")
16997 (defun org-agenda-columns ()
16998 "Turn on column view in the agenda."
16999 (interactive)
17000 (org-verify-version 'columns)
17001 (org-columns-remove-overlays)
17002 (move-marker org-columns-begin-marker (point))
17003 (let (fmt cache maxwidths m)
17004 (cond
17005 ((and (local-variable-p 'org-overriding-columns-format)
17006 org-overriding-columns-format)
17007 (setq fmt org-overriding-columns-format))
17008 ((setq m (get-text-property (point-at-bol) 'org-hd-marker))
17009 (setq fmt (org-entry-get m "COLUMNS" t)))
17010 ((and (boundp 'org-columns-current-fmt)
17011 (local-variable-p 'org-columns-current-fmt)
17012 org-columns-current-fmt)
17013 (setq fmt org-columns-current-fmt))
17014 ((setq m (next-single-property-change (point-min) 'org-hd-marker))
17015 (setq m (get-text-property m 'org-hd-marker))
17016 (setq fmt (org-entry-get m "COLUMNS" t))))
17017 (setq fmt (or fmt org-columns-default-format))
17018 (org-set-local 'org-columns-current-fmt fmt)
17019 (org-columns-compile-format fmt)
17020 (save-excursion
17021 ;; Get and cache the properties
17022 (goto-char (point-min))
17023 (while (not (eobp))
17024 (when (setq m (or (get-text-property (point) 'org-hd-marker)
17025 (get-text-property (point) 'org-marker)))
17026 (push (cons (org-current-line) (org-entry-properties m)) cache))
17027 (beginning-of-line 2))
17028 (when cache
17029 (setq maxwidths (org-columns-get-autowidth-alist fmt cache))
17030 (org-set-local 'org-columns-current-maxwidths maxwidths)
17031 (org-columns-display-here-title)
17032 (mapc (lambda (x)
17033 (goto-line (car x))
17034 (org-columns-display-here (cdr x)))
17035 cache)))))
17037 (defun org-columns-get-autowidth-alist (s cache)
17038 "Derive the maximum column widths from the format and the cache."
17039 (let ((start 0) rtn)
17040 (while (string-match (org-re "%\\([[:alpha:]][[:alnum:]_-]*\\)") s start)
17041 (push (cons (match-string 1 s) 1) rtn)
17042 (setq start (match-end 0)))
17043 (mapc (lambda (x)
17044 (setcdr x (apply 'max
17045 (mapcar
17046 (lambda (y)
17047 (length (or (cdr (assoc (car x) (cdr y))) " ")))
17048 cache))))
17049 rtn)
17050 rtn))
17052 (defun org-columns-compute-all ()
17053 "Compute all columns that have operators defined."
17054 (org-unmodified
17055 (remove-text-properties (point-min) (point-max) '(org-summaries t)))
17056 (let ((columns org-columns-current-fmt-compiled) col)
17057 (while (setq col (pop columns))
17058 (when (nth 3 col)
17059 (save-excursion
17060 (org-columns-compute (car col)))))))
17062 (defun org-columns-update (property)
17063 "Recompute PROPERTY, and update the columns display for it."
17064 (org-columns-compute property)
17065 (let (fmt val pos)
17066 (save-excursion
17067 (mapc (lambda (ov)
17068 (when (equal (org-overlay-get ov 'org-columns-key) property)
17069 (setq pos (org-overlay-start ov))
17070 (goto-char pos)
17071 (when (setq val (cdr (assoc property
17072 (get-text-property
17073 (point-at-bol) 'org-summaries))))
17074 (setq fmt (org-overlay-get ov 'org-columns-format))
17075 (org-overlay-put ov 'org-columns-value val)
17076 (org-overlay-put ov 'display (format fmt val)))))
17077 org-columns-overlays))))
17079 (defun org-columns-compute (property)
17080 "Sum the values of property PROPERTY hierarchically, for the entire buffer."
17081 (interactive)
17082 (let* ((re (concat "^" outline-regexp))
17083 (lmax 30) ; Does anyone use deeper levels???
17084 (lsum (make-vector lmax 0))
17085 (lflag (make-vector lmax nil))
17086 (level 0)
17087 (ass (assoc property org-columns-current-fmt-compiled))
17088 (format (nth 4 ass))
17089 (printf (nth 5 ass))
17090 (beg org-columns-top-level-marker)
17091 last-level val valflag flag end sumpos sum-alist sum str str1 useval)
17092 (save-excursion
17093 ;; Find the region to compute
17094 (goto-char beg)
17095 (setq end (condition-case nil (org-end-of-subtree t) (error (point-max))))
17096 (goto-char end)
17097 ;; Walk the tree from the back and do the computations
17098 (while (re-search-backward re beg t)
17099 (setq sumpos (match-beginning 0)
17100 last-level level
17101 level (org-outline-level)
17102 val (org-entry-get nil property)
17103 valflag (and val (string-match "\\S-" val)))
17104 (cond
17105 ((< level last-level)
17106 ;; put the sum of lower levels here as a property
17107 (setq sum (aref lsum last-level) ; current sum
17108 flag (aref lflag last-level) ; any valid entries from children?
17109 str (org-column-number-to-string sum format printf)
17110 str1 (org-add-props (copy-sequence str) nil 'org-computed t 'face 'bold)
17111 useval (if flag str1 (if valflag val ""))
17112 sum-alist (get-text-property sumpos 'org-summaries))
17113 (if (assoc property sum-alist)
17114 (setcdr (assoc property sum-alist) useval)
17115 (push (cons property useval) sum-alist)
17116 (org-unmodified
17117 (add-text-properties sumpos (1+ sumpos)
17118 (list 'org-summaries sum-alist))))
17119 (when val
17120 (org-entry-put nil property (if flag str val)))
17121 ;; add current to current level accumulator
17122 (when (or flag valflag)
17123 (aset lsum level (+ (aref lsum level)
17124 (if flag sum (org-column-string-to-number
17125 (if flag str val) format))))
17126 (aset lflag level t))
17127 ;; clear accumulators for deeper levels
17128 (loop for l from (1+ level) to (1- lmax) do
17129 (aset lsum l 0)
17130 (aset lflag l nil)))
17131 ((>= level last-level)
17132 ;; add what we have here to the accumulator for this level
17133 (aset lsum level (+ (aref lsum level)
17134 (org-column-string-to-number (or val "0") format)))
17135 (and valflag (aset lflag level t)))
17136 (t (error "This should not happen")))))))
17138 (defun org-columns-redo ()
17139 "Construct the column display again."
17140 (interactive)
17141 (message "Recomputing columns...")
17142 (save-excursion
17143 (if (marker-position org-columns-begin-marker)
17144 (goto-char org-columns-begin-marker))
17145 (org-columns-remove-overlays)
17146 (if (org-mode-p)
17147 (call-interactively 'org-columns)
17148 (call-interactively 'org-agenda-columns)))
17149 (message "Recomputing columns...done"))
17151 (defun org-columns-not-in-agenda ()
17152 (if (eq major-mode 'org-agenda-mode)
17153 (error "This command is only allowed in Org-mode buffers")))
17156 (defun org-string-to-number (s)
17157 "Convert string to number, and interpret hh:mm:ss."
17158 (if (not (string-match ":" s))
17159 (string-to-number s)
17160 (let ((l (nreverse (org-split-string s ":"))) (sum 0.0))
17161 (while l
17162 (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
17163 sum)))
17165 (defun org-column-number-to-string (n fmt &optional printf)
17166 "Convert a computed column number to a string value, according to FMT."
17167 (cond
17168 ((eq fmt 'add_times)
17169 (let* ((h (floor n)) (m (floor (+ 0.5 (* 60 (- n h))))))
17170 (format "%d:%02d" h m)))
17171 ((eq fmt 'checkbox)
17172 (cond ((= n (floor n)) "[X]")
17173 ((> n 1.) "[-]")
17174 (t "[ ]")))
17175 ((memq fmt '(checkbox-n-of-m checkbox-percent))
17176 (let* ((n1 (floor n)) (n2 (floor (+ .5 (* 1000000 (- n n1))))))
17177 (org-nofm-to-completion n1 (+ n2 n1) (eq fmt 'checkbox-percent))))
17178 (printf (format printf n))
17179 ((eq fmt 'currency)
17180 (format "%.2f" n))
17181 (t (number-to-string n))))
17183 (defun org-nofm-to-completion (n m &optional percent)
17184 (if (not percent)
17185 (format "[%d/%d]" n m)
17186 (format "[%d%%]"(floor (+ 0.5 (* 100. (/ (* 1.0 n) m)))))))
17188 (defun org-column-string-to-number (s fmt)
17189 "Convert a column value to a number that can be used for column computing."
17190 (cond
17191 ((string-match ":" s)
17192 (let ((l (nreverse (org-split-string s ":"))) (sum 0.0))
17193 (while l
17194 (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
17195 sum))
17196 ((memq fmt '(checkbox checkbox-n-of-m checkbox-percent))
17197 (if (equal s "[X]") 1. 0.000001))
17198 (t (string-to-number s))))
17200 (defun org-columns-uncompile-format (cfmt)
17201 "Turn the compiled columns format back into a string representation."
17202 (let ((rtn "") e s prop title op width fmt printf)
17203 (while (setq e (pop cfmt))
17204 (setq prop (car e)
17205 title (nth 1 e)
17206 width (nth 2 e)
17207 op (nth 3 e)
17208 fmt (nth 4 e)
17209 printf (nth 5 e))
17210 (cond
17211 ((eq fmt 'add_times) (setq op ":"))
17212 ((eq fmt 'checkbox) (setq op "X"))
17213 ((eq fmt 'checkbox-n-of-m) (setq op "X/"))
17214 ((eq fmt 'checkbox-percent) (setq op "X%"))
17215 ((eq fmt 'add_numbers) (setq op "+"))
17216 ((eq fmt 'currency) (setq op "$")))
17217 (if (and op printf) (setq op (concat op ";" printf)))
17218 (if (equal title prop) (setq title nil))
17219 (setq s (concat "%" (if width (number-to-string width))
17220 prop
17221 (if title (concat "(" title ")"))
17222 (if op (concat "{" op "}"))))
17223 (setq rtn (concat rtn " " s)))
17224 (org-trim rtn)))
17226 (defun org-columns-compile-format (fmt)
17227 "Turn a column format string into an alist of specifications.
17228 The alist has one entry for each column in the format. The elements of
17229 that list are:
17230 property the property
17231 title the title field for the columns
17232 width the column width in characters, can be nil for automatic
17233 operator the operator if any
17234 format the output format for computed results, derived from operator
17235 printf a printf format for computed values"
17236 (let ((start 0) width prop title op f printf)
17237 (setq org-columns-current-fmt-compiled nil)
17238 (while (string-match
17239 (org-re "%\\([0-9]+\\)?\\([[:alnum:]_-]+\\)\\(?:(\\([^)]+\\))\\)?\\(?:{\\([^}]+\\)}\\)?\\s-*")
17240 fmt start)
17241 (setq start (match-end 0)
17242 width (match-string 1 fmt)
17243 prop (match-string 2 fmt)
17244 title (or (match-string 3 fmt) prop)
17245 op (match-string 4 fmt)
17246 f nil
17247 printf nil)
17248 (if width (setq width (string-to-number width)))
17249 (when (and op (string-match ";" op))
17250 (setq printf (substring op (match-end 0))
17251 op (substring op 0 (match-beginning 0))))
17252 (cond
17253 ((equal op "+") (setq f 'add_numbers))
17254 ((equal op "$") (setq f 'currency))
17255 ((equal op ":") (setq f 'add_times))
17256 ((equal op "X") (setq f 'checkbox))
17257 ((equal op "X/") (setq f 'checkbox-n-of-m))
17258 ((equal op "X%") (setq f 'checkbox-percent))
17260 (push (list prop title width op f printf) org-columns-current-fmt-compiled))
17261 (setq org-columns-current-fmt-compiled
17262 (nreverse org-columns-current-fmt-compiled))))
17265 ;;; Dynamic block for Column view
17267 (defun org-columns-capture-view (&optional maxlevel skip-empty-rows)
17268 "Get the column view of the current buffer or subtree.
17269 The first optional argument MAXLEVEL sets the level limit. A
17270 second optional argument SKIP-EMPTY-ROWS tells whether to skip
17271 empty rows, an empty row being one where all the column view
17272 specifiers except ITEM are empty. This function returns a list
17273 containing the title row and all other rows. Each row is a list
17274 of fields."
17275 (save-excursion
17276 (let* ((title (mapcar 'cadr org-columns-current-fmt-compiled))
17277 (n (length title)) row tbl)
17278 (goto-char (point-min))
17279 (while (and (re-search-forward "^\\(\\*+\\) " nil t)
17280 (or (null maxlevel)
17281 (>= maxlevel
17282 (if org-odd-levels-only
17283 (/ (1+ (length (match-string 1))) 2)
17284 (length (match-string 1))))))
17285 (when (get-char-property (match-beginning 0) 'org-columns-key)
17286 (setq row nil)
17287 (loop for i from 0 to (1- n) do
17288 (push (or (get-char-property (+ (match-beginning 0) i) 'org-columns-value-modified)
17289 (get-char-property (+ (match-beginning 0) i) 'org-columns-value)
17291 row))
17292 (setq row (nreverse row))
17293 (unless (and skip-empty-rows
17294 (eq 1 (length (delete "" (delete-dups row)))))
17295 (push row tbl))))
17296 (append (list title 'hline) (nreverse tbl)))))
17298 (defun org-dblock-write:columnview (params)
17299 "Write the column view table.
17300 PARAMS is a property list of parameters:
17302 :width enforce same column widths with <N> specifiers.
17303 :id the :ID: property of the entry where the columns view
17304 should be built, as a string. When `local', call locally.
17305 When `global' call column view with the cursor at the beginning
17306 of the buffer (usually this means that the whole buffer switches
17307 to column view).
17308 :hlines When t, insert a hline before each item. When a number, insert
17309 a hline before each level <= that number.
17310 :vlines When t, make each column a colgroup to enforce vertical lines.
17311 :maxlevel When set to a number, don't capture headlines below this level.
17312 :skip-empty-rows
17313 When t, skip rows where all specifiers other than ITEM are empty."
17314 (let ((pos (move-marker (make-marker) (point)))
17315 (hlines (plist-get params :hlines))
17316 (vlines (plist-get params :vlines))
17317 (maxlevel (plist-get params :maxlevel))
17318 (skip-empty-rows (plist-get params :skip-empty-rows))
17319 tbl id idpos nfields tmp)
17320 (save-excursion
17321 (save-restriction
17322 (when (setq id (plist-get params :id))
17323 (cond ((not id) nil)
17324 ((eq id 'global) (goto-char (point-min)))
17325 ((eq id 'local) nil)
17326 ((setq idpos (org-find-entry-with-id id))
17327 (goto-char idpos))
17328 (t (error "Cannot find entry with :ID: %s" id))))
17329 (org-columns)
17330 (setq tbl (org-columns-capture-view maxlevel skip-empty-rows))
17331 (setq nfields (length (car tbl)))
17332 (org-columns-quit)))
17333 (goto-char pos)
17334 (move-marker pos nil)
17335 (when tbl
17336 (when (plist-get params :hlines)
17337 (setq tmp nil)
17338 (while tbl
17339 (if (eq (car tbl) 'hline)
17340 (push (pop tbl) tmp)
17341 (if (string-match "\\` *\\(\\*+\\)" (caar tbl))
17342 (if (and (not (eq (car tmp) 'hline))
17343 (or (eq hlines t)
17344 (and (numberp hlines) (<= (- (match-end 1) (match-beginning 1)) hlines))))
17345 (push 'hline tmp)))
17346 (push (pop tbl) tmp)))
17347 (setq tbl (nreverse tmp)))
17348 (when vlines
17349 (setq tbl (mapcar (lambda (x)
17350 (if (eq 'hline x) x (cons "" x)))
17351 tbl))
17352 (setq tbl (append tbl (list (cons "/" (make-list nfields "<>"))))))
17353 (setq pos (point))
17354 (insert (org-listtable-to-string tbl))
17355 (when (plist-get params :width)
17356 (insert "\n|" (mapconcat (lambda (x) (format "<%d>" (max 3 x)))
17357 org-columns-current-widths "|")))
17358 (goto-char pos)
17359 (org-table-align))))
17361 (defun org-listtable-to-string (tbl)
17362 "Convert a listtable TBL to a string that contains the Org-mode table.
17363 The table still need to be alligned. The resulting string has no leading
17364 and tailing newline characters."
17365 (mapconcat
17366 (lambda (x)
17367 (cond
17368 ((listp x)
17369 (concat "|" (mapconcat 'identity x "|") "|"))
17370 ((eq x 'hline) "|-|")
17371 (t (error "Garbage in listtable: %s" x))))
17372 tbl "\n"))
17374 (defun org-insert-columns-dblock ()
17375 "Create a dynamic block capturing a column view table."
17376 (interactive)
17377 (let ((defaults '(:name "columnview" :hlines 1))
17378 (id (completing-read
17379 "Capture columns (local, global, entry with :ID: property) [local]: "
17380 (append '(("global") ("local"))
17381 (mapcar 'list (org-property-values "ID"))))))
17382 (if (equal id "") (setq id 'local))
17383 (if (equal id "global") (setq id 'global))
17384 (setq defaults (append defaults (list :id id)))
17385 (org-create-dblock defaults)
17386 (org-update-dblock)))
17388 ;;;; Timestamps
17390 (defvar org-last-changed-timestamp nil)
17391 (defvar org-time-was-given) ; dynamically scoped parameter
17392 (defvar org-end-time-was-given) ; dynamically scoped parameter
17393 (defvar org-ts-what) ; dynamically scoped parameter
17395 (defun org-time-stamp (arg)
17396 "Prompt for a date/time and insert a time stamp.
17397 If the user specifies a time like HH:MM, or if this command is called
17398 with a prefix argument, the time stamp will contain date and time.
17399 Otherwise, only the date will be included. All parts of a date not
17400 specified by the user will be filled in from the current date/time.
17401 So if you press just return without typing anything, the time stamp
17402 will represent the current date/time. If there is already a timestamp
17403 at the cursor, it will be modified."
17404 (interactive "P")
17405 (let* ((ts nil)
17406 (default-time
17407 ;; Default time is either today, or, when entering a range,
17408 ;; the range start.
17409 (if (or (and (org-at-timestamp-p t) (setq ts (match-string 0)))
17410 (save-excursion
17411 (re-search-backward
17412 (concat org-ts-regexp "--?-?\\=") ; 1-3 minuses
17413 (- (point) 20) t)))
17414 (apply 'encode-time (org-parse-time-string (match-string 1)))
17415 (current-time)))
17416 (default-input (and ts (org-get-compact-tod ts)))
17417 org-time-was-given org-end-time-was-given time)
17418 (cond
17419 ((and (org-at-timestamp-p)
17420 (eq last-command 'org-time-stamp)
17421 (eq this-command 'org-time-stamp))
17422 (insert "--")
17423 (setq time (let ((this-command this-command))
17424 (org-read-date arg 'totime nil nil default-time default-input)))
17425 (org-insert-time-stamp time (or org-time-was-given arg)))
17426 ((org-at-timestamp-p)
17427 (setq time (let ((this-command this-command))
17428 (org-read-date arg 'totime nil nil default-time default-input)))
17429 (when (org-at-timestamp-p) ; just to get the match data
17430 (replace-match "")
17431 (setq org-last-changed-timestamp
17432 (org-insert-time-stamp
17433 time (or org-time-was-given arg)
17434 nil nil nil (list org-end-time-was-given))))
17435 (message "Timestamp updated"))
17437 (setq time (let ((this-command this-command))
17438 (org-read-date arg 'totime nil nil default-time default-input)))
17439 (org-insert-time-stamp time (or org-time-was-given arg)
17440 nil nil nil (list org-end-time-was-given))))))
17442 ;; FIXME: can we use this for something else????
17443 ;; like computing time differences?????
17444 (defun org-get-compact-tod (s)
17445 (when (string-match "\\(\\([012]?[0-9]\\):\\([0-5][0-9]\\)\\)\\(-\\(\\([012]?[0-9]\\):\\([0-5][0-9]\\)\\)\\)?" s)
17446 (let* ((t1 (match-string 1 s))
17447 (h1 (string-to-number (match-string 2 s)))
17448 (m1 (string-to-number (match-string 3 s)))
17449 (t2 (and (match-end 4) (match-string 5 s)))
17450 (h2 (and t2 (string-to-number (match-string 6 s))))
17451 (m2 (and t2 (string-to-number (match-string 7 s))))
17452 dh dm)
17453 (if (not t2)
17455 (setq dh (- h2 h1) dm (- m2 m1))
17456 (if (< dm 0) (setq dm (+ dm 60) dh (1- dh)))
17457 (concat t1 "+" (number-to-string dh)
17458 (if (/= 0 dm) (concat ":" (number-to-string dm))))))))
17460 (defun org-time-stamp-inactive (&optional arg)
17461 "Insert an inactive time stamp.
17462 An inactive time stamp is enclosed in square brackets instead of angle
17463 brackets. It is inactive in the sense that it does not trigger agenda entries,
17464 does not link to the calendar and cannot be changed with the S-cursor keys.
17465 So these are more for recording a certain time/date."
17466 (interactive "P")
17467 (let (org-time-was-given org-end-time-was-given time)
17468 (setq time (org-read-date arg 'totime))
17469 (org-insert-time-stamp time (or org-time-was-given arg) 'inactive
17470 nil nil (list org-end-time-was-given))))
17472 (defvar org-date-ovl (org-make-overlay 1 1))
17473 (org-overlay-put org-date-ovl 'face 'org-warning)
17474 (org-detach-overlay org-date-ovl)
17476 (defvar org-ans1) ; dynamically scoped parameter
17477 (defvar org-ans2) ; dynamically scoped parameter
17479 (defvar org-plain-time-of-day-regexp) ; defined below
17481 (defvar org-read-date-overlay nil)
17482 (defvar org-dcst nil) ; dynamically scoped
17484 (defun org-read-date (&optional with-time to-time from-string prompt
17485 default-time default-input)
17486 "Read a date, possibly a time, and make things smooth for the user.
17487 The prompt will suggest to enter an ISO date, but you can also enter anything
17488 which will at least partially be understood by `parse-time-string'.
17489 Unrecognized parts of the date will default to the current day, month, year,
17490 hour and minute. If this command is called to replace a timestamp at point,
17491 of to enter the second timestamp of a range, the default time is taken from the
17492 existing stamp. For example,
17493 3-2-5 --> 2003-02-05
17494 feb 15 --> currentyear-02-15
17495 sep 12 9 --> 2009-09-12
17496 12:45 --> today 12:45
17497 22 sept 0:34 --> currentyear-09-22 0:34
17498 12 --> currentyear-currentmonth-12
17499 Fri --> nearest Friday (today or later)
17500 etc.
17502 Furthermore you can specify a relative date by giving, as the *first* thing
17503 in the input: a plus/minus sign, a number and a letter [dwmy] to indicate
17504 change in days weeks, months, years.
17505 With a single plus or minus, the date is relative to today. With a double
17506 plus or minus, it is relative to the date in DEFAULT-TIME. E.g.
17507 +4d --> four days from today
17508 +4 --> same as above
17509 +2w --> two weeks from today
17510 ++5 --> five days from default date
17512 The function understands only English month and weekday abbreviations,
17513 but this can be configured with the variables `parse-time-months' and
17514 `parse-time-weekdays'.
17516 While prompting, a calendar is popped up - you can also select the
17517 date with the mouse (button 1). The calendar shows a period of three
17518 months. To scroll it to other months, use the keys `>' and `<'.
17519 If you don't like the calendar, turn it off with
17520 \(setq org-read-date-popup-calendar nil)
17522 With optional argument TO-TIME, the date will immediately be converted
17523 to an internal time.
17524 With an optional argument WITH-TIME, the prompt will suggest to also
17525 insert a time. Note that when WITH-TIME is not set, you can still
17526 enter a time, and this function will inform the calling routine about
17527 this change. The calling routine may then choose to change the format
17528 used to insert the time stamp into the buffer to include the time.
17529 With optional argument FROM-STRING, read from this string instead from
17530 the user. PROMPT can overwrite the default prompt. DEFAULT-TIME is
17531 the time/date that is used for everything that is not specified by the
17532 user."
17533 (require 'parse-time)
17534 (let* ((org-time-stamp-rounding-minutes
17535 (if (equal with-time '(16)) '(0 0) org-time-stamp-rounding-minutes))
17536 (org-dcst org-display-custom-times)
17537 (ct (org-current-time))
17538 (def (or default-time ct))
17539 (defdecode (decode-time def))
17540 (dummy (progn
17541 (when (< (nth 2 defdecode) org-extend-today-until)
17542 (setcar (nthcdr 2 defdecode) -1)
17543 (setcar (nthcdr 1 defdecode) 59)
17544 (setq def (apply 'encode-time defdecode)
17545 defdecode (decode-time def)))))
17546 (calendar-move-hook nil)
17547 (view-diary-entries-initially nil)
17548 (view-calendar-holidays-initially nil)
17549 (timestr (format-time-string
17550 (if with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") def))
17551 (prompt (concat (if prompt (concat prompt " ") "")
17552 (format "Date+time [%s]: " timestr)))
17553 ans (org-ans0 "") org-ans1 org-ans2 final)
17555 (cond
17556 (from-string (setq ans from-string))
17557 (org-read-date-popup-calendar
17558 (save-excursion
17559 (save-window-excursion
17560 (calendar)
17561 (calendar-forward-day (- (time-to-days def)
17562 (calendar-absolute-from-gregorian
17563 (calendar-current-date))))
17564 (org-eval-in-calendar nil t)
17565 (let* ((old-map (current-local-map))
17566 (map (copy-keymap calendar-mode-map))
17567 (minibuffer-local-map (copy-keymap minibuffer-local-map)))
17568 (org-defkey map (kbd "RET") 'org-calendar-select)
17569 (org-defkey map (if (featurep 'xemacs) [button1] [mouse-1])
17570 'org-calendar-select-mouse)
17571 (org-defkey map (if (featurep 'xemacs) [button2] [mouse-2])
17572 'org-calendar-select-mouse)
17573 (org-defkey minibuffer-local-map [(meta shift left)]
17574 (lambda () (interactive)
17575 (org-eval-in-calendar '(calendar-backward-month 1))))
17576 (org-defkey minibuffer-local-map [(meta shift right)]
17577 (lambda () (interactive)
17578 (org-eval-in-calendar '(calendar-forward-month 1))))
17579 (org-defkey minibuffer-local-map [(meta shift up)]
17580 (lambda () (interactive)
17581 (org-eval-in-calendar '(calendar-backward-year 1))))
17582 (org-defkey minibuffer-local-map [(meta shift down)]
17583 (lambda () (interactive)
17584 (org-eval-in-calendar '(calendar-forward-year 1))))
17585 (org-defkey minibuffer-local-map [(shift up)]
17586 (lambda () (interactive)
17587 (org-eval-in-calendar '(calendar-backward-week 1))))
17588 (org-defkey minibuffer-local-map [(shift down)]
17589 (lambda () (interactive)
17590 (org-eval-in-calendar '(calendar-forward-week 1))))
17591 (org-defkey minibuffer-local-map [(shift left)]
17592 (lambda () (interactive)
17593 (org-eval-in-calendar '(calendar-backward-day 1))))
17594 (org-defkey minibuffer-local-map [(shift right)]
17595 (lambda () (interactive)
17596 (org-eval-in-calendar '(calendar-forward-day 1))))
17597 (org-defkey minibuffer-local-map ">"
17598 (lambda () (interactive)
17599 (org-eval-in-calendar '(scroll-calendar-left 1))))
17600 (org-defkey minibuffer-local-map "<"
17601 (lambda () (interactive)
17602 (org-eval-in-calendar '(scroll-calendar-right 1))))
17603 (unwind-protect
17604 (progn
17605 (use-local-map map)
17606 (add-hook 'post-command-hook 'org-read-date-display)
17607 (setq org-ans0 (read-string prompt default-input nil nil))
17608 ;; org-ans0: from prompt
17609 ;; org-ans1: from mouse click
17610 ;; org-ans2: from calendar motion
17611 (setq ans (concat org-ans0 " " (or org-ans1 org-ans2))))
17612 (remove-hook 'post-command-hook 'org-read-date-display)
17613 (use-local-map old-map)
17614 (when org-read-date-overlay
17615 (org-delete-overlay org-read-date-overlay)
17616 (setq org-read-date-overlay nil)))))))
17618 (t ; Naked prompt only
17619 (unwind-protect
17620 (setq ans (read-string prompt default-input nil timestr))
17621 (when org-read-date-overlay
17622 (org-delete-overlay org-read-date-overlay)
17623 (setq org-read-date-overlay nil)))))
17625 (setq final (org-read-date-analyze ans def defdecode))
17627 (if to-time
17628 (apply 'encode-time final)
17629 (if (and (boundp 'org-time-was-given) org-time-was-given)
17630 (format "%04d-%02d-%02d %02d:%02d"
17631 (nth 5 final) (nth 4 final) (nth 3 final)
17632 (nth 2 final) (nth 1 final))
17633 (format "%04d-%02d-%02d" (nth 5 final) (nth 4 final) (nth 3 final))))))
17634 (defvar def)
17635 (defvar defdecode)
17636 (defvar with-time)
17637 (defun org-read-date-display ()
17638 "Display the currrent date prompt interpretation in the minibuffer."
17639 (when org-read-date-display-live
17640 (when org-read-date-overlay
17641 (org-delete-overlay org-read-date-overlay))
17642 (let ((p (point)))
17643 (end-of-line 1)
17644 (while (not (equal (buffer-substring
17645 (max (point-min) (- (point) 4)) (point))
17646 " "))
17647 (insert " "))
17648 (goto-char p))
17649 (let* ((ans (concat (buffer-substring (point-at-bol) (point-max))
17650 " " (or org-ans1 org-ans2)))
17651 (org-end-time-was-given nil)
17652 (f (org-read-date-analyze ans def defdecode))
17653 (fmts (if org-dcst
17654 org-time-stamp-custom-formats
17655 org-time-stamp-formats))
17656 (fmt (if (or with-time
17657 (and (boundp 'org-time-was-given) org-time-was-given))
17658 (cdr fmts)
17659 (car fmts)))
17660 (txt (concat "=> " (format-time-string fmt (apply 'encode-time f)))))
17661 (when (and org-end-time-was-given
17662 (string-match org-plain-time-of-day-regexp txt))
17663 (setq txt (concat (substring txt 0 (match-end 0)) "-"
17664 org-end-time-was-given
17665 (substring txt (match-end 0)))))
17666 (setq org-read-date-overlay
17667 (make-overlay (1- (point-at-eol)) (point-at-eol)))
17668 (org-overlay-display org-read-date-overlay txt 'secondary-selection))))
17670 (defun org-read-date-analyze (ans def defdecode)
17671 "Analyze the combined answer of the date prompt."
17672 ;; FIXME: cleanup and comment
17673 (let (delta deltan deltaw deltadef year month day
17674 hour minute second wday pm h2 m2 tl wday1
17675 iso-year iso-weekday iso-week iso-year iso-date)
17677 (when (setq delta (org-read-date-get-relative ans (current-time) def))
17678 (setq ans (replace-match "" t t ans)
17679 deltan (car delta)
17680 deltaw (nth 1 delta)
17681 deltadef (nth 2 delta)))
17683 ;; Check if there is an iso week date in there
17684 ;; If yes, sore the info and ostpone interpreting it until the rest
17685 ;; of the parsing is done
17686 (when (string-match "\\<\\(?:\\([0-9]+\\)-\\)?[wW]\\([0-9]\\{1,2\\}\\)\\(?:-\\([0-6]\\)\\)?\\([ \t]\\|$\\)" ans)
17687 (setq iso-year (if (match-end 1) (org-small-year-to-year (string-to-number (match-string 1 ans))))
17688 iso-weekday (if (match-end 3) (string-to-number (match-string 3 ans)))
17689 iso-week (string-to-number (match-string 2 ans)))
17690 (setq ans (replace-match "" t t ans)))
17692 ;; Help matching ISO dates with single digit month ot day, like 2006-8-11.
17693 (when (string-match
17694 "^ *\\(\\([0-9]+\\)-\\)?\\([0-1]?[0-9]\\)-\\([0-3]?[0-9]\\)\\([^-0-9]\\|$\\)" ans)
17695 (setq year (if (match-end 2)
17696 (string-to-number (match-string 2 ans))
17697 (string-to-number (format-time-string "%Y")))
17698 month (string-to-number (match-string 3 ans))
17699 day (string-to-number (match-string 4 ans)))
17700 (if (< year 100) (setq year (+ 2000 year)))
17701 (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
17702 t nil ans)))
17703 ;; Help matching am/pm times, because `parse-time-string' does not do that.
17704 ;; If there is a time with am/pm, and *no* time without it, we convert
17705 ;; so that matching will be successful.
17706 (loop for i from 1 to 2 do ; twice, for end time as well
17707 (when (and (not (string-match "\\(\\`\\|[^+]\\)[012]?[0-9]:[0-9][0-9]\\([ \t\n]\\|$\\)" ans))
17708 (string-match "\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\(am\\|AM\\|pm\\|PM\\)\\>" ans))
17709 (setq hour (string-to-number (match-string 1 ans))
17710 minute (if (match-end 3)
17711 (string-to-number (match-string 3 ans))
17713 pm (equal ?p
17714 (string-to-char (downcase (match-string 4 ans)))))
17715 (if (and (= hour 12) (not pm))
17716 (setq hour 0)
17717 (if (and pm (< hour 12)) (setq hour (+ 12 hour))))
17718 (setq ans (replace-match (format "%02d:%02d" hour minute)
17719 t t ans))))
17721 ;; Check if a time range is given as a duration
17722 (when (string-match "\\([012]?[0-9]\\):\\([0-6][0-9]\\)\\+\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?" ans)
17723 (setq hour (string-to-number (match-string 1 ans))
17724 h2 (+ hour (string-to-number (match-string 3 ans)))
17725 minute (string-to-number (match-string 2 ans))
17726 m2 (+ minute (if (match-end 5) (string-to-number
17727 (match-string 5 ans))0)))
17728 (if (>= m2 60) (setq h2 (1+ h2) m2 (- m2 60)))
17729 (setq ans (replace-match (format "%02d:%02d-%02d:%02d" hour minute h2 m2)
17730 t t ans)))
17732 ;; Check if there is a time range
17733 (when (boundp 'org-end-time-was-given)
17734 (setq org-time-was-given nil)
17735 (when (and (string-match org-plain-time-of-day-regexp ans)
17736 (match-end 8))
17737 (setq org-end-time-was-given (match-string 8 ans))
17738 (setq ans (concat (substring ans 0 (match-beginning 7))
17739 (substring ans (match-end 7))))))
17741 (setq tl (parse-time-string ans)
17742 day (or (nth 3 tl) (nth 3 defdecode))
17743 month (or (nth 4 tl)
17744 (if (and org-read-date-prefer-future
17745 (nth 3 tl) (< (nth 3 tl) (nth 3 defdecode)))
17746 (1+ (nth 4 defdecode))
17747 (nth 4 defdecode)))
17748 year (or (nth 5 tl)
17749 (if (and org-read-date-prefer-future
17750 (nth 4 tl) (< (nth 4 tl) (nth 4 defdecode)))
17751 (1+ (nth 5 defdecode))
17752 (nth 5 defdecode)))
17753 hour (or (nth 2 tl) (nth 2 defdecode))
17754 minute (or (nth 1 tl) (nth 1 defdecode))
17755 second (or (nth 0 tl) 0)
17756 wday (nth 6 tl))
17758 ;; Special date definitions below
17759 (cond
17760 (iso-week
17761 ;; There was an iso week
17762 (setq year (or iso-year year)
17763 day (or iso-weekday wday 1)
17764 wday nil ; to make sure that the trigger below does not match
17765 iso-date (calendar-gregorian-from-absolute
17766 (calendar-absolute-from-iso
17767 (list iso-week day year))))
17768 ; FIXME: Should we also push ISO weeks into the future?
17769 ; (when (and org-read-date-prefer-future
17770 ; (not iso-year)
17771 ; (< (calendar-absolute-from-gregorian iso-date)
17772 ; (time-to-days (current-time))))
17773 ; (setq year (1+ year)
17774 ; iso-date (calendar-gregorian-from-absolute
17775 ; (calendar-absolute-from-iso
17776 ; (list iso-week day year)))))
17777 (setq month (car iso-date)
17778 year (nth 2 iso-date)
17779 day (nth 1 iso-date)))
17780 (deltan
17781 (unless deltadef
17782 (let ((now (decode-time (current-time))))
17783 (setq day (nth 3 now) month (nth 4 now) year (nth 5 now))))
17784 (cond ((member deltaw '("d" "")) (setq day (+ day deltan)))
17785 ((equal deltaw "w") (setq day (+ day (* 7 deltan))))
17786 ((equal deltaw "m") (setq month (+ month deltan)))
17787 ((equal deltaw "y") (setq year (+ year deltan)))))
17788 ((and wday (not (nth 3 tl)))
17789 ;; Weekday was given, but no day, so pick that day in the week
17790 ;; on or after the derived date.
17791 (setq wday1 (nth 6 (decode-time (encode-time 0 0 0 day month year))))
17792 (unless (equal wday wday1)
17793 (setq day (+ day (% (- wday wday1 -7) 7))))))
17794 (if (and (boundp 'org-time-was-given)
17795 (nth 2 tl))
17796 (setq org-time-was-given t))
17797 (if (< year 100) (setq year (+ 2000 year)))
17798 (if (< year 1970) (setq year (nth 5 defdecode))) ; not representable
17799 (list second minute hour day month year)))
17801 (defvar parse-time-weekdays)
17803 (defun org-read-date-get-relative (s today default)
17804 "Check string S for special relative date string.
17805 TODAY and DEFAULT are internal times, for today and for a default.
17806 Return shift list (N what def-flag)
17807 WHAT is \"d\", \"w\", \"m\", or \"y\" for day, week, month, year.
17808 N is the number of WHATs to shift.
17809 DEF-FLAG is t when a double ++ or -- indicates shift relative to
17810 the DEFAULT date rather than TODAY."
17811 (when (string-match
17812 (concat
17813 "\\`[ \t]*\\([-+]\\{1,2\\}\\)"
17814 "\\([0-9]+\\)?"
17815 "\\([dwmy]\\|\\(" (mapconcat 'car parse-time-weekdays "\\|") "\\)\\)?"
17816 "\\([ \t]\\|$\\)") s)
17817 (let* ((dir (if (match-end 1)
17818 (string-to-char (substring (match-string 1 s) -1))
17819 ?+))
17820 (rel (and (match-end 1) (= 2 (- (match-end 1) (match-beginning 1)))))
17821 (n (if (match-end 2) (string-to-number (match-string 2 s)) 1))
17822 (what (if (match-end 3) (match-string 3 s) "d"))
17823 (wday1 (cdr (assoc (downcase what) parse-time-weekdays)))
17824 (date (if rel default today))
17825 (wday (nth 6 (decode-time date)))
17826 delta)
17827 (if wday1
17828 (progn
17829 (setq delta (mod (+ 7 (- wday1 wday)) 7))
17830 (if (= dir ?-) (setq delta (- delta 7)))
17831 (if (> n 1) (setq delta (+ delta (* (1- n) (if (= dir ?-) -7 7)))))
17832 (list delta "d" rel))
17833 (list (* n (if (= dir ?-) -1 1)) what rel)))))
17835 (defun org-eval-in-calendar (form &optional keepdate)
17836 "Eval FORM in the calendar window and return to current window.
17837 Also, store the cursor date in variable org-ans2."
17838 (let ((sw (selected-window)))
17839 (select-window (get-buffer-window "*Calendar*"))
17840 (eval form)
17841 (when (and (not keepdate) (calendar-cursor-to-date))
17842 (let* ((date (calendar-cursor-to-date))
17843 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
17844 (setq org-ans2 (format-time-string "%Y-%m-%d" time))))
17845 (org-move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer))
17846 (select-window sw)))
17848 ; ;; Update the prompt to show new default date
17849 ; (save-excursion
17850 ; (goto-char (point-min))
17851 ; (when (and org-ans2
17852 ; (re-search-forward "\\[[-0-9]+\\]" nil t)
17853 ; (get-text-property (match-end 0) 'field))
17854 ; (let ((inhibit-read-only t))
17855 ; (replace-match (concat "[" org-ans2 "]") t t)
17856 ; (add-text-properties (point-min) (1+ (match-end 0))
17857 ; (text-properties-at (1+ (point-min)))))))))
17859 (defun org-calendar-select ()
17860 "Return to `org-read-date' with the date currently selected.
17861 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
17862 (interactive)
17863 (when (calendar-cursor-to-date)
17864 (let* ((date (calendar-cursor-to-date))
17865 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
17866 (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
17867 (if (active-minibuffer-window) (exit-minibuffer))))
17869 (defun org-insert-time-stamp (time &optional with-hm inactive pre post extra)
17870 "Insert a date stamp for the date given by the internal TIME.
17871 WITH-HM means, use the stamp format that includes the time of the day.
17872 INACTIVE means use square brackets instead of angular ones, so that the
17873 stamp will not contribute to the agenda.
17874 PRE and POST are optional strings to be inserted before and after the
17875 stamp.
17876 The command returns the inserted time stamp."
17877 (let ((fmt (funcall (if with-hm 'cdr 'car) org-time-stamp-formats))
17878 stamp)
17879 (if inactive (setq fmt (concat "[" (substring fmt 1 -1) "]")))
17880 (insert-before-markers (or pre ""))
17881 (insert-before-markers (setq stamp (format-time-string fmt time)))
17882 (when (listp extra)
17883 (setq extra (car extra))
17884 (if (and (stringp extra)
17885 (string-match "\\([0-9]+\\):\\([0-9]+\\)" extra))
17886 (setq extra (format "-%02d:%02d"
17887 (string-to-number (match-string 1 extra))
17888 (string-to-number (match-string 2 extra))))
17889 (setq extra nil)))
17890 (when extra
17891 (backward-char 1)
17892 (insert-before-markers extra)
17893 (forward-char 1))
17894 (insert-before-markers (or post ""))
17895 stamp))
17897 (defun org-toggle-time-stamp-overlays ()
17898 "Toggle the use of custom time stamp formats."
17899 (interactive)
17900 (setq org-display-custom-times (not org-display-custom-times))
17901 (unless org-display-custom-times
17902 (let ((p (point-min)) (bmp (buffer-modified-p)))
17903 (while (setq p (next-single-property-change p 'display))
17904 (if (and (get-text-property p 'display)
17905 (eq (get-text-property p 'face) 'org-date))
17906 (remove-text-properties
17907 p (setq p (next-single-property-change p 'display))
17908 '(display t))))
17909 (set-buffer-modified-p bmp)))
17910 (if (featurep 'xemacs)
17911 (remove-text-properties (point-min) (point-max) '(end-glyph t)))
17912 (org-restart-font-lock)
17913 (setq org-table-may-need-update t)
17914 (if org-display-custom-times
17915 (message "Time stamps are overlayed with custom format")
17916 (message "Time stamp overlays removed")))
17918 (defun org-display-custom-time (beg end)
17919 "Overlay modified time stamp format over timestamp between BED and END."
17920 (let* ((ts (buffer-substring beg end))
17921 t1 w1 with-hm tf time str w2 (off 0))
17922 (save-match-data
17923 (setq t1 (org-parse-time-string ts t))
17924 (if (string-match "\\(-[0-9]+:[0-9]+\\)?\\( [.+]?\\+[0-9]+[dwmy]\\)?\\'" ts)
17925 (setq off (- (match-end 0) (match-beginning 0)))))
17926 (setq end (- end off))
17927 (setq w1 (- end beg)
17928 with-hm (and (nth 1 t1) (nth 2 t1))
17929 tf (funcall (if with-hm 'cdr 'car) org-time-stamp-custom-formats)
17930 time (org-fix-decoded-time t1)
17931 str (org-add-props
17932 (format-time-string
17933 (substring tf 1 -1) (apply 'encode-time time))
17934 nil 'mouse-face 'highlight)
17935 w2 (length str))
17936 (if (not (= w2 w1))
17937 (add-text-properties (1+ beg) (+ 2 beg)
17938 (list 'org-dwidth t 'org-dwidth-n (- w1 w2))))
17939 (if (featurep 'xemacs)
17940 (progn
17941 (put-text-property beg end 'invisible t)
17942 (put-text-property beg end 'end-glyph (make-glyph str)))
17943 (put-text-property beg end 'display str))))
17945 (defun org-translate-time (string)
17946 "Translate all timestamps in STRING to custom format.
17947 But do this only if the variable `org-display-custom-times' is set."
17948 (when org-display-custom-times
17949 (save-match-data
17950 (let* ((start 0)
17951 (re org-ts-regexp-both)
17952 t1 with-hm inactive tf time str beg end)
17953 (while (setq start (string-match re string start))
17954 (setq beg (match-beginning 0)
17955 end (match-end 0)
17956 t1 (save-match-data
17957 (org-parse-time-string (substring string beg end) t))
17958 with-hm (and (nth 1 t1) (nth 2 t1))
17959 inactive (equal (substring string beg (1+ beg)) "[")
17960 tf (funcall (if with-hm 'cdr 'car)
17961 org-time-stamp-custom-formats)
17962 time (org-fix-decoded-time t1)
17963 str (format-time-string
17964 (concat
17965 (if inactive "[" "<") (substring tf 1 -1)
17966 (if inactive "]" ">"))
17967 (apply 'encode-time time))
17968 string (replace-match str t t string)
17969 start (+ start (length str)))))))
17970 string)
17972 (defun org-fix-decoded-time (time)
17973 "Set 0 instead of nil for the first 6 elements of time.
17974 Don't touch the rest."
17975 (let ((n 0))
17976 (mapcar (lambda (x) (if (< (setq n (1+ n)) 7) (or x 0) x)) time)))
17978 (defun org-days-to-time (timestamp-string)
17979 "Difference between TIMESTAMP-STRING and now in days."
17980 (- (time-to-days (org-time-string-to-time timestamp-string))
17981 (time-to-days (current-time))))
17983 (defun org-deadline-close (timestamp-string &optional ndays)
17984 "Is the time in TIMESTAMP-STRING close to the current date?"
17985 (setq ndays (or ndays (org-get-wdays timestamp-string)))
17986 (and (< (org-days-to-time timestamp-string) ndays)
17987 (not (org-entry-is-done-p))))
17989 (defun org-get-wdays (ts)
17990 "Get the deadline lead time appropriate for timestring TS."
17991 (cond
17992 ((<= org-deadline-warning-days 0)
17993 ;; 0 or negative, enforce this value no matter what
17994 (- org-deadline-warning-days))
17995 ((string-match "-\\([0-9]+\\)\\([dwmy]\\)\\(\\'\\|>\\)" ts)
17996 ;; lead time is specified.
17997 (floor (* (string-to-number (match-string 1 ts))
17998 (cdr (assoc (match-string 2 ts)
17999 '(("d" . 1) ("w" . 7)
18000 ("m" . 30.4) ("y" . 365.25)))))))
18001 ;; go for the default.
18002 (t org-deadline-warning-days)))
18004 (defun org-calendar-select-mouse (ev)
18005 "Return to `org-read-date' with the date currently selected.
18006 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
18007 (interactive "e")
18008 (mouse-set-point ev)
18009 (when (calendar-cursor-to-date)
18010 (let* ((date (calendar-cursor-to-date))
18011 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
18012 (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
18013 (if (active-minibuffer-window) (exit-minibuffer))))
18015 (defun org-check-deadlines (ndays)
18016 "Check if there are any deadlines due or past due.
18017 A deadline is considered due if it happens within `org-deadline-warning-days'
18018 days from today's date. If the deadline appears in an entry marked DONE,
18019 it is not shown. The prefix arg NDAYS can be used to test that many
18020 days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are shown."
18021 (interactive "P")
18022 (let* ((org-warn-days
18023 (cond
18024 ((equal ndays '(4)) 100000)
18025 (ndays (prefix-numeric-value ndays))
18026 (t (abs org-deadline-warning-days))))
18027 (case-fold-search nil)
18028 (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>"))
18029 (callback
18030 (lambda () (org-deadline-close (match-string 1) org-warn-days))))
18032 (message "%d deadlines past-due or due within %d days"
18033 (org-occur regexp nil callback)
18034 org-warn-days)))
18036 (defun org-check-before-date (date)
18037 "Check if there are deadlines or scheduled entries before DATE."
18038 (interactive (list (org-read-date)))
18039 (let ((case-fold-search nil)
18040 (regexp (concat "\\<\\(" org-deadline-string
18041 "\\|" org-scheduled-string
18042 "\\) *<\\([^>]+\\)>"))
18043 (callback
18044 (lambda () (time-less-p
18045 (org-time-string-to-time (match-string 2))
18046 (org-time-string-to-time date)))))
18047 (message "%d entries before %s"
18048 (org-occur regexp nil callback) date)))
18050 (defun org-evaluate-time-range (&optional to-buffer)
18051 "Evaluate a time range by computing the difference between start and end.
18052 Normally the result is just printed in the echo area, but with prefix arg
18053 TO-BUFFER, the result is inserted just after the date stamp into the buffer.
18054 If the time range is actually in a table, the result is inserted into the
18055 next column.
18056 For time difference computation, a year is assumed to be exactly 365
18057 days in order to avoid rounding problems."
18058 (interactive "P")
18060 (org-clock-update-time-maybe)
18061 (save-excursion
18062 (unless (org-at-date-range-p t)
18063 (goto-char (point-at-bol))
18064 (re-search-forward org-tr-regexp-both (point-at-eol) t))
18065 (if (not (org-at-date-range-p t))
18066 (error "Not at a time-stamp range, and none found in current line")))
18067 (let* ((ts1 (match-string 1))
18068 (ts2 (match-string 2))
18069 (havetime (or (> (length ts1) 15) (> (length ts2) 15)))
18070 (match-end (match-end 0))
18071 (time1 (org-time-string-to-time ts1))
18072 (time2 (org-time-string-to-time ts2))
18073 (t1 (time-to-seconds time1))
18074 (t2 (time-to-seconds time2))
18075 (diff (abs (- t2 t1)))
18076 (negative (< (- t2 t1) 0))
18077 ;; (ys (floor (* 365 24 60 60)))
18078 (ds (* 24 60 60))
18079 (hs (* 60 60))
18080 (fy "%dy %dd %02d:%02d")
18081 (fy1 "%dy %dd")
18082 (fd "%dd %02d:%02d")
18083 (fd1 "%dd")
18084 (fh "%02d:%02d")
18085 y d h m align)
18086 (if havetime
18087 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
18089 d (floor (/ diff ds)) diff (mod diff ds)
18090 h (floor (/ diff hs)) diff (mod diff hs)
18091 m (floor (/ diff 60)))
18092 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
18094 d (floor (+ (/ diff ds) 0.5))
18095 h 0 m 0))
18096 (if (not to-buffer)
18097 (message "%s" (org-make-tdiff-string y d h m))
18098 (if (org-at-table-p)
18099 (progn
18100 (goto-char match-end)
18101 (setq align t)
18102 (and (looking-at " *|") (goto-char (match-end 0))))
18103 (goto-char match-end))
18104 (if (looking-at
18105 "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]")
18106 (replace-match ""))
18107 (if negative (insert " -"))
18108 (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m))
18109 (if (> d 0) (insert " " (format (if havetime fd fd1) d h m))
18110 (insert " " (format fh h m))))
18111 (if align (org-table-align))
18112 (message "Time difference inserted")))))
18114 (defun org-make-tdiff-string (y d h m)
18115 (let ((fmt "")
18116 (l nil))
18117 (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ")
18118 l (push y l)))
18119 (if (> d 0) (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ")
18120 l (push d l)))
18121 (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ")
18122 l (push h l)))
18123 (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ")
18124 l (push m l)))
18125 (apply 'format fmt (nreverse l))))
18127 (defun org-time-string-to-time (s)
18128 (apply 'encode-time (org-parse-time-string s)))
18130 (defun org-time-string-to-absolute (s &optional daynr prefer)
18131 "Convert a time stamp to an absolute day number.
18132 If there is a specifyer for a cyclic time stamp, get the closest date to
18133 DAYNR."
18134 (cond
18135 ((and daynr (string-match "\\`%%\\((.*)\\)" s))
18136 (if (org-diary-sexp-entry (match-string 1 s) "" date)
18137 daynr
18138 (+ daynr 1000)))
18139 ((and daynr (string-match "\\+[0-9]+[dwmy]" s))
18140 (org-closest-date s (if (and (boundp 'daynr) (integerp daynr)) daynr
18141 (time-to-days (current-time))) (match-string 0 s)
18142 prefer))
18143 (t (time-to-days (apply 'encode-time (org-parse-time-string s))))))
18145 (defun org-time-from-absolute (d)
18146 "Return the time corresponding to date D.
18147 D may be an absolute day number, or a calendar-type list (month day year)."
18148 (if (numberp d) (setq d (calendar-gregorian-from-absolute d)))
18149 (encode-time 0 0 0 (nth 1 d) (car d) (nth 2 d)))
18151 (defun org-calendar-holiday ()
18152 "List of holidays, for Diary display in Org-mode."
18153 (require 'holidays)
18154 (let ((hl (funcall
18155 (if (fboundp 'calendar-check-holidays)
18156 'calendar-check-holidays 'check-calendar-holidays) date)))
18157 (if hl (mapconcat 'identity hl "; "))))
18159 (defun org-diary-sexp-entry (sexp entry date)
18160 "Process a SEXP diary ENTRY for DATE."
18161 (require 'diary-lib)
18162 (let ((result (if calendar-debug-sexp
18163 (let ((stack-trace-on-error t))
18164 (eval (car (read-from-string sexp))))
18165 (condition-case nil
18166 (eval (car (read-from-string sexp)))
18167 (error
18168 (beep)
18169 (message "Bad sexp at line %d in %s: %s"
18170 (org-current-line)
18171 (buffer-file-name) sexp)
18172 (sleep-for 2))))))
18173 (cond ((stringp result) result)
18174 ((and (consp result)
18175 (stringp (cdr result))) (cdr result))
18176 (result entry)
18177 (t nil))))
18179 (defun org-diary-to-ical-string (frombuf)
18180 "Get iCalendar entries from diary entries in buffer FROMBUF.
18181 This uses the icalendar.el library."
18182 (let* ((tmpdir (if (featurep 'xemacs)
18183 (temp-directory)
18184 temporary-file-directory))
18185 (tmpfile (make-temp-name
18186 (expand-file-name "orgics" tmpdir)))
18187 buf rtn b e)
18188 (save-excursion
18189 (set-buffer frombuf)
18190 (icalendar-export-region (point-min) (point-max) tmpfile)
18191 (setq buf (find-buffer-visiting tmpfile))
18192 (set-buffer buf)
18193 (goto-char (point-min))
18194 (if (re-search-forward "^BEGIN:VEVENT" nil t)
18195 (setq b (match-beginning 0)))
18196 (goto-char (point-max))
18197 (if (re-search-backward "^END:VEVENT" nil t)
18198 (setq e (match-end 0)))
18199 (setq rtn (if (and b e) (concat (buffer-substring b e) "\n") "")))
18200 (kill-buffer buf)
18201 (kill-buffer frombuf)
18202 (delete-file tmpfile)
18203 rtn))
18205 (defun org-closest-date (start current change prefer)
18206 "Find the date closest to CURRENT that is consistent with START and CHANGE.
18207 When PREFER is `past' return a date that is either CURRENT or past.
18208 When PREFER is `future', return a date that is either CURRENT or future."
18209 ;; Make the proper lists from the dates
18210 (catch 'exit
18211 (let ((a1 '(("d" . day) ("w" . week) ("m" . month) ("y" . year)))
18212 dn dw sday cday n1 n2
18213 d m y y1 y2 date1 date2 nmonths nm ny m2)
18215 (setq start (org-date-to-gregorian start)
18216 current (org-date-to-gregorian
18217 (if org-agenda-repeating-timestamp-show-all
18218 current
18219 (time-to-days (current-time))))
18220 sday (calendar-absolute-from-gregorian start)
18221 cday (calendar-absolute-from-gregorian current))
18223 (if (<= cday sday) (throw 'exit sday))
18225 (if (string-match "\\(\\+[0-9]+\\)\\([dwmy]\\)" change)
18226 (setq dn (string-to-number (match-string 1 change))
18227 dw (cdr (assoc (match-string 2 change) a1)))
18228 (error "Invalid change specifyer: %s" change))
18229 (if (eq dw 'week) (setq dw 'day dn (* 7 dn)))
18230 (cond
18231 ((eq dw 'day)
18232 (setq n1 (+ sday (* dn (floor (/ (- cday sday) dn))))
18233 n2 (+ n1 dn)))
18234 ((eq dw 'year)
18235 (setq d (nth 1 start) m (car start) y1 (nth 2 start) y2 (nth 2 current))
18236 (setq y1 (+ (* (floor (/ (- y2 y1) dn)) dn) y1))
18237 (setq date1 (list m d y1)
18238 n1 (calendar-absolute-from-gregorian date1)
18239 date2 (list m d (+ y1 (* (if (< n1 cday) 1 -1) dn)))
18240 n2 (calendar-absolute-from-gregorian date2)))
18241 ((eq dw 'month)
18242 ;; approx number of month between the tow dates
18243 (setq nmonths (floor (/ (- cday sday) 30.436875)))
18244 ;; How often does dn fit in there?
18245 (setq d (nth 1 start) m (car start) y (nth 2 start)
18246 nm (* dn (max 0 (1- (floor (/ nmonths dn)))))
18247 m (+ m nm)
18248 ny (floor (/ m 12))
18249 y (+ y ny)
18250 m (- m (* ny 12)))
18251 (while (> m 12) (setq m (- m 12) y (1+ y)))
18252 (setq n1 (calendar-absolute-from-gregorian (list m d y)))
18253 (setq m2 (+ m dn) y2 y)
18254 (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
18255 (setq n2 (calendar-absolute-from-gregorian (list m2 d y2)))
18256 (while (< n2 cday)
18257 (setq n1 n2 m m2 y y2)
18258 (setq m2 (+ m dn) y2 y)
18259 (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
18260 (setq n2 (calendar-absolute-from-gregorian (list m2 d y2))))))
18262 (if org-agenda-repeating-timestamp-show-all
18263 (cond
18264 ((eq prefer 'past) n1)
18265 ((eq prefer 'future) (if (= cday n1) n1 n2))
18266 (t (if (> (abs (- cday n1)) (abs (- cday n2))) n2 n1)))
18267 (cond
18268 ((eq prefer 'past) n1)
18269 ((eq prefer 'future) (if (= cday n1) n1 n2))
18270 (t (if (= cday n1) n1 n2)))))))
18272 (defun org-date-to-gregorian (date)
18273 "Turn any specification of DATE into a gregorian date for the calendar."
18274 (cond ((integerp date) (calendar-gregorian-from-absolute date))
18275 ((and (listp date) (= (length date) 3)) date)
18276 ((stringp date)
18277 (setq date (org-parse-time-string date))
18278 (list (nth 4 date) (nth 3 date) (nth 5 date)))
18279 ((listp date)
18280 (list (nth 4 date) (nth 3 date) (nth 5 date)))))
18282 (defun org-parse-time-string (s &optional nodefault)
18283 "Parse the standard Org-mode time string.
18284 This should be a lot faster than the normal `parse-time-string'.
18285 If time is not given, defaults to 0:00. However, with optional NODEFAULT,
18286 hour and minute fields will be nil if not given."
18287 (if (string-match org-ts-regexp0 s)
18288 (list 0
18289 (if (or (match-beginning 8) (not nodefault))
18290 (string-to-number (or (match-string 8 s) "0")))
18291 (if (or (match-beginning 7) (not nodefault))
18292 (string-to-number (or (match-string 7 s) "0")))
18293 (string-to-number (match-string 4 s))
18294 (string-to-number (match-string 3 s))
18295 (string-to-number (match-string 2 s))
18296 nil nil nil)
18297 (make-list 9 0)))
18299 (defun org-timestamp-up (&optional arg)
18300 "Increase the date item at the cursor by one.
18301 If the cursor is on the year, change the year. If it is on the month or
18302 the day, change that.
18303 With prefix ARG, change by that many units."
18304 (interactive "p")
18305 (org-timestamp-change (prefix-numeric-value arg)))
18307 (defun org-timestamp-down (&optional arg)
18308 "Decrease the date item at the cursor by one.
18309 If the cursor is on the year, change the year. If it is on the month or
18310 the day, change that.
18311 With prefix ARG, change by that many units."
18312 (interactive "p")
18313 (org-timestamp-change (- (prefix-numeric-value arg))))
18315 (defun org-timestamp-up-day (&optional arg)
18316 "Increase the date in the time stamp by one day.
18317 With prefix ARG, change that many days."
18318 (interactive "p")
18319 (if (and (not (org-at-timestamp-p t))
18320 (org-on-heading-p))
18321 (org-todo 'up)
18322 (org-timestamp-change (prefix-numeric-value arg) 'day)))
18324 (defun org-timestamp-down-day (&optional arg)
18325 "Decrease the date in the time stamp by one day.
18326 With prefix ARG, change that many days."
18327 (interactive "p")
18328 (if (and (not (org-at-timestamp-p t))
18329 (org-on-heading-p))
18330 (org-todo 'down)
18331 (org-timestamp-change (- (prefix-numeric-value arg)) 'day)))
18333 (defsubst org-pos-in-match-range (pos n)
18334 (and (match-beginning n)
18335 (<= (match-beginning n) pos)
18336 (>= (match-end n) pos)))
18338 (defun org-at-timestamp-p (&optional inactive-ok)
18339 "Determine if the cursor is in or at a timestamp."
18340 (interactive)
18341 (let* ((tsr (if inactive-ok org-ts-regexp3 org-ts-regexp2))
18342 (pos (point))
18343 (ans (or (looking-at tsr)
18344 (save-excursion
18345 (skip-chars-backward "^[<\n\r\t")
18346 (if (> (point) (point-min)) (backward-char 1))
18347 (and (looking-at tsr)
18348 (> (- (match-end 0) pos) -1))))))
18349 (and ans
18350 (boundp 'org-ts-what)
18351 (setq org-ts-what
18352 (cond
18353 ((= pos (match-beginning 0)) 'bracket)
18354 ((= pos (1- (match-end 0))) 'bracket)
18355 ((org-pos-in-match-range pos 2) 'year)
18356 ((org-pos-in-match-range pos 3) 'month)
18357 ((org-pos-in-match-range pos 7) 'hour)
18358 ((org-pos-in-match-range pos 8) 'minute)
18359 ((or (org-pos-in-match-range pos 4)
18360 (org-pos-in-match-range pos 5)) 'day)
18361 ((and (> pos (or (match-end 8) (match-end 5)))
18362 (< pos (match-end 0)))
18363 (- pos (or (match-end 8) (match-end 5))))
18364 (t 'day))))
18365 ans))
18367 (defun org-toggle-timestamp-type ()
18368 "Toggle the type (<active> or [inactive]) of a time stamp."
18369 (interactive)
18370 (when (org-at-timestamp-p t)
18371 (save-excursion
18372 (goto-char (match-beginning 0))
18373 (insert (if (equal (char-after) ?<) "[" "<")) (delete-char 1)
18374 (goto-char (1- (match-end 0)))
18375 (insert (if (equal (char-after) ?>) "]" ">")) (delete-char 1))
18376 (message "Timestamp is now %sactive"
18377 (if (equal (char-before) ?>) "in" ""))))
18379 (defun org-timestamp-change (n &optional what)
18380 "Change the date in the time stamp at point.
18381 The date will be changed by N times WHAT. WHAT can be `day', `month',
18382 `year', `minute', `second'. If WHAT is not given, the cursor position
18383 in the timestamp determines what will be changed."
18384 (let ((pos (point))
18385 with-hm inactive
18386 (dm (max (nth 1 org-time-stamp-rounding-minutes) 1))
18387 org-ts-what
18388 extra rem
18389 ts time time0)
18390 (if (not (org-at-timestamp-p t))
18391 (error "Not at a timestamp"))
18392 (if (and (not what) (eq org-ts-what 'bracket))
18393 (org-toggle-timestamp-type)
18394 (if (and (not what) (not (eq org-ts-what 'day))
18395 org-display-custom-times
18396 (get-text-property (point) 'display)
18397 (not (get-text-property (1- (point)) 'display)))
18398 (setq org-ts-what 'day))
18399 (setq org-ts-what (or what org-ts-what)
18400 inactive (= (char-after (match-beginning 0)) ?\[)
18401 ts (match-string 0))
18402 (replace-match "")
18403 (if (string-match
18404 "\\(\\(-[012][0-9]:[0-5][0-9]\\)?\\( +[.+]?[-+][0-9]+[dwmy]\\)*\\)[]>]"
18406 (setq extra (match-string 1 ts)))
18407 (if (string-match "^.\\{10\\}.*?[0-9]+:[0-9][0-9]" ts)
18408 (setq with-hm t))
18409 (setq time0 (org-parse-time-string ts))
18410 (when (and (eq org-ts-what 'minute)
18411 (eq current-prefix-arg nil))
18412 (setq n (* dm (org-no-warnings (signum n))))
18413 (when (not (= 0 (setq rem (% (nth 1 time0) dm))))
18414 (setcar (cdr time0) (+ (nth 1 time0)
18415 (if (> n 0) (- rem) (- dm rem))))))
18416 (setq time
18417 (encode-time (or (car time0) 0)
18418 (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0))
18419 (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0))
18420 (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0))
18421 (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0))
18422 (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0))
18423 (nthcdr 6 time0)))
18424 (when (integerp org-ts-what)
18425 (setq extra (org-modify-ts-extra extra org-ts-what n dm)))
18426 (if (eq what 'calendar)
18427 (let ((cal-date (org-get-date-from-calendar)))
18428 (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month
18429 (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day
18430 (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year
18431 (setcar time0 (or (car time0) 0))
18432 (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
18433 (setcar (nthcdr 2 time0) (or (nth 2 time0) 0))
18434 (setq time (apply 'encode-time time0))))
18435 (setq org-last-changed-timestamp
18436 (org-insert-time-stamp time with-hm inactive nil nil extra))
18437 (org-clock-update-time-maybe)
18438 (goto-char pos)
18439 ;; Try to recenter the calendar window, if any
18440 (if (and org-calendar-follow-timestamp-change
18441 (get-buffer-window "*Calendar*" t)
18442 (memq org-ts-what '(day month year)))
18443 (org-recenter-calendar (time-to-days time))))))
18445 ;; FIXME: does not yet work for lead times
18446 (defun org-modify-ts-extra (s pos n dm)
18447 "Change the different parts of the lead-time and repeat fields in timestamp."
18448 (let ((idx '(("d" . 0) ("w" . 1) ("m" . 2) ("y" . 3) ("d" . -1) ("y" . 4)))
18449 ng h m new rem)
18450 (when (string-match "\\(-\\([012][0-9]\\):\\([0-5][0-9]\\)\\)?\\( +\\+\\([0-9]+\\)\\([dmwy]\\)\\)?\\( +-\\([0-9]+\\)\\([dmwy]\\)\\)?" s)
18451 (cond
18452 ((or (org-pos-in-match-range pos 2)
18453 (org-pos-in-match-range pos 3))
18454 (setq m (string-to-number (match-string 3 s))
18455 h (string-to-number (match-string 2 s)))
18456 (if (org-pos-in-match-range pos 2)
18457 (setq h (+ h n))
18458 (setq n (* dm (org-no-warnings (signum n))))
18459 (when (not (= 0 (setq rem (% m dm))))
18460 (setq m (+ m (if (> n 0) (- rem) (- dm rem)))))
18461 (setq m (+ m n)))
18462 (if (< m 0) (setq m (+ m 60) h (1- h)))
18463 (if (> m 59) (setq m (- m 60) h (1+ h)))
18464 (setq h (min 24 (max 0 h)))
18465 (setq ng 1 new (format "-%02d:%02d" h m)))
18466 ((org-pos-in-match-range pos 6)
18467 (setq ng 6 new (car (rassoc (+ n (cdr (assoc (match-string 6 s) idx))) idx))))
18468 ((org-pos-in-match-range pos 5)
18469 (setq ng 5 new (format "%d" (max 1 (+ n (string-to-number (match-string 5 s)))))))
18471 ((org-pos-in-match-range pos 9)
18472 (setq ng 9 new (car (rassoc (+ n (cdr (assoc (match-string 9 s) idx))) idx))))
18473 ((org-pos-in-match-range pos 8)
18474 (setq ng 8 new (format "%d" (max 0 (+ n (string-to-number (match-string 8 s))))))))
18476 (when ng
18477 (setq s (concat
18478 (substring s 0 (match-beginning ng))
18480 (substring s (match-end ng))))))
18483 (defun org-recenter-calendar (date)
18484 "If the calendar is visible, recenter it to DATE."
18485 (let* ((win (selected-window))
18486 (cwin (get-buffer-window "*Calendar*" t))
18487 (calendar-move-hook nil))
18488 (when cwin
18489 (select-window cwin)
18490 (calendar-goto-date (if (listp date) date
18491 (calendar-gregorian-from-absolute date)))
18492 (select-window win))))
18494 (defun org-goto-calendar (&optional arg)
18495 "Go to the Emacs calendar at the current date.
18496 If there is a time stamp in the current line, go to that date.
18497 A prefix ARG can be used to force the current date."
18498 (interactive "P")
18499 (let ((tsr org-ts-regexp) diff
18500 (calendar-move-hook nil)
18501 (view-calendar-holidays-initially nil)
18502 (view-diary-entries-initially nil))
18503 (if (or (org-at-timestamp-p)
18504 (save-excursion
18505 (beginning-of-line 1)
18506 (looking-at (concat ".*" tsr))))
18507 (let ((d1 (time-to-days (current-time)))
18508 (d2 (time-to-days
18509 (org-time-string-to-time (match-string 1)))))
18510 (setq diff (- d2 d1))))
18511 (calendar)
18512 (calendar-goto-today)
18513 (if (and diff (not arg)) (calendar-forward-day diff))))
18515 (defun org-get-date-from-calendar ()
18516 "Return a list (month day year) of date at point in calendar."
18517 (with-current-buffer "*Calendar*"
18518 (save-match-data
18519 (calendar-cursor-to-date))))
18521 (defun org-date-from-calendar ()
18522 "Insert time stamp corresponding to cursor date in *Calendar* buffer.
18523 If there is already a time stamp at the cursor position, update it."
18524 (interactive)
18525 (if (org-at-timestamp-p t)
18526 (org-timestamp-change 0 'calendar)
18527 (let ((cal-date (org-get-date-from-calendar)))
18528 (org-insert-time-stamp
18529 (encode-time 0 0 0 (nth 1 cal-date) (car cal-date) (nth 2 cal-date))))))
18531 (defvar appt-time-msg-list)
18533 ;;;###autoload
18534 (defun org-agenda-to-appt (&optional refresh filter)
18535 "Activate appointments found in `org-agenda-files'.
18536 With a \\[universal-argument] prefix, refresh the list of
18537 appointements.
18539 If FILTER is t, interactively prompt the user for a regular
18540 expression, and filter out entries that don't match it.
18542 If FILTER is a string, use this string as a regular expression
18543 for filtering entries out.
18545 FILTER can also be an alist with the car of each cell being
18546 either 'headline or 'category. For example:
18548 '((headline \"IMPORTANT\")
18549 (category \"Work\"))
18551 will only add headlines containing IMPORTANT or headlines
18552 belonging to the \"Work\" category."
18553 (interactive "P")
18554 (require 'calendar)
18555 (if refresh (setq appt-time-msg-list nil))
18556 (if (eq filter t)
18557 (setq filter (read-from-minibuffer "Regexp filter: ")))
18558 (let* ((cnt 0) ; count added events
18559 (org-agenda-new-buffers nil)
18560 (org-deadline-warning-days 0)
18561 (today (org-date-to-gregorian
18562 (time-to-days (current-time))))
18563 (files (org-agenda-files)) entries file)
18564 ;; Get all entries which may contain an appt
18565 (while (setq file (pop files))
18566 (setq entries
18567 (append entries
18568 (org-agenda-get-day-entries
18569 file today :timestamp :scheduled :deadline))))
18570 (setq entries (delq nil entries))
18571 ;; Map thru entries and find if we should filter them out
18572 (mapc
18573 (lambda(x)
18574 (let* ((evt (org-trim (get-text-property 1 'txt x)))
18575 (cat (get-text-property 1 'org-category x))
18576 (tod (get-text-property 1 'time-of-day x))
18577 (ok (or (null filter)
18578 (and (stringp filter) (string-match filter evt))
18579 (and (listp filter)
18580 (or (string-match
18581 (cadr (assoc 'category filter)) cat)
18582 (string-match
18583 (cadr (assoc 'headline filter)) evt))))))
18584 ;; FIXME: Shall we remove text-properties for the appt text?
18585 ;; (setq evt (set-text-properties 0 (length evt) nil evt))
18586 (when (and ok tod)
18587 (setq tod (number-to-string tod)
18588 tod (when (string-match
18589 "\\([0-9]\\{1,2\\}\\)\\([0-9]\\{2\\}\\)" tod)
18590 (concat (match-string 1 tod) ":"
18591 (match-string 2 tod))))
18592 (appt-add tod evt)
18593 (setq cnt (1+ cnt))))) entries)
18594 (org-release-buffers org-agenda-new-buffers)
18595 (if (eq cnt 0)
18596 (message "No event to add")
18597 (message "Added %d event%s for today" cnt (if (> cnt 1) "s" "")))))
18599 ;;; The clock for measuring work time.
18601 (defvar org-mode-line-string "")
18602 (put 'org-mode-line-string 'risky-local-variable t)
18604 (defvar org-mode-line-timer nil)
18605 (defvar org-clock-heading "")
18606 (defvar org-clock-start-time "")
18608 (defun org-update-mode-line ()
18609 (let* ((delta (- (time-to-seconds (current-time))
18610 (time-to-seconds org-clock-start-time)))
18611 (h (floor delta 3600))
18612 (m (floor (- delta (* 3600 h)) 60)))
18613 (setq org-mode-line-string
18614 (propertize (format "-[%d:%02d (%s)]" h m org-clock-heading)
18615 'help-echo "Org-mode clock is running"))
18616 (force-mode-line-update)))
18618 (defvar org-clock-marker (make-marker)
18619 "Marker recording the last clock-in.")
18620 (defvar org-clock-mode-line-entry nil
18621 "Information for the modeline about the running clock.")
18623 (defun org-clock-in ()
18624 "Start the clock on the current item.
18625 If necessary, clock-out of the currently active clock."
18626 (interactive)
18627 (org-clock-out t)
18628 (let (ts)
18629 (save-excursion
18630 (org-back-to-heading t)
18631 (when (and org-clock-in-switch-to-state
18632 (not (looking-at (concat outline-regexp "[ \t]*"
18633 org-clock-in-switch-to-state
18634 "\\>"))))
18635 (org-todo org-clock-in-switch-to-state))
18636 (if (and org-clock-heading-function
18637 (functionp org-clock-heading-function))
18638 (setq org-clock-heading (funcall org-clock-heading-function))
18639 (if (looking-at org-complex-heading-regexp)
18640 (setq org-clock-heading (match-string 4))
18641 (setq org-clock-heading "???")))
18642 (setq org-clock-heading (propertize org-clock-heading 'face nil))
18643 (org-clock-find-position)
18645 (insert "\n") (backward-char 1)
18646 (indent-relative)
18647 (insert org-clock-string " ")
18648 (setq org-clock-start-time (current-time))
18649 (setq ts (org-insert-time-stamp (current-time) 'with-hm 'inactive))
18650 (move-marker org-clock-marker (point) (buffer-base-buffer))
18651 (or global-mode-string (setq global-mode-string '("")))
18652 (or (memq 'org-mode-line-string global-mode-string)
18653 (setq global-mode-string
18654 (append global-mode-string '(org-mode-line-string))))
18655 (org-update-mode-line)
18656 (setq org-mode-line-timer (run-with-timer 60 60 'org-update-mode-line))
18657 (message "Clock started at %s" ts))))
18659 (defun org-clock-find-position ()
18660 "Find the location where the next clock line should be inserted."
18661 (org-back-to-heading t)
18662 (catch 'exit
18663 (let ((beg (save-excursion
18664 (beginning-of-line 2)
18665 (or (bolp) (newline))
18666 (point)))
18667 (end (progn (outline-next-heading) (point)))
18668 (re (concat "^[ \t]*" org-clock-string))
18669 (cnt 0)
18670 first last)
18671 (goto-char beg)
18672 (when (eobp) (newline) (setq end (max (point) end)))
18673 (when (re-search-forward "^[ \t]*:CLOCK:" end t)
18674 ;; we seem to have a CLOCK drawer, so go there.
18675 (beginning-of-line 2)
18676 (throw 'exit t))
18677 ;; Lets count the CLOCK lines
18678 (goto-char beg)
18679 (while (re-search-forward re end t)
18680 (setq first (or first (match-beginning 0))
18681 last (match-beginning 0)
18682 cnt (1+ cnt)))
18683 (when (and (integerp org-clock-into-drawer)
18684 (>= (1+ cnt) org-clock-into-drawer))
18685 ;; Wrap current entries into a new drawer
18686 (goto-char last)
18687 (beginning-of-line 2)
18688 (if (org-at-item-p) (org-end-of-item))
18689 (insert ":END:\n")
18690 (beginning-of-line 0)
18691 (org-indent-line-function)
18692 (goto-char first)
18693 (insert ":CLOCK:\n")
18694 (beginning-of-line 0)
18695 (org-indent-line-function)
18696 (org-flag-drawer t)
18697 (beginning-of-line 2)
18698 (throw 'exit nil))
18700 (goto-char beg)
18701 (while (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
18702 (not (equal (match-string 1) org-clock-string)))
18703 ;; Planning info, skip to after it
18704 (beginning-of-line 2)
18705 (or (bolp) (newline)))
18706 (when (eq t org-clock-into-drawer)
18707 (insert ":CLOCK:\n:END:\n")
18708 (beginning-of-line -1)
18709 (org-indent-line-function)
18710 (org-flag-drawer t)
18711 (beginning-of-line 2)
18712 (org-indent-line-function)))))
18714 (defun org-clock-out (&optional fail-quietly)
18715 "Stop the currently running clock.
18716 If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
18717 (interactive)
18718 (catch 'exit
18719 (if (not (marker-buffer org-clock-marker))
18720 (if fail-quietly (throw 'exit t) (error "No active clock")))
18721 (let (ts te s h m)
18722 (save-excursion
18723 (set-buffer (marker-buffer org-clock-marker))
18724 (goto-char org-clock-marker)
18725 (beginning-of-line 1)
18726 (if (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
18727 (equal (match-string 1) org-clock-string))
18728 (setq ts (match-string 2))
18729 (if fail-quietly (throw 'exit nil) (error "Clock start time is gone")))
18730 (goto-char (match-end 0))
18731 (delete-region (point) (point-at-eol))
18732 (insert "--")
18733 (setq te (org-insert-time-stamp (current-time) 'with-hm 'inactive))
18734 (setq s (- (time-to-seconds (apply 'encode-time (org-parse-time-string te)))
18735 (time-to-seconds (apply 'encode-time (org-parse-time-string ts))))
18736 h (floor (/ s 3600))
18737 s (- s (* 3600 h))
18738 m (floor (/ s 60))
18739 s (- s (* 60 s)))
18740 (insert " => " (format "%2d:%02d" h m))
18741 (move-marker org-clock-marker nil)
18742 (when org-log-note-clock-out
18743 (org-add-log-maybe 'clock-out))
18744 (when org-mode-line-timer
18745 (cancel-timer org-mode-line-timer)
18746 (setq org-mode-line-timer nil))
18747 (setq global-mode-string
18748 (delq 'org-mode-line-string global-mode-string))
18749 (force-mode-line-update)
18750 (message "Clock stopped at %s after HH:MM = %d:%02d" te h m)))))
18752 (defun org-clock-cancel ()
18753 "Cancel the running clock be removing the start timestamp."
18754 (interactive)
18755 (if (not (marker-buffer org-clock-marker))
18756 (error "No active clock"))
18757 (save-excursion
18758 (set-buffer (marker-buffer org-clock-marker))
18759 (goto-char org-clock-marker)
18760 (delete-region (1- (point-at-bol)) (point-at-eol)))
18761 (setq global-mode-string
18762 (delq 'org-mode-line-string global-mode-string))
18763 (force-mode-line-update)
18764 (message "Clock canceled"))
18766 (defun org-clock-goto (&optional delete-windows)
18767 "Go to the currently clocked-in entry."
18768 (interactive "P")
18769 (if (not (marker-buffer org-clock-marker))
18770 (error "No active clock"))
18771 (switch-to-buffer-other-window
18772 (marker-buffer org-clock-marker))
18773 (if delete-windows (delete-other-windows))
18774 (goto-char org-clock-marker)
18775 (org-show-entry)
18776 (org-back-to-heading)
18777 (recenter))
18779 (defvar org-clock-file-total-minutes nil
18780 "Holds the file total time in minutes, after a call to `org-clock-sum'.")
18781 (make-variable-buffer-local 'org-clock-file-total-minutes)
18783 (defun org-clock-sum (&optional tstart tend)
18784 "Sum the times for each subtree.
18785 Puts the resulting times in minutes as a text property on each headline."
18786 (interactive)
18787 (let* ((bmp (buffer-modified-p))
18788 (re (concat "^\\(\\*+\\)[ \t]\\|^[ \t]*"
18789 org-clock-string
18790 "[ \t]*\\(?:\\(\\[.*?\\]\\)-+\\(\\[.*?\\]\\)\\|=>[ \t]+\\([0-9]+\\):\\([0-9]+\\)\\)"))
18791 (lmax 30)
18792 (ltimes (make-vector lmax 0))
18793 (t1 0)
18794 (level 0)
18795 ts te dt
18796 time)
18797 (remove-text-properties (point-min) (point-max) '(:org-clock-minutes t))
18798 (save-excursion
18799 (goto-char (point-max))
18800 (while (re-search-backward re nil t)
18801 (cond
18802 ((match-end 2)
18803 ;; Two time stamps
18804 (setq ts (match-string 2)
18805 te (match-string 3)
18806 ts (time-to-seconds
18807 (apply 'encode-time (org-parse-time-string ts)))
18808 te (time-to-seconds
18809 (apply 'encode-time (org-parse-time-string te)))
18810 ts (if tstart (max ts tstart) ts)
18811 te (if tend (min te tend) te)
18812 dt (- te ts)
18813 t1 (if (> dt 0) (+ t1 (floor (/ dt 60))) t1)))
18814 ((match-end 4)
18815 ;; A naket time
18816 (setq t1 (+ t1 (string-to-number (match-string 5))
18817 (* 60 (string-to-number (match-string 4))))))
18818 (t ;; A headline
18819 (setq level (- (match-end 1) (match-beginning 1)))
18820 (when (or (> t1 0) (> (aref ltimes level) 0))
18821 (loop for l from 0 to level do
18822 (aset ltimes l (+ (aref ltimes l) t1)))
18823 (setq t1 0 time (aref ltimes level))
18824 (loop for l from level to (1- lmax) do
18825 (aset ltimes l 0))
18826 (goto-char (match-beginning 0))
18827 (put-text-property (point) (point-at-eol) :org-clock-minutes time)))))
18828 (setq org-clock-file-total-minutes (aref ltimes 0)))
18829 (set-buffer-modified-p bmp)))
18831 (defun org-clock-display (&optional total-only)
18832 "Show subtree times in the entire buffer.
18833 If TOTAL-ONLY is non-nil, only show the total time for the entire file
18834 in the echo area."
18835 (interactive)
18836 (org-remove-clock-overlays)
18837 (let (time h m p)
18838 (org-clock-sum)
18839 (unless total-only
18840 (save-excursion
18841 (goto-char (point-min))
18842 (while (or (and (equal (setq p (point)) (point-min))
18843 (get-text-property p :org-clock-minutes))
18844 (setq p (next-single-property-change
18845 (point) :org-clock-minutes)))
18846 (goto-char p)
18847 (when (setq time (get-text-property p :org-clock-minutes))
18848 (org-put-clock-overlay time (funcall outline-level))))
18849 (setq h (/ org-clock-file-total-minutes 60)
18850 m (- org-clock-file-total-minutes (* 60 h)))
18851 ;; Arrange to remove the overlays upon next change.
18852 (when org-remove-highlights-with-change
18853 (org-add-hook 'before-change-functions 'org-remove-clock-overlays
18854 nil 'local))))
18855 (message "Total file time: %d:%02d (%d hours and %d minutes)" h m h m)))
18857 (defvar org-clock-overlays nil)
18858 (make-variable-buffer-local 'org-clock-overlays)
18860 (defun org-put-clock-overlay (time &optional level)
18861 "Put an overlays on the current line, displaying TIME.
18862 If LEVEL is given, prefix time with a corresponding number of stars.
18863 This creates a new overlay and stores it in `org-clock-overlays', so that it
18864 will be easy to remove."
18865 (let* ((c 60) (h (floor (/ time 60))) (m (- time (* 60 h)))
18866 (l (if level (org-get-valid-level level 0) 0))
18867 (off 0)
18868 ov tx)
18869 (move-to-column c)
18870 (unless (eolp) (skip-chars-backward "^ \t"))
18871 (skip-chars-backward " \t")
18872 (setq ov (org-make-overlay (1- (point)) (point-at-eol))
18873 tx (concat (buffer-substring (1- (point)) (point))
18874 (make-string (+ off (max 0 (- c (current-column)))) ?.)
18875 (org-add-props (format "%s %2d:%02d%s"
18876 (make-string l ?*) h m
18877 (make-string (- 16 l) ?\ ))
18878 '(face secondary-selection))
18879 ""))
18880 (if (not (featurep 'xemacs))
18881 (org-overlay-put ov 'display tx)
18882 (org-overlay-put ov 'invisible t)
18883 (org-overlay-put ov 'end-glyph (make-glyph tx)))
18884 (push ov org-clock-overlays)))
18886 (defun org-remove-clock-overlays (&optional beg end noremove)
18887 "Remove the occur highlights from the buffer.
18888 BEG and END are ignored. If NOREMOVE is nil, remove this function
18889 from the `before-change-functions' in the current buffer."
18890 (interactive)
18891 (unless org-inhibit-highlight-removal
18892 (mapc 'org-delete-overlay org-clock-overlays)
18893 (setq org-clock-overlays nil)
18894 (unless noremove
18895 (remove-hook 'before-change-functions
18896 'org-remove-clock-overlays 'local))))
18898 (defun org-clock-out-if-current ()
18899 "Clock out if the current entry contains the running clock.
18900 This is used to stop the clock after a TODO entry is marked DONE,
18901 and is only done if the variable `org-clock-out-when-done' is not nil."
18902 (when (and org-clock-out-when-done
18903 (member state org-done-keywords)
18904 (equal (marker-buffer org-clock-marker) (current-buffer))
18905 (< (point) org-clock-marker)
18906 (> (save-excursion (outline-next-heading) (point))
18907 org-clock-marker))
18908 ;; Clock out, but don't accept a logging message for this.
18909 (let ((org-log-note-clock-out nil))
18910 (org-clock-out))))
18912 (add-hook 'org-after-todo-state-change-hook
18913 'org-clock-out-if-current)
18915 (defun org-check-running-clock ()
18916 "Check if the current buffer contains the running clock.
18917 If yes, offer to stop it and to save the buffer with the changes."
18918 (when (and (equal (marker-buffer org-clock-marker) (current-buffer))
18919 (y-or-n-p (format "Clock-out in buffer %s before killing it? "
18920 (buffer-name))))
18921 (org-clock-out)
18922 (when (y-or-n-p "Save changed buffer?")
18923 (save-buffer))))
18925 (defun org-clock-report (&optional arg)
18926 "Create a table containing a report about clocked time.
18927 If the cursor is inside an existing clocktable block, then the table
18928 will be updated. If not, a new clocktable will be inserted.
18929 When called with a prefix argument, move to the first clock table in the
18930 buffer and update it."
18931 (interactive "P")
18932 (org-remove-clock-overlays)
18933 (when arg
18934 (org-find-dblock "clocktable")
18935 (org-show-entry))
18936 (if (org-in-clocktable-p)
18937 (goto-char (org-in-clocktable-p))
18938 (org-create-dblock (list :name "clocktable"
18939 :maxlevel 2 :scope 'file)))
18940 (org-update-dblock))
18942 (defun org-in-clocktable-p ()
18943 "Check if the cursor is in a clocktable."
18944 (let ((pos (point)) start)
18945 (save-excursion
18946 (end-of-line 1)
18947 (and (re-search-backward "^#\\+BEGIN:[ \t]+clocktable" nil t)
18948 (setq start (match-beginning 0))
18949 (re-search-forward "^#\\+END:.*" nil t)
18950 (>= (match-end 0) pos)
18951 start))))
18953 (defun org-clock-update-time-maybe ()
18954 "If this is a CLOCK line, update it and return t.
18955 Otherwise, return nil."
18956 (interactive)
18957 (save-excursion
18958 (beginning-of-line 1)
18959 (skip-chars-forward " \t")
18960 (when (looking-at org-clock-string)
18961 (let ((re (concat "[ \t]*" org-clock-string
18962 " *[[<]\\([^]>]+\\)[]>]-+[[<]\\([^]>]+\\)[]>]"
18963 "\\([ \t]*=>.*\\)?"))
18964 ts te h m s)
18965 (if (not (looking-at re))
18967 (and (match-end 3) (delete-region (match-beginning 3) (match-end 3)))
18968 (end-of-line 1)
18969 (setq ts (match-string 1)
18970 te (match-string 2))
18971 (setq s (- (time-to-seconds
18972 (apply 'encode-time (org-parse-time-string te)))
18973 (time-to-seconds
18974 (apply 'encode-time (org-parse-time-string ts))))
18975 h (floor (/ s 3600))
18976 s (- s (* 3600 h))
18977 m (floor (/ s 60))
18978 s (- s (* 60 s)))
18979 (insert " => " (format "%2d:%02d" h m))
18980 t)))))
18982 (defun org-clock-special-range (key &optional time as-strings)
18983 "Return two times bordering a special time range.
18984 Key is a symbol specifying the range and can be one of `today', `yesterday',
18985 `thisweek', `lastweek', `thismonth', `lastmonth', `thisyear', `lastyear'.
18986 A week starts Monday 0:00 and ends Sunday 24:00.
18987 The range is determined relative to TIME. TIME defaults to the current time.
18988 The return value is a cons cell with two internal times like the ones
18989 returned by `current time' or `encode-time'. if AS-STRINGS is non-nil,
18990 the returned times will be formatted strings."
18991 (let* ((tm (decode-time (or time (current-time))))
18992 (s 0) (m (nth 1 tm)) (h (nth 2 tm))
18993 (d (nth 3 tm)) (month (nth 4 tm)) (y (nth 5 tm))
18994 (dow (nth 6 tm))
18995 s1 m1 h1 d1 month1 y1 diff ts te fm)
18996 (cond
18997 ((eq key 'today)
18998 (setq h 0 m 0 h1 24 m1 0))
18999 ((eq key 'yesterday)
19000 (setq d (1- d) h 0 m 0 h1 24 m1 0))
19001 ((eq key 'thisweek)
19002 (setq diff (if (= dow 0) 6 (1- dow))
19003 m 0 h 0 d (- d diff) d1 (+ 7 d)))
19004 ((eq key 'lastweek)
19005 (setq diff (+ 7 (if (= dow 0) 6 (1- dow)))
19006 m 0 h 0 d (- d diff) d1 (+ 7 d)))
19007 ((eq key 'thismonth)
19008 (setq d 1 h 0 m 0 d1 1 month1 (1+ month) h1 0 m1 0))
19009 ((eq key 'lastmonth)
19010 (setq d 1 h 0 m 0 d1 1 month (1- month) month1 (1+ month) h1 0 m1 0))
19011 ((eq key 'thisyear)
19012 (setq m 0 h 0 d 1 month 1 y1 (1+ y)))
19013 ((eq key 'lastyear)
19014 (setq m 0 h 0 d 1 month 1 y (1- y) y1 (1+ y)))
19015 (t (error "No such time block %s" key)))
19016 (setq ts (encode-time s m h d month y)
19017 te (encode-time (or s1 s) (or m1 m) (or h1 h)
19018 (or d1 d) (or month1 month) (or y1 y)))
19019 (setq fm (cdr org-time-stamp-formats))
19020 (if as-strings
19021 (cons (format-time-string fm ts) (format-time-string fm te))
19022 (cons ts te))))
19024 (defun org-dblock-write:clocktable (params)
19025 "Write the standard clocktable."
19026 (catch 'exit
19027 (let* ((hlchars '((1 . "*") (2 . "/")))
19028 (ins (make-marker))
19029 (total-time nil)
19030 (scope (plist-get params :scope))
19031 (tostring (plist-get params :tostring))
19032 (multifile (plist-get params :multifile))
19033 (header (plist-get params :header))
19034 (maxlevel (or (plist-get params :maxlevel) 3))
19035 (step (plist-get params :step))
19036 (emph (plist-get params :emphasize))
19037 (ts (plist-get params :tstart))
19038 (te (plist-get params :tend))
19039 (block (plist-get params :block))
19040 (link (plist-get params :link))
19041 ipos time h m p level hlc hdl
19042 cc beg end pos tbl)
19043 (when step
19044 (org-clocktable-steps params)
19045 (throw 'exit nil))
19046 (when block
19047 (setq cc (org-clock-special-range block nil t)
19048 ts (car cc) te (cdr cc)))
19049 (if ts (setq ts (time-to-seconds
19050 (apply 'encode-time (org-parse-time-string ts)))))
19051 (if te (setq te (time-to-seconds
19052 (apply 'encode-time (org-parse-time-string te)))))
19053 (move-marker ins (point))
19054 (setq ipos (point))
19056 ;; Get the right scope
19057 (setq pos (point))
19058 (save-restriction
19059 (cond
19060 ((not scope))
19061 ((eq scope 'file) (widen))
19062 ((eq scope 'subtree) (org-narrow-to-subtree))
19063 ((eq scope 'tree)
19064 (while (org-up-heading-safe))
19065 (org-narrow-to-subtree))
19066 ((and (symbolp scope) (string-match "^tree\\([0-9]+\\)$"
19067 (symbol-name scope)))
19068 (setq level (string-to-number (match-string 1 (symbol-name scope))))
19069 (catch 'exit
19070 (while (org-up-heading-safe)
19071 (looking-at outline-regexp)
19072 (if (<= (org-reduced-level (funcall outline-level)) level)
19073 (throw 'exit nil))))
19074 (org-narrow-to-subtree))
19075 ((or (listp scope) (eq scope 'agenda))
19076 (let* ((files (if (listp scope) scope (org-agenda-files)))
19077 (scope 'agenda)
19078 (p1 (copy-sequence params))
19079 file)
19080 (plist-put p1 :tostring t)
19081 (plist-put p1 :multifile t)
19082 (plist-put p1 :scope 'file)
19083 (org-prepare-agenda-buffers files)
19084 (while (setq file (pop files))
19085 (with-current-buffer (find-buffer-visiting file)
19086 (push (org-clocktable-add-file
19087 file (org-dblock-write:clocktable p1)) tbl)
19088 (setq total-time (+ (or total-time 0)
19089 org-clock-file-total-minutes)))))))
19090 (goto-char pos)
19092 (unless (eq scope 'agenda)
19093 (org-clock-sum ts te)
19094 (goto-char (point-min))
19095 (while (setq p (next-single-property-change (point) :org-clock-minutes))
19096 (goto-char p)
19097 (when (setq time (get-text-property p :org-clock-minutes))
19098 (save-excursion
19099 (beginning-of-line 1)
19100 (when (and (looking-at (org-re "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ \t]+:[[:alnum:]_@:]+:\\)?[ \t]*$"))
19101 (setq level (org-reduced-level
19102 (- (match-end 1) (match-beginning 1))))
19103 (<= level maxlevel))
19104 (setq hlc (if emph (or (cdr (assoc level hlchars)) "") "")
19105 hdl (if (not link)
19106 (match-string 2)
19107 (org-make-link-string
19108 (format "file:%s::%s"
19109 (buffer-file-name)
19110 (save-match-data
19111 (org-make-org-heading-search-string
19112 (match-string 2))))
19113 (match-string 2)))
19114 h (/ time 60)
19115 m (- time (* 60 h)))
19116 (if (and (not multifile) (= level 1)) (push "|-" tbl))
19117 (push (concat
19118 "| " (int-to-string level) "|" hlc hdl hlc " |"
19119 (make-string (1- level) ?|)
19120 hlc (format "%d:%02d" h m) hlc
19121 " |") tbl))))))
19122 (setq tbl (nreverse tbl))
19123 (if tostring
19124 (if tbl (mapconcat 'identity tbl "\n") nil)
19125 (goto-char ins)
19126 (insert-before-markers
19127 (or header
19128 (concat
19129 "Clock summary at ["
19130 (substring
19131 (format-time-string (cdr org-time-stamp-formats))
19132 1 -1)
19133 "]."
19134 (if block
19135 (format " Considered range is /%s/." block)
19137 "\n\n"))
19138 (if (eq scope 'agenda) "|File" "")
19139 "|L|Headline|Time|\n")
19140 (setq total-time (or total-time org-clock-file-total-minutes)
19141 h (/ total-time 60)
19142 m (- total-time (* 60 h)))
19143 (insert-before-markers
19144 "|-\n|"
19145 (if (eq scope 'agenda) "|" "")
19147 "*Total time*| "
19148 (format "*%d:%02d*" h m)
19149 "|\n|-\n")
19150 (setq tbl (delq nil tbl))
19151 (if (and (stringp (car tbl)) (> (length (car tbl)) 1)
19152 (equal (substring (car tbl) 0 2) "|-"))
19153 (pop tbl))
19154 (insert-before-markers (mapconcat
19155 'identity (delq nil tbl)
19156 (if (eq scope 'agenda) "\n|-\n" "\n")))
19157 (backward-delete-char 1)
19158 (goto-char ipos)
19159 (skip-chars-forward "^|")
19160 (org-table-align))))))
19162 (defun org-clocktable-steps (params)
19163 (let* ((p1 (copy-sequence params))
19164 (ts (plist-get p1 :tstart))
19165 (te (plist-get p1 :tend))
19166 (step0 (plist-get p1 :step))
19167 (step (cdr (assoc step0 '((day . 86400) (week . 604800)))))
19168 (block (plist-get p1 :block))
19170 (when block
19171 (setq cc (org-clock-special-range block nil t)
19172 ts (car cc) te (cdr cc)))
19173 (if ts (setq ts (time-to-seconds
19174 (apply 'encode-time (org-parse-time-string ts)))))
19175 (if te (setq te (time-to-seconds
19176 (apply 'encode-time (org-parse-time-string te)))))
19177 (plist-put p1 :header "")
19178 (plist-put p1 :step nil)
19179 (plist-put p1 :block nil)
19180 (while (< ts te)
19181 (or (bolp) (insert "\n"))
19182 (plist-put p1 :tstart (format-time-string
19183 (car org-time-stamp-formats)
19184 (seconds-to-time ts)))
19185 (plist-put p1 :tend (format-time-string
19186 (car org-time-stamp-formats)
19187 (seconds-to-time (setq ts (+ ts step)))))
19188 (insert "\n" (if (eq step0 'day) "Daily report: " "Weekly report starting on: ")
19189 (plist-get p1 :tstart) "\n")
19190 (org-dblock-write:clocktable p1)
19191 (re-search-forward "#\\+END:")
19192 (end-of-line 0))))
19195 (defun org-clocktable-add-file (file table)
19196 (if table
19197 (let ((lines (org-split-string table "\n"))
19198 (ff (file-name-nondirectory file)))
19199 (mapconcat 'identity
19200 (mapcar (lambda (x)
19201 (if (string-match org-table-dataline-regexp x)
19202 (concat "|" ff x)
19204 lines)
19205 "\n"))))
19207 ;; FIXME: I don't think anybody uses this, ask David
19208 (defun org-collect-clock-time-entries ()
19209 "Return an internal list with clocking information.
19210 This list has one entry for each CLOCK interval.
19211 FIXME: describe the elements."
19212 (interactive)
19213 (let ((re (concat "^[ \t]*" org-clock-string
19214 " *\\[\\(.*?\\)\\]--\\[\\(.*?\\)\\]"))
19215 rtn beg end next cont level title total closedp leafp
19216 clockpos titlepos h m donep)
19217 (save-excursion
19218 (org-clock-sum)
19219 (goto-char (point-min))
19220 (while (re-search-forward re nil t)
19221 (setq clockpos (match-beginning 0)
19222 beg (match-string 1) end (match-string 2)
19223 cont (match-end 0))
19224 (setq beg (apply 'encode-time (org-parse-time-string beg))
19225 end (apply 'encode-time (org-parse-time-string end)))
19226 (org-back-to-heading t)
19227 (setq donep (org-entry-is-done-p))
19228 (setq titlepos (point)
19229 total (or (get-text-property (1+ (point)) :org-clock-minutes) 0)
19230 h (/ total 60) m (- total (* 60 h))
19231 total (cons h m))
19232 (looking-at "\\(\\*+\\) +\\(.*\\)")
19233 (setq level (- (match-end 1) (match-beginning 1))
19234 title (org-match-string-no-properties 2))
19235 (save-excursion (outline-next-heading) (setq next (point)))
19236 (setq closedp (re-search-forward org-closed-time-regexp next t))
19237 (goto-char next)
19238 (setq leafp (and (looking-at "^\\*+ ")
19239 (<= (- (match-end 0) (point)) level)))
19240 (push (list beg end clockpos closedp donep
19241 total title titlepos level leafp)
19242 rtn)
19243 (goto-char cont)))
19244 (nreverse rtn)))
19246 ;;;; Agenda, and Diary Integration
19248 ;;; Define the Org-agenda-mode
19250 (defvar org-agenda-mode-map (make-sparse-keymap)
19251 "Keymap for `org-agenda-mode'.")
19253 (defvar org-agenda-menu) ; defined later in this file.
19254 (defvar org-agenda-follow-mode nil)
19255 (defvar org-agenda-show-log nil)
19256 (defvar org-agenda-redo-command nil)
19257 (defvar org-agenda-query-string nil)
19258 (defvar org-agenda-mode-hook nil)
19259 (defvar org-agenda-type nil)
19260 (defvar org-agenda-force-single-file nil)
19262 (defun org-agenda-mode ()
19263 "Mode for time-sorted view on action items in Org-mode files.
19265 The following commands are available:
19267 \\{org-agenda-mode-map}"
19268 (interactive)
19269 (kill-all-local-variables)
19270 (setq org-agenda-undo-list nil
19271 org-agenda-pending-undo-list nil)
19272 (setq major-mode 'org-agenda-mode)
19273 ;; Keep global-font-lock-mode from turning on font-lock-mode
19274 (org-set-local 'font-lock-global-modes (list 'not major-mode))
19275 (setq mode-name "Org-Agenda")
19276 (use-local-map org-agenda-mode-map)
19277 (easy-menu-add org-agenda-menu)
19278 (if org-startup-truncated (setq truncate-lines t))
19279 (org-add-hook 'post-command-hook 'org-agenda-post-command-hook nil 'local)
19280 (org-add-hook 'pre-command-hook 'org-unhighlight nil 'local)
19281 ;; Make sure properties are removed when copying text
19282 (when (boundp 'buffer-substring-filters)
19283 (org-set-local 'buffer-substring-filters
19284 (cons (lambda (x)
19285 (set-text-properties 0 (length x) nil x) x)
19286 buffer-substring-filters)))
19287 (unless org-agenda-keep-modes
19288 (setq org-agenda-follow-mode org-agenda-start-with-follow-mode
19289 org-agenda-show-log nil))
19290 (easy-menu-change
19291 '("Agenda") "Agenda Files"
19292 (append
19293 (list
19294 (vector
19295 (if (get 'org-agenda-files 'org-restrict)
19296 "Restricted to single file"
19297 "Edit File List")
19298 '(org-edit-agenda-file-list)
19299 (not (get 'org-agenda-files 'org-restrict)))
19300 "--")
19301 (mapcar 'org-file-menu-entry (org-agenda-files))))
19302 (org-agenda-set-mode-name)
19303 (apply
19304 (if (fboundp 'run-mode-hooks) 'run-mode-hooks 'run-hooks)
19305 (list 'org-agenda-mode-hook)))
19307 (substitute-key-definition 'undo 'org-agenda-undo
19308 org-agenda-mode-map global-map)
19309 (org-defkey org-agenda-mode-map "\C-i" 'org-agenda-goto)
19310 (org-defkey org-agenda-mode-map [(tab)] 'org-agenda-goto)
19311 (org-defkey org-agenda-mode-map "\C-m" 'org-agenda-switch-to)
19312 (org-defkey org-agenda-mode-map "\C-k" 'org-agenda-kill)
19313 (org-defkey org-agenda-mode-map "\C-c$" 'org-agenda-archive)
19314 (org-defkey org-agenda-mode-map "\C-c\C-x\C-s" 'org-agenda-archive)
19315 (org-defkey org-agenda-mode-map "$" 'org-agenda-archive)
19316 (org-defkey org-agenda-mode-map "\C-c\C-o" 'org-agenda-open-link)
19317 (org-defkey org-agenda-mode-map " " 'org-agenda-show)
19318 (org-defkey org-agenda-mode-map "\C-c\C-t" 'org-agenda-todo)
19319 (org-defkey org-agenda-mode-map [(control shift right)] 'org-agenda-todo-nextset)
19320 (org-defkey org-agenda-mode-map [(control shift left)] 'org-agenda-todo-previousset)
19321 (org-defkey org-agenda-mode-map "\C-c\C-xb" 'org-agenda-tree-to-indirect-buffer)
19322 (org-defkey org-agenda-mode-map "b" 'org-agenda-tree-to-indirect-buffer)
19323 (org-defkey org-agenda-mode-map "o" 'delete-other-windows)
19324 (org-defkey org-agenda-mode-map "L" 'org-agenda-recenter)
19325 (org-defkey org-agenda-mode-map "t" 'org-agenda-todo)
19326 (org-defkey org-agenda-mode-map "a" 'org-agenda-toggle-archive-tag)
19327 (org-defkey org-agenda-mode-map ":" 'org-agenda-set-tags)
19328 (org-defkey org-agenda-mode-map "." 'org-agenda-goto-today)
19329 (org-defkey org-agenda-mode-map "j" 'org-agenda-goto-date)
19330 (org-defkey org-agenda-mode-map "d" 'org-agenda-day-view)
19331 (org-defkey org-agenda-mode-map "w" 'org-agenda-week-view)
19332 (org-defkey org-agenda-mode-map "m" 'org-agenda-month-view)
19333 (org-defkey org-agenda-mode-map "y" 'org-agenda-year-view)
19334 (org-defkey org-agenda-mode-map [(shift right)] 'org-agenda-date-later)
19335 (org-defkey org-agenda-mode-map [(shift left)] 'org-agenda-date-earlier)
19336 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (right)] 'org-agenda-date-later)
19337 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (left)] 'org-agenda-date-earlier)
19339 (org-defkey org-agenda-mode-map ">" 'org-agenda-date-prompt)
19340 (org-defkey org-agenda-mode-map "\C-c\C-s" 'org-agenda-schedule)
19341 (org-defkey org-agenda-mode-map "\C-c\C-d" 'org-agenda-deadline)
19342 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
19343 (while l (org-defkey org-agenda-mode-map
19344 (int-to-string (pop l)) 'digit-argument)))
19346 (org-defkey org-agenda-mode-map "f" 'org-agenda-follow-mode)
19347 (org-defkey org-agenda-mode-map "l" 'org-agenda-log-mode)
19348 (org-defkey org-agenda-mode-map "D" 'org-agenda-toggle-diary)
19349 (org-defkey org-agenda-mode-map "G" 'org-agenda-toggle-time-grid)
19350 (org-defkey org-agenda-mode-map "r" 'org-agenda-redo)
19351 (org-defkey org-agenda-mode-map "g" 'org-agenda-redo)
19352 (org-defkey org-agenda-mode-map "e" 'org-agenda-execute)
19353 (org-defkey org-agenda-mode-map "q" 'org-agenda-quit)
19354 (org-defkey org-agenda-mode-map "x" 'org-agenda-exit)
19355 (org-defkey org-agenda-mode-map "\C-x\C-w" 'org-write-agenda)
19356 (org-defkey org-agenda-mode-map "s" 'org-save-all-org-buffers)
19357 (org-defkey org-agenda-mode-map "\C-x\C-s" 'org-save-all-org-buffers)
19358 (org-defkey org-agenda-mode-map "P" 'org-agenda-show-priority)
19359 (org-defkey org-agenda-mode-map "T" 'org-agenda-show-tags)
19360 (org-defkey org-agenda-mode-map "n" 'next-line)
19361 (org-defkey org-agenda-mode-map "p" 'previous-line)
19362 (org-defkey org-agenda-mode-map "\C-c\C-n" 'org-agenda-next-date-line)
19363 (org-defkey org-agenda-mode-map "\C-c\C-p" 'org-agenda-previous-date-line)
19364 (org-defkey org-agenda-mode-map "," 'org-agenda-priority)
19365 (org-defkey org-agenda-mode-map "\C-c," 'org-agenda-priority)
19366 (org-defkey org-agenda-mode-map "i" 'org-agenda-diary-entry)
19367 (org-defkey org-agenda-mode-map "c" 'org-agenda-goto-calendar)
19368 (eval-after-load "calendar"
19369 '(org-defkey calendar-mode-map org-calendar-to-agenda-key
19370 'org-calendar-goto-agenda))
19371 (org-defkey org-agenda-mode-map "C" 'org-agenda-convert-date)
19372 (org-defkey org-agenda-mode-map "M" 'org-agenda-phases-of-moon)
19373 (org-defkey org-agenda-mode-map "S" 'org-agenda-sunrise-sunset)
19374 (org-defkey org-agenda-mode-map "h" 'org-agenda-holidays)
19375 (org-defkey org-agenda-mode-map "H" 'org-agenda-holidays)
19376 (org-defkey org-agenda-mode-map "\C-c\C-x\C-i" 'org-agenda-clock-in)
19377 (org-defkey org-agenda-mode-map "I" 'org-agenda-clock-in)
19378 (org-defkey org-agenda-mode-map "\C-c\C-x\C-o" 'org-agenda-clock-out)
19379 (org-defkey org-agenda-mode-map "O" 'org-agenda-clock-out)
19380 (org-defkey org-agenda-mode-map "\C-c\C-x\C-x" 'org-agenda-clock-cancel)
19381 (org-defkey org-agenda-mode-map "X" 'org-agenda-clock-cancel)
19382 (org-defkey org-agenda-mode-map "\C-c\C-x\C-j" 'org-clock-goto)
19383 (org-defkey org-agenda-mode-map "J" 'org-clock-goto)
19384 (org-defkey org-agenda-mode-map "+" 'org-agenda-priority-up)
19385 (org-defkey org-agenda-mode-map "-" 'org-agenda-priority-down)
19386 (org-defkey org-agenda-mode-map [(shift up)] 'org-agenda-priority-up)
19387 (org-defkey org-agenda-mode-map [(shift down)] 'org-agenda-priority-down)
19388 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (up)] 'org-agenda-priority-up)
19389 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (down)] 'org-agenda-priority-down)
19390 (org-defkey org-agenda-mode-map [(right)] 'org-agenda-later)
19391 (org-defkey org-agenda-mode-map [(left)] 'org-agenda-earlier)
19392 (org-defkey org-agenda-mode-map "\C-c\C-x\C-c" 'org-agenda-columns)
19394 (org-defkey org-agenda-mode-map "[" 'org-agenda-manipulate-query-add)
19395 (org-defkey org-agenda-mode-map "]" 'org-agenda-manipulate-query-subtract)
19396 (org-defkey org-agenda-mode-map "{" 'org-agenda-manipulate-query-add-re)
19397 (org-defkey org-agenda-mode-map "}" 'org-agenda-manipulate-query-subtract-re)
19399 (defvar org-agenda-keymap (copy-keymap org-agenda-mode-map)
19400 "Local keymap for agenda entries from Org-mode.")
19402 (org-defkey org-agenda-keymap
19403 (if (featurep 'xemacs) [(button2)] [(mouse-2)]) 'org-agenda-goto-mouse)
19404 (org-defkey org-agenda-keymap
19405 (if (featurep 'xemacs) [(button3)] [(mouse-3)]) 'org-agenda-show-mouse)
19406 (when org-agenda-mouse-1-follows-link
19407 (org-defkey org-agenda-keymap [follow-link] 'mouse-face))
19408 (easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu"
19409 '("Agenda"
19410 ("Agenda Files")
19411 "--"
19412 ["Show" org-agenda-show t]
19413 ["Go To (other window)" org-agenda-goto t]
19414 ["Go To (this window)" org-agenda-switch-to t]
19415 ["Follow Mode" org-agenda-follow-mode
19416 :style toggle :selected org-agenda-follow-mode :active t]
19417 ["Tree to indirect frame" org-agenda-tree-to-indirect-buffer t]
19418 "--"
19419 ["Cycle TODO" org-agenda-todo t]
19420 ["Archive subtree" org-agenda-archive t]
19421 ["Delete subtree" org-agenda-kill t]
19422 "--"
19423 ["Goto Today" org-agenda-goto-today (org-agenda-check-type nil 'agenda 'timeline)]
19424 ["Next Dates" org-agenda-later (org-agenda-check-type nil 'agenda)]
19425 ["Previous Dates" org-agenda-earlier (org-agenda-check-type nil 'agenda)]
19426 ["Jump to date" org-agenda-goto-date (org-agenda-check-type nil 'agenda)]
19427 "--"
19428 ("Tags and Properties"
19429 ["Show all Tags" org-agenda-show-tags t]
19430 ["Set Tags current line" org-agenda-set-tags (not (org-region-active-p))]
19431 ["Change tag in region" org-agenda-set-tags (org-region-active-p)]
19432 "--"
19433 ["Column View" org-columns t])
19434 ("Date/Schedule"
19435 ["Schedule" org-agenda-schedule t]
19436 ["Set Deadline" org-agenda-deadline t]
19437 "--"
19438 ["Change Date +1 day" org-agenda-date-later (org-agenda-check-type nil 'agenda 'timeline)]
19439 ["Change Date -1 day" org-agenda-date-earlier (org-agenda-check-type nil 'agenda 'timeline)]
19440 ["Change Date to ..." org-agenda-date-prompt (org-agenda-check-type nil 'agenda 'timeline)])
19441 ("Clock"
19442 ["Clock in" org-agenda-clock-in t]
19443 ["Clock out" org-agenda-clock-out t]
19444 ["Clock cancel" org-agenda-clock-cancel t]
19445 ["Goto running clock" org-clock-goto t])
19446 ("Priority"
19447 ["Set Priority" org-agenda-priority t]
19448 ["Increase Priority" org-agenda-priority-up t]
19449 ["Decrease Priority" org-agenda-priority-down t]
19450 ["Show Priority" org-agenda-show-priority t])
19451 ("Calendar/Diary"
19452 ["New Diary Entry" org-agenda-diary-entry (org-agenda-check-type nil 'agenda 'timeline)]
19453 ["Goto Calendar" org-agenda-goto-calendar (org-agenda-check-type nil 'agenda 'timeline)]
19454 ["Phases of the Moon" org-agenda-phases-of-moon (org-agenda-check-type nil 'agenda 'timeline)]
19455 ["Sunrise/Sunset" org-agenda-sunrise-sunset (org-agenda-check-type nil 'agenda 'timeline)]
19456 ["Holidays" org-agenda-holidays (org-agenda-check-type nil 'agenda 'timeline)]
19457 ["Convert" org-agenda-convert-date (org-agenda-check-type nil 'agenda 'timeline)]
19458 "--"
19459 ["Create iCalendar file" org-export-icalendar-combine-agenda-files t])
19460 "--"
19461 ("View"
19462 ["Day View" org-agenda-day-view :active (org-agenda-check-type nil 'agenda)
19463 :style radio :selected (equal org-agenda-ndays 1)]
19464 ["Week View" org-agenda-week-view :active (org-agenda-check-type nil 'agenda)
19465 :style radio :selected (equal org-agenda-ndays 7)]
19466 ["Month View" org-agenda-month-view :active (org-agenda-check-type nil 'agenda)
19467 :style radio :selected (member org-agenda-ndays '(28 29 30 31))]
19468 ["Year View" org-agenda-year-view :active (org-agenda-check-type nil 'agenda)
19469 :style radio :selected (member org-agenda-ndays '(365 366))]
19470 "--"
19471 ["Show Logbook entries" org-agenda-log-mode
19472 :style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)]
19473 ["Include Diary" org-agenda-toggle-diary
19474 :style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)]
19475 ["Use Time Grid" org-agenda-toggle-time-grid
19476 :style toggle :selected org-agenda-use-time-grid :active (org-agenda-check-type nil 'agenda)])
19477 ["Write view to file" org-write-agenda t]
19478 ["Rebuild buffer" org-agenda-redo t]
19479 ["Save all Org-mode Buffers" org-save-all-org-buffers t]
19480 "--"
19481 ["Undo Remote Editing" org-agenda-undo org-agenda-undo-list]
19482 "--"
19483 ["Quit" org-agenda-quit t]
19484 ["Exit and Release Buffers" org-agenda-exit t]
19487 ;;; Agenda undo
19489 (defvar org-agenda-allow-remote-undo t
19490 "Non-nil means, allow remote undo from the agenda buffer.")
19491 (defvar org-agenda-undo-list nil
19492 "List of undoable operations in the agenda since last refresh.")
19493 (defvar org-agenda-undo-has-started-in nil
19494 "Buffers that have already seen `undo-start' in the current undo sequence.")
19495 (defvar org-agenda-pending-undo-list nil
19496 "In a series of undo commands, this is the list of remaning undo items.")
19498 (defmacro org-if-unprotected (&rest body)
19499 "Execute BODY if there is no `org-protected' text property at point."
19500 (declare (debug t))
19501 `(unless (get-text-property (point) 'org-protected)
19502 ,@body))
19504 (defmacro org-with-remote-undo (_buffer &rest _body)
19505 "Execute BODY while recording undo information in two buffers."
19506 (declare (indent 1) (debug t))
19507 `(let ((_cline (org-current-line))
19508 (_cmd this-command)
19509 (_buf1 (current-buffer))
19510 (_buf2 ,_buffer)
19511 (_undo1 buffer-undo-list)
19512 (_undo2 (with-current-buffer ,_buffer buffer-undo-list))
19513 _c1 _c2)
19514 ,@_body
19515 (when org-agenda-allow-remote-undo
19516 (setq _c1 (org-verify-change-for-undo
19517 _undo1 (with-current-buffer _buf1 buffer-undo-list))
19518 _c2 (org-verify-change-for-undo
19519 _undo2 (with-current-buffer _buf2 buffer-undo-list)))
19520 (when (or _c1 _c2)
19521 ;; make sure there are undo boundaries
19522 (and _c1 (with-current-buffer _buf1 (undo-boundary)))
19523 (and _c2 (with-current-buffer _buf2 (undo-boundary)))
19524 ;; remember which buffer to undo
19525 (push (list _cmd _cline _buf1 _c1 _buf2 _c2)
19526 org-agenda-undo-list)))))
19528 (defun org-agenda-undo ()
19529 "Undo a remote editing step in the agenda.
19530 This undoes changes both in the agenda buffer and in the remote buffer
19531 that have been changed along."
19532 (interactive)
19533 (or org-agenda-allow-remote-undo
19534 (error "Check the variable `org-agenda-allow-remote-undo' to activate remote undo."))
19535 (if (not (eq this-command last-command))
19536 (setq org-agenda-undo-has-started-in nil
19537 org-agenda-pending-undo-list org-agenda-undo-list))
19538 (if (not org-agenda-pending-undo-list)
19539 (error "No further undo information"))
19540 (let* ((entry (pop org-agenda-pending-undo-list))
19541 buf line cmd rembuf)
19542 (setq cmd (pop entry) line (pop entry))
19543 (setq rembuf (nth 2 entry))
19544 (org-with-remote-undo rembuf
19545 (while (bufferp (setq buf (pop entry)))
19546 (if (pop entry)
19547 (with-current-buffer buf
19548 (let ((last-undo-buffer buf)
19549 (inhibit-read-only t))
19550 (unless (memq buf org-agenda-undo-has-started-in)
19551 (push buf org-agenda-undo-has-started-in)
19552 (make-local-variable 'pending-undo-list)
19553 (undo-start))
19554 (while (and pending-undo-list
19555 (listp pending-undo-list)
19556 (not (car pending-undo-list)))
19557 (pop pending-undo-list))
19558 (undo-more 1))))))
19559 (goto-line line)
19560 (message "`%s' undone (buffer %s)" cmd (buffer-name rembuf))))
19562 (defun org-verify-change-for-undo (l1 l2)
19563 "Verify that a real change occurred between the undo lists L1 and L2."
19564 (while (and l1 (listp l1) (null (car l1))) (pop l1))
19565 (while (and l2 (listp l2) (null (car l2))) (pop l2))
19566 (not (eq l1 l2)))
19568 ;;; Agenda dispatch
19570 (defvar org-agenda-restrict nil)
19571 (defvar org-agenda-restrict-begin (make-marker))
19572 (defvar org-agenda-restrict-end (make-marker))
19573 (defvar org-agenda-last-dispatch-buffer nil)
19574 (defvar org-agenda-overriding-restriction nil)
19576 ;;;###autoload
19577 (defun org-agenda (arg &optional keys restriction)
19578 "Dispatch agenda commands to collect entries to the agenda buffer.
19579 Prompts for a command to execute. Any prefix arg will be passed
19580 on to the selected command. The default selections are:
19582 a Call `org-agenda-list' to display the agenda for current day or week.
19583 t Call `org-todo-list' to display the global todo list.
19584 T Call `org-todo-list' to display the global todo list, select only
19585 entries with a specific TODO keyword (the user gets a prompt).
19586 m Call `org-tags-view' to display headlines with tags matching
19587 a condition (the user is prompted for the condition).
19588 M Like `m', but select only TODO entries, no ordinary headlines.
19589 L Create a timeline for the current buffer.
19590 e Export views to associated files.
19592 More commands can be added by configuring the variable
19593 `org-agenda-custom-commands'. In particular, specific tags and TODO keyword
19594 searches can be pre-defined in this way.
19596 If the current buffer is in Org-mode and visiting a file, you can also
19597 first press `<' once to indicate that the agenda should be temporarily
19598 \(until the next use of \\[org-agenda]) restricted to the current file.
19599 Pressing `<' twice means to restrict to the current subtree or region
19600 \(if active)."
19601 (interactive "P")
19602 (catch 'exit
19603 (let* ((prefix-descriptions nil)
19604 (org-agenda-custom-commands-orig org-agenda-custom-commands)
19605 (org-agenda-custom-commands
19606 ;; normalize different versions
19607 (delq nil
19608 (mapcar
19609 (lambda (x)
19610 (cond ((stringp (cdr x))
19611 (push x prefix-descriptions)
19612 nil)
19613 ((stringp (nth 1 x)) x)
19614 ((not (nth 1 x)) (cons (car x) (cons "" (cddr x))))
19615 (t (cons (car x) (cons "" (cdr x))))))
19616 org-agenda-custom-commands)))
19617 (buf (current-buffer))
19618 (bfn (buffer-file-name (buffer-base-buffer)))
19619 entry key type match lprops ans)
19620 ;; Turn off restriction unless there is an overriding one
19621 (unless org-agenda-overriding-restriction
19622 (put 'org-agenda-files 'org-restrict nil)
19623 (setq org-agenda-restrict nil)
19624 (move-marker org-agenda-restrict-begin nil)
19625 (move-marker org-agenda-restrict-end nil))
19626 ;; Delete old local properties
19627 (put 'org-agenda-redo-command 'org-lprops nil)
19628 ;; Remember where this call originated
19629 (setq org-agenda-last-dispatch-buffer (current-buffer))
19630 (unless keys
19631 (setq ans (org-agenda-get-restriction-and-command prefix-descriptions)
19632 keys (car ans)
19633 restriction (cdr ans)))
19634 ;; Estabish the restriction, if any
19635 (when (and (not org-agenda-overriding-restriction) restriction)
19636 (put 'org-agenda-files 'org-restrict (list bfn))
19637 (cond
19638 ((eq restriction 'region)
19639 (setq org-agenda-restrict t)
19640 (move-marker org-agenda-restrict-begin (region-beginning))
19641 (move-marker org-agenda-restrict-end (region-end)))
19642 ((eq restriction 'subtree)
19643 (save-excursion
19644 (setq org-agenda-restrict t)
19645 (org-back-to-heading t)
19646 (move-marker org-agenda-restrict-begin (point))
19647 (move-marker org-agenda-restrict-end
19648 (progn (org-end-of-subtree t)))))))
19650 (require 'calendar) ; FIXME: can we avoid this for some commands?
19651 ;; For example the todo list should not need it (but does...)
19652 (cond
19653 ((setq entry (assoc keys org-agenda-custom-commands))
19654 (if (or (symbolp (nth 2 entry)) (functionp (nth 2 entry)))
19655 (progn
19656 (setq type (nth 2 entry) match (nth 3 entry) lprops (nth 4 entry))
19657 (put 'org-agenda-redo-command 'org-lprops lprops)
19658 (cond
19659 ((eq type 'agenda)
19660 (org-let lprops '(org-agenda-list current-prefix-arg)))
19661 ((eq type 'alltodo)
19662 (org-let lprops '(org-todo-list current-prefix-arg)))
19663 ((eq type 'search)
19664 (org-let lprops '(org-search-view current-prefix-arg match nil)))
19665 ((eq type 'stuck)
19666 (org-let lprops '(org-agenda-list-stuck-projects
19667 current-prefix-arg)))
19668 ((eq type 'tags)
19669 (org-let lprops '(org-tags-view current-prefix-arg match)))
19670 ((eq type 'tags-todo)
19671 (org-let lprops '(org-tags-view '(4) match)))
19672 ((eq type 'todo)
19673 (org-let lprops '(org-todo-list match)))
19674 ((eq type 'tags-tree)
19675 (org-check-for-org-mode)
19676 (org-let lprops '(org-tags-sparse-tree current-prefix-arg match)))
19677 ((eq type 'todo-tree)
19678 (org-check-for-org-mode)
19679 (org-let lprops
19680 '(org-occur (concat "^" outline-regexp "[ \t]*"
19681 (regexp-quote match) "\\>"))))
19682 ((eq type 'occur-tree)
19683 (org-check-for-org-mode)
19684 (org-let lprops '(org-occur match)))
19685 ((functionp type)
19686 (org-let lprops '(funcall type match)))
19687 ((fboundp type)
19688 (org-let lprops '(funcall type match)))
19689 (t (error "Invalid custom agenda command type %s" type))))
19690 (org-run-agenda-series (nth 1 entry) (cddr entry))))
19691 ((equal keys "C")
19692 (setq org-agenda-custom-commands org-agenda-custom-commands-orig)
19693 (customize-variable 'org-agenda-custom-commands))
19694 ((equal keys "a") (call-interactively 'org-agenda-list))
19695 ((equal keys "s") (call-interactively 'org-search-view))
19696 ((equal keys "t") (call-interactively 'org-todo-list))
19697 ((equal keys "T") (org-call-with-arg 'org-todo-list (or arg '(4))))
19698 ((equal keys "m") (call-interactively 'org-tags-view))
19699 ((equal keys "M") (org-call-with-arg 'org-tags-view (or arg '(4))))
19700 ((equal keys "e") (call-interactively 'org-store-agenda-views))
19701 ((equal keys "L")
19702 (unless (org-mode-p)
19703 (error "This is not an Org-mode file"))
19704 (unless restriction
19705 (put 'org-agenda-files 'org-restrict (list bfn))
19706 (org-call-with-arg 'org-timeline arg)))
19707 ((equal keys "#") (call-interactively 'org-agenda-list-stuck-projects))
19708 ((equal keys "/") (call-interactively 'org-occur-in-agenda-files))
19709 ((equal keys "!") (customize-variable 'org-stuck-projects))
19710 (t (error "Invalid agenda key"))))))
19712 (defun org-agenda-normalize-custom-commands (cmds)
19713 (delq nil
19714 (mapcar
19715 (lambda (x)
19716 (cond ((stringp (cdr x)) nil)
19717 ((stringp (nth 1 x)) x)
19718 ((not (nth 1 x)) (cons (car x) (cons "" (cddr x))))
19719 (t (cons (car x) (cons "" (cdr x))))))
19720 cmds)))
19722 (defun org-agenda-get-restriction-and-command (prefix-descriptions)
19723 "The user interface for selecting an agenda command."
19724 (catch 'exit
19725 (let* ((bfn (buffer-file-name (buffer-base-buffer)))
19726 (restrict-ok (and bfn (org-mode-p)))
19727 (region-p (org-region-active-p))
19728 (custom org-agenda-custom-commands)
19729 (selstring "")
19730 restriction second-time
19731 c entry key type match prefixes rmheader header-end custom1 desc)
19732 (save-window-excursion
19733 (delete-other-windows)
19734 (org-switch-to-buffer-other-window " *Agenda Commands*")
19735 (erase-buffer)
19736 (insert (eval-when-compile
19737 (let ((header
19739 Press key for an agenda command: < Buffer,subtree/region restriction
19740 -------------------------------- > Remove restriction
19741 a Agenda for current week or day e Export agenda views
19742 t List of all TODO entries T Entries with special TODO kwd
19743 m Match a TAGS query M Like m, but only TODO entries
19744 L Timeline for current buffer # List stuck projects (!=configure)
19745 s Search for keywords C Configure custom agenda commands
19746 / Multi-occur
19748 (start 0))
19749 (while (string-match
19750 "\\(^\\| \\|(\\)\\(\\S-\\)\\( \\|=\\)"
19751 header start)
19752 (setq start (match-end 0))
19753 (add-text-properties (match-beginning 2) (match-end 2)
19754 '(face bold) header))
19755 header)))
19756 (setq header-end (move-marker (make-marker) (point)))
19757 (while t
19758 (setq custom1 custom)
19759 (when (eq rmheader t)
19760 (goto-line 1)
19761 (re-search-forward ":" nil t)
19762 (delete-region (match-end 0) (point-at-eol))
19763 (forward-char 1)
19764 (looking-at "-+")
19765 (delete-region (match-end 0) (point-at-eol))
19766 (move-marker header-end (match-end 0)))
19767 (goto-char header-end)
19768 (delete-region (point) (point-max))
19769 (while (setq entry (pop custom1))
19770 (setq key (car entry) desc (nth 1 entry)
19771 type (nth 2 entry) match (nth 3 entry))
19772 (if (> (length key) 1)
19773 (add-to-list 'prefixes (string-to-char key))
19774 (insert
19775 (format
19776 "\n%-4s%-14s: %s"
19777 (org-add-props (copy-sequence key)
19778 '(face bold))
19779 (cond
19780 ((string-match "\\S-" desc) desc)
19781 ((eq type 'agenda) "Agenda for current week or day")
19782 ((eq type 'alltodo) "List of all TODO entries")
19783 ((eq type 'search) "Word search")
19784 ((eq type 'stuck) "List of stuck projects")
19785 ((eq type 'todo) "TODO keyword")
19786 ((eq type 'tags) "Tags query")
19787 ((eq type 'tags-todo) "Tags (TODO)")
19788 ((eq type 'tags-tree) "Tags tree")
19789 ((eq type 'todo-tree) "TODO kwd tree")
19790 ((eq type 'occur-tree) "Occur tree")
19791 ((functionp type) (if (symbolp type)
19792 (symbol-name type)
19793 "Lambda expression"))
19794 (t "???"))
19795 (cond
19796 ((stringp match)
19797 (org-add-props match nil 'face 'org-warning))
19798 (match
19799 (format "set of %d commands" (length match)))
19800 (t ""))))))
19801 (when prefixes
19802 (mapc (lambda (x)
19803 (insert
19804 (format "\n%s %s"
19805 (org-add-props (char-to-string x)
19806 nil 'face 'bold)
19807 (or (cdr (assoc (concat selstring (char-to-string x))
19808 prefix-descriptions))
19809 "Prefix key"))))
19810 prefixes))
19811 (goto-char (point-min))
19812 (when (fboundp 'fit-window-to-buffer)
19813 (if second-time
19814 (if (not (pos-visible-in-window-p (point-max)))
19815 (fit-window-to-buffer))
19816 (setq second-time t)
19817 (fit-window-to-buffer)))
19818 (message "Press key for agenda command%s:"
19819 (if (or restrict-ok org-agenda-overriding-restriction)
19820 (if org-agenda-overriding-restriction
19821 " (restriction lock active)"
19822 (if restriction
19823 (format " (restricted to %s)" restriction)
19824 " (unrestricted)"))
19825 ""))
19826 (setq c (read-char-exclusive))
19827 (message "")
19828 (cond
19829 ((assoc (char-to-string c) custom)
19830 (setq selstring (concat selstring (char-to-string c)))
19831 (throw 'exit (cons selstring restriction)))
19832 ((memq c prefixes)
19833 (setq selstring (concat selstring (char-to-string c))
19834 prefixes nil
19835 rmheader (or rmheader t)
19836 custom (delq nil (mapcar
19837 (lambda (x)
19838 (if (or (= (length (car x)) 1)
19839 (/= (string-to-char (car x)) c))
19841 (cons (substring (car x) 1) (cdr x))))
19842 custom))))
19843 ((and (not restrict-ok) (memq c '(?1 ?0 ?<)))
19844 (message "Restriction is only possible in Org-mode buffers")
19845 (ding) (sit-for 1))
19846 ((eq c ?1)
19847 (org-agenda-remove-restriction-lock 'noupdate)
19848 (setq restriction 'buffer))
19849 ((eq c ?0)
19850 (org-agenda-remove-restriction-lock 'noupdate)
19851 (setq restriction (if region-p 'region 'subtree)))
19852 ((eq c ?<)
19853 (org-agenda-remove-restriction-lock 'noupdate)
19854 (setq restriction
19855 (cond
19856 ((eq restriction 'buffer)
19857 (if region-p 'region 'subtree))
19858 ((memq restriction '(subtree region))
19859 nil)
19860 (t 'buffer))))
19861 ((eq c ?>)
19862 (org-agenda-remove-restriction-lock 'noupdate)
19863 (setq restriction nil))
19864 ((and (equal selstring "") (memq c '(?s ?a ?t ?m ?L ?C ?e ?T ?M ?# ?! ?/)))
19865 (throw 'exit (cons (setq selstring (char-to-string c)) restriction)))
19866 ((and (> (length selstring) 0) (eq c ?\d))
19867 (delete-window)
19868 (org-agenda-get-restriction-and-command prefix-descriptions))
19870 ((equal c ?q) (error "Abort"))
19871 (t (error "Invalid key %c" c))))))))
19873 (defun org-run-agenda-series (name series)
19874 (org-prepare-agenda name)
19875 (let* ((org-agenda-multi t)
19876 (redo (list 'org-run-agenda-series name (list 'quote series)))
19877 (cmds (car series))
19878 (gprops (nth 1 series))
19879 match ;; The byte compiler incorrectly complains about this. Keep it!
19880 cmd type lprops)
19881 (while (setq cmd (pop cmds))
19882 (setq type (car cmd) match (nth 1 cmd) lprops (nth 2 cmd))
19883 (cond
19884 ((eq type 'agenda)
19885 (org-let2 gprops lprops
19886 '(call-interactively 'org-agenda-list)))
19887 ((eq type 'alltodo)
19888 (org-let2 gprops lprops
19889 '(call-interactively 'org-todo-list)))
19890 ((eq type 'search)
19891 (org-let2 gprops lprops
19892 '(org-search-view current-prefix-arg match nil)))
19893 ((eq type 'stuck)
19894 (org-let2 gprops lprops
19895 '(call-interactively 'org-agenda-list-stuck-projects)))
19896 ((eq type 'tags)
19897 (org-let2 gprops lprops
19898 '(org-tags-view current-prefix-arg match)))
19899 ((eq type 'tags-todo)
19900 (org-let2 gprops lprops
19901 '(org-tags-view '(4) match)))
19902 ((eq type 'todo)
19903 (org-let2 gprops lprops
19904 '(org-todo-list match)))
19905 ((fboundp type)
19906 (org-let2 gprops lprops
19907 '(funcall type match)))
19908 (t (error "Invalid type in command series"))))
19909 (widen)
19910 (setq org-agenda-redo-command redo)
19911 (goto-char (point-min)))
19912 (org-finalize-agenda))
19914 ;;;###autoload
19915 (defmacro org-batch-agenda (cmd-key &rest parameters)
19916 "Run an agenda command in batch mode and send the result to STDOUT.
19917 If CMD-KEY is a string of length 1, it is used as a key in
19918 `org-agenda-custom-commands' and triggers this command. If it is a
19919 longer string it is used as a tags/todo match string.
19920 Paramters are alternating variable names and values that will be bound
19921 before running the agenda command."
19922 (let (pars)
19923 (while parameters
19924 (push (list (pop parameters) (if parameters (pop parameters))) pars))
19925 (if (> (length cmd-key) 2)
19926 (eval (list 'let (nreverse pars)
19927 (list 'org-tags-view nil cmd-key)))
19928 (eval (list 'let (nreverse pars) (list 'org-agenda nil cmd-key))))
19929 (set-buffer org-agenda-buffer-name)
19930 (princ (org-encode-for-stdout (buffer-string)))))
19932 (defun org-encode-for-stdout (string)
19933 (if (fboundp 'encode-coding-string)
19934 (encode-coding-string string buffer-file-coding-system)
19935 string))
19937 (defvar org-agenda-info nil)
19939 ;;;###autoload
19940 (defmacro org-batch-agenda-csv (cmd-key &rest parameters)
19941 "Run an agenda command in batch mode and send the result to STDOUT.
19942 If CMD-KEY is a string of length 1, it is used as a key in
19943 `org-agenda-custom-commands' and triggers this command. If it is a
19944 longer string it is used as a tags/todo match string.
19945 Paramters are alternating variable names and values that will be bound
19946 before running the agenda command.
19948 The output gives a line for each selected agenda item. Each
19949 item is a list of comma-separated values, like this:
19951 category,head,type,todo,tags,date,time,extra,priority-l,priority-n
19953 category The category of the item
19954 head The headline, without TODO kwd, TAGS and PRIORITY
19955 type The type of the agenda entry, can be
19956 todo selected in TODO match
19957 tagsmatch selected in tags match
19958 diary imported from diary
19959 deadline a deadline on given date
19960 scheduled scheduled on given date
19961 timestamp entry has timestamp on given date
19962 closed entry was closed on given date
19963 upcoming-deadline warning about deadline
19964 past-scheduled forwarded scheduled item
19965 block entry has date block including g. date
19966 todo The todo keyword, if any
19967 tags All tags including inherited ones, separated by colons
19968 date The relevant date, like 2007-2-14
19969 time The time, like 15:00-16:50
19970 extra Sting with extra planning info
19971 priority-l The priority letter if any was given
19972 priority-n The computed numerical priority
19973 agenda-day The day in the agenda where this is listed"
19975 (let (pars)
19976 (while parameters
19977 (push (list (pop parameters) (if parameters (pop parameters))) pars))
19978 (push (list 'org-agenda-remove-tags t) pars)
19979 (if (> (length cmd-key) 2)
19980 (eval (list 'let (nreverse pars)
19981 (list 'org-tags-view nil cmd-key)))
19982 (eval (list 'let (nreverse pars) (list 'org-agenda nil cmd-key))))
19983 (set-buffer org-agenda-buffer-name)
19984 (let* ((lines (org-split-string (buffer-string) "\n"))
19985 line)
19986 (while (setq line (pop lines))
19987 (catch 'next
19988 (if (not (get-text-property 0 'org-category line)) (throw 'next nil))
19989 (setq org-agenda-info
19990 (org-fix-agenda-info (text-properties-at 0 line)))
19991 (princ
19992 (org-encode-for-stdout
19993 (mapconcat 'org-agenda-export-csv-mapper
19994 '(org-category txt type todo tags date time-of-day extra
19995 priority-letter priority agenda-day)
19996 ",")))
19997 (princ "\n"))))))
19999 (defun org-fix-agenda-info (props)
20000 "Make sure all properties on an agenda item have a canonical form,
20001 so the export commands can easily use it."
20002 (let (tmp re)
20003 (when (setq tmp (plist-get props 'tags))
20004 (setq props (plist-put props 'tags (mapconcat 'identity tmp ":"))))
20005 (when (setq tmp (plist-get props 'date))
20006 (if (integerp tmp) (setq tmp (calendar-gregorian-from-absolute tmp)))
20007 (let ((calendar-date-display-form '(year "-" month "-" day)))
20008 '((format "%4d, %9s %2s, %4s" dayname monthname day year))
20010 (setq tmp (calendar-date-string tmp)))
20011 (setq props (plist-put props 'date tmp)))
20012 (when (setq tmp (plist-get props 'day))
20013 (if (integerp tmp) (setq tmp (calendar-gregorian-from-absolute tmp)))
20014 (let ((calendar-date-display-form '(year "-" month "-" day)))
20015 (setq tmp (calendar-date-string tmp)))
20016 (setq props (plist-put props 'day tmp))
20017 (setq props (plist-put props 'agenda-day tmp)))
20018 (when (setq tmp (plist-get props 'txt))
20019 (when (string-match "\\[#\\([A-Z0-9]\\)\\] ?" tmp)
20020 (plist-put props 'priority-letter (match-string 1 tmp))
20021 (setq tmp (replace-match "" t t tmp)))
20022 (when (and (setq re (plist-get props 'org-todo-regexp))
20023 (setq re (concat "\\`\\.*" re " ?"))
20024 (string-match re tmp))
20025 (plist-put props 'todo (match-string 1 tmp))
20026 (setq tmp (replace-match "" t t tmp)))
20027 (plist-put props 'txt tmp)))
20028 props)
20030 (defun org-agenda-export-csv-mapper (prop)
20031 (let ((res (plist-get org-agenda-info prop)))
20032 (setq res
20033 (cond
20034 ((not res) "")
20035 ((stringp res) res)
20036 (t (prin1-to-string res))))
20037 (while (string-match "," res)
20038 (setq res (replace-match ";" t t res)))
20039 (org-trim res)))
20042 ;;;###autoload
20043 (defun org-store-agenda-views (&rest parameters)
20044 (interactive)
20045 (eval (list 'org-batch-store-agenda-views)))
20047 ;; FIXME, why is this a macro?????
20048 ;;;###autoload
20049 (defmacro org-batch-store-agenda-views (&rest parameters)
20050 "Run all custom agenda commands that have a file argument."
20051 (let ((cmds (org-agenda-normalize-custom-commands org-agenda-custom-commands))
20052 (pop-up-frames nil)
20053 (dir default-directory)
20054 pars cmd thiscmdkey files opts)
20055 (while parameters
20056 (push (list (pop parameters) (if parameters (pop parameters))) pars))
20057 (setq pars (reverse pars))
20058 (save-window-excursion
20059 (while cmds
20060 (setq cmd (pop cmds)
20061 thiscmdkey (car cmd)
20062 opts (nth 4 cmd)
20063 files (nth 5 cmd))
20064 (if (stringp files) (setq files (list files)))
20065 (when files
20066 (eval (list 'let (append org-agenda-exporter-settings opts pars)
20067 (list 'org-agenda nil thiscmdkey)))
20068 (set-buffer org-agenda-buffer-name)
20069 (while files
20070 (eval (list 'let (append org-agenda-exporter-settings opts pars)
20071 (list 'org-write-agenda
20072 (expand-file-name (pop files) dir) t))))
20073 (and (get-buffer org-agenda-buffer-name)
20074 (kill-buffer org-agenda-buffer-name)))))))
20076 (defun org-write-agenda (file &optional nosettings)
20077 "Write the current buffer (an agenda view) as a file.
20078 Depending on the extension of the file name, plain text (.txt),
20079 HTML (.html or .htm) or Postscript (.ps) is produced.
20080 If the extension is .ics, run icalendar export over all files used
20081 to construct the agenda and limit the export to entries listed in the
20082 agenda now.
20083 If NOSETTINGS is given, do not scope the settings of
20084 `org-agenda-exporter-settings' into the export commands. This is used when
20085 the settings have already been scoped and we do not wish to overrule other,
20086 higher priority settings."
20087 (interactive "FWrite agenda to file: ")
20088 (if (not (file-writable-p file))
20089 (error "Cannot write agenda to file %s" file))
20090 (cond
20091 ((string-match "\\.html?\\'" file) (require 'htmlize))
20092 ((string-match "\\.ps\\'" file) (require 'ps-print)))
20093 (org-let (if nosettings nil org-agenda-exporter-settings)
20094 '(save-excursion
20095 (save-window-excursion
20096 (cond
20097 ((string-match "\\.html?\\'" file)
20098 (set-buffer (htmlize-buffer (current-buffer)))
20100 (when (and org-agenda-export-html-style
20101 (string-match "<style>" org-agenda-export-html-style))
20102 ;; replace <style> section with org-agenda-export-html-style
20103 (goto-char (point-min))
20104 (kill-region (- (search-forward "<style") 6)
20105 (search-forward "</style>"))
20106 (insert org-agenda-export-html-style))
20107 (write-file file)
20108 (kill-buffer (current-buffer))
20109 (message "HTML written to %s" file))
20110 ((string-match "\\.ps\\'" file)
20111 (ps-print-buffer-with-faces file)
20112 (message "Postscript written to %s" file))
20113 ((string-match "\\.ics\\'" file)
20114 (let ((org-agenda-marker-table
20115 (org-create-marker-find-array
20116 (org-agenda-collect-markers)))
20117 (org-icalendar-verify-function 'org-check-agenda-marker-table)
20118 (org-combined-agenda-icalendar-file file))
20119 (apply 'org-export-icalendar 'combine (org-agenda-files))))
20121 (let ((bs (buffer-string)))
20122 (find-file file)
20123 (insert bs)
20124 (save-buffer 0)
20125 (kill-buffer (current-buffer))
20126 (message "Plain text written to %s" file))))))
20127 (set-buffer org-agenda-buffer-name)))
20129 (defun org-agenda-collect-markers ()
20130 "Collect the markers pointing to entries in the agenda buffer."
20131 (let (m markers)
20132 (save-excursion
20133 (goto-char (point-min))
20134 (while (not (eobp))
20135 (when (setq m (or (get-text-property (point) 'org-hd-marker)
20136 (get-text-property (point) 'org-marker)))
20137 (push m markers))
20138 (beginning-of-line 2)))
20139 (nreverse markers)))
20141 (defun org-create-marker-find-array (marker-list)
20142 "Create a alist of files names with all marker positions in that file."
20143 (let (f tbl m a p)
20144 (while (setq m (pop marker-list))
20145 (setq p (marker-position m)
20146 f (buffer-file-name (or (buffer-base-buffer
20147 (marker-buffer m))
20148 (marker-buffer m))))
20149 (if (setq a (assoc f tbl))
20150 (push (marker-position m) (cdr a))
20151 (push (list f p) tbl)))
20152 (mapcar (lambda (x) (setcdr x (sort (copy-sequence (cdr x)) '<)) x)
20153 tbl)))
20155 (defvar org-agenda-marker-table nil) ; dyamically scoped parameter
20156 (defun org-check-agenda-marker-table ()
20157 "Check of the current entry is on the marker list."
20158 (let ((file (buffer-file-name (or (buffer-base-buffer) (current-buffer))))
20160 (and (setq a (assoc file org-agenda-marker-table))
20161 (save-match-data
20162 (save-excursion
20163 (org-back-to-heading t)
20164 (member (point) (cdr a)))))))
20166 (defmacro org-no-read-only (&rest body)
20167 "Inhibit read-only for BODY."
20168 `(let ((inhibit-read-only t)) ,@body))
20170 (defun org-check-for-org-mode ()
20171 "Make sure current buffer is in org-mode. Error if not."
20172 (or (org-mode-p)
20173 (error "Cannot execute org-mode agenda command on buffer in %s."
20174 major-mode)))
20176 (defun org-fit-agenda-window ()
20177 "Fit the window to the buffer size."
20178 (and (memq org-agenda-window-setup '(reorganize-frame))
20179 (fboundp 'fit-window-to-buffer)
20180 (fit-window-to-buffer
20182 (floor (* (frame-height) (cdr org-agenda-window-frame-fractions)))
20183 (floor (* (frame-height) (car org-agenda-window-frame-fractions))))))
20185 ;;; Agenda file list
20187 (defun org-agenda-files (&optional unrestricted)
20188 "Get the list of agenda files.
20189 Optional UNRESTRICTED means return the full list even if a restriction
20190 is currently in place."
20191 (let ((files
20192 (cond
20193 ((and (not unrestricted) (get 'org-agenda-files 'org-restrict)))
20194 ((stringp org-agenda-files) (org-read-agenda-file-list))
20195 ((listp org-agenda-files) org-agenda-files)
20196 (t (error "Invalid value of `org-agenda-files'")))))
20197 (setq files (apply 'append
20198 (mapcar (lambda (f)
20199 (if (file-directory-p f)
20200 (directory-files f t
20201 org-agenda-file-regexp)
20202 (list f)))
20203 files)))
20204 (if org-agenda-skip-unavailable-files
20205 (delq nil
20206 (mapcar (function
20207 (lambda (file)
20208 (and (file-readable-p file) file)))
20209 files))
20210 files))) ; `org-check-agenda-file' will remove them from the list
20212 (defun org-edit-agenda-file-list ()
20213 "Edit the list of agenda files.
20214 Depending on setup, this either uses customize to edit the variable
20215 `org-agenda-files', or it visits the file that is holding the list. In the
20216 latter case, the buffer is set up in a way that saving it automatically kills
20217 the buffer and restores the previous window configuration."
20218 (interactive)
20219 (if (stringp org-agenda-files)
20220 (let ((cw (current-window-configuration)))
20221 (find-file org-agenda-files)
20222 (org-set-local 'org-window-configuration cw)
20223 (org-add-hook 'after-save-hook
20224 (lambda ()
20225 (set-window-configuration
20226 (prog1 org-window-configuration
20227 (kill-buffer (current-buffer))))
20228 (org-install-agenda-files-menu)
20229 (message "New agenda file list installed"))
20230 nil 'local)
20231 (message "%s" (substitute-command-keys
20232 "Edit list and finish with \\[save-buffer]")))
20233 (customize-variable 'org-agenda-files)))
20235 (defun org-store-new-agenda-file-list (list)
20236 "Set new value for the agenda file list and save it correcly."
20237 (if (stringp org-agenda-files)
20238 (let ((f org-agenda-files) b)
20239 (while (setq b (find-buffer-visiting f)) (kill-buffer b))
20240 (with-temp-file f
20241 (insert (mapconcat 'identity list "\n") "\n")))
20242 (let ((org-mode-hook nil) (default-major-mode 'fundamental-mode))
20243 (setq org-agenda-files list)
20244 (customize-save-variable 'org-agenda-files org-agenda-files))))
20246 (defun org-read-agenda-file-list ()
20247 "Read the list of agenda files from a file."
20248 (when (stringp org-agenda-files)
20249 (with-temp-buffer
20250 (insert-file-contents org-agenda-files)
20251 (org-split-string (buffer-string) "[ \t\r\n]*?[\r\n][ \t\r\n]*"))))
20254 ;;;###autoload
20255 (defun org-cycle-agenda-files ()
20256 "Cycle through the files in `org-agenda-files'.
20257 If the current buffer visits an agenda file, find the next one in the list.
20258 If the current buffer does not, find the first agenda file."
20259 (interactive)
20260 (let* ((fs (org-agenda-files t))
20261 (files (append fs (list (car fs))))
20262 (tcf (if buffer-file-name (file-truename buffer-file-name)))
20263 file)
20264 (unless files (error "No agenda files"))
20265 (catch 'exit
20266 (while (setq file (pop files))
20267 (if (equal (file-truename file) tcf)
20268 (when (car files)
20269 (find-file (car files))
20270 (throw 'exit t))))
20271 (find-file (car fs)))
20272 (if (buffer-base-buffer) (switch-to-buffer (buffer-base-buffer)))))
20274 (defun org-agenda-file-to-front (&optional to-end)
20275 "Move/add the current file to the top of the agenda file list.
20276 If the file is not present in the list, it is added to the front. If it is
20277 present, it is moved there. With optional argument TO-END, add/move to the
20278 end of the list."
20279 (interactive "P")
20280 (let ((org-agenda-skip-unavailable-files nil)
20281 (file-alist (mapcar (lambda (x)
20282 (cons (file-truename x) x))
20283 (org-agenda-files t)))
20284 (ctf (file-truename buffer-file-name))
20285 x had)
20286 (setq x (assoc ctf file-alist) had x)
20288 (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name))))
20289 (if to-end
20290 (setq file-alist (append (delq x file-alist) (list x)))
20291 (setq file-alist (cons x (delq x file-alist))))
20292 (org-store-new-agenda-file-list (mapcar 'cdr file-alist))
20293 (org-install-agenda-files-menu)
20294 (message "File %s to %s of agenda file list"
20295 (if had "moved" "added") (if to-end "end" "front"))))
20297 (defun org-remove-file (&optional file)
20298 "Remove current file from the list of files in variable `org-agenda-files'.
20299 These are the files which are being checked for agenda entries.
20300 Optional argument FILE means, use this file instead of the current."
20301 (interactive)
20302 (let* ((org-agenda-skip-unavailable-files nil)
20303 (file (or file buffer-file-name))
20304 (true-file (file-truename file))
20305 (afile (abbreviate-file-name file))
20306 (files (delq nil (mapcar
20307 (lambda (x)
20308 (if (equal true-file
20309 (file-truename x))
20310 nil x))
20311 (org-agenda-files t)))))
20312 (if (not (= (length files) (length (org-agenda-files t))))
20313 (progn
20314 (org-store-new-agenda-file-list files)
20315 (org-install-agenda-files-menu)
20316 (message "Removed file: %s" afile))
20317 (message "File was not in list: %s (not removed)" afile))))
20319 (defun org-file-menu-entry (file)
20320 (vector file (list 'find-file file) t))
20322 (defun org-check-agenda-file (file)
20323 "Make sure FILE exists. If not, ask user what to do."
20324 (when (not (file-exists-p file))
20325 (message "non-existent file %s. [R]emove from list or [A]bort?"
20326 (abbreviate-file-name file))
20327 (let ((r (downcase (read-char-exclusive))))
20328 (cond
20329 ((equal r ?r)
20330 (org-remove-file file)
20331 (throw 'nextfile t))
20332 (t (error "Abort"))))))
20334 ;;; Agenda prepare and finalize
20336 (defvar org-agenda-multi nil) ; dynammically scoped
20337 (defvar org-agenda-buffer-name "*Org Agenda*")
20338 (defvar org-pre-agenda-window-conf nil)
20339 (defvar org-agenda-name nil)
20340 (defun org-prepare-agenda (&optional name)
20341 (setq org-todo-keywords-for-agenda nil)
20342 (setq org-done-keywords-for-agenda nil)
20343 (if org-agenda-multi
20344 (progn
20345 (setq buffer-read-only nil)
20346 (goto-char (point-max))
20347 (unless (or (bobp) org-agenda-compact-blocks)
20348 (insert "\n" (make-string (window-width) ?=) "\n"))
20349 (narrow-to-region (point) (point-max)))
20350 (org-agenda-reset-markers)
20351 (org-prepare-agenda-buffers (org-agenda-files))
20352 (setq org-todo-keywords-for-agenda
20353 (org-uniquify org-todo-keywords-for-agenda))
20354 (setq org-done-keywords-for-agenda
20355 (org-uniquify org-done-keywords-for-agenda))
20356 (let* ((abuf (get-buffer-create org-agenda-buffer-name))
20357 (awin (get-buffer-window abuf)))
20358 (cond
20359 ((equal (current-buffer) abuf) nil)
20360 (awin (select-window awin))
20361 ((not (setq org-pre-agenda-window-conf (current-window-configuration))))
20362 ((equal org-agenda-window-setup 'current-window)
20363 (switch-to-buffer abuf))
20364 ((equal org-agenda-window-setup 'other-window)
20365 (org-switch-to-buffer-other-window abuf))
20366 ((equal org-agenda-window-setup 'other-frame)
20367 (switch-to-buffer-other-frame abuf))
20368 ((equal org-agenda-window-setup 'reorganize-frame)
20369 (delete-other-windows)
20370 (org-switch-to-buffer-other-window abuf))))
20371 (setq buffer-read-only nil)
20372 (erase-buffer)
20373 (org-agenda-mode)
20374 (and name (not org-agenda-name)
20375 (org-set-local 'org-agenda-name name)))
20376 (setq buffer-read-only nil))
20378 (defun org-finalize-agenda ()
20379 "Finishing touch for the agenda buffer, called just before displaying it."
20380 (unless org-agenda-multi
20381 (save-excursion
20382 (let ((inhibit-read-only t))
20383 (goto-char (point-min))
20384 (while (org-activate-bracket-links (point-max))
20385 (add-text-properties (match-beginning 0) (match-end 0)
20386 '(face org-link)))
20387 (org-agenda-align-tags)
20388 (unless org-agenda-with-colors
20389 (remove-text-properties (point-min) (point-max) '(face nil))))
20390 (if (and (boundp 'org-overriding-columns-format)
20391 org-overriding-columns-format)
20392 (org-set-local 'org-overriding-columns-format
20393 org-overriding-columns-format))
20394 (if (and (boundp 'org-agenda-view-columns-initially)
20395 org-agenda-view-columns-initially)
20396 (org-agenda-columns))
20397 (when org-agenda-fontify-priorities
20398 (org-fontify-priorities))
20399 (run-hooks 'org-finalize-agenda-hook)
20400 (setq org-agenda-type (get-text-property (point) 'org-agenda-type))
20403 (defun org-fontify-priorities ()
20404 "Make highest priority lines bold, and lowest italic."
20405 (interactive)
20406 (mapc (lambda (o) (if (eq (org-overlay-get o 'org-type) 'org-priority)
20407 (org-delete-overlay o)))
20408 (org-overlays-in (point-min) (point-max)))
20409 (save-excursion
20410 (let ((inhibit-read-only t)
20411 b e p ov h l)
20412 (goto-char (point-min))
20413 (while (re-search-forward "\\[#\\(.\\)\\]" nil t)
20414 (setq h (or (get-char-property (point) 'org-highest-priority)
20415 org-highest-priority)
20416 l (or (get-char-property (point) 'org-lowest-priority)
20417 org-lowest-priority)
20418 p (string-to-char (match-string 1))
20419 b (match-beginning 0) e (point-at-eol)
20420 ov (org-make-overlay b e))
20421 (org-overlay-put
20422 ov 'face
20423 (cond ((listp org-agenda-fontify-priorities)
20424 (cdr (assoc p org-agenda-fontify-priorities)))
20425 ((equal p l) 'italic)
20426 ((equal p h) 'bold)))
20427 (org-overlay-put ov 'org-type 'org-priority)))))
20429 (defun org-prepare-agenda-buffers (files)
20430 "Create buffers for all agenda files, protect archived trees and comments."
20431 (interactive)
20432 (let ((pa '(:org-archived t))
20433 (pc '(:org-comment t))
20434 (pall '(:org-archived t :org-comment t))
20435 (inhibit-read-only t)
20436 (rea (concat ":" org-archive-tag ":"))
20437 bmp file re)
20438 (save-excursion
20439 (save-restriction
20440 (while (setq file (pop files))
20441 (if (bufferp file)
20442 (set-buffer file)
20443 (org-check-agenda-file file)
20444 (set-buffer (org-get-agenda-file-buffer file)))
20445 (widen)
20446 (setq bmp (buffer-modified-p))
20447 (org-refresh-category-properties)
20448 (setq org-todo-keywords-for-agenda
20449 (append org-todo-keywords-for-agenda org-todo-keywords-1))
20450 (setq org-done-keywords-for-agenda
20451 (append org-done-keywords-for-agenda org-done-keywords))
20452 (save-excursion
20453 (remove-text-properties (point-min) (point-max) pall)
20454 (when org-agenda-skip-archived-trees
20455 (goto-char (point-min))
20456 (while (re-search-forward rea nil t)
20457 (if (org-on-heading-p t)
20458 (add-text-properties (point-at-bol) (org-end-of-subtree t) pa))))
20459 (goto-char (point-min))
20460 (setq re (concat "^\\*+ +" org-comment-string "\\>"))
20461 (while (re-search-forward re nil t)
20462 (add-text-properties
20463 (match-beginning 0) (org-end-of-subtree t) pc)))
20464 (set-buffer-modified-p bmp))))))
20466 (defvar org-agenda-skip-function nil
20467 "Function to be called at each match during agenda construction.
20468 If this function returns nil, the current match should not be skipped.
20469 Otherwise, the function must return a position from where the search
20470 should be continued.
20471 This may also be a Lisp form, it will be evaluated.
20472 Never set this variable using `setq' or so, because then it will apply
20473 to all future agenda commands. Instead, bind it with `let' to scope
20474 it dynamically into the agenda-constructing command. A good way to set
20475 it is through options in org-agenda-custom-commands.")
20477 (defun org-agenda-skip ()
20478 "Throw to `:skip' in places that should be skipped.
20479 Also moves point to the end of the skipped region, so that search can
20480 continue from there."
20481 (let ((p (point-at-bol)) to fp)
20482 (and org-agenda-skip-archived-trees
20483 (get-text-property p :org-archived)
20484 (org-end-of-subtree t)
20485 (throw :skip t))
20486 (and (get-text-property p :org-comment)
20487 (org-end-of-subtree t)
20488 (throw :skip t))
20489 (if (equal (char-after p) ?#) (throw :skip t))
20490 (when (and (or (setq fp (functionp org-agenda-skip-function))
20491 (consp org-agenda-skip-function))
20492 (setq to (save-excursion
20493 (save-match-data
20494 (if fp
20495 (funcall org-agenda-skip-function)
20496 (eval org-agenda-skip-function))))))
20497 (goto-char to)
20498 (throw :skip t))))
20500 (defvar org-agenda-markers nil
20501 "List of all currently active markers created by `org-agenda'.")
20502 (defvar org-agenda-last-marker-time (time-to-seconds (current-time))
20503 "Creation time of the last agenda marker.")
20505 (defun org-agenda-new-marker (&optional pos)
20506 "Return a new agenda marker.
20507 Org-mode keeps a list of these markers and resets them when they are
20508 no longer in use."
20509 (let ((m (copy-marker (or pos (point)))))
20510 (setq org-agenda-last-marker-time (time-to-seconds (current-time)))
20511 (push m org-agenda-markers)
20514 (defun org-agenda-reset-markers ()
20515 "Reset markers created by `org-agenda'."
20516 (while org-agenda-markers
20517 (move-marker (pop org-agenda-markers) nil)))
20519 (defun org-get-agenda-file-buffer (file)
20520 "Get a buffer visiting FILE. If the buffer needs to be created, add
20521 it to the list of buffers which might be released later."
20522 (let ((buf (org-find-base-buffer-visiting file)))
20523 (if buf
20524 buf ; just return it
20525 ;; Make a new buffer and remember it
20526 (setq buf (find-file-noselect file))
20527 (if buf (push buf org-agenda-new-buffers))
20528 buf)))
20530 (defun org-release-buffers (blist)
20531 "Release all buffers in list, asking the user for confirmation when needed.
20532 When a buffer is unmodified, it is just killed. When modified, it is saved
20533 \(if the user agrees) and then killed."
20534 (let (buf file)
20535 (while (setq buf (pop blist))
20536 (setq file (buffer-file-name buf))
20537 (when (and (buffer-modified-p buf)
20538 file
20539 (y-or-n-p (format "Save file %s? " file)))
20540 (with-current-buffer buf (save-buffer)))
20541 (kill-buffer buf))))
20543 (defun org-get-category (&optional pos)
20544 "Get the category applying to position POS."
20545 (get-text-property (or pos (point)) 'org-category))
20547 ;;; Agenda timeline
20549 (defvar org-agenda-only-exact-dates nil) ; dynamically scoped
20551 (defun org-timeline (&optional include-all)
20552 "Show a time-sorted view of the entries in the current org file.
20553 Only entries with a time stamp of today or later will be listed. With
20554 \\[universal-argument] prefix, all unfinished TODO items will also be shown,
20555 under the current date.
20556 If the buffer contains an active region, only check the region for
20557 dates."
20558 (interactive "P")
20559 (require 'calendar)
20560 (org-compile-prefix-format 'timeline)
20561 (org-set-sorting-strategy 'timeline)
20562 (let* ((dopast t)
20563 (dotodo include-all)
20564 (doclosed org-agenda-show-log)
20565 (entry buffer-file-name)
20566 (date (calendar-current-date))
20567 (beg (if (org-region-active-p) (region-beginning) (point-min)))
20568 (end (if (org-region-active-p) (region-end) (point-max)))
20569 (day-numbers (org-get-all-dates beg end 'no-ranges
20570 t doclosed ; always include today
20571 org-timeline-show-empty-dates))
20572 (org-deadline-warning-days 0)
20573 (org-agenda-only-exact-dates t)
20574 (today (time-to-days (current-time)))
20575 (past t)
20576 args
20577 s e rtn d emptyp)
20578 (setq org-agenda-redo-command
20579 (list 'progn
20580 (list 'org-switch-to-buffer-other-window (current-buffer))
20581 (list 'org-timeline (list 'quote include-all))))
20582 (if (not dopast)
20583 ;; Remove past dates from the list of dates.
20584 (setq day-numbers (delq nil (mapcar (lambda(x)
20585 (if (>= x today) x nil))
20586 day-numbers))))
20587 (org-prepare-agenda (concat "Timeline "
20588 (file-name-nondirectory buffer-file-name)))
20589 (if doclosed (push :closed args))
20590 (push :timestamp args)
20591 (push :deadline args)
20592 (push :scheduled args)
20593 (push :sexp args)
20594 (if dotodo (push :todo args))
20595 (while (setq d (pop day-numbers))
20596 (if (and (listp d) (eq (car d) :omitted))
20597 (progn
20598 (setq s (point))
20599 (insert (format "\n[... %d empty days omitted]\n\n" (cdr d)))
20600 (put-text-property s (1- (point)) 'face 'org-agenda-structure))
20601 (if (listp d) (setq d (car d) emptyp t) (setq emptyp nil))
20602 (if (and (>= d today)
20603 dopast
20604 past)
20605 (progn
20606 (setq past nil)
20607 (insert (make-string 79 ?-) "\n")))
20608 (setq date (calendar-gregorian-from-absolute d))
20609 (setq s (point))
20610 (setq rtn (and (not emptyp)
20611 (apply 'org-agenda-get-day-entries entry
20612 date args)))
20613 (if (or rtn (equal d today) org-timeline-show-empty-dates)
20614 (progn
20615 (insert
20616 (if (stringp org-agenda-format-date)
20617 (format-time-string org-agenda-format-date
20618 (org-time-from-absolute date))
20619 (funcall org-agenda-format-date date))
20620 "\n")
20621 (put-text-property s (1- (point)) 'face 'org-agenda-structure)
20622 (put-text-property s (1- (point)) 'org-date-line t)
20623 (if (equal d today)
20624 (put-text-property s (1- (point)) 'org-today t))
20625 (and rtn (insert (org-finalize-agenda-entries rtn) "\n"))
20626 (put-text-property s (1- (point)) 'day d)))))
20627 (goto-char (point-min))
20628 (goto-char (or (text-property-any (point-min) (point-max) 'org-today t)
20629 (point-min)))
20630 (add-text-properties (point-min) (point-max) '(org-agenda-type timeline))
20631 (org-finalize-agenda)
20632 (setq buffer-read-only t)))
20634 (defun org-get-all-dates (beg end &optional no-ranges force-today inactive empty pre-re)
20635 "Return a list of all relevant day numbers from BEG to END buffer positions.
20636 If NO-RANGES is non-nil, include only the start and end dates of a range,
20637 not every single day in the range. If FORCE-TODAY is non-nil, make
20638 sure that TODAY is included in the list. If INACTIVE is non-nil, also
20639 inactive time stamps (those in square brackets) are included.
20640 When EMPTY is non-nil, also include days without any entries."
20641 (let ((re (concat
20642 (if pre-re pre-re "")
20643 (if inactive org-ts-regexp-both org-ts-regexp)))
20644 dates dates1 date day day1 day2 ts1 ts2)
20645 (if force-today
20646 (setq dates (list (time-to-days (current-time)))))
20647 (save-excursion
20648 (goto-char beg)
20649 (while (re-search-forward re end t)
20650 (setq day (time-to-days (org-time-string-to-time
20651 (substring (match-string 1) 0 10))))
20652 (or (memq day dates) (push day dates)))
20653 (unless no-ranges
20654 (goto-char beg)
20655 (while (re-search-forward org-tr-regexp end t)
20656 (setq ts1 (substring (match-string 1) 0 10)
20657 ts2 (substring (match-string 2) 0 10)
20658 day1 (time-to-days (org-time-string-to-time ts1))
20659 day2 (time-to-days (org-time-string-to-time ts2)))
20660 (while (< (setq day1 (1+ day1)) day2)
20661 (or (memq day1 dates) (push day1 dates)))))
20662 (setq dates (sort dates '<))
20663 (when empty
20664 (while (setq day (pop dates))
20665 (setq day2 (car dates))
20666 (push day dates1)
20667 (when (and day2 empty)
20668 (if (or (eq empty t)
20669 (and (numberp empty) (<= (- day2 day) empty)))
20670 (while (< (setq day (1+ day)) day2)
20671 (push (list day) dates1))
20672 (push (cons :omitted (- day2 day)) dates1))))
20673 (setq dates (nreverse dates1)))
20674 dates)))
20676 ;;; Agenda Daily/Weekly
20678 (defvar org-agenda-overriding-arguments nil) ; dynamically scoped parameter
20679 (defvar org-agenda-start-day nil) ; dynamically scoped parameter
20680 (defvar org-agenda-last-arguments nil
20681 "The arguments of the previous call to org-agenda")
20682 (defvar org-starting-day nil) ; local variable in the agenda buffer
20683 (defvar org-agenda-span nil) ; local variable in the agenda buffer
20684 (defvar org-include-all-loc nil) ; local variable
20685 (defvar org-agenda-remove-date nil) ; dynamically scoped FIXME: not used???
20687 ;;;###autoload
20688 (defun org-agenda-list (&optional include-all start-day ndays)
20689 "Produce a daily/weekly view from all files in variable `org-agenda-files'.
20690 The view will be for the current day or week, but from the overview buffer
20691 you will be able to go to other days/weeks.
20693 With one \\[universal-argument] prefix argument INCLUDE-ALL,
20694 all unfinished TODO items will also be shown, before the agenda.
20695 This feature is considered obsolete, please use the TODO list or a block
20696 agenda instead.
20698 With a numeric prefix argument in an interactive call, the agenda will
20699 span INCLUDE-ALL days. Lisp programs should instead specify NDAYS to change
20700 the number of days. NDAYS defaults to `org-agenda-ndays'.
20702 START-DAY defaults to TODAY, or to the most recent match for the weekday
20703 given in `org-agenda-start-on-weekday'."
20704 (interactive "P")
20705 (if (and (integerp include-all) (> include-all 0))
20706 (setq ndays include-all include-all nil))
20707 (setq ndays (or ndays org-agenda-ndays)
20708 start-day (or start-day org-agenda-start-day))
20709 (if org-agenda-overriding-arguments
20710 (setq include-all (car org-agenda-overriding-arguments)
20711 start-day (nth 1 org-agenda-overriding-arguments)
20712 ndays (nth 2 org-agenda-overriding-arguments)))
20713 (if (stringp start-day)
20714 ;; Convert to an absolute day number
20715 (setq start-day (time-to-days (org-read-date nil t start-day))))
20716 (setq org-agenda-last-arguments (list include-all start-day ndays))
20717 (org-compile-prefix-format 'agenda)
20718 (org-set-sorting-strategy 'agenda)
20719 (require 'calendar)
20720 (let* ((org-agenda-start-on-weekday
20721 (if (or (equal ndays 7) (and (null ndays) (equal 7 org-agenda-ndays)))
20722 org-agenda-start-on-weekday nil))
20723 (thefiles (org-agenda-files))
20724 (files thefiles)
20725 (today (time-to-days
20726 (time-subtract (current-time)
20727 (list 0 (* 3600 org-extend-today-until) 0))))
20728 (sd (or start-day today))
20729 (start (if (or (null org-agenda-start-on-weekday)
20730 (< org-agenda-ndays 7))
20732 (let* ((nt (calendar-day-of-week
20733 (calendar-gregorian-from-absolute sd)))
20734 (n1 org-agenda-start-on-weekday)
20735 (d (- nt n1)))
20736 (- sd (+ (if (< d 0) 7 0) d)))))
20737 (day-numbers (list start))
20738 (day-cnt 0)
20739 (inhibit-redisplay (not debug-on-error))
20740 s e rtn rtnall file date d start-pos end-pos todayp nd)
20741 (setq org-agenda-redo-command
20742 (list 'org-agenda-list (list 'quote include-all) start-day ndays))
20743 ;; Make the list of days
20744 (setq ndays (or ndays org-agenda-ndays)
20745 nd ndays)
20746 (while (> ndays 1)
20747 (push (1+ (car day-numbers)) day-numbers)
20748 (setq ndays (1- ndays)))
20749 (setq day-numbers (nreverse day-numbers))
20750 (org-prepare-agenda "Day/Week")
20751 (org-set-local 'org-starting-day (car day-numbers))
20752 (org-set-local 'org-include-all-loc include-all)
20753 (org-set-local 'org-agenda-span
20754 (org-agenda-ndays-to-span nd))
20755 (when (and (or include-all org-agenda-include-all-todo)
20756 (member today day-numbers))
20757 (setq files thefiles
20758 rtnall nil)
20759 (while (setq file (pop files))
20760 (catch 'nextfile
20761 (org-check-agenda-file file)
20762 (setq date (calendar-gregorian-from-absolute today)
20763 rtn (org-agenda-get-day-entries
20764 file date :todo))
20765 (setq rtnall (append rtnall rtn))))
20766 (when rtnall
20767 (insert "ALL CURRENTLY OPEN TODO ITEMS:\n")
20768 (add-text-properties (point-min) (1- (point))
20769 (list 'face 'org-agenda-structure))
20770 (insert (org-finalize-agenda-entries rtnall) "\n")))
20771 (unless org-agenda-compact-blocks
20772 (let* ((d1 (car day-numbers))
20773 (d2 (org-last day-numbers))
20774 (w1 (org-days-to-iso-week d1))
20775 (w2 (org-days-to-iso-week d2)))
20776 (setq s (point))
20777 (insert (capitalize (symbol-name (org-agenda-ndays-to-span nd)))
20778 "-agenda"
20779 (if (< (- d2 d1) 350)
20780 (if (= w1 w2)
20781 (format " (W%02d)" w1)
20782 (format " (W%02d-W%02d)" w1 w2))
20784 ":\n"))
20785 (add-text-properties s (1- (point)) (list 'face 'org-agenda-structure
20786 'org-date-line t)))
20787 (while (setq d (pop day-numbers))
20788 (setq date (calendar-gregorian-from-absolute d)
20789 s (point))
20790 (if (or (setq todayp (= d today))
20791 (and (not start-pos) (= d sd)))
20792 (setq start-pos (point))
20793 (if (and start-pos (not end-pos))
20794 (setq end-pos (point))))
20795 (setq files thefiles
20796 rtnall nil)
20797 (while (setq file (pop files))
20798 (catch 'nextfile
20799 (org-check-agenda-file file)
20800 (if org-agenda-show-log
20801 (setq rtn (org-agenda-get-day-entries
20802 file date
20803 :deadline :scheduled :timestamp :sexp :closed))
20804 (setq rtn (org-agenda-get-day-entries
20805 file date
20806 :deadline :scheduled :sexp :timestamp)))
20807 (setq rtnall (append rtnall rtn))))
20808 (if org-agenda-include-diary
20809 (progn
20810 (require 'diary-lib)
20811 (setq rtn (org-get-entries-from-diary date))
20812 (setq rtnall (append rtnall rtn))))
20813 (if (or rtnall org-agenda-show-all-dates)
20814 (progn
20815 (setq day-cnt (1+ day-cnt))
20816 (insert
20817 (if (stringp org-agenda-format-date)
20818 (format-time-string org-agenda-format-date
20819 (org-time-from-absolute date))
20820 (funcall org-agenda-format-date date))
20821 "\n")
20822 (put-text-property s (1- (point)) 'face 'org-agenda-structure)
20823 (put-text-property s (1- (point)) 'org-date-line t)
20824 (put-text-property s (1- (point)) 'org-day-cnt day-cnt)
20825 (if todayp (put-text-property s (1- (point)) 'org-today t))
20826 (if rtnall (insert
20827 (org-finalize-agenda-entries
20828 (org-agenda-add-time-grid-maybe
20829 rtnall nd todayp))
20830 "\n"))
20831 (put-text-property s (1- (point)) 'day d)
20832 (put-text-property s (1- (point)) 'org-day-cnt day-cnt))))
20833 (goto-char (point-min))
20834 (org-fit-agenda-window)
20835 (unless (and (pos-visible-in-window-p (point-min))
20836 (pos-visible-in-window-p (point-max)))
20837 (goto-char (1- (point-max)))
20838 (recenter -1)
20839 (if (not (pos-visible-in-window-p (or start-pos 1)))
20840 (progn
20841 (goto-char (or start-pos 1))
20842 (recenter 1))))
20843 (goto-char (or start-pos 1))
20844 (add-text-properties (point-min) (point-max) '(org-agenda-type agenda))
20845 (org-finalize-agenda)
20846 (setq buffer-read-only t)
20847 (message "")))
20849 (defun org-agenda-ndays-to-span (n)
20850 (cond ((< n 7) 'day) ((= n 7) 'week) ((< n 32) 'month) (t 'year)))
20852 ;;; Agenda word search
20854 (defvar org-agenda-search-history nil)
20855 (defvar org-todo-only nil)
20857 (defvar org-search-syntax-table nil
20858 "Special syntax table for org-mode search.
20859 In this table, we have single quotes not as word constituents, to
20860 that when \"+Ameli\" is searchd as a work, it will also match \"Ameli's\"")
20862 (defun org-search-syntax-table ()
20863 (unless org-search-syntax-table
20864 (setq org-search-syntax-table (copy-syntax-table org-mode-syntax-table))
20865 (modify-syntax-entry ?' "." org-search-syntax-table)
20866 (modify-syntax-entry ?` "." org-search-syntax-table))
20867 org-search-syntax-table)
20869 ;;;###autoload
20870 (defun org-search-view (&optional todo-only string edit-at)
20871 "Show all entries that contain words or regular expressions.
20872 If the first character of the search string is an asterisks,
20873 search only the headlines.
20875 With optional prefix argument TODO-ONLY, only consider entries that are
20876 TODO entries. The argument STRING can be used to pass a default search
20877 string into this function. If EDIT-AT is non-nil, it means that the
20878 user should get a chance to edit this string, with cursor at position
20879 EDIT-AT.
20881 The search string is broken into \"words\" by splitting at whitespace.
20882 The individual words are then interpreted as a boolean expression with
20883 logical AND. Words prefixed with a minus must not occur in the entry.
20884 Words without a prefix or prefixed with a plus must occur in the entry.
20885 Matching is case-insensitive and the words are enclosed by word delimiters.
20887 Words enclosed by curly braces are interpreted as regular expressions
20888 that must or must not match in the entry.
20890 If the search string starts with an asterisk, search only in headlines.
20891 If (possibly after the leading star) the search string starts with an
20892 exclamation mark, this also means to look at TODO entries only, an effect
20893 that can also be achieved with a prefix argument.
20895 This command searches the agenda files, and in addition the files listed
20896 in `org-agenda-text-search-extra-files'."
20897 (interactive "P")
20898 (org-compile-prefix-format 'search)
20899 (org-set-sorting-strategy 'search)
20900 (org-prepare-agenda "SEARCH")
20901 (let* ((props (list 'face nil
20902 'done-face 'org-done
20903 'org-not-done-regexp org-not-done-regexp
20904 'org-todo-regexp org-todo-regexp
20905 'mouse-face 'highlight
20906 'keymap org-agenda-keymap
20907 'help-echo (format "mouse-2 or RET jump to location")))
20908 regexp rtn rtnall files file pos
20909 marker priority category tags c neg re
20910 ee txt beg end words regexps+ regexps- hdl-only buffer beg1 str)
20911 (unless (and (not edit-at)
20912 (stringp string)
20913 (string-match "\\S-" string))
20914 (setq string (read-string "[+-]Word/{Regexp} ...: "
20915 (cond
20916 ((integerp edit-at) (cons string edit-at))
20917 (edit-at string))
20918 'org-agenda-search-history)))
20919 (org-set-local 'org-todo-only todo-only)
20920 (setq org-agenda-redo-command
20921 (list 'org-search-view (if todo-only t nil) string
20922 '(if current-prefix-arg 1 nil)))
20923 (setq org-agenda-query-string string)
20925 (if (equal (string-to-char string) ?*)
20926 (setq hdl-only t
20927 words (substring string 1))
20928 (setq words string))
20929 (when (equal (string-to-char words) ?!)
20930 (setq todo-only t
20931 words (substring words 1)))
20932 (setq words (org-split-string words))
20933 (mapc (lambda (w)
20934 (setq c (string-to-char w))
20935 (if (equal c ?-)
20936 (setq neg t w (substring w 1))
20937 (if (equal c ?+)
20938 (setq neg nil w (substring w 1))
20939 (setq neg nil)))
20940 (if (string-match "\\`{.*}\\'" w)
20941 (setq re (substring w 1 -1))
20942 (setq re (concat "\\<" (regexp-quote (downcase w)) "\\>")))
20943 (if neg (push re regexps-) (push re regexps+)))
20944 words)
20945 (setq regexps+ (sort regexps+ (lambda (a b) (> (length a) (length b)))))
20946 (if (not regexps+)
20947 (setq regexp (concat "^" org-outline-regexp))
20948 (setq regexp (pop regexps+))
20949 (if hdl-only (setq regexp (concat "^" org-outline-regexp ".*?"
20950 regexp))))
20951 (setq files (append (org-agenda-files) org-agenda-text-search-extra-files)
20952 rtnall nil)
20953 (while (setq file (pop files))
20954 (setq ee nil)
20955 (catch 'nextfile
20956 (org-check-agenda-file file)
20957 (setq buffer (if (file-exists-p file)
20958 (org-get-agenda-file-buffer file)
20959 (error "No such file %s" file)))
20960 (if (not buffer)
20961 ;; If file does not exist, make sure an error message is sent
20962 (setq rtn (list (format "ORG-AGENDA-ERROR: No such org-file %s"
20963 file))))
20964 (with-current-buffer buffer
20965 (with-syntax-table (org-search-syntax-table)
20966 (unless (org-mode-p)
20967 (error "Agenda file %s is not in `org-mode'" file))
20968 (let ((case-fold-search t))
20969 (save-excursion
20970 (save-restriction
20971 (if org-agenda-restrict
20972 (narrow-to-region org-agenda-restrict-begin
20973 org-agenda-restrict-end)
20974 (widen))
20975 (goto-char (point-min))
20976 (unless (or (org-on-heading-p)
20977 (outline-next-heading))
20978 (throw 'nextfile t))
20979 (goto-char (max (point-min) (1- (point))))
20980 (while (re-search-forward regexp nil t)
20981 (org-back-to-heading t)
20982 (skip-chars-forward "* ")
20983 (setq beg (point-at-bol)
20984 beg1 (point)
20985 end (progn (outline-next-heading) (point)))
20986 (catch :skip
20987 (goto-char beg)
20988 (org-agenda-skip)
20989 (setq str (buffer-substring-no-properties
20990 (point-at-bol)
20991 (if hdl-only (point-at-eol) end)))
20992 (mapc (lambda (wr) (when (string-match wr str)
20993 (goto-char (1- end))
20994 (throw :skip t)))
20995 regexps-)
20996 (mapc (lambda (wr) (unless (string-match wr str)
20997 (goto-char (1- end))
20998 (throw :skip t)))
20999 (if todo-only
21000 (cons (concat "^\*+[ \t]+" org-not-done-regexp)
21001 regexps+)
21002 regexps+))
21003 (goto-char beg)
21004 (setq marker (org-agenda-new-marker (point))
21005 category (org-get-category)
21006 tags (org-get-tags-at (point))
21007 txt (org-format-agenda-item
21009 (buffer-substring-no-properties
21010 beg1 (point-at-eol))
21011 category tags))
21012 (org-add-props txt props
21013 'org-marker marker 'org-hd-marker marker
21014 'org-todo-regexp org-todo-regexp
21015 'priority 1000 'org-category category
21016 'type "search")
21017 (push txt ee)
21018 (goto-char (1- end))))))))))
21019 (setq rtn (nreverse ee))
21020 (setq rtnall (append rtnall rtn)))
21021 (if org-agenda-overriding-header
21022 (insert (org-add-props (copy-sequence org-agenda-overriding-header)
21023 nil 'face 'org-agenda-structure) "\n")
21024 (insert "Search words: ")
21025 (add-text-properties (point-min) (1- (point))
21026 (list 'face 'org-agenda-structure))
21027 (setq pos (point))
21028 (insert string "\n")
21029 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
21030 (setq pos (point))
21031 (unless org-agenda-multi
21032 (insert "Press `[', `]' to add/sub word, `{', `}' to add/sub regexp, `C-u r' to edit\n")
21033 (add-text-properties pos (1- (point))
21034 (list 'face 'org-agenda-structure))))
21035 (when rtnall
21036 (insert (org-finalize-agenda-entries rtnall) "\n"))
21037 (goto-char (point-min))
21038 (org-fit-agenda-window)
21039 (add-text-properties (point-min) (point-max) '(org-agenda-type search))
21040 (org-finalize-agenda)
21041 (setq buffer-read-only t)))
21043 ;;; Agenda TODO list
21045 (defvar org-select-this-todo-keyword nil)
21046 (defvar org-last-arg nil)
21048 ;;;###autoload
21049 (defun org-todo-list (arg)
21050 "Show all TODO entries from all agenda file in a single list.
21051 The prefix arg can be used to select a specific TODO keyword and limit
21052 the list to these. When using \\[universal-argument], you will be prompted
21053 for a keyword. A numeric prefix directly selects the Nth keyword in
21054 `org-todo-keywords-1'."
21055 (interactive "P")
21056 (require 'calendar)
21057 (org-compile-prefix-format 'todo)
21058 (org-set-sorting-strategy 'todo)
21059 (org-prepare-agenda "TODO")
21060 (let* ((today (time-to-days (current-time)))
21061 (date (calendar-gregorian-from-absolute today))
21062 (kwds org-todo-keywords-for-agenda)
21063 (completion-ignore-case t)
21064 (org-select-this-todo-keyword
21065 (if (stringp arg) arg
21066 (and arg (integerp arg) (> arg 0)
21067 (nth (1- arg) kwds))))
21068 rtn rtnall files file pos)
21069 (when (equal arg '(4))
21070 (setq org-select-this-todo-keyword
21071 (completing-read "Keyword (or KWD1|K2D2|...): "
21072 (mapcar 'list kwds) nil nil)))
21073 (and (equal 0 arg) (setq org-select-this-todo-keyword nil))
21074 (org-set-local 'org-last-arg arg)
21075 (setq org-agenda-redo-command
21076 '(org-todo-list (or current-prefix-arg org-last-arg)))
21077 (setq files (org-agenda-files)
21078 rtnall nil)
21079 (while (setq file (pop files))
21080 (catch 'nextfile
21081 (org-check-agenda-file file)
21082 (setq rtn (org-agenda-get-day-entries file date :todo))
21083 (setq rtnall (append rtnall rtn))))
21084 (if org-agenda-overriding-header
21085 (insert (org-add-props (copy-sequence org-agenda-overriding-header)
21086 nil 'face 'org-agenda-structure) "\n")
21087 (insert "Global list of TODO items of type: ")
21088 (add-text-properties (point-min) (1- (point))
21089 (list 'face 'org-agenda-structure))
21090 (setq pos (point))
21091 (insert (or org-select-this-todo-keyword "ALL") "\n")
21092 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
21093 (setq pos (point))
21094 (unless org-agenda-multi
21095 (insert "Available with `N r': (0)ALL")
21096 (let ((n 0) s)
21097 (mapc (lambda (x)
21098 (setq s (format "(%d)%s" (setq n (1+ n)) x))
21099 (if (> (+ (current-column) (string-width s) 1) (frame-width))
21100 (insert "\n "))
21101 (insert " " s))
21102 kwds))
21103 (insert "\n"))
21104 (add-text-properties pos (1- (point)) (list 'face 'org-agenda-structure)))
21105 (when rtnall
21106 (insert (org-finalize-agenda-entries rtnall) "\n"))
21107 (goto-char (point-min))
21108 (org-fit-agenda-window)
21109 (add-text-properties (point-min) (point-max) '(org-agenda-type todo))
21110 (org-finalize-agenda)
21111 (setq buffer-read-only t)))
21113 ;;; Agenda tags match
21115 ;;;###autoload
21116 (defun org-tags-view (&optional todo-only match)
21117 "Show all headlines for all `org-agenda-files' matching a TAGS criterion.
21118 The prefix arg TODO-ONLY limits the search to TODO entries."
21119 (interactive "P")
21120 (org-compile-prefix-format 'tags)
21121 (org-set-sorting-strategy 'tags)
21122 (let* ((org-tags-match-list-sublevels
21123 (if todo-only t org-tags-match-list-sublevels))
21124 (completion-ignore-case t)
21125 rtn rtnall files file pos matcher
21126 buffer)
21127 (setq matcher (org-make-tags-matcher match)
21128 match (car matcher) matcher (cdr matcher))
21129 (org-prepare-agenda (concat "TAGS " match))
21130 (setq org-agenda-query-string match)
21131 (setq org-agenda-redo-command
21132 (list 'org-tags-view (list 'quote todo-only)
21133 (list 'if 'current-prefix-arg nil 'org-agenda-query-string)))
21134 (setq files (org-agenda-files)
21135 rtnall nil)
21136 (while (setq file (pop files))
21137 (catch 'nextfile
21138 (org-check-agenda-file file)
21139 (setq buffer (if (file-exists-p file)
21140 (org-get-agenda-file-buffer file)
21141 (error "No such file %s" file)))
21142 (if (not buffer)
21143 ;; If file does not exist, merror message to agenda
21144 (setq rtn (list
21145 (format "ORG-AGENDA-ERROR: No such org-file %s" file))
21146 rtnall (append rtnall rtn))
21147 (with-current-buffer buffer
21148 (unless (org-mode-p)
21149 (error "Agenda file %s is not in `org-mode'" file))
21150 (save-excursion
21151 (save-restriction
21152 (if org-agenda-restrict
21153 (narrow-to-region org-agenda-restrict-begin
21154 org-agenda-restrict-end)
21155 (widen))
21156 (setq rtn (org-scan-tags 'agenda matcher todo-only))
21157 (setq rtnall (append rtnall rtn))))))))
21158 (if org-agenda-overriding-header
21159 (insert (org-add-props (copy-sequence org-agenda-overriding-header)
21160 nil 'face 'org-agenda-structure) "\n")
21161 (insert "Headlines with TAGS match: ")
21162 (add-text-properties (point-min) (1- (point))
21163 (list 'face 'org-agenda-structure))
21164 (setq pos (point))
21165 (insert match "\n")
21166 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
21167 (setq pos (point))
21168 (unless org-agenda-multi
21169 (insert "Press `C-u r' to search again with new search string\n"))
21170 (add-text-properties pos (1- (point)) (list 'face 'org-agenda-structure)))
21171 (when rtnall
21172 (insert (org-finalize-agenda-entries rtnall) "\n"))
21173 (goto-char (point-min))
21174 (org-fit-agenda-window)
21175 (add-text-properties (point-min) (point-max) '(org-agenda-type tags))
21176 (org-finalize-agenda)
21177 (setq buffer-read-only t)))
21179 ;;; Agenda Finding stuck projects
21181 (defvar org-agenda-skip-regexp nil
21182 "Regular expression used in skipping subtrees for the agenda.
21183 This is basically a temporary global variable that can be set and then
21184 used by user-defined selections using `org-agenda-skip-function'.")
21186 (defvar org-agenda-overriding-header nil
21187 "When this is set during todo and tags searches, will replace header.")
21189 (defun org-agenda-skip-subtree-when-regexp-matches ()
21190 "Checks if the current subtree contains match for `org-agenda-skip-regexp'.
21191 If yes, it returns the end position of this tree, causing agenda commands
21192 to skip this subtree. This is a function that can be put into
21193 `org-agenda-skip-function' for the duration of a command."
21194 (let ((end (save-excursion (org-end-of-subtree t)))
21195 skip)
21196 (save-excursion
21197 (setq skip (re-search-forward org-agenda-skip-regexp end t)))
21198 (and skip end)))
21200 (defun org-agenda-skip-entry-if (&rest conditions)
21201 "Skip entry if any of CONDITIONS is true.
21202 See `org-agenda-skip-if' for details."
21203 (org-agenda-skip-if nil conditions))
21205 (defun org-agenda-skip-subtree-if (&rest conditions)
21206 "Skip entry if any of CONDITIONS is true.
21207 See `org-agenda-skip-if' for details."
21208 (org-agenda-skip-if t conditions))
21210 (defun org-agenda-skip-if (subtree conditions)
21211 "Checks current entity for CONDITIONS.
21212 If SUBTREE is non-nil, the entire subtree is checked. Otherwise, only
21213 the entry, i.e. the text before the next heading is checked.
21215 CONDITIONS is a list of symbols, boolean OR is used to combine the results
21216 from different tests. Valid conditions are:
21218 scheduled Check if there is a scheduled cookie
21219 notscheduled Check if there is no scheduled cookie
21220 deadline Check if there is a deadline
21221 notdeadline Check if there is no deadline
21222 regexp Check if regexp matches
21223 notregexp Check if regexp does not match.
21225 The regexp is taken from the conditions list, it must come right after
21226 the `regexp' or `notregexp' element.
21228 If any of these conditions is met, this function returns the end point of
21229 the entity, causing the search to continue from there. This is a function
21230 that can be put into `org-agenda-skip-function' for the duration of a command."
21231 (let (beg end m)
21232 (org-back-to-heading t)
21233 (setq beg (point)
21234 end (if subtree
21235 (progn (org-end-of-subtree t) (point))
21236 (progn (outline-next-heading) (1- (point)))))
21237 (goto-char beg)
21238 (and
21240 (and (memq 'scheduled conditions)
21241 (re-search-forward org-scheduled-time-regexp end t))
21242 (and (memq 'notscheduled conditions)
21243 (not (re-search-forward org-scheduled-time-regexp end t)))
21244 (and (memq 'deadline conditions)
21245 (re-search-forward org-deadline-time-regexp end t))
21246 (and (memq 'notdeadline conditions)
21247 (not (re-search-forward org-deadline-time-regexp end t)))
21248 (and (setq m (memq 'regexp conditions))
21249 (stringp (nth 1 m))
21250 (re-search-forward (nth 1 m) end t))
21251 (and (setq m (memq 'notregexp conditions))
21252 (stringp (nth 1 m))
21253 (not (re-search-forward (nth 1 m) end t))))
21254 end)))
21256 ;;;###autoload
21257 (defun org-agenda-list-stuck-projects (&rest ignore)
21258 "Create agenda view for projects that are stuck.
21259 Stuck projects are project that have no next actions. For the definitions
21260 of what a project is and how to check if it stuck, customize the variable
21261 `org-stuck-projects'.
21262 MATCH is being ignored."
21263 (interactive)
21264 (let* ((org-agenda-skip-function 'org-agenda-skip-subtree-when-regexp-matches)
21265 ;; FIXME: we could have used org-agenda-skip-if here.
21266 (org-agenda-overriding-header "List of stuck projects: ")
21267 (matcher (nth 0 org-stuck-projects))
21268 (todo (nth 1 org-stuck-projects))
21269 (todo-wds (if (member "*" todo)
21270 (progn
21271 (org-prepare-agenda-buffers (org-agenda-files))
21272 (org-delete-all
21273 org-done-keywords-for-agenda
21274 (copy-sequence org-todo-keywords-for-agenda)))
21275 todo))
21276 (todo-re (concat "^\\*+[ \t]+\\("
21277 (mapconcat 'identity todo-wds "\\|")
21278 "\\)\\>"))
21279 (tags (nth 2 org-stuck-projects))
21280 (tags-re (if (member "*" tags)
21281 (org-re "^\\*+ .*:[[:alnum:]_@]+:[ \t]*$")
21282 (concat "^\\*+ .*:\\("
21283 (mapconcat 'identity tags "\\|")
21284 (org-re "\\):[[:alnum:]_@:]*[ \t]*$"))))
21285 (gen-re (nth 3 org-stuck-projects))
21286 (re-list
21287 (delq nil
21288 (list
21289 (if todo todo-re)
21290 (if tags tags-re)
21291 (and gen-re (stringp gen-re) (string-match "\\S-" gen-re)
21292 gen-re)))))
21293 (setq org-agenda-skip-regexp
21294 (if re-list
21295 (mapconcat 'identity re-list "\\|")
21296 (error "No information how to identify unstuck projects")))
21297 (org-tags-view nil matcher)
21298 (with-current-buffer org-agenda-buffer-name
21299 (setq org-agenda-redo-command
21300 '(org-agenda-list-stuck-projects
21301 (or current-prefix-arg org-last-arg))))))
21303 ;;; Diary integration
21305 (defvar org-disable-agenda-to-diary nil) ;Dynamically-scoped param.
21306 (defvar list-diary-entries-hook)
21308 (defun org-get-entries-from-diary (date)
21309 "Get the (Emacs Calendar) diary entries for DATE."
21310 (require 'diary-lib)
21311 (let* ((fancy-diary-buffer "*temporary-fancy-diary-buffer*")
21312 (diary-display-hook '(fancy-diary-display))
21313 (pop-up-frames nil)
21314 (list-diary-entries-hook
21315 (cons 'org-diary-default-entry list-diary-entries-hook))
21316 (diary-file-name-prefix-function nil) ; turn this feature off
21317 (diary-modify-entry-list-string-function 'org-modify-diary-entry-string)
21318 entries
21319 (org-disable-agenda-to-diary t))
21320 (save-excursion
21321 (save-window-excursion
21322 (funcall (if (fboundp 'diary-list-entries)
21323 'diary-list-entries 'list-diary-entries)
21324 date 1)))
21325 (if (not (get-buffer fancy-diary-buffer))
21326 (setq entries nil)
21327 (with-current-buffer fancy-diary-buffer
21328 (setq buffer-read-only nil)
21329 (if (zerop (buffer-size))
21330 ;; No entries
21331 (setq entries nil)
21332 ;; Omit the date and other unnecessary stuff
21333 (org-agenda-cleanup-fancy-diary)
21334 ;; Add prefix to each line and extend the text properties
21335 (if (zerop (buffer-size))
21336 (setq entries nil)
21337 (setq entries (buffer-substring (point-min) (- (point-max) 1)))))
21338 (set-buffer-modified-p nil)
21339 (kill-buffer fancy-diary-buffer)))
21340 (when entries
21341 (setq entries (org-split-string entries "\n"))
21342 (setq entries
21343 (mapcar
21344 (lambda (x)
21345 (setq x (org-format-agenda-item "" x "Diary" nil 'time))
21346 ;; Extend the text properties to the beginning of the line
21347 (org-add-props x (text-properties-at (1- (length x)) x)
21348 'type "diary" 'date date))
21349 entries)))))
21351 (defun org-agenda-cleanup-fancy-diary ()
21352 "Remove unwanted stuff in buffer created by `fancy-diary-display'.
21353 This gets rid of the date, the underline under the date, and
21354 the dummy entry installed by `org-mode' to ensure non-empty diary for each
21355 date. It also removes lines that contain only whitespace."
21356 (goto-char (point-min))
21357 (if (looking-at ".*?:[ \t]*")
21358 (progn
21359 (replace-match "")
21360 (re-search-forward "\n=+$" nil t)
21361 (replace-match "")
21362 (while (re-search-backward "^ +\n?" nil t) (replace-match "")))
21363 (re-search-forward "\n=+$" nil t)
21364 (delete-region (point-min) (min (point-max) (1+ (match-end 0)))))
21365 (goto-char (point-min))
21366 (while (re-search-forward "^ +\n" nil t)
21367 (replace-match ""))
21368 (goto-char (point-min))
21369 (if (re-search-forward "^Org-mode dummy\n?" nil t)
21370 (replace-match "")))
21372 ;; Make sure entries from the diary have the right text properties.
21373 (eval-after-load "diary-lib"
21374 '(if (boundp 'diary-modify-entry-list-string-function)
21375 ;; We can rely on the hook, nothing to do
21377 ;; Hook not avaiable, must use advice to make this work
21378 (defadvice add-to-diary-list (before org-mark-diary-entry activate)
21379 "Make the position visible."
21380 (if (and org-disable-agenda-to-diary ;; called from org-agenda
21381 (stringp string)
21382 buffer-file-name)
21383 (setq string (org-modify-diary-entry-string string))))))
21385 (defun org-modify-diary-entry-string (string)
21386 "Add text properties to string, allowing org-mode to act on it."
21387 (org-add-props string nil
21388 'mouse-face 'highlight
21389 'keymap org-agenda-keymap
21390 'help-echo (if buffer-file-name
21391 (format "mouse-2 or RET jump to diary file %s"
21392 (abbreviate-file-name buffer-file-name))
21394 'org-agenda-diary-link t
21395 'org-marker (org-agenda-new-marker (point-at-bol))))
21397 (defun org-diary-default-entry ()
21398 "Add a dummy entry to the diary.
21399 Needed to avoid empty dates which mess up holiday display."
21400 ;; Catch the error if dealing with the new add-to-diary-alist
21401 (when org-disable-agenda-to-diary
21402 (condition-case nil
21403 (add-to-diary-list original-date "Org-mode dummy" "")
21404 (error
21405 (add-to-diary-list original-date "Org-mode dummy" "" nil)))))
21407 ;;;###autoload
21408 (defun org-diary (&rest args)
21409 "Return diary information from org-files.
21410 This function can be used in a \"sexp\" diary entry in the Emacs calendar.
21411 It accesses org files and extracts information from those files to be
21412 listed in the diary. The function accepts arguments specifying what
21413 items should be listed. The following arguments are allowed:
21415 :timestamp List the headlines of items containing a date stamp or
21416 date range matching the selected date. Deadlines will
21417 also be listed, on the expiration day.
21419 :sexp List entries resulting from diary-like sexps.
21421 :deadline List any deadlines past due, or due within
21422 `org-deadline-warning-days'. The listing occurs only
21423 in the diary for *today*, not at any other date. If
21424 an entry is marked DONE, it is no longer listed.
21426 :scheduled List all items which are scheduled for the given date.
21427 The diary for *today* also contains items which were
21428 scheduled earlier and are not yet marked DONE.
21430 :todo List all TODO items from the org-file. This may be a
21431 long list - so this is not turned on by default.
21432 Like deadlines, these entries only show up in the
21433 diary for *today*, not at any other date.
21435 The call in the diary file should look like this:
21437 &%%(org-diary) ~/path/to/some/orgfile.org
21439 Use a separate line for each org file to check. Or, if you omit the file name,
21440 all files listed in `org-agenda-files' will be checked automatically:
21442 &%%(org-diary)
21444 If you don't give any arguments (as in the example above), the default
21445 arguments (:deadline :scheduled :timestamp :sexp) are used.
21446 So the example above may also be written as
21448 &%%(org-diary :deadline :timestamp :sexp :scheduled)
21450 The function expects the lisp variables `entry' and `date' to be provided
21451 by the caller, because this is how the calendar works. Don't use this
21452 function from a program - use `org-agenda-get-day-entries' instead."
21453 (when (> (- (time-to-seconds (current-time))
21454 org-agenda-last-marker-time)
21456 (org-agenda-reset-markers))
21457 (org-compile-prefix-format 'agenda)
21458 (org-set-sorting-strategy 'agenda)
21459 (setq args (or args '(:deadline :scheduled :timestamp :sexp)))
21460 (let* ((files (if (and entry (stringp entry) (string-match "\\S-" entry))
21461 (list entry)
21462 (org-agenda-files t)))
21463 file rtn results)
21464 (org-prepare-agenda-buffers files)
21465 ;; If this is called during org-agenda, don't return any entries to
21466 ;; the calendar. Org Agenda will list these entries itself.
21467 (if org-disable-agenda-to-diary (setq files nil))
21468 (while (setq file (pop files))
21469 (setq rtn (apply 'org-agenda-get-day-entries file date args))
21470 (setq results (append results rtn)))
21471 (if results
21472 (concat (org-finalize-agenda-entries results) "\n"))))
21474 ;;; Agenda entry finders
21476 (defun org-agenda-get-day-entries (file date &rest args)
21477 "Does the work for `org-diary' and `org-agenda'.
21478 FILE is the path to a file to be checked for entries. DATE is date like
21479 the one returned by `calendar-current-date'. ARGS are symbols indicating
21480 which kind of entries should be extracted. For details about these, see
21481 the documentation of `org-diary'."
21482 (setq args (or args '(:deadline :scheduled :timestamp :sexp)))
21483 (let* ((org-startup-folded nil)
21484 (org-startup-align-all-tables nil)
21485 (buffer (if (file-exists-p file)
21486 (org-get-agenda-file-buffer file)
21487 (error "No such file %s" file)))
21488 arg results rtn)
21489 (if (not buffer)
21490 ;; If file does not exist, make sure an error message ends up in diary
21491 (list (format "ORG-AGENDA-ERROR: No such org-file %s" file))
21492 (with-current-buffer buffer
21493 (unless (org-mode-p)
21494 (error "Agenda file %s is not in `org-mode'" file))
21495 (let ((case-fold-search nil))
21496 (save-excursion
21497 (save-restriction
21498 (if org-agenda-restrict
21499 (narrow-to-region org-agenda-restrict-begin
21500 org-agenda-restrict-end)
21501 (widen))
21502 ;; The way we repeatedly append to `results' makes it O(n^2) :-(
21503 (while (setq arg (pop args))
21504 (cond
21505 ((and (eq arg :todo)
21506 (equal date (calendar-current-date)))
21507 (setq rtn (org-agenda-get-todos))
21508 (setq results (append results rtn)))
21509 ((eq arg :timestamp)
21510 (setq rtn (org-agenda-get-blocks))
21511 (setq results (append results rtn))
21512 (setq rtn (org-agenda-get-timestamps))
21513 (setq results (append results rtn)))
21514 ((eq arg :sexp)
21515 (setq rtn (org-agenda-get-sexps))
21516 (setq results (append results rtn)))
21517 ((eq arg :scheduled)
21518 (setq rtn (org-agenda-get-scheduled))
21519 (setq results (append results rtn)))
21520 ((eq arg :closed)
21521 (setq rtn (org-agenda-get-closed))
21522 (setq results (append results rtn)))
21523 ((eq arg :deadline)
21524 (setq rtn (org-agenda-get-deadlines))
21525 (setq results (append results rtn))))))))
21526 results))))
21528 (defun org-entry-is-todo-p ()
21529 (member (org-get-todo-state) org-not-done-keywords))
21531 (defun org-entry-is-done-p ()
21532 (member (org-get-todo-state) org-done-keywords))
21534 (defun org-get-todo-state ()
21535 (save-excursion
21536 (org-back-to-heading t)
21537 (and (looking-at org-todo-line-regexp)
21538 (match-end 2)
21539 (match-string 2))))
21541 (defun org-at-date-range-p (&optional inactive-ok)
21542 "Is the cursor inside a date range?"
21543 (interactive)
21544 (save-excursion
21545 (catch 'exit
21546 (let ((pos (point)))
21547 (skip-chars-backward "^[<\r\n")
21548 (skip-chars-backward "<[")
21549 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
21550 (>= (match-end 0) pos)
21551 (throw 'exit t))
21552 (skip-chars-backward "^<[\r\n")
21553 (skip-chars-backward "<[")
21554 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
21555 (>= (match-end 0) pos)
21556 (throw 'exit t)))
21557 nil)))
21559 (defun org-agenda-get-todos ()
21560 "Return the TODO information for agenda display."
21561 (let* ((props (list 'face nil
21562 'done-face 'org-done
21563 'org-not-done-regexp org-not-done-regexp
21564 'org-todo-regexp org-todo-regexp
21565 'mouse-face 'highlight
21566 'keymap org-agenda-keymap
21567 'help-echo
21568 (format "mouse-2 or RET jump to org file %s"
21569 (abbreviate-file-name buffer-file-name))))
21570 ;; FIXME: get rid of the \n at some point but watch out
21571 (regexp (concat "^\\*+[ \t]+\\("
21572 (if org-select-this-todo-keyword
21573 (if (equal org-select-this-todo-keyword "*")
21574 org-todo-regexp
21575 (concat "\\<\\("
21576 (mapconcat 'identity (org-split-string org-select-this-todo-keyword "|") "\\|")
21577 "\\)\\>"))
21578 org-not-done-regexp)
21579 "[^\n\r]*\\)"))
21580 marker priority category tags
21581 ee txt beg end)
21582 (goto-char (point-min))
21583 (while (re-search-forward regexp nil t)
21584 (catch :skip
21585 (save-match-data
21586 (beginning-of-line)
21587 (setq beg (point) end (progn (outline-next-heading) (point)))
21588 (when (or (and org-agenda-todo-ignore-with-date (goto-char beg)
21589 (re-search-forward org-ts-regexp end t))
21590 (and org-agenda-todo-ignore-scheduled (goto-char beg)
21591 (re-search-forward org-scheduled-time-regexp end t))
21592 (and org-agenda-todo-ignore-deadlines (goto-char beg)
21593 (re-search-forward org-deadline-time-regexp end t)
21594 (org-deadline-close (match-string 1))))
21595 (goto-char (1+ beg))
21596 (or org-agenda-todo-list-sublevels (org-end-of-subtree 'invisible))
21597 (throw :skip nil)))
21598 (goto-char beg)
21599 (org-agenda-skip)
21600 (goto-char (match-beginning 1))
21601 (setq marker (org-agenda-new-marker (match-beginning 0))
21602 category (org-get-category)
21603 tags (org-get-tags-at (point))
21604 txt (org-format-agenda-item "" (match-string 1) category tags)
21605 priority (1+ (org-get-priority txt)))
21606 (org-add-props txt props
21607 'org-marker marker 'org-hd-marker marker
21608 'priority priority 'org-category category
21609 'type "todo")
21610 (push txt ee)
21611 (if org-agenda-todo-list-sublevels
21612 (goto-char (match-end 1))
21613 (org-end-of-subtree 'invisible))))
21614 (nreverse ee)))
21616 (defconst org-agenda-no-heading-message
21617 "No heading for this item in buffer or region.")
21619 (defun org-agenda-get-timestamps ()
21620 "Return the date stamp information for agenda display."
21621 (let* ((props (list 'face nil
21622 'org-not-done-regexp org-not-done-regexp
21623 'org-todo-regexp org-todo-regexp
21624 'mouse-face 'highlight
21625 'keymap org-agenda-keymap
21626 'help-echo
21627 (format "mouse-2 or RET jump to org file %s"
21628 (abbreviate-file-name buffer-file-name))))
21629 (d1 (calendar-absolute-from-gregorian date))
21630 (remove-re
21631 (concat
21632 (regexp-quote
21633 (format-time-string
21634 "<%Y-%m-%d"
21635 (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
21636 ".*?>"))
21637 (regexp
21638 (concat
21639 (regexp-quote
21640 (substring
21641 (format-time-string
21642 (car org-time-stamp-formats)
21643 (apply 'encode-time ; DATE bound by calendar
21644 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
21645 0 11))
21646 "\\|\\(<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[dwmy]>\\)"
21647 "\\|\\(<%%\\(([^>\n]+)\\)>\\)"))
21648 marker hdmarker deadlinep scheduledp donep tmp priority category
21649 ee txt timestr tags b0 b3 e3 head)
21650 (goto-char (point-min))
21651 (while (re-search-forward regexp nil t)
21652 (setq b0 (match-beginning 0)
21653 b3 (match-beginning 3) e3 (match-end 3))
21654 (catch :skip
21655 (and (org-at-date-range-p) (throw :skip nil))
21656 (org-agenda-skip)
21657 (if (and (match-end 1)
21658 (not (= d1 (org-time-string-to-absolute (match-string 1) d1))))
21659 (throw :skip nil))
21660 (if (and e3
21661 (not (org-diary-sexp-entry (buffer-substring b3 e3) "" date)))
21662 (throw :skip nil))
21663 (setq marker (org-agenda-new-marker b0)
21664 category (org-get-category b0)
21665 tmp (buffer-substring (max (point-min)
21666 (- b0 org-ds-keyword-length))
21668 timestr (if b3 "" (buffer-substring b0 (point-at-eol)))
21669 deadlinep (string-match org-deadline-regexp tmp)
21670 scheduledp (string-match org-scheduled-regexp tmp)
21671 donep (org-entry-is-done-p))
21672 (if (or scheduledp deadlinep) (throw :skip t))
21673 (if (string-match ">" timestr)
21674 ;; substring should only run to end of time stamp
21675 (setq timestr (substring timestr 0 (match-end 0))))
21676 (save-excursion
21677 (if (re-search-backward "^\\*+ " nil t)
21678 (progn
21679 (goto-char (match-beginning 0))
21680 (setq hdmarker (org-agenda-new-marker)
21681 tags (org-get-tags-at))
21682 (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
21683 (setq head (match-string 1))
21684 (and org-agenda-skip-timestamp-if-done donep (throw :skip t))
21685 (setq txt (org-format-agenda-item
21686 nil head category tags timestr nil
21687 remove-re)))
21688 (setq txt org-agenda-no-heading-message))
21689 (setq priority (org-get-priority txt))
21690 (org-add-props txt props
21691 'org-marker marker 'org-hd-marker hdmarker)
21692 (org-add-props txt nil 'priority priority
21693 'org-category category 'date date
21694 'type "timestamp")
21695 (push txt ee))
21696 (outline-next-heading)))
21697 (nreverse ee)))
21699 (defun org-agenda-get-sexps ()
21700 "Return the sexp information for agenda display."
21701 (require 'diary-lib)
21702 (let* ((props (list 'face nil
21703 'mouse-face 'highlight
21704 'keymap org-agenda-keymap
21705 'help-echo
21706 (format "mouse-2 or RET jump to org file %s"
21707 (abbreviate-file-name buffer-file-name))))
21708 (regexp "^&?%%(")
21709 marker category ee txt tags entry result beg b sexp sexp-entry)
21710 (goto-char (point-min))
21711 (while (re-search-forward regexp nil t)
21712 (catch :skip
21713 (org-agenda-skip)
21714 (setq beg (match-beginning 0))
21715 (goto-char (1- (match-end 0)))
21716 (setq b (point))
21717 (forward-sexp 1)
21718 (setq sexp (buffer-substring b (point)))
21719 (setq sexp-entry (if (looking-at "[ \t]*\\(\\S-.*\\)")
21720 (org-trim (match-string 1))
21721 ""))
21722 (setq result (org-diary-sexp-entry sexp sexp-entry date))
21723 (when result
21724 (setq marker (org-agenda-new-marker beg)
21725 category (org-get-category beg))
21727 (if (string-match "\\S-" result)
21728 (setq txt result)
21729 (setq txt "SEXP entry returned empty string"))
21731 (setq txt (org-format-agenda-item
21732 "" txt category tags 'time))
21733 (org-add-props txt props 'org-marker marker)
21734 (org-add-props txt nil
21735 'org-category category 'date date
21736 'type "sexp")
21737 (push txt ee))))
21738 (nreverse ee)))
21740 (defun org-agenda-get-closed ()
21741 "Return the logged TODO entries for agenda display."
21742 (let* ((props (list 'mouse-face 'highlight
21743 'org-not-done-regexp org-not-done-regexp
21744 'org-todo-regexp org-todo-regexp
21745 'keymap org-agenda-keymap
21746 'help-echo
21747 (format "mouse-2 or RET jump to org file %s"
21748 (abbreviate-file-name buffer-file-name))))
21749 (regexp (concat
21750 "\\<\\(" org-closed-string "\\|" org-clock-string "\\) *\\["
21751 (regexp-quote
21752 (substring
21753 (format-time-string
21754 (car org-time-stamp-formats)
21755 (apply 'encode-time ; DATE bound by calendar
21756 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
21757 1 11))))
21758 marker hdmarker priority category tags closedp
21759 ee txt timestr)
21760 (goto-char (point-min))
21761 (while (re-search-forward regexp nil t)
21762 (catch :skip
21763 (org-agenda-skip)
21764 (setq marker (org-agenda-new-marker (match-beginning 0))
21765 closedp (equal (match-string 1) org-closed-string)
21766 category (org-get-category (match-beginning 0))
21767 timestr (buffer-substring (match-beginning 0) (point-at-eol))
21768 ;; donep (org-entry-is-done-p)
21770 (if (string-match "\\]" timestr)
21771 ;; substring should only run to end of time stamp
21772 (setq timestr (substring timestr 0 (match-end 0))))
21773 (save-excursion
21774 (if (re-search-backward "^\\*+ " nil t)
21775 (progn
21776 (goto-char (match-beginning 0))
21777 (setq hdmarker (org-agenda-new-marker)
21778 tags (org-get-tags-at))
21779 (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
21780 (setq txt (org-format-agenda-item
21781 (if closedp "Closed: " "Clocked: ")
21782 (match-string 1) category tags timestr)))
21783 (setq txt org-agenda-no-heading-message))
21784 (setq priority 100000)
21785 (org-add-props txt props
21786 'org-marker marker 'org-hd-marker hdmarker 'face 'org-done
21787 'priority priority 'org-category category
21788 'type "closed" 'date date
21789 'undone-face 'org-warning 'done-face 'org-done)
21790 (push txt ee))
21791 (goto-char (point-at-eol))))
21792 (nreverse ee)))
21794 (defun org-agenda-get-deadlines ()
21795 "Return the deadline information for agenda display."
21796 (let* ((props (list 'mouse-face 'highlight
21797 'org-not-done-regexp org-not-done-regexp
21798 'org-todo-regexp org-todo-regexp
21799 'keymap org-agenda-keymap
21800 'help-echo
21801 (format "mouse-2 or RET jump to org file %s"
21802 (abbreviate-file-name buffer-file-name))))
21803 (regexp org-deadline-time-regexp)
21804 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
21805 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
21806 d2 diff dfrac wdays pos pos1 category tags
21807 ee txt head face s upcomingp donep timestr)
21808 (goto-char (point-min))
21809 (while (re-search-forward regexp nil t)
21810 (catch :skip
21811 (org-agenda-skip)
21812 (setq s (match-string 1)
21813 pos (1- (match-beginning 1))
21814 d2 (org-time-string-to-absolute (match-string 1) d1 'past)
21815 diff (- d2 d1)
21816 wdays (org-get-wdays s)
21817 dfrac (/ (* 1.0 (- wdays diff)) (max wdays 1))
21818 upcomingp (and todayp (> diff 0)))
21819 ;; When to show a deadline in the calendar:
21820 ;; If the expiration is within wdays warning time.
21821 ;; Past-due deadlines are only shown on the current date
21822 (if (or (and (<= diff wdays)
21823 (and todayp (not org-agenda-only-exact-dates)))
21824 (= diff 0))
21825 (save-excursion
21826 (setq category (org-get-category))
21827 (if (re-search-backward "^\\*+[ \t]+" nil t)
21828 (progn
21829 (goto-char (match-end 0))
21830 (setq pos1 (match-beginning 0))
21831 (setq tags (org-get-tags-at pos1))
21832 (setq head (buffer-substring-no-properties
21833 (point)
21834 (progn (skip-chars-forward "^\r\n")
21835 (point))))
21836 (setq donep (string-match org-looking-at-done-regexp head))
21837 (if (string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s)
21838 (setq timestr
21839 (concat (substring s (match-beginning 1)) " "))
21840 (setq timestr 'time))
21841 (if (and donep
21842 (or org-agenda-skip-deadline-if-done
21843 (not (= diff 0))))
21844 (setq txt nil)
21845 (setq txt (org-format-agenda-item
21846 (if (= diff 0)
21847 (car org-agenda-deadline-leaders)
21848 (format (nth 1 org-agenda-deadline-leaders)
21849 diff))
21850 head category tags timestr))))
21851 (setq txt org-agenda-no-heading-message))
21852 (when txt
21853 (setq face (org-agenda-deadline-face dfrac wdays))
21854 (org-add-props txt props
21855 'org-marker (org-agenda-new-marker pos)
21856 'org-hd-marker (org-agenda-new-marker pos1)
21857 'priority (+ (- diff)
21858 (org-get-priority txt))
21859 'org-category category
21860 'type (if upcomingp "upcoming-deadline" "deadline")
21861 'date (if upcomingp date d2)
21862 'face (if donep 'org-done face)
21863 'undone-face face 'done-face 'org-done)
21864 (push txt ee))))))
21865 (nreverse ee)))
21867 (defun org-agenda-deadline-face (fraction &optional wdays)
21868 "Return the face to displaying a deadline item.
21869 FRACTION is what fraction of the head-warning time has passed."
21870 (if (equal wdays 0) (setq fraction 1.))
21871 (let ((faces org-agenda-deadline-faces) f)
21872 (catch 'exit
21873 (while (setq f (pop faces))
21874 (if (>= fraction (car f)) (throw 'exit (cdr f)))))))
21876 (defun org-agenda-get-scheduled ()
21877 "Return the scheduled information for agenda display."
21878 (let* ((props (list 'org-not-done-regexp org-not-done-regexp
21879 'org-todo-regexp org-todo-regexp
21880 'done-face 'org-done
21881 'mouse-face 'highlight
21882 'keymap org-agenda-keymap
21883 'help-echo
21884 (format "mouse-2 or RET jump to org file %s"
21885 (abbreviate-file-name buffer-file-name))))
21886 (regexp org-scheduled-time-regexp)
21887 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
21888 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
21889 d2 diff pos pos1 category tags
21890 ee txt head pastschedp donep face timestr s)
21891 (goto-char (point-min))
21892 (while (re-search-forward regexp nil t)
21893 (catch :skip
21894 (org-agenda-skip)
21895 (setq s (match-string 1)
21896 pos (1- (match-beginning 1))
21897 d2 (org-time-string-to-absolute (match-string 1) d1 'past)
21898 ;;; is this right?
21899 ;;; do we need to do this for deadleine too????
21900 ;;; d2 (org-time-string-to-absolute (match-string 1) (if todayp nil d1))
21901 diff (- d2 d1))
21902 (setq pastschedp (and todayp (< diff 0)))
21903 ;; When to show a scheduled item in the calendar:
21904 ;; If it is on or past the date.
21905 (if (or (and (< diff 0)
21906 (< (abs diff) org-scheduled-past-days)
21907 (and todayp (not org-agenda-only-exact-dates)))
21908 (= diff 0))
21909 (save-excursion
21910 (setq category (org-get-category))
21911 (if (re-search-backward "^\\*+[ \t]+" nil t)
21912 (progn
21913 (goto-char (match-end 0))
21914 (setq pos1 (match-beginning 0))
21915 (setq tags (org-get-tags-at))
21916 (setq head (buffer-substring-no-properties
21917 (point)
21918 (progn (skip-chars-forward "^\r\n") (point))))
21919 (setq donep (string-match org-looking-at-done-regexp head))
21920 (if (string-match " \\([012]?[0-9]:[0-9][0-9]\\)" s)
21921 (setq timestr
21922 (concat (substring s (match-beginning 1)) " "))
21923 (setq timestr 'time))
21924 (if (and donep
21925 (or org-agenda-skip-scheduled-if-done
21926 (not (= diff 0))))
21927 (setq txt nil)
21928 (setq txt (org-format-agenda-item
21929 (if (= diff 0)
21930 (car org-agenda-scheduled-leaders)
21931 (format (nth 1 org-agenda-scheduled-leaders)
21932 (- 1 diff)))
21933 head category tags timestr))))
21934 (setq txt org-agenda-no-heading-message))
21935 (when txt
21936 (setq face (if pastschedp
21937 'org-scheduled-previously
21938 'org-scheduled-today))
21939 (org-add-props txt props
21940 'undone-face face
21941 'face (if donep 'org-done face)
21942 'org-marker (org-agenda-new-marker pos)
21943 'org-hd-marker (org-agenda-new-marker pos1)
21944 'type (if pastschedp "past-scheduled" "scheduled")
21945 'date (if pastschedp d2 date)
21946 'priority (+ 94 (- 5 diff) (org-get-priority txt))
21947 'org-category category)
21948 (push txt ee))))))
21949 (nreverse ee)))
21951 (defun org-agenda-get-blocks ()
21952 "Return the date-range information for agenda display."
21953 (let* ((props (list 'face nil
21954 'org-not-done-regexp org-not-done-regexp
21955 'org-todo-regexp org-todo-regexp
21956 'mouse-face 'highlight
21957 'keymap org-agenda-keymap
21958 'help-echo
21959 (format "mouse-2 or RET jump to org file %s"
21960 (abbreviate-file-name buffer-file-name))))
21961 (regexp org-tr-regexp)
21962 (d0 (calendar-absolute-from-gregorian date))
21963 marker hdmarker ee txt d1 d2 s1 s2 timestr category tags pos
21964 donep head)
21965 (goto-char (point-min))
21966 (while (re-search-forward regexp nil t)
21967 (catch :skip
21968 (org-agenda-skip)
21969 (setq pos (point))
21970 (setq timestr (match-string 0)
21971 s1 (match-string 1)
21972 s2 (match-string 2)
21973 d1 (time-to-days (org-time-string-to-time s1))
21974 d2 (time-to-days (org-time-string-to-time s2)))
21975 (if (and (> (- d0 d1) -1) (> (- d2 d0) -1))
21976 ;; Only allow days between the limits, because the normal
21977 ;; date stamps will catch the limits.
21978 (save-excursion
21979 (setq marker (org-agenda-new-marker (point)))
21980 (setq category (org-get-category))
21981 (if (re-search-backward "^\\*+ " nil t)
21982 (progn
21983 (goto-char (match-beginning 0))
21984 (setq hdmarker (org-agenda-new-marker (point)))
21985 (setq tags (org-get-tags-at))
21986 (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
21987 (setq head (match-string 1))
21988 (and org-agenda-skip-timestamp-if-done
21989 (org-entry-is-done-p)
21990 (throw :skip t))
21991 (setq txt (org-format-agenda-item
21992 (format (if (= d1 d2) "" "(%d/%d): ")
21993 (1+ (- d0 d1)) (1+ (- d2 d1)))
21994 head category tags
21995 (if (= d0 d1) timestr))))
21996 (setq txt org-agenda-no-heading-message))
21997 (org-add-props txt props
21998 'org-marker marker 'org-hd-marker hdmarker
21999 'type "block" 'date date
22000 'priority (org-get-priority txt) 'org-category category)
22001 (push txt ee)))
22002 (goto-char pos)))
22003 ;; Sort the entries by expiration date.
22004 (nreverse ee)))
22006 ;;; Agenda presentation and sorting
22008 (defconst org-plain-time-of-day-regexp
22009 (concat
22010 "\\(\\<[012]?[0-9]"
22011 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
22012 "\\(--?"
22013 "\\(\\<[012]?[0-9]"
22014 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
22015 "\\)?")
22016 "Regular expression to match a plain time or time range.
22017 Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
22018 groups carry important information:
22019 0 the full match
22020 1 the first time, range or not
22021 8 the second time, if it is a range.")
22023 (defconst org-plain-time-extension-regexp
22024 (concat
22025 "\\(\\<[012]?[0-9]"
22026 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
22027 "\\+\\([0-9]+\\)\\(:\\([0-5][0-9]\\)\\)?")
22028 "Regular expression to match a time range like 13:30+2:10 = 13:30-15:40.
22029 Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
22030 groups carry important information:
22031 0 the full match
22032 7 hours of duration
22033 9 minutes of duration")
22035 (defconst org-stamp-time-of-day-regexp
22036 (concat
22037 "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +\\sw+ +\\)"
22038 "\\([012][0-9]:[0-5][0-9]\\(-\\([012][0-9]:[0-5][0-9]\\)\\)?[^\n\r>]*?\\)>"
22039 "\\(--?"
22040 "<\\1\\([012][0-9]:[0-5][0-9]\\)>\\)?")
22041 "Regular expression to match a timestamp time or time range.
22042 After a match, the following groups carry important information:
22043 0 the full match
22044 1 date plus weekday, for backreferencing to make sure both times on same day
22045 2 the first time, range or not
22046 4 the second time, if it is a range.")
22048 (defvar org-prefix-has-time nil
22049 "A flag, set by `org-compile-prefix-format'.
22050 The flag is set if the currently compiled format contains a `%t'.")
22051 (defvar org-prefix-has-tag nil
22052 "A flag, set by `org-compile-prefix-format'.
22053 The flag is set if the currently compiled format contains a `%T'.")
22055 (defun org-format-agenda-item (extra txt &optional category tags dotime
22056 noprefix remove-re)
22057 "Format TXT to be inserted into the agenda buffer.
22058 In particular, it adds the prefix and corresponding text properties. EXTRA
22059 must be a string and replaces the `%s' specifier in the prefix format.
22060 CATEGORY (string, symbol or nil) may be used to overrule the default
22061 category taken from local variable or file name. It will replace the `%c'
22062 specifier in the format. DOTIME, when non-nil, indicates that a
22063 time-of-day should be extracted from TXT for sorting of this entry, and for
22064 the `%t' specifier in the format. When DOTIME is a string, this string is
22065 searched for a time before TXT is. NOPREFIX is a flag and indicates that
22066 only the correctly processes TXT should be returned - this is used by
22067 `org-agenda-change-all-lines'. TAGS can be the tags of the headline.
22068 Any match of REMOVE-RE will be removed from TXT."
22069 (save-match-data
22070 ;; Diary entries sometimes have extra whitespace at the beginning
22071 (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt)))
22072 (let* ((category (or category
22073 org-category
22074 (if buffer-file-name
22075 (file-name-sans-extension
22076 (file-name-nondirectory buffer-file-name))
22077 "")))
22078 (tag (if tags (nth (1- (length tags)) tags) ""))
22079 time ; time and tag are needed for the eval of the prefix format
22080 (ts (if dotime (concat (if (stringp dotime) dotime "") txt)))
22081 (time-of-day (and dotime (org-get-time-of-day ts)))
22082 stamp plain s0 s1 s2 rtn srp)
22083 (when (and dotime time-of-day org-prefix-has-time)
22084 ;; Extract starting and ending time and move them to prefix
22085 (when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts))
22086 (setq plain (string-match org-plain-time-of-day-regexp ts)))
22087 (setq s0 (match-string 0 ts)
22088 srp (and stamp (match-end 3))
22089 s1 (match-string (if plain 1 2) ts)
22090 s2 (match-string (if plain 8 (if srp 4 6)) ts))
22092 ;; If the times are in TXT (not in DOTIMES), and the prefix will list
22093 ;; them, we might want to remove them there to avoid duplication.
22094 ;; The user can turn this off with a variable.
22095 (if (and org-agenda-remove-times-when-in-prefix (or stamp plain)
22096 (string-match (concat (regexp-quote s0) " *") txt)
22097 (not (equal ?\] (string-to-char (substring txt (match-end 0)))))
22098 (if (eq org-agenda-remove-times-when-in-prefix 'beg)
22099 (= (match-beginning 0) 0)
22101 (setq txt (replace-match "" nil nil txt))))
22102 ;; Normalize the time(s) to 24 hour
22103 (if s1 (setq s1 (org-get-time-of-day s1 'string t)))
22104 (if s2 (setq s2 (org-get-time-of-day s2 'string t))))
22106 (when (and s1 (not s2) org-agenda-default-appointment-duration
22107 (string-match "\\([0-9]+\\):\\([0-9]+\\)" s1))
22108 (let ((m (+ (string-to-number (match-string 2 s1))
22109 (* 60 (string-to-number (match-string 1 s1)))
22110 org-agenda-default-appointment-duration))
22112 (setq h (/ m 60) m (- m (* h 60)))
22113 (setq s2 (format "%02d:%02d" h m))))
22115 (when (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$")
22116 txt)
22117 ;; Tags are in the string
22118 (if (or (eq org-agenda-remove-tags t)
22119 (and org-agenda-remove-tags
22120 org-prefix-has-tag))
22121 (setq txt (replace-match "" t t txt))
22122 (setq txt (replace-match
22123 (concat (make-string (max (- 50 (length txt)) 1) ?\ )
22124 (match-string 2 txt))
22125 t t txt))))
22127 (when remove-re
22128 (while (string-match remove-re txt)
22129 (setq txt (replace-match "" t t txt))))
22131 ;; Create the final string
22132 (if noprefix
22133 (setq rtn txt)
22134 ;; Prepare the variables needed in the eval of the compiled format
22135 (setq time (cond (s2 (concat s1 "-" s2))
22136 (s1 (concat s1 "......"))
22137 (t ""))
22138 extra (or extra "")
22139 category (if (symbolp category) (symbol-name category) category))
22140 ;; Evaluate the compiled format
22141 (setq rtn (concat (eval org-prefix-format-compiled) txt)))
22143 ;; And finally add the text properties
22144 (org-add-props rtn nil
22145 'org-category (downcase category) 'tags tags
22146 'org-highest-priority org-highest-priority
22147 'org-lowest-priority org-lowest-priority
22148 'prefix-length (- (length rtn) (length txt))
22149 'time-of-day time-of-day
22150 'txt txt
22151 'time time
22152 'extra extra
22153 'dotime dotime))))
22155 (defvar org-agenda-sorting-strategy) ;; because the def is in a let form
22156 (defvar org-agenda-sorting-strategy-selected nil)
22158 (defun org-agenda-add-time-grid-maybe (list ndays todayp)
22159 (catch 'exit
22160 (cond ((not org-agenda-use-time-grid) (throw 'exit list))
22161 ((and todayp (member 'today (car org-agenda-time-grid))))
22162 ((and (= ndays 1) (member 'daily (car org-agenda-time-grid))))
22163 ((member 'weekly (car org-agenda-time-grid)))
22164 (t (throw 'exit list)))
22165 (let* ((have (delq nil (mapcar
22166 (lambda (x) (get-text-property 1 'time-of-day x))
22167 list)))
22168 (string (nth 1 org-agenda-time-grid))
22169 (gridtimes (nth 2 org-agenda-time-grid))
22170 (req (car org-agenda-time-grid))
22171 (remove (member 'remove-match req))
22172 new time)
22173 (if (and (member 'require-timed req) (not have))
22174 ;; don't show empty grid
22175 (throw 'exit list))
22176 (while (setq time (pop gridtimes))
22177 (unless (and remove (member time have))
22178 (setq time (int-to-string time))
22179 (push (org-format-agenda-item
22180 nil string "" nil
22181 (concat (substring time 0 -2) ":" (substring time -2)))
22182 new)
22183 (put-text-property
22184 1 (length (car new)) 'face 'org-time-grid (car new))))
22185 (if (member 'time-up org-agenda-sorting-strategy-selected)
22186 (append new list)
22187 (append list new)))))
22189 (defun org-compile-prefix-format (key)
22190 "Compile the prefix format into a Lisp form that can be evaluated.
22191 The resulting form is returned and stored in the variable
22192 `org-prefix-format-compiled'."
22193 (setq org-prefix-has-time nil org-prefix-has-tag nil)
22194 (let ((s (cond
22195 ((stringp org-agenda-prefix-format)
22196 org-agenda-prefix-format)
22197 ((assq key org-agenda-prefix-format)
22198 (cdr (assq key org-agenda-prefix-format)))
22199 (t " %-12:c%?-12t% s")))
22200 (start 0)
22201 varform vars var e c f opt)
22202 (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([cts]\\)"
22203 s start)
22204 (setq var (cdr (assoc (match-string 4 s)
22205 '(("c" . category) ("t" . time) ("s" . extra)
22206 ("T" . tag))))
22207 c (or (match-string 3 s) "")
22208 opt (match-beginning 1)
22209 start (1+ (match-beginning 0)))
22210 (if (equal var 'time) (setq org-prefix-has-time t))
22211 (if (equal var 'tag) (setq org-prefix-has-tag t))
22212 (setq f (concat "%" (match-string 2 s) "s"))
22213 (if opt
22214 (setq varform
22215 `(if (equal "" ,var)
22217 (format ,f (if (equal "" ,var) "" (concat ,var ,c)))))
22218 (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c)))))
22219 (setq s (replace-match "%s" t nil s))
22220 (push varform vars))
22221 (setq vars (nreverse vars))
22222 (setq org-prefix-format-compiled `(format ,s ,@vars))))
22224 (defun org-set-sorting-strategy (key)
22225 (if (symbolp (car org-agenda-sorting-strategy))
22226 ;; the old format
22227 (setq org-agenda-sorting-strategy-selected org-agenda-sorting-strategy)
22228 (setq org-agenda-sorting-strategy-selected
22229 (or (cdr (assq key org-agenda-sorting-strategy))
22230 (cdr (assq 'agenda org-agenda-sorting-strategy))
22231 '(time-up category-keep priority-down)))))
22233 (defun org-get-time-of-day (s &optional string mod24)
22234 "Check string S for a time of day.
22235 If found, return it as a military time number between 0 and 2400.
22236 If not found, return nil.
22237 The optional STRING argument forces conversion into a 5 character wide string
22238 HH:MM."
22239 (save-match-data
22240 (when
22241 (or (string-match "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)\\([AaPp][Mm]\\)?\\> *" s)
22242 (string-match "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\([AaPp][Mm]\\)\\> *" s))
22243 (let* ((h (string-to-number (match-string 1 s)))
22244 (m (if (match-end 3) (string-to-number (match-string 3 s)) 0))
22245 (ampm (if (match-end 4) (downcase (match-string 4 s))))
22246 (am-p (equal ampm "am"))
22247 (h1 (cond ((not ampm) h)
22248 ((= h 12) (if am-p 0 12))
22249 (t (+ h (if am-p 0 12)))))
22250 (h2 (if (and string mod24 (not (and (= m 0) (= h1 24))))
22251 (mod h1 24) h1))
22252 (t0 (+ (* 100 h2) m))
22253 (t1 (concat (if (>= h1 24) "+" " ")
22254 (if (< t0 100) "0" "")
22255 (if (< t0 10) "0" "")
22256 (int-to-string t0))))
22257 (if string (concat (substring t1 -4 -2) ":" (substring t1 -2)) t0)))))
22259 (defun org-finalize-agenda-entries (list &optional nosort)
22260 "Sort and concatenate the agenda items."
22261 (setq list (mapcar 'org-agenda-highlight-todo list))
22262 (if nosort
22263 list
22264 (mapconcat 'identity (sort list 'org-entries-lessp) "\n")))
22266 (defun org-agenda-highlight-todo (x)
22267 (let (re pl)
22268 (if (eq x 'line)
22269 (save-excursion
22270 (beginning-of-line 1)
22271 (setq re (get-text-property (point) 'org-todo-regexp))
22272 (goto-char (+ (point) (or (get-text-property (point) 'prefix-length) 0)))
22273 (when (looking-at (concat "[ \t]*\\.*" re " +"))
22274 (add-text-properties (match-beginning 0) (match-end 0)
22275 (list 'face (org-get-todo-face 0)))
22276 (let ((s (buffer-substring (match-beginning 1) (match-end 1))))
22277 (delete-region (match-beginning 1) (1- (match-end 0)))
22278 (goto-char (match-beginning 1))
22279 (insert (format org-agenda-todo-keyword-format s)))))
22280 (setq re (concat (get-text-property 0 'org-todo-regexp x))
22281 pl (get-text-property 0 'prefix-length x))
22282 (when (and re
22283 (equal (string-match (concat "\\(\\.*\\)" re "\\( +\\)")
22284 x (or pl 0)) pl))
22285 (add-text-properties
22286 (or (match-end 1) (match-end 0)) (match-end 0)
22287 (list 'face (org-get-todo-face (match-string 2 x)))
22289 (setq x (concat (substring x 0 (match-end 1))
22290 (format org-agenda-todo-keyword-format
22291 (match-string 2 x))
22293 (substring x (match-end 3)))))
22294 x)))
22296 (defsubst org-cmp-priority (a b)
22297 "Compare the priorities of string A and B."
22298 (let ((pa (or (get-text-property 1 'priority a) 0))
22299 (pb (or (get-text-property 1 'priority b) 0)))
22300 (cond ((> pa pb) +1)
22301 ((< pa pb) -1)
22302 (t nil))))
22304 (defsubst org-cmp-category (a b)
22305 "Compare the string values of categories of strings A and B."
22306 (let ((ca (or (get-text-property 1 'org-category a) ""))
22307 (cb (or (get-text-property 1 'org-category b) "")))
22308 (cond ((string-lessp ca cb) -1)
22309 ((string-lessp cb ca) +1)
22310 (t nil))))
22312 (defsubst org-cmp-tag (a b)
22313 "Compare the string values of categories of strings A and B."
22314 (let ((ta (car (last (get-text-property 1 'tags a))))
22315 (tb (car (last (get-text-property 1 'tags b)))))
22316 (cond ((not ta) +1)
22317 ((not tb) -1)
22318 ((string-lessp ta tb) -1)
22319 ((string-lessp tb ta) +1)
22320 (t nil))))
22322 (defsubst org-cmp-time (a b)
22323 "Compare the time-of-day values of strings A and B."
22324 (let* ((def (if org-sort-agenda-notime-is-late 9901 -1))
22325 (ta (or (get-text-property 1 'time-of-day a) def))
22326 (tb (or (get-text-property 1 'time-of-day b) def)))
22327 (cond ((< ta tb) -1)
22328 ((< tb ta) +1)
22329 (t nil))))
22331 (defun org-entries-lessp (a b)
22332 "Predicate for sorting agenda entries."
22333 ;; The following variables will be used when the form is evaluated.
22334 ;; So even though the compiler complains, keep them.
22335 (let* ((time-up (org-cmp-time a b))
22336 (time-down (if time-up (- time-up) nil))
22337 (priority-up (org-cmp-priority a b))
22338 (priority-down (if priority-up (- priority-up) nil))
22339 (category-up (org-cmp-category a b))
22340 (category-down (if category-up (- category-up) nil))
22341 (category-keep (if category-up +1 nil))
22342 (tag-up (org-cmp-tag a b))
22343 (tag-down (if tag-up (- tag-up) nil)))
22344 (cdr (assoc
22345 (eval (cons 'or org-agenda-sorting-strategy-selected))
22346 '((-1 . t) (1 . nil) (nil . nil))))))
22348 ;;; Agenda restriction lock
22350 (defvar org-agenda-restriction-lock-overlay (org-make-overlay 1 1)
22351 "Overlay to mark the headline to which arenda commands are restricted.")
22352 (org-overlay-put org-agenda-restriction-lock-overlay
22353 'face 'org-agenda-restriction-lock)
22354 (org-overlay-put org-agenda-restriction-lock-overlay
22355 'help-echo "Agendas are currently limited to this subtree.")
22356 (org-detach-overlay org-agenda-restriction-lock-overlay)
22357 (defvar org-speedbar-restriction-lock-overlay (org-make-overlay 1 1)
22358 "Overlay marking the agenda restriction line in speedbar.")
22359 (org-overlay-put org-speedbar-restriction-lock-overlay
22360 'face 'org-agenda-restriction-lock)
22361 (org-overlay-put org-speedbar-restriction-lock-overlay
22362 'help-echo "Agendas are currently limited to this item.")
22363 (org-detach-overlay org-speedbar-restriction-lock-overlay)
22365 (defun org-agenda-set-restriction-lock (&optional type)
22366 "Set restriction lock for agenda, to current subtree or file.
22367 Restriction will be the file if TYPE is `file', or if type is the
22368 universal prefix '(4), or if the cursor is before the first headline
22369 in the file. Otherwise, restriction will be to the current subtree."
22370 (interactive "P")
22371 (and (equal type '(4)) (setq type 'file))
22372 (setq type (cond
22373 (type type)
22374 ((org-at-heading-p) 'subtree)
22375 ((condition-case nil (org-back-to-heading t) (error nil))
22376 'subtree)
22377 (t 'file)))
22378 (if (eq type 'subtree)
22379 (progn
22380 (setq org-agenda-restrict t)
22381 (setq org-agenda-overriding-restriction 'subtree)
22382 (put 'org-agenda-files 'org-restrict
22383 (list (buffer-file-name (buffer-base-buffer))))
22384 (org-back-to-heading t)
22385 (org-move-overlay org-agenda-restriction-lock-overlay (point) (point-at-eol))
22386 (move-marker org-agenda-restrict-begin (point))
22387 (move-marker org-agenda-restrict-end
22388 (save-excursion (org-end-of-subtree t)))
22389 (message "Locking agenda restriction to subtree"))
22390 (put 'org-agenda-files 'org-restrict
22391 (list (buffer-file-name (buffer-base-buffer))))
22392 (setq org-agenda-restrict nil)
22393 (setq org-agenda-overriding-restriction 'file)
22394 (move-marker org-agenda-restrict-begin nil)
22395 (move-marker org-agenda-restrict-end nil)
22396 (message "Locking agenda restriction to file"))
22397 (setq current-prefix-arg nil)
22398 (org-agenda-maybe-redo))
22400 (defun org-agenda-remove-restriction-lock (&optional noupdate)
22401 "Remove the agenda restriction lock."
22402 (interactive "P")
22403 (org-detach-overlay org-agenda-restriction-lock-overlay)
22404 (org-detach-overlay org-speedbar-restriction-lock-overlay)
22405 (setq org-agenda-overriding-restriction nil)
22406 (setq org-agenda-restrict nil)
22407 (put 'org-agenda-files 'org-restrict nil)
22408 (move-marker org-agenda-restrict-begin nil)
22409 (move-marker org-agenda-restrict-end nil)
22410 (setq current-prefix-arg nil)
22411 (message "Agenda restriction lock removed")
22412 (or noupdate (org-agenda-maybe-redo)))
22414 (defun org-agenda-maybe-redo ()
22415 "If there is any window showing the agenda view, update it."
22416 (let ((w (get-buffer-window org-agenda-buffer-name t))
22417 (w0 (selected-window)))
22418 (when w
22419 (select-window w)
22420 (org-agenda-redo)
22421 (select-window w0)
22422 (if org-agenda-overriding-restriction
22423 (message "Agenda view shifted to new %s restriction"
22424 org-agenda-overriding-restriction)
22425 (message "Agenda restriction lock removed")))))
22427 ;;; Agenda commands
22429 (defun org-agenda-check-type (error &rest types)
22430 "Check if agenda buffer is of allowed type.
22431 If ERROR is non-nil, throw an error, otherwise just return nil."
22432 (if (memq org-agenda-type types)
22434 (if error
22435 (error "Not allowed in %s-type agenda buffers" org-agenda-type)
22436 nil)))
22438 (defun org-agenda-quit ()
22439 "Exit agenda by removing the window or the buffer."
22440 (interactive)
22441 (let ((buf (current-buffer)))
22442 (if (not (one-window-p)) (delete-window))
22443 (kill-buffer buf)
22444 (org-agenda-reset-markers)
22445 (org-columns-remove-overlays))
22446 ;; Maybe restore the pre-agenda window configuration.
22447 (and org-agenda-restore-windows-after-quit
22448 (not (eq org-agenda-window-setup 'other-frame))
22449 org-pre-agenda-window-conf
22450 (set-window-configuration org-pre-agenda-window-conf)))
22452 (defun org-agenda-exit ()
22453 "Exit agenda by removing the window or the buffer.
22454 Also kill all Org-mode buffers which have been loaded by `org-agenda'.
22455 Org-mode buffers visited directly by the user will not be touched."
22456 (interactive)
22457 (org-release-buffers org-agenda-new-buffers)
22458 (setq org-agenda-new-buffers nil)
22459 (org-agenda-quit))
22461 (defun org-agenda-execute (arg)
22462 "Execute another agenda command, keeping same window.\\<global-map>
22463 So this is just a shortcut for `\\[org-agenda]', available in the agenda."
22464 (interactive "P")
22465 (let ((org-agenda-window-setup 'current-window))
22466 (org-agenda arg)))
22468 (defun org-save-all-org-buffers ()
22469 "Save all Org-mode buffers without user confirmation."
22470 (interactive)
22471 (message "Saving all Org-mode buffers...")
22472 (save-some-buffers t 'org-mode-p)
22473 (message "Saving all Org-mode buffers... done"))
22475 (defun org-agenda-redo ()
22476 "Rebuild Agenda.
22477 When this is the global TODO list, a prefix argument will be interpreted."
22478 (interactive)
22479 (let* ((org-agenda-keep-modes t)
22480 (line (org-current-line))
22481 (window-line (- line (org-current-line (window-start))))
22482 (lprops (get 'org-agenda-redo-command 'org-lprops)))
22483 (message "Rebuilding agenda buffer...")
22484 (org-let lprops '(eval org-agenda-redo-command))
22485 (setq org-agenda-undo-list nil
22486 org-agenda-pending-undo-list nil)
22487 (message "Rebuilding agenda buffer...done")
22488 (goto-line line)
22489 (recenter window-line)))
22491 (defun org-agenda-manipulate-query-add ()
22492 "Manipulate the query by adding a search term with positive selection.
22493 Positive selection means, the term must be matched for selection of an entry."
22494 (interactive)
22495 (org-agenda-manipulate-query ?\[))
22496 (defun org-agenda-manipulate-query-subtract ()
22497 "Manipulate the query by adding a search term with negative selection.
22498 Negative selection means, term must not be matched for selection of an entry."
22499 (interactive)
22500 (org-agenda-manipulate-query ?\]))
22501 (defun org-agenda-manipulate-query-add-re ()
22502 "Manipulate the query by adding a search regexp with positive selection.
22503 Positive selection means, the regexp must match for selection of an entry."
22504 (interactive)
22505 (org-agenda-manipulate-query ?\{))
22506 (defun org-agenda-manipulate-query-subtract-re ()
22507 "Manipulate the query by adding a search regexp with negative selection.
22508 Negative selection means, regexp must not match for selection of an entry."
22509 (interactive)
22510 (org-agenda-manipulate-query ?\}))
22511 (defun org-agenda-manipulate-query (char)
22512 (cond
22513 ((eq org-agenda-type 'search)
22514 (org-add-to-string
22515 'org-agenda-query-string
22516 (cdr (assoc char '((?\[ . " +") (?\] . " -")
22517 (?\{ . " +{}") (?\} . " -{}")))))
22518 (setq org-agenda-redo-command
22519 (list 'org-search-view
22520 org-todo-only
22521 org-agenda-query-string
22522 (+ (length org-agenda-query-string)
22523 (if (member char '(?\{ ?\})) 0 1))))
22524 (set-register org-agenda-query-register org-agenda-query-string)
22525 (org-agenda-redo))
22526 (t (error "Canot manipulate query for %s-type agenda buffers"
22527 org-agenda-type))))
22529 (defun org-add-to-string (var string)
22530 (set var (concat (symbol-value var) string)))
22532 (defun org-agenda-goto-date (date)
22533 "Jump to DATE in agenda."
22534 (interactive (list (org-read-date)))
22535 (org-agenda-list nil date))
22537 (defun org-agenda-goto-today ()
22538 "Go to today."
22539 (interactive)
22540 (org-agenda-check-type t 'timeline 'agenda)
22541 (let ((tdpos (text-property-any (point-min) (point-max) 'org-today t)))
22542 (cond
22543 (tdpos (goto-char tdpos))
22544 ((eq org-agenda-type 'agenda)
22545 (let* ((sd (time-to-days
22546 (time-subtract (current-time)
22547 (list 0 (* 3600 org-extend-today-until) 0))))
22548 (comp (org-agenda-compute-time-span sd org-agenda-span))
22549 (org-agenda-overriding-arguments org-agenda-last-arguments))
22550 (setf (nth 1 org-agenda-overriding-arguments) (car comp))
22551 (setf (nth 2 org-agenda-overriding-arguments) (cdr comp))
22552 (org-agenda-redo)
22553 (org-agenda-find-same-or-today-or-agenda)))
22554 (t (error "Cannot find today")))))
22556 (defun org-agenda-find-same-or-today-or-agenda (&optional cnt)
22557 (goto-char
22558 (or (and cnt (text-property-any (point-min) (point-max) 'org-day-cnt cnt))
22559 (text-property-any (point-min) (point-max) 'org-today t)
22560 (text-property-any (point-min) (point-max) 'org-agenda-type 'agenda)
22561 (point-min))))
22563 (defun org-agenda-later (arg)
22564 "Go forward in time by thee current span.
22565 With prefix ARG, go forward that many times the current span."
22566 (interactive "p")
22567 (org-agenda-check-type t 'agenda)
22568 (let* ((span org-agenda-span)
22569 (sd org-starting-day)
22570 (greg (calendar-gregorian-from-absolute sd))
22571 (cnt (get-text-property (point) 'org-day-cnt))
22572 greg2 nd)
22573 (cond
22574 ((eq span 'day)
22575 (setq sd (+ arg sd) nd 1))
22576 ((eq span 'week)
22577 (setq sd (+ (* 7 arg) sd) nd 7))
22578 ((eq span 'month)
22579 (setq greg2 (list (+ (car greg) arg) (nth 1 greg) (nth 2 greg))
22580 sd (calendar-absolute-from-gregorian greg2))
22581 (setcar greg2 (1+ (car greg2)))
22582 (setq nd (- (calendar-absolute-from-gregorian greg2) sd)))
22583 ((eq span 'year)
22584 (setq greg2 (list (car greg) (nth 1 greg) (+ arg (nth 2 greg)))
22585 sd (calendar-absolute-from-gregorian greg2))
22586 (setcar (nthcdr 2 greg2) (1+ (nth 2 greg2)))
22587 (setq nd (- (calendar-absolute-from-gregorian greg2) sd))))
22588 (let ((org-agenda-overriding-arguments
22589 (list (car org-agenda-last-arguments) sd nd t)))
22590 (org-agenda-redo)
22591 (org-agenda-find-same-or-today-or-agenda cnt))))
22593 (defun org-agenda-earlier (arg)
22594 "Go backward in time by the current span.
22595 With prefix ARG, go backward that many times the current span."
22596 (interactive "p")
22597 (org-agenda-later (- arg)))
22599 (defun org-agenda-day-view (&optional day-of-year)
22600 "Switch to daily view for agenda.
22601 With argument DAY-OF-YEAR, switch to that day of the year."
22602 (interactive "P")
22603 (setq org-agenda-ndays 1)
22604 (org-agenda-change-time-span 'day day-of-year))
22605 (defun org-agenda-week-view (&optional iso-week)
22606 "Switch to daily view for agenda.
22607 With argument ISO-WEEK, switch to the corresponding ISO week.
22608 If ISO-WEEK has more then 2 digits, only the last two encode the
22609 week. Any digits before this encode a year. So 200712 means
22610 week 12 of year 2007. Years in the range 1938-2037 can also be
22611 written as 2-digit years."
22612 (interactive "P")
22613 (setq org-agenda-ndays 7)
22614 (org-agenda-change-time-span 'week iso-week))
22615 (defun org-agenda-month-view (&optional month)
22616 "Switch to daily view for agenda.
22617 With argument MONTH, switch to that month."
22618 (interactive "P")
22619 ;; FIXME: allow month like 812 to mean 2008 december
22620 (org-agenda-change-time-span 'month month))
22621 (defun org-agenda-year-view (&optional year)
22622 "Switch to daily view for agenda.
22623 With argument YEAR, switch to that year.
22624 If MONTH has more then 2 digits, only the last two encode the
22625 month. Any digits before this encode a year. So 200712 means
22626 December year 2007. Years in the range 1938-2037 can also be
22627 written as 2-digit years."
22628 (interactive "P")
22629 (when year
22630 (setq year (org-small-year-to-year year)))
22631 (if (y-or-n-p "Are you sure you want to compute the agenda for an entire year? ")
22632 (org-agenda-change-time-span 'year year)
22633 (error "Abort")))
22635 (defun org-agenda-change-time-span (span &optional n)
22636 "Change the agenda view to SPAN.
22637 SPAN may be `day', `week', `month', `year'."
22638 (org-agenda-check-type t 'agenda)
22639 (if (and (not n) (equal org-agenda-span span))
22640 (error "Viewing span is already \"%s\"" span))
22641 (let* ((sd (or (get-text-property (point) 'day)
22642 org-starting-day))
22643 (computed (org-agenda-compute-time-span sd span n))
22644 (org-agenda-overriding-arguments
22645 (list (car org-agenda-last-arguments)
22646 (car computed) (cdr computed) t)))
22647 (org-agenda-redo)
22648 (org-agenda-find-same-or-today-or-agenda))
22649 (org-agenda-set-mode-name)
22650 (message "Switched to %s view" span))
22652 (defun org-agenda-compute-time-span (sd span &optional n)
22653 "Compute starting date and number of days for agenda.
22654 SPAN may be `day', `week', `month', `year'. The return value
22655 is a cons cell with the starting date and the number of days,
22656 so that the date SD will be in that range."
22657 (let* ((greg (calendar-gregorian-from-absolute sd))
22658 (dg (nth 1 greg))
22659 (mg (car greg))
22660 (yg (nth 2 greg))
22661 nd w1 y1 m1 thisweek)
22662 (cond
22663 ((eq span 'day)
22664 (when n
22665 (setq sd (+ (calendar-absolute-from-gregorian
22666 (list mg 1 yg))
22667 n -1)))
22668 (setq nd 1))
22669 ((eq span 'week)
22670 (let* ((nt (calendar-day-of-week
22671 (calendar-gregorian-from-absolute sd)))
22672 (d (if org-agenda-start-on-weekday
22673 (- nt org-agenda-start-on-weekday)
22674 0)))
22675 (setq sd (- sd (+ (if (< d 0) 7 0) d)))
22676 (when n
22677 (require 'cal-iso)
22678 (setq thisweek (car (calendar-iso-from-absolute sd)))
22679 (when (> n 99)
22680 (setq y1 (org-small-year-to-year (/ n 100))
22681 n (mod n 100)))
22682 (setq sd
22683 (calendar-absolute-from-iso
22684 (list n 1
22685 (or y1 (nth 2 (calendar-iso-from-absolute sd)))))))
22686 (setq nd 7)))
22687 ((eq span 'month)
22688 (when (and n (> n 99))
22689 (setq y1 (org-small-year-to-year (/ n 100))
22690 n (mod n 100)))
22691 (setq sd (calendar-absolute-from-gregorian
22692 (list (or n mg) 1 (or y1 yg)))
22693 nd (- (calendar-absolute-from-gregorian
22694 (list (1+ (or n mg)) 1 (or y1 yg)))
22695 sd)))
22696 ((eq span 'year)
22697 (setq sd (calendar-absolute-from-gregorian
22698 (list 1 1 (or n yg)))
22699 nd (- (calendar-absolute-from-gregorian
22700 (list 1 1 (1+ (or n yg))))
22701 sd))))
22702 (cons sd nd)))
22704 (defun org-days-to-iso-week (days)
22705 "Return the iso week number."
22706 (require 'cal-iso)
22707 (car (calendar-iso-from-absolute days)))
22709 (defun org-small-year-to-year (year)
22710 "Convert 2-digit years into 4-digit years.
22711 38-99 are mapped into 1938-1999. 1-37 are mapped into 2001-2007.
22712 The year 2000 cannot be abbreviated. Any year lager than 99
22713 is retrned unchanged."
22714 (if (< year 38)
22715 (setq year (+ 2000 year))
22716 (if (< year 100)
22717 (setq year (+ 1900 year))))
22718 year)
22720 ;; FIXME: does not work if user makes date format that starts with a blank
22721 (defun org-agenda-next-date-line (&optional arg)
22722 "Jump to the next line indicating a date in agenda buffer."
22723 (interactive "p")
22724 (org-agenda-check-type t 'agenda 'timeline)
22725 (beginning-of-line 1)
22726 (if (looking-at "^\\S-") (forward-char 1))
22727 (if (not (re-search-forward "^\\S-" nil t arg))
22728 (progn
22729 (backward-char 1)
22730 (error "No next date after this line in this buffer")))
22731 (goto-char (match-beginning 0)))
22733 (defun org-agenda-previous-date-line (&optional arg)
22734 "Jump to the previous line indicating a date in agenda buffer."
22735 (interactive "p")
22736 (org-agenda-check-type t 'agenda 'timeline)
22737 (beginning-of-line 1)
22738 (if (not (re-search-backward "^\\S-" nil t arg))
22739 (error "No previous date before this line in this buffer")))
22741 ;; Initialize the highlight
22742 (defvar org-hl (org-make-overlay 1 1))
22743 (org-overlay-put org-hl 'face 'highlight)
22745 (defun org-highlight (begin end &optional buffer)
22746 "Highlight a region with overlay."
22747 (funcall (if (featurep 'xemacs) 'set-extent-endpoints 'move-overlay)
22748 org-hl begin end (or buffer (current-buffer))))
22750 (defun org-unhighlight ()
22751 "Detach overlay INDEX."
22752 (funcall (if (featurep 'xemacs) 'detach-extent 'delete-overlay) org-hl))
22754 ;; FIXME this is currently not used.
22755 (defun org-highlight-until-next-command (beg end &optional buffer)
22756 (org-highlight beg end buffer)
22757 (add-hook 'pre-command-hook 'org-unhighlight-once))
22758 (defun org-unhighlight-once ()
22759 (remove-hook 'pre-command-hook 'org-unhighlight-once)
22760 (org-unhighlight))
22762 (defun org-agenda-follow-mode ()
22763 "Toggle follow mode in an agenda buffer."
22764 (interactive)
22765 (setq org-agenda-follow-mode (not org-agenda-follow-mode))
22766 (org-agenda-set-mode-name)
22767 (message "Follow mode is %s"
22768 (if org-agenda-follow-mode "on" "off")))
22770 (defun org-agenda-log-mode ()
22771 "Toggle log mode in an agenda buffer."
22772 (interactive)
22773 (org-agenda-check-type t 'agenda 'timeline)
22774 (setq org-agenda-show-log (not org-agenda-show-log))
22775 (org-agenda-set-mode-name)
22776 (org-agenda-redo)
22777 (message "Log mode is %s"
22778 (if org-agenda-show-log "on" "off")))
22780 (defun org-agenda-toggle-diary ()
22781 "Toggle diary inclusion in an agenda buffer."
22782 (interactive)
22783 (org-agenda-check-type t 'agenda)
22784 (setq org-agenda-include-diary (not org-agenda-include-diary))
22785 (org-agenda-redo)
22786 (org-agenda-set-mode-name)
22787 (message "Diary inclusion turned %s"
22788 (if org-agenda-include-diary "on" "off")))
22790 (defun org-agenda-toggle-time-grid ()
22791 "Toggle time grid in an agenda buffer."
22792 (interactive)
22793 (org-agenda-check-type t 'agenda)
22794 (setq org-agenda-use-time-grid (not org-agenda-use-time-grid))
22795 (org-agenda-redo)
22796 (org-agenda-set-mode-name)
22797 (message "Time-grid turned %s"
22798 (if org-agenda-use-time-grid "on" "off")))
22800 (defun org-agenda-set-mode-name ()
22801 "Set the mode name to indicate all the small mode settings."
22802 (setq mode-name
22803 (concat "Org-Agenda"
22804 (if (equal org-agenda-ndays 1) " Day" "")
22805 (if (equal org-agenda-ndays 7) " Week" "")
22806 (if org-agenda-follow-mode " Follow" "")
22807 (if org-agenda-include-diary " Diary" "")
22808 (if org-agenda-use-time-grid " Grid" "")
22809 (if org-agenda-show-log " Log" "")))
22810 (force-mode-line-update))
22812 (defun org-agenda-post-command-hook ()
22813 (and (eolp) (not (bolp)) (backward-char 1))
22814 (setq org-agenda-type (get-text-property (point) 'org-agenda-type))
22815 (if (and org-agenda-follow-mode
22816 (get-text-property (point) 'org-marker))
22817 (org-agenda-show)))
22819 (defun org-agenda-show-priority ()
22820 "Show the priority of the current item.
22821 This priority is composed of the main priority given with the [#A] cookies,
22822 and by additional input from the age of a schedules or deadline entry."
22823 (interactive)
22824 (let* ((pri (get-text-property (point-at-bol) 'priority)))
22825 (message "Priority is %d" (if pri pri -1000))))
22827 (defun org-agenda-show-tags ()
22828 "Show the tags applicable to the current item."
22829 (interactive)
22830 (let* ((tags (get-text-property (point-at-bol) 'tags)))
22831 (if tags
22832 (message "Tags are :%s:"
22833 (org-no-properties (mapconcat 'identity tags ":")))
22834 (message "No tags associated with this line"))))
22836 (defun org-agenda-goto (&optional highlight)
22837 "Go to the Org-mode file which contains the item at point."
22838 (interactive)
22839 (let* ((marker (or (get-text-property (point) 'org-marker)
22840 (org-agenda-error)))
22841 (buffer (marker-buffer marker))
22842 (pos (marker-position marker)))
22843 (switch-to-buffer-other-window buffer)
22844 (widen)
22845 (goto-char pos)
22846 (when (org-mode-p)
22847 (org-show-context 'agenda)
22848 (save-excursion
22849 (and (outline-next-heading)
22850 (org-flag-heading nil)))) ; show the next heading
22851 (recenter (/ (window-height) 2))
22852 (run-hooks 'org-agenda-after-show-hook)
22853 (and highlight (org-highlight (point-at-bol) (point-at-eol)))))
22855 (defvar org-agenda-after-show-hook nil
22856 "Normal hook run after an item has been shown from the agenda.
22857 Point is in the buffer where the item originated.")
22859 (defun org-agenda-kill ()
22860 "Kill the entry or subtree belonging to the current agenda entry."
22861 (interactive)
22862 (or (eq major-mode 'org-agenda-mode) (error "Not in agenda"))
22863 (let* ((marker (or (get-text-property (point) 'org-marker)
22864 (org-agenda-error)))
22865 (buffer (marker-buffer marker))
22866 (pos (marker-position marker))
22867 (type (get-text-property (point) 'type))
22868 dbeg dend (n 0) conf)
22869 (org-with-remote-undo buffer
22870 (with-current-buffer buffer
22871 (save-excursion
22872 (goto-char pos)
22873 (if (and (org-mode-p) (not (member type '("sexp"))))
22874 (setq dbeg (progn (org-back-to-heading t) (point))
22875 dend (org-end-of-subtree t t))
22876 (setq dbeg (point-at-bol)
22877 dend (min (point-max) (1+ (point-at-eol)))))
22878 (goto-char dbeg)
22879 (while (re-search-forward "^[ \t]*\\S-" dend t) (setq n (1+ n)))))
22880 (setq conf (or (eq t org-agenda-confirm-kill)
22881 (and (numberp org-agenda-confirm-kill)
22882 (> n org-agenda-confirm-kill))))
22883 (and conf
22884 (not (y-or-n-p
22885 (format "Delete entry with %d lines in buffer \"%s\"? "
22886 n (buffer-name buffer))))
22887 (error "Abort"))
22888 (org-remove-subtree-entries-from-agenda buffer dbeg dend)
22889 (with-current-buffer buffer (delete-region dbeg dend))
22890 (message "Agenda item and source killed"))))
22892 (defun org-agenda-archive ()
22893 "Kill the entry or subtree belonging to the current agenda entry."
22894 (interactive)
22895 (or (eq major-mode 'org-agenda-mode) (error "Not in agenda"))
22896 (let* ((marker (or (get-text-property (point) 'org-marker)
22897 (org-agenda-error)))
22898 (buffer (marker-buffer marker))
22899 (pos (marker-position marker)))
22900 (org-with-remote-undo buffer
22901 (with-current-buffer buffer
22902 (if (org-mode-p)
22903 (save-excursion
22904 (goto-char pos)
22905 (org-remove-subtree-entries-from-agenda)
22906 (org-back-to-heading t)
22907 (org-archive-subtree))
22908 (error "Archiving works only in Org-mode files"))))))
22910 (defun org-remove-subtree-entries-from-agenda (&optional buf beg end)
22911 "Remove all lines in the agenda that correspond to a given subtree.
22912 The subtree is the one in buffer BUF, starting at BEG and ending at END.
22913 If this information is not given, the function uses the tree at point."
22914 (let ((buf (or buf (current-buffer))) m p)
22915 (save-excursion
22916 (unless (and beg end)
22917 (org-back-to-heading t)
22918 (setq beg (point))
22919 (org-end-of-subtree t)
22920 (setq end (point)))
22921 (set-buffer (get-buffer org-agenda-buffer-name))
22922 (save-excursion
22923 (goto-char (point-max))
22924 (beginning-of-line 1)
22925 (while (not (bobp))
22926 (when (and (setq m (get-text-property (point) 'org-marker))
22927 (equal buf (marker-buffer m))
22928 (setq p (marker-position m))
22929 (>= p beg)
22930 (<= p end))
22931 (let ((inhibit-read-only t))
22932 (delete-region (point-at-bol) (1+ (point-at-eol)))))
22933 (beginning-of-line 0))))))
22935 (defun org-agenda-open-link ()
22936 "Follow the link in the current line, if any."
22937 (interactive)
22938 (org-agenda-copy-local-variable 'org-link-abbrev-alist-local)
22939 (save-excursion
22940 (save-restriction
22941 (narrow-to-region (point-at-bol) (point-at-eol))
22942 (org-open-at-point))))
22944 (defun org-agenda-copy-local-variable (var)
22945 "Get a variable from a referenced buffer and install it here."
22946 (let ((m (get-text-property (point) 'org-marker)))
22947 (when (and m (buffer-live-p (marker-buffer m)))
22948 (org-set-local var (with-current-buffer (marker-buffer m)
22949 (symbol-value var))))))
22951 (defun org-agenda-switch-to (&optional delete-other-windows)
22952 "Go to the Org-mode file which contains the item at point."
22953 (interactive)
22954 (let* ((marker (or (get-text-property (point) 'org-marker)
22955 (org-agenda-error)))
22956 (buffer (marker-buffer marker))
22957 (pos (marker-position marker)))
22958 (switch-to-buffer buffer)
22959 (and delete-other-windows (delete-other-windows))
22960 (widen)
22961 (goto-char pos)
22962 (when (org-mode-p)
22963 (org-show-context 'agenda)
22964 (save-excursion
22965 (and (outline-next-heading)
22966 (org-flag-heading nil)))))) ; show the next heading
22968 (defun org-agenda-goto-mouse (ev)
22969 "Go to the Org-mode file which contains the item at the mouse click."
22970 (interactive "e")
22971 (mouse-set-point ev)
22972 (org-agenda-goto))
22974 (defun org-agenda-show ()
22975 "Display the Org-mode file which contains the item at point."
22976 (interactive)
22977 (let ((win (selected-window)))
22978 (org-agenda-goto t)
22979 (select-window win)))
22981 (defun org-agenda-recenter (arg)
22982 "Display the Org-mode file which contains the item at point and recenter."
22983 (interactive "P")
22984 (let ((win (selected-window)))
22985 (org-agenda-goto t)
22986 (recenter arg)
22987 (select-window win)))
22989 (defun org-agenda-show-mouse (ev)
22990 "Display the Org-mode file which contains the item at the mouse click."
22991 (interactive "e")
22992 (mouse-set-point ev)
22993 (org-agenda-show))
22995 (defun org-agenda-check-no-diary ()
22996 "Check if the entry is a diary link and abort if yes."
22997 (if (get-text-property (point) 'org-agenda-diary-link)
22998 (org-agenda-error)))
23000 (defun org-agenda-error ()
23001 (error "Command not allowed in this line"))
23003 (defun org-agenda-tree-to-indirect-buffer ()
23004 "Show the subtree corresponding to the current entry in an indirect buffer.
23005 This calls the command `org-tree-to-indirect-buffer' from the original
23006 Org-mode buffer.
23007 With numerical prefix arg ARG, go up to this level and then take that tree.
23008 With a C-u prefix, make a separate frame for this tree (i.e. don't use the
23009 dedicated frame)."
23010 (interactive)
23011 (org-agenda-check-no-diary)
23012 (let* ((marker (or (get-text-property (point) 'org-marker)
23013 (org-agenda-error)))
23014 (buffer (marker-buffer marker))
23015 (pos (marker-position marker)))
23016 (with-current-buffer buffer
23017 (save-excursion
23018 (goto-char pos)
23019 (call-interactively 'org-tree-to-indirect-buffer)))))
23021 (defvar org-last-heading-marker (make-marker)
23022 "Marker pointing to the headline that last changed its TODO state
23023 by a remote command from the agenda.")
23025 (defun org-agenda-todo-nextset ()
23026 "Switch TODO entry to next sequence."
23027 (interactive)
23028 (org-agenda-todo 'nextset))
23030 (defun org-agenda-todo-previousset ()
23031 "Switch TODO entry to previous sequence."
23032 (interactive)
23033 (org-agenda-todo 'previousset))
23035 (defun org-agenda-todo (&optional arg)
23036 "Cycle TODO state of line at point, also in Org-mode file.
23037 This changes the line at point, all other lines in the agenda referring to
23038 the same tree node, and the headline of the tree node in the Org-mode file."
23039 (interactive "P")
23040 (org-agenda-check-no-diary)
23041 (let* ((col (current-column))
23042 (marker (or (get-text-property (point) 'org-marker)
23043 (org-agenda-error)))
23044 (buffer (marker-buffer marker))
23045 (pos (marker-position marker))
23046 (hdmarker (get-text-property (point) 'org-hd-marker))
23047 (inhibit-read-only t)
23048 newhead)
23049 (org-with-remote-undo buffer
23050 (with-current-buffer buffer
23051 (widen)
23052 (goto-char pos)
23053 (org-show-context 'agenda)
23054 (save-excursion
23055 (and (outline-next-heading)
23056 (org-flag-heading nil))) ; show the next heading
23057 (org-todo arg)
23058 (and (bolp) (forward-char 1))
23059 (setq newhead (org-get-heading))
23060 (save-excursion
23061 (org-back-to-heading)
23062 (move-marker org-last-heading-marker (point))))
23063 (beginning-of-line 1)
23064 (save-excursion
23065 (org-agenda-change-all-lines newhead hdmarker 'fixface))
23066 (move-to-column col))))
23068 (defun org-agenda-change-all-lines (newhead hdmarker &optional fixface)
23069 "Change all lines in the agenda buffer which match HDMARKER.
23070 The new content of the line will be NEWHEAD (as modified by
23071 `org-format-agenda-item'). HDMARKER is checked with
23072 `equal' against all `org-hd-marker' text properties in the file.
23073 If FIXFACE is non-nil, the face of each item is modified acording to
23074 the new TODO state."
23075 (let* ((inhibit-read-only t)
23076 props m pl undone-face done-face finish new dotime cat tags)
23077 (save-excursion
23078 (goto-char (point-max))
23079 (beginning-of-line 1)
23080 (while (not finish)
23081 (setq finish (bobp))
23082 (when (and (setq m (get-text-property (point) 'org-hd-marker))
23083 (equal m hdmarker))
23084 (setq props (text-properties-at (point))
23085 dotime (get-text-property (point) 'dotime)
23086 cat (get-text-property (point) 'org-category)
23087 tags (get-text-property (point) 'tags)
23088 new (org-format-agenda-item "x" newhead cat tags dotime 'noprefix)
23089 pl (get-text-property (point) 'prefix-length)
23090 undone-face (get-text-property (point) 'undone-face)
23091 done-face (get-text-property (point) 'done-face))
23092 (move-to-column pl)
23093 (cond
23094 ((equal new "")
23095 (beginning-of-line 1)
23096 (and (looking-at ".*\n?") (replace-match "")))
23097 ((looking-at ".*")
23098 (replace-match new t t)
23099 (beginning-of-line 1)
23100 (add-text-properties (point-at-bol) (point-at-eol) props)
23101 (when fixface
23102 (add-text-properties
23103 (point-at-bol) (point-at-eol)
23104 (list 'face
23105 (if org-last-todo-state-is-todo
23106 undone-face done-face))))
23107 (org-agenda-highlight-todo 'line)
23108 (beginning-of-line 1))
23109 (t (error "Line update did not work"))))
23110 (beginning-of-line 0)))
23111 (org-finalize-agenda)))
23113 (defun org-agenda-align-tags (&optional line)
23114 "Align all tags in agenda items to `org-agenda-tags-column'."
23115 (let ((inhibit-read-only t) l c)
23116 (save-excursion
23117 (goto-char (if line (point-at-bol) (point-min)))
23118 (while (re-search-forward (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$")
23119 (if line (point-at-eol) nil) t)
23120 (add-text-properties
23121 (match-beginning 2) (match-end 2)
23122 (list 'face (delq nil (list 'org-tag (get-text-property
23123 (match-beginning 2) 'face)))))
23124 (setq l (- (match-end 2) (match-beginning 2))
23125 c (if (< org-agenda-tags-column 0)
23126 (- (abs org-agenda-tags-column) l)
23127 org-agenda-tags-column))
23128 (delete-region (match-beginning 1) (match-end 1))
23129 (goto-char (match-beginning 1))
23130 (insert (org-add-props
23131 (make-string (max 1 (- c (current-column))) ?\ )
23132 (text-properties-at (point))))))))
23134 (defun org-agenda-priority-up ()
23135 "Increase the priority of line at point, also in Org-mode file."
23136 (interactive)
23137 (org-agenda-priority 'up))
23139 (defun org-agenda-priority-down ()
23140 "Decrease the priority of line at point, also in Org-mode file."
23141 (interactive)
23142 (org-agenda-priority 'down))
23144 (defun org-agenda-priority (&optional force-direction)
23145 "Set the priority of line at point, also in Org-mode file.
23146 This changes the line at point, all other lines in the agenda referring to
23147 the same tree node, and the headline of the tree node in the Org-mode file."
23148 (interactive)
23149 (org-agenda-check-no-diary)
23150 (let* ((marker (or (get-text-property (point) 'org-marker)
23151 (org-agenda-error)))
23152 (hdmarker (get-text-property (point) 'org-hd-marker))
23153 (buffer (marker-buffer hdmarker))
23154 (pos (marker-position hdmarker))
23155 (inhibit-read-only t)
23156 newhead)
23157 (org-with-remote-undo buffer
23158 (with-current-buffer buffer
23159 (widen)
23160 (goto-char pos)
23161 (org-show-context 'agenda)
23162 (save-excursion
23163 (and (outline-next-heading)
23164 (org-flag-heading nil))) ; show the next heading
23165 (funcall 'org-priority force-direction)
23166 (end-of-line 1)
23167 (setq newhead (org-get-heading)))
23168 (org-agenda-change-all-lines newhead hdmarker)
23169 (beginning-of-line 1))))
23171 (defun org-get-tags-at (&optional pos)
23172 "Get a list of all headline tags applicable at POS.
23173 POS defaults to point. If tags are inherited, the list contains
23174 the targets in the same sequence as the headlines appear, i.e.
23175 the tags of the current headline come last."
23176 (interactive)
23177 (let (tags lastpos)
23178 (save-excursion
23179 (save-restriction
23180 (widen)
23181 (goto-char (or pos (point)))
23182 (save-match-data
23183 (condition-case nil
23184 (progn
23185 (org-back-to-heading t)
23186 (while (not (equal lastpos (point)))
23187 (setq lastpos (point))
23188 (if (looking-at (org-re "[^\r\n]+?:\\([[:alnum:]_@:]+\\):[ \t]*$"))
23189 (setq tags (append (org-split-string
23190 (org-match-string-no-properties 1) ":")
23191 tags)))
23192 (or org-use-tag-inheritance (error ""))
23193 (org-up-heading-all 1)))
23194 (error nil))))
23195 tags)))
23197 ;; FIXME: should fix the tags property of the agenda line.
23198 (defun org-agenda-set-tags ()
23199 "Set tags for the current headline."
23200 (interactive)
23201 (org-agenda-check-no-diary)
23202 (if (and (org-region-active-p) (interactive-p))
23203 (call-interactively 'org-change-tag-in-region)
23204 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
23205 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
23206 (org-agenda-error)))
23207 (buffer (marker-buffer hdmarker))
23208 (pos (marker-position hdmarker))
23209 (inhibit-read-only t)
23210 newhead)
23211 (org-with-remote-undo buffer
23212 (with-current-buffer buffer
23213 (widen)
23214 (goto-char pos)
23215 (save-excursion
23216 (org-show-context 'agenda))
23217 (save-excursion
23218 (and (outline-next-heading)
23219 (org-flag-heading nil))) ; show the next heading
23220 (goto-char pos)
23221 (call-interactively 'org-set-tags)
23222 (end-of-line 1)
23223 (setq newhead (org-get-heading)))
23224 (org-agenda-change-all-lines newhead hdmarker)
23225 (beginning-of-line 1)))))
23227 (defun org-agenda-toggle-archive-tag ()
23228 "Toggle the archive tag for the current entry."
23229 (interactive)
23230 (org-agenda-check-no-diary)
23231 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
23232 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
23233 (org-agenda-error)))
23234 (buffer (marker-buffer hdmarker))
23235 (pos (marker-position hdmarker))
23236 (inhibit-read-only t)
23237 newhead)
23238 (org-with-remote-undo buffer
23239 (with-current-buffer buffer
23240 (widen)
23241 (goto-char pos)
23242 (org-show-context 'agenda)
23243 (save-excursion
23244 (and (outline-next-heading)
23245 (org-flag-heading nil))) ; show the next heading
23246 (call-interactively 'org-toggle-archive-tag)
23247 (end-of-line 1)
23248 (setq newhead (org-get-heading)))
23249 (org-agenda-change-all-lines newhead hdmarker)
23250 (beginning-of-line 1))))
23252 (defun org-agenda-date-later (arg &optional what)
23253 "Change the date of this item to one day later."
23254 (interactive "p")
23255 (org-agenda-check-type t 'agenda 'timeline)
23256 (org-agenda-check-no-diary)
23257 (let* ((marker (or (get-text-property (point) 'org-marker)
23258 (org-agenda-error)))
23259 (buffer (marker-buffer marker))
23260 (pos (marker-position marker)))
23261 (org-with-remote-undo buffer
23262 (with-current-buffer buffer
23263 (widen)
23264 (goto-char pos)
23265 (if (not (org-at-timestamp-p))
23266 (error "Cannot find time stamp"))
23267 (org-timestamp-change arg (or what 'day)))
23268 (org-agenda-show-new-time marker org-last-changed-timestamp))
23269 (message "Time stamp changed to %s" org-last-changed-timestamp)))
23271 (defun org-agenda-date-earlier (arg &optional what)
23272 "Change the date of this item to one day earlier."
23273 (interactive "p")
23274 (org-agenda-date-later (- arg) what))
23276 (defun org-agenda-show-new-time (marker stamp &optional prefix)
23277 "Show new date stamp via text properties."
23278 ;; We use text properties to make this undoable
23279 (let ((inhibit-read-only t))
23280 (setq stamp (concat " " prefix " => " stamp))
23281 (save-excursion
23282 (goto-char (point-max))
23283 (while (not (bobp))
23284 (when (equal marker (get-text-property (point) 'org-marker))
23285 (move-to-column (- (window-width) (length stamp)) t)
23286 (if (featurep 'xemacs)
23287 ;; Use `duplicable' property to trigger undo recording
23288 (let ((ex (make-extent nil nil))
23289 (gl (make-glyph stamp)))
23290 (set-glyph-face gl 'secondary-selection)
23291 (set-extent-properties
23292 ex (list 'invisible t 'end-glyph gl 'duplicable t))
23293 (insert-extent ex (1- (point)) (point-at-eol)))
23294 (add-text-properties
23295 (1- (point)) (point-at-eol)
23296 (list 'display (org-add-props stamp nil
23297 'face 'secondary-selection))))
23298 (beginning-of-line 1))
23299 (beginning-of-line 0)))))
23301 (defun org-agenda-date-prompt (arg)
23302 "Change the date of this item. Date is prompted for, with default today.
23303 The prefix ARG is passed to the `org-time-stamp' command and can therefore
23304 be used to request time specification in the time stamp."
23305 (interactive "P")
23306 (org-agenda-check-type t 'agenda 'timeline)
23307 (org-agenda-check-no-diary)
23308 (let* ((marker (or (get-text-property (point) 'org-marker)
23309 (org-agenda-error)))
23310 (buffer (marker-buffer marker))
23311 (pos (marker-position marker)))
23312 (org-with-remote-undo buffer
23313 (with-current-buffer buffer
23314 (widen)
23315 (goto-char pos)
23316 (if (not (org-at-timestamp-p))
23317 (error "Cannot find time stamp"))
23318 (org-time-stamp arg)
23319 (message "Time stamp changed to %s" org-last-changed-timestamp)))))
23321 (defun org-agenda-schedule (arg)
23322 "Schedule the item at point."
23323 (interactive "P")
23324 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags 'search)
23325 (org-agenda-check-no-diary)
23326 (let* ((marker (or (get-text-property (point) 'org-marker)
23327 (org-agenda-error)))
23328 (type (marker-insertion-type marker))
23329 (buffer (marker-buffer marker))
23330 (pos (marker-position marker))
23331 (org-insert-labeled-timestamps-at-point nil)
23333 (when type (message "%s" type) (sit-for 3))
23334 (set-marker-insertion-type marker t)
23335 (org-with-remote-undo buffer
23336 (with-current-buffer buffer
23337 (widen)
23338 (goto-char pos)
23339 (setq ts (org-schedule arg)))
23340 (org-agenda-show-new-time marker ts "S"))
23341 (message "Item scheduled for %s" ts)))
23343 (defun org-agenda-deadline (arg)
23344 "Schedule the item at point."
23345 (interactive "P")
23346 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags 'search)
23347 (org-agenda-check-no-diary)
23348 (let* ((marker (or (get-text-property (point) 'org-marker)
23349 (org-agenda-error)))
23350 (buffer (marker-buffer marker))
23351 (pos (marker-position marker))
23352 (org-insert-labeled-timestamps-at-point nil)
23354 (org-with-remote-undo buffer
23355 (with-current-buffer buffer
23356 (widen)
23357 (goto-char pos)
23358 (setq ts (org-deadline arg)))
23359 (org-agenda-show-new-time marker ts "S"))
23360 (message "Deadline for this item set to %s" ts)))
23362 (defun org-get-heading (&optional no-tags)
23363 "Return the heading of the current entry, without the stars."
23364 (save-excursion
23365 (org-back-to-heading t)
23366 (if (looking-at
23367 (if no-tags
23368 (org-re "\\*+[ \t]+\\([^\n\r]*?\\)\\([ \t]+:[[:alnum:]:_@]+:[ \t]*\\)?$")
23369 "\\*+[ \t]+\\([^\r\n]*\\)"))
23370 (match-string 1) "")))
23372 (defun org-agenda-clock-in (&optional arg)
23373 "Start the clock on the currently selected item."
23374 (interactive "P")
23375 (org-agenda-check-no-diary)
23376 (let* ((marker (or (get-text-property (point) 'org-marker)
23377 (org-agenda-error)))
23378 (pos (marker-position marker)))
23379 (org-with-remote-undo (marker-buffer marker)
23380 (with-current-buffer (marker-buffer marker)
23381 (widen)
23382 (goto-char pos)
23383 (org-clock-in)))))
23385 (defun org-agenda-clock-out (&optional arg)
23386 "Stop the currently running clock."
23387 (interactive "P")
23388 (unless (marker-buffer org-clock-marker)
23389 (error "No running clock"))
23390 (org-with-remote-undo (marker-buffer org-clock-marker)
23391 (org-clock-out)))
23393 (defun org-agenda-clock-cancel (&optional arg)
23394 "Cancel the currently running clock."
23395 (interactive "P")
23396 (unless (marker-buffer org-clock-marker)
23397 (error "No running clock"))
23398 (org-with-remote-undo (marker-buffer org-clock-marker)
23399 (org-clock-cancel)))
23401 (defun org-agenda-diary-entry ()
23402 "Make a diary entry, like the `i' command from the calendar.
23403 All the standard commands work: block, weekly etc."
23404 (interactive)
23405 (org-agenda-check-type t 'agenda 'timeline)
23406 (require 'diary-lib)
23407 (let* ((char (progn
23408 (message "Diary entry: [d]ay [w]eekly [m]onthly [y]early [a]nniversary [b]lock [c]yclic")
23409 (read-char-exclusive)))
23410 (cmd (cdr (assoc char
23411 '((?d . insert-diary-entry)
23412 (?w . insert-weekly-diary-entry)
23413 (?m . insert-monthly-diary-entry)
23414 (?y . insert-yearly-diary-entry)
23415 (?a . insert-anniversary-diary-entry)
23416 (?b . insert-block-diary-entry)
23417 (?c . insert-cyclic-diary-entry)))))
23418 (oldf (symbol-function 'calendar-cursor-to-date))
23419 ; (buf (get-file-buffer (substitute-in-file-name diary-file)))
23420 (point (point))
23421 (mark (or (mark t) (point))))
23422 (unless cmd
23423 (error "No command associated with <%c>" char))
23424 (unless (and (get-text-property point 'day)
23425 (or (not (equal ?b char))
23426 (get-text-property mark 'day)))
23427 (error "Don't know which date to use for diary entry"))
23428 ;; We implement this by hacking the `calendar-cursor-to-date' function
23429 ;; and the `calendar-mark-ring' variable. Saves a lot of code.
23430 (let ((calendar-mark-ring
23431 (list (calendar-gregorian-from-absolute
23432 (or (get-text-property mark 'day)
23433 (get-text-property point 'day))))))
23434 (unwind-protect
23435 (progn
23436 (fset 'calendar-cursor-to-date
23437 (lambda (&optional error)
23438 (calendar-gregorian-from-absolute
23439 (get-text-property point 'day))))
23440 (call-interactively cmd))
23441 (fset 'calendar-cursor-to-date oldf)))))
23444 (defun org-agenda-execute-calendar-command (cmd)
23445 "Execute a calendar command from the agenda, with the date associated to
23446 the cursor position."
23447 (org-agenda-check-type t 'agenda 'timeline)
23448 (require 'diary-lib)
23449 (unless (get-text-property (point) 'day)
23450 (error "Don't know which date to use for calendar command"))
23451 (let* ((oldf (symbol-function 'calendar-cursor-to-date))
23452 (point (point))
23453 (date (calendar-gregorian-from-absolute
23454 (get-text-property point 'day)))
23455 ;; the following 3 vars are needed in the calendar
23456 (displayed-day (extract-calendar-day date))
23457 (displayed-month (extract-calendar-month date))
23458 (displayed-year (extract-calendar-year date)))
23459 (unwind-protect
23460 (progn
23461 (fset 'calendar-cursor-to-date
23462 (lambda (&optional error)
23463 (calendar-gregorian-from-absolute
23464 (get-text-property point 'day))))
23465 (call-interactively cmd))
23466 (fset 'calendar-cursor-to-date oldf))))
23468 (defun org-agenda-phases-of-moon ()
23469 "Display the phases of the moon for the 3 months around the cursor date."
23470 (interactive)
23471 (org-agenda-execute-calendar-command 'calendar-phases-of-moon))
23473 (defun org-agenda-holidays ()
23474 "Display the holidays for the 3 months around the cursor date."
23475 (interactive)
23476 (org-agenda-execute-calendar-command 'list-calendar-holidays))
23478 (defvar calendar-longitude)
23479 (defvar calendar-latitude)
23480 (defvar calendar-location-name)
23482 (defun org-agenda-sunrise-sunset (arg)
23483 "Display sunrise and sunset for the cursor date.
23484 Latitude and longitude can be specified with the variables
23485 `calendar-latitude' and `calendar-longitude'. When called with prefix
23486 argument, latitude and longitude will be prompted for."
23487 (interactive "P")
23488 (require 'solar)
23489 (let ((calendar-longitude (if arg nil calendar-longitude))
23490 (calendar-latitude (if arg nil calendar-latitude))
23491 (calendar-location-name
23492 (if arg "the given coordinates" calendar-location-name)))
23493 (org-agenda-execute-calendar-command 'calendar-sunrise-sunset)))
23495 (defun org-agenda-goto-calendar ()
23496 "Open the Emacs calendar with the date at the cursor."
23497 (interactive)
23498 (org-agenda-check-type t 'agenda 'timeline)
23499 (let* ((day (or (get-text-property (point) 'day)
23500 (error "Don't know which date to open in calendar")))
23501 (date (calendar-gregorian-from-absolute day))
23502 (calendar-move-hook nil)
23503 (view-calendar-holidays-initially nil)
23504 (view-diary-entries-initially nil))
23505 (calendar)
23506 (calendar-goto-date date)))
23508 (defun org-calendar-goto-agenda ()
23509 "Compute the Org-mode agenda for the calendar date displayed at the cursor.
23510 This is a command that has to be installed in `calendar-mode-map'."
23511 (interactive)
23512 (org-agenda-list nil (calendar-absolute-from-gregorian
23513 (calendar-cursor-to-date))
23514 nil))
23516 (defun org-agenda-convert-date ()
23517 (interactive)
23518 (org-agenda-check-type t 'agenda 'timeline)
23519 (let ((day (get-text-property (point) 'day))
23520 date s)
23521 (unless day
23522 (error "Don't know which date to convert"))
23523 (setq date (calendar-gregorian-from-absolute day))
23524 (setq s (concat
23525 "Gregorian: " (calendar-date-string date) "\n"
23526 "ISO: " (calendar-iso-date-string date) "\n"
23527 "Day of Yr: " (calendar-day-of-year-string date) "\n"
23528 "Julian: " (calendar-julian-date-string date) "\n"
23529 "Astron. JD: " (calendar-astro-date-string date)
23530 " (Julian date number at noon UTC)\n"
23531 "Hebrew: " (calendar-hebrew-date-string date) " (until sunset)\n"
23532 "Islamic: " (calendar-islamic-date-string date) " (until sunset)\n"
23533 "French: " (calendar-french-date-string date) "\n"
23534 "Baha'i: " (calendar-bahai-date-string date) " (until sunset)\n"
23535 "Mayan: " (calendar-mayan-date-string date) "\n"
23536 "Coptic: " (calendar-coptic-date-string date) "\n"
23537 "Ethiopic: " (calendar-ethiopic-date-string date) "\n"
23538 "Persian: " (calendar-persian-date-string date) "\n"
23539 "Chinese: " (calendar-chinese-date-string date) "\n"))
23540 (with-output-to-temp-buffer "*Dates*"
23541 (princ s))
23542 (if (fboundp 'fit-window-to-buffer)
23543 (fit-window-to-buffer (get-buffer-window "*Dates*")))))
23546 ;;;; Embedded LaTeX
23548 (defvar org-cdlatex-mode-map (make-sparse-keymap)
23549 "Keymap for the minor `org-cdlatex-mode'.")
23551 (org-defkey org-cdlatex-mode-map "_" 'org-cdlatex-underscore-caret)
23552 (org-defkey org-cdlatex-mode-map "^" 'org-cdlatex-underscore-caret)
23553 (org-defkey org-cdlatex-mode-map "`" 'cdlatex-math-symbol)
23554 (org-defkey org-cdlatex-mode-map "'" 'org-cdlatex-math-modify)
23555 (org-defkey org-cdlatex-mode-map "\C-c{" 'cdlatex-environment)
23557 (defvar org-cdlatex-texmathp-advice-is-done nil
23558 "Flag remembering if we have applied the advice to texmathp already.")
23560 (define-minor-mode org-cdlatex-mode
23561 "Toggle the minor `org-cdlatex-mode'.
23562 This mode supports entering LaTeX environment and math in LaTeX fragments
23563 in Org-mode.
23564 \\{org-cdlatex-mode-map}"
23565 nil " OCDL" nil
23566 (when org-cdlatex-mode (require 'cdlatex))
23567 (unless org-cdlatex-texmathp-advice-is-done
23568 (setq org-cdlatex-texmathp-advice-is-done t)
23569 (defadvice texmathp (around org-math-always-on activate)
23570 "Always return t in org-mode buffers.
23571 This is because we want to insert math symbols without dollars even outside
23572 the LaTeX math segments. If Orgmode thinks that point is actually inside
23573 en embedded LaTeX fragement, let texmathp do its job.
23574 \\[org-cdlatex-mode-map]"
23575 (interactive)
23576 (let (p)
23577 (cond
23578 ((not (org-mode-p)) ad-do-it)
23579 ((eq this-command 'cdlatex-math-symbol)
23580 (setq ad-return-value t
23581 texmathp-why '("cdlatex-math-symbol in org-mode" . 0)))
23583 (let ((p (org-inside-LaTeX-fragment-p)))
23584 (if (and p (member (car p) (plist-get org-format-latex-options :matchers)))
23585 (setq ad-return-value t
23586 texmathp-why '("Org-mode embedded math" . 0))
23587 (if p ad-do-it)))))))))
23589 (defun turn-on-org-cdlatex ()
23590 "Unconditionally turn on `org-cdlatex-mode'."
23591 (org-cdlatex-mode 1))
23593 (defun org-inside-LaTeX-fragment-p ()
23594 "Test if point is inside a LaTeX fragment.
23595 I.e. after a \\begin, \\(, \\[, $, or $$, without the corresponding closing
23596 sequence appearing also before point.
23597 Even though the matchers for math are configurable, this function assumes
23598 that \\begin, \\(, \\[, and $$ are always used. Only the single dollar
23599 delimiters are skipped when they have been removed by customization.
23600 The return value is nil, or a cons cell with the delimiter and
23601 and the position of this delimiter.
23603 This function does a reasonably good job, but can locally be fooled by
23604 for example currency specifications. For example it will assume being in
23605 inline math after \"$22.34\". The LaTeX fragment formatter will only format
23606 fragments that are properly closed, but during editing, we have to live
23607 with the uncertainty caused by missing closing delimiters. This function
23608 looks only before point, not after."
23609 (catch 'exit
23610 (let ((pos (point))
23611 (dodollar (member "$" (plist-get org-format-latex-options :matchers)))
23612 (lim (progn
23613 (re-search-backward (concat "^\\(" paragraph-start "\\)") nil t)
23614 (point)))
23615 dd-on str (start 0) m re)
23616 (goto-char pos)
23617 (when dodollar
23618 (setq str (concat (buffer-substring lim (point)) "\000 X$.")
23619 re (nth 1 (assoc "$" org-latex-regexps)))
23620 (while (string-match re str start)
23621 (cond
23622 ((= (match-end 0) (length str))
23623 (throw 'exit (cons "$" (+ lim (match-beginning 0) 1))))
23624 ((= (match-end 0) (- (length str) 5))
23625 (throw 'exit nil))
23626 (t (setq start (match-end 0))))))
23627 (when (setq m (re-search-backward "\\(\\\\begin{[^}]*}\\|\\\\(\\|\\\\\\[\\)\\|\\(\\\\end{[^}]*}\\|\\\\)\\|\\\\\\]\\)\\|\\(\\$\\$\\)" lim t))
23628 (goto-char pos)
23629 (and (match-beginning 1) (throw 'exit (cons (match-string 1) m)))
23630 (and (match-beginning 2) (throw 'exit nil))
23631 ;; count $$
23632 (while (re-search-backward "\\$\\$" lim t)
23633 (setq dd-on (not dd-on)))
23634 (goto-char pos)
23635 (if dd-on (cons "$$" m))))))
23638 (defun org-try-cdlatex-tab ()
23639 "Check if it makes sense to execute `cdlatex-tab', and do it if yes.
23640 It makes sense to do so if `org-cdlatex-mode' is active and if the cursor is
23641 - inside a LaTeX fragment, or
23642 - after the first word in a line, where an abbreviation expansion could
23643 insert a LaTeX environment."
23644 (when org-cdlatex-mode
23645 (cond
23646 ((save-excursion
23647 (skip-chars-backward "a-zA-Z0-9*")
23648 (skip-chars-backward " \t")
23649 (bolp))
23650 (cdlatex-tab) t)
23651 ((org-inside-LaTeX-fragment-p)
23652 (cdlatex-tab) t)
23653 (t nil))))
23655 (defun org-cdlatex-underscore-caret (&optional arg)
23656 "Execute `cdlatex-sub-superscript' in LaTeX fragments.
23657 Revert to the normal definition outside of these fragments."
23658 (interactive "P")
23659 (if (org-inside-LaTeX-fragment-p)
23660 (call-interactively 'cdlatex-sub-superscript)
23661 (let (org-cdlatex-mode)
23662 (call-interactively (key-binding (vector last-input-event))))))
23664 (defun org-cdlatex-math-modify (&optional arg)
23665 "Execute `cdlatex-math-modify' in LaTeX fragments.
23666 Revert to the normal definition outside of these fragments."
23667 (interactive "P")
23668 (if (org-inside-LaTeX-fragment-p)
23669 (call-interactively 'cdlatex-math-modify)
23670 (let (org-cdlatex-mode)
23671 (call-interactively (key-binding (vector last-input-event))))))
23673 (defvar org-latex-fragment-image-overlays nil
23674 "List of overlays carrying the images of latex fragments.")
23675 (make-variable-buffer-local 'org-latex-fragment-image-overlays)
23677 (defun org-remove-latex-fragment-image-overlays ()
23678 "Remove all overlays with LaTeX fragment images in current buffer."
23679 (mapc 'org-delete-overlay org-latex-fragment-image-overlays)
23680 (setq org-latex-fragment-image-overlays nil))
23682 (defun org-preview-latex-fragment (&optional subtree)
23683 "Preview the LaTeX fragment at point, or all locally or globally.
23684 If the cursor is in a LaTeX fragment, create the image and overlay
23685 it over the source code. If there is no fragment at point, display
23686 all fragments in the current text, from one headline to the next. With
23687 prefix SUBTREE, display all fragments in the current subtree. With a
23688 double prefix `C-u C-u', or when the cursor is before the first headline,
23689 display all fragments in the buffer.
23690 The images can be removed again with \\[org-ctrl-c-ctrl-c]."
23691 (interactive "P")
23692 (org-remove-latex-fragment-image-overlays)
23693 (save-excursion
23694 (save-restriction
23695 (let (beg end at msg)
23696 (cond
23697 ((or (equal subtree '(16))
23698 (not (save-excursion
23699 (re-search-backward (concat "^" outline-regexp) nil t))))
23700 (setq beg (point-min) end (point-max)
23701 msg "Creating images for buffer...%s"))
23702 ((equal subtree '(4))
23703 (org-back-to-heading)
23704 (setq beg (point) end (org-end-of-subtree t)
23705 msg "Creating images for subtree...%s"))
23707 (if (setq at (org-inside-LaTeX-fragment-p))
23708 (goto-char (max (point-min) (- (cdr at) 2)))
23709 (org-back-to-heading))
23710 (setq beg (point) end (progn (outline-next-heading) (point))
23711 msg (if at "Creating image...%s"
23712 "Creating images for entry...%s"))))
23713 (message msg "")
23714 (narrow-to-region beg end)
23715 (goto-char beg)
23716 (org-format-latex
23717 (concat "ltxpng/" (file-name-sans-extension
23718 (file-name-nondirectory
23719 buffer-file-name)))
23720 default-directory 'overlays msg at 'forbuffer)
23721 (message msg "done. Use `C-c C-c' to remove images.")))))
23723 (defvar org-latex-regexps
23724 '(("begin" "^[ \t]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^\000]+?\\\\end{\\2}\\)" 1 t)
23725 ;; ("$" "\\([ (]\\|^\\)\\(\\(\\([$]\\)\\([^ \r\n,.$].*?\\(\n.*?\\)\\{0,5\\}[^ \r\n,.$]\\)\\4\\)\\)\\([ .,?;:'\")]\\|$\\)" 2 nil)
23726 ;; \000 in the following regex is needed for org-inside-LaTeX-fragment-p
23727 ("$" "\\([^$]\\)\\(\\(\\$\\([^ \r\n,;.$][^$\n\r]*?\\(\n[^$\n\r]*?\\)\\{0,2\\}[^ \r\n,.$]\\)\\$\\)\\)\\([ .,?;:'\")\000]\\|$\\)" 2 nil)
23728 ("\\(" "\\\\([^\000]*?\\\\)" 0 nil)
23729 ("\\[" "\\\\\\[[^\000]*?\\\\\\]" 0 t)
23730 ("$$" "\\$\\$[^\000]*?\\$\\$" 0 t))
23731 "Regular expressions for matching embedded LaTeX.")
23733 (defun org-format-latex (prefix &optional dir overlays msg at forbuffer)
23734 "Replace LaTeX fragments with links to an image, and produce images."
23735 (if (and overlays (fboundp 'clear-image-cache)) (clear-image-cache))
23736 (let* ((prefixnodir (file-name-nondirectory prefix))
23737 (absprefix (expand-file-name prefix dir))
23738 (todir (file-name-directory absprefix))
23739 (opt org-format-latex-options)
23740 (matchers (plist-get opt :matchers))
23741 (re-list org-latex-regexps)
23742 (cnt 0) txt link beg end re e checkdir
23743 m n block linkfile movefile ov)
23744 ;; Check if there are old images files with this prefix, and remove them
23745 (when (file-directory-p todir)
23746 (mapc 'delete-file
23747 (directory-files
23748 todir 'full
23749 (concat (regexp-quote prefixnodir) "_[0-9]+\\.png$"))))
23750 ;; Check the different regular expressions
23751 (while (setq e (pop re-list))
23752 (setq m (car e) re (nth 1 e) n (nth 2 e)
23753 block (if (nth 3 e) "\n\n" ""))
23754 (when (member m matchers)
23755 (goto-char (point-min))
23756 (while (re-search-forward re nil t)
23757 (when (or (not at) (equal (cdr at) (match-beginning n)))
23758 (setq txt (match-string n)
23759 beg (match-beginning n) end (match-end n)
23760 cnt (1+ cnt)
23761 linkfile (format "%s_%04d.png" prefix cnt)
23762 movefile (format "%s_%04d.png" absprefix cnt)
23763 link (concat block "[[file:" linkfile "]]" block))
23764 (if msg (message msg cnt))
23765 (goto-char beg)
23766 (unless checkdir ; make sure the directory exists
23767 (setq checkdir t)
23768 (or (file-directory-p todir) (make-directory todir)))
23769 (org-create-formula-image
23770 txt movefile opt forbuffer)
23771 (if overlays
23772 (progn
23773 (setq ov (org-make-overlay beg end))
23774 (if (featurep 'xemacs)
23775 (progn
23776 (org-overlay-put ov 'invisible t)
23777 (org-overlay-put
23778 ov 'end-glyph
23779 (make-glyph (vector 'png :file movefile))))
23780 (org-overlay-put
23781 ov 'display
23782 (list 'image :type 'png :file movefile :ascent 'center)))
23783 (push ov org-latex-fragment-image-overlays)
23784 (goto-char end))
23785 (delete-region beg end)
23786 (insert link))))))))
23788 ;; This function borrows from Ganesh Swami's latex2png.el
23789 (defun org-create-formula-image (string tofile options buffer)
23790 (let* ((tmpdir (if (featurep 'xemacs)
23791 (temp-directory)
23792 temporary-file-directory))
23793 (texfilebase (make-temp-name
23794 (expand-file-name "orgtex" tmpdir)))
23795 (texfile (concat texfilebase ".tex"))
23796 (dvifile (concat texfilebase ".dvi"))
23797 (pngfile (concat texfilebase ".png"))
23798 (fnh (face-attribute 'default :height nil))
23799 (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0))
23800 (dpi (number-to-string (* scale (floor (* 0.9 (if buffer fnh 140.))))))
23801 (fg (or (plist-get options (if buffer :foreground :html-foreground))
23802 "Black"))
23803 (bg (or (plist-get options (if buffer :background :html-background))
23804 "Transparent")))
23805 (if (eq fg 'default) (setq fg (org-dvipng-color :foreground)))
23806 (if (eq bg 'default) (setq bg (org-dvipng-color :background)))
23807 (with-temp-file texfile
23808 (insert org-format-latex-header
23809 "\n\\begin{document}\n" string "\n\\end{document}\n"))
23810 (let ((dir default-directory))
23811 (condition-case nil
23812 (progn
23813 (cd tmpdir)
23814 (call-process "latex" nil nil nil texfile))
23815 (error nil))
23816 (cd dir))
23817 (if (not (file-exists-p dvifile))
23818 (progn (message "Failed to create dvi file from %s" texfile) nil)
23819 (call-process "dvipng" nil nil nil
23820 "-E" "-fg" fg "-bg" bg
23821 "-D" dpi
23822 ;;"-x" scale "-y" scale
23823 "-T" "tight"
23824 "-o" pngfile
23825 dvifile)
23826 (if (not (file-exists-p pngfile))
23827 (progn (message "Failed to create png file from %s" texfile) nil)
23828 ;; Use the requested file name and clean up
23829 (copy-file pngfile tofile 'replace)
23830 (loop for e in '(".dvi" ".tex" ".aux" ".log" ".png") do
23831 (delete-file (concat texfilebase e)))
23832 pngfile))))
23834 (defun org-dvipng-color (attr)
23835 "Return an rgb color specification for dvipng."
23836 (apply 'format "rgb %s %s %s"
23837 (mapcar 'org-normalize-color
23838 (color-values (face-attribute 'default attr nil)))))
23840 (defun org-normalize-color (value)
23841 "Return string to be used as color value for an RGB component."
23842 (format "%g" (/ value 65535.0)))
23844 ;;;; Exporting
23846 ;;; Variables, constants, and parameter plists
23848 (defconst org-level-max 20)
23850 (defvar org-export-html-preamble nil
23851 "Preamble, to be inserted just after <body>. Set by publishing functions.")
23852 (defvar org-export-html-postamble nil
23853 "Preamble, to be inserted just before </body>. Set by publishing functions.")
23854 (defvar org-export-html-auto-preamble t
23855 "Should default preamble be inserted? Set by publishing functions.")
23856 (defvar org-export-html-auto-postamble t
23857 "Should default postamble be inserted? Set by publishing functions.")
23858 (defvar org-current-export-file nil) ; dynamically scoped parameter
23859 (defvar org-current-export-dir nil) ; dynamically scoped parameter
23862 (defconst org-export-plist-vars
23863 '((:language . org-export-default-language)
23864 (:customtime . org-display-custom-times)
23865 (:headline-levels . org-export-headline-levels)
23866 (:section-numbers . org-export-with-section-numbers)
23867 (:table-of-contents . org-export-with-toc)
23868 (:preserve-breaks . org-export-preserve-breaks)
23869 (:archived-trees . org-export-with-archived-trees)
23870 (:emphasize . org-export-with-emphasize)
23871 (:sub-superscript . org-export-with-sub-superscripts)
23872 (:special-strings . org-export-with-special-strings)
23873 (:footnotes . org-export-with-footnotes)
23874 (:drawers . org-export-with-drawers)
23875 (:tags . org-export-with-tags)
23876 (:TeX-macros . org-export-with-TeX-macros)
23877 (:LaTeX-fragments . org-export-with-LaTeX-fragments)
23878 (:skip-before-1st-heading . org-export-skip-text-before-1st-heading)
23879 (:fixed-width . org-export-with-fixed-width)
23880 (:timestamps . org-export-with-timestamps)
23881 (:author-info . org-export-author-info)
23882 (:time-stamp-file . org-export-time-stamp-file)
23883 (:tables . org-export-with-tables)
23884 (:table-auto-headline . org-export-highlight-first-table-line)
23885 (:style . org-export-html-style)
23886 (:agenda-style . org-agenda-export-html-style)
23887 (:convert-org-links . org-export-html-link-org-files-as-html)
23888 (:inline-images . org-export-html-inline-images)
23889 (:html-extension . org-export-html-extension)
23890 (:html-table-tag . org-export-html-table-tag)
23891 (:expand-quoted-html . org-export-html-expand)
23892 (:timestamp . org-export-html-with-timestamp)
23893 (:publishing-directory . org-export-publishing-directory)
23894 (:preamble . org-export-html-preamble)
23895 (:postamble . org-export-html-postamble)
23896 (:auto-preamble . org-export-html-auto-preamble)
23897 (:auto-postamble . org-export-html-auto-postamble)
23898 (:author . user-full-name)
23899 (:email . user-mail-address)))
23901 (defun org-default-export-plist ()
23902 "Return the property list with default settings for the export variables."
23903 (let ((l org-export-plist-vars) rtn e)
23904 (while (setq e (pop l))
23905 (setq rtn (cons (car e) (cons (symbol-value (cdr e)) rtn))))
23906 rtn))
23908 (defun org-infile-export-plist ()
23909 "Return the property list with file-local settings for export."
23910 (save-excursion
23911 (save-restriction
23912 (widen)
23913 (goto-char 0)
23914 (let ((re (org-make-options-regexp
23915 '("TITLE" "AUTHOR" "DATE" "EMAIL" "TEXT" "OPTIONS" "LANGUAGE")))
23916 p key val text options)
23917 (while (re-search-forward re nil t)
23918 (setq key (org-match-string-no-properties 1)
23919 val (org-match-string-no-properties 2))
23920 (cond
23921 ((string-equal key "TITLE") (setq p (plist-put p :title val)))
23922 ((string-equal key "AUTHOR")(setq p (plist-put p :author val)))
23923 ((string-equal key "EMAIL") (setq p (plist-put p :email val)))
23924 ((string-equal key "DATE") (setq p (plist-put p :date val)))
23925 ((string-equal key "LANGUAGE") (setq p (plist-put p :language val)))
23926 ((string-equal key "TEXT")
23927 (setq text (if text (concat text "\n" val) val)))
23928 ((string-equal key "OPTIONS") (setq options val))))
23929 (setq p (plist-put p :text text))
23930 (when options
23931 (let ((op '(("H" . :headline-levels)
23932 ("num" . :section-numbers)
23933 ("toc" . :table-of-contents)
23934 ("\\n" . :preserve-breaks)
23935 ("@" . :expand-quoted-html)
23936 (":" . :fixed-width)
23937 ("|" . :tables)
23938 ("^" . :sub-superscript)
23939 ("-" . :special-strings)
23940 ("f" . :footnotes)
23941 ("d" . :drawers)
23942 ("tags" . :tags)
23943 ("*" . :emphasize)
23944 ("TeX" . :TeX-macros)
23945 ("LaTeX" . :LaTeX-fragments)
23946 ("skip" . :skip-before-1st-heading)
23947 ("author" . :author-info)
23948 ("timestamp" . :time-stamp-file)))
23950 (while (setq o (pop op))
23951 (if (string-match (concat (regexp-quote (car o))
23952 ":\\([^ \t\n\r;,.]*\\)")
23953 options)
23954 (setq p (plist-put p (cdr o)
23955 (car (read-from-string
23956 (match-string 1 options)))))))))
23957 p))))
23959 (defun org-export-directory (type plist)
23960 (let* ((val (plist-get plist :publishing-directory))
23961 (dir (if (listp val)
23962 (or (cdr (assoc type val)) ".")
23963 val)))
23964 dir))
23966 (defun org-skip-comments (lines)
23967 "Skip lines starting with \"#\" and subtrees starting with COMMENT."
23968 (let ((re1 (concat "^\\(\\*+\\)[ \t]+" org-comment-string))
23969 (re2 "^\\(\\*+\\)[ \t\n\r]")
23970 (case-fold-search nil)
23971 rtn line level)
23972 (while (setq line (pop lines))
23973 (cond
23974 ((and (string-match re1 line)
23975 (setq level (- (match-end 1) (match-beginning 1))))
23976 ;; Beginning of a COMMENT subtree. Skip it.
23977 (while (and (setq line (pop lines))
23978 (or (not (string-match re2 line))
23979 (> (- (match-end 1) (match-beginning 1)) level))))
23980 (setq lines (cons line lines)))
23981 ((string-match "^#" line)
23982 ;; an ordinary comment line
23984 ((and org-export-table-remove-special-lines
23985 (string-match "^[ \t]*|" line)
23986 (or (string-match "^[ \t]*| *[!_^] *|" line)
23987 (and (string-match "| *<[0-9]+> *|" line)
23988 (not (string-match "| *[^ <|]" line)))))
23989 ;; a special table line that should be removed
23991 (t (setq rtn (cons line rtn)))))
23992 (nreverse rtn)))
23994 (defun org-export (&optional arg)
23995 (interactive)
23996 (let ((help "[t] insert the export option template
23997 \[v] limit export to visible part of outline tree
23999 \[a] export as ASCII
24001 \[h] export as HTML
24002 \[H] export as HTML to temporary buffer
24003 \[R] export region as HTML
24004 \[b] export as HTML and browse immediately
24005 \[x] export as XOXO
24007 \[l] export as LaTeX
24008 \[L] export as LaTeX to temporary buffer
24010 \[i] export current file as iCalendar file
24011 \[I] export all agenda files as iCalendar files
24012 \[c] export agenda files into combined iCalendar file
24014 \[F] publish current file
24015 \[P] publish current project
24016 \[X] publish... (project will be prompted for)
24017 \[A] publish all projects")
24018 (cmds
24019 '((?t . org-insert-export-options-template)
24020 (?v . org-export-visible)
24021 (?a . org-export-as-ascii)
24022 (?h . org-export-as-html)
24023 (?b . org-export-as-html-and-open)
24024 (?H . org-export-as-html-to-buffer)
24025 (?R . org-export-region-as-html)
24026 (?x . org-export-as-xoxo)
24027 (?l . org-export-as-latex)
24028 (?L . org-export-as-latex-to-buffer)
24029 (?i . org-export-icalendar-this-file)
24030 (?I . org-export-icalendar-all-agenda-files)
24031 (?c . org-export-icalendar-combine-agenda-files)
24032 (?F . org-publish-current-file)
24033 (?P . org-publish-current-project)
24034 (?X . org-publish)
24035 (?A . org-publish-all)))
24036 r1 r2 ass)
24037 (save-window-excursion
24038 (delete-other-windows)
24039 (with-output-to-temp-buffer "*Org Export/Publishing Help*"
24040 (princ help))
24041 (message "Select command: ")
24042 (setq r1 (read-char-exclusive)))
24043 (setq r2 (if (< r1 27) (+ r1 96) r1))
24044 (if (setq ass (assq r2 cmds))
24045 (call-interactively (cdr ass))
24046 (error "No command associated with key %c" r1))))
24048 (defconst org-html-entities
24049 '(("nbsp")
24050 ("iexcl")
24051 ("cent")
24052 ("pound")
24053 ("curren")
24054 ("yen")
24055 ("brvbar")
24056 ("vert" . "&#124;")
24057 ("sect")
24058 ("uml")
24059 ("copy")
24060 ("ordf")
24061 ("laquo")
24062 ("not")
24063 ("shy")
24064 ("reg")
24065 ("macr")
24066 ("deg")
24067 ("plusmn")
24068 ("sup2")
24069 ("sup3")
24070 ("acute")
24071 ("micro")
24072 ("para")
24073 ("middot")
24074 ("odot"."o")
24075 ("star"."*")
24076 ("cedil")
24077 ("sup1")
24078 ("ordm")
24079 ("raquo")
24080 ("frac14")
24081 ("frac12")
24082 ("frac34")
24083 ("iquest")
24084 ("Agrave")
24085 ("Aacute")
24086 ("Acirc")
24087 ("Atilde")
24088 ("Auml")
24089 ("Aring") ("AA"."&Aring;")
24090 ("AElig")
24091 ("Ccedil")
24092 ("Egrave")
24093 ("Eacute")
24094 ("Ecirc")
24095 ("Euml")
24096 ("Igrave")
24097 ("Iacute")
24098 ("Icirc")
24099 ("Iuml")
24100 ("ETH")
24101 ("Ntilde")
24102 ("Ograve")
24103 ("Oacute")
24104 ("Ocirc")
24105 ("Otilde")
24106 ("Ouml")
24107 ("times")
24108 ("Oslash")
24109 ("Ugrave")
24110 ("Uacute")
24111 ("Ucirc")
24112 ("Uuml")
24113 ("Yacute")
24114 ("THORN")
24115 ("szlig")
24116 ("agrave")
24117 ("aacute")
24118 ("acirc")
24119 ("atilde")
24120 ("auml")
24121 ("aring")
24122 ("aelig")
24123 ("ccedil")
24124 ("egrave")
24125 ("eacute")
24126 ("ecirc")
24127 ("euml")
24128 ("igrave")
24129 ("iacute")
24130 ("icirc")
24131 ("iuml")
24132 ("eth")
24133 ("ntilde")
24134 ("ograve")
24135 ("oacute")
24136 ("ocirc")
24137 ("otilde")
24138 ("ouml")
24139 ("divide")
24140 ("oslash")
24141 ("ugrave")
24142 ("uacute")
24143 ("ucirc")
24144 ("uuml")
24145 ("yacute")
24146 ("thorn")
24147 ("yuml")
24148 ("fnof")
24149 ("Alpha")
24150 ("Beta")
24151 ("Gamma")
24152 ("Delta")
24153 ("Epsilon")
24154 ("Zeta")
24155 ("Eta")
24156 ("Theta")
24157 ("Iota")
24158 ("Kappa")
24159 ("Lambda")
24160 ("Mu")
24161 ("Nu")
24162 ("Xi")
24163 ("Omicron")
24164 ("Pi")
24165 ("Rho")
24166 ("Sigma")
24167 ("Tau")
24168 ("Upsilon")
24169 ("Phi")
24170 ("Chi")
24171 ("Psi")
24172 ("Omega")
24173 ("alpha")
24174 ("beta")
24175 ("gamma")
24176 ("delta")
24177 ("epsilon")
24178 ("varepsilon"."&epsilon;")
24179 ("zeta")
24180 ("eta")
24181 ("theta")
24182 ("iota")
24183 ("kappa")
24184 ("lambda")
24185 ("mu")
24186 ("nu")
24187 ("xi")
24188 ("omicron")
24189 ("pi")
24190 ("rho")
24191 ("sigmaf") ("varsigma"."&sigmaf;")
24192 ("sigma")
24193 ("tau")
24194 ("upsilon")
24195 ("phi")
24196 ("chi")
24197 ("psi")
24198 ("omega")
24199 ("thetasym") ("vartheta"."&thetasym;")
24200 ("upsih")
24201 ("piv")
24202 ("bull") ("bullet"."&bull;")
24203 ("hellip") ("dots"."&hellip;")
24204 ("prime")
24205 ("Prime")
24206 ("oline")
24207 ("frasl")
24208 ("weierp")
24209 ("image")
24210 ("real")
24211 ("trade")
24212 ("alefsym")
24213 ("larr") ("leftarrow"."&larr;") ("gets"."&larr;")
24214 ("uarr") ("uparrow"."&uarr;")
24215 ("rarr") ("to"."&rarr;") ("rightarrow"."&rarr;")
24216 ("darr")("downarrow"."&darr;")
24217 ("harr") ("leftrightarrow"."&harr;")
24218 ("crarr") ("hookleftarrow"."&crarr;") ; has round hook, not quite CR
24219 ("lArr") ("Leftarrow"."&lArr;")
24220 ("uArr") ("Uparrow"."&uArr;")
24221 ("rArr") ("Rightarrow"."&rArr;")
24222 ("dArr") ("Downarrow"."&dArr;")
24223 ("hArr") ("Leftrightarrow"."&hArr;")
24224 ("forall")
24225 ("part") ("partial"."&part;")
24226 ("exist") ("exists"."&exist;")
24227 ("empty") ("emptyset"."&empty;")
24228 ("nabla")
24229 ("isin") ("in"."&isin;")
24230 ("notin")
24231 ("ni")
24232 ("prod")
24233 ("sum")
24234 ("minus")
24235 ("lowast") ("ast"."&lowast;")
24236 ("radic")
24237 ("prop") ("proptp"."&prop;")
24238 ("infin") ("infty"."&infin;")
24239 ("ang") ("angle"."&ang;")
24240 ("and") ("wedge"."&and;")
24241 ("or") ("vee"."&or;")
24242 ("cap")
24243 ("cup")
24244 ("int")
24245 ("there4")
24246 ("sim")
24247 ("cong") ("simeq"."&cong;")
24248 ("asymp")("approx"."&asymp;")
24249 ("ne") ("neq"."&ne;")
24250 ("equiv")
24251 ("le")
24252 ("ge")
24253 ("sub") ("subset"."&sub;")
24254 ("sup") ("supset"."&sup;")
24255 ("nsub")
24256 ("sube")
24257 ("supe")
24258 ("oplus")
24259 ("otimes")
24260 ("perp")
24261 ("sdot") ("cdot"."&sdot;")
24262 ("lceil")
24263 ("rceil")
24264 ("lfloor")
24265 ("rfloor")
24266 ("lang")
24267 ("rang")
24268 ("loz") ("Diamond"."&loz;")
24269 ("spades") ("spadesuit"."&spades;")
24270 ("clubs") ("clubsuit"."&clubs;")
24271 ("hearts") ("diamondsuit"."&hearts;")
24272 ("diams") ("diamondsuit"."&diams;")
24273 ("smile"."&#9786;") ("blacksmile"."&#9787;") ("sad"."&#9785;")
24274 ("quot")
24275 ("amp")
24276 ("lt")
24277 ("gt")
24278 ("OElig")
24279 ("oelig")
24280 ("Scaron")
24281 ("scaron")
24282 ("Yuml")
24283 ("circ")
24284 ("tilde")
24285 ("ensp")
24286 ("emsp")
24287 ("thinsp")
24288 ("zwnj")
24289 ("zwj")
24290 ("lrm")
24291 ("rlm")
24292 ("ndash")
24293 ("mdash")
24294 ("lsquo")
24295 ("rsquo")
24296 ("sbquo")
24297 ("ldquo")
24298 ("rdquo")
24299 ("bdquo")
24300 ("dagger")
24301 ("Dagger")
24302 ("permil")
24303 ("lsaquo")
24304 ("rsaquo")
24305 ("euro")
24307 ("arccos"."arccos")
24308 ("arcsin"."arcsin")
24309 ("arctan"."arctan")
24310 ("arg"."arg")
24311 ("cos"."cos")
24312 ("cosh"."cosh")
24313 ("cot"."cot")
24314 ("coth"."coth")
24315 ("csc"."csc")
24316 ("deg"."deg")
24317 ("det"."det")
24318 ("dim"."dim")
24319 ("exp"."exp")
24320 ("gcd"."gcd")
24321 ("hom"."hom")
24322 ("inf"."inf")
24323 ("ker"."ker")
24324 ("lg"."lg")
24325 ("lim"."lim")
24326 ("liminf"."liminf")
24327 ("limsup"."limsup")
24328 ("ln"."ln")
24329 ("log"."log")
24330 ("max"."max")
24331 ("min"."min")
24332 ("Pr"."Pr")
24333 ("sec"."sec")
24334 ("sin"."sin")
24335 ("sinh"."sinh")
24336 ("sup"."sup")
24337 ("tan"."tan")
24338 ("tanh"."tanh")
24340 "Entities for TeX->HTML translation.
24341 Entries can be like (\"ent\"), in which case \"\\ent\" will be translated to
24342 \"&ent;\". An entry can also be a dotted pair like (\"ent\".\"&other;\").
24343 In that case, \"\\ent\" will be translated to \"&other;\".
24344 The list contains HTML entities for Latin-1, Greek and other symbols.
24345 It is supplemented by a number of commonly used TeX macros with appropriate
24346 translations. There is currently no way for users to extend this.")
24348 ;;; General functions for all backends
24350 (defun org-cleaned-string-for-export (string &rest parameters)
24351 "Cleanup a buffer STRING so that links can be created safely."
24352 (interactive)
24353 (let* ((re-radio (and org-target-link-regexp
24354 (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)")))
24355 (re-plain-link (concat "\\([^[<]\\)" org-plain-link-re))
24356 (re-angle-link (concat "\\([^[]\\)" org-angle-link-re))
24357 (re-archive (concat ":" org-archive-tag ":"))
24358 (re-quote (concat "^\\*+[ \t]+" org-quote-string "\\>"))
24359 (re-commented (concat "^\\*+[ \t]+" org-comment-string "\\>"))
24360 (htmlp (plist-get parameters :for-html))
24361 (asciip (plist-get parameters :for-ascii))
24362 (latexp (plist-get parameters :for-LaTeX))
24363 (commentsp (plist-get parameters :comments))
24364 (archived-trees (plist-get parameters :archived-trees))
24365 (inhibit-read-only t)
24366 (drawers org-drawers)
24367 (exp-drawers (plist-get parameters :drawers))
24368 (outline-regexp "\\*+ ")
24369 a b xx
24370 rtn p)
24371 (with-current-buffer (get-buffer-create " org-mode-tmp")
24372 (erase-buffer)
24373 (insert string)
24374 ;; Remove license-to-kill stuff
24375 (while (setq p (text-property-any (point-min) (point-max)
24376 :org-license-to-kill t))
24377 (delete-region p (next-single-property-change p :org-license-to-kill)))
24379 (let ((org-inhibit-startup t)) (org-mode))
24380 (untabify (point-min) (point-max))
24382 ;; Get rid of drawers
24383 (unless (eq t exp-drawers)
24384 (goto-char (point-min))
24385 (let ((re (concat "^[ \t]*:\\("
24386 (mapconcat
24387 'identity
24388 (org-delete-all exp-drawers
24389 (copy-sequence drawers))
24390 "\\|")
24391 "\\):[ \t]*\n\\([^@]*?\n\\)?[ \t]*:END:[ \t]*\n")))
24392 (while (re-search-forward re nil t)
24393 (replace-match ""))))
24395 ;; Get the correct stuff before the first headline
24396 (when (plist-get parameters :skip-before-1st-heading)
24397 (goto-char (point-min))
24398 (when (re-search-forward "^\\*+[ \t]" nil t)
24399 (delete-region (point-min) (match-beginning 0))
24400 (goto-char (point-min))
24401 (insert "\n")))
24402 (when (plist-get parameters :add-text)
24403 (goto-char (point-min))
24404 (insert (plist-get parameters :add-text) "\n"))
24406 ;; Get rid of archived trees
24407 (when (not (eq archived-trees t))
24408 (goto-char (point-min))
24409 (while (re-search-forward re-archive nil t)
24410 (if (not (org-on-heading-p t))
24411 (org-end-of-subtree t)
24412 (beginning-of-line 1)
24413 (setq a (if archived-trees
24414 (1+ (point-at-eol)) (point))
24415 b (org-end-of-subtree t))
24416 (if (> b a) (delete-region a b)))))
24418 ;; Find targets in comments and move them out of comments,
24419 ;; but mark them as targets that should be invisible
24420 (goto-char (point-min))
24421 (while (re-search-forward "^#.*?\\(<<<?[^>\r\n]+>>>?\\).*" nil t)
24422 (replace-match "\\1(INVISIBLE)"))
24424 ;; Protect backend specific stuff, throw away the others.
24425 (let ((formatters
24426 `((,htmlp "HTML" "BEGIN_HTML" "END_HTML")
24427 (,asciip "ASCII" "BEGIN_ASCII" "END_ASCII")
24428 (,latexp "LaTeX" "BEGIN_LaTeX" "END_LaTeX")))
24429 fmt)
24430 (goto-char (point-min))
24431 (while (re-search-forward "^#\\+BEGIN_EXAMPLE[ \t]*\n" nil t)
24432 (goto-char (match-end 0))
24433 (while (not (looking-at "#\\+END_EXAMPLE"))
24434 (insert ": ")
24435 (beginning-of-line 2)))
24436 (goto-char (point-min))
24437 (while (re-search-forward "^[ \t]*:.*\\(\n[ \t]*:.*\\)*" nil t)
24438 (add-text-properties (match-beginning 0) (match-end 0)
24439 '(org-protected t)))
24440 (while formatters
24441 (setq fmt (pop formatters))
24442 (when (car fmt)
24443 (goto-char (point-min))
24444 (while (re-search-forward (concat "^#\\+" (cadr fmt)
24445 ":[ \t]*\\(.*\\)") nil t)
24446 (replace-match "\\1" t)
24447 (add-text-properties
24448 (point-at-bol) (min (1+ (point-at-eol)) (point-max))
24449 '(org-protected t))))
24450 (goto-char (point-min))
24451 (while (re-search-forward
24452 (concat "^#\\+"
24453 (caddr fmt) "\\>.*\\(\\(\n.*\\)*?\n\\)#\\+"
24454 (cadddr fmt) "\\>.*\n?") nil t)
24455 (if (car fmt)
24456 (add-text-properties (match-beginning 1) (1+ (match-end 1))
24457 '(org-protected t))
24458 (delete-region (match-beginning 0) (match-end 0))))))
24460 ;; Protect quoted subtrees
24461 (goto-char (point-min))
24462 (while (re-search-forward re-quote nil t)
24463 (goto-char (match-beginning 0))
24464 (end-of-line 1)
24465 (add-text-properties (point) (org-end-of-subtree t)
24466 '(org-protected t)))
24468 ;; Protect verbatim elements
24469 (goto-char (point-min))
24470 (while (re-search-forward org-verbatim-re nil t)
24471 (add-text-properties (match-beginning 4) (match-end 4)
24472 '(org-protected t))
24473 (goto-char (1+ (match-end 4))))
24475 ;; Remove subtrees that are commented
24476 (goto-char (point-min))
24477 (while (re-search-forward re-commented nil t)
24478 (goto-char (match-beginning 0))
24479 (delete-region (point) (org-end-of-subtree t)))
24481 ;; Remove special table lines
24482 (when org-export-table-remove-special-lines
24483 (goto-char (point-min))
24484 (while (re-search-forward "^[ \t]*|" nil t)
24485 (beginning-of-line 1)
24486 (if (or (looking-at "[ \t]*| *[!_^] *|")
24487 (and (looking-at ".*?| *<[0-9]+> *|")
24488 (not (looking-at ".*?| *[^ <|]"))))
24489 (delete-region (max (point-min) (1- (point-at-bol)))
24490 (point-at-eol))
24491 (end-of-line 1))))
24493 ;; Specific LaTeX stuff
24494 (when latexp
24495 (require 'org-export-latex nil)
24496 (org-export-latex-cleaned-string))
24498 (when asciip
24499 (org-export-ascii-clean-string))
24501 ;; Specific HTML stuff
24502 (when htmlp
24503 ;; Convert LaTeX fragments to images
24504 (when (plist-get parameters :LaTeX-fragments)
24505 (org-format-latex
24506 (concat "ltxpng/" (file-name-sans-extension
24507 (file-name-nondirectory
24508 org-current-export-file)))
24509 org-current-export-dir nil "Creating LaTeX image %s"))
24510 (message "Exporting..."))
24512 ;; Remove or replace comments
24513 (goto-char (point-min))
24514 (while (re-search-forward "^#\\(.*\n?\\)" nil t)
24515 (if commentsp
24516 (progn (add-text-properties
24517 (match-beginning 0) (match-end 0) '(org-protected t))
24518 (replace-match (format commentsp (match-string 1)) t t))
24519 (replace-match "")))
24521 ;; Find matches for radio targets and turn them into internal links
24522 (goto-char (point-min))
24523 (when re-radio
24524 (while (re-search-forward re-radio nil t)
24525 (org-if-unprotected
24526 (replace-match "\\1[[\\2]]"))))
24528 ;; Find all links that contain a newline and put them into a single line
24529 (goto-char (point-min))
24530 (while (re-search-forward "\\(\\(\\[\\|\\]\\)\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\(\\[\\|\\]\\)\\)" nil t)
24531 (org-if-unprotected
24532 (replace-match "\\1 \\3")
24533 (goto-char (match-beginning 0))))
24536 ;; Normalize links: Convert angle and plain links into bracket links
24537 ;; Expand link abbreviations
24538 (goto-char (point-min))
24539 (while (re-search-forward re-plain-link nil t)
24540 (goto-char (1- (match-end 0)))
24541 (org-if-unprotected
24542 (let* ((s (concat (match-string 1) "[[" (match-string 2)
24543 ":" (match-string 3) "]]")))
24544 ;; added 'org-link face to links
24545 (put-text-property 0 (length s) 'face 'org-link s)
24546 (replace-match s t t))))
24547 (goto-char (point-min))
24548 (while (re-search-forward re-angle-link nil t)
24549 (goto-char (1- (match-end 0)))
24550 (org-if-unprotected
24551 (let* ((s (concat (match-string 1) "[[" (match-string 2)
24552 ":" (match-string 3) "]]")))
24553 (put-text-property 0 (length s) 'face 'org-link s)
24554 (replace-match s t t))))
24555 (goto-char (point-min))
24556 (while (re-search-forward org-bracket-link-regexp nil t)
24557 (org-if-unprotected
24558 (let* ((s (concat "[[" (setq xx (save-match-data
24559 (org-link-expand-abbrev (match-string 1))))
24561 (if (match-end 3)
24562 (match-string 2)
24563 (concat "[" xx "]"))
24564 "]")))
24565 (put-text-property 0 (length s) 'face 'org-link s)
24566 (replace-match s t t))))
24568 ;; Find multiline emphasis and put them into single line
24569 (when (plist-get parameters :emph-multiline)
24570 (goto-char (point-min))
24571 (while (re-search-forward org-emph-re nil t)
24572 (if (not (= (char-after (match-beginning 3))
24573 (char-after (match-beginning 4))))
24574 (org-if-unprotected
24575 (subst-char-in-region (match-beginning 0) (match-end 0)
24576 ?\n ?\ t)
24577 (goto-char (1- (match-end 0))))
24578 (goto-char (1+ (match-beginning 0))))))
24580 (setq rtn (buffer-string)))
24581 (kill-buffer " org-mode-tmp")
24582 rtn))
24584 (defun org-export-grab-title-from-buffer ()
24585 "Get a title for the current document, from looking at the buffer."
24586 (let ((inhibit-read-only t))
24587 (save-excursion
24588 (goto-char (point-min))
24589 (let ((end (save-excursion (outline-next-heading) (point))))
24590 (when (re-search-forward "^[ \t]*[^|# \t\r\n].*\n" end t)
24591 ;; Mark the line so that it will not be exported as normal text.
24592 (org-unmodified
24593 (add-text-properties (match-beginning 0) (match-end 0)
24594 (list :org-license-to-kill t)))
24595 ;; Return the title string
24596 (org-trim (match-string 0)))))))
24598 (defun org-export-get-title-from-subtree ()
24599 "Return subtree title and exclude it from export."
24600 (let (title (m (mark)))
24601 (save-excursion
24602 (goto-char (region-beginning))
24603 (when (and (org-at-heading-p)
24604 (>= (org-end-of-subtree t t) (region-end)))
24605 ;; This is a subtree, we take the title from the first heading
24606 (goto-char (region-beginning))
24607 (looking-at org-todo-line-regexp)
24608 (setq title (match-string 3))
24609 (org-unmodified
24610 (add-text-properties (point) (1+ (point-at-eol))
24611 (list :org-license-to-kill t)))))
24612 title))
24614 (defun org-solidify-link-text (s &optional alist)
24615 "Take link text and make a safe target out of it."
24616 (save-match-data
24617 (let* ((rtn
24618 (mapconcat
24619 'identity
24620 (org-split-string s "[ \t\r\n]+") "--"))
24621 (a (assoc rtn alist)))
24622 (or (cdr a) rtn))))
24624 (defun org-get-min-level (lines)
24625 "Get the minimum level in LINES."
24626 (let ((re "^\\(\\*+\\) ") l min)
24627 (catch 'exit
24628 (while (setq l (pop lines))
24629 (if (string-match re l)
24630 (throw 'exit (org-tr-level (length (match-string 1 l))))))
24631 1)))
24633 ;; Variable holding the vector with section numbers
24634 (defvar org-section-numbers (make-vector org-level-max 0))
24636 (defun org-init-section-numbers ()
24637 "Initialize the vector for the section numbers."
24638 (let* ((level -1)
24639 (numbers (nreverse (org-split-string "" "\\.")))
24640 (depth (1- (length org-section-numbers)))
24641 (i depth) number-string)
24642 (while (>= i 0)
24643 (if (> i level)
24644 (aset org-section-numbers i 0)
24645 (setq number-string (or (car numbers) "0"))
24646 (if (string-match "\\`[A-Z]\\'" number-string)
24647 (aset org-section-numbers i
24648 (- (string-to-char number-string) ?A -1))
24649 (aset org-section-numbers i (string-to-number number-string)))
24650 (pop numbers))
24651 (setq i (1- i)))))
24653 (defun org-section-number (&optional level)
24654 "Return a string with the current section number.
24655 When LEVEL is non-nil, increase section numbers on that level."
24656 (let* ((depth (1- (length org-section-numbers))) idx n (string ""))
24657 (when level
24658 (when (> level -1)
24659 (aset org-section-numbers
24660 level (1+ (aref org-section-numbers level))))
24661 (setq idx (1+ level))
24662 (while (<= idx depth)
24663 (if (not (= idx 1))
24664 (aset org-section-numbers idx 0))
24665 (setq idx (1+ idx))))
24666 (setq idx 0)
24667 (while (<= idx depth)
24668 (setq n (aref org-section-numbers idx))
24669 (setq string (concat string (if (not (string= string "")) "." "")
24670 (int-to-string n)))
24671 (setq idx (1+ idx)))
24672 (save-match-data
24673 (if (string-match "\\`\\([@0]\\.\\)+" string)
24674 (setq string (replace-match "" t nil string)))
24675 (if (string-match "\\(\\.0\\)+\\'" string)
24676 (setq string (replace-match "" t nil string))))
24677 string))
24679 ;;; ASCII export
24681 (defvar org-last-level nil) ; dynamically scoped variable
24682 (defvar org-min-level nil) ; dynamically scoped variable
24683 (defvar org-levels-open nil) ; dynamically scoped parameter
24684 (defvar org-ascii-current-indentation nil) ; For communication
24686 (defun org-export-as-ascii (arg)
24687 "Export the outline as a pretty ASCII file.
24688 If there is an active region, export only the region.
24689 The prefix ARG specifies how many levels of the outline should become
24690 underlined headlines. The default is 3."
24691 (interactive "P")
24692 (setq-default org-todo-line-regexp org-todo-line-regexp)
24693 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
24694 (org-infile-export-plist)))
24695 (region-p (org-region-active-p))
24696 (subtree-p
24697 (when region-p
24698 (save-excursion
24699 (goto-char (region-beginning))
24700 (and (org-at-heading-p)
24701 (>= (org-end-of-subtree t t) (region-end))))))
24702 (custom-times org-display-custom-times)
24703 (org-ascii-current-indentation '(0 . 0))
24704 (level 0) line txt
24705 (umax nil)
24706 (umax-toc nil)
24707 (case-fold-search nil)
24708 (filename (concat (file-name-as-directory
24709 (org-export-directory :ascii opt-plist))
24710 (file-name-sans-extension
24711 (or (and subtree-p
24712 (org-entry-get (region-beginning)
24713 "EXPORT_FILE_NAME" t))
24714 (file-name-nondirectory buffer-file-name)))
24715 ".txt"))
24716 (filename (if (equal (file-truename filename)
24717 (file-truename buffer-file-name))
24718 (concat filename ".txt")
24719 filename))
24720 (buffer (find-file-noselect filename))
24721 (org-levels-open (make-vector org-level-max nil))
24722 (odd org-odd-levels-only)
24723 (date (plist-get opt-plist :date))
24724 (author (plist-get opt-plist :author))
24725 (title (or (and subtree-p (org-export-get-title-from-subtree))
24726 (plist-get opt-plist :title)
24727 (and (not
24728 (plist-get opt-plist :skip-before-1st-heading))
24729 (org-export-grab-title-from-buffer))
24730 (file-name-sans-extension
24731 (file-name-nondirectory buffer-file-name))))
24732 (email (plist-get opt-plist :email))
24733 (language (plist-get opt-plist :language))
24734 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
24735 ; (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
24736 (todo nil)
24737 (lang-words nil)
24738 (region
24739 (buffer-substring
24740 (if (org-region-active-p) (region-beginning) (point-min))
24741 (if (org-region-active-p) (region-end) (point-max))))
24742 (lines (org-split-string
24743 (org-cleaned-string-for-export
24744 region
24745 :for-ascii t
24746 :skip-before-1st-heading
24747 (plist-get opt-plist :skip-before-1st-heading)
24748 :drawers (plist-get opt-plist :drawers)
24749 :verbatim-multiline t
24750 :archived-trees
24751 (plist-get opt-plist :archived-trees)
24752 :add-text (plist-get opt-plist :text))
24753 "\n"))
24754 thetoc have-headings first-heading-pos
24755 table-open table-buffer)
24757 (let ((inhibit-read-only t))
24758 (org-unmodified
24759 (remove-text-properties (point-min) (point-max)
24760 '(:org-license-to-kill t))))
24762 (setq org-min-level (org-get-min-level lines))
24763 (setq org-last-level org-min-level)
24764 (org-init-section-numbers)
24766 (find-file-noselect filename)
24768 (setq lang-words (or (assoc language org-export-language-setup)
24769 (assoc "en" org-export-language-setup)))
24770 (switch-to-buffer-other-window buffer)
24771 (erase-buffer)
24772 (fundamental-mode)
24773 ;; create local variables for all options, to make sure all called
24774 ;; functions get the correct information
24775 (mapc (lambda (x)
24776 (set (make-local-variable (cdr x))
24777 (plist-get opt-plist (car x))))
24778 org-export-plist-vars)
24779 (org-set-local 'org-odd-levels-only odd)
24780 (setq umax (if arg (prefix-numeric-value arg)
24781 org-export-headline-levels))
24782 (setq umax-toc (if (integerp org-export-with-toc)
24783 (min org-export-with-toc umax)
24784 umax))
24786 ;; File header
24787 (if title (org-insert-centered title ?=))
24788 (insert "\n")
24789 (if (and (or author email)
24790 org-export-author-info)
24791 (insert (concat (nth 1 lang-words) ": " (or author "")
24792 (if email (concat " <" email ">") "")
24793 "\n")))
24795 (cond
24796 ((and date (string-match "%" date))
24797 (setq date (format-time-string date)))
24798 (date)
24799 (t (setq date (format-time-string "%Y/%m/%d %X"))))
24801 (if (and date org-export-time-stamp-file)
24802 (insert (concat (nth 2 lang-words) ": " date"\n")))
24804 (insert "\n\n")
24806 (if org-export-with-toc
24807 (progn
24808 (push (concat (nth 3 lang-words) "\n") thetoc)
24809 (push (concat (make-string (length (nth 3 lang-words)) ?=) "\n") thetoc)
24810 (mapc '(lambda (line)
24811 (if (string-match org-todo-line-regexp
24812 line)
24813 ;; This is a headline
24814 (progn
24815 (setq have-headings t)
24816 (setq level (- (match-end 1) (match-beginning 1))
24817 level (org-tr-level level)
24818 txt (match-string 3 line)
24819 todo
24820 (or (and org-export-mark-todo-in-toc
24821 (match-beginning 2)
24822 (not (member (match-string 2 line)
24823 org-done-keywords)))
24824 ; TODO, not DONE
24825 (and org-export-mark-todo-in-toc
24826 (= level umax-toc)
24827 (org-search-todo-below
24828 line lines level))))
24829 (setq txt (org-html-expand-for-ascii txt))
24831 (while (string-match org-bracket-link-regexp txt)
24832 (setq txt
24833 (replace-match
24834 (match-string (if (match-end 2) 3 1) txt)
24835 t t txt)))
24837 (if (and (memq org-export-with-tags '(not-in-toc nil))
24838 (string-match
24839 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
24840 txt))
24841 (setq txt (replace-match "" t t txt)))
24842 (if (string-match quote-re0 txt)
24843 (setq txt (replace-match "" t t txt)))
24845 (if org-export-with-section-numbers
24846 (setq txt (concat (org-section-number level)
24847 " " txt)))
24848 (if (<= level umax-toc)
24849 (progn
24850 (push
24851 (concat
24852 (make-string
24853 (* (max 0 (- level org-min-level)) 4) ?\ )
24854 (format (if todo "%s (*)\n" "%s\n") txt))
24855 thetoc)
24856 (setq org-last-level level))
24857 ))))
24858 lines)
24859 (setq thetoc (if have-headings (nreverse thetoc) nil))))
24861 (org-init-section-numbers)
24862 (while (setq line (pop lines))
24863 ;; Remove the quoted HTML tags.
24864 (setq line (org-html-expand-for-ascii line))
24865 ;; Remove targets
24866 (while (string-match "<<<?[^<>]*>>>?[ \t]*\n?" line)
24867 (setq line (replace-match "" t t line)))
24868 ;; Replace internal links
24869 (while (string-match org-bracket-link-regexp line)
24870 (setq line (replace-match
24871 (if (match-end 3) "[\\3]" "[\\1]")
24872 t nil line)))
24873 (when custom-times
24874 (setq line (org-translate-time line)))
24875 (cond
24876 ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line)
24877 ;; a Headline
24878 (setq first-heading-pos (or first-heading-pos (point)))
24879 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
24880 txt (match-string 2 line))
24881 (org-ascii-level-start level txt umax lines))
24883 ((and org-export-with-tables
24884 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
24885 (if (not table-open)
24886 ;; New table starts
24887 (setq table-open t table-buffer nil))
24888 ;; Accumulate lines
24889 (setq table-buffer (cons line table-buffer))
24890 (when (or (not lines)
24891 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
24892 (car lines))))
24893 (setq table-open nil
24894 table-buffer (nreverse table-buffer))
24895 (insert (mapconcat
24896 (lambda (x)
24897 (org-fix-indentation x org-ascii-current-indentation))
24898 (org-format-table-ascii table-buffer)
24899 "\n") "\n")))
24901 (setq line (org-fix-indentation line org-ascii-current-indentation))
24902 (if (and org-export-with-fixed-width
24903 (string-match "^\\([ \t]*\\)\\(:\\)" line))
24904 (setq line (replace-match "\\1" nil nil line)))
24905 (insert line "\n"))))
24907 (normal-mode)
24909 ;; insert the table of contents
24910 (when thetoc
24911 (goto-char (point-min))
24912 (if (re-search-forward "^[ \t]*\\[TABLE-OF-CONTENTS\\][ \t]*$" nil t)
24913 (progn
24914 (goto-char (match-beginning 0))
24915 (replace-match ""))
24916 (goto-char first-heading-pos))
24917 (mapc 'insert thetoc)
24918 (or (looking-at "[ \t]*\n[ \t]*\n")
24919 (insert "\n\n")))
24921 ;; Convert whitespace place holders
24922 (goto-char (point-min))
24923 (let (beg end)
24924 (while (setq beg (next-single-property-change (point) 'org-whitespace))
24925 (setq end (next-single-property-change beg 'org-whitespace))
24926 (goto-char beg)
24927 (delete-region beg end)
24928 (insert (make-string (- end beg) ?\ ))))
24930 (save-buffer)
24931 ;; remove display and invisible chars
24932 (let (beg end)
24933 (goto-char (point-min))
24934 (while (setq beg (next-single-property-change (point) 'display))
24935 (setq end (next-single-property-change beg 'display))
24936 (delete-region beg end)
24937 (goto-char beg)
24938 (insert "=>"))
24939 (goto-char (point-min))
24940 (while (setq beg (next-single-property-change (point) 'org-cwidth))
24941 (setq end (next-single-property-change beg 'org-cwidth))
24942 (delete-region beg end)
24943 (goto-char beg)))
24944 (goto-char (point-min))))
24946 (defun org-export-ascii-clean-string ()
24947 "Do extra work for ASCII export"
24948 (goto-char (point-min))
24949 (while (re-search-forward org-verbatim-re nil t)
24950 (goto-char (match-end 2))
24951 (backward-delete-char 1) (insert "'")
24952 (goto-char (match-beginning 2))
24953 (delete-char 1) (insert "`")
24954 (goto-char (match-end 2))))
24956 (defun org-search-todo-below (line lines level)
24957 "Search the subtree below LINE for any TODO entries."
24958 (let ((rest (cdr (memq line lines)))
24959 (re org-todo-line-regexp)
24960 line lv todo)
24961 (catch 'exit
24962 (while (setq line (pop rest))
24963 (if (string-match re line)
24964 (progn
24965 (setq lv (- (match-end 1) (match-beginning 1))
24966 todo (and (match-beginning 2)
24967 (not (member (match-string 2 line)
24968 org-done-keywords))))
24969 ; TODO, not DONE
24970 (if (<= lv level) (throw 'exit nil))
24971 (if todo (throw 'exit t))))))))
24973 (defun org-html-expand-for-ascii (line)
24974 "Handle quoted HTML for ASCII export."
24975 (if org-export-html-expand
24976 (while (string-match "@<[^<>\n]*>" line)
24977 ;; We just remove the tags for now.
24978 (setq line (replace-match "" nil nil line))))
24979 line)
24981 (defun org-insert-centered (s &optional underline)
24982 "Insert the string S centered and underline it with character UNDERLINE."
24983 (let ((ind (max (/ (- 80 (string-width s)) 2) 0)))
24984 (insert (make-string ind ?\ ) s "\n")
24985 (if underline
24986 (insert (make-string ind ?\ )
24987 (make-string (string-width s) underline)
24988 "\n"))))
24990 (defun org-ascii-level-start (level title umax &optional lines)
24991 "Insert a new level in ASCII export."
24992 (let (char (n (- level umax 1)) (ind 0))
24993 (if (> level umax)
24994 (progn
24995 (insert (make-string (* 2 n) ?\ )
24996 (char-to-string (nth (% n (length org-export-ascii-bullets))
24997 org-export-ascii-bullets))
24998 " " title "\n")
24999 ;; find the indentation of the next non-empty line
25000 (catch 'stop
25001 (while lines
25002 (if (string-match "^\\* " (car lines)) (throw 'stop nil))
25003 (if (string-match "^\\([ \t]*\\)\\S-" (car lines))
25004 (throw 'stop (setq ind (org-get-indentation (car lines)))))
25005 (pop lines)))
25006 (setq org-ascii-current-indentation (cons (* 2 (1+ n)) ind)))
25007 (if (or (not (equal (char-before) ?\n))
25008 (not (equal (char-before (1- (point))) ?\n)))
25009 (insert "\n"))
25010 (setq char (nth (- umax level) (reverse org-export-ascii-underline)))
25011 (unless org-export-with-tags
25012 (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
25013 (setq title (replace-match "" t t title))))
25014 (if org-export-with-section-numbers
25015 (setq title (concat (org-section-number level) " " title)))
25016 (insert title "\n" (make-string (string-width title) char) "\n")
25017 (setq org-ascii-current-indentation '(0 . 0)))))
25019 (defun org-export-visible (type arg)
25020 "Create a copy of the visible part of the current buffer, and export it.
25021 The copy is created in a temporary buffer and removed after use.
25022 TYPE is the final key (as a string) that also select the export command in
25023 the `C-c C-e' export dispatcher.
25024 As a special case, if the you type SPC at the prompt, the temporary
25025 org-mode file will not be removed but presented to you so that you can
25026 continue to use it. The prefix arg ARG is passed through to the exporting
25027 command."
25028 (interactive
25029 (list (progn
25030 (message "Export visible: [a]SCII [h]tml [b]rowse HTML [H/R]uffer with HTML [x]OXO [ ]keep buffer")
25031 (read-char-exclusive))
25032 current-prefix-arg))
25033 (if (not (member type '(?a ?\C-a ?b ?\C-b ?h ?x ?\ )))
25034 (error "Invalid export key"))
25035 (let* ((binding (cdr (assoc type
25036 '((?a . org-export-as-ascii)
25037 (?\C-a . org-export-as-ascii)
25038 (?b . org-export-as-html-and-open)
25039 (?\C-b . org-export-as-html-and-open)
25040 (?h . org-export-as-html)
25041 (?H . org-export-as-html-to-buffer)
25042 (?R . org-export-region-as-html)
25043 (?x . org-export-as-xoxo)))))
25044 (keepp (equal type ?\ ))
25045 (file buffer-file-name)
25046 (buffer (get-buffer-create "*Org Export Visible*"))
25047 s e)
25048 ;; Need to hack the drawers here.
25049 (save-excursion
25050 (goto-char (point-min))
25051 (while (re-search-forward org-drawer-regexp nil t)
25052 (goto-char (match-beginning 1))
25053 (or (org-invisible-p) (org-flag-drawer nil))))
25054 (with-current-buffer buffer (erase-buffer))
25055 (save-excursion
25056 (setq s (goto-char (point-min)))
25057 (while (not (= (point) (point-max)))
25058 (goto-char (org-find-invisible))
25059 (append-to-buffer buffer s (point))
25060 (setq s (goto-char (org-find-visible))))
25061 (org-cycle-hide-drawers 'all)
25062 (goto-char (point-min))
25063 (unless keepp
25064 ;; Copy all comment lines to the end, to make sure #+ settings are
25065 ;; still available for the second export step. Kind of a hack, but
25066 ;; does do the trick.
25067 (if (looking-at "#[^\r\n]*")
25068 (append-to-buffer buffer (match-beginning 0) (1+ (match-end 0))))
25069 (while (re-search-forward "[\n\r]#[^\n\r]*" nil t)
25070 (append-to-buffer buffer (1+ (match-beginning 0))
25071 (min (point-max) (1+ (match-end 0))))))
25072 (set-buffer buffer)
25073 (let ((buffer-file-name file)
25074 (org-inhibit-startup t))
25075 (org-mode)
25076 (show-all)
25077 (unless keepp (funcall binding arg))))
25078 (if (not keepp)
25079 (kill-buffer buffer)
25080 (switch-to-buffer-other-window buffer)
25081 (goto-char (point-min)))))
25083 (defun org-find-visible ()
25084 (let ((s (point)))
25085 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
25086 (get-char-property s 'invisible)))
25088 (defun org-find-invisible ()
25089 (let ((s (point)))
25090 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
25091 (not (get-char-property s 'invisible))))
25094 ;;; HTML export
25096 (defun org-get-current-options ()
25097 "Return a string with current options as keyword options.
25098 Does include HTML export options as well as TODO and CATEGORY stuff."
25099 (format
25100 "#+TITLE: %s
25101 #+AUTHOR: %s
25102 #+EMAIL: %s
25103 #+DATE: %s
25104 #+LANGUAGE: %s
25105 #+TEXT: Some descriptive text to be emitted. Several lines OK.
25106 #+OPTIONS: H:%d num:%s toc:%s \\n:%s @:%s ::%s |:%s ^:%s -:%s f:%s *:%s TeX:%s LaTeX:%s skip:%s d:%s tags:%s
25107 #+CATEGORY: %s
25108 #+SEQ_TODO: %s
25109 #+TYP_TODO: %s
25110 #+PRIORITIES: %c %c %c
25111 #+DRAWERS: %s
25112 #+STARTUP: %s %s %s %s %s
25113 #+TAGS: %s
25114 #+ARCHIVE: %s
25115 #+LINK: %s
25117 (buffer-name) (user-full-name) user-mail-address
25118 (format-time-string (car org-time-stamp-formats))
25119 org-export-default-language
25120 org-export-headline-levels
25121 org-export-with-section-numbers
25122 org-export-with-toc
25123 org-export-preserve-breaks
25124 org-export-html-expand
25125 org-export-with-fixed-width
25126 org-export-with-tables
25127 org-export-with-sub-superscripts
25128 org-export-with-special-strings
25129 org-export-with-footnotes
25130 org-export-with-emphasize
25131 org-export-with-TeX-macros
25132 org-export-with-LaTeX-fragments
25133 org-export-skip-text-before-1st-heading
25134 org-export-with-drawers
25135 org-export-with-tags
25136 (file-name-nondirectory buffer-file-name)
25137 "TODO FEEDBACK VERIFY DONE"
25138 "Me Jason Marie DONE"
25139 org-highest-priority org-lowest-priority org-default-priority
25140 (mapconcat 'identity org-drawers " ")
25141 (cdr (assoc org-startup-folded
25142 '((nil . "showall") (t . "overview") (content . "content"))))
25143 (if org-odd-levels-only "odd" "oddeven")
25144 (if org-hide-leading-stars "hidestars" "showstars")
25145 (if org-startup-align-all-tables "align" "noalign")
25146 (cond ((eq org-log-done t) "logdone")
25147 ((equal org-log-done 'note) "lognotedone")
25148 ((not org-log-done) "nologdone"))
25149 (or (mapconcat (lambda (x)
25150 (cond
25151 ((equal '(:startgroup) x) "{")
25152 ((equal '(:endgroup) x) "}")
25153 ((cdr x) (format "%s(%c)" (car x) (cdr x)))
25154 (t (car x))))
25155 (or org-tag-alist (org-get-buffer-tags)) " ") "")
25156 org-archive-location
25157 "org file:~/org/%s.org"
25160 (defun org-insert-export-options-template ()
25161 "Insert into the buffer a template with information for exporting."
25162 (interactive)
25163 (if (not (bolp)) (newline))
25164 (let ((s (org-get-current-options)))
25165 (and (string-match "#\\+CATEGORY" s)
25166 (setq s (substring s 0 (match-beginning 0))))
25167 (insert s)))
25169 (defun org-toggle-fixed-width-section (arg)
25170 "Toggle the fixed-width export.
25171 If there is no active region, the QUOTE keyword at the current headline is
25172 inserted or removed. When present, it causes the text between this headline
25173 and the next to be exported as fixed-width text, and unmodified.
25174 If there is an active region, this command adds or removes a colon as the
25175 first character of this line. If the first character of a line is a colon,
25176 this line is also exported in fixed-width font."
25177 (interactive "P")
25178 (let* ((cc 0)
25179 (regionp (org-region-active-p))
25180 (beg (if regionp (region-beginning) (point)))
25181 (end (if regionp (region-end)))
25182 (nlines (or arg (if (and beg end) (count-lines beg end) 1)))
25183 (case-fold-search nil)
25184 (re "[ \t]*\\(:\\)")
25185 off)
25186 (if regionp
25187 (save-excursion
25188 (goto-char beg)
25189 (setq cc (current-column))
25190 (beginning-of-line 1)
25191 (setq off (looking-at re))
25192 (while (> nlines 0)
25193 (setq nlines (1- nlines))
25194 (beginning-of-line 1)
25195 (cond
25196 (arg
25197 (move-to-column cc t)
25198 (insert ":\n")
25199 (forward-line -1))
25200 ((and off (looking-at re))
25201 (replace-match "" t t nil 1))
25202 ((not off) (move-to-column cc t) (insert ":")))
25203 (forward-line 1)))
25204 (save-excursion
25205 (org-back-to-heading)
25206 (if (looking-at (concat outline-regexp
25207 "\\( *\\<" org-quote-string "\\>[ \t]*\\)"))
25208 (replace-match "" t t nil 1)
25209 (if (looking-at outline-regexp)
25210 (progn
25211 (goto-char (match-end 0))
25212 (insert org-quote-string " "))))))))
25214 (defun org-export-as-html-and-open (arg)
25215 "Export the outline as HTML and immediately open it with a browser.
25216 If there is an active region, export only the region.
25217 The prefix ARG specifies how many levels of the outline should become
25218 headlines. The default is 3. Lower levels will become bulleted lists."
25219 (interactive "P")
25220 (org-export-as-html arg 'hidden)
25221 (org-open-file buffer-file-name))
25223 (defun org-export-as-html-batch ()
25224 "Call `org-export-as-html', may be used in batch processing as
25225 emacs --batch
25226 --load=$HOME/lib/emacs/org.el
25227 --eval \"(setq org-export-headline-levels 2)\"
25228 --visit=MyFile --funcall org-export-as-html-batch"
25229 (org-export-as-html org-export-headline-levels 'hidden))
25231 (defun org-export-as-html-to-buffer (arg)
25232 "Call `org-exort-as-html` with output to a temporary buffer.
25233 No file is created. The prefix ARG is passed through to `org-export-as-html'."
25234 (interactive "P")
25235 (org-export-as-html arg nil nil "*Org HTML Export*")
25236 (switch-to-buffer-other-window "*Org HTML Export*"))
25238 (defun org-replace-region-by-html (beg end)
25239 "Assume the current region has org-mode syntax, and convert it to HTML.
25240 This can be used in any buffer. For example, you could write an
25241 itemized list in org-mode syntax in an HTML buffer and then use this
25242 command to convert it."
25243 (interactive "r")
25244 (let (reg html buf pop-up-frames)
25245 (save-window-excursion
25246 (if (org-mode-p)
25247 (setq html (org-export-region-as-html
25248 beg end t 'string))
25249 (setq reg (buffer-substring beg end)
25250 buf (get-buffer-create "*Org tmp*"))
25251 (with-current-buffer buf
25252 (erase-buffer)
25253 (insert reg)
25254 (org-mode)
25255 (setq html (org-export-region-as-html
25256 (point-min) (point-max) t 'string)))
25257 (kill-buffer buf)))
25258 (delete-region beg end)
25259 (insert html)))
25261 (defun org-export-region-as-html (beg end &optional body-only buffer)
25262 "Convert region from BEG to END in org-mode buffer to HTML.
25263 If prefix arg BODY-ONLY is set, omit file header, footer, and table of
25264 contents, and only produce the region of converted text, useful for
25265 cut-and-paste operations.
25266 If BUFFER is a buffer or a string, use/create that buffer as a target
25267 of the converted HTML. If BUFFER is the symbol `string', return the
25268 produced HTML as a string and leave not buffer behind. For example,
25269 a Lisp program could call this function in the following way:
25271 (setq html (org-export-region-as-html beg end t 'string))
25273 When called interactively, the output buffer is selected, and shown
25274 in a window. A non-interactive call will only retunr the buffer."
25275 (interactive "r\nP")
25276 (when (interactive-p)
25277 (setq buffer "*Org HTML Export*"))
25278 (let ((transient-mark-mode t) (zmacs-regions t)
25279 rtn)
25280 (goto-char end)
25281 (set-mark (point)) ;; to activate the region
25282 (goto-char beg)
25283 (setq rtn (org-export-as-html
25284 nil nil nil
25285 buffer body-only))
25286 (if (fboundp 'deactivate-mark) (deactivate-mark))
25287 (if (and (interactive-p) (bufferp rtn))
25288 (switch-to-buffer-other-window rtn)
25289 rtn)))
25291 (defvar html-table-tag nil) ; dynamically scoped into this.
25292 (defun org-export-as-html (arg &optional hidden ext-plist
25293 to-buffer body-only pub-dir)
25294 "Export the outline as a pretty HTML file.
25295 If there is an active region, export only the region. The prefix
25296 ARG specifies how many levels of the outline should become
25297 headlines. The default is 3. Lower levels will become bulleted
25298 lists. When HIDDEN is non-nil, don't display the HTML buffer.
25299 EXT-PLIST is a property list with external parameters overriding
25300 org-mode's default settings, but still inferior to file-local
25301 settings. When TO-BUFFER is non-nil, create a buffer with that
25302 name and export to that buffer. If TO-BUFFER is the symbol
25303 `string', don't leave any buffer behind but just return the
25304 resulting HTML as a string. When BODY-ONLY is set, don't produce
25305 the file header and footer, simply return the content of
25306 <body>...</body>, without even the body tags themselves. When
25307 PUB-DIR is set, use this as the publishing directory."
25308 (interactive "P")
25310 ;; Make sure we have a file name when we need it.
25311 (when (and (not (or to-buffer body-only))
25312 (not buffer-file-name))
25313 (if (buffer-base-buffer)
25314 (org-set-local 'buffer-file-name
25315 (with-current-buffer (buffer-base-buffer)
25316 buffer-file-name))
25317 (error "Need a file name to be able to export.")))
25319 (message "Exporting...")
25320 (setq-default org-todo-line-regexp org-todo-line-regexp)
25321 (setq-default org-deadline-line-regexp org-deadline-line-regexp)
25322 (setq-default org-done-keywords org-done-keywords)
25323 (setq-default org-maybe-keyword-time-regexp org-maybe-keyword-time-regexp)
25324 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
25325 ext-plist
25326 (org-infile-export-plist)))
25328 (style (plist-get opt-plist :style))
25329 (html-extension (plist-get opt-plist :html-extension))
25330 (link-validate (plist-get opt-plist :link-validation-function))
25331 valid thetoc have-headings first-heading-pos
25332 (odd org-odd-levels-only)
25333 (region-p (org-region-active-p))
25334 (subtree-p
25335 (when region-p
25336 (save-excursion
25337 (goto-char (region-beginning))
25338 (and (org-at-heading-p)
25339 (>= (org-end-of-subtree t t) (region-end))))))
25340 ;; The following two are dynamically scoped into other
25341 ;; routines below.
25342 (org-current-export-dir
25343 (or pub-dir (org-export-directory :html opt-plist)))
25344 (org-current-export-file buffer-file-name)
25345 (level 0) (line "") (origline "") txt todo
25346 (umax nil)
25347 (umax-toc nil)
25348 (filename (if to-buffer nil
25349 (expand-file-name
25350 (concat
25351 (file-name-sans-extension
25352 (or (and subtree-p
25353 (org-entry-get (region-beginning)
25354 "EXPORT_FILE_NAME" t))
25355 (file-name-nondirectory buffer-file-name)))
25356 "." html-extension)
25357 (file-name-as-directory
25358 (or pub-dir (org-export-directory :html opt-plist))))))
25359 (current-dir (if buffer-file-name
25360 (file-name-directory buffer-file-name)
25361 default-directory))
25362 (buffer (if to-buffer
25363 (cond
25364 ((eq to-buffer 'string) (get-buffer-create "*Org HTML Export*"))
25365 (t (get-buffer-create to-buffer)))
25366 (find-file-noselect filename)))
25367 (org-levels-open (make-vector org-level-max nil))
25368 (date (plist-get opt-plist :date))
25369 (author (plist-get opt-plist :author))
25370 (title (or (and subtree-p (org-export-get-title-from-subtree))
25371 (plist-get opt-plist :title)
25372 (and (not
25373 (plist-get opt-plist :skip-before-1st-heading))
25374 (org-export-grab-title-from-buffer))
25375 (and buffer-file-name
25376 (file-name-sans-extension
25377 (file-name-nondirectory buffer-file-name)))
25378 "UNTITLED"))
25379 (html-table-tag (plist-get opt-plist :html-table-tag))
25380 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
25381 (quote-re (concat "^\\(\\*+\\)\\([ \t]+" org-quote-string "\\>\\)"))
25382 (inquote nil)
25383 (infixed nil)
25384 (in-local-list nil)
25385 (local-list-num nil)
25386 (local-list-indent nil)
25387 (llt org-plain-list-ordered-item-terminator)
25388 (email (plist-get opt-plist :email))
25389 (language (plist-get opt-plist :language))
25390 (lang-words nil)
25391 (target-alist nil) tg
25392 (head-count 0) cnt
25393 (start 0)
25394 (coding-system (and (boundp 'buffer-file-coding-system)
25395 buffer-file-coding-system))
25396 (coding-system-for-write (or org-export-html-coding-system
25397 coding-system))
25398 (save-buffer-coding-system (or org-export-html-coding-system
25399 coding-system))
25400 (charset (and coding-system-for-write
25401 (fboundp 'coding-system-get)
25402 (coding-system-get coding-system-for-write
25403 'mime-charset)))
25404 (region
25405 (buffer-substring
25406 (if region-p (region-beginning) (point-min))
25407 (if region-p (region-end) (point-max))))
25408 (lines
25409 (org-split-string
25410 (org-cleaned-string-for-export
25411 region
25412 :emph-multiline t
25413 :for-html t
25414 :skip-before-1st-heading
25415 (plist-get opt-plist :skip-before-1st-heading)
25416 :drawers (plist-get opt-plist :drawers)
25417 :archived-trees
25418 (plist-get opt-plist :archived-trees)
25419 :add-text
25420 (plist-get opt-plist :text)
25421 :LaTeX-fragments
25422 (plist-get opt-plist :LaTeX-fragments))
25423 "[\r\n]"))
25424 table-open type
25425 table-buffer table-orig-buffer
25426 ind start-is-num starter didclose
25427 rpl path desc descp desc1 desc2 link
25428 snumber fnc
25431 (let ((inhibit-read-only t))
25432 (org-unmodified
25433 (remove-text-properties (point-min) (point-max)
25434 '(:org-license-to-kill t))))
25436 (message "Exporting...")
25438 (setq org-min-level (org-get-min-level lines))
25439 (setq org-last-level org-min-level)
25440 (org-init-section-numbers)
25442 (cond
25443 ((and date (string-match "%" date))
25444 (setq date (format-time-string date)))
25445 (date)
25446 (t (setq date (format-time-string "%Y/%m/%d %X"))))
25448 ;; Get the language-dependent settings
25449 (setq lang-words (or (assoc language org-export-language-setup)
25450 (assoc "en" org-export-language-setup)))
25452 ;; Switch to the output buffer
25453 (set-buffer buffer)
25454 (let ((inhibit-read-only t)) (erase-buffer))
25455 (fundamental-mode)
25457 (and (fboundp 'set-buffer-file-coding-system)
25458 (set-buffer-file-coding-system coding-system-for-write))
25460 (let ((case-fold-search nil)
25461 (org-odd-levels-only odd))
25462 ;; create local variables for all options, to make sure all called
25463 ;; functions get the correct information
25464 (mapc (lambda (x)
25465 (set (make-local-variable (cdr x))
25466 (plist-get opt-plist (car x))))
25467 org-export-plist-vars)
25468 (setq umax (if arg (prefix-numeric-value arg)
25469 org-export-headline-levels))
25470 (setq umax-toc (if (integerp org-export-with-toc)
25471 (min org-export-with-toc umax)
25472 umax))
25473 (unless body-only
25474 ;; File header
25475 (insert (format
25476 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
25477 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
25478 <html xmlns=\"http://www.w3.org/1999/xhtml\"
25479 lang=\"%s\" xml:lang=\"%s\">
25480 <head>
25481 <title>%s</title>
25482 <meta http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"/>
25483 <meta name=\"generator\" content=\"Org-mode\"/>
25484 <meta name=\"generated\" content=\"%s\"/>
25485 <meta name=\"author\" content=\"%s\"/>
25487 </head><body>
25489 language language (org-html-expand title)
25490 (or charset "iso-8859-1") date author style))
25492 (insert (or (plist-get opt-plist :preamble) ""))
25494 (when (plist-get opt-plist :auto-preamble)
25495 (if title (insert (format org-export-html-title-format
25496 (org-html-expand title))))))
25498 (if (and org-export-with-toc (not body-only))
25499 (progn
25500 (push (format "<h%d>%s</h%d>\n"
25501 org-export-html-toplevel-hlevel
25502 (nth 3 lang-words)
25503 org-export-html-toplevel-hlevel)
25504 thetoc)
25505 (push "<div id=\"text-table-of-contents\">\n" thetoc)
25506 (push "<ul>\n<li>" thetoc)
25507 (setq lines
25508 (mapcar '(lambda (line)
25509 (if (string-match org-todo-line-regexp line)
25510 ;; This is a headline
25511 (progn
25512 (setq have-headings t)
25513 (setq level (- (match-end 1) (match-beginning 1))
25514 level (org-tr-level level)
25515 txt (save-match-data
25516 (org-html-expand
25517 (org-export-cleanup-toc-line
25518 (match-string 3 line))))
25519 todo
25520 (or (and org-export-mark-todo-in-toc
25521 (match-beginning 2)
25522 (not (member (match-string 2 line)
25523 org-done-keywords)))
25524 ; TODO, not DONE
25525 (and org-export-mark-todo-in-toc
25526 (= level umax-toc)
25527 (org-search-todo-below
25528 line lines level))))
25529 (if (string-match
25530 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") txt)
25531 (setq txt (replace-match "&nbsp;&nbsp;&nbsp;<span class=\"tag\"> \\1</span>" t nil txt)))
25532 (if (string-match quote-re0 txt)
25533 (setq txt (replace-match "" t t txt)))
25534 (setq snumber (org-section-number level))
25535 (if org-export-with-section-numbers
25536 (setq txt (concat snumber " " txt)))
25537 (if (<= level (max umax umax-toc))
25538 (setq head-count (+ head-count 1)))
25539 (if (<= level umax-toc)
25540 (progn
25541 (if (> level org-last-level)
25542 (progn
25543 (setq cnt (- level org-last-level))
25544 (while (>= (setq cnt (1- cnt)) 0)
25545 (push "\n<ul>\n<li>" thetoc))
25546 (push "\n" thetoc)))
25547 (if (< level org-last-level)
25548 (progn
25549 (setq cnt (- org-last-level level))
25550 (while (>= (setq cnt (1- cnt)) 0)
25551 (push "</li>\n</ul>" thetoc))
25552 (push "\n" thetoc)))
25553 ;; Check for targets
25554 (while (string-match org-target-regexp line)
25555 (setq tg (match-string 1 line)
25556 line (replace-match
25557 (concat "@<span class=\"target\">" tg "@</span> ")
25558 t t line))
25559 (push (cons (org-solidify-link-text tg)
25560 (format "sec-%s" snumber))
25561 target-alist))
25562 (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
25563 (setq txt (replace-match "" t t txt)))
25564 (push
25565 (format
25566 (if todo
25567 "</li>\n<li><a href=\"#sec-%s\"><span class=\"todo\">%s</span></a>"
25568 "</li>\n<li><a href=\"#sec-%s\">%s</a>")
25569 snumber txt) thetoc)
25571 (setq org-last-level level))
25573 line)
25574 lines))
25575 (while (> org-last-level (1- org-min-level))
25576 (setq org-last-level (1- org-last-level))
25577 (push "</li>\n</ul>\n" thetoc))
25578 (push "</div>\n" thetoc)
25579 (setq thetoc (if have-headings (nreverse thetoc) nil))))
25581 (setq head-count 0)
25582 (org-init-section-numbers)
25584 (while (setq line (pop lines) origline line)
25585 (catch 'nextline
25587 ;; end of quote section?
25588 (when (and inquote (string-match "^\\*+ " line))
25589 (insert "</pre>\n")
25590 (setq inquote nil))
25591 ;; inside a quote section?
25592 (when inquote
25593 (insert (org-html-protect line) "\n")
25594 (throw 'nextline nil))
25596 ;; verbatim lines
25597 (when (and org-export-with-fixed-width
25598 (string-match "^[ \t]*:\\(.*\\)" line))
25599 (when (not infixed)
25600 (setq infixed t)
25601 (insert "<pre>\n"))
25602 (insert (org-html-protect (match-string 1 line)) "\n")
25603 (when (and lines
25604 (not (string-match "^[ \t]*\\(:.*\\)"
25605 (car lines))))
25606 (setq infixed nil)
25607 (insert "</pre>\n"))
25608 (throw 'nextline nil))
25610 ;; Protected HTML
25611 (when (get-text-property 0 'org-protected line)
25612 (let (par)
25613 (when (re-search-backward
25614 "\\(<p>\\)\\([ \t\r\n]*\\)\\=" (- (point) 100) t)
25615 (setq par (match-string 1))
25616 (replace-match "\\2\n"))
25617 (insert line "\n")
25618 (while (and lines
25619 (or (= (length (car lines)) 0)
25620 (get-text-property 0 'org-protected (car lines))))
25621 (insert (pop lines) "\n"))
25622 (and par (insert "<p>\n")))
25623 (throw 'nextline nil))
25625 ;; Horizontal line
25626 (when (string-match "^[ \t]*-\\{5,\\}[ \t]*$" line)
25627 (insert "\n<hr/>\n")
25628 (throw 'nextline nil))
25630 ;; make targets to anchors
25631 (while (string-match "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line)
25632 (cond
25633 ((match-end 2)
25634 (setq line (replace-match
25635 (concat "@<a name=\""
25636 (org-solidify-link-text (match-string 1 line))
25637 "\">\\nbsp@</a>")
25638 t t line)))
25639 ((and org-export-with-toc (equal (string-to-char line) ?*))
25640 (setq line (replace-match
25641 (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
25642 ; (concat "@<i>" (match-string 1 line) "@</i> ")
25643 t t line)))
25645 (setq line (replace-match
25646 (concat "@<a name=\""
25647 (org-solidify-link-text (match-string 1 line))
25648 "\" class=\"target\">" (match-string 1 line) "@</a> ")
25649 t t line)))))
25651 (setq line (org-html-handle-time-stamps line))
25653 ;; replace "&" by "&amp;", "<" and ">" by "&lt;" and "&gt;"
25654 ;; handle @<..> HTML tags (replace "@&gt;..&lt;" by "<..>")
25655 ;; Also handle sub_superscripts and checkboxes
25656 (or (string-match org-table-hline-regexp line)
25657 (setq line (org-html-expand line)))
25659 ;; Format the links
25660 (setq start 0)
25661 (while (string-match org-bracket-link-analytic-regexp line start)
25662 (setq start (match-beginning 0))
25663 (setq type (if (match-end 2) (match-string 2 line) "internal"))
25664 (setq path (match-string 3 line))
25665 (setq desc1 (if (match-end 5) (match-string 5 line))
25666 desc2 (if (match-end 2) (concat type ":" path) path)
25667 descp (and desc1 (not (equal desc1 desc2)))
25668 desc (or desc1 desc2))
25669 ;; Make an image out of the description if that is so wanted
25670 (when (and descp (org-file-image-p desc))
25671 (save-match-data
25672 (if (string-match "^file:" desc)
25673 (setq desc (substring desc (match-end 0)))))
25674 (setq desc (concat "<img src=\"" desc "\"/>")))
25675 ;; FIXME: do we need to unescape here somewhere?
25676 (cond
25677 ((equal type "internal")
25678 (setq rpl
25679 (concat
25680 "<a href=\"#"
25681 (org-solidify-link-text
25682 (save-match-data (org-link-unescape path)) target-alist)
25683 "\">" desc "</a>")))
25684 ((member type '("http" "https"))
25685 ;; standard URL, just check if we need to inline an image
25686 (if (and (or (eq t org-export-html-inline-images)
25687 (and org-export-html-inline-images (not descp)))
25688 (org-file-image-p path))
25689 (setq rpl (concat "<img src=\"" type ":" path "\"/>"))
25690 (setq link (concat type ":" path))
25691 (setq rpl (concat "<a href=\"" link "\">" desc "</a>"))))
25692 ((member type '("ftp" "mailto" "news"))
25693 ;; standard URL
25694 (setq link (concat type ":" path))
25695 (setq rpl (concat "<a href=\"" link "\">" desc "</a>")))
25696 ((string= type "file")
25697 ;; FILE link
25698 (let* ((filename path)
25699 (abs-p (file-name-absolute-p filename))
25700 thefile file-is-image-p search)
25701 (save-match-data
25702 (if (string-match "::\\(.*\\)" filename)
25703 (setq search (match-string 1 filename)
25704 filename (replace-match "" t nil filename)))
25705 (setq valid
25706 (if (functionp link-validate)
25707 (funcall link-validate filename current-dir)
25709 (setq file-is-image-p (org-file-image-p filename))
25710 (setq thefile (if abs-p (expand-file-name filename) filename))
25711 (when (and org-export-html-link-org-files-as-html
25712 (string-match "\\.org$" thefile))
25713 (setq thefile (concat (substring thefile 0
25714 (match-beginning 0))
25715 "." html-extension))
25716 (if (and search
25717 ;; make sure this is can be used as target search
25718 (not (string-match "^[0-9]*$" search))
25719 (not (string-match "^\\*" search))
25720 (not (string-match "^/.*/$" search)))
25721 (setq thefile (concat thefile "#"
25722 (org-solidify-link-text
25723 (org-link-unescape search)))))
25724 (when (string-match "^file:" desc)
25725 (setq desc (replace-match "" t t desc))
25726 (if (string-match "\\.org$" desc)
25727 (setq desc (replace-match "" t t desc))))))
25728 (setq rpl (if (and file-is-image-p
25729 (or (eq t org-export-html-inline-images)
25730 (and org-export-html-inline-images
25731 (not descp))))
25732 (concat "<img src=\"" thefile "\"/>")
25733 (concat "<a href=\"" thefile "\">" desc "</a>")))
25734 (if (not valid) (setq rpl desc))))
25736 ((functionp (setq fnc (nth 2 (assoc type org-link-protocols))))
25737 (setq rpl
25738 (save-match-data
25739 (funcall fnc (org-link-unescape path) desc1 'html))))
25742 ;; just publish the path, as default
25743 (setq rpl (concat "<i>&lt;" type ":"
25744 (save-match-data (org-link-unescape path))
25745 "&gt;</i>"))))
25746 (setq line (replace-match rpl t t line)
25747 start (+ start (length rpl))))
25749 ;; TODO items
25750 (if (and (string-match org-todo-line-regexp line)
25751 (match-beginning 2))
25753 (setq line
25754 (concat (substring line 0 (match-beginning 2))
25755 "<span class=\""
25756 (if (member (match-string 2 line)
25757 org-done-keywords)
25758 "done" "todo")
25759 "\">" (match-string 2 line)
25760 "</span>" (substring line (match-end 2)))))
25762 ;; Does this contain a reference to a footnote?
25763 (when org-export-with-footnotes
25764 (setq start 0)
25765 (while (string-match "\\([^* \t].*?\\)\\[\\([0-9]+\\)\\]" line start)
25766 (if (get-text-property (match-beginning 2) 'org-protected line)
25767 (setq start (match-end 2))
25768 (let ((n (match-string 2 line)))
25769 (setq line
25770 (replace-match
25771 (format
25772 "%s<sup><a class=\"footref\" name=\"fnr.%s\" href=\"#fn.%s\">%s</a></sup>"
25773 (match-string 1 line) n n n)
25774 t t line))))))
25776 (cond
25777 ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line)
25778 ;; This is a headline
25779 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
25780 txt (match-string 2 line))
25781 (if (string-match quote-re0 txt)
25782 (setq txt (replace-match "" t t txt)))
25783 (if (<= level (max umax umax-toc))
25784 (setq head-count (+ head-count 1)))
25785 (when in-local-list
25786 ;; Close any local lists before inserting a new header line
25787 (while local-list-num
25788 (org-close-li)
25789 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
25790 (pop local-list-num))
25791 (setq local-list-indent nil
25792 in-local-list nil))
25793 (setq first-heading-pos (or first-heading-pos (point)))
25794 (org-html-level-start level txt umax
25795 (and org-export-with-toc (<= level umax))
25796 head-count)
25797 ;; QUOTES
25798 (when (string-match quote-re line)
25799 (insert "<pre>")
25800 (setq inquote t)))
25802 ((and org-export-with-tables
25803 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
25804 (if (not table-open)
25805 ;; New table starts
25806 (setq table-open t table-buffer nil table-orig-buffer nil))
25807 ;; Accumulate lines
25808 (setq table-buffer (cons line table-buffer)
25809 table-orig-buffer (cons origline table-orig-buffer))
25810 (when (or (not lines)
25811 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
25812 (car lines))))
25813 (setq table-open nil
25814 table-buffer (nreverse table-buffer)
25815 table-orig-buffer (nreverse table-orig-buffer))
25816 (org-close-par-maybe)
25817 (insert (org-format-table-html table-buffer table-orig-buffer))))
25819 ;; Normal lines
25820 (when (string-match
25821 (cond
25822 ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
25823 ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
25824 ((= llt ?\)) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
25825 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
25826 line)
25827 (setq ind (org-get-string-indentation line)
25828 start-is-num (match-beginning 4)
25829 starter (if (match-beginning 2)
25830 (substring (match-string 2 line) 0 -1))
25831 line (substring line (match-beginning 5)))
25832 (unless (string-match "[^ \t]" line)
25833 ;; empty line. Pretend indentation is large.
25834 (setq ind (if org-empty-line-terminates-plain-lists
25836 (1+ (or (car local-list-indent) 1)))))
25837 (setq didclose nil)
25838 (while (and in-local-list
25839 (or (and (= ind (car local-list-indent))
25840 (not starter))
25841 (< ind (car local-list-indent))))
25842 (setq didclose t)
25843 (org-close-li)
25844 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
25845 (pop local-list-num) (pop local-list-indent)
25846 (setq in-local-list local-list-indent))
25847 (cond
25848 ((and starter
25849 (or (not in-local-list)
25850 (> ind (car local-list-indent))))
25851 ;; Start new (level of) list
25852 (org-close-par-maybe)
25853 (insert (if start-is-num "<ol>\n<li>\n" "<ul>\n<li>\n"))
25854 (push start-is-num local-list-num)
25855 (push ind local-list-indent)
25856 (setq in-local-list t))
25857 (starter
25858 ;; continue current list
25859 (org-close-li)
25860 (insert "<li>\n"))
25861 (didclose
25862 ;; we did close a list, normal text follows: need <p>
25863 (org-open-par)))
25864 (if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
25865 (setq line
25866 (replace-match
25867 (if (equal (match-string 1 line) "X")
25868 "<b>[X]</b>"
25869 "<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
25870 t t line))))
25872 ;; Empty lines start a new paragraph. If hand-formatted lists
25873 ;; are not fully interpreted, lines starting with "-", "+", "*"
25874 ;; also start a new paragraph.
25875 (if (string-match "^ [-+*]-\\|^[ \t]*$" line) (org-open-par))
25877 ;; Is this the start of a footnote?
25878 (when org-export-with-footnotes
25879 (when (string-match "^[ \t]*\\[\\([0-9]+\\)\\]" line)
25880 (org-close-par-maybe)
25881 (let ((n (match-string 1 line)))
25882 (setq line (replace-match
25883 (format "<p class=\"footnote\"><sup><a class=\"footnum\" name=\"fn.%s\" href=\"#fnr.%s\">%s</a></sup>" n n n) t t line)))))
25885 ;; Check if the line break needs to be conserved
25886 (cond
25887 ((string-match "\\\\\\\\[ \t]*$" line)
25888 (setq line (replace-match "<br/>" t t line)))
25889 (org-export-preserve-breaks
25890 (setq line (concat line "<br/>"))))
25892 (insert line "\n")))))
25894 ;; Properly close all local lists and other lists
25895 (when inquote (insert "</pre>\n"))
25896 (when in-local-list
25897 ;; Close any local lists before inserting a new header line
25898 (while local-list-num
25899 (org-close-li)
25900 (insert (if (car local-list-num) "</ol>\n" "</ul>\n"))
25901 (pop local-list-num))
25902 (setq local-list-indent nil
25903 in-local-list nil))
25904 (org-html-level-start 1 nil umax
25905 (and org-export-with-toc (<= level umax))
25906 head-count)
25907 ;; the </div> to lose the last text-... div.
25908 (insert "</div>\n")
25910 (unless body-only
25911 (when (plist-get opt-plist :auto-postamble)
25912 (insert "<div id=\"postamble\">")
25913 (when (and org-export-author-info author)
25914 (insert "<p class=\"author\"> "
25915 (nth 1 lang-words) ": " author "\n")
25916 (when email
25917 (if (listp (split-string email ",+ *"))
25918 (mapc (lambda(e)
25919 (insert "<a href=\"mailto:" e "\">&lt;"
25920 e "&gt;</a>\n"))
25921 (split-string email ",+ *"))
25922 (insert "<a href=\"mailto:" email "\">&lt;"
25923 email "&gt;</a>\n")))
25924 (insert "</p>\n"))
25925 (when (and date org-export-time-stamp-file)
25926 (insert "<p class=\"date\"> "
25927 (nth 2 lang-words) ": "
25928 date "</p>\n"))
25929 (insert "</div>"))
25931 (if org-export-html-with-timestamp
25932 (insert org-export-html-html-helper-timestamp))
25933 (insert (or (plist-get opt-plist :postamble) ""))
25934 (insert "</body>\n</html>\n"))
25936 (normal-mode)
25937 (if (eq major-mode default-major-mode) (html-mode))
25939 ;; insert the table of contents
25940 (goto-char (point-min))
25941 (when thetoc
25942 (if (or (re-search-forward
25943 "<p>\\s-*\\[TABLE-OF-CONTENTS\\]\\s-*</p>" nil t)
25944 (re-search-forward
25945 "\\[TABLE-OF-CONTENTS\\]" nil t))
25946 (progn
25947 (goto-char (match-beginning 0))
25948 (replace-match ""))
25949 (goto-char first-heading-pos)
25950 (when (looking-at "\\s-*</p>")
25951 (goto-char (match-end 0))
25952 (insert "\n")))
25953 (insert "<div id=\"table-of-contents\">\n")
25954 (mapc 'insert thetoc)
25955 (insert "</div>\n"))
25956 ;; remove empty paragraphs and lists
25957 (goto-char (point-min))
25958 (while (re-search-forward "<p>[ \r\n\t]*</p>" nil t)
25959 (replace-match ""))
25960 (goto-char (point-min))
25961 (while (re-search-forward "<li>[ \r\n\t]*</li>\n?" nil t)
25962 (replace-match ""))
25963 (goto-char (point-min))
25964 (while (re-search-forward "</ul>\\s-*<ul>\n?" nil t)
25965 (replace-match ""))
25966 ;; Convert whitespace place holders
25967 (goto-char (point-min))
25968 (let (beg end n)
25969 (while (setq beg (next-single-property-change (point) 'org-whitespace))
25970 (setq n (get-text-property beg 'org-whitespace)
25971 end (next-single-property-change beg 'org-whitespace))
25972 (goto-char beg)
25973 (delete-region beg end)
25974 (insert (format "<span style=\"visibility:hidden;\">%s</span>"
25975 (make-string n ?x)))))
25976 (or to-buffer (save-buffer))
25977 (goto-char (point-min))
25978 (message "Exporting... done")
25979 (if (eq to-buffer 'string)
25980 (prog1 (buffer-substring (point-min) (point-max))
25981 (kill-buffer (current-buffer)))
25982 (current-buffer)))))
25984 (defvar org-table-colgroup-info nil)
25985 (defun org-format-table-ascii (lines)
25986 "Format a table for ascii export."
25987 (if (stringp lines)
25988 (setq lines (org-split-string lines "\n")))
25989 (if (not (string-match "^[ \t]*|" (car lines)))
25990 ;; Table made by table.el - test for spanning
25991 lines
25993 ;; A normal org table
25994 ;; Get rid of hlines at beginning and end
25995 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
25996 (setq lines (nreverse lines))
25997 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
25998 (setq lines (nreverse lines))
25999 (when org-export-table-remove-special-lines
26000 ;; Check if the table has a marking column. If yes remove the
26001 ;; column and the special lines
26002 (setq lines (org-table-clean-before-export lines)))
26003 ;; Get rid of the vertical lines except for grouping
26004 (let ((vl (org-colgroup-info-to-vline-list org-table-colgroup-info))
26005 rtn line vl1 start)
26006 (while (setq line (pop lines))
26007 (if (string-match org-table-hline-regexp line)
26008 (and (string-match "|\\(.*\\)|" line)
26009 (setq line (replace-match " \\1" t nil line)))
26010 (setq start 0 vl1 vl)
26011 (while (string-match "|" line start)
26012 (setq start (match-end 0))
26013 (or (pop vl1) (setq line (replace-match " " t t line)))))
26014 (push line rtn))
26015 (nreverse rtn))))
26017 (defun org-colgroup-info-to-vline-list (info)
26018 (let (vl new last)
26019 (while info
26020 (setq last new new (pop info))
26021 (if (or (memq last '(:end :startend))
26022 (memq new '(:start :startend)))
26023 (push t vl)
26024 (push nil vl)))
26025 (setq vl (nreverse vl))
26026 (and vl (setcar vl nil))
26027 vl))
26029 (defun org-format-table-html (lines olines)
26030 "Find out which HTML converter to use and return the HTML code."
26031 (if (stringp lines)
26032 (setq lines (org-split-string lines "\n")))
26033 (if (string-match "^[ \t]*|" (car lines))
26034 ;; A normal org table
26035 (org-format-org-table-html lines)
26036 ;; Table made by table.el - test for spanning
26037 (let* ((hlines (delq nil (mapcar
26038 (lambda (x)
26039 (if (string-match "^[ \t]*\\+-" x) x
26040 nil))
26041 lines)))
26042 (first (car hlines))
26043 (ll (and (string-match "\\S-+" first)
26044 (match-string 0 first)))
26045 (re (concat "^[ \t]*" (regexp-quote ll)))
26046 (spanning (delq nil (mapcar (lambda (x) (not (string-match re x)))
26047 hlines))))
26048 (if (and (not spanning)
26049 (not org-export-prefer-native-exporter-for-tables))
26050 ;; We can use my own converter with HTML conversions
26051 (org-format-table-table-html lines)
26052 ;; Need to use the code generator in table.el, with the original text.
26053 (org-format-table-table-html-using-table-generate-source olines)))))
26055 (defun org-format-org-table-html (lines &optional splice)
26056 "Format a table into HTML."
26057 ;; Get rid of hlines at beginning and end
26058 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
26059 (setq lines (nreverse lines))
26060 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
26061 (setq lines (nreverse lines))
26062 (when org-export-table-remove-special-lines
26063 ;; Check if the table has a marking column. If yes remove the
26064 ;; column and the special lines
26065 (setq lines (org-table-clean-before-export lines)))
26067 (let ((head (and org-export-highlight-first-table-line
26068 (delq nil (mapcar
26069 (lambda (x) (string-match "^[ \t]*|-" x))
26070 (cdr lines)))))
26071 (nlines 0) fnum i
26072 tbopen line fields html gr colgropen)
26073 (if splice (setq head nil))
26074 (unless splice (push (if head "<thead>" "<tbody>") html))
26075 (setq tbopen t)
26076 (while (setq line (pop lines))
26077 (catch 'next-line
26078 (if (string-match "^[ \t]*|-" line)
26079 (progn
26080 (unless splice
26081 (push (if head "</thead>" "</tbody>") html)
26082 (if lines (push "<tbody>" html) (setq tbopen nil)))
26083 (setq head nil) ;; head ends here, first time around
26084 ;; ignore this line
26085 (throw 'next-line t)))
26086 ;; Break the line into fields
26087 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
26088 (unless fnum (setq fnum (make-vector (length fields) 0)))
26089 (setq nlines (1+ nlines) i -1)
26090 (push (concat "<tr>"
26091 (mapconcat
26092 (lambda (x)
26093 (setq i (1+ i))
26094 (if (and (< i nlines)
26095 (string-match org-table-number-regexp x))
26096 (incf (aref fnum i)))
26097 (if head
26098 (concat (car org-export-table-header-tags) x
26099 (cdr org-export-table-header-tags))
26100 (concat (car org-export-table-data-tags) x
26101 (cdr org-export-table-data-tags))))
26102 fields "")
26103 "</tr>")
26104 html)))
26105 (unless splice (if tbopen (push "</tbody>" html)))
26106 (unless splice (push "</table>\n" html))
26107 (setq html (nreverse html))
26108 (unless splice
26109 ;; Put in col tags with the alignment (unfortuntely often ignored...)
26110 (push (mapconcat
26111 (lambda (x)
26112 (setq gr (pop org-table-colgroup-info))
26113 (format "%s<col align=\"%s\"></col>%s"
26114 (if (memq gr '(:start :startend))
26115 (prog1
26116 (if colgropen "</colgroup>\n<colgroup>" "<colgroup>")
26117 (setq colgropen t))
26119 (if (> (/ (float x) nlines) org-table-number-fraction)
26120 "right" "left")
26121 (if (memq gr '(:end :startend))
26122 (progn (setq colgropen nil) "</colgroup>")
26123 "")))
26124 fnum "")
26125 html)
26126 (if colgropen (setq html (cons (car html) (cons "</colgroup>" (cdr html)))))
26127 (push html-table-tag html))
26128 (concat (mapconcat 'identity html "\n") "\n")))
26130 (defun org-table-clean-before-export (lines)
26131 "Check if the table has a marking column.
26132 If yes remove the column and the special lines."
26133 (setq org-table-colgroup-info nil)
26134 (if (memq nil
26135 (mapcar
26136 (lambda (x) (or (string-match "^[ \t]*|-" x)
26137 (string-match "^[ \t]*| *\\([#!$*_^ /]\\) *|" x)))
26138 lines))
26139 (progn
26140 (setq org-table-clean-did-remove-column nil)
26141 (delq nil
26142 (mapcar
26143 (lambda (x)
26144 (cond
26145 ((string-match "^[ \t]*| */ *|" x)
26146 (setq org-table-colgroup-info
26147 (mapcar (lambda (x)
26148 (cond ((member x '("<" "&lt;")) :start)
26149 ((member x '(">" "&gt;")) :end)
26150 ((member x '("<>" "&lt;&gt;")) :startend)
26151 (t nil)))
26152 (org-split-string x "[ \t]*|[ \t]*")))
26153 nil)
26154 (t x)))
26155 lines)))
26156 (setq org-table-clean-did-remove-column t)
26157 (delq nil
26158 (mapcar
26159 (lambda (x)
26160 (cond
26161 ((string-match "^[ \t]*| */ *|" x)
26162 (setq org-table-colgroup-info
26163 (mapcar (lambda (x)
26164 (cond ((member x '("<" "&lt;")) :start)
26165 ((member x '(">" "&gt;")) :end)
26166 ((member x '("<>" "&lt;&gt;")) :startend)
26167 (t nil)))
26168 (cdr (org-split-string x "[ \t]*|[ \t]*"))))
26169 nil)
26170 ((string-match "^[ \t]*| *[!_^/] *|" x)
26171 nil) ; ignore this line
26172 ((or (string-match "^\\([ \t]*\\)|-+\\+" x)
26173 (string-match "^\\([ \t]*\\)|[^|]*|" x))
26174 ;; remove the first column
26175 (replace-match "\\1|" t nil x))))
26176 lines))))
26178 (defun org-format-table-table-html (lines)
26179 "Format a table generated by table.el into HTML.
26180 This conversion does *not* use `table-generate-source' from table.el.
26181 This has the advantage that Org-mode's HTML conversions can be used.
26182 But it has the disadvantage, that no cell- or row-spanning is allowed."
26183 (let (line field-buffer
26184 (head org-export-highlight-first-table-line)
26185 fields html empty)
26186 (setq html (concat html-table-tag "\n"))
26187 (while (setq line (pop lines))
26188 (setq empty "&nbsp;")
26189 (catch 'next-line
26190 (if (string-match "^[ \t]*\\+-" line)
26191 (progn
26192 (if field-buffer
26193 (progn
26194 (setq
26195 html
26196 (concat
26197 html
26198 "<tr>"
26199 (mapconcat
26200 (lambda (x)
26201 (if (equal x "") (setq x empty))
26202 (if head
26203 (concat (car org-export-table-header-tags) x
26204 (cdr org-export-table-header-tags))
26205 (concat (car org-export-table-data-tags) x
26206 (cdr org-export-table-data-tags))))
26207 field-buffer "\n")
26208 "</tr>\n"))
26209 (setq head nil)
26210 (setq field-buffer nil)))
26211 ;; Ignore this line
26212 (throw 'next-line t)))
26213 ;; Break the line into fields and store the fields
26214 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
26215 (if field-buffer
26216 (setq field-buffer (mapcar
26217 (lambda (x)
26218 (concat x "<br/>" (pop fields)))
26219 field-buffer))
26220 (setq field-buffer fields))))
26221 (setq html (concat html "</table>\n"))
26222 html))
26224 (defun org-format-table-table-html-using-table-generate-source (lines)
26225 "Format a table into html, using `table-generate-source' from table.el.
26226 This has the advantage that cell- or row-spanning is allowed.
26227 But it has the disadvantage, that Org-mode's HTML conversions cannot be used."
26228 (require 'table)
26229 (with-current-buffer (get-buffer-create " org-tmp1 ")
26230 (erase-buffer)
26231 (insert (mapconcat 'identity lines "\n"))
26232 (goto-char (point-min))
26233 (if (not (re-search-forward "|[^+]" nil t))
26234 (error "Error processing table"))
26235 (table-recognize-table)
26236 (with-current-buffer (get-buffer-create " org-tmp2 ") (erase-buffer))
26237 (table-generate-source 'html " org-tmp2 ")
26238 (set-buffer " org-tmp2 ")
26239 (buffer-substring (point-min) (point-max))))
26241 (defun org-html-handle-time-stamps (s)
26242 "Format time stamps in string S, or remove them."
26243 (catch 'exit
26244 (let (r b)
26245 (while (string-match org-maybe-keyword-time-regexp s)
26246 (if (and (match-end 1) (equal (match-string 1 s) org-clock-string))
26247 ;; never export CLOCK
26248 (throw 'exit ""))
26249 (or b (setq b (substring s 0 (match-beginning 0))))
26250 (if (not org-export-with-timestamps)
26251 (setq r (concat r (substring s 0 (match-beginning 0)))
26252 s (substring s (match-end 0)))
26253 (setq r (concat
26254 r (substring s 0 (match-beginning 0))
26255 (if (match-end 1)
26256 (format "@<span class=\"timestamp-kwd\">%s @</span>"
26257 (match-string 1 s)))
26258 (format " @<span class=\"timestamp\">%s@</span>"
26259 (substring
26260 (org-translate-time (match-string 3 s)) 1 -1)))
26261 s (substring s (match-end 0)))))
26262 ;; Line break if line started and ended with time stamp stuff
26263 (if (not r)
26265 (setq r (concat r s))
26266 (unless (string-match "\\S-" (concat b s))
26267 (setq r (concat r "@<br/>")))
26268 r))))
26270 (defun org-html-protect (s)
26271 ;; convert & to &amp;, < to &lt; and > to &gt;
26272 (let ((start 0))
26273 (while (string-match "&" s start)
26274 (setq s (replace-match "&amp;" t t s)
26275 start (1+ (match-beginning 0))))
26276 (while (string-match "<" s)
26277 (setq s (replace-match "&lt;" t t s)))
26278 (while (string-match ">" s)
26279 (setq s (replace-match "&gt;" t t s))))
26282 (defun org-export-cleanup-toc-line (s)
26283 "Remove tags and time staps from lines going into the toc."
26284 (when (memq org-export-with-tags '(not-in-toc nil))
26285 (if (string-match (org-re " +:[[:alnum:]_@:]+: *$") s)
26286 (setq s (replace-match "" t t s))))
26287 (when org-export-remove-timestamps-from-toc
26288 (while (string-match org-maybe-keyword-time-regexp s)
26289 (setq s (replace-match "" t t s))))
26290 (while (string-match org-bracket-link-regexp s)
26291 (setq s (replace-match (match-string (if (match-end 3) 3 1) s)
26292 t t s)))
26295 (defun org-html-expand (string)
26296 "Prepare STRING for HTML export. Applies all active conversions.
26297 If there are links in the string, don't modify these."
26298 (let* ((re (concat org-bracket-link-regexp "\\|"
26299 (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$")))
26300 m s l res)
26301 (while (setq m (string-match re string))
26302 (setq s (substring string 0 m)
26303 l (match-string 0 string)
26304 string (substring string (match-end 0)))
26305 (push (org-html-do-expand s) res)
26306 (push l res))
26307 (push (org-html-do-expand string) res)
26308 (apply 'concat (nreverse res))))
26310 (defun org-html-do-expand (s)
26311 "Apply all active conversions to translate special ASCII to HTML."
26312 (setq s (org-html-protect s))
26313 (if org-export-html-expand
26314 (let ((start 0))
26315 (while (string-match "@&lt;\\([^&]*\\)&gt;" s)
26316 (setq s (replace-match "<\\1>" t nil s)))))
26317 (if org-export-with-emphasize
26318 (setq s (org-export-html-convert-emphasize s)))
26319 (if org-export-with-special-strings
26320 (setq s (org-export-html-convert-special-strings s)))
26321 (if org-export-with-sub-superscripts
26322 (setq s (org-export-html-convert-sub-super s)))
26323 (if org-export-with-TeX-macros
26324 (let ((start 0) wd ass)
26325 (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)" s start))
26326 (if (get-text-property (match-beginning 0) 'org-protected s)
26327 (setq start (match-end 0))
26328 (setq wd (match-string 1 s))
26329 (if (setq ass (assoc wd org-html-entities))
26330 (setq s (replace-match (or (cdr ass)
26331 (concat "&" (car ass) ";"))
26332 t t s))
26333 (setq start (+ start (length wd))))))))
26336 (defun org-create-multibrace-regexp (left right n)
26337 "Create a regular expression which will match a balanced sexp.
26338 Opening delimiter is LEFT, and closing delimiter is RIGHT, both given
26339 as single character strings.
26340 The regexp returned will match the entire expression including the
26341 delimiters. It will also define a single group which contains the
26342 match except for the outermost delimiters. The maximum depth of
26343 stacked delimiters is N. Escaping delimiters is not possible."
26344 (let* ((nothing (concat "[^" "\\" left "\\" right "]*?"))
26345 (or "\\|")
26346 (re nothing)
26347 (next (concat "\\(?:" nothing left nothing right "\\)+" nothing)))
26348 (while (> n 1)
26349 (setq n (1- n)
26350 re (concat re or next)
26351 next (concat "\\(?:" nothing left next right "\\)+" nothing)))
26352 (concat left "\\(" re "\\)" right)))
26354 (defvar org-match-substring-regexp
26355 (concat
26356 "\\([^\\]\\)\\([_^]\\)\\("
26357 "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
26358 "\\|"
26359 "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
26360 "\\|"
26361 "\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
26362 "The regular expression matching a sub- or superscript.")
26364 (defvar org-match-substring-with-braces-regexp
26365 (concat
26366 "\\([^\\]\\)\\([_^]\\)\\("
26367 "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
26368 "\\)")
26369 "The regular expression matching a sub- or superscript, forcing braces.")
26371 (defconst org-export-html-special-string-regexps
26372 '(("\\\\-" . "&shy;")
26373 ("---\\([^-]\\)" . "&mdash;\\1")
26374 ("--\\([^-]\\)" . "&ndash;\\1")
26375 ("\\.\\.\\." . "&hellip;"))
26376 "Regular expressions for special string conversion.")
26378 (defun org-export-html-convert-special-strings (string)
26379 "Convert special characters in STRING to HTML."
26380 (let ((all org-export-html-special-string-regexps)
26381 e a re rpl start)
26382 (while (setq a (pop all))
26383 (setq re (car a) rpl (cdr a) start 0)
26384 (while (string-match re string start)
26385 (if (get-text-property (match-beginning 0) 'org-protected string)
26386 (setq start (match-end 0))
26387 (setq string (replace-match rpl t nil string)))))
26388 string))
26390 (defun org-export-html-convert-sub-super (string)
26391 "Convert sub- and superscripts in STRING to HTML."
26392 (let (key c (s 0) (requireb (eq org-export-with-sub-superscripts '{})))
26393 (while (string-match org-match-substring-regexp string s)
26394 (cond
26395 ((and requireb (match-end 8)) (setq s (match-end 2)))
26396 ((get-text-property (match-beginning 2) 'org-protected string)
26397 (setq s (match-end 2)))
26399 (setq s (match-end 1)
26400 key (if (string= (match-string 2 string) "_") "sub" "sup")
26401 c (or (match-string 8 string)
26402 (match-string 6 string)
26403 (match-string 5 string))
26404 string (replace-match
26405 (concat (match-string 1 string)
26406 "<" key ">" c "</" key ">")
26407 t t string)))))
26408 (while (string-match "\\\\\\([_^]\\)" string)
26409 (setq string (replace-match (match-string 1 string) t t string)))
26410 string))
26412 (defun org-export-html-convert-emphasize (string)
26413 "Apply emphasis."
26414 (let ((s 0) rpl)
26415 (while (string-match org-emph-re string s)
26416 (if (not (equal
26417 (substring string (match-beginning 3) (1+ (match-beginning 3)))
26418 (substring string (match-beginning 4) (1+ (match-beginning 4)))))
26419 (setq s (match-beginning 0)
26421 (concat
26422 (match-string 1 string)
26423 (nth 2 (assoc (match-string 3 string) org-emphasis-alist))
26424 (match-string 4 string)
26425 (nth 3 (assoc (match-string 3 string)
26426 org-emphasis-alist))
26427 (match-string 5 string))
26428 string (replace-match rpl t t string)
26429 s (+ s (- (length rpl) 2)))
26430 (setq s (1+ s))))
26431 string))
26433 (defvar org-par-open nil)
26434 (defun org-open-par ()
26435 "Insert <p>, but first close previous paragraph if any."
26436 (org-close-par-maybe)
26437 (insert "\n<p>")
26438 (setq org-par-open t))
26439 (defun org-close-par-maybe ()
26440 "Close paragraph if there is one open."
26441 (when org-par-open
26442 (insert "</p>")
26443 (setq org-par-open nil)))
26444 (defun org-close-li ()
26445 "Close <li> if necessary."
26446 (org-close-par-maybe)
26447 (insert "</li>\n"))
26449 (defvar body-only) ; dynamically scoped into this.
26450 (defun org-html-level-start (level title umax with-toc head-count)
26451 "Insert a new level in HTML export.
26452 When TITLE is nil, just close all open levels."
26453 (org-close-par-maybe)
26454 (let ((l org-level-max) snumber)
26455 (while (>= l level)
26456 (if (aref org-levels-open (1- l))
26457 (progn
26458 (org-html-level-close l umax)
26459 (aset org-levels-open (1- l) nil)))
26460 (setq l (1- l)))
26461 (when title
26462 ;; If title is nil, this means this function is called to close
26463 ;; all levels, so the rest is done only if title is given
26464 (when (string-match (org-re "\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
26465 (setq title (replace-match
26466 (if org-export-with-tags
26467 (save-match-data
26468 (concat
26469 "&nbsp;&nbsp;&nbsp;<span class=\"tag\">"
26470 (mapconcat 'identity (org-split-string
26471 (match-string 1 title) ":")
26472 "&nbsp;")
26473 "</span>"))
26475 t t title)))
26476 (if (> level umax)
26477 (progn
26478 (if (aref org-levels-open (1- level))
26479 (progn
26480 (org-close-li)
26481 (insert "<li>" title "<br/>\n"))
26482 (aset org-levels-open (1- level) t)
26483 (org-close-par-maybe)
26484 (insert "<ul>\n<li>" title "<br/>\n")))
26485 (aset org-levels-open (1- level) t)
26486 (setq snumber (org-section-number level))
26487 (if (and org-export-with-section-numbers (not body-only))
26488 (setq title (concat snumber " " title)))
26489 (setq level (+ level org-export-html-toplevel-hlevel -1))
26490 (unless (= head-count 1) (insert "\n</div>\n"))
26491 (insert (format "\n<div id=\"outline-container-%s\" class=\"outline-%d\">\n<h%d id=\"sec-%s\">%s</h%d>\n<div id=\"text-%s\">\n"
26492 snumber level level snumber title level snumber))
26493 (org-open-par)))))
26495 (defun org-html-level-close (level max-outline-level)
26496 "Terminate one level in HTML export."
26497 (if (<= level max-outline-level)
26498 (insert "</div>\n")
26499 (org-close-li)
26500 (insert "</ul>\n")))
26502 ;;; iCalendar export
26504 ;;;###autoload
26505 (defun org-export-icalendar-this-file ()
26506 "Export current file as an iCalendar file.
26507 The iCalendar file will be located in the same directory as the Org-mode
26508 file, but with extension `.ics'."
26509 (interactive)
26510 (org-export-icalendar nil buffer-file-name))
26512 ;;;###autoload
26513 (defun org-export-icalendar-all-agenda-files ()
26514 "Export all files in `org-agenda-files' to iCalendar .ics files.
26515 Each iCalendar file will be located in the same directory as the Org-mode
26516 file, but with extension `.ics'."
26517 (interactive)
26518 (apply 'org-export-icalendar nil (org-agenda-files t)))
26520 ;;;###autoload
26521 (defun org-export-icalendar-combine-agenda-files ()
26522 "Export all files in `org-agenda-files' to a single combined iCalendar file.
26523 The file is stored under the name `org-combined-agenda-icalendar-file'."
26524 (interactive)
26525 (apply 'org-export-icalendar t (org-agenda-files t)))
26527 (defun org-export-icalendar (combine &rest files)
26528 "Create iCalendar files for all elements of FILES.
26529 If COMBINE is non-nil, combine all calendar entries into a single large
26530 file and store it under the name `org-combined-agenda-icalendar-file'."
26531 (save-excursion
26532 (org-prepare-agenda-buffers files)
26533 (let* ((dir (org-export-directory
26534 :ical (list :publishing-directory
26535 org-export-publishing-directory)))
26536 file ical-file ical-buffer category started org-agenda-new-buffers)
26537 (and (get-buffer "*ical-tmp*") (kill-buffer "*ical-tmp*"))
26538 (when combine
26539 (setq ical-file
26540 (if (file-name-absolute-p org-combined-agenda-icalendar-file)
26541 org-combined-agenda-icalendar-file
26542 (expand-file-name org-combined-agenda-icalendar-file dir))
26543 ical-buffer (org-get-agenda-file-buffer ical-file))
26544 (set-buffer ical-buffer) (erase-buffer))
26545 (while (setq file (pop files))
26546 (catch 'nextfile
26547 (org-check-agenda-file file)
26548 (set-buffer (org-get-agenda-file-buffer file))
26549 (unless combine
26550 (setq ical-file (concat (file-name-as-directory dir)
26551 (file-name-sans-extension
26552 (file-name-nondirectory buffer-file-name))
26553 ".ics"))
26554 (setq ical-buffer (org-get-agenda-file-buffer ical-file))
26555 (with-current-buffer ical-buffer (erase-buffer)))
26556 (setq category (or org-category
26557 (file-name-sans-extension
26558 (file-name-nondirectory buffer-file-name))))
26559 (if (symbolp category) (setq category (symbol-name category)))
26560 (let ((standard-output ical-buffer))
26561 (if combine
26562 (and (not started) (setq started t)
26563 (org-start-icalendar-file org-icalendar-combined-name))
26564 (org-start-icalendar-file category))
26565 (org-print-icalendar-entries combine)
26566 (when (or (and combine (not files)) (not combine))
26567 (org-finish-icalendar-file)
26568 (set-buffer ical-buffer)
26569 (save-buffer)
26570 (run-hooks 'org-after-save-iCalendar-file-hook)))))
26571 (org-release-buffers org-agenda-new-buffers))))
26573 (defvar org-after-save-iCalendar-file-hook nil
26574 "Hook run after an iCalendar file has been saved.
26575 The iCalendar buffer is still current when this hook is run.
26576 A good way to use this is to tell a desktop calenndar application to re-read
26577 the iCalendar file.")
26579 (defun org-print-icalendar-entries (&optional combine)
26580 "Print iCalendar entries for the current Org-mode file to `standard-output'.
26581 When COMBINE is non nil, add the category to each line."
26582 (let ((re1 (concat org-ts-regexp "\\|<%%([^>\n]+>"))
26583 (re2 (concat "--?-?\\(" org-ts-regexp "\\)"))
26584 (dts (org-ical-ts-to-string
26585 (format-time-string (cdr org-time-stamp-formats) (current-time))
26586 "DTSTART"))
26587 hd ts ts2 state status (inc t) pos b sexp rrule
26588 scheduledp deadlinep tmp pri category entry location summary desc
26589 (sexp-buffer (get-buffer-create "*ical-tmp*")))
26590 (org-refresh-category-properties)
26591 (save-excursion
26592 (goto-char (point-min))
26593 (while (re-search-forward re1 nil t)
26594 (catch :skip
26595 (org-agenda-skip)
26596 (when (boundp 'org-icalendar-verify-function)
26597 (unless (funcall org-icalendar-verify-function)
26598 (outline-next-heading)
26599 (backward-char 1)
26600 (throw :skip nil)))
26601 (setq pos (match-beginning 0)
26602 ts (match-string 0)
26603 inc t
26604 hd (org-get-heading)
26605 summary (org-icalendar-cleanup-string
26606 (org-entry-get nil "SUMMARY"))
26607 desc (org-icalendar-cleanup-string
26608 (or (org-entry-get nil "DESCRIPTION")
26609 (and org-icalendar-include-body (org-get-entry)))
26610 t org-icalendar-include-body)
26611 location (org-icalendar-cleanup-string
26612 (org-entry-get nil "LOCATION"))
26613 category (org-get-category))
26614 (if (looking-at re2)
26615 (progn
26616 (goto-char (match-end 0))
26617 (setq ts2 (match-string 1) inc nil))
26618 (setq tmp (buffer-substring (max (point-min)
26619 (- pos org-ds-keyword-length))
26620 pos)
26621 ts2 (if (string-match "[0-9]\\{1,2\\}:[0-9][0-9]-\\([0-9]\\{1,2\\}:[0-9][0-9]\\)" ts)
26622 (progn
26623 (setq inc nil)
26624 (replace-match "\\1" t nil ts))
26626 deadlinep (string-match org-deadline-regexp tmp)
26627 scheduledp (string-match org-scheduled-regexp tmp)
26628 ;; donep (org-entry-is-done-p)
26630 (if (or (string-match org-tr-regexp hd)
26631 (string-match org-ts-regexp hd))
26632 (setq hd (replace-match "" t t hd)))
26633 (if (string-match "\\+\\([0-9]+\\)\\([dwmy]\\)>" ts)
26634 (setq rrule
26635 (concat "\nRRULE:FREQ="
26636 (cdr (assoc
26637 (match-string 2 ts)
26638 '(("d" . "DAILY")("w" . "WEEKLY")
26639 ("m" . "MONTHLY")("y" . "YEARLY"))))
26640 ";INTERVAL=" (match-string 1 ts)))
26641 (setq rrule ""))
26642 (setq summary (or summary hd))
26643 (if (string-match org-bracket-link-regexp summary)
26644 (setq summary
26645 (replace-match (if (match-end 3)
26646 (match-string 3 summary)
26647 (match-string 1 summary))
26648 t t summary)))
26649 (if deadlinep (setq summary (concat "DL: " summary)))
26650 (if scheduledp (setq summary (concat "S: " summary)))
26651 (if (string-match "\\`<%%" ts)
26652 (with-current-buffer sexp-buffer
26653 (insert (substring ts 1 -1) " " summary "\n"))
26654 (princ (format "BEGIN:VEVENT
26656 %s%s
26657 SUMMARY:%s%s%s
26658 CATEGORIES:%s
26659 END:VEVENT\n"
26660 (org-ical-ts-to-string ts "DTSTART")
26661 (org-ical-ts-to-string ts2 "DTEND" inc)
26662 rrule summary
26663 (if (and desc (string-match "\\S-" desc))
26664 (concat "\nDESCRIPTION: " desc) "")
26665 (if (and location (string-match "\\S-" location))
26666 (concat "\nLOCATION: " location) "")
26667 category)))))
26669 (when (and org-icalendar-include-sexps
26670 (condition-case nil (require 'icalendar) (error nil))
26671 (fboundp 'icalendar-export-region))
26672 ;; Get all the literal sexps
26673 (goto-char (point-min))
26674 (while (re-search-forward "^&?%%(" nil t)
26675 (catch :skip
26676 (org-agenda-skip)
26677 (setq b (match-beginning 0))
26678 (goto-char (1- (match-end 0)))
26679 (forward-sexp 1)
26680 (end-of-line 1)
26681 (setq sexp (buffer-substring b (point)))
26682 (with-current-buffer sexp-buffer
26683 (insert sexp "\n"))
26684 (princ (org-diary-to-ical-string sexp-buffer)))))
26686 (when org-icalendar-include-todo
26687 (goto-char (point-min))
26688 (while (re-search-forward org-todo-line-regexp nil t)
26689 (catch :skip
26690 (org-agenda-skip)
26691 (when (boundp 'org-icalendar-verify-function)
26692 (unless (funcall org-icalendar-verify-function)
26693 (outline-next-heading)
26694 (backward-char 1)
26695 (throw :skip nil)))
26696 (setq state (match-string 2))
26697 (setq status (if (member state org-done-keywords)
26698 "COMPLETED" "NEEDS-ACTION"))
26699 (when (and state
26700 (or (not (member state org-done-keywords))
26701 (eq org-icalendar-include-todo 'all))
26702 (not (member org-archive-tag (org-get-tags-at)))
26704 (setq hd (match-string 3)
26705 summary (org-icalendar-cleanup-string
26706 (org-entry-get nil "SUMMARY"))
26707 desc (org-icalendar-cleanup-string
26708 (or (org-entry-get nil "DESCRIPTION")
26709 (and org-icalendar-include-body (org-get-entry)))
26710 t org-icalendar-include-body)
26711 location (org-icalendar-cleanup-string
26712 (org-entry-get nil "LOCATION")))
26713 (if (string-match org-bracket-link-regexp hd)
26714 (setq hd (replace-match (if (match-end 3) (match-string 3 hd)
26715 (match-string 1 hd))
26716 t t hd)))
26717 (if (string-match org-priority-regexp hd)
26718 (setq pri (string-to-char (match-string 2 hd))
26719 hd (concat (substring hd 0 (match-beginning 1))
26720 (substring hd (match-end 1))))
26721 (setq pri org-default-priority))
26722 (setq pri (floor (1+ (* 8. (/ (float (- org-lowest-priority pri))
26723 (- org-lowest-priority org-highest-priority))))))
26725 (princ (format "BEGIN:VTODO
26727 SUMMARY:%s%s%s
26728 CATEGORIES:%s
26729 SEQUENCE:1
26730 PRIORITY:%d
26731 STATUS:%s
26732 END:VTODO\n"
26734 (or summary hd)
26735 (if (and location (string-match "\\S-" location))
26736 (concat "\nLOCATION: " location) "")
26737 (if (and desc (string-match "\\S-" desc))
26738 (concat "\nDESCRIPTION: " desc) "")
26739 category pri status)))))))))
26741 (defun org-icalendar-cleanup-string (s &optional is-body maxlength)
26742 "Take out stuff and quote what needs to be quoted.
26743 When IS-BODY is non-nil, assume that this is the body of an item, clean up
26744 whitespace, newlines, drawers, and timestamps, and cut it down to MAXLENGTH
26745 characters."
26746 (if (not s)
26748 (when is-body
26749 (let ((re (concat "\\(" org-drawer-regexp "\\)[^\000]*?:END:.*\n?"))
26750 (re2 (concat "^[ \t]*" org-keyword-time-regexp ".*\n?")))
26751 (while (string-match re s) (setq s (replace-match "" t t s)))
26752 (while (string-match re2 s) (setq s (replace-match "" t t s)))))
26753 (let ((start 0))
26754 (while (string-match "\\([,;\\]\\)" s start)
26755 (setq start (+ (match-beginning 0) 2)
26756 s (replace-match "\\\\\\1" nil nil s))))
26757 (when is-body
26758 (while (string-match "[ \t]*\n[ \t]*" s)
26759 (setq s (replace-match "\\n" t t s))))
26760 (setq s (org-trim s))
26761 (if is-body
26762 (if maxlength
26763 (if (and (numberp maxlength)
26764 (> (length s) maxlength))
26765 (setq s (substring s 0 maxlength)))))
26768 (defun org-get-entry ()
26769 "Clean-up description string."
26770 (save-excursion
26771 (org-back-to-heading t)
26772 (buffer-substring (point-at-bol 2) (org-end-of-subtree t))))
26774 (defun org-start-icalendar-file (name)
26775 "Start an iCalendar file by inserting the header."
26776 (let ((user user-full-name)
26777 (name (or name "unknown"))
26778 (timezone (cadr (current-time-zone))))
26779 (princ
26780 (format "BEGIN:VCALENDAR
26781 VERSION:2.0
26782 X-WR-CALNAME:%s
26783 PRODID:-//%s//Emacs with Org-mode//EN
26784 X-WR-TIMEZONE:%s
26785 CALSCALE:GREGORIAN\n" name user timezone))))
26787 (defun org-finish-icalendar-file ()
26788 "Finish an iCalendar file by inserting the END statement."
26789 (princ "END:VCALENDAR\n"))
26791 (defun org-ical-ts-to-string (s keyword &optional inc)
26792 "Take a time string S and convert it to iCalendar format.
26793 KEYWORD is added in front, to make a complete line like DTSTART....
26794 When INC is non-nil, increase the hour by two (if time string contains
26795 a time), or the day by one (if it does not contain a time)."
26796 (let ((t1 (org-parse-time-string s 'nodefault))
26797 t2 fmt have-time time)
26798 (if (and (car t1) (nth 1 t1) (nth 2 t1))
26799 (setq t2 t1 have-time t)
26800 (setq t2 (org-parse-time-string s)))
26801 (let ((s (car t2)) (mi (nth 1 t2)) (h (nth 2 t2))
26802 (d (nth 3 t2)) (m (nth 4 t2)) (y (nth 5 t2)))
26803 (when inc
26804 (if have-time
26805 (if org-agenda-default-appointment-duration
26806 (setq mi (+ org-agenda-default-appointment-duration mi))
26807 (setq h (+ 2 h)))
26808 (setq d (1+ d))))
26809 (setq time (encode-time s mi h d m y)))
26810 (setq fmt (if have-time ":%Y%m%dT%H%M%S" ";VALUE=DATE:%Y%m%d"))
26811 (concat keyword (format-time-string fmt time))))
26813 ;;; XOXO export
26815 (defun org-export-as-xoxo-insert-into (buffer &rest output)
26816 (with-current-buffer buffer
26817 (apply 'insert output)))
26818 (put 'org-export-as-xoxo-insert-into 'lisp-indent-function 1)
26820 (defun org-export-as-xoxo (&optional buffer)
26821 "Export the org buffer as XOXO.
26822 The XOXO buffer is named *xoxo-<source buffer name>*"
26823 (interactive (list (current-buffer)))
26824 ;; A quickie abstraction
26826 ;; Output everything as XOXO
26827 (with-current-buffer (get-buffer buffer)
26828 (let* ((pos (point))
26829 (opt-plist (org-combine-plists (org-default-export-plist)
26830 (org-infile-export-plist)))
26831 (filename (concat (file-name-as-directory
26832 (org-export-directory :xoxo opt-plist))
26833 (file-name-sans-extension
26834 (file-name-nondirectory buffer-file-name))
26835 ".html"))
26836 (out (find-file-noselect filename))
26837 (last-level 1)
26838 (hanging-li nil))
26839 (goto-char (point-min)) ;; CD: beginning-of-buffer is not allowed.
26840 ;; Check the output buffer is empty.
26841 (with-current-buffer out (erase-buffer))
26842 ;; Kick off the output
26843 (org-export-as-xoxo-insert-into out "<ol class='xoxo'>\n")
26844 (while (re-search-forward "^\\(\\*+\\)[ \t]+\\(.+\\)" (point-max) 't)
26845 (let* ((hd (match-string-no-properties 1))
26846 (level (length hd))
26847 (text (concat
26848 (match-string-no-properties 2)
26849 (save-excursion
26850 (goto-char (match-end 0))
26851 (let ((str ""))
26852 (catch 'loop
26853 (while 't
26854 (forward-line)
26855 (if (looking-at "^[ \t]\\(.*\\)")
26856 (setq str (concat str (match-string-no-properties 1)))
26857 (throw 'loop str)))))))))
26859 ;; Handle level rendering
26860 (cond
26861 ((> level last-level)
26862 (org-export-as-xoxo-insert-into out "\n<ol>\n"))
26864 ((< level last-level)
26865 (dotimes (- (- last-level level) 1)
26866 (if hanging-li
26867 (org-export-as-xoxo-insert-into out "</li>\n"))
26868 (org-export-as-xoxo-insert-into out "</ol>\n"))
26869 (when hanging-li
26870 (org-export-as-xoxo-insert-into out "</li>\n")
26871 (setq hanging-li nil)))
26873 ((equal level last-level)
26874 (if hanging-li
26875 (org-export-as-xoxo-insert-into out "</li>\n")))
26878 (setq last-level level)
26880 ;; And output the new li
26881 (setq hanging-li 't)
26882 (if (equal ?+ (elt text 0))
26883 (org-export-as-xoxo-insert-into out "<li class='" (substring text 1) "'>")
26884 (org-export-as-xoxo-insert-into out "<li>" text))))
26886 ;; Finally finish off the ol
26887 (dotimes (- last-level 1)
26888 (if hanging-li
26889 (org-export-as-xoxo-insert-into out "</li>\n"))
26890 (org-export-as-xoxo-insert-into out "</ol>\n"))
26892 (goto-char pos)
26893 ;; Finish the buffer off and clean it up.
26894 (switch-to-buffer-other-window out)
26895 (indent-region (point-min) (point-max) nil)
26896 (save-buffer)
26897 (goto-char (point-min))
26901 ;;;; Key bindings
26903 ;; Make `C-c C-x' a prefix key
26904 (org-defkey org-mode-map "\C-c\C-x" (make-sparse-keymap))
26906 ;; TAB key with modifiers
26907 (org-defkey org-mode-map "\C-i" 'org-cycle)
26908 (org-defkey org-mode-map [(tab)] 'org-cycle)
26909 (org-defkey org-mode-map [(control tab)] 'org-force-cycle-archived)
26910 (org-defkey org-mode-map [(meta tab)] 'org-complete)
26911 (org-defkey org-mode-map "\M-\t" 'org-complete)
26912 (org-defkey org-mode-map "\M-\C-i" 'org-complete)
26913 ;; The following line is necessary under Suse GNU/Linux
26914 (unless (featurep 'xemacs)
26915 (org-defkey org-mode-map [S-iso-lefttab] 'org-shifttab))
26916 (org-defkey org-mode-map [(shift tab)] 'org-shifttab)
26917 (define-key org-mode-map [backtab] 'org-shifttab)
26919 (org-defkey org-mode-map [(shift return)] 'org-table-copy-down)
26920 (org-defkey org-mode-map [(meta shift return)] 'org-insert-todo-heading)
26921 (org-defkey org-mode-map [(meta return)] 'org-meta-return)
26923 ;; Cursor keys with modifiers
26924 (org-defkey org-mode-map [(meta left)] 'org-metaleft)
26925 (org-defkey org-mode-map [(meta right)] 'org-metaright)
26926 (org-defkey org-mode-map [(meta up)] 'org-metaup)
26927 (org-defkey org-mode-map [(meta down)] 'org-metadown)
26929 (org-defkey org-mode-map [(meta shift left)] 'org-shiftmetaleft)
26930 (org-defkey org-mode-map [(meta shift right)] 'org-shiftmetaright)
26931 (org-defkey org-mode-map [(meta shift up)] 'org-shiftmetaup)
26932 (org-defkey org-mode-map [(meta shift down)] 'org-shiftmetadown)
26934 (org-defkey org-mode-map [(shift up)] 'org-shiftup)
26935 (org-defkey org-mode-map [(shift down)] 'org-shiftdown)
26936 (org-defkey org-mode-map [(shift left)] 'org-shiftleft)
26937 (org-defkey org-mode-map [(shift right)] 'org-shiftright)
26939 (org-defkey org-mode-map [(control shift right)] 'org-shiftcontrolright)
26940 (org-defkey org-mode-map [(control shift left)] 'org-shiftcontrolleft)
26942 ;;; Extra keys for tty access.
26943 ;; We only set them when really needed because otherwise the
26944 ;; menus don't show the simple keys
26946 (when (or (featurep 'xemacs) ;; because XEmacs supports multi-device stuff
26947 (not window-system))
26948 (org-defkey org-mode-map "\C-c\C-xc" 'org-table-copy-down)
26949 (org-defkey org-mode-map "\C-c\C-xM" 'org-insert-todo-heading)
26950 (org-defkey org-mode-map "\C-c\C-xm" 'org-meta-return)
26951 (org-defkey org-mode-map [?\e (return)] 'org-meta-return)
26952 (org-defkey org-mode-map [?\e (left)] 'org-metaleft)
26953 (org-defkey org-mode-map "\C-c\C-xl" 'org-metaleft)
26954 (org-defkey org-mode-map [?\e (right)] 'org-metaright)
26955 (org-defkey org-mode-map "\C-c\C-xr" 'org-metaright)
26956 (org-defkey org-mode-map [?\e (up)] 'org-metaup)
26957 (org-defkey org-mode-map "\C-c\C-xu" 'org-metaup)
26958 (org-defkey org-mode-map [?\e (down)] 'org-metadown)
26959 (org-defkey org-mode-map "\C-c\C-xd" 'org-metadown)
26960 (org-defkey org-mode-map "\C-c\C-xL" 'org-shiftmetaleft)
26961 (org-defkey org-mode-map "\C-c\C-xR" 'org-shiftmetaright)
26962 (org-defkey org-mode-map "\C-c\C-xU" 'org-shiftmetaup)
26963 (org-defkey org-mode-map "\C-c\C-xD" 'org-shiftmetadown)
26964 (org-defkey org-mode-map [?\C-c (up)] 'org-shiftup)
26965 (org-defkey org-mode-map [?\C-c (down)] 'org-shiftdown)
26966 (org-defkey org-mode-map [?\C-c (left)] 'org-shiftleft)
26967 (org-defkey org-mode-map [?\C-c (right)] 'org-shiftright)
26968 (org-defkey org-mode-map [?\C-c ?\C-x (right)] 'org-shiftcontrolright)
26969 (org-defkey org-mode-map [?\C-c ?\C-x (left)] 'org-shiftcontrolleft))
26971 ;; All the other keys
26973 (org-defkey org-mode-map "\C-c\C-a" 'show-all) ; in case allout messed up.
26974 (org-defkey org-mode-map "\C-c\C-r" 'org-reveal)
26975 (org-defkey org-mode-map "\C-xns" 'org-narrow-to-subtree)
26976 (org-defkey org-mode-map "\C-c$" 'org-archive-subtree)
26977 (org-defkey org-mode-map "\C-c\C-x\C-s" 'org-advertized-archive-subtree)
26978 (org-defkey org-mode-map "\C-c\C-x\C-a" 'org-toggle-archive-tag)
26979 (org-defkey org-mode-map "\C-c\C-xb" 'org-tree-to-indirect-buffer)
26980 (org-defkey org-mode-map "\C-c\C-j" 'org-goto)
26981 (org-defkey org-mode-map "\C-c\C-t" 'org-todo)
26982 (org-defkey org-mode-map "\C-c\C-s" 'org-schedule)
26983 (org-defkey org-mode-map "\C-c\C-d" 'org-deadline)
26984 (org-defkey org-mode-map "\C-c;" 'org-toggle-comment)
26985 (org-defkey org-mode-map "\C-c\C-v" 'org-show-todo-tree)
26986 (org-defkey org-mode-map "\C-c\C-w" 'org-refile)
26987 (org-defkey org-mode-map "\C-c/" 'org-sparse-tree) ; Minor-mode reserved
26988 (org-defkey org-mode-map "\C-c\\" 'org-tags-sparse-tree) ; Minor-mode res.
26989 (org-defkey org-mode-map "\C-c\C-m" 'org-ctrl-c-ret)
26990 (org-defkey org-mode-map "\M-\C-m" 'org-insert-heading)
26991 (org-defkey org-mode-map [(control return)] 'org-insert-heading-after-current)
26992 (org-defkey org-mode-map "\C-c\C-x\C-n" 'org-next-link)
26993 (org-defkey org-mode-map "\C-c\C-x\C-p" 'org-previous-link)
26994 (org-defkey org-mode-map "\C-c\C-l" 'org-insert-link)
26995 (org-defkey org-mode-map "\C-c\C-o" 'org-open-at-point)
26996 (org-defkey org-mode-map "\C-c%" 'org-mark-ring-push)
26997 (org-defkey org-mode-map "\C-c&" 'org-mark-ring-goto)
26998 (org-defkey org-mode-map "\C-c\C-z" 'org-time-stamp) ; Alternative binding
26999 (org-defkey org-mode-map "\C-c." 'org-time-stamp) ; Minor-mode reserved
27000 (org-defkey org-mode-map "\C-c!" 'org-time-stamp-inactive) ; Minor-mode r.
27001 (org-defkey org-mode-map "\C-c," 'org-priority) ; Minor-mode reserved
27002 (org-defkey org-mode-map "\C-c\C-y" 'org-evaluate-time-range)
27003 (org-defkey org-mode-map "\C-c>" 'org-goto-calendar)
27004 (org-defkey org-mode-map "\C-c<" 'org-date-from-calendar)
27005 (org-defkey org-mode-map [(control ?,)] 'org-cycle-agenda-files)
27006 (org-defkey org-mode-map [(control ?\')] 'org-cycle-agenda-files)
27007 (org-defkey org-mode-map "\C-c[" 'org-agenda-file-to-front)
27008 (org-defkey org-mode-map "\C-c]" 'org-remove-file)
27009 (org-defkey org-mode-map "\C-c\C-x<" 'org-agenda-set-restriction-lock)
27010 (org-defkey org-mode-map "\C-c\C-x>" 'org-agenda-remove-restriction-lock)
27011 (org-defkey org-mode-map "\C-c-" 'org-ctrl-c-minus)
27012 (org-defkey org-mode-map "\C-c*" 'org-ctrl-c-star)
27013 (org-defkey org-mode-map "\C-c^" 'org-sort)
27014 (org-defkey org-mode-map "\C-c\C-c" 'org-ctrl-c-ctrl-c)
27015 (org-defkey org-mode-map "\C-c\C-k" 'org-kill-note-or-show-branches)
27016 (org-defkey org-mode-map "\C-c#" 'org-update-checkbox-count)
27017 (org-defkey org-mode-map "\C-m" 'org-return)
27018 (org-defkey org-mode-map "\C-j" 'org-return-indent)
27019 (org-defkey org-mode-map "\C-c?" 'org-table-field-info)
27020 (org-defkey org-mode-map "\C-c " 'org-table-blank-field)
27021 (org-defkey org-mode-map "\C-c+" 'org-table-sum)
27022 (org-defkey org-mode-map "\C-c=" 'org-table-eval-formula)
27023 (org-defkey org-mode-map "\C-c'" 'org-table-edit-formulas)
27024 (org-defkey org-mode-map "\C-c`" 'org-table-edit-field)
27025 (org-defkey org-mode-map "\C-c|" 'org-table-create-or-convert-from-region)
27026 (org-defkey org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks)
27027 (org-defkey org-mode-map "\C-c~" 'org-table-create-with-table.el)
27028 (org-defkey org-mode-map "\C-c\C-q" 'org-table-wrap-region)
27029 (org-defkey org-mode-map "\C-c}" 'org-table-toggle-coordinate-overlays)
27030 (org-defkey org-mode-map "\C-c{" 'org-table-toggle-formula-debugger)
27031 (org-defkey org-mode-map "\C-c\C-e" 'org-export)
27032 (org-defkey org-mode-map "\C-c:" 'org-toggle-fixed-width-section)
27033 (org-defkey org-mode-map "\C-c\C-x\C-f" 'org-emphasize)
27035 (org-defkey org-mode-map "\C-c\C-x\C-k" 'org-cut-special)
27036 (org-defkey org-mode-map "\C-c\C-x\C-w" 'org-cut-special)
27037 (org-defkey org-mode-map "\C-c\C-x\M-w" 'org-copy-special)
27038 (org-defkey org-mode-map "\C-c\C-x\C-y" 'org-paste-special)
27040 (org-defkey org-mode-map "\C-c\C-x\C-t" 'org-toggle-time-stamp-overlays)
27041 (org-defkey org-mode-map "\C-c\C-x\C-i" 'org-clock-in)
27042 (org-defkey org-mode-map "\C-c\C-x\C-o" 'org-clock-out)
27043 (org-defkey org-mode-map "\C-c\C-x\C-j" 'org-clock-goto)
27044 (org-defkey org-mode-map "\C-c\C-x\C-x" 'org-clock-cancel)
27045 (org-defkey org-mode-map "\C-c\C-x\C-d" 'org-clock-display)
27046 (org-defkey org-mode-map "\C-c\C-x\C-r" 'org-clock-report)
27047 (org-defkey org-mode-map "\C-c\C-x\C-u" 'org-dblock-update)
27048 (org-defkey org-mode-map "\C-c\C-x\C-l" 'org-preview-latex-fragment)
27049 (org-defkey org-mode-map "\C-c\C-x\C-b" 'org-toggle-checkbox)
27050 (org-defkey org-mode-map "\C-c\C-xp" 'org-set-property)
27051 (org-defkey org-mode-map "\C-c\C-xr" 'org-insert-columns-dblock)
27053 (define-key org-mode-map "\C-c\C-x\C-c" 'org-columns)
27055 (when (featurep 'xemacs)
27056 (org-defkey org-mode-map 'button3 'popup-mode-menu))
27058 (defsubst org-table-p () (org-at-table-p))
27060 (defun org-self-insert-command (N)
27061 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
27062 If the cursor is in a table looking at whitespace, the whitespace is
27063 overwritten, and the table is not marked as requiring realignment."
27064 (interactive "p")
27065 (if (and (org-table-p)
27066 (progn
27067 ;; check if we blank the field, and if that triggers align
27068 (and org-table-auto-blank-field
27069 (member last-command
27070 '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c))
27071 (if (or (equal (char-after) ?\ ) (looking-at "[^|\n]* |"))
27072 ;; got extra space, this field does not determine column width
27073 (let (org-table-may-need-update) (org-table-blank-field))
27074 ;; no extra space, this field may determine column width
27075 (org-table-blank-field)))
27077 (eq N 1)
27078 (looking-at "[^|\n]* |"))
27079 (let (org-table-may-need-update)
27080 (goto-char (1- (match-end 0)))
27081 (delete-backward-char 1)
27082 (goto-char (match-beginning 0))
27083 (self-insert-command N))
27084 (setq org-table-may-need-update t)
27085 (self-insert-command N)
27086 (org-fix-tags-on-the-fly)))
27088 (defun org-fix-tags-on-the-fly ()
27089 (when (and (equal (char-after (point-at-bol)) ?*)
27090 (org-on-heading-p))
27091 (org-align-tags-here org-tags-column)))
27093 (defun org-delete-backward-char (N)
27094 "Like `delete-backward-char', insert whitespace at field end in tables.
27095 When deleting backwards, in tables this function will insert whitespace in
27096 front of the next \"|\" separator, to keep the table aligned. The table will
27097 still be marked for re-alignment if the field did fill the entire column,
27098 because, in this case the deletion might narrow the column."
27099 (interactive "p")
27100 (if (and (org-table-p)
27101 (eq N 1)
27102 (string-match "|" (buffer-substring (point-at-bol) (point)))
27103 (looking-at ".*?|"))
27104 (let ((pos (point))
27105 (noalign (looking-at "[^|\n\r]* |"))
27106 (c org-table-may-need-update))
27107 (backward-delete-char N)
27108 (skip-chars-forward "^|")
27109 (insert " ")
27110 (goto-char (1- pos))
27111 ;; noalign: if there were two spaces at the end, this field
27112 ;; does not determine the width of the column.
27113 (if noalign (setq org-table-may-need-update c)))
27114 (backward-delete-char N)
27115 (org-fix-tags-on-the-fly)))
27117 (defun org-delete-char (N)
27118 "Like `delete-char', but insert whitespace at field end in tables.
27119 When deleting characters, in tables this function will insert whitespace in
27120 front of the next \"|\" separator, to keep the table aligned. The table will
27121 still be marked for re-alignment if the field did fill the entire column,
27122 because, in this case the deletion might narrow the column."
27123 (interactive "p")
27124 (if (and (org-table-p)
27125 (not (bolp))
27126 (not (= (char-after) ?|))
27127 (eq N 1))
27128 (if (looking-at ".*?|")
27129 (let ((pos (point))
27130 (noalign (looking-at "[^|\n\r]* |"))
27131 (c org-table-may-need-update))
27132 (replace-match (concat
27133 (substring (match-string 0) 1 -1)
27134 " |"))
27135 (goto-char pos)
27136 ;; noalign: if there were two spaces at the end, this field
27137 ;; does not determine the width of the column.
27138 (if noalign (setq org-table-may-need-update c)))
27139 (delete-char N))
27140 (delete-char N)
27141 (org-fix-tags-on-the-fly)))
27143 ;; Make `delete-selection-mode' work with org-mode and orgtbl-mode
27144 (put 'org-self-insert-command 'delete-selection t)
27145 (put 'orgtbl-self-insert-command 'delete-selection t)
27146 (put 'org-delete-char 'delete-selection 'supersede)
27147 (put 'org-delete-backward-char 'delete-selection 'supersede)
27149 ;; Make `flyspell-mode' delay after some commands
27150 (put 'org-self-insert-command 'flyspell-delayed t)
27151 (put 'orgtbl-self-insert-command 'flyspell-delayed t)
27152 (put 'org-delete-char 'flyspell-delayed t)
27153 (put 'org-delete-backward-char 'flyspell-delayed t)
27155 ;; Make pabbrev-mode expand after org-mode commands
27156 (put 'org-self-insert-command 'pabbrev-expand-after-command t)
27157 (put 'orgybl-self-insert-command 'pabbrev-expand-after-command t)
27159 ;; How to do this: Measure non-white length of current string
27160 ;; If equal to column width, we should realign.
27162 (defun org-remap (map &rest commands)
27163 "In MAP, remap the functions given in COMMANDS.
27164 COMMANDS is a list of alternating OLDDEF NEWDEF command names."
27165 (let (new old)
27166 (while commands
27167 (setq old (pop commands) new (pop commands))
27168 (if (fboundp 'command-remapping)
27169 (org-defkey map (vector 'remap old) new)
27170 (substitute-key-definition old new map global-map)))))
27172 (when (eq org-enable-table-editor 'optimized)
27173 ;; If the user wants maximum table support, we need to hijack
27174 ;; some standard editing functions
27175 (org-remap org-mode-map
27176 'self-insert-command 'org-self-insert-command
27177 'delete-char 'org-delete-char
27178 'delete-backward-char 'org-delete-backward-char)
27179 (org-defkey org-mode-map "|" 'org-force-self-insert))
27181 (defun org-shiftcursor-error ()
27182 "Throw an error because Shift-Cursor command was applied in wrong context."
27183 (error "This command is active in special context like tables, headlines or timestamps"))
27185 (defun org-shifttab (&optional arg)
27186 "Global visibility cycling or move to previous table field.
27187 Calls `org-cycle' with argument t, or `org-table-previous-field', depending
27188 on context.
27189 See the individual commands for more information."
27190 (interactive "P")
27191 (cond
27192 ((org-at-table-p) (call-interactively 'org-table-previous-field))
27193 (arg (message "Content view to level: ")
27194 (org-content (prefix-numeric-value arg))
27195 (setq org-cycle-global-status 'overview))
27196 (t (call-interactively 'org-global-cycle))))
27198 (defun org-shiftmetaleft ()
27199 "Promote subtree or delete table column.
27200 Calls `org-promote-subtree', `org-outdent-item',
27201 or `org-table-delete-column', depending on context.
27202 See the individual commands for more information."
27203 (interactive)
27204 (cond
27205 ((org-at-table-p) (call-interactively 'org-table-delete-column))
27206 ((org-on-heading-p) (call-interactively 'org-promote-subtree))
27207 ((org-at-item-p) (call-interactively 'org-outdent-item))
27208 (t (org-shiftcursor-error))))
27210 (defun org-shiftmetaright ()
27211 "Demote subtree or insert table column.
27212 Calls `org-demote-subtree', `org-indent-item',
27213 or `org-table-insert-column', depending on context.
27214 See the individual commands for more information."
27215 (interactive)
27216 (cond
27217 ((org-at-table-p) (call-interactively 'org-table-insert-column))
27218 ((org-on-heading-p) (call-interactively 'org-demote-subtree))
27219 ((org-at-item-p) (call-interactively 'org-indent-item))
27220 (t (org-shiftcursor-error))))
27222 (defun org-shiftmetaup (&optional arg)
27223 "Move subtree up or kill table row.
27224 Calls `org-move-subtree-up' or `org-table-kill-row' or
27225 `org-move-item-up' depending on context. See the individual commands
27226 for more information."
27227 (interactive "P")
27228 (cond
27229 ((org-at-table-p) (call-interactively 'org-table-kill-row))
27230 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
27231 ((org-at-item-p) (call-interactively 'org-move-item-up))
27232 (t (org-shiftcursor-error))))
27233 (defun org-shiftmetadown (&optional arg)
27234 "Move subtree down or insert table row.
27235 Calls `org-move-subtree-down' or `org-table-insert-row' or
27236 `org-move-item-down', depending on context. See the individual
27237 commands for more information."
27238 (interactive "P")
27239 (cond
27240 ((org-at-table-p) (call-interactively 'org-table-insert-row))
27241 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
27242 ((org-at-item-p) (call-interactively 'org-move-item-down))
27243 (t (org-shiftcursor-error))))
27245 (defun org-metaleft (&optional arg)
27246 "Promote heading or move table column to left.
27247 Calls `org-do-promote' or `org-table-move-column', depending on context.
27248 With no specific context, calls the Emacs default `backward-word'.
27249 See the individual commands for more information."
27250 (interactive "P")
27251 (cond
27252 ((org-at-table-p) (org-call-with-arg 'org-table-move-column 'left))
27253 ((or (org-on-heading-p) (org-region-active-p))
27254 (call-interactively 'org-do-promote))
27255 ((org-at-item-p) (call-interactively 'org-outdent-item))
27256 (t (call-interactively 'backward-word))))
27258 (defun org-metaright (&optional arg)
27259 "Demote subtree or move table column to right.
27260 Calls `org-do-demote' or `org-table-move-column', depending on context.
27261 With no specific context, calls the Emacs default `forward-word'.
27262 See the individual commands for more information."
27263 (interactive "P")
27264 (cond
27265 ((org-at-table-p) (call-interactively 'org-table-move-column))
27266 ((or (org-on-heading-p) (org-region-active-p))
27267 (call-interactively 'org-do-demote))
27268 ((org-at-item-p) (call-interactively 'org-indent-item))
27269 (t (call-interactively 'forward-word))))
27271 (defun org-metaup (&optional arg)
27272 "Move subtree up or move table row up.
27273 Calls `org-move-subtree-up' or `org-table-move-row' or
27274 `org-move-item-up', depending on context. See the individual commands
27275 for more information."
27276 (interactive "P")
27277 (cond
27278 ((org-at-table-p) (org-call-with-arg 'org-table-move-row 'up))
27279 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
27280 ((org-at-item-p) (call-interactively 'org-move-item-up))
27281 (t (transpose-lines 1) (beginning-of-line -1))))
27283 (defun org-metadown (&optional arg)
27284 "Move subtree down or move table row down.
27285 Calls `org-move-subtree-down' or `org-table-move-row' or
27286 `org-move-item-down', depending on context. See the individual
27287 commands for more information."
27288 (interactive "P")
27289 (cond
27290 ((org-at-table-p) (call-interactively 'org-table-move-row))
27291 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
27292 ((org-at-item-p) (call-interactively 'org-move-item-down))
27293 (t (beginning-of-line 2) (transpose-lines 1) (beginning-of-line 0))))
27295 (defun org-shiftup (&optional arg)
27296 "Increase item in timestamp or increase priority of current headline.
27297 Calls `org-timestamp-up' or `org-priority-up', or `org-previous-item',
27298 depending on context. See the individual commands for more information."
27299 (interactive "P")
27300 (cond
27301 ((org-at-timestamp-p t)
27302 (call-interactively (if org-edit-timestamp-down-means-later
27303 'org-timestamp-down 'org-timestamp-up)))
27304 ((org-on-heading-p) (call-interactively 'org-priority-up))
27305 ((org-at-item-p) (call-interactively 'org-previous-item))
27306 (t (call-interactively 'org-beginning-of-item) (beginning-of-line 1))))
27308 (defun org-shiftdown (&optional arg)
27309 "Decrease item in timestamp or decrease priority of current headline.
27310 Calls `org-timestamp-down' or `org-priority-down', or `org-next-item'
27311 depending on context. See the individual commands for more information."
27312 (interactive "P")
27313 (cond
27314 ((org-at-timestamp-p t)
27315 (call-interactively (if org-edit-timestamp-down-means-later
27316 'org-timestamp-up 'org-timestamp-down)))
27317 ((org-on-heading-p) (call-interactively 'org-priority-down))
27318 (t (call-interactively 'org-next-item))))
27320 (defun org-shiftright ()
27321 "Next TODO keyword or timestamp one day later, depending on context."
27322 (interactive)
27323 (cond
27324 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-up-day))
27325 ((org-on-heading-p) (org-call-with-arg 'org-todo 'right))
27326 ((org-at-item-p) (org-call-with-arg 'org-cycle-list-bullet nil))
27327 ((org-at-property-p) (call-interactively 'org-property-next-allowed-value))
27328 (t (org-shiftcursor-error))))
27330 (defun org-shiftleft ()
27331 "Previous TODO keyword or timestamp one day earlier, depending on context."
27332 (interactive)
27333 (cond
27334 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-down-day))
27335 ((org-on-heading-p) (org-call-with-arg 'org-todo 'left))
27336 ((org-at-item-p) (org-call-with-arg 'org-cycle-list-bullet 'previous))
27337 ((org-at-property-p)
27338 (call-interactively 'org-property-previous-allowed-value))
27339 (t (org-shiftcursor-error))))
27341 (defun org-shiftcontrolright ()
27342 "Switch to next TODO set."
27343 (interactive)
27344 (cond
27345 ((org-on-heading-p) (org-call-with-arg 'org-todo 'nextset))
27346 (t (org-shiftcursor-error))))
27348 (defun org-shiftcontrolleft ()
27349 "Switch to previous TODO set."
27350 (interactive)
27351 (cond
27352 ((org-on-heading-p) (org-call-with-arg 'org-todo 'previousset))
27353 (t (org-shiftcursor-error))))
27355 (defun org-ctrl-c-ret ()
27356 "Call `org-table-hline-and-move' or `org-insert-heading' dep. on context."
27357 (interactive)
27358 (cond
27359 ((org-at-table-p) (call-interactively 'org-table-hline-and-move))
27360 (t (call-interactively 'org-insert-heading))))
27362 (defun org-copy-special ()
27363 "Copy region in table or copy current subtree.
27364 Calls `org-table-copy' or `org-copy-subtree', depending on context.
27365 See the individual commands for more information."
27366 (interactive)
27367 (call-interactively
27368 (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree)))
27370 (defun org-cut-special ()
27371 "Cut region in table or cut current subtree.
27372 Calls `org-table-copy' or `org-cut-subtree', depending on context.
27373 See the individual commands for more information."
27374 (interactive)
27375 (call-interactively
27376 (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree)))
27378 (defun org-paste-special (arg)
27379 "Paste rectangular region into table, or past subtree relative to level.
27380 Calls `org-table-paste-rectangle' or `org-paste-subtree', depending on context.
27381 See the individual commands for more information."
27382 (interactive "P")
27383 (if (org-at-table-p)
27384 (org-table-paste-rectangle)
27385 (org-paste-subtree arg)))
27387 (defun org-ctrl-c-ctrl-c (&optional arg)
27388 "Set tags in headline, or update according to changed information at point.
27390 This command does many different things, depending on context:
27392 - If the cursor is in a headline, prompt for tags and insert them
27393 into the current line, aligned to `org-tags-column'. When called
27394 with prefix arg, realign all tags in the current buffer.
27396 - If the cursor is in one of the special #+KEYWORD lines, this
27397 triggers scanning the buffer for these lines and updating the
27398 information.
27400 - If the cursor is inside a table, realign the table. This command
27401 works even if the automatic table editor has been turned off.
27403 - If the cursor is on a #+TBLFM line, re-apply the formulas to
27404 the entire table.
27406 - If the cursor is a the beginning of a dynamic block, update it.
27408 - If the cursor is inside a table created by the table.el package,
27409 activate that table.
27411 - If the current buffer is a remember buffer, close note and file it.
27412 with a prefix argument, file it without further interaction to the default
27413 location.
27415 - If the cursor is on a <<<target>>>, update radio targets and corresponding
27416 links in this buffer.
27418 - If the cursor is on a numbered item in a plain list, renumber the
27419 ordered list.
27421 - If the cursor is on a checkbox, toggle it."
27422 (interactive "P")
27423 (let ((org-enable-table-editor t))
27424 (cond
27425 ((or org-clock-overlays
27426 org-occur-highlights
27427 org-latex-fragment-image-overlays)
27428 (org-remove-clock-overlays)
27429 (org-remove-occur-highlights)
27430 (org-remove-latex-fragment-image-overlays)
27431 (message "Temporary highlights/overlays removed from current buffer"))
27432 ((and (local-variable-p 'org-finish-function (current-buffer))
27433 (fboundp org-finish-function))
27434 (funcall org-finish-function))
27435 ((org-at-property-p)
27436 (call-interactively 'org-property-action))
27437 ((org-on-target-p) (call-interactively 'org-update-radio-target-regexp))
27438 ((org-on-heading-p) (call-interactively 'org-set-tags))
27439 ((org-at-table.el-p)
27440 (require 'table)
27441 (beginning-of-line 1)
27442 (re-search-forward "|" (save-excursion (end-of-line 2) (point)))
27443 (call-interactively 'table-recognize-table))
27444 ((org-at-table-p)
27445 (org-table-maybe-eval-formula)
27446 (if arg
27447 (call-interactively 'org-table-recalculate)
27448 (org-table-maybe-recalculate-line))
27449 (call-interactively 'org-table-align))
27450 ((org-at-item-checkbox-p)
27451 (call-interactively 'org-toggle-checkbox))
27452 ((org-at-item-p)
27453 (call-interactively 'org-maybe-renumber-ordered-list))
27454 ((save-excursion (beginning-of-line 1) (looking-at "#\\+BEGIN:"))
27455 ;; Dynamic block
27456 (beginning-of-line 1)
27457 (org-update-dblock))
27458 ((save-excursion (beginning-of-line 1) (looking-at "#\\+\\([A-Z]+\\)"))
27459 (cond
27460 ((equal (match-string 1) "TBLFM")
27461 ;; Recalculate the table before this line
27462 (save-excursion
27463 (beginning-of-line 1)
27464 (skip-chars-backward " \r\n\t")
27465 (if (org-at-table-p)
27466 (org-call-with-arg 'org-table-recalculate t))))
27468 (call-interactively 'org-mode-restart))))
27469 (t (error "C-c C-c can do nothing useful at this location.")))))
27471 (defun org-mode-restart ()
27472 "Restart Org-mode, to scan again for special lines.
27473 Also updates the keyword regular expressions."
27474 (interactive)
27475 (let ((org-inhibit-startup t)) (org-mode))
27476 (message "Org-mode restarted to refresh keyword and special line setup"))
27478 (defun org-kill-note-or-show-branches ()
27479 "If this is a Note buffer, abort storing the note. Else call `show-branches'."
27480 (interactive)
27481 (if (not org-finish-function)
27482 (call-interactively 'show-branches)
27483 (let ((org-note-abort t))
27484 (funcall org-finish-function))))
27486 (defun org-return (&optional indent)
27487 "Goto next table row or insert a newline.
27488 Calls `org-table-next-row' or `newline', depending on context.
27489 See the individual commands for more information."
27490 (interactive)
27491 (cond
27492 ((bobp) (if indent (newline-and-indent) (newline)))
27493 ((and (org-at-heading-p)
27494 (looking-at
27495 (org-re "\\([ \t]+\\(:[[:alnum:]_@:]+:\\)\\)[ \t]*$")))
27496 (org-show-entry)
27497 (end-of-line 1)
27498 (newline))
27499 ((org-at-table-p)
27500 (org-table-justify-field-maybe)
27501 (call-interactively 'org-table-next-row))
27502 (t (if indent (newline-and-indent) (newline)))))
27504 (defun org-return-indent ()
27505 "Goto next table row or insert a newline and indent.
27506 Calls `org-table-next-row' or `newline-and-indent', depending on
27507 context. See the individual commands for more information."
27508 (interactive)
27509 (org-return t))
27511 (defun org-ctrl-c-star ()
27512 "Compute table, or change heading status of lines.
27513 Calls `org-table-recalculate' or `org-toggle-region-headlines',
27514 depending on context. This will also turn a plain list item or a normal
27515 line into a subheading."
27516 (interactive)
27517 (cond
27518 ((org-at-table-p)
27519 (call-interactively 'org-table-recalculate))
27520 ((org-region-active-p)
27521 ;; Convert all lines in region to list items
27522 (call-interactively 'org-toggle-region-headings))
27523 ((org-on-heading-p)
27524 (org-toggle-region-headings (point-at-bol)
27525 (min (1+ (point-at-eol)) (point-max))))
27526 ((org-at-item-p)
27527 ;; Convert to heading
27528 (let ((level (save-match-data
27529 (save-excursion
27530 (condition-case nil
27531 (progn
27532 (org-back-to-heading t)
27533 (funcall outline-level))
27534 (error 0))))))
27535 (replace-match
27536 (concat (make-string (org-get-valid-level level 1) ?*) " ") t t)))
27537 (t (org-toggle-region-headings (point-at-bol)
27538 (min (1+ (point-at-eol)) (point-max))))))
27540 (defun org-ctrl-c-minus ()
27541 "Insert separator line in table or modify bullet status of line.
27542 Also turns a plain line or a region of lines into list items.
27543 Calls `org-table-insert-hline', `org-toggle-region-items', or
27544 `org-cycle-list-bullet', depending on context."
27545 (interactive)
27546 (cond
27547 ((org-at-table-p)
27548 (call-interactively 'org-table-insert-hline))
27549 ((org-on-heading-p)
27550 ;; Convert to item
27551 (save-excursion
27552 (beginning-of-line 1)
27553 (if (looking-at "\\*+ ")
27554 (replace-match (concat (make-string (- (match-end 0) (point) 1) ?\ ) "- ")))))
27555 ((org-region-active-p)
27556 ;; Convert all lines in region to list items
27557 (call-interactively 'org-toggle-region-items))
27558 ((org-in-item-p)
27559 (call-interactively 'org-cycle-list-bullet))
27560 (t (org-toggle-region-items (point-at-bol)
27561 (min (1+ (point-at-eol)) (point-max))))))
27563 (defun org-toggle-region-items (beg end)
27564 "Convert all lines in region to list items.
27565 If the first line is already an item, convert all list items in the region
27566 to normal lines."
27567 (interactive "r")
27568 (let (l2 l)
27569 (save-excursion
27570 (goto-char end)
27571 (setq l2 (org-current-line))
27572 (goto-char beg)
27573 (beginning-of-line 1)
27574 (setq l (1- (org-current-line)))
27575 (if (org-at-item-p)
27576 ;; We already have items, de-itemize
27577 (while (< (setq l (1+ l)) l2)
27578 (when (org-at-item-p)
27579 (goto-char (match-beginning 2))
27580 (delete-region (match-beginning 2) (match-end 2))
27581 (and (looking-at "[ \t]+") (replace-match "")))
27582 (beginning-of-line 2))
27583 (while (< (setq l (1+ l)) l2)
27584 (unless (org-at-item-p)
27585 (if (looking-at "\\([ \t]*\\)\\(\\S-\\)")
27586 (replace-match "\\1- \\2")))
27587 (beginning-of-line 2))))))
27589 (defun org-toggle-region-headings (beg end)
27590 "Convert all lines in region to list items.
27591 If the first line is already an item, convert all list items in the region
27592 to normal lines."
27593 (interactive "r")
27594 (let (l2 l)
27595 (save-excursion
27596 (goto-char end)
27597 (setq l2 (org-current-line))
27598 (goto-char beg)
27599 (beginning-of-line 1)
27600 (setq l (1- (org-current-line)))
27601 (if (org-on-heading-p)
27602 ;; We already have headlines, de-star them
27603 (while (< (setq l (1+ l)) l2)
27604 (when (org-on-heading-p t)
27605 (and (looking-at outline-regexp) (replace-match "")))
27606 (beginning-of-line 2))
27607 (let* ((stars (save-excursion
27608 (re-search-backward org-complex-heading-regexp nil t)
27609 (or (match-string 1) "*")))
27610 (add-stars (if org-odd-levels-only "**" "*"))
27611 (rpl (concat stars add-stars " \\2")))
27612 (while (< (setq l (1+ l)) l2)
27613 (unless (org-on-heading-p)
27614 (if (looking-at "\\([ \t]*\\)\\(\\S-\\)")
27615 (replace-match rpl)))
27616 (beginning-of-line 2)))))))
27618 (defun org-meta-return (&optional arg)
27619 "Insert a new heading or wrap a region in a table.
27620 Calls `org-insert-heading' or `org-table-wrap-region', depending on context.
27621 See the individual commands for more information."
27622 (interactive "P")
27623 (cond
27624 ((org-at-table-p)
27625 (call-interactively 'org-table-wrap-region))
27626 (t (call-interactively 'org-insert-heading))))
27628 ;;; Menu entries
27630 ;; Define the Org-mode menus
27631 (easy-menu-define org-tbl-menu org-mode-map "Tbl menu"
27632 '("Tbl"
27633 ["Align" org-ctrl-c-ctrl-c (org-at-table-p)]
27634 ["Next Field" org-cycle (org-at-table-p)]
27635 ["Previous Field" org-shifttab (org-at-table-p)]
27636 ["Next Row" org-return (org-at-table-p)]
27637 "--"
27638 ["Blank Field" org-table-blank-field (org-at-table-p)]
27639 ["Edit Field" org-table-edit-field (org-at-table-p)]
27640 ["Copy Field from Above" org-table-copy-down (org-at-table-p)]
27641 "--"
27642 ("Column"
27643 ["Move Column Left" org-metaleft (org-at-table-p)]
27644 ["Move Column Right" org-metaright (org-at-table-p)]
27645 ["Delete Column" org-shiftmetaleft (org-at-table-p)]
27646 ["Insert Column" org-shiftmetaright (org-at-table-p)])
27647 ("Row"
27648 ["Move Row Up" org-metaup (org-at-table-p)]
27649 ["Move Row Down" org-metadown (org-at-table-p)]
27650 ["Delete Row" org-shiftmetaup (org-at-table-p)]
27651 ["Insert Row" org-shiftmetadown (org-at-table-p)]
27652 ["Sort lines in region" org-table-sort-lines (org-at-table-p)]
27653 "--"
27654 ["Insert Hline" org-ctrl-c-minus (org-at-table-p)])
27655 ("Rectangle"
27656 ["Copy Rectangle" org-copy-special (org-at-table-p)]
27657 ["Cut Rectangle" org-cut-special (org-at-table-p)]
27658 ["Paste Rectangle" org-paste-special (org-at-table-p)]
27659 ["Fill Rectangle" org-table-wrap-region (org-at-table-p)])
27660 "--"
27661 ("Calculate"
27662 ["Set Column Formula" org-table-eval-formula (org-at-table-p)]
27663 ["Set Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
27664 ["Edit Formulas" org-table-edit-formulas (org-at-table-p)]
27665 "--"
27666 ["Recalculate line" org-table-recalculate (org-at-table-p)]
27667 ["Recalculate all" (lambda () (interactive) (org-table-recalculate '(4))) :active (org-at-table-p) :keys "C-u C-c *"]
27668 ["Iterate all" (lambda () (interactive) (org-table-recalculate '(16))) :active (org-at-table-p) :keys "C-u C-u C-c *"]
27669 "--"
27670 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks (org-at-table-p)]
27671 "--"
27672 ["Sum Column/Rectangle" org-table-sum
27673 (or (org-at-table-p) (org-region-active-p))]
27674 ["Which Column?" org-table-current-column (org-at-table-p)])
27675 ["Debug Formulas"
27676 org-table-toggle-formula-debugger
27677 :style toggle :selected org-table-formula-debug]
27678 ["Show Col/Row Numbers"
27679 org-table-toggle-coordinate-overlays
27680 :style toggle :selected org-table-overlay-coordinates]
27681 "--"
27682 ["Create" org-table-create (and (not (org-at-table-p))
27683 org-enable-table-editor)]
27684 ["Convert Region" org-table-convert-region (not (org-at-table-p 'any))]
27685 ["Import from File" org-table-import (not (org-at-table-p))]
27686 ["Export to File" org-table-export (org-at-table-p)]
27687 "--"
27688 ["Create/Convert from/to table.el" org-table-create-with-table.el t]))
27690 (easy-menu-define org-org-menu org-mode-map "Org menu"
27691 '("Org"
27692 ("Show/Hide"
27693 ["Cycle Visibility" org-cycle (or (bobp) (outline-on-heading-p))]
27694 ["Cycle Global Visibility" org-shifttab (not (org-at-table-p))]
27695 ["Sparse Tree" org-occur t]
27696 ["Reveal Context" org-reveal t]
27697 ["Show All" show-all t]
27698 "--"
27699 ["Subtree to indirect buffer" org-tree-to-indirect-buffer t])
27700 "--"
27701 ["New Heading" org-insert-heading t]
27702 ("Navigate Headings"
27703 ["Up" outline-up-heading t]
27704 ["Next" outline-next-visible-heading t]
27705 ["Previous" outline-previous-visible-heading t]
27706 ["Next Same Level" outline-forward-same-level t]
27707 ["Previous Same Level" outline-backward-same-level t]
27708 "--"
27709 ["Jump" org-goto t])
27710 ("Edit Structure"
27711 ["Move Subtree Up" org-shiftmetaup (not (org-at-table-p))]
27712 ["Move Subtree Down" org-shiftmetadown (not (org-at-table-p))]
27713 "--"
27714 ["Copy Subtree" org-copy-special (not (org-at-table-p))]
27715 ["Cut Subtree" org-cut-special (not (org-at-table-p))]
27716 ["Paste Subtree" org-paste-special (not (org-at-table-p))]
27717 "--"
27718 ["Promote Heading" org-metaleft (not (org-at-table-p))]
27719 ["Promote Subtree" org-shiftmetaleft (not (org-at-table-p))]
27720 ["Demote Heading" org-metaright (not (org-at-table-p))]
27721 ["Demote Subtree" org-shiftmetaright (not (org-at-table-p))]
27722 "--"
27723 ["Sort Region/Children" org-sort (not (org-at-table-p))]
27724 "--"
27725 ["Convert to odd levels" org-convert-to-odd-levels t]
27726 ["Convert to odd/even levels" org-convert-to-oddeven-levels t])
27727 ("Editing"
27728 ["Emphasis..." org-emphasize t])
27729 ("Archive"
27730 ["Toggle ARCHIVE tag" org-toggle-archive-tag t]
27731 ; ["Check and Tag Children" (org-toggle-archive-tag (4))
27732 ; :active t :keys "C-u C-c C-x C-a"]
27733 ["Sparse trees open ARCHIVE trees"
27734 (setq org-sparse-tree-open-archived-trees
27735 (not org-sparse-tree-open-archived-trees))
27736 :style toggle :selected org-sparse-tree-open-archived-trees]
27737 ["Cycling opens ARCHIVE trees"
27738 (setq org-cycle-open-archived-trees (not org-cycle-open-archived-trees))
27739 :style toggle :selected org-cycle-open-archived-trees]
27740 ["Agenda includes ARCHIVE trees"
27741 (setq org-agenda-skip-archived-trees (not org-agenda-skip-archived-trees))
27742 :style toggle :selected (not org-agenda-skip-archived-trees)]
27743 "--"
27744 ["Move Subtree to Archive" org-advertized-archive-subtree t]
27745 ; ["Check and Move Children" (org-archive-subtree '(4))
27746 ; :active t :keys "C-u C-c C-x C-s"]
27748 "--"
27749 ("TODO Lists"
27750 ["TODO/DONE/-" org-todo t]
27751 ("Select keyword"
27752 ["Next keyword" org-shiftright (org-on-heading-p)]
27753 ["Previous keyword" org-shiftleft (org-on-heading-p)]
27754 ["Complete Keyword" org-complete (assq :todo-keyword (org-context))]
27755 ["Next keyword set" org-shiftcontrolright (and (> (length org-todo-sets) 1) (org-on-heading-p))]
27756 ["Previous keyword set" org-shiftcontrolright (and (> (length org-todo-sets) 1) (org-on-heading-p))])
27757 ["Show TODO Tree" org-show-todo-tree t]
27758 ["Global TODO list" org-todo-list t]
27759 "--"
27760 ["Set Priority" org-priority t]
27761 ["Priority Up" org-shiftup t]
27762 ["Priority Down" org-shiftdown t])
27763 ("TAGS and Properties"
27764 ["Set Tags" 'org-ctrl-c-ctrl-c (org-at-heading-p)]
27765 ["Change tag in region" 'org-change-tag-in-region (org-region-active-p)]
27766 "--"
27767 ["Set property" 'org-set-property t]
27768 ["Column view of properties" org-columns t]
27769 ["Insert Column View DBlock" org-insert-columns-dblock t])
27770 ("Dates and Scheduling"
27771 ["Timestamp" org-time-stamp t]
27772 ["Timestamp (inactive)" org-time-stamp-inactive t]
27773 ("Change Date"
27774 ["1 Day Later" org-shiftright t]
27775 ["1 Day Earlier" org-shiftleft t]
27776 ["1 ... Later" org-shiftup t]
27777 ["1 ... Earlier" org-shiftdown t])
27778 ["Compute Time Range" org-evaluate-time-range t]
27779 ["Schedule Item" org-schedule t]
27780 ["Deadline" org-deadline t]
27781 "--"
27782 ["Custom time format" org-toggle-time-stamp-overlays
27783 :style radio :selected org-display-custom-times]
27784 "--"
27785 ["Goto Calendar" org-goto-calendar t]
27786 ["Date from Calendar" org-date-from-calendar t])
27787 ("Logging work"
27788 ["Clock in" org-clock-in t]
27789 ["Clock out" org-clock-out t]
27790 ["Clock cancel" org-clock-cancel t]
27791 ["Goto running clock" org-clock-goto t]
27792 ["Display times" org-clock-display t]
27793 ["Create clock table" org-clock-report t]
27794 "--"
27795 ["Record DONE time"
27796 (progn (setq org-log-done (not org-log-done))
27797 (message "Switching to %s will %s record a timestamp"
27798 (car org-done-keywords)
27799 (if org-log-done "automatically" "not")))
27800 :style toggle :selected org-log-done])
27801 "--"
27802 ["Agenda Command..." org-agenda t]
27803 ["Set Restriction Lock" org-agenda-set-restriction-lock t]
27804 ("File List for Agenda")
27805 ("Special views current file"
27806 ["TODO Tree" org-show-todo-tree t]
27807 ["Check Deadlines" org-check-deadlines t]
27808 ["Timeline" org-timeline t]
27809 ["Tags Tree" org-tags-sparse-tree t])
27810 "--"
27811 ("Hyperlinks"
27812 ["Store Link (Global)" org-store-link t]
27813 ["Insert Link" org-insert-link t]
27814 ["Follow Link" org-open-at-point t]
27815 "--"
27816 ["Next link" org-next-link t]
27817 ["Previous link" org-previous-link t]
27818 "--"
27819 ["Descriptive Links"
27820 (progn (org-add-to-invisibility-spec '(org-link)) (org-restart-font-lock))
27821 :style radio :selected (member '(org-link) buffer-invisibility-spec)]
27822 ["Literal Links"
27823 (progn
27824 (org-remove-from-invisibility-spec '(org-link)) (org-restart-font-lock))
27825 :style radio :selected (not (member '(org-link) buffer-invisibility-spec))])
27826 "--"
27827 ["Export/Publish..." org-export t]
27828 ("LaTeX"
27829 ["Org CDLaTeX mode" org-cdlatex-mode :style toggle
27830 :selected org-cdlatex-mode]
27831 ["Insert Environment" cdlatex-environment (fboundp 'cdlatex-environment)]
27832 ["Insert math symbol" cdlatex-math-symbol (fboundp 'cdlatex-math-symbol)]
27833 ["Modify math symbol" org-cdlatex-math-modify
27834 (org-inside-LaTeX-fragment-p)]
27835 ["Export LaTeX fragments as images"
27836 (setq org-export-with-LaTeX-fragments (not org-export-with-LaTeX-fragments))
27837 :style toggle :selected org-export-with-LaTeX-fragments])
27838 "--"
27839 ("Documentation"
27840 ["Show Version" org-version t]
27841 ["Info Documentation" org-info t])
27842 ("Customize"
27843 ["Browse Org Group" org-customize t]
27844 "--"
27845 ["Expand This Menu" org-create-customize-menu
27846 (fboundp 'customize-menu-create)])
27847 "--"
27848 ["Refresh setup" org-mode-restart t]
27851 (defun org-info (&optional node)
27852 "Read documentation for Org-mode in the info system.
27853 With optional NODE, go directly to that node."
27854 (interactive)
27855 (info (format "(org)%s" (or node ""))))
27857 (defun org-install-agenda-files-menu ()
27858 (let ((bl (buffer-list)))
27859 (save-excursion
27860 (while bl
27861 (set-buffer (pop bl))
27862 (if (org-mode-p) (setq bl nil)))
27863 (when (org-mode-p)
27864 (easy-menu-change
27865 '("Org") "File List for Agenda"
27866 (append
27867 (list
27868 ["Edit File List" (org-edit-agenda-file-list) t]
27869 ["Add/Move Current File to Front of List" org-agenda-file-to-front t]
27870 ["Remove Current File from List" org-remove-file t]
27871 ["Cycle through agenda files" org-cycle-agenda-files t]
27872 ["Occur in all agenda files" org-occur-in-agenda-files t]
27873 "--")
27874 (mapcar 'org-file-menu-entry (org-agenda-files t))))))))
27876 ;;;; Documentation
27878 (defun org-customize ()
27879 "Call the customize function with org as argument."
27880 (interactive)
27881 (customize-browse 'org))
27883 (defun org-create-customize-menu ()
27884 "Create a full customization menu for Org-mode, insert it into the menu."
27885 (interactive)
27886 (if (fboundp 'customize-menu-create)
27887 (progn
27888 (easy-menu-change
27889 '("Org") "Customize"
27890 `(["Browse Org group" org-customize t]
27891 "--"
27892 ,(customize-menu-create 'org)
27893 ["Set" Custom-set t]
27894 ["Save" Custom-save t]
27895 ["Reset to Current" Custom-reset-current t]
27896 ["Reset to Saved" Custom-reset-saved t]
27897 ["Reset to Standard Settings" Custom-reset-standard t]))
27898 (message "\"Org\"-menu now contains full customization menu"))
27899 (error "Cannot expand menu (outdated version of cus-edit.el)")))
27901 ;;;; Miscellaneous stuff
27904 ;;; Generally useful functions
27906 (defun org-context ()
27907 "Return a list of contexts of the current cursor position.
27908 If several contexts apply, all are returned.
27909 Each context entry is a list with a symbol naming the context, and
27910 two positions indicating start and end of the context. Possible
27911 contexts are:
27913 :headline anywhere in a headline
27914 :headline-stars on the leading stars in a headline
27915 :todo-keyword on a TODO keyword (including DONE) in a headline
27916 :tags on the TAGS in a headline
27917 :priority on the priority cookie in a headline
27918 :item on the first line of a plain list item
27919 :item-bullet on the bullet/number of a plain list item
27920 :checkbox on the checkbox in a plain list item
27921 :table in an org-mode table
27922 :table-special on a special filed in a table
27923 :table-table in a table.el table
27924 :link on a hyperlink
27925 :keyword on a keyword: SCHEDULED, DEADLINE, CLOSE,COMMENT, QUOTE.
27926 :target on a <<target>>
27927 :radio-target on a <<<radio-target>>>
27928 :latex-fragment on a LaTeX fragment
27929 :latex-preview on a LaTeX fragment with overlayed preview image
27931 This function expects the position to be visible because it uses font-lock
27932 faces as a help to recognize the following contexts: :table-special, :link,
27933 and :keyword."
27934 (let* ((f (get-text-property (point) 'face))
27935 (faces (if (listp f) f (list f)))
27936 (p (point)) clist o)
27937 ;; First the large context
27938 (cond
27939 ((org-on-heading-p t)
27940 (push (list :headline (point-at-bol) (point-at-eol)) clist)
27941 (when (progn
27942 (beginning-of-line 1)
27943 (looking-at org-todo-line-tags-regexp))
27944 (push (org-point-in-group p 1 :headline-stars) clist)
27945 (push (org-point-in-group p 2 :todo-keyword) clist)
27946 (push (org-point-in-group p 4 :tags) clist))
27947 (goto-char p)
27948 (skip-chars-backward "^[\n\r \t") (or (eobp) (backward-char 1))
27949 (if (looking-at "\\[#[A-Z0-9]\\]")
27950 (push (org-point-in-group p 0 :priority) clist)))
27952 ((org-at-item-p)
27953 (push (org-point-in-group p 2 :item-bullet) clist)
27954 (push (list :item (point-at-bol)
27955 (save-excursion (org-end-of-item) (point)))
27956 clist)
27957 (and (org-at-item-checkbox-p)
27958 (push (org-point-in-group p 0 :checkbox) clist)))
27960 ((org-at-table-p)
27961 (push (list :table (org-table-begin) (org-table-end)) clist)
27962 (if (memq 'org-formula faces)
27963 (push (list :table-special
27964 (previous-single-property-change p 'face)
27965 (next-single-property-change p 'face)) clist)))
27966 ((org-at-table-p 'any)
27967 (push (list :table-table) clist)))
27968 (goto-char p)
27970 ;; Now the small context
27971 (cond
27972 ((org-at-timestamp-p)
27973 (push (org-point-in-group p 0 :timestamp) clist))
27974 ((memq 'org-link faces)
27975 (push (list :link
27976 (previous-single-property-change p 'face)
27977 (next-single-property-change p 'face)) clist))
27978 ((memq 'org-special-keyword faces)
27979 (push (list :keyword
27980 (previous-single-property-change p 'face)
27981 (next-single-property-change p 'face)) clist))
27982 ((org-on-target-p)
27983 (push (org-point-in-group p 0 :target) clist)
27984 (goto-char (1- (match-beginning 0)))
27985 (if (looking-at org-radio-target-regexp)
27986 (push (org-point-in-group p 0 :radio-target) clist))
27987 (goto-char p))
27988 ((setq o (car (delq nil
27989 (mapcar
27990 (lambda (x)
27991 (if (memq x org-latex-fragment-image-overlays) x))
27992 (org-overlays-at (point))))))
27993 (push (list :latex-fragment
27994 (org-overlay-start o) (org-overlay-end o)) clist)
27995 (push (list :latex-preview
27996 (org-overlay-start o) (org-overlay-end o)) clist))
27997 ((org-inside-LaTeX-fragment-p)
27998 ;; FIXME: positions wrong.
27999 (push (list :latex-fragment (point) (point)) clist)))
28001 (setq clist (nreverse (delq nil clist)))
28002 clist))
28004 ;; FIXME: Compare with at-regexp-p Do we need both?
28005 (defun org-in-regexp (re &optional nlines visually)
28006 "Check if point is inside a match of regexp.
28007 Normally only the current line is checked, but you can include NLINES extra
28008 lines both before and after point into the search.
28009 If VISUALLY is set, require that the cursor is not after the match but
28010 really on, so that the block visually is on the match."
28011 (catch 'exit
28012 (let ((pos (point))
28013 (eol (point-at-eol (+ 1 (or nlines 0))))
28014 (inc (if visually 1 0)))
28015 (save-excursion
28016 (beginning-of-line (- 1 (or nlines 0)))
28017 (while (re-search-forward re eol t)
28018 (if (and (<= (match-beginning 0) pos)
28019 (>= (+ inc (match-end 0)) pos))
28020 (throw 'exit (cons (match-beginning 0) (match-end 0)))))))))
28022 (defun org-at-regexp-p (regexp)
28023 "Is point inside a match of REGEXP in the current line?"
28024 (catch 'exit
28025 (save-excursion
28026 (let ((pos (point)) (end (point-at-eol)))
28027 (beginning-of-line 1)
28028 (while (re-search-forward regexp end t)
28029 (if (and (<= (match-beginning 0) pos)
28030 (>= (match-end 0) pos))
28031 (throw 'exit t)))
28032 nil))))
28034 (defun org-occur-in-agenda-files (regexp &optional nlines)
28035 "Call `multi-occur' with buffers for all agenda files."
28036 (interactive "sOrg-files matching: \np")
28037 (let* ((files (org-agenda-files))
28038 (tnames (mapcar 'file-truename files))
28039 (extra org-agenda-text-search-extra-files)
28041 (while (setq f (pop extra))
28042 (unless (member (file-truename f) tnames)
28043 (add-to-list 'files f 'append)
28044 (add-to-list 'tnames (file-truename f) 'append)))
28045 (multi-occur
28046 (mapcar (lambda (x) (or (get-file-buffer x) (find-file-noselect x))) files)
28047 regexp)))
28049 (if (boundp 'occur-mode-find-occurrence-hook)
28050 ;; Emacs 23
28051 (add-hook 'occur-mode-find-occurrence-hook
28052 (lambda ()
28053 (when (org-mode-p)
28054 (org-reveal))))
28055 ;; Emacs 22
28056 (defadvice occur-mode-goto-occurrence
28057 (after org-occur-reveal activate)
28058 (and (org-mode-p) (org-reveal)))
28059 (defadvice occur-mode-goto-occurrence-other-window
28060 (after org-occur-reveal activate)
28061 (and (org-mode-p) (org-reveal)))
28062 (defadvice occur-mode-display-occurrence
28063 (after org-occur-reveal activate)
28064 (when (org-mode-p)
28065 (let ((pos (occur-mode-find-occurrence)))
28066 (with-current-buffer (marker-buffer pos)
28067 (save-excursion
28068 (goto-char pos)
28069 (org-reveal)))))))
28071 (defun org-uniquify (list)
28072 "Remove duplicate elements from LIST."
28073 (let (res)
28074 (mapc (lambda (x) (add-to-list 'res x 'append)) list)
28075 res))
28077 (defun org-delete-all (elts list)
28078 "Remove all elements in ELTS from LIST."
28079 (while elts
28080 (setq list (delete (pop elts) list)))
28081 list)
28083 (defun org-back-over-empty-lines ()
28084 "Move backwards over witespace, to the beginning of the first empty line.
28085 Returns the number of empty lines passed."
28086 (let ((pos (point)))
28087 (skip-chars-backward " \t\n\r")
28088 (beginning-of-line 2)
28089 (goto-char (min (point) pos))
28090 (count-lines (point) pos)))
28092 (defun org-skip-whitespace ()
28093 (skip-chars-forward " \t\n\r"))
28095 (defun org-point-in-group (point group &optional context)
28096 "Check if POINT is in match-group GROUP.
28097 If CONTEXT is non-nil, return a list with CONTEXT and the boundaries of the
28098 match. If the match group does ot exist or point is not inside it,
28099 return nil."
28100 (and (match-beginning group)
28101 (>= point (match-beginning group))
28102 (<= point (match-end group))
28103 (if context
28104 (list context (match-beginning group) (match-end group))
28105 t)))
28107 (defun org-switch-to-buffer-other-window (&rest args)
28108 "Switch to buffer in a second window on the current frame.
28109 In particular, do not allow pop-up frames."
28110 (let (pop-up-frames special-display-buffer-names special-display-regexps
28111 special-display-function)
28112 (apply 'switch-to-buffer-other-window args)))
28114 (defun org-combine-plists (&rest plists)
28115 "Create a single property list from all plists in PLISTS.
28116 The process starts by copying the first list, and then setting properties
28117 from the other lists. Settings in the last list are the most significant
28118 ones and overrule settings in the other lists."
28119 (let ((rtn (copy-sequence (pop plists)))
28120 p v ls)
28121 (while plists
28122 (setq ls (pop plists))
28123 (while ls
28124 (setq p (pop ls) v (pop ls))
28125 (setq rtn (plist-put rtn p v))))
28126 rtn))
28128 (defun org-move-line-down (arg)
28129 "Move the current line down. With prefix argument, move it past ARG lines."
28130 (interactive "p")
28131 (let ((col (current-column))
28132 beg end pos)
28133 (beginning-of-line 1) (setq beg (point))
28134 (beginning-of-line 2) (setq end (point))
28135 (beginning-of-line (+ 1 arg))
28136 (setq pos (move-marker (make-marker) (point)))
28137 (insert (delete-and-extract-region beg end))
28138 (goto-char pos)
28139 (move-to-column col)))
28141 (defun org-move-line-up (arg)
28142 "Move the current line up. With prefix argument, move it past ARG lines."
28143 (interactive "p")
28144 (let ((col (current-column))
28145 beg end pos)
28146 (beginning-of-line 1) (setq beg (point))
28147 (beginning-of-line 2) (setq end (point))
28148 (beginning-of-line (- arg))
28149 (setq pos (move-marker (make-marker) (point)))
28150 (insert (delete-and-extract-region beg end))
28151 (goto-char pos)
28152 (move-to-column col)))
28154 (defun org-replace-escapes (string table)
28155 "Replace %-escapes in STRING with values in TABLE.
28156 TABLE is an association list with keys like \"%a\" and string values.
28157 The sequences in STRING may contain normal field width and padding information,
28158 for example \"%-5s\". Replacements happen in the sequence given by TABLE,
28159 so values can contain further %-escapes if they are define later in TABLE."
28160 (let ((case-fold-search nil)
28161 e re rpl)
28162 (while (setq e (pop table))
28163 (setq re (concat "%-?[0-9.]*" (substring (car e) 1)))
28164 (while (string-match re string)
28165 (setq rpl (format (concat (substring (match-string 0 string) 0 -1) "s")
28166 (cdr e)))
28167 (setq string (replace-match rpl t t string))))
28168 string))
28171 (defun org-sublist (list start end)
28172 "Return a section of LIST, from START to END.
28173 Counting starts at 1."
28174 (let (rtn (c start))
28175 (setq list (nthcdr (1- start) list))
28176 (while (and list (<= c end))
28177 (push (pop list) rtn)
28178 (setq c (1+ c)))
28179 (nreverse rtn)))
28181 (defun org-find-base-buffer-visiting (file)
28182 "Like `find-buffer-visiting' but alway return the base buffer and
28183 not an indirect buffer."
28184 (let ((buf (find-buffer-visiting file)))
28185 (if buf
28186 (or (buffer-base-buffer buf) buf)
28187 nil)))
28189 (defun org-image-file-name-regexp ()
28190 "Return regexp matching the file names of images."
28191 (if (fboundp 'image-file-name-regexp)
28192 (image-file-name-regexp)
28193 (let ((image-file-name-extensions
28194 '("png" "jpeg" "jpg" "gif" "tiff" "tif"
28195 "xbm" "xpm" "pbm" "pgm" "ppm")))
28196 (concat "\\."
28197 (regexp-opt (nconc (mapcar 'upcase
28198 image-file-name-extensions)
28199 image-file-name-extensions)
28201 "\\'"))))
28203 (defun org-file-image-p (file)
28204 "Return non-nil if FILE is an image."
28205 (save-match-data
28206 (string-match (org-image-file-name-regexp) file)))
28208 ;;; Paragraph filling stuff.
28209 ;; We want this to be just right, so use the full arsenal.
28211 (defun org-indent-line-function ()
28212 "Indent line like previous, but further if previous was headline or item."
28213 (interactive)
28214 (let* ((pos (point))
28215 (itemp (org-at-item-p))
28216 column bpos bcol tpos tcol bullet btype bullet-type)
28217 ;; Find the previous relevant line
28218 (beginning-of-line 1)
28219 (cond
28220 ((looking-at "#") (setq column 0))
28221 ((looking-at "\\*+ ") (setq column 0))
28223 (beginning-of-line 0)
28224 (while (and (not (bobp)) (looking-at "[ \t]*[\n:#|]"))
28225 (beginning-of-line 0))
28226 (cond
28227 ((looking-at "\\*+[ \t]+")
28228 (goto-char (match-end 0))
28229 (setq column (current-column)))
28230 ((org-in-item-p)
28231 (org-beginning-of-item)
28232 ; (looking-at "[ \t]*\\(\\S-+\\)[ \t]*")
28233 (looking-at "[ \t]*\\(\\S-+\\)[ \t]*\\(\\[[- X]\\][ \t]*\\)?")
28234 (setq bpos (match-beginning 1) tpos (match-end 0)
28235 bcol (progn (goto-char bpos) (current-column))
28236 tcol (progn (goto-char tpos) (current-column))
28237 bullet (match-string 1)
28238 bullet-type (if (string-match "[0-9]" bullet) "n" bullet))
28239 (if (not itemp)
28240 (setq column tcol)
28241 (goto-char pos)
28242 (beginning-of-line 1)
28243 (if (looking-at "\\S-")
28244 (progn
28245 (looking-at "[ \t]*\\(\\S-+\\)[ \t]*")
28246 (setq bullet (match-string 1)
28247 btype (if (string-match "[0-9]" bullet) "n" bullet))
28248 (setq column (if (equal btype bullet-type) bcol tcol)))
28249 (setq column (org-get-indentation)))))
28250 (t (setq column (org-get-indentation))))))
28251 (goto-char pos)
28252 (if (<= (current-column) (current-indentation))
28253 (indent-line-to column)
28254 (save-excursion (indent-line-to column)))
28255 (setq column (current-column))
28256 (beginning-of-line 1)
28257 (if (looking-at
28258 "\\([ \t]+\\)\\(:[-_0-9a-zA-Z]+:\\)[ \t]*\\(\\S-.*\\(\\S-\\|$\\)\\)")
28259 (replace-match (concat "\\1" (format org-property-format
28260 (match-string 2) (match-string 3)))
28261 t nil))
28262 (move-to-column column)))
28264 (defun org-set-autofill-regexps ()
28265 (interactive)
28266 ;; In the paragraph separator we include headlines, because filling
28267 ;; text in a line directly attached to a headline would otherwise
28268 ;; fill the headline as well.
28269 (org-set-local 'comment-start-skip "^#+[ \t]*")
28270 (org-set-local 'paragraph-separate "\f\\|\\*+ \\|[ ]*$\\|[ \t]*[:|]")
28271 ;; The paragraph starter includes hand-formatted lists.
28272 (org-set-local 'paragraph-start
28273 "\f\\|[ ]*$\\|\\*+ \\|\f\\|[ \t]*\\([-+*][ \t]+\\|[0-9]+[.)][ \t]+\\)\\|[ \t]*[:|]")
28274 ;; Inhibit auto-fill for headers, tables and fixed-width lines.
28275 ;; But only if the user has not turned off tables or fixed-width regions
28276 (org-set-local
28277 'auto-fill-inhibit-regexp
28278 (concat "\\*+ \\|#\\+"
28279 "\\|[ \t]*" org-keyword-time-regexp
28280 (if (or org-enable-table-editor org-enable-fixed-width-editor)
28281 (concat
28282 "\\|[ \t]*["
28283 (if org-enable-table-editor "|" "")
28284 (if org-enable-fixed-width-editor ":" "")
28285 "]"))))
28286 ;; We use our own fill-paragraph function, to make sure that tables
28287 ;; and fixed-width regions are not wrapped. That function will pass
28288 ;; through to `fill-paragraph' when appropriate.
28289 (org-set-local 'fill-paragraph-function 'org-fill-paragraph)
28290 ; Adaptive filling: To get full control, first make sure that
28291 ;; `adaptive-fill-regexp' never matches. Then install our own matcher.
28292 (org-set-local 'adaptive-fill-regexp "\000")
28293 (org-set-local 'adaptive-fill-function
28294 'org-adaptive-fill-function)
28295 (org-set-local
28296 'align-mode-rules-list
28297 '((org-in-buffer-settings
28298 (regexp . "^#\\+[A-Z_]+:\\(\\s-*\\)\\S-+")
28299 (modes . '(org-mode))))))
28301 (defun org-fill-paragraph (&optional justify)
28302 "Re-align a table, pass through to fill-paragraph if no table."
28303 (let ((table-p (org-at-table-p))
28304 (table.el-p (org-at-table.el-p)))
28305 (cond ((and (equal (char-after (point-at-bol)) ?*)
28306 (save-excursion (goto-char (point-at-bol))
28307 (looking-at outline-regexp)))
28308 t) ; skip headlines
28309 (table.el-p t) ; skip table.el tables
28310 (table-p (org-table-align) t) ; align org-mode tables
28311 (t nil)))) ; call paragraph-fill
28313 ;; For reference, this is the default value of adaptive-fill-regexp
28314 ;; "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*"
28316 (defun org-adaptive-fill-function ()
28317 "Return a fill prefix for org-mode files.
28318 In particular, this makes sure hanging paragraphs for hand-formatted lists
28319 work correctly."
28320 (cond ((looking-at "#[ \t]+")
28321 (match-string 0))
28322 ((looking-at "[ \t]*\\([-*+] \\|[0-9]+[.)] \\)?")
28323 (save-excursion
28324 (goto-char (match-end 0))
28325 (make-string (current-column) ?\ )))
28326 (t nil)))
28328 ;;;; Functions extending outline functionality
28331 (defun org-beginning-of-line (&optional arg)
28332 "Go to the beginning of the current line. If that is invisible, continue
28333 to a visible line beginning. This makes the function of C-a more intuitive.
28334 If this is a headline, and `org-special-ctrl-a/e' is set, ignore tags on the
28335 first attempt, and only move to after the tags when the cursor is already
28336 beyond the end of the headline."
28337 (interactive "P")
28338 (let ((pos (point)))
28339 (beginning-of-line 1)
28340 (if (bobp)
28342 (backward-char 1)
28343 (if (org-invisible-p)
28344 (while (and (not (bobp)) (org-invisible-p))
28345 (backward-char 1)
28346 (beginning-of-line 1))
28347 (forward-char 1)))
28348 (when org-special-ctrl-a/e
28349 (cond
28350 ((and (looking-at org-todo-line-regexp)
28351 (= (char-after (match-end 1)) ?\ ))
28352 (goto-char
28353 (if (eq org-special-ctrl-a/e t)
28354 (cond ((> pos (match-beginning 3)) (match-beginning 3))
28355 ((= pos (point)) (match-beginning 3))
28356 (t (point)))
28357 (cond ((> pos (point)) (point))
28358 ((not (eq last-command this-command)) (point))
28359 (t (match-beginning 3))))))
28360 ((org-at-item-p)
28361 (goto-char
28362 (if (eq org-special-ctrl-a/e t)
28363 (cond ((> pos (match-end 4)) (match-end 4))
28364 ((= pos (point)) (match-end 4))
28365 (t (point)))
28366 (cond ((> pos (point)) (point))
28367 ((not (eq last-command this-command)) (point))
28368 (t (match-end 4))))))))))
28370 (defun org-end-of-line (&optional arg)
28371 "Go to the end of the line.
28372 If this is a headline, and `org-special-ctrl-a/e' is set, ignore tags on the
28373 first attempt, and only move to after the tags when the cursor is already
28374 beyond the end of the headline."
28375 (interactive "P")
28376 (if (or (not org-special-ctrl-a/e)
28377 (not (org-on-heading-p)))
28378 (end-of-line arg)
28379 (let ((pos (point)))
28380 (beginning-of-line 1)
28381 (if (looking-at (org-re ".*?\\([ \t]*\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$"))
28382 (if (eq org-special-ctrl-a/e t)
28383 (if (or (< pos (match-beginning 1))
28384 (= pos (match-end 0)))
28385 (goto-char (match-beginning 1))
28386 (goto-char (match-end 0)))
28387 (if (or (< pos (match-end 0)) (not (eq this-command last-command)))
28388 (goto-char (match-end 0))
28389 (goto-char (match-beginning 1))))
28390 (end-of-line arg)))))
28392 (define-key org-mode-map "\C-a" 'org-beginning-of-line)
28393 (define-key org-mode-map "\C-e" 'org-end-of-line)
28395 (defun org-kill-line (&optional arg)
28396 "Kill line, to tags or end of line."
28397 (interactive "P")
28398 (cond
28399 ((or (not org-special-ctrl-k)
28400 (bolp)
28401 (not (org-on-heading-p)))
28402 (call-interactively 'kill-line))
28403 ((looking-at (org-re ".*?\\S-\\([ \t]+\\(:[[:alnum:]_@:]+:\\)\\)[ \t]*$"))
28404 (kill-region (point) (match-beginning 1))
28405 (org-set-tags nil t))
28406 (t (kill-region (point) (point-at-eol)))))
28408 (define-key org-mode-map "\C-k" 'org-kill-line)
28410 (defun org-invisible-p ()
28411 "Check if point is at a character currently not visible."
28412 ;; Early versions of noutline don't have `outline-invisible-p'.
28413 (if (fboundp 'outline-invisible-p)
28414 (outline-invisible-p)
28415 (get-char-property (point) 'invisible)))
28417 (defun org-invisible-p2 ()
28418 "Check if point is at a character currently not visible."
28419 (save-excursion
28420 (if (and (eolp) (not (bobp))) (backward-char 1))
28421 ;; Early versions of noutline don't have `outline-invisible-p'.
28422 (if (fboundp 'outline-invisible-p)
28423 (outline-invisible-p)
28424 (get-char-property (point) 'invisible))))
28426 (defalias 'org-back-to-heading 'outline-back-to-heading)
28427 (defalias 'org-on-heading-p 'outline-on-heading-p)
28428 (defalias 'org-at-heading-p 'outline-on-heading-p)
28429 (defun org-at-heading-or-item-p ()
28430 (or (org-on-heading-p) (org-at-item-p)))
28432 (defun org-on-target-p ()
28433 (or (org-in-regexp org-radio-target-regexp)
28434 (org-in-regexp org-target-regexp)))
28436 (defun org-up-heading-all (arg)
28437 "Move to the heading line of which the present line is a subheading.
28438 This function considers both visible and invisible heading lines.
28439 With argument, move up ARG levels."
28440 (if (fboundp 'outline-up-heading-all)
28441 (outline-up-heading-all arg) ; emacs 21 version of outline.el
28442 (outline-up-heading arg t))) ; emacs 22 version of outline.el
28444 (defun org-up-heading-safe ()
28445 "Move to the heading line of which the present line is a subheading.
28446 This version will not throw an error. It will return the level of the
28447 headline found, or nil if no higher level is found."
28448 (let ((pos (point)) start-level level
28449 (re (concat "^" outline-regexp)))
28450 (catch 'exit
28451 (outline-back-to-heading t)
28452 (setq start-level (funcall outline-level))
28453 (if (equal start-level 1) (throw 'exit nil))
28454 (while (re-search-backward re nil t)
28455 (setq level (funcall outline-level))
28456 (if (< level start-level) (throw 'exit level)))
28457 nil)))
28459 (defun org-first-sibling-p ()
28460 "Is this heading the first child of its parents?"
28461 (interactive)
28462 (let ((re (concat "^" outline-regexp))
28463 level l)
28464 (unless (org-at-heading-p t)
28465 (error "Not at a heading"))
28466 (setq level (funcall outline-level))
28467 (save-excursion
28468 (if (not (re-search-backward re nil t))
28470 (setq l (funcall outline-level))
28471 (< l level)))))
28473 (defun org-goto-sibling (&optional previous)
28474 "Goto the next sibling, even if it is invisible.
28475 When PREVIOUS is set, go to the previous sibling instead. Returns t
28476 when a sibling was found. When none is found, return nil and don't
28477 move point."
28478 (let ((fun (if previous 're-search-backward 're-search-forward))
28479 (pos (point))
28480 (re (concat "^" outline-regexp))
28481 level l)
28482 (when (condition-case nil (org-back-to-heading t) (error nil))
28483 (setq level (funcall outline-level))
28484 (catch 'exit
28485 (or previous (forward-char 1))
28486 (while (funcall fun re nil t)
28487 (setq l (funcall outline-level))
28488 (when (< l level) (goto-char pos) (throw 'exit nil))
28489 (when (= l level) (goto-char (match-beginning 0)) (throw 'exit t)))
28490 (goto-char pos)
28491 nil))))
28493 (defun org-show-siblings ()
28494 "Show all siblings of the current headline."
28495 (save-excursion
28496 (while (org-goto-sibling) (org-flag-heading nil)))
28497 (save-excursion
28498 (while (org-goto-sibling 'previous)
28499 (org-flag-heading nil))))
28501 (defun org-show-hidden-entry ()
28502 "Show an entry where even the heading is hidden."
28503 (save-excursion
28504 (org-show-entry)))
28506 (defun org-flag-heading (flag &optional entry)
28507 "Flag the current heading. FLAG non-nil means make invisible.
28508 When ENTRY is non-nil, show the entire entry."
28509 (save-excursion
28510 (org-back-to-heading t)
28511 ;; Check if we should show the entire entry
28512 (if entry
28513 (progn
28514 (org-show-entry)
28515 (save-excursion
28516 (and (outline-next-heading)
28517 (org-flag-heading nil))))
28518 (outline-flag-region (max (point-min) (1- (point)))
28519 (save-excursion (outline-end-of-heading) (point))
28520 flag))))
28522 (defun org-end-of-subtree (&optional invisible-OK to-heading)
28523 ;; This is an exact copy of the original function, but it uses
28524 ;; `org-back-to-heading', to make it work also in invisible
28525 ;; trees. And is uses an invisible-OK argument.
28526 ;; Under Emacs this is not needed, but the old outline.el needs this fix.
28527 (org-back-to-heading invisible-OK)
28528 (let ((first t)
28529 (level (funcall outline-level)))
28530 (while (and (not (eobp))
28531 (or first (> (funcall outline-level) level)))
28532 (setq first nil)
28533 (outline-next-heading))
28534 (unless to-heading
28535 (if (memq (preceding-char) '(?\n ?\^M))
28536 (progn
28537 ;; Go to end of line before heading
28538 (forward-char -1)
28539 (if (memq (preceding-char) '(?\n ?\^M))
28540 ;; leave blank line before heading
28541 (forward-char -1))))))
28542 (point))
28544 (defun org-show-subtree ()
28545 "Show everything after this heading at deeper levels."
28546 (outline-flag-region
28547 (point)
28548 (save-excursion
28549 (outline-end-of-subtree) (outline-next-heading) (point))
28550 nil))
28552 (defun org-show-entry ()
28553 "Show the body directly following this heading.
28554 Show the heading too, if it is currently invisible."
28555 (interactive)
28556 (save-excursion
28557 (condition-case nil
28558 (progn
28559 (org-back-to-heading t)
28560 (outline-flag-region
28561 (max (point-min) (1- (point)))
28562 (save-excursion
28563 (re-search-forward
28564 (concat "[\r\n]\\(" outline-regexp "\\)") nil 'move)
28565 (or (match-beginning 1) (point-max)))
28566 nil))
28567 (error nil))))
28569 (defun org-make-options-regexp (kwds)
28570 "Make a regular expression for keyword lines."
28571 (concat
28573 "#?[ \t]*\\+\\("
28574 (mapconcat 'regexp-quote kwds "\\|")
28575 "\\):[ \t]*"
28576 "\\(.+\\)"))
28578 ;; Make isearch reveal the necessary context
28579 (defun org-isearch-end ()
28580 "Reveal context after isearch exits."
28581 (when isearch-success ; only if search was successful
28582 (if (featurep 'xemacs)
28583 ;; Under XEmacs, the hook is run in the correct place,
28584 ;; we directly show the context.
28585 (org-show-context 'isearch)
28586 ;; In Emacs the hook runs *before* restoring the overlays.
28587 ;; So we have to use a one-time post-command-hook to do this.
28588 ;; (Emacs 22 has a special variable, see function `org-mode')
28589 (unless (and (boundp 'isearch-mode-end-hook-quit)
28590 isearch-mode-end-hook-quit)
28591 ;; Only when the isearch was not quitted.
28592 (org-add-hook 'post-command-hook 'org-isearch-post-command
28593 'append 'local)))))
28595 (defun org-isearch-post-command ()
28596 "Remove self from hook, and show context."
28597 (remove-hook 'post-command-hook 'org-isearch-post-command 'local)
28598 (org-show-context 'isearch))
28601 ;;;; Integration with and fixes for other packages
28603 ;;; Imenu support
28605 (defvar org-imenu-markers nil
28606 "All markers currently used by Imenu.")
28607 (make-variable-buffer-local 'org-imenu-markers)
28609 (defun org-imenu-new-marker (&optional pos)
28610 "Return a new marker for use by Imenu, and remember the marker."
28611 (let ((m (make-marker)))
28612 (move-marker m (or pos (point)))
28613 (push m org-imenu-markers)
28616 (defun org-imenu-get-tree ()
28617 "Produce the index for Imenu."
28618 (mapc (lambda (x) (move-marker x nil)) org-imenu-markers)
28619 (setq org-imenu-markers nil)
28620 (let* ((n org-imenu-depth)
28621 (re (concat "^" outline-regexp))
28622 (subs (make-vector (1+ n) nil))
28623 (last-level 0)
28624 m tree level head)
28625 (save-excursion
28626 (save-restriction
28627 (widen)
28628 (goto-char (point-max))
28629 (while (re-search-backward re nil t)
28630 (setq level (org-reduced-level (funcall outline-level)))
28631 (when (<= level n)
28632 (looking-at org-complex-heading-regexp)
28633 (setq head (org-match-string-no-properties 4)
28634 m (org-imenu-new-marker))
28635 (org-add-props head nil 'org-imenu-marker m 'org-imenu t)
28636 (if (>= level last-level)
28637 (push (cons head m) (aref subs level))
28638 (push (cons head (aref subs (1+ level))) (aref subs level))
28639 (loop for i from (1+ level) to n do (aset subs i nil)))
28640 (setq last-level level)))))
28641 (aref subs 1)))
28643 (eval-after-load "imenu"
28644 '(progn
28645 (add-hook 'imenu-after-jump-hook
28646 (lambda () (org-show-context 'org-goto)))))
28648 ;; Speedbar support
28650 (defun org-speedbar-set-agenda-restriction ()
28651 "Restrict future agenda commands to the location at point in speedbar.
28652 To get rid of the restriction, use \\[org-agenda-remove-restriction-lock]."
28653 (interactive)
28654 (let (p m tp np dir txt w)
28655 (cond
28656 ((setq p (text-property-any (point-at-bol) (point-at-eol)
28657 'org-imenu t))
28658 (setq m (get-text-property p 'org-imenu-marker))
28659 (save-excursion
28660 (save-restriction
28661 (set-buffer (marker-buffer m))
28662 (goto-char m)
28663 (org-agenda-set-restriction-lock 'subtree))))
28664 ((setq p (text-property-any (point-at-bol) (point-at-eol)
28665 'speedbar-function 'speedbar-find-file))
28666 (setq tp (previous-single-property-change
28667 (1+ p) 'speedbar-function)
28668 np (next-single-property-change
28669 tp 'speedbar-function)
28670 dir (speedbar-line-directory)
28671 txt (buffer-substring-no-properties (or tp (point-min))
28672 (or np (point-max))))
28673 (save-excursion
28674 (save-restriction
28675 (set-buffer (find-file-noselect
28676 (let ((default-directory dir))
28677 (expand-file-name txt))))
28678 (unless (org-mode-p)
28679 (error "Cannot restrict to non-Org-mode file"))
28680 (org-agenda-set-restriction-lock 'file))))
28681 (t (error "Don't know how to restrict Org-mode's agenda")))
28682 (org-move-overlay org-speedbar-restriction-lock-overlay
28683 (point-at-bol) (point-at-eol))
28684 (setq current-prefix-arg nil)
28685 (org-agenda-maybe-redo)))
28687 (eval-after-load "speedbar"
28688 '(progn
28689 (speedbar-add-supported-extension ".org")
28690 (define-key speedbar-file-key-map "<" 'org-speedbar-set-agenda-restriction)
28691 (define-key speedbar-file-key-map "\C-c\C-x<" 'org-speedbar-set-agenda-restriction)
28692 (define-key speedbar-file-key-map ">" 'org-agenda-remove-restriction-lock)
28693 (define-key speedbar-file-key-map "\C-c\C-x>" 'org-agenda-remove-restriction-lock)
28694 (add-hook 'speedbar-visiting-tag-hook
28695 (lambda () (org-show-context 'org-goto)))))
28698 ;;; Fixes and Hacks
28700 ;; Make flyspell not check words in links, to not mess up our keymap
28701 (defun org-mode-flyspell-verify ()
28702 "Don't let flyspell put overlays at active buttons."
28703 (not (get-text-property (point) 'keymap)))
28705 ;; Make `bookmark-jump' show the jump location if it was hidden.
28706 (eval-after-load "bookmark"
28707 '(if (boundp 'bookmark-after-jump-hook)
28708 ;; We can use the hook
28709 (add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide)
28710 ;; Hook not available, use advice
28711 (defadvice bookmark-jump (after org-make-visible activate)
28712 "Make the position visible."
28713 (org-bookmark-jump-unhide))))
28715 (defun org-bookmark-jump-unhide ()
28716 "Unhide the current position, to show the bookmark location."
28717 (and (org-mode-p)
28718 (or (org-invisible-p)
28719 (save-excursion (goto-char (max (point-min) (1- (point))))
28720 (org-invisible-p)))
28721 (org-show-context 'bookmark-jump)))
28723 ;; Make session.el ignore our circular variable
28724 (eval-after-load "session"
28725 '(add-to-list 'session-globals-exclude 'org-mark-ring))
28727 ;;;; Experimental code
28729 (defun org-closed-in-range ()
28730 "Sparse tree of items closed in a certain time range.
28731 Still experimental, may disappear in the future."
28732 (interactive)
28733 ;; Get the time interval from the user.
28734 (let* ((time1 (time-to-seconds
28735 (org-read-date nil 'to-time nil "Starting date: ")))
28736 (time2 (time-to-seconds
28737 (org-read-date nil 'to-time nil "End date:")))
28738 ;; callback function
28739 (callback (lambda ()
28740 (let ((time
28741 (time-to-seconds
28742 (apply 'encode-time
28743 (org-parse-time-string
28744 (match-string 1))))))
28745 ;; check if time in interval
28746 (and (>= time time1) (<= time time2))))))
28747 ;; make tree, check each match with the callback
28748 (org-occur "CLOSED: +\\[\\(.*?\\)\\]" nil callback)))
28751 ;;;; Finish up
28753 (provide 'org)
28755 (run-hooks 'org-load-hook)
28757 ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
28758 ;;; org.el ends here