]> code.delx.au - gnu-emacs/blob - lisp/textmodes/org.el
2470326b604ecb018b2bb2a75eeb12f249c530f4
[gnu-emacs] / lisp / textmodes / org.el
1 ;;; org.el --- Outline-based notes management and organize
2 ;; Carstens outline-mode for keeping track of everything.
3 ;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4 ;;
5 ;; Author: Carsten Dominik <dominik at science dot uva dot nl>
6 ;; Keywords: outlines, hypermedia, calendar, wp
7 ;; Homepage: http://www.astro.uva.nl/~dominik/Tools/org/
8 ;; Version: 4.54
9 ;;
10 ;; This file is part of GNU Emacs.
11 ;;
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
16
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.
21
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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27 ;;
28 ;;; Commentary:
29 ;;
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.
32 ;;
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.
47 ;;
48 ;; Installation and Activation
49 ;; ---------------------------
50 ;; See the corresponding sections in the manual at
51 ;;
52 ;; http://staff.science.uva.nl/~dominik/Tools/org/org.html#Installation
53 ;;
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.
61 ;;
62 ;; Recent changes
63 ;; --------------
64 ;; Version 4.54
65 ;; - Improvements to fast tag selection
66 ;; + show status also in target line.
67 ;; + option to auto-exit after first change to tags list (see manual).
68 ;; - Tags sparse trees now also respect the settings in
69 ;; `org-show-hierarchy-above' and `org-show-following-heading'.
70 ;; - Bug fixes.
71 ;;
72 ;; Version 4.53
73 ;; - Custom time formats can be overlayed over time stamps.
74 ;; - New option `org-agenda-todo-ignore-deadlines'.
75 ;; - Work-around for flyspell bug (CVS Emacs has this fixed in flyspell.el).
76 ;; - Work-around for session.el problem with circular data structures.
77 ;; - Bug fixes.
78 ;;
79 ;; Version 4.52
80 ;; - TAG matches can also specify conditions on TODO keywords.
81 ;; - The fast tag interface allows setting tags that are not in the
82 ;; predefined list.
83 ;; - Bug fixes.
84 ;;
85 ;; Version 4.51
86 ;; - Link abbreviations (manual section 4.5).
87 ;; - More control over how agenda is displayed. See the new variables
88 ;; `org-agenda-window-setup', `org-agenda-restore-windows-after-quit'.
89 ;; - Bug fixes.
90 ;;
91 ;; Version 4.50
92 ;; - Closing a TODO item can record an additional note.
93 ;; See variables `org-log-done' and `org-log-note-headings'.
94 ;; - Inserting headlines and bullets can leave an extra blank line.
95 ;; See variable `org-blank-before-new-entry'. (Ed Hirgelt patch)
96 ;; - [[bracket links]] in the agenda are active just as in org-mode buffers.
97 ;; - C-c C-o on a date range displays the agenda for exactly this range.
98 ;; - The default for `org-cycle-include-plain-lists' is back to nil.
99 ;; - Calls to `org-occur' can be stacked by using a prefix argument.
100 ;; - The options `org-show-hierarchy-above' and `org-show-following-heading'
101 ;; now always default to `t', but can be customized differently for
102 ;; different types of sparse trees or jump commands.
103 ;; - Bug fixes.
104 ;;
105 ;; Version 4.49
106 ;; - Agenda views can be made in batch mode from the command line.
107 ;; - `org-store-link' does the right thing in dired-mode.
108 ;; - File links can contain environment variables.
109 ;; - Full Emacs 21 compatibility has been restored.
110 ;; - Bug fixes.
111 ;;
112 ;; Version 4.47
113 ;; - Custom commands may produce an agenda which contains several blocks,
114 ;; each block created by a different agenda command.
115 ;; - Agenda commands can be restricted to the current file, region, subtree.
116 ;; - The timeline command must now be called through the agenda
117 ;; dispatcher (C-c a L). `C-c C-r' no longer works.
118 ;; - Agenda items can be sorted by tag. The *last* tag is used for this.
119 ;; - The prefix and the sorting strategy for agenda items can depend
120 ;; upon the agenda type.
121 ;; - The handling of `mailto:' links can be customized, see the new
122 ;; variable `org-link-mailto-program'.
123 ;; - `mailto' links can specify a subject after a double colon,
124 ;; like [[mailto:carsten@orgmode.org::Org-mode is buggy]].
125 ;; - In the #+STARTUP line, M-TAB completes valid keywords.
126 ;; - In the #+TAGS: line, M-TAB after ":" inserts all currently used tags.
127 ;; - Again full Emacs 21 support: Checkboxes and publishing are fixed.
128 ;; - More minor bug fixes.
129 ;;
130 ;; Version 4.45
131 ;; - Checkbox lists can show statistics about checked items.
132 ;; - C-TAB will cycle the visibility of archived subtrees.
133 ;;; - Documentation about checkboxes has been moved to chapter 5.
134 ;; - Bux fixes.
135 ;;
136 ;; Version 4.44
137 ;; - Clock table can be done for a limited time interval.
138 ;; - Obsolete support for the old outline mode has been removed.
139 ;; - Bug fixes and code cleaning.
140 ;;
141 ;; Version 4.43
142 ;; - Bug fixes
143 ;; - `s' key in the agenda saves all org-mode buffers.
144 ;;
145 ;; Version 4.41
146 ;; - Shift-curser keys can modify inactive time stamps (inactive time
147 ;; stamps are the ones in [...] brackets.
148 ;; - Toggle all checkboxes in a region/below a headline.
149 ;; - Bug fixes.
150 ;;
151 ;;; Code:
152
153 (eval-when-compile
154 (require 'cl)
155 (require 'calendar))
156 ;; For XEmacs, noutline is not yet provided by outline.el, so arrange for
157 ;; the file noutline.el being loaded.
158 (if (featurep 'xemacs) (condition-case nil (require 'noutline)))
159 ;; We require noutline, which might be provided in outline.el
160 (require 'outline) (require 'noutline)
161 ;; Other stuff we need.
162 (require 'time-date)
163 (require 'easymenu)
164
165 ;;; Customization variables
166
167 (defvar org-version "4.54"
168 "The version number of the file org.el.")
169 (defun org-version ()
170 (interactive)
171 (message "Org-mode version %s" org-version))
172
173 ;; Compatibility constants
174 (defconst org-xemacs-p (featurep 'xemacs)) ; not used by org.el itself
175 (defconst org-format-transports-properties-p
176 (let ((x "a"))
177 (add-text-properties 0 1 '(test t) x)
178 (get-text-property 0 'test (format "%s" x)))
179 "Does format transport text properties?")
180
181 (defgroup org nil
182 "Outline-based notes management and organizer."
183 :tag "Org"
184 :group 'outlines
185 :group 'hypermedia
186 :group 'calendar)
187
188 (defgroup org-startup nil
189 "Options concerning startup of Org-mode."
190 :tag "Org Startup"
191 :group 'org)
192
193 (defcustom org-startup-folded t
194 "Non-nil means, entering Org-mode will switch to OVERVIEW.
195 This can also be configured on a per-file basis by adding one of
196 the following lines anywhere in the buffer:
197
198 #+STARTUP: fold
199 #+STARTUP: nofold
200 #+STARTUP: content"
201 :group 'org-startup
202 :type '(choice
203 (const :tag "nofold: show all" nil)
204 (const :tag "fold: overview" t)
205 (const :tag "content: all headlines" content)))
206
207 (defcustom org-startup-truncated t
208 "Non-nil means, entering Org-mode will set `truncate-lines'.
209 This is useful since some lines containing links can be very long and
210 uninteresting. Also tables look terrible when wrapped."
211 :group 'org-startup
212 :type 'boolean)
213
214 (defcustom org-startup-align-all-tables nil
215 "Non-nil means, align all tables when visiting a file.
216 This is useful when the column width in tables is forced with <N> cookies
217 in table fields. Such tables will look correct only after the first re-align.
218 This can also be configured on a per-file basis by adding one of
219 the following lines anywhere in the buffer:
220 #+STARTUP: align
221 #+STARTUP: noalign"
222 :group 'org-startup
223 :type 'boolean)
224
225 (defcustom org-startup-with-deadline-check nil
226 "Non-nil means, entering Org-mode will run the deadline check.
227 This means, if you start editing an org file, you will get an
228 immediate reminder of any due deadlines.
229 This can also be configured on a per-file basis by adding one of
230 the following lines anywhere in the buffer:
231 #+STARTUP: dlcheck
232 #+STARTUP: nodlcheck"
233 :group 'org-startup
234 :type 'boolean)
235
236 (defcustom org-insert-mode-line-in-empty-file nil
237 "Non-nil means insert the first line setting Org-mode in empty files.
238 When the function `org-mode' is called interactively in an empty file, this
239 normally means that the file name does not automatically trigger Org-mode.
240 To ensure that the file will always be in Org-mode in the future, a
241 line enforcing Org-mode will be inserted into the buffer, if this option
242 has been set."
243 :group 'org-startup
244 :type 'boolean)
245
246 (defcustom org-CUA-compatible nil
247 "Non-nil means use alternative key bindings for S-<cursor movement>.
248 Org-mode used S-<cursor movement> for changing timestamps and priorities.
249 S-<cursor movement> is also used for example by `CUA-mode' to select text.
250 If you want to use Org-mode together with `CUA-mode', Org-mode needs to use
251 alternative bindings. Setting this variable to t will replace the following
252 keys both in Org-mode and in the Org-agenda buffer.
253
254 S-RET -> C-S-RET
255 S-up -> M-p
256 S-down -> M-n
257 S-left -> M--
258 S-right -> M-+
259
260 If you do not like the alternative keys, take a look at the variable
261 `org-disputed-keys'.
262
263 This option is only relevant at load-time of Org-mode. Changing it requires
264 a restart of Emacs to become effective."
265 :group 'org-startup
266 :type 'boolean)
267
268 (defvar org-disputed-keys
269 '((S-up [(shift up)] [(meta ?p)])
270 (S-down [(shift down)] [(meta ?n)])
271 (S-left [(shift left)] [(meta ?-)])
272 (S-right [(shift right)] [(meta ?+)])
273 (S-return [(shift return)] [(control shift return)]))
274 "Keys for which Org-mode and other modes compete.
275 This is an alist, cars are symbols for lookup, 1st element is the default key,
276 second element will be used when `org-CUA-compatible' is t.")
277
278 (defun org-key (key)
279 "Select a key according to `org-CUA-compatible'."
280 (nth (if org-CUA-compatible 2 1)
281 (or (assq key org-disputed-keys)
282 (error "Invalid Key %s in `org-key'" key))))
283
284 (defcustom org-ellipsis nil
285 "The ellipsis to use in the Org-mode outline.
286 When nil, just use the standard three dots. When a string, use that instead,
287 and just in Org-mode (which will then use its own display table).
288 Changing this requires executing `M-x org-mode' in a buffer to become
289 effective."
290 :group 'org-startup
291 :type '(choice (const :tag "Default" nil)
292 (string :tag "String" :value "...#")))
293
294 (defvar org-display-table nil
295 "The display table for org-mode, in case `org-ellipsis' is non-nil.")
296
297 (defgroup org-keywords nil
298 "Keywords in Org-mode."
299 :tag "Org Keywords"
300 :group 'org)
301
302 (defcustom org-deadline-string "DEADLINE:"
303 "String to mark deadline entries.
304 A deadline is this string, followed by a time stamp. Should be a word,
305 terminated by a colon. You can insert a schedule keyword and
306 a timestamp with \\[org-deadline].
307 Changes become only effective after restarting Emacs."
308 :group 'org-keywords
309 :type 'string)
310
311 (defcustom org-scheduled-string "SCHEDULED:"
312 "String to mark scheduled TODO entries.
313 A schedule is this string, followed by a time stamp. Should be a word,
314 terminated by a colon. You can insert a schedule keyword and
315 a timestamp with \\[org-schedule].
316 Changes become only effective after restarting Emacs."
317 :group 'org-keywords
318 :type 'string)
319
320 (defcustom org-closed-string "CLOSED:"
321 "String used as the prefix for timestamps logging closing a TODO entry."
322 :group 'org-keywords
323 :type 'string)
324
325 (defcustom org-clock-string "CLOCK:"
326 "String used as prefix for timestamps clocking work hours on an item."
327 :group 'org-keywords
328 :type 'string)
329
330 (defcustom org-comment-string "COMMENT"
331 "Entries starting with this keyword will never be exported.
332 An entry can be toggled between COMMENT and normal with
333 \\[org-toggle-comment].
334 Changes become only effective after restarting Emacs."
335 :group 'org-keywords
336 :type 'string)
337
338 (defcustom org-quote-string "QUOTE"
339 "Entries starting with this keyword will be exported in fixed-width font.
340 Quoting applies only to the text in the entry following the headline, and does
341 not extend beyond the next headline, even if that is lower level.
342 An entry can be toggled between QUOTE and normal with
343 \\[org-toggle-fixed-width-section]."
344 :group 'org-keywords
345 :type 'string)
346
347 (defgroup org-structure nil
348 "Options concerning the general structure of Org-mode files."
349 :tag "Org Structure"
350 :group 'org)
351
352 (defgroup org-cycle nil
353 "Options concerning visibility cycling in Org-mode."
354 :tag "Org Cycle"
355 :group 'org-structure)
356
357 (defcustom org-cycle-global-at-bob t
358 "Cycle globally if cursor is at beginning of buffer and not at a headline.
359 This makes it possible to do global cycling without having to use S-TAB or
360 C-u TAB. For this special case to work, the first line of the buffer
361 must not be a headline - it may be empty ot some other text. When used in
362 this way, `org-cycle-hook' is disables temporarily, to make sure the
363 cursor stays at the beginning of the buffer.
364 When this option is nil, don't do anything special at the beginning
365 of the buffer."
366 :group 'org-cycle
367 :type 'boolean)
368
369 (defcustom org-cycle-emulate-tab t
370 "Where should `org-cycle' emulate TAB.
371 nil Never
372 white Only in completely white lines
373 whitestart Only at the beginning of lines, before the first non-white char.
374 t Everywhere except in headlines
375 If TAB is used in a place where it does not emulate TAB, the current subtree
376 visibility is cycled."
377 :group 'org-cycle
378 :type '(choice (const :tag "Never" nil)
379 (const :tag "Only in completely white lines" white)
380 (const :tag "Before first char in a line" whitestart)
381 (const :tag "Everywhere except in headlines" t)
382 ))
383
384 (defcustom org-cycle-hook '(org-cycle-hide-archived-subtrees
385 org-optimize-window-after-visibility-change)
386 "Hook that is run after `org-cycle' has changed the buffer visibility.
387 The function(s) in this hook must accept a single argument which indicates
388 the new state that was set by the most recent `org-cycle' command. The
389 argument is a symbol. After a global state change, it can have the values
390 `overview', `content', or `all'. After a local state change, it can have
391 the values `folded', `children', or `subtree'."
392 :group 'org-cycle
393 :type 'hook)
394
395 (defgroup org-edit-structure nil
396 "Options concerning structure editing in Org-mode."
397 :tag "Org Edit Structure"
398 :group 'org-structure)
399
400 (defcustom org-odd-levels-only nil
401 "Non-nil means, skip even levels and only use odd levels for the outline.
402 This has the effect that two stars are being added/taken away in
403 promotion/demotion commands. It also influences how levels are
404 handled by the exporters.
405 Changing it requires restart of `font-lock-mode' to become effective
406 for fontification also in regions already fontified.
407 You may also set this on a per-file basis by adding one of the following
408 lines to the buffer:
409
410 #+STARTUP: odd
411 #+STARTUP: oddeven"
412 :group 'org-edit-structure
413 :group 'org-font-lock
414 :type 'boolean)
415
416 (defcustom org-adapt-indentation t
417 "Non-nil means, adapt indentation when promoting and demoting.
418 When this is set and the *entire* text in an entry is indented, the
419 indentation is increased by one space in a demotion command, and
420 decreased by one in a promotion command. If any line in the entry
421 body starts at column 0, indentation is not changed at all."
422 :group 'org-edit-structure
423 :type 'boolean)
424
425 (defcustom org-blank-before-new-entry '((heading . nil)
426 (plain-list-item . nil))
427 "Should `org-insert-heading' leave a blank line before new heading/item?
428 The value is an alist, with `heading' and `plain-list-item' as car,
429 and a boolean flag as cdr."
430 :group 'org-edit-structure
431 :type '(list
432 (cons (const heading) (boolean))
433 (cons (const plain-list-item) (boolean))))
434
435 (defcustom org-insert-heading-hook nil
436 "Hook being run after inserting a new heading."
437 :group 'org-edit-structure
438 :type 'boolean)
439
440 (defcustom org-enable-fixed-width-editor t
441 "Non-nil means, lines starting with \":\" are treated as fixed-width.
442 This currently only means, they are never auto-wrapped.
443 When nil, such lines will be treated like ordinary lines.
444 See also the QUOTE keyword."
445 :group 'org-edit-structure
446 :type 'boolean)
447
448 (defgroup org-sparse-trees nil
449 "Options concerning sparse trees in Org-mode."
450 :tag "Org Sparse Trees"
451 :group 'org-structure)
452
453 (defcustom org-highlight-sparse-tree-matches t
454 "Non-nil means, highlight all matches that define a sparse tree.
455 The highlights will automatically disappear the next time the buffer is
456 changed by an edit command."
457 :group 'org-sparse-trees
458 :type 'boolean)
459
460 (defcustom org-remove-highlights-with-change t
461 "Non-nil means, any change to the buffer will remove temporary highlights.
462 Such highlights are created by `org-occur' and `org-clock-display'.
463 When nil, `C-c C-c needs to be used to get rid of the highlights.
464 The highlights created by `org-preview-latex-fragment' always need
465 `C-c C-c' to be removed."
466 :group 'org-sparse-trees
467 :group 'org-time
468 :type 'boolean)
469
470 (defcustom org-show-hierarchy-above '((default t))
471 "Non-nil means, show full hierarchy when showing a spot in the tree.
472 Turning this off makes sparse trees more compact, but also less clear.
473 Instead of t, this can also be an alist specifying this option for different
474 contexts. Valid contexts are
475 agenda when exposing an entry from the agenda
476 org-goto when using the command `org-goto' on key C-c C-j
477 occur-tree when using the command `org-occur' on key C-c /
478 tags-tree when constructing a sparse tree based on tags matches
479 link-search when exposing search matches associated with a link
480 mark-goto when exposing the jump goal of a mark
481 bookmark-jump when exposing a bookmark location
482 default default for all contexts not set explicitly"
483 :group 'org-sparse-trees
484 :type '(choice
485 (const :tag "Always" t)
486 (const :tag "Never" nil)
487 (repeat :greedy t :tag "Individual contexts"
488 (cons
489 (choice :tag "Context"
490 (const agenda)
491 (const org-goto)
492 (const occur-tree)
493 (const tags-tree)
494 (const link-search)
495 (const mark-goto)
496 (const bookmark-jump)
497 (const default))
498 (boolean)))))
499
500 (defcustom org-show-following-heading '((default t))
501 "Non-nil means, show heading following match in `org-occur'.
502 When doing an `org-occur' it is useful to show the headline which
503 follows the match, even if they do not match the regexp. This makes it
504 easier to edit directly inside the sparse tree. However, if you use
505 `org-occur' mainly as an overview, the following headlines are
506 unnecessary clutter.
507 Instead of t, this can also be an alist specifying this option for different
508 contexts. See `org-show-hierarchy-above' for valid contexts."
509 :group 'org-sparse-trees
510 :type '(choice
511 (const :tag "Always" t)
512 (const :tag "Never" nil)
513 (repeat :greedy t :tag "Individual contexts"
514 (cons
515 (choice :tag "Context"
516 (const agenda)
517 (const org-goto)
518 (const occur-tree)
519 (const tags-tree)
520 (const link-search)
521 (const mark-goto)
522 (const bookmark-jump)
523 (const default))
524 (boolean)))))
525
526 (defcustom org-occur-hook '(org-first-headline-recenter)
527 "Hook that is run after `org-occur' has constructed a sparse tree.
528 This can be used to recenter the window to show as much of the structure
529 as possible."
530 :group 'org-sparse-trees
531 :type 'hook)
532
533 (defgroup org-plain-lists nil
534 "Options concerning plain lists in Org-mode."
535 :tag "Org Plain lists"
536 :group 'org-structure)
537
538 (defcustom org-cycle-include-plain-lists nil
539 "Non-nil means, include plain lists into visibility cycling.
540 This means that during cycling, plain list items will *temporarily* be
541 interpreted as outline headlines with a level given by 1000+i where i is the
542 indentation of the bullet. In all other operations, plain list items are
543 not seen as headlines. For example, you cannot assign a TODO keyword to
544 such an item."
545 :group 'org-plain-lists
546 :type 'boolean)
547
548 (defcustom org-plain-list-ordered-item-terminator t
549 "The character that makes a line with leading number an ordered list item.
550 Valid values are ?. and ?\). To get both terminators, use t. While
551 ?. may look nicer, it creates the danger that a line with leading
552 number may be incorrectly interpreted as an item. ?\) therefore is
553 the safe choice."
554 :group 'org-plain-lists
555 :type '(choice (const :tag "dot like in \"2.\"" ?.)
556 (const :tag "paren like in \"2)\"" ?\))
557 (const :tab "both" t)))
558
559 (defcustom org-auto-renumber-ordered-lists t
560 "Non-nil means, automatically renumber ordered plain lists.
561 Renumbering happens when the sequence have been changed with
562 \\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands,
563 use \\[org-ctrl-c-ctrl-c] to trigger renumbering."
564 :group 'org-plain-lists
565 :type 'boolean)
566
567 (defcustom org-provide-checkbox-statistics t
568 "Non-nil means, update checkbox statistics after insert and toggle.
569 When this is set, checkbox statistics is updated each time you either insert
570 a new checkbox with \\[org-insert-todo-heading] or toggle a checkbox
571 with \\[org-ctrl-c-ctrl-c\\]."
572 :group 'org
573 :type 'boolean)
574
575 (defgroup org-archive nil
576 "Options concerning archiving in Org-mode."
577 :tag "Org Archive"
578 :group 'org-structure)
579
580 (defcustom org-archive-tag "ARCHIVE"
581 "The tag that marks a subtree as archived.
582 An archived subtree does not open during visibility cycling, and does
583 not contribute to the agenda listings."
584 :group 'org-archive
585 :group 'org-keywords
586 :type 'string)
587
588 (defcustom org-agenda-skip-archived-trees t
589 "Non-nil means, the agenda will skip any items located in archived trees.
590 An archived tree is a tree marked with the tag ARCHIVE."
591 :group 'org-archive
592 :group 'org-agenda-display
593 :type 'boolean)
594
595 (defcustom org-cycle-open-archived-trees nil
596 "Non-nil means, `org-cycle' will open archived trees.
597 An archived tree is a tree marked with the tag ARCHIVE.
598 When nil, archived trees will stay folded. You can still open them with
599 normal outline commands like `show-all', but not with the cycling commands."
600 :group 'org-archive
601 :group 'org-cycle
602 :type 'boolean)
603
604 (defcustom org-sparse-tree-open-archived-trees nil
605 "Non-nil means sparse tree construction shows matches in archived trees.
606 When nil, matches in these trees are highlighted, but the trees are kept in
607 collapsed state."
608 :group 'org-archive
609 :group 'org-sparse-trees
610 :type 'boolean)
611
612 (defcustom org-archive-location "%s_archive::"
613 "The location where subtrees should be archived.
614 This string consists of two parts, separated by a double-colon.
615
616 The first part is a file name - when omitted, archiving happens in the same
617 file. %s will be replaced by the current file name (without directory part).
618 Archiving to a different file is useful to keep archived entries from
619 contributing to the Org-mode Agenda.
620
621 The part after the double colon is a headline. The archived entries will be
622 filed under that headline. When omitted, the subtrees are simply filed away
623 at the end of the file, as top-level entries.
624
625 Here are a few examples:
626 \"%s_archive::\"
627 If the current file is Projects.org, archive in file
628 Projects.org_archive, as top-level trees. This is the default.
629
630 \"::* Archived Tasks\"
631 Archive in the current file, under the top-level headline
632 \"* Archived Tasks\".
633
634 \"~/org/archive.org::\"
635 Archive in file ~/org/archive.org (absolute path), as top-level trees.
636
637 \"basement::** Finished Tasks\"
638 Archive in file ./basement (relative path), as level 3 trees
639 below the level 2 heading \"** Finished Tasks\".
640
641 You may set this option on a per-file basis by adding to the buffer a
642 line like
643
644 #+ARCHIVE: basement::** Finished Tasks"
645 :group 'org-archive
646 :type 'string)
647
648 (defcustom org-archive-mark-done t
649 "Non-nil means, mark entries as DONE when they are moved to the archive file."
650 :group 'org-archive
651 :type 'boolean)
652
653 (defcustom org-archive-stamp-time t
654 "Non-nil means, add a time stamp to entries moved to an archive file.
655 The time stamp will be added directly after the TODO state keyword in the
656 first line, so it is probably best to use this in combinations with
657 `org-archive-mark-done'."
658 :group 'org-archive
659 :type 'boolean)
660
661 (defgroup org-table nil
662 "Options concerning tables in Org-mode."
663 :tag "Org Table"
664 :group 'org)
665
666 (defcustom org-enable-table-editor 'optimized
667 "Non-nil means, lines starting with \"|\" are handled by the table editor.
668 When nil, such lines will be treated like ordinary lines.
669
670 When equal to the symbol `optimized', the table editor will be optimized to
671 do the following:
672 - Automatic overwrite mode in front of whitespace in table fields.
673 This makes the structure of the table stay in tact as long as the edited
674 field does not exceed the column width.
675 - Minimize the number of realigns. Normally, the table is aligned each time
676 TAB or RET are pressed to move to another field. With optimization this
677 happens only if changes to a field might have changed the column width.
678 Optimization requires replacing the functions `self-insert-command',
679 `delete-char', and `backward-delete-char' in Org-mode buffers, with a
680 slight (in fact: unnoticeable) speed impact for normal typing. Org-mode is
681 very good at guessing when a re-align will be necessary, but you can always
682 force one with \\[org-ctrl-c-ctrl-c].
683
684 If you would like to use the optimized version in Org-mode, but the
685 un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'.
686
687 This variable can be used to turn on and off the table editor during a session,
688 but in order to toggle optimization, a restart is required.
689
690 See also the variable `org-table-auto-blank-field'."
691 :group 'org-table
692 :type '(choice
693 (const :tag "off" nil)
694 (const :tag "on" t)
695 (const :tag "on, optimized" optimized)))
696
697 (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized)
698 "Non-nil means, use the optimized table editor version for `orgtbl-mode'.
699 In the optimized version, the table editor takes over all simple keys that
700 normally just insert a character. In tables, the characters are inserted
701 in a way to minimize disturbing the table structure (i.e. in overwrite mode
702 for empty fields). Outside tables, the correct binding of the keys is
703 restored.
704
705 The default for this option is t if the optimized version is also used in
706 Org-mode. See the variable `org-enable-table-editor' for details. Changing
707 this variable requires a restart of Emacs to become effective."
708 :group 'org-table
709 :type 'boolean)
710
711 (defgroup org-table-settings nil
712 "Settings for tables in Org-mode."
713 :tag "Org Table Settings"
714 :group 'org-table)
715
716 (defcustom org-table-default-size "5x2"
717 "The default size for newly created tables, Columns x Rows."
718 :group 'org-table-settings
719 :type 'string)
720
721 (defcustom org-table-number-regexp
722 "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*\\|\\(0[xX]\\)?[0-9a-fA-F]+\\)$"
723 "Regular expression for recognizing numbers in table columns.
724 If a table column contains mostly numbers, it will be aligned to the
725 right. If not, it will be aligned to the left.
726
727 The default value of this option is a regular expression which allows
728 anything which looks remotely like a number as used in scientific
729 context. For example, all of the following will be considered a
730 number:
731 12 12.2 2.4e-08 2x10^12 4.034+-0.02 2.7(10) >3.5
732
733 Other options offered by the customize interface are more restrictive."
734 :group 'org-table-settings
735 :type '(choice
736 (const :tag "Positive Integers"
737 "^[0-9]+$")
738 (const :tag "Integers"
739 "^[-+]?[0-9]+$")
740 (const :tag "Floating Point Numbers"
741 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.[0-9]*\\)$")
742 (const :tag "Floating Point Number or Integer"
743 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.?[0-9]*\\)$")
744 (const :tag "Exponential, Floating point, Integer"
745 "^[-+]?[0-9.]+\\([eEdD][-+0-9]+\\)?$")
746 (const :tag "Very General Number-Like, including hex"
747 "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*\\|\\(0[xX]\\)?[0-9a-fA-F]+\\)$")
748 (string :tag "Regexp:")))
749
750 (defcustom org-table-number-fraction 0.5
751 "Fraction of numbers in a column required to make the column align right.
752 In a column all non-white fields are considered. If at least this
753 fraction of fields is matched by `org-table-number-fraction',
754 alignment to the right border applies."
755 :group 'org-table-settings
756 :type 'number)
757
758 (defgroup org-table-editing nil
759 "Bahavior of tables during editing in Org-mode."
760 :tag "Org Table Editing"
761 :group 'org-table)
762
763 (defcustom org-table-automatic-realign t
764 "Non-nil means, automatically re-align table when pressing TAB or RETURN.
765 When nil, aligning is only done with \\[org-table-align], or after column
766 removal/insertion."
767 :group 'org-table-editing
768 :type 'boolean)
769
770 (defcustom org-table-limit-column-width t ;kw
771 "Non-nil means, allow to limit the width of table columns with <N> fields."
772 :group 'org-table-editing
773 :type 'boolean)
774
775 (defcustom org-table-auto-blank-field t
776 "Non-nil means, automatically blank table field when starting to type into it.
777 This only happens when typing immediately after a field motion
778 command (TAB, S-TAB or RET).
779 Only relevant when `org-enable-table-editor' is equal to `optimized'."
780 :group 'org-table-editing
781 :type 'boolean)
782
783 (defcustom org-table-tab-jumps-over-hlines t
784 "Non-nil means, tab in the last column of a table with jump over a hline.
785 If a horizontal separator line is following the current line,
786 `org-table-next-field' can either create a new row before that line, or jump
787 over the line. When this option is nil, a new line will be created before
788 this line."
789 :group 'org-table-editing
790 :type 'boolean)
791
792 (defcustom org-table-tab-recognizes-table.el t
793 "Non-nil means, TAB will automatically notice a table.el table.
794 When it sees such a table, it moves point into it and - if necessary -
795 calls `table-recognize-table'."
796 :group 'org-table-editing
797 :type 'boolean)
798
799 (defgroup org-table-calculation nil
800 "Options concerning tables in Org-mode."
801 :tag "Org Table Calculation"
802 :group 'org-table)
803
804 (defcustom org-table-copy-increment t
805 "Non-nil means, increment when copying current field with \\[org-table-copy-down]."
806 :group 'org-table-calculation
807 :type 'boolean)
808
809 (defcustom org-calc-default-modes
810 '(calc-internal-prec 12
811 calc-float-format (float 5)
812 calc-angle-mode deg
813 calc-prefer-frac nil
814 calc-symbolic-mode nil
815 calc-date-format (YYYY "-" MM "-" DD " " Www (" " HH ":" mm))
816 calc-display-working-message t
817 )
818 "List with Calc mode settings for use in calc-eval for table formulas.
819 The list must contain alternating symbols (Calc modes variables and values).
820 Don't remove any of the default settings, just change the values. Org-mode
821 relies on the variables to be present in the list."
822 :group 'org-table-calculation
823 :type 'plist)
824
825 (defcustom org-table-formula-evaluate-inline t
826 "Non-nil means, TAB and RET evaluate a formula in current table field.
827 If the current field starts with an equal sign, it is assumed to be a formula
828 which should be evaluated as described in the manual and in the documentation
829 string of the command `org-table-eval-formula'. This feature requires the
830 Emacs calc package.
831 When this variable is nil, formula calculation is only available through
832 the command \\[org-table-eval-formula]."
833 :group 'org-table-calculation
834 :type 'boolean)
835
836
837 (defcustom org-table-formula-use-constants t
838 "Non-nil means, interpret constants in formulas in tables.
839 A constant looks like `$c' or `$Grav' and will be replaced before evaluation
840 by the value given in `org-table-formula-constants', or by a value obtained
841 from the `constants.el' package."
842 :group 'org-table-calculation
843 :type 'boolean)
844
845 (defcustom org-table-formula-constants nil
846 "Alist with constant names and values, for use in table formulas.
847 The car of each element is a name of a constant, without the `$' before it.
848 The cdr is the value as a string. For example, if you'd like to use the
849 speed of light in a formula, you would configure
850
851 (setq org-table-formula-constants '((\"c\" . \"299792458.\")))
852
853 and then use it in an equation like `$1*$c'."
854 :group 'org-table-calculation
855 :type '(repeat
856 (cons (string :tag "name")
857 (string :tag "value"))))
858
859 (defcustom org-table-formula-numbers-only nil
860 "Non-nil means, calculate only with numbers in table formulas.
861 Then all input fields will be converted to a number, and the result
862 must also be a number. When nil, calc's full potential is available
863 in table calculations, including symbolics etc."
864 :group 'org-table-calculation
865 :type 'boolean)
866
867 (defcustom org-table-allow-automatic-line-recalculation t
868 "Non-nil means, lines marked with |#| or |*| will be recomputed automatically.
869 Automatically means, when TAB or RET or C-c C-c are pressed in the line."
870 :group 'org-table-calculation
871 :type 'boolean)
872
873 (defgroup org-link nil
874 "Options concerning links in Org-mode."
875 :tag "Org Link"
876 :group 'org)
877
878 (defvar org-link-abbrev-alist-local nil
879 "buffer-local version of `org-link-abbrev-alist', which see.
880 The value of this is taken from the #+LINK lines.")
881 (make-variable-buffer-local 'org-link-abbrev-alist-local)
882
883 (defcustom org-link-abbrev-alist nil
884 "Alist of link abbreviations.
885 The car of each element is a string, to be replaced at the start of a link.
886 The cdrs are replacement values, like (\"linkkey\" . REPLACE). Abbreviated
887 links in Org-mode buffers can have an optional tag after a double colon, e.g.
888
889 [[linkkey::tag][description]]
890
891 If REPLACE is a string, the tag will simply be appended to create the link.
892 If the string contains \"%s\", the tag will be inserted there. REPLACE may
893 also be a function that will be called with the tag as the only argument to
894 create the link. See the manual for examples."
895 :group 'org-link
896 :type 'alist)
897
898 (defcustom org-descriptive-links t
899 "Non-nil means, hide link part and only show description of bracket links.
900 Bracket links are like [[link][descritpion]]. This variable sets the initial
901 state in new org-mode buffers. The setting can then be toggled on a
902 per-buffer basis from the Org->Hyperlinks menu."
903 :group 'org-link
904 :type 'boolean)
905
906 (defcustom org-link-style 'bracket
907 "The style of links to be inserted with \\[org-insert-link].
908 Possible values are:
909 bracket [[link][description]]. This is recommended
910 plain Description \\n link. The old way, no longer recommended."
911 :group 'org-link
912 :type '(choice
913 (const :tag "Bracket (recommended)" bracket)
914 (const :tag "Plain (no longer recommended)" plain)))
915
916 (defcustom org-link-format "%s"
917 "Default format for external, URL-like linkes in the buffer.
918 This is a format string for printf, %s will be replaced by the link text.
919 The recommended value is just \"%s\", since links will be protected by
920 enclosing them in double brackets. If you prefer plain links (see variable
921 `org-link-style'), \"<%s>\" is useful. Some people also recommend an
922 additional URL: prefix, so the format would be \"<URL:%s>\"."
923 :group 'org-link
924 :type '(choice
925 (const :tag "\"%s\" (e.g. http://www.there.com)" "%s")
926 (const :tag "\"<%s>\" (e.g. <http://www.there.com>)" "<%s>")
927 (const :tag "\"<URL:%s>\" (e.g. <URL:http://www.there.com>)" "<URL:%s>")
928 (string :tag "Other" :value "<%s>")))
929
930 (defcustom org-link-file-path-type 'adaptive
931 "How the path name in file links should be stored.
932 Valid values are:
933
934 relative relative to the current directory, i.e. the directory of the file
935 into which the link is being inserted.
936 absolute absolute path, if possible with ~ for home directory.
937 noabbrev absolute path, no abbreviation of home directory.
938 adaptive Use relative path for files in the current directory and sub-
939 directories of it. For other files, use an absolute path."
940 :group 'org-link
941 :type '(choice
942 (const relative)
943 (const absolute)
944 (const noabbrev)
945 (const adaptive)))
946
947 (defcustom org-activate-links '(bracket angle plain radio tag date)
948 "Types of links that should be activated in Org-mode files.
949 This is a list of symbols, each leading to the activation of a certain link
950 type. In principle, it does not hurt to turn on most link types - there may
951 be a small gain when turning off unused link types. The types are:
952
953 bracket The recommended [[link][description]] or [[link]] links with hiding.
954 angular Links in angular brackes that may contain whitespace like
955 <bbdb:Carsten Dominik>.
956 plain Plain links in normal text, no whitespace, like http://google.com.
957 radio Text that is matched by a radio target, see manual for details.
958 tag Tag settings in a headline (link to tag search).
959 date Time stamps (link to calendar).
960 camel CamelCase words defining text searches.
961
962 Changing this variable requires a restart of Emacs to become effective."
963 :group 'org-link
964 :type '(set (const :tag "Double bracket links (new style)" bracket)
965 (const :tag "Angular bracket links (old style)" angular)
966 (const :tag "plain text links" plain)
967 (const :tag "Radio target matches" radio)
968 (const :tag "Tags" tag)
969 (const :tag "Timestamps" date)
970 (const :tag "CamelCase words" camel)))
971
972 (defgroup org-link-store nil
973 "Options concerning storing links in Org-mode"
974 :tag "Org Store Link"
975 :group 'org-link)
976
977 (defcustom org-context-in-file-links t
978 "Non-nil means, file links from `org-store-link' contain context.
979 A search string will be added to the file name with :: as separator and
980 used to find the context when the link is activated by the command
981 `org-open-at-point'.
982 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
983 negates this setting for the duration of the command."
984 :group 'org-link-store
985 :type 'boolean)
986
987 (defcustom org-file-link-context-use-camel-case nil
988 "Non-nil means, use CamelCase to store a search context in a file link.
989 When nil, the search string simply consists of the words of the string.
990 CamelCase is deprecated, and support for it may be dropped in the future."
991 :group 'org-link-store
992 :type 'boolean)
993
994 (defcustom org-keep-stored-link-after-insertion nil
995 "Non-nil means, keep link in list for entire session.
996
997 The command `org-store-link' adds a link pointing to the current
998 location to an internal list. These links accumulate during a session.
999 The command `org-insert-link' can be used to insert links into any
1000 Org-mode file (offering completion for all stored links). When this
1001 option is nil, every link which has been inserted once using \\[org-insert-link]
1002 will be removed from the list, to make completing the unused links
1003 more efficient."
1004 :group 'org-link-store
1005 :type 'boolean)
1006
1007 (defcustom org-usenet-links-prefer-google nil
1008 "Non-nil means, `org-store-link' will create web links to Google groups.
1009 When nil, Gnus will be used for such links.
1010 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
1011 negates this setting for the duration of the command."
1012 :group 'org-link-store
1013 :type 'boolean)
1014
1015 (defgroup org-link-follow nil
1016 "Options concerning following links in Org-mode"
1017 :tag "Org Follow Link"
1018 :group 'org-link)
1019
1020 (defcustom org-tab-follows-link nil
1021 "Non-nil means, on links TAB will follow the link.
1022 Needs to be set before org.el is loaded."
1023 :group 'org-link-follow
1024 :type 'boolean)
1025
1026 (defcustom org-return-follows-link nil
1027 "Non-nil means, on links RET will follow the link.
1028 Needs to be set before org.el is loaded."
1029 :group 'org-link-follow
1030 :type 'boolean)
1031
1032 (defcustom org-mouse-1-follows-link t
1033 "Non-nil means, mouse-1 on a link will follow the link.
1034 A longer mouse click will still set point. Does not wortk on XEmacs.
1035 Needs to be set before org.el is loaded."
1036 :group 'org-link-follow
1037 :type 'boolean)
1038
1039 (defcustom org-mark-ring-length 4
1040 "Number of different positions to be recorded in the ring
1041 Changing this requires a restart of Emacs to work correctly."
1042 :group 'org-link-follow
1043 :type 'interger)
1044
1045 (defcustom org-link-frame-setup
1046 '((vm . vm-visit-folder-other-frame)
1047 (gnus . gnus-other-frame)
1048 (file . find-file-other-window))
1049 "Setup the frame configuration for following links.
1050 When following a link with Emacs, it may often be useful to display
1051 this link in another window or frame. This variable can be used to
1052 set this up for the different types of links.
1053 For VM, use any of
1054 `vm-visit-folder'
1055 `vm-visit-folder-other-frame'
1056 For Gnus, use any of
1057 `gnus'
1058 `gnus-other-frame'
1059 For FILE, use any of
1060 `find-file'
1061 `find-file-other-window'
1062 `find-file-other-frame'
1063 For the calendar, use the variable `calendar-setup'.
1064 For BBDB, it is currently only possible to display the matches in
1065 another window."
1066 :group 'org-link-follow
1067 :type '(list
1068 (cons (const vm)
1069 (choice
1070 (const vm-visit-folder)
1071 (const vm-visit-folder-other-window)
1072 (const vm-visit-folder-other-frame)))
1073 (cons (const gnus)
1074 (choice
1075 (const gnus)
1076 (const gnus-other-frame)))
1077 (cons (const file)
1078 (choice
1079 (const find-file)
1080 (const find-file-other-window)
1081 (const find-file-other-frame)))))
1082
1083 (defcustom org-display-internal-link-with-indirect-buffer nil
1084 "Non-nil means, use indirect buffer to display infile links.
1085 Activating internal links (from one location in a file to another location
1086 in the same file) normally just jumps to the location. When the link is
1087 activated with a C-u prefix (or with mouse-3), the link is displayed in
1088 another window. When this option is set, the other window actually displays
1089 an indirect buffer clone of the current buffer, to avoid any visibility
1090 changes to the current buffer."
1091 :group 'org-link-follow
1092 :type 'boolean)
1093
1094
1095 (defcustom org-open-non-existing-files nil
1096 "Non-nil means, `org-open-file' will open non-existing file.
1097 When nil, an error will be generated."
1098 :group 'org-link-follow
1099 :type 'boolean)
1100
1101 (defcustom org-link-mailto-program '(browse-url "mailto:%a?subject=%s")
1102 "Function and arguments to call for following mailto links.
1103 This is a list with the first element being a lisp function, and the
1104 remaining elements being arguments to the function. In string arguments,
1105 %a will be replaced by the address, and %s will be replaced by the subject
1106 if one was given like in <mailto:arthur@galaxy.org::this subject>."
1107 :group 'org-link-follow
1108 :type '(choice
1109 (const :tag "browse-url" (browse-url-mail "mailto:%a?subject=%s"))
1110 (const :tag "compose-mail" (compose-mail "%a" "%s"))
1111 (const :tag "message-mail" (message-mail "%a" "%s"))
1112 (cons :tag "other" (function) (repeat :tag "argument" sexp))))
1113
1114 (defcustom org-confirm-shell-link-function 'yes-or-no-p
1115 "Non-nil means, ask for confirmation before executing shell links.
1116 Shell links can be dangerous, just thing about a link
1117
1118 [[shell:rm -rf ~/*][Google Search]]
1119
1120 This link would show up in your Org-mode document as \"Google Search\"
1121 but really it would remove your entire home directory.
1122 Therefore I *definitely* advise against setting this variable to nil.
1123 Just change it to `y-or-n-p' of you want to confirm with a single key press
1124 rather than having to type \"yes\"."
1125 :group 'org-link-follow
1126 :type '(choice
1127 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1128 (const :tag "with y-or-n (faster)" y-or-n-p)
1129 (const :tag "no confirmation (dangerous)" nil)))
1130
1131 (defcustom org-confirm-elisp-link-function 'yes-or-no-p
1132 "Non-nil means, ask for confirmation before executing elisp links.
1133 Elisp links can be dangerous, just think about a link
1134
1135 [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]]
1136
1137 This link would show up in your Org-mode document as \"Google Search\"
1138 but really it would remove your entire home directory.
1139 Therefore I *definitely* advise against setting this variable to nil.
1140 Just change it to `y-or-n-p' of you want to confirm with a single key press
1141 rather than having to type \"yes\"."
1142 :group 'org-link-follow
1143 :type '(choice
1144 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1145 (const :tag "with y-or-n (faster)" y-or-n-p)
1146 (const :tag "no confirmation (dangerous)" nil)))
1147
1148 (defconst org-file-apps-defaults-gnu
1149 '((remote . emacs)
1150 (t . mailcap))
1151 "Default file applications on a UNIX or GNU/Linux system.
1152 See `org-file-apps'.")
1153
1154 (defconst org-file-apps-defaults-macosx
1155 '((remote . emacs)
1156 (t . "open %s")
1157 ("ps" . "gv %s")
1158 ("ps.gz" . "gv %s")
1159 ("eps" . "gv %s")
1160 ("eps.gz" . "gv %s")
1161 ("dvi" . "xdvi %s")
1162 ("fig" . "xfig %s"))
1163 "Default file applications on a MacOS X system.
1164 The system \"open\" is known as a default, but we use X11 applications
1165 for some files for which the OS does not have a good default.
1166 See `org-file-apps'.")
1167
1168 (defconst org-file-apps-defaults-windowsnt
1169 (list
1170 '(remote . emacs)
1171 (cons t
1172 (list (if (featurep 'xemacs)
1173 'mswindows-shell-execute
1174 'w32-shell-execute)
1175 "open" 'file)))
1176 "Default file applications on a Windows NT system.
1177 The system \"open\" is used for most files.
1178 See `org-file-apps'.")
1179
1180 (defcustom org-file-apps
1181 '(
1182 ("txt" . emacs)
1183 ("tex" . emacs)
1184 ("ltx" . emacs)
1185 ("org" . emacs)
1186 ("el" . emacs)
1187 ("bib" . emacs)
1188 )
1189 "External applications for opening `file:path' items in a document.
1190 Org-mode uses system defaults for different file types, but
1191 you can use this variable to set the application for a given file
1192 extension. The entries in this list are cons cells where the car identifies
1193 files and the cdr the corresponding command. Possible values for the
1194 file identifier are
1195 \"ext\" A string identifying an extension
1196 `directory' Matches a directory
1197 `remote' Matches a remote file, accessible through tramp or efs.
1198 Remote files most likely should be visited through Emacs
1199 because external applications cannot handle such paths.
1200 t Default for all remaining files
1201
1202 Possible values for the command are:
1203 `emacs' The file will be visited by the current Emacs process.
1204 `default' Use the default application for this file type.
1205 string A command to be executed by a shell; %s will be replaced
1206 by the path to the file.
1207 sexp A Lisp form which will be evaluated. The file path will
1208 be available in the Lisp variable `file'.
1209 For more examples, see the system specific constants
1210 `org-file-apps-defaults-macosx'
1211 `org-file-apps-defaults-windowsnt'
1212 `org-file-apps-defaults-gnu'."
1213 :group 'org-link-follow
1214 :type '(repeat
1215 (cons (choice :value ""
1216 (string :tag "Extension")
1217 (const :tag "Default for unrecognized files" t)
1218 (const :tag "Remote file" remote)
1219 (const :tag "Links to a directory" directory))
1220 (choice :value ""
1221 (const :tag "Visit with Emacs" emacs)
1222 (const :tag "Use system default" default)
1223 (string :tag "Command")
1224 (sexp :tag "Lisp form")))))
1225
1226 (defcustom org-mhe-search-all-folders nil
1227 "Non-nil means, that the search for the mh-message will be extended to
1228 all folders if the message cannot be found in the folder given in the link.
1229 Searching all folders is very effective with one of the search engines
1230 supported by MH-E, but will be slow with pick."
1231 :group 'org-link-follow
1232 :type 'boolean)
1233
1234 (defgroup org-remember nil
1235 "Options concerning interaction with remember.el."
1236 :tag "Org Remember"
1237 :group 'org)
1238
1239 (defcustom org-directory "~/org"
1240 "Directory with org files.
1241 This directory will be used as default to prompt for org files.
1242 Used by the hooks for remember.el."
1243 :group 'org-remember
1244 :type 'directory)
1245
1246 (defcustom org-default-notes-file "~/.notes"
1247 "Default target for storing notes.
1248 Used by the hooks for remember.el. This can be a string, or nil to mean
1249 the value of `remember-data-file'."
1250 :group 'org-remember
1251 :type '(choice
1252 (const :tag "Default from remember-data-file" nil)
1253 file))
1254
1255 (defcustom org-remember-templates nil
1256 "Templates for the creation of remember buffers.
1257 When nil, just let remember make the buffer.
1258 When not nil, this is a list of 3-element lists. In each entry, the first
1259 element is a character, a unique key to select this template.
1260 The second element is the template. The third element is optional and can
1261 specify a destination file for remember items created with this template.
1262 The default file is given by `org-default-notes-file'.
1263
1264 The template specifies the structure of the remember buffer. It should have
1265 a first line starting with a star, to act as the org-mode headline.
1266 Furthermore, the following %-escapes will be replaced with content:
1267 %t time stamp, date only
1268 %T time stamp with date and time
1269 %u inactive time stamp, date only
1270 %U inactive time stamp with date and time
1271 %n user name
1272 %a annotation, normally the link created with org-store-link
1273 %i initial content, the region when remember is called with C-u.
1274 If %i is indented, the entire inserted text will be indented as well.
1275 %? This will be removed, and the cursor placed at this position."
1276 :group 'org-remember
1277 :type '(repeat :tag "enabled"
1278 (list :value (?a "\n" nil)
1279 (character :tag "Selection Key")
1280 (string :tag "Template")
1281 (file :tag "Destination file (optional)"))))
1282
1283 (defcustom org-reverse-note-order nil
1284 "Non-nil means, store new notes at the beginning of a file or entry.
1285 When nil, new notes will be filed to the end of a file or entry."
1286 :group 'org-remember
1287 :type '(choice
1288 (const :tag "Reverse always" t)
1289 (const :tag "Reverse never" nil)
1290 (repeat :tag "By file name regexp"
1291 (cons regexp boolean))))
1292
1293 (defgroup org-todo nil
1294 "Options concerning TODO items in Org-mode."
1295 :tag "Org TODO"
1296 :group 'org)
1297
1298 (defcustom org-todo-keywords '("TODO" "DONE")
1299 "List of TODO entry keywords.
1300 \\<org-mode-map>By default, this is '(\"TODO\" \"DONE\"). The last entry in the list is
1301 considered to mean that the entry is \"done\". All the other mean that
1302 action is required, and will make the entry show up in todo lists, diaries
1303 etc.
1304 The command \\[org-todo] cycles an entry through these states, and an
1305 additional state where no keyword is present. For details about this
1306 cycling, see also the variable `org-todo-interpretation'
1307 Changes become only effective after restarting Emacs."
1308 :group 'org-todo
1309 :group 'org-keywords
1310 :type '(repeat (string :tag "Keyword")))
1311
1312 (defcustom org-todo-interpretation 'sequence
1313 "Controls how TODO keywords are interpreted.
1314 This variable is only relevant if `org-todo-keywords' contains more than two
1315 states. \\<org-mode-map>Possible values are `sequence' and `type'.
1316
1317 When `sequence', \\[org-todo] will always switch to the next state in the
1318 `org-todo-keywords' list. When `type', \\[org-todo] only cycles from state
1319 to state when executed several times in direct succession. Otherwise, it
1320 switches directly to DONE from any state.
1321 See the manual for more information."
1322 :group 'org-todo
1323 :group 'org-keywords
1324 :type '(choice (const sequence)
1325 (const type)))
1326
1327 (defcustom org-after-todo-state-change-hook nil
1328 "Hook which is run after the state of a TODO item was changed.
1329 The new state (a string with a TODO keyword, or nil) is available in the
1330 Lisp variable `state'."
1331 :group 'org-todo
1332 :type 'hook)
1333
1334 (defcustom org-log-done nil
1335 "When set, insert a (non-active) time stamp when TODO entry is marked DONE.
1336 When the state of an entry is changed from nothing to TODO, remove a previous
1337 closing date.
1338
1339 This can also be a list of symbols indicating under which conditions
1340 the time stamp recording the action should be annotated with a short note.
1341 Valid members of this list are
1342
1343 done Offer to record a note when marking entries done
1344 clock-out Offer to record a note when clocking out of an item.
1345
1346 A separate window will then pop up and allow you to type a note.
1347 After finishing with C-c C-c, the note will be added directly after the
1348 timestamp, as a plain list item. See also the variable
1349 `org-log-note-headings'.
1350
1351 Logging can also be configured on a per-file basis by adding one of
1352 the following lines anywhere in the buffer:
1353
1354 #+STARTUP: logging
1355 #+STARTUP: nologging"
1356 ;; FIXME: in-buffer words for notes???????
1357 :group 'org-todo
1358 :type '(choice
1359 (const :tag "off" nil)
1360 (const :tag "on" t)
1361 (set :tag "on, with notes" :greedy t :value (done)
1362 (const done) (const clock-out))))
1363
1364 (defcustom org-log-note-headings '((done . "CLOSING NOTE") (clock-out . ""))
1365 "Headings for notes added when clocking out or closing TODO items.
1366 The value is an alist, with the car being a sympol indicating the note
1367 context, and the cdr is the heading to be used. The heading may also be the
1368 empty string."
1369 :group 'org-todo
1370 :type '(list :greedy t
1371 (cons (const :tag "Heading when closing an item" done) string)
1372 (cons (const :tag "Heading when clocking out" clock-out) string)))
1373
1374 (defgroup org-priorities nil
1375 "Priorities in Org-mode."
1376 :tag "Org Priorities"
1377 :group 'org-todo)
1378
1379 (defcustom org-default-priority ?B
1380 "The default priority of TODO items.
1381 This is the priority an item get if no explicit priority is given."
1382 :group 'org-priorities
1383 :type 'character)
1384
1385 (defcustom org-lowest-priority ?C
1386 "The lowest priority of TODO items. A character like ?A, ?B etc."
1387 :group 'org-priorities
1388 :type 'character)
1389
1390 (defgroup org-time nil
1391 "Options concerning time stamps and deadlines in Org-mode."
1392 :tag "Org Time"
1393 :group 'org)
1394
1395 (defcustom org-insert-labeled-timestamps-at-point nil
1396 "Non-nil means, SCHEDULED and DEADLINE timestamps are inserted at point.
1397 When nil, these labeled time stamps are forces into the second line of an
1398 entry, just after the headline. When scheduling from the global TODO list,
1399 the time stamp will always be forced into the second line."
1400 :group 'org-time
1401 :type 'boolean)
1402
1403 (defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
1404 "Formats for `format-time-string' which are used for time stamps.
1405 It is not recommended to change this constant.")
1406
1407 (defcustom org-time-stamp-rounding-minutes 0
1408 "Number of minutes to round time stamps to upon insertion.
1409 When zero, insert the time unmodified. Useful rounding numbers
1410 should be factors of 60, so for example 5, 10, 15.
1411 When this is not zero, you can still force an exact time-stamp by using
1412 a double prefix argument to a time-stamp command like `C-c .' or `C-c !'."
1413 :group 'org-time
1414 :type 'integer)
1415
1416 (defcustom org-display-custom-times nil
1417 "Non-nil means, overlay custom formats over all time stamps.
1418 The formats are defined through the variable `org-time-stamp-custom-formats'.
1419 To turn this on on a per-file basis, insert anywhere in the file:
1420 #+STARTUP: customtime"
1421 :group 'org-time
1422 :set 'set-default
1423 :type 'sexp)
1424 (make-variable-buffer-local 'org-display-custom-times)
1425
1426 (defcustom org-time-stamp-custom-formats
1427 '("<%m/%d/%y %a>" . "<%m/%d/%y %a %H:%M>") ; american
1428 "Custom formats for time stamps. See `format-time-string' for the syntax.
1429 These are overlayed over the default ISO format if the variable
1430 `org-display-custom-times' is set."
1431 :group 'org-time
1432 :type 'sexp)
1433
1434 (defcustom org-deadline-warning-days 30
1435 "No. of days before expiration during which a deadline becomes active.
1436 This variable governs the display in sparse trees and in the agenda."
1437 :group 'org-time
1438 :type 'number)
1439
1440 (defcustom org-popup-calendar-for-date-prompt t
1441 "Non-nil means, pop up a calendar when prompting for a date.
1442 In the calendar, the date can be selected with mouse-1. However, the
1443 minibuffer will also be active, and you can simply enter the date as well.
1444 When nil, only the minibuffer will be available."
1445 :group 'org-time
1446 :type 'boolean)
1447
1448 (defcustom org-calendar-follow-timestamp-change t
1449 "Non-nil means, make the calendar window follow timestamp changes.
1450 When a timestamp is modified and the calendar window is visible, it will be
1451 moved to the new date."
1452 :group 'org-time
1453 :type 'boolean)
1454
1455 (defgroup org-tags nil
1456 "Options concerning tags in Org-mode."
1457 :tag "Org Tags"
1458 :group 'org)
1459
1460 (defcustom org-tag-alist nil
1461 "List of tags allowed in Org-mode files.
1462 When this list is nil, Org-mode will base TAG input on what is already in the
1463 buffer.
1464 The value of this variable is an alist, the car may be (and should) be a
1465 character that is used to select that tag through the fast-tag-selection
1466 interface. See the manual for details."
1467 :group 'org-tags
1468 :type '(repeat
1469 (choice
1470 (cons (string :tag "Tag name")
1471 (character :tag "Access char"))
1472 (const :tag "Start radio group" (:startgroup))
1473 (const :tag "End radio group" (:endgroup)))))
1474
1475 (defcustom org-use-fast-tag-selection 'auto
1476 "Non-nil means, use fast tag selection scheme.
1477 This is a special interface to select and deselect tags with single keys.
1478 When nil, fast selection is never used.
1479 When the symbol `auto', fast selection is used if and only if selection
1480 characters for tags have been configured, either through the variable
1481 `org-tag-alist' or through a #+TAGS line in the buffer.
1482 When t, fast selection is always used and selection keys are assigned
1483 automatically if necessary."
1484 :group 'org-tags
1485 :type '(choice
1486 (const :tag "Always" t)
1487 (const :tag "Never" nil)
1488 (const :tag "When selection characters are configured" 'auto)))
1489
1490 (defcustom org-fast-tag-selection-single-key nil
1491 "Non-nil means, fast tag selection exits after first change.
1492 When nil, you have to press RET to exit it.
1493 During fast tag selection, you can toggle this flag with `C-c'."
1494 :group 'org-tags
1495 :type 'boolean)
1496
1497 (defcustom org-tags-column 48
1498 "The column to which tags should be indented in a headline.
1499 If this number is positive, it specifies the column. If it is negative,
1500 it means that the tags should be flushright to that column. For example,
1501 -79 works well for a normal 80 character screen."
1502 :group 'org-tags
1503 :type 'integer)
1504
1505 (defcustom org-auto-align-tags t
1506 "Non-nil means, realign tags after pro/demotion of TODO state change.
1507 These operations change the length of a headline and therefore shift
1508 the tags around. With this options turned on, after each such operation
1509 the tags are again aligned to `org-tags-column'."
1510 :group 'org-tags
1511 :type 'boolean)
1512
1513 (defcustom org-use-tag-inheritance t
1514 "Non-nil means, tags in levels apply also for sublevels.
1515 When nil, only the tags directly given in a specific line apply there.
1516 If you turn off this option, you very likely want to turn on the
1517 companion option `org-tags-match-list-sublevels'."
1518 :group 'org-tags
1519 :type 'boolean)
1520
1521 (defcustom org-tags-match-list-sublevels nil
1522 "Non-nil means list also sublevels of headlines matching tag search.
1523 Because of tag inheritance (see variable `org-use-tag-inheritance'),
1524 the sublevels of a headline matching a tag search often also match
1525 the same search. Listing all of them can create very long lists.
1526 Setting this variable to nil causes subtrees of a match to be skipped.
1527 This option is off by default, because inheritance in on. If you turn
1528 inheritance off, you very likely want to turn this option on.
1529
1530 As a special case, if the tag search is restricted to TODO items, the
1531 value of this variable is ignored and sublevels are always checked, to
1532 make sure all corresponding TODO items find their way into the list."
1533 :group 'org-tags
1534 :type 'boolean)
1535
1536 (defvar org-tags-history nil
1537 "History of minibuffer reads for tags.")
1538 (defvar org-last-tags-completion-table nil
1539 "The last used completion table for tags.")
1540
1541 (defgroup org-agenda nil
1542 "Options concerning agenda display Org-mode."
1543 :tag "Org Agenda"
1544 :group 'org)
1545
1546 (defvar org-category nil
1547 "Variable used by org files to set a category for agenda display.
1548 Such files should use a file variable to set it, for example
1549
1550 -*- mode: org; org-category: \"ELisp\"
1551
1552 or contain a special line
1553
1554 #+CATEGORY: ELisp
1555
1556 If the file does not specify a category, then file's base name
1557 is used instead.")
1558 (make-variable-buffer-local 'org-category)
1559
1560 (defcustom org-agenda-files nil
1561 "The files to be used for agenda display.
1562 Entries may be added to this list with \\[org-agenda-file-to-front] and removed with
1563 \\[org-remove-file]. You can also use customize to edit the list.
1564
1565 If the value of the variable is not a list but a single file name, then
1566 the list of agenda files is actually stored and maintained in that file, one
1567 agenda file per line."
1568 :group 'org-agenda
1569 :type '(choice
1570 (repeat :tag "List of files" file)
1571 (file :tag "Store list in a file\n" :value "~/.agenda_files")))
1572
1573 (defcustom org-agenda-custom-commands ;'(("w" todo "WAITING"))
1574 '(("w" todo "WAITING" ((aaa 1) (bbb 2))))
1575 "Custom commands for the agenda.
1576 These commands will be offered on the splash screen displayed by the
1577 agenda dispatcher \\[org-agenda]. Each entry is a list like this:
1578
1579 (key type match options)
1580
1581 key The key (a single char as a string) to be associated with the command.
1582 type The command type, any of the following symbols:
1583 todo Entries with a specific TODO keyword, in all agenda files.
1584 tags Tags match in all agenda files.
1585 tags-todo Tags match in all agenda files, TODO entries only.
1586 todo-tree Sparse tree of specific TODO keyword in *current* file.
1587 tags-tree Sparse tree with all tags matches in *current* file.
1588 occur-tree Occur sparse tree for *current* file.
1589 match What to search for:
1590 - a single keyword for TODO keyword searches
1591 - a tags match expression for tags searches
1592 - a regular expression for occur searches
1593 options A list of option setttings, similar to that in a let form, so like
1594 this: ((opt1 val1) (opt2 val2) ...)
1595
1596 You can also define a set of commands, to create a composite agenda buffer.
1597 In this case, an entry looks like this:
1598
1599 (key desc (cmd1 cmd2 ...) general-options)
1600
1601 where
1602
1603 desc A description string to be displayed in the dispatcher menu.
1604 cmd An agenda command, similar to the above. However, tree commands
1605 are no allowed, but instead you can get agenda and global todo list.
1606 So valid commands for a set are:
1607 (agenda)
1608 (alltodo)
1609 (todo \"match\" options)
1610 (tags \"match\" options )
1611 (tags-todo \"match\" options)
1612
1613 Each command can carry a list of options, and another set of options can be
1614 given for the whole set of commands. Individual command options take
1615 precedence over the general options."
1616 :group 'org-agenda
1617 :type '(repeat
1618 (choice
1619 (list :tag "Single command"
1620 (string :tag "Key")
1621 (choice
1622 (const :tag "Tags search (all agenda files)" tags)
1623 (const :tag "Tags search of TODO entries (all agenda files)" tags-todo)
1624 (const :tag "TODO keyword search (all agenda files)" todo)
1625 (const :tag "Tags sparse tree (current buffer)" tags-tree)
1626 (const :tag "TODO keyword tree (current buffer)" todo-tree)
1627 (const :tag "Occur tree (current buffer)" occur-tree))
1628 (string :tag "Match")
1629 (repeat :tag "Local options"
1630 (list (variable :tag "Option") (sexp :tag "Value"))))
1631 (list :tag "Command series, all agenda files"
1632 (string :tag "Key")
1633 (string :tag "Description")
1634 (repeat
1635 (choice
1636 (const :tag "Agenda" (agenda))
1637 (const :tag "TODO list" (alltodo))
1638 (list :tag "Tags search"
1639 (const :format "" tags)
1640 (string :tag "Match")
1641 (repeat :tag "Local options"
1642 (list (variable :tag "Option")
1643 (sexp :tag "Value"))))
1644
1645 (list :tag "Tags search, TODO entries only"
1646 (const :format "" tags-todo)
1647 (string :tag "Match")
1648 (repeat :tag "Local options"
1649 (list (variable :tag "Option")
1650 (sexp :tag "Value"))))
1651
1652 (list :tag "TODO keyword search"
1653 (const :format "" todo)
1654 (string :tag "Match")
1655 (repeat :tag "Local options"
1656 (list (variable :tag "Option")
1657 (sexp :tag "Value"))))))
1658 (repeat :tag "General options"
1659 (list (variable :tag "Option")
1660 (sexp :tag "Value")))))))
1661
1662 (defcustom org-agenda-todo-list-sublevels t
1663 "Non-nil means, check also the sublevels of a TODO entry for TODO entries.
1664 When nil, the sublevels of a TODO entry are not checked, resulting in
1665 potentially much shorter TODO lists."
1666 :group 'org-agenda
1667 :group 'org-todo
1668 :type 'boolean)
1669
1670 (defcustom org-agenda-todo-ignore-scheduled nil
1671 "Non-nil means, don't show scheduled entries in the global todo list.
1672 The idea behind this is that by scheduling it, you have already taken care
1673 of this item."
1674 :group 'org-agenda
1675 :group 'org-todo
1676 :type 'boolean)
1677
1678 (defcustom org-agenda-todo-ignore-deadlines nil
1679 "Non-nil means, don't show near deadline entries in the global todo list.
1680 Near means closer than `org-deadline-warning-days' days.
1681 The idea behind this is that such items will appear in the agenda anyway."
1682 :group 'org-agenda
1683 :group 'org-todo
1684 :type 'boolean)
1685
1686
1687 (defcustom org-timeline-show-empty-dates 3
1688 "Non-nil means, `org-timeline' also shows dates without an entry.
1689 When nil, only the days which actually have entries are shown.
1690 When t, all days between the first and the last date are shown.
1691 When an integer, show also empty dates, but if there is a gap of more than
1692 N days, just insert a special line indicating the size of the gap."
1693 :group 'org-agenda
1694 :type '(choice
1695 (const :tag "None" nil)
1696 (const :tag "All" t)
1697 (number :tag "at most")))
1698
1699 (defcustom org-agenda-include-all-todo nil
1700 "Set means weekly/daily agenda will always contain all TODO entries.
1701 The TODO entries will be listed at the top of the agenda, before
1702 the entries for specific days."
1703 :group 'org-agenda
1704 :type 'boolean)
1705
1706 (defcustom org-agenda-include-diary nil
1707 "If non-nil, include in the agenda entries from the Emacs Calendar's diary."
1708 :group 'org-agenda
1709 :type 'boolean)
1710
1711 (defcustom org-calendar-to-agenda-key [?c]
1712 "The key to be installed in `calendar-mode-map' for switching to the agenda.
1713 The command `org-calendar-goto-agenda' will be bound to this key. The
1714 default is the character `c' because then `c' can be used to switch back and
1715 forth between agenda and calendar."
1716 :group 'org-agenda
1717 :type 'sexp)
1718
1719 (defgroup org-agenda-setup nil
1720 "Options concerning setting up the Agenda window in Org Mode."
1721 :tag "Org Agenda Window Setup"
1722 :group 'org-agenda)
1723
1724 (defcustom org-agenda-window-setup 'reorganize-frame
1725 "How the agenda buffer should be displayed.
1726 Possible values for this option are:
1727
1728 current-window Show agenda in the current window, keeping all other windows.
1729 other-frame Use `switch-to-buffer-other-frame' to display agenda.
1730 other-window Use `switch-to-buffer-other-window' to display agenda.
1731 reorganize-frame Show only two windows on the current frame, the current
1732 window and the agenda. Also, if the option
1733 `org-fit-agenda-window' is set, resize the agenda window to
1734 try to show as much as possible of the buffer content.
1735 See also the variable `org-agenda-restore-windows-after-quit'."
1736 :group 'org-agenda-setup
1737 :type '(choice
1738 (const current-window)
1739 (const other-frame)
1740 (const other-window)
1741 (const reorganize-frame)))
1742
1743 (defcustom org-agenda-restore-windows-after-quit nil
1744 "Non-nil means, restore window configuration open exiting agenda.
1745 Before the window configuration is changed for displaying the agenda,
1746 the current status is recorded. When the agenda is exited with
1747 `q' or `x' and this option is set, the old state is restored. If
1748 `org-agenda-window-setup' is `other-frame', the value of this
1749 option will be ignored.."
1750 :group 'org-agenda-setup
1751 :type 'boolean)
1752
1753 ;; FIXME: I think this variable could be removed.
1754 (defcustom org-select-agenda-window t
1755 "Non-nil means, after creating an agenda, move cursor into Agenda window.
1756 When nil, cursor will remain in the current window."
1757 :group 'org-agenda-setup
1758 :type 'boolean)
1759
1760 ;; FIXME: I think this variable could be removed.
1761 (defcustom org-fit-agenda-window t
1762 "Non-nil means, change window size of agenda to fit content.
1763 This is only effective if `org-agenda-window-setup' is `reorganize-frame'."
1764 :group 'org-agenda-setup
1765 :type 'boolean)
1766
1767 (defcustom org-finalize-agenda-hook nil
1768 "Hook run just before displaying an agenda buffer."
1769 :group 'org-agenda-setup
1770 :type 'hook)
1771
1772 (defcustom org-agenda-mouse-1-follows-link nil
1773 "Non-nil means, mouse-1 on a link will follow the link in the agenda.
1774 A longer mouse click will still set point. Does not wortk on XEmacs.
1775 Needs to be set before org.el is loaded."
1776 :group 'org-agenda-setup
1777 :type 'boolean)
1778
1779 (defcustom org-agenda-start-with-follow-mode nil
1780 "The initial value of follwo-mode in a newly created agenda window."
1781 :group 'org-agenda-setup
1782 :type 'boolean)
1783
1784 (defgroup org-agenda-display nil
1785 "Options concerning what to display initially in Agenda."
1786 :tag "Org Agenda Display"
1787 :group 'org-agenda)
1788
1789 (defcustom org-agenda-show-all-dates t
1790 "Non-nil means, `org-agenda' shows every day in the selected range.
1791 When nil, only the days which actually have entries are shown."
1792 :group 'org-agenda-display
1793 :type 'boolean)
1794
1795 (defcustom org-agenda-start-on-weekday 1
1796 "Non-nil means, start the overview always on the specified weekday.
1797 0 denotes Sunday, 1 denotes Monday etc.
1798 When nil, always start on the current day."
1799 :group 'org-agenda-display
1800 :type '(choice (const :tag "Today" nil)
1801 (number :tag "Weekday No.")))
1802
1803 (defcustom org-agenda-ndays 7
1804 "Number of days to include in overview display.
1805 Should be 1 or 7."
1806 :group 'org-agenda-display
1807 :type 'number)
1808
1809 (defcustom org-agenda-use-time-grid t
1810 "Non-nil means, show a time grid in the agenda schedule.
1811 A time grid is a set of lines for specific times (like every two hours between
1812 8:00 and 20:00). The items scheduled for a day at specific times are
1813 sorted in between these lines.
1814 For details about when the grid will be shown, and what it will look like, see
1815 the variable `org-agenda-time-grid'."
1816 :group 'org-agenda-display
1817 :type 'boolean)
1818
1819 (defcustom org-agenda-time-grid
1820 '((daily today require-timed)
1821 "----------------"
1822 (800 1000 1200 1400 1600 1800 2000))
1823
1824 "The settings for time grid for agenda display.
1825 This is a list of three items. The first item is again a list. It contains
1826 symbols specifying conditions when the grid should be displayed:
1827
1828 daily if the agenda shows a single day
1829 weekly if the agenda shows an entire week
1830 today show grid on current date, independent of daily/weekly display
1831 require-timed show grid only if at least one item has a time specification
1832
1833 The second item is a string which will be places behing the grid time.
1834
1835 The third item is a list of integers, indicating the times that should have
1836 a grid line."
1837 :group 'org-agenda-display
1838 :type
1839 '(list
1840 (set :greedy t :tag "Grid Display Options"
1841 (const :tag "Show grid in single day agenda display" daily)
1842 (const :tag "Show grid in weekly agenda display" weekly)
1843 (const :tag "Always show grid for today" today)
1844 (const :tag "Show grid only if any timed entries are present"
1845 require-timed)
1846 (const :tag "Skip grid times already present in an entry"
1847 remove-match))
1848 (string :tag "Grid String")
1849 (repeat :tag "Grid Times" (integer :tag "Time"))))
1850
1851 (let ((sorting-choice
1852 '(choice
1853 (const time-up) (const time-down)
1854 (const category-keep) (const category-up) (const category-down)
1855 (const tag-down) (const tag-up)
1856 (const priority-up) (const priority-down))))
1857
1858 (defcustom org-agenda-sorting-strategy
1859 '((agenda time-up category-keep priority-down)
1860 (todo category-keep priority-down)
1861 (tags category-keep))
1862 "Sorting structure for the agenda items of a single day.
1863 This is a list of symbols which will be used in sequence to determine
1864 if an entry should be listed before another entry. The following
1865 symbols are recognized:
1866
1867 time-up Put entries with time-of-day indications first, early first
1868 time-down Put entries with time-of-day indications first, late first
1869 category-keep Keep the default order of categories, corresponding to the
1870 sequence in `org-agenda-files'.
1871 category-up Sort alphabetically by category, A-Z.
1872 category-down Sort alphabetically by category, Z-A.
1873 tag-up Sort alphabetically by last tag, A-Z.
1874 tag-down Sort alphabetically by last tag, Z-A.
1875 priority-up Sort numerically by priority, high priority last.
1876 priority-down Sort numerically by priority, high priority first.
1877
1878 The different possibilities will be tried in sequence, and testing stops
1879 if one comparison returns a \"not-equal\". For example, the default
1880 '(time-up category-keep priority-down)
1881 means: Pull out all entries having a specified time of day and sort them,
1882 in order to make a time schedule for the current day the first thing in the
1883 agenda listing for the day. Of the entries without a time indication, keep
1884 the grouped in categories, don't sort the categories, but keep them in
1885 the sequence given in `org-agenda-files'. Within each category sort by
1886 priority.
1887
1888 Leaving out `category-keep' would mean that items will be sorted across
1889 categories by priority."
1890 :group 'org-agenda-display
1891 :type `(choice
1892 (repeat :tag "General" ,sorting-choice)
1893 (list :tag "Individually"
1894 (cons (const :tag "Strategy for Weekly/Daily agenda" agenda)
1895 (repeat ,sorting-choice))
1896 (cons (const :tag "Strategy for TODO lists" todo)
1897 (repeat ,sorting-choice))
1898 (cons (const :tag "Strategy for Tags matches" tags)
1899 (repeat ,sorting-choice))))))
1900
1901 (defcustom org-sort-agenda-notime-is-late t
1902 "Non-nil means, items without time are considered late.
1903 This is only relevant for sorting. When t, items which have no explicit
1904 time like 15:30 will be considered as 99:01, i.e. later than any items which
1905 do have a time. When nil, the default time is before 0:00. You can use this
1906 option to decide if the schedule for today should come before or after timeless
1907 agenda entries."
1908 :group 'org-agenda-display
1909 :type 'boolean)
1910
1911 (defgroup org-agenda-prefix nil
1912 "Options concerning the entry prefix in the Org-mode agenda display."
1913 :tag "Org Agenda Prefix"
1914 :group 'org-agenda)
1915
1916 (defcustom org-agenda-prefix-format
1917 '((agenda . " %-12:c%?-12t% s")
1918 (timeline . " % s")
1919 (todo . " %-12:c")
1920 (tags . " %-12:c"))
1921 "Format specifications for the prefix of items in the agenda views.
1922 An alist with four entries, for the different agenda types. The keys to the
1923 sublists are `agenda', `timeline', `todo', and `tags'. The values
1924 are format strings.
1925 This format works similar to a printf format, with the following meaning:
1926
1927 %c the category of the item, \"Diary\" for entries from the diary, or
1928 as given by the CATEGORY keyword or derived from the file name.
1929 %T the *last* tag of the item. Last because inherited tags come
1930 first in the list.
1931 %t the time-of-day specification if one applies to the entry, in the
1932 format HH:MM
1933 %s Scheduling/Deadline information, a short string
1934
1935 All specifiers work basically like the standard `%s' of printf, but may
1936 contain two additional characters: A question mark just after the `%' and
1937 a whitespace/punctuation character just before the final letter.
1938
1939 If the first character after `%' is a question mark, the entire field
1940 will only be included if the corresponding value applies to the
1941 current entry. This is useful for fields which should have fixed
1942 width when present, but zero width when absent. For example,
1943 \"%?-12t\" will result in a 12 character time field if a time of the
1944 day is specified, but will completely disappear in entries which do
1945 not contain a time.
1946
1947 If there is punctuation or whitespace character just before the final
1948 format letter, this character will be appended to the field value if
1949 the value is not empty. For example, the format \"%-12:c\" leads to
1950 \"Diary: \" if the category is \"Diary\". If the category were be
1951 empty, no additional colon would be interted.
1952
1953 The default value of this option is \" %-12:c%?-12t% s\", meaning:
1954 - Indent the line with two space characters
1955 - Give the category in a 12 chars wide field, padded with whitespace on
1956 the right (because of `-'). Append a colon if there is a category
1957 (because of `:').
1958 - If there is a time-of-day, put it into a 12 chars wide field. If no
1959 time, don't put in an empty field, just skip it (because of '?').
1960 - Finally, put the scheduling information and append a whitespace.
1961
1962 As another example, if you don't want the time-of-day of entries in
1963 the prefix, you could use:
1964
1965 (setq org-agenda-prefix-format \" %-11:c% s\")
1966
1967 See also the variables `org-agenda-remove-times-when-in-prefix' and
1968 `org-agenda-remove-tags-when-in-prefix'."
1969 :type '(choice
1970 (string :tag "General format")
1971 (list :greedy t :tag "View dependent"
1972 (cons (const agenda) (string :tag "Format"))
1973 (cons (const timeline) (string :tag "Format"))
1974 (cons (const todo) (string :tag "Format"))
1975 (cons (const tags) (string :tag "Format"))))
1976 :group 'org-agenda-prefix)
1977
1978 (defvar org-prefix-format-compiled nil
1979 "The compiled version of the most recently used prefix format.
1980 See the variable `org-agenda-prefix-format'.")
1981
1982 (defcustom org-agenda-remove-times-when-in-prefix t
1983 "Non-nil means, remove duplicate time specifications in agenda items.
1984 When the format `org-agenda-prefix-format' contains a `%t' specifier, a
1985 time-of-day specification in a headline or diary entry is extracted and
1986 placed into the prefix. If this option is non-nil, the original specification
1987 \(a timestamp or -range, or just a plain time(range) specification like
1988 11:30-4pm) will be removed for agenda display. This makes the agenda less
1989 cluttered.
1990 The option can be t or nil. It may also be the symbol `beg', indicating
1991 that the time should only be removed what it is located at the beginning of
1992 the headline/diary entry."
1993 :group 'org-agenda-prefix
1994 :type '(choice
1995 (const :tag "Always" t)
1996 (const :tag "Never" nil)
1997 (const :tag "When at beginning of entry" beg)))
1998
1999 (defcustom org-agenda-remove-tags-when-in-prefix nil
2000 "Non-nil means, remove the tags from the headline copy in the agenda.
2001 When this is the symbol `prefix', only remove tags when
2002 `org-agenda-prefix-format' contains a `%T' specifier."
2003 :group 'org-agenda-prefix
2004 :type '(choice
2005 (const :tag "Always" t)
2006 (const :tag "Never" nil)
2007 (const :tag "When prefix format contains %T" prefix)))
2008
2009 (defcustom org-agenda-align-tags-to-column 65
2010 "Shift tags in agenda items to this column."
2011 :group 'org-agenda-prefix
2012 :type 'integer)
2013
2014 (defgroup org-latex nil
2015 "Options for embedding LaTeX code into Org-mode"
2016 :tag "Org LaTeX"
2017 :group 'org)
2018
2019 (defcustom org-format-latex-options
2020 '(:foreground "Black" :background "Transparent" :scale 1.0
2021 :matchers ("begin" "$" "$$" "\\(" "\\["))
2022 "Options for creating images from LaTeX fragments.
2023 This is a property list with the following properties:
2024 :foreground the foreground color, for example \"Black\".
2025 :background the background color, or \"Transparent\".
2026 :scale a scaling factor for the size of the images
2027 :matchers a list indicating which matchers should be used to
2028 find LaTeX fragments. Valid members of this list are:
2029 \"begin\" find environments
2030 \"$\" find math expressions surrounded by $...$
2031 \"$$\" find math expressions surrounded by $$....$$
2032 \"\\(\" find math expressions surrounded by \\(...\\)
2033 \"\\ [\" find math expressions surrounded by \\ [...\\]"
2034 :group 'org-latex
2035 :type 'plist)
2036
2037 (defgroup org-export nil
2038 "Options for exporting org-listings."
2039 :tag "Org Export"
2040 :group 'org)
2041
2042 (defgroup org-export-general nil
2043 "General options for exporting Org-mode files."
2044 :tag "Org Export General"
2045 :group 'org-export)
2046
2047 (defcustom org-export-publishing-directory "."
2048 "Path to the location where exported files should be located.
2049 This path may be relative to the directory where the Org-mode file lives.
2050 The default is to put them into the same directory as the Org-mode file.
2051 The variable may also be an alist with export types `:html', `:ascii',
2052 `:ical', or `:xoxo' and the corresponding directories. If a direcoty path
2053 is relative, it is interpreted relative to the directory where the exported
2054 Org-mode files lives."
2055 :group 'org-export-general
2056 :type '(choice
2057 (directory)
2058 (repeat
2059 (cons
2060 (choice :tag "Type"
2061 (const :html) (const :ascii) (const :ical) (const :xoxo))
2062 (directory)))))
2063
2064 (defcustom org-export-language-setup
2065 '(("en" "Author" "Date" "Table of Contents")
2066 ("cs" "Autor" "Datum" "Obsah")
2067 ("da" "Ophavsmand" "Dato" "Indhold")
2068 ("de" "Autor" "Datum" "Inhaltsverzeichnis")
2069 ("es" "Autor" "Fecha" "\xccndice")
2070 ("fr" "Auteur" "Date" "Table des Mati\xe8res")
2071 ("it" "Autore" "Data" "Indice")
2072 ("nl" "Auteur" "Datum" "Inhoudsopgave")
2073 ("nn" "Forfattar" "Dato" "Innhold") ;; nn = Norsk (nynorsk)
2074 ("sv" "F\xf6rfattarens" "Datum" "Inneh\xe5ll"))
2075 "Terms used in export text, translated to different languages.
2076 Use the variable `org-export-default-language' to set the language,
2077 or use the +OPTION lines for a per-file setting."
2078 :group 'org-export-general
2079 :type '(repeat
2080 (list
2081 (string :tag "HTML language tag")
2082 (string :tag "Author")
2083 (string :tag "Date")
2084 (string :tag "Table of Contents"))))
2085
2086 (defcustom org-export-default-language "en"
2087 "The default language of HTML export, as a string.
2088 This should have an association in `org-export-language-setup'."
2089 :group 'org-export-general
2090 :type 'string)
2091
2092 (defcustom org-export-headline-levels 3
2093 "The last level which is still exported as a headline.
2094 Inferior levels will produce itemize lists when exported.
2095 Note that a numeric prefix argument to an exporter function overrides
2096 this setting.
2097
2098 This option can also be set with the +OPTIONS line, e.g. \"H:2\"."
2099 :group 'org-export-general
2100 :type 'number)
2101
2102 (defcustom org-export-with-section-numbers t
2103 "Non-nil means, add section numbers to headlines when exporting.
2104
2105 This option can also be set with the +OPTIONS line, e.g. \"num:t\"."
2106 :group 'org-export-general
2107 :type 'boolean)
2108
2109 (defcustom org-export-with-toc t
2110 "Non-nil means, create a table of contents in exported files.
2111 The TOC contains headlines with levels up to`org-export-headline-levels'.
2112
2113 Headlines which contain any TODO items will be marked with \"(*)\" in
2114 ASCII export, and with red color in HTML output.
2115
2116 In HTML output, the TOC will be clickable.
2117
2118 This option can also be set with the +OPTIONS line, e.g. \"toc:nil\"."
2119 :group 'org-export-general
2120 :type 'boolean)
2121
2122 (defcustom org-export-mark-todo-in-toc nil
2123 "Non-nil means, mark TOC lines that contain any open TODO items."
2124 :group 'org-export-general
2125 :type 'boolean)
2126
2127 (defcustom org-export-preserve-breaks nil
2128 "Non-nil means, preserve all line breaks when exporting.
2129 Normally, in HTML output paragraphs will be reformatted. In ASCII
2130 export, line breaks will always be preserved, regardless of this variable.
2131
2132 This option can also be set with the +OPTIONS line, e.g. \"\\n:t\"."
2133 :group 'org-export-general
2134 :type 'boolean)
2135
2136 (defcustom org-export-with-archived-trees 'headline
2137 "Whether subtrees with the ARCHIVE tag should be exported.
2138 This can have three different values
2139 nil Do not export, pretend this tree is not present
2140 t Do export the entire tree
2141 headline Only export the headline, but skip the tree below it."
2142 :group 'org-export-general
2143 :group 'org-archive
2144 :type '(choice
2145 (const :tag "not at all" nil)
2146 (const :tag "headline only" 'headline)
2147 (const :tag "entirely" t)))
2148
2149 (defcustom org-export-with-timestamps t
2150 "Nil means, do not export time stamps and associated keywords."
2151 :group 'org-export-general
2152 :type 'boolean)
2153
2154 (defcustom org-export-remove-timestamps-from-toc t
2155 "Nil means, remove timestamps from the table of contents entries."
2156 :group 'org-export-general
2157 :type 'boolean)
2158
2159 (defcustom org-export-with-tags 'not-in-toc
2160 "Nil means, do not export tags, just remove them from headlines.
2161 If this is the sysmbol `not-in-toc', tags will be removed from table of
2162 contents entries, but still be shown in the headlines of the document."
2163 :group 'org-export-general
2164 :type '(choice
2165 (const :tag "Off" nil)
2166 (const :tag "Not in TOC" not-in-toc)
2167 (const :tag "On" t)))
2168
2169 (defgroup org-export-translation nil
2170 "Options for translating special ascii sequences for the export backends."
2171 :tag "Org Export Translation"
2172 :group 'org-export)
2173
2174 (defcustom org-export-with-emphasize t
2175 "Non-nil means, interpret *word*, /word/, and _word_ as emphasized text.
2176 If the export target supports emphasizing text, the word will be
2177 typeset in bold, italic, or underlined, respectively. Works only for
2178 single words, but you can say: I *really* *mean* *this*.
2179 Not all export backends support this.
2180
2181 This option can also be set with the +OPTIONS line, e.g. \"*:nil\"."
2182 :group 'org-export-translation
2183 :type 'boolean)
2184
2185 (defcustom org-export-with-sub-superscripts t
2186 "Non-nil means, interpret \"_\" and \"^\" for export.
2187 When this option is turned on, you can use TeX-like syntax for sub- and
2188 superscripts. Several characters after \"_\" or \"^\" will be
2189 considered as a single item - so grouping with {} is normally not
2190 needed. For example, the following things will be parsed as single
2191 sub- or superscripts.
2192
2193 10^24 or 10^tau several digits will be considered 1 item.
2194 10^-12 or 10^-tau a leading sign with digits or a word
2195 x^2-y^3 will be read as x^2 - y^3, because items are
2196 terminated by almost any nonword/nondigit char.
2197 x_{i^2} or x^(2-i) braces or parenthesis do grouping.
2198
2199 Still, ambiguity is possible - so when in doubt use {} to enclose the
2200 sub/superscript.
2201 Not all export backends support this, but HTML does.
2202
2203 This option can also be set with the +OPTIONS line, e.g. \"^:nil\"."
2204 :group 'org-export-translation
2205 :type 'boolean)
2206
2207 (defcustom org-export-with-TeX-macros t
2208 "Non-nil means, interpret simple TeX-like macros when exporting.
2209 For example, HTML export converts \\alpha to &alpha; and \\AA to &Aring;.
2210 No only real TeX macros will work here, but the standard HTML entities
2211 for math can be used as macro names as well. For a list of supported
2212 names in HTML export, see the constant `org-html-entities'.
2213 Not all export backends support this.
2214
2215 This option can also be set with the +OPTIONS line, e.g. \"TeX:nil\"."
2216 :group 'org-export-translation
2217 :group 'org-latex
2218 :type 'boolean)
2219
2220 (defcustom org-export-with-LaTeX-fragments nil
2221 "Non-nil means, convert LaTeX fragments to images when exporting to HTML.
2222 When set, the exporter will find LaTeX environments if the \\begin line is
2223 the first non-white thing on a line. It will also find the math delimiters
2224 like $a=b$ and \\( a=b \\) for inline math, $$a=b$$ and \\[ a=b \\] for
2225 display math.
2226
2227 This option can also be set with the +OPTIONS line, e.g. \"LaTeX:t\"."
2228 :group 'org-export-translation
2229 :group 'org-latex
2230 :type 'boolean)
2231
2232 (defcustom org-export-with-fixed-width t
2233 "Non-nil means, lines starting with \":\" will be in fixed width font.
2234 This can be used to have pre-formatted text, fragments of code etc. For
2235 example:
2236 : ;; Some Lisp examples
2237 : (while (defc cnt)
2238 : (ding))
2239 will be looking just like this in also HTML. See also the QUOTE keyword.
2240 Not all export backends support this.
2241
2242 This option can also be set with the +OPTIONS line, e.g. \"::nil\"."
2243 :group 'org-export-translation
2244 :type 'boolean)
2245
2246 (defcustom org-match-sexp-depth 3
2247 "Number of stacked braces for sub/superscript matching.
2248 This has to be set before loading org.el to be effective."
2249 :group 'org-export-translation
2250 :type 'integer)
2251
2252 (defgroup org-export-tables nil
2253 "Options for exporting tables in Org-mode."
2254 :tag "Org Export Tables"
2255 :group 'org-export)
2256
2257 (defcustom org-export-with-tables t
2258 "If non-nil, lines starting with \"|\" define a table.
2259 For example:
2260
2261 | Name | Address | Birthday |
2262 |-------------+----------+-----------|
2263 | Arthur Dent | England | 29.2.2100 |
2264
2265 Not all export backends support this.
2266
2267 This option can also be set with the +OPTIONS line, e.g. \"|:nil\"."
2268 :group 'org-export-tables
2269 :type 'boolean)
2270
2271 (defcustom org-export-highlight-first-table-line t
2272 "Non-nil means, highlight the first table line.
2273 In HTML export, this means use <th> instead of <td>.
2274 In tables created with table.el, this applies to the first table line.
2275 In Org-mode tables, all lines before the first horizontal separator
2276 line will be formatted with <th> tags."
2277 :group 'org-export-tables
2278 :type 'boolean)
2279
2280 (defcustom org-export-table-remove-special-lines t
2281 "Remove special lines and marking characters in calculating tables.
2282 This removes the special marking character column from tables that are set
2283 up for spreadsheet calculations. It also removes the entire lines
2284 marked with `!', `_', or `^'. The lines with `$' are kept, because
2285 the values of constants may be useful to have."
2286 :group 'org-export-tables
2287 :type 'boolean)
2288
2289 (defcustom org-export-prefer-native-exporter-for-tables nil
2290 "Non-nil means, always export tables created with table.el natively.
2291 Natively means, use the HTML code generator in table.el.
2292 When nil, Org-mode's own HTML generator is used when possible (i.e. if
2293 the table does not use row- or column-spanning). This has the
2294 advantage, that the automatic HTML conversions for math symbols and
2295 sub/superscripts can be applied. Org-mode's HTML generator is also
2296 much faster."
2297 :group 'org-export-tables
2298 :type 'boolean)
2299
2300 (defgroup org-export-ascii nil
2301 "Options specific for ASCII export of Org-mode files."
2302 :tag "Org Export ASCII"
2303 :group 'org-export)
2304
2305 (defcustom org-export-ascii-underline '(?\$ ?\# ?^ ?\~ ?\= ?\-)
2306 "Characters for underlining headings in ASCII export.
2307 In the given sequence, these characters will be used for level 1, 2, ..."
2308 :group 'org-export-ascii
2309 :type '(repeat character))
2310
2311 (defcustom org-export-ascii-bullets '(?* ?+ ?-)
2312 "Bullet characters for headlines converted to lists in ASCII export.
2313 The first character is is used for the first lest level generated in this
2314 way, and so on. If there are more levels than characters given here,
2315 the list will be repeated.
2316 Note that plain lists will keep the same bullets as the have in the
2317 Org-mode file."
2318 :group 'org-export-ascii
2319 :type '(repeat character))
2320
2321 (defcustom org-export-ascii-show-new-buffer t
2322 "Non-nil means, popup buffer containing the exported ASCII text.
2323 Otherwise the buffer will just be saved to a file and stay hidden."
2324 :group 'org-export-ascii
2325 :type 'boolean)
2326
2327 (defgroup org-export-xml nil
2328 "Options specific for XML export of Org-mode files."
2329 :tag "Org Export XML"
2330 :group 'org-export)
2331
2332 (defgroup org-export-html nil
2333 "Options specific for HTML export of Org-mode files."
2334 :tag "Org Export HTML"
2335 :group 'org-export)
2336
2337 (defcustom org-export-html-style
2338 "<style type=\"text/css\">
2339 html {
2340 font-family: Times, serif;
2341 font-size: 12pt;
2342 }
2343 .title { text-align: center; }
2344 .todo { color: red; }
2345 .done { color: green; }
2346 .timestamp { color: grey }
2347 .timestamp-kwd { color: CadetBlue }
2348 .tag { background-color:lightblue; font-weight:normal }
2349 .target { background-color: lavender; }
2350 pre {
2351 border: 1pt solid #AEBDCC;
2352 background-color: #F3F5F7;
2353 padding: 5pt;
2354 font-family: courier, monospace;
2355 }
2356 table { border-collapse: collapse; }
2357 td, th {
2358 vertical-align: top;
2359 border: 1pt solid #ADB9CC;
2360 }
2361 </style>"
2362 "The default style specification for exported HTML files.
2363 Since there are different ways of setting style information, this variable
2364 needs to contain the full HTML structure to provide a style, including the
2365 surrounding HTML tags. The style specifications should include definitions
2366 for new classes todo, done, title, and deadline. For example, legal values
2367 would be:
2368
2369 <style type=\"text/css\">
2370 p { font-weight: normal; color: gray; }
2371 h1 { color: black; }
2372 .title { text-align: center; }
2373 .todo, .deadline { color: red; }
2374 .done { color: green; }
2375 </style>
2376
2377 or, if you want to keep the style in a file,
2378
2379 <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\">
2380
2381 As the value of this option simply gets inserted into the HTML <head> header,
2382 you can \"misuse\" it to add arbitrary text to the header."
2383 :group 'org-export-html
2384 :type 'string)
2385
2386 (defcustom org-export-html-title-format "<h1 class=\"title\">%s</h1>\n"
2387 "Format for typesetting the document title in HTML export."
2388 :group 'org-export-html
2389 :type 'string)
2390
2391 (defcustom org-export-html-toplevel-hlevel 2
2392 "The <H> level for level 1 headings in HTML export."
2393 :group 'org-export-html
2394 :type 'string)
2395
2396 (defcustom org-export-html-link-org-files-as-html t
2397 "Non-nil means, make file links to `file.org' point to `file.html'.
2398 When org-mode is exporting an org-mode file to HTML, links to
2399 non-html files are directly put into a href tag in HTML.
2400 However, links to other Org-mode files (recognized by the
2401 extension `.org.) should become links to the corresponding html
2402 file, assuming that the linked org-mode file will also be
2403 converted to HTML.
2404 When nil, the links still point to the plain `.org' file."
2405 :group 'org-export-html
2406 :type 'boolean)
2407
2408 (defcustom org-export-html-inline-images 'maybe
2409 "Non-nil means, inline images into exported HTML pages.
2410 This is done using an <img> tag. When nil, an anchor with href is used to
2411 link to the image. If this option is `maybe', then images in links with
2412 an empty description will be inlined, while images with a description will
2413 be linked only."
2414 :group 'org-export-html
2415 :type '(choice (const :tag "Never" nil)
2416 (const :tag "Always" t)
2417 (const :tag "When there is no description" maybe)))
2418
2419 (defcustom org-export-html-expand t
2420 "Non-nil means, for HTML export, treat @<...> as HTML tag.
2421 When nil, these tags will be exported as plain text and therefore
2422 not be interpreted by a browser.
2423
2424 This option can also be set with the +OPTIONS line, e.g. \"@:nil\"."
2425 :group 'org-export-html
2426 :type 'boolean)
2427
2428 (defcustom org-export-html-table-tag
2429 "<table border=\"1\" cellspacing=\"0\" cellpadding=\"6\">"
2430 "The HTML tag used to start a table.
2431 This must be a <table> tag, but you may change the options like
2432 borders and spacing."
2433 :group 'org-export-html
2434 :type 'string)
2435
2436 (defcustom org-export-html-with-timestamp nil
2437 "If non-nil, write `org-export-html-html-helper-timestamp'
2438 into the exported HTML text. Otherwise, the buffer will just be saved
2439 to a file."
2440 :group 'org-export-html
2441 :type 'boolean)
2442
2443 (defcustom org-export-html-html-helper-timestamp
2444 "<br/><br/><hr><p><!-- hhmts start --> <!-- hhmts end --></p>\n"
2445 "The HTML tag used as timestamp delimiter for HTML-helper-mode."
2446 :group 'org-export-html
2447 :type 'string)
2448
2449 (defcustom org-export-html-show-new-buffer nil
2450 "Non-nil means, popup buffer containing the exported html text.
2451 Otherwise, the buffer will just be saved to a file and stay hidden."
2452 :group 'org-export-html
2453 :type 'boolean)
2454
2455 (defgroup org-export-icalendar nil
2456 "Options specific for iCalendar export of Org-mode files."
2457 :tag "Org Export iCalendar"
2458 :group 'org-export)
2459
2460 (defcustom org-combined-agenda-icalendar-file "~/org.ics"
2461 "The file name for the iCalendar file covering all agenda files.
2462 This file is created with the command \\[org-export-icalendar-all-agenda-files].
2463 The file name should be absolute."
2464 :group 'org-export-icalendar
2465 :type 'file)
2466
2467 (defcustom org-icalendar-include-todo nil
2468 "Non-nil means, export to iCalendar files should also cover TODO items."
2469 :group 'org-export-icalendar
2470 :type 'boolean)
2471
2472 (defcustom org-icalendar-combined-name "OrgMode"
2473 "Calendar name for the combined iCalendar representing all agenda files."
2474 :group 'org-export-icalendar
2475 :type 'string)
2476
2477 (defgroup org-font-lock nil
2478 "Font-lock settings for highlighting in Org-mode."
2479 :tag "Org Font Lock"
2480 :group 'org)
2481
2482 (defcustom org-level-color-stars-only nil
2483 "Non-nil means fontify only the stars in each headline.
2484 When nil, the entire headline is fontified.
2485 Changing it requires restart of `font-lock-mode' to become effective
2486 also in regions already fontified."
2487 :group 'org-font-lock
2488 :type 'boolean)
2489
2490 (defcustom org-hide-leading-stars nil
2491 "Non-nil means, hide the first N-1 stars in a headline.
2492 This works by using the face `org-hide' for these stars. This
2493 face is white for a light background, and black for a dark
2494 background. You may have to customize the face `org-hide' to
2495 make this work.
2496 Changing it requires restart of `font-lock-mode' to become effective
2497 also in regions already fontified.
2498 You may also set this on a per-file basis by adding one of the following
2499 lines to the buffer:
2500
2501 #+STARTUP: hidestars
2502 #+STARTUP: showstars"
2503 :group 'org-font-lock
2504 :type 'boolean)
2505
2506 (defcustom org-fontify-done-headline nil
2507 "Non-nil means, change the face of a headline if it is marked DONE.
2508 Normally, only the TODO/DONE keyword indicates the state of a headline.
2509 When this is non-nil, the headline after the keyword is set to the
2510 `org-headline-done' as an additional indication."
2511 :group 'org-font-lock
2512 :type 'boolean)
2513
2514 (defcustom org-fontify-emphasized-text t
2515 "Non-nil means fontify *bold*, /italic/ and _underlined_ text.
2516 Changing this variable requires a restart of Emacs to take effect."
2517 :group 'org-font-lock
2518 :type 'boolean)
2519
2520 (defvar org-emph-re nil
2521 "Regular expression for matching emphasis.")
2522 (defvar org-emphasis-regexp-components) ; defined just below
2523 (defvar org-emphasis-alist) ; defined just below
2524 (defun org-set-emph-re (var val)
2525 "Set variable and compute the emphasis regular expression."
2526 (set var val)
2527 (when (and (boundp 'org-emphasis-alist)
2528 (boundp 'org-emphasis-regexp-components)
2529 org-emphasis-alist org-emphasis-regexp-components)
2530 (let* ((e org-emphasis-regexp-components)
2531 (pre (car e))
2532 (post (nth 1 e))
2533 (border (nth 2 e))
2534 (body (nth 3 e))
2535 (nl (nth 4 e))
2536 (stacked (nth 5 e))
2537 (body1 (concat body "*?"))
2538 (markers (mapconcat 'car org-emphasis-alist "")))
2539 ;; make sure special characters appear at the right position in the class
2540 (if (string-match "\\^" markers)
2541 (setq markers (concat (replace-match "" t t markers) "^")))
2542 (if (string-match "-" markers)
2543 (setq markers (concat (replace-match "" t t markers) "-")))
2544 ; (while (>= (setq nl (1- nl)) 0) (setq body1 (concat body1 "\n?" body "*?")))
2545 ; (while (>= (setq nl (1- nl)) 0) (setq body1 (concat body1 "\\(?:\n?" body "*?\\)?")))
2546 (if (> nl 0)
2547 (setq body1 (concat body1 "\\(?:\n" body "*?\\)\\{0,"
2548 (int-to-string nl) "\\}")))
2549 ;; Make the regexp
2550 (setq org-emph-re
2551 (concat "\\([" pre (if stacked markers) "]\\|^\\)"
2552 "\\("
2553 "\\([" markers "]\\)"
2554 "\\("
2555 "[^" border markers "]"
2556 body1
2557 "[^" border markers "]"
2558 "\\)"
2559 "\\3\\)"
2560 "\\([" post (if stacked markers) "]\\|$\\)")))))
2561
2562 (defcustom org-emphasis-regexp-components
2563 '(" \t(" " \t.,?;'\")" " \t\r\n," "." 1 nil)
2564 "Components used to build the reqular expression for emphasis.
2565 This is a list with 6 entries. Terminology: In an emphasis string
2566 like \" *strong word* \", we call the initial space PREMATCH, the final
2567 space POSTMATCH, the stars MARKERS, \"s\" and \"d\" are BORDER characters
2568 and \"trong wor\" is the body. The different components in this variable
2569 specify what is allowed/forbidden in each part:
2570
2571 pre Chars allowed as prematch. Beginning of line will be allowed too.
2572 post Chars allowed as postmatch. End of line will be allowed too.
2573 border The chars *forbidden* as border characters. In addition to the
2574 characters given here, all marker characters are forbidden too.
2575 body-regexp A regexp like \".\" to match a body character. Don't use
2576 non-shy groups here, and don't allow newline here.
2577 newline The maximum number of newlines allowed in an emphasis exp.
2578 stacked Non-nil means, allow stacked styles. This works only in HTML
2579 export. When this is set, all marker characters (as given in
2580 `org-emphasis-alist') will be allowed as pre/post, aiding
2581 inside-out matching.
2582 Use customize to modify this, or restart Emacs after changing it."
2583 :group 'org-font-lock
2584 :set 'org-set-emph-re
2585 :type '(list
2586 (sexp :tag "Allowed chars in pre ")
2587 (sexp :tag "Allowed chars in post ")
2588 (sexp :tag "Forbidden chars in border ")
2589 (sexp :tag "Regexp for body ")
2590 (integer :tag "number of newlines allowed")
2591 (boolean :tag "Stacking allowed ")))
2592
2593 (defcustom org-emphasis-alist
2594 '(("*" bold "<b>" "</b>")
2595 ("/" italic "<i>" "</i>")
2596 ("_" underline "<u>" "</u>")
2597 ("=" shadow "<code>" "</code>")
2598 ("+" (:strike-through t) "<del>" "</del>")
2599 )
2600 "Special syntax for emphasized text.
2601 Text starting and ending with a special character will be emphasized, for
2602 example *bold*, _underlined_ and /italic/. This variable sets the marker
2603 characters, the face to bbe used by font-lock for highlighting in Org-mode
2604 Emacs buffers, and the HTML tags to be used for this.
2605 Use customize to modify this, or restart Emacs after changing it."
2606 :group 'org-font-lock
2607 :set 'org-set-emph-re
2608 :type '(repeat
2609 (list
2610 (string :tag "Marker character")
2611 (choice
2612 (face :tag "Font-lock-face")
2613 (plist :tag "Face property list"))
2614 (string :tag "HTML start tag")
2615 (string :tag "HTML end tag"))))
2616
2617 (defgroup org-faces nil
2618 "Faces in Org-mode."
2619 :tag "Org Faces"
2620 :group 'org-font-lock)
2621
2622 (defun org-compatible-face (specs)
2623 "Make a compatible face specification.
2624 XEmacs and Emacs 21 do not know about the `min-colors' attribute.
2625 For them we convert a (min-colors 8) entry to a `tty' entry and move it
2626 to the top of the list. The `min-colors' attribute will be removed from
2627 any other entries, and any resulting duplicates will be removed entirely."
2628 (if (or (featurep 'xemacs) (< emacs-major-version 22))
2629 (let (r e a)
2630 (while (setq e (pop specs))
2631 (cond
2632 ((memq (car e) '(t default)) (push e r))
2633 ((setq a (member '(min-colors 8) (car e)))
2634 (nconc r (list (cons (cons '(type tty) (delq (car a) (car e)))
2635 (cdr e)))))
2636 ((setq a (assq 'min-colors (car e)))
2637 (setq e (cons (delq a (car e)) (cdr e)))
2638 (or (assoc (car e) r) (push e r)))
2639 (t (or (assoc (car e) r) (push e r)))))
2640 (nreverse r))
2641 specs))
2642
2643 (defface org-hide
2644 '((((background light)) (:foreground "white"))
2645 (((background dark)) (:foreground "black")))
2646 "Face used to hide leading stars in headlines.
2647 The forground color of this face should be equal to the background
2648 color of the frame."
2649 :group 'org-faces)
2650
2651 (defface org-level-1 ;; font-lock-function-name-face
2652 (org-compatible-face
2653 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
2654 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
2655 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
2656 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
2657 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
2658 (t (:bold t))))
2659 "Face used for level 1 headlines."
2660 :group 'org-faces)
2661
2662 (defface org-level-2 ;; font-lock-variable-name-face
2663 (org-compatible-face
2664 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
2665 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
2666 (((class color) (min-colors 8) (background light)) (:foreground "yellow"))
2667 (((class color) (min-colors 8) (background dark)) (:foreground "yellow" :bold t))
2668 (t (:bold t))))
2669 "Face used for level 2 headlines."
2670 :group 'org-faces)
2671
2672 (defface org-level-3 ;; font-lock-keyword-face
2673 (org-compatible-face
2674 '((((class color) (min-colors 88) (background light)) (:foreground "Purple"))
2675 (((class color) (min-colors 88) (background dark)) (:foreground "Cyan1"))
2676 (((class color) (min-colors 16) (background light)) (:foreground "Purple"))
2677 (((class color) (min-colors 16) (background dark)) (:foreground "Cyan"))
2678 (((class color) (min-colors 8) (background light)) (:foreground "purple" :bold t))
2679 (((class color) (min-colors 8) (background dark)) (:foreground "cyan" :bold t))
2680 (t (:bold t))))
2681 "Face used for level 3 headlines."
2682 :group 'org-faces)
2683
2684 (defface org-level-4 ;; font-lock-comment-face
2685 (org-compatible-face
2686 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2687 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2688 (((class color) (min-colors 16) (background light)) (:foreground "red"))
2689 (((class color) (min-colors 16) (background dark)) (:foreground "red1"))
2690 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
2691 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2692 (t (:bold t))))
2693 "Face used for level 4 headlines."
2694 :group 'org-faces)
2695
2696 (defface org-level-5 ;; font-lock-type-face
2697 (org-compatible-face
2698 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
2699 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
2700 (((class color) (min-colors 8)) (:foreground "green"))))
2701 "Face used for level 5 headlines."
2702 :group 'org-faces)
2703
2704 (defface org-level-6 ;; font-lock-constant-face
2705 (org-compatible-face
2706 '((((class color) (min-colors 16) (background light)) (:foreground "CadetBlue"))
2707 (((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine"))
2708 (((class color) (min-colors 8)) (:foreground "magenta"))))
2709 "Face used for level 6 headlines."
2710 :group 'org-faces)
2711
2712 (defface org-level-7 ;; font-lock-builtin-face
2713 (org-compatible-face
2714 '((((class color) (min-colors 16) (background light)) (:foreground "Orchid"))
2715 (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue"))
2716 (((class color) (min-colors 8)) (:foreground "blue"))))
2717 "Face used for level 7 headlines."
2718 :group 'org-faces)
2719
2720 (defface org-level-8 ;; font-lock-string-face
2721 (org-compatible-face
2722 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
2723 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
2724 (((class color) (min-colors 8)) (:foreground "green"))))
2725 "Face used for level 8 headlines."
2726 :group 'org-faces)
2727
2728 (defface org-special-keyword ;; font-lock-string-face
2729 (org-compatible-face
2730 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
2731 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
2732 (t (:italic t))))
2733 "Face used for special keywords."
2734 :group 'org-faces)
2735
2736 (defface org-warning ;; font-lock-warning-face
2737 (org-compatible-face
2738 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
2739 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
2740 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
2741 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2742 (t (:bold t))))
2743 "Face for deadlines and TODO keywords."
2744 :group 'org-faces)
2745
2746 (defface org-headline-done ;; font-lock-string-face
2747 (org-compatible-face
2748 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
2749 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
2750 (((class color) (min-colors 8) (background light)) (:bold nil))))
2751 "Face used to indicate that a headline is DONE.
2752 This face is only used if `org-fontify-done-headline' is set."
2753 :group 'org-faces)
2754
2755 (defface org-archived ; similar to shadow
2756 (org-compatible-face
2757 '((((class color grayscale) (min-colors 88) (background light))
2758 (:foreground "grey50"))
2759 (((class color grayscale) (min-colors 88) (background dark))
2760 (:foreground "grey70"))
2761 (((class color) (min-colors 8) (background light))
2762 (:foreground "green"))
2763 (((class color) (min-colors 8) (background dark))
2764 (:foreground "yellow"))))
2765 "Face for headline with the ARCHIVE tag."
2766 :group 'org-faces)
2767
2768 (defface org-link
2769 '((((class color) (background light)) (:foreground "Purple" :underline t))
2770 (((class color) (background dark)) (:foreground "Cyan" :underline t))
2771 (t (:underline t)))
2772 "Face for links."
2773 :group 'org-faces)
2774
2775 (defface org-date
2776 '((((class color) (background light)) (:foreground "Purple" :underline t))
2777 (((class color) (background dark)) (:foreground "Cyan" :underline t))
2778 (t (:underline t)))
2779 "Face for links."
2780 :group 'org-faces)
2781
2782 (defface org-tag
2783 '((t (:bold t)))
2784 "Face for tags."
2785 :group 'org-faces)
2786
2787 (defface org-todo ;; font-lock-warning-face
2788 (org-compatible-face
2789 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
2790 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
2791 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
2792 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2793 (t (:inverse-video t :bold t))))
2794 "Face for TODO keywords."
2795 :group 'org-faces)
2796
2797 (defface org-done ;; font-lock-type-face
2798 (org-compatible-face
2799 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen" :bold t))
2800 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen" :bold t))
2801 (((class color) (min-colors 8)) (:foreground "green"))
2802 (t (:bold t))))
2803 "Face used for DONE."
2804 :group 'org-faces)
2805
2806 (defface org-table ;; font-lock-function-name-face
2807 (org-compatible-face
2808 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
2809 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
2810 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
2811 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
2812 (((class color) (min-colors 8) (background light)) (:foreground "blue"))
2813 (((class color) (min-colors 8) (background dark)))))
2814 "Face used for tables."
2815 :group 'org-faces)
2816
2817 (defface org-formula
2818 (org-compatible-face
2819 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2820 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2821 (((class color) (min-colors 8) (background light)) (:foreground "red"))
2822 (((class color) (min-colors 8) (background dark)) (:foreground "red"))
2823 (t (:bold t :italic t))))
2824 "Face for formulas."
2825 :group 'org-faces)
2826
2827 (defface org-scheduled-today
2828 (org-compatible-face
2829 '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen"))
2830 (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen"))
2831 (((class color) (min-colors 8)) (:foreground "green"))
2832 (t (:bold t :italic t))))
2833 "Face for items scheduled for a certain day."
2834 :group 'org-faces)
2835
2836 (defface org-scheduled-previously
2837 (org-compatible-face
2838 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2839 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2840 (((class color) (min-colors 8) (background light)) (:foreground "red"))
2841 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2842 (t (:bold t))))
2843 "Face for items scheduled previously, and not yet done."
2844 :group 'org-faces)
2845
2846 (defface org-upcoming-deadline
2847 (org-compatible-face
2848 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2849 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2850 (((class color) (min-colors 8) (background light)) (:foreground "red"))
2851 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2852 (t (:bold t))))
2853 "Face for items scheduled previously, and not yet done."
2854 :group 'org-faces)
2855
2856 (defface org-time-grid ;; font-lock-variable-name-face
2857 (org-compatible-face
2858 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
2859 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
2860 (((class color) (min-colors 8)) (:foreground "yellow" :weight light))))
2861 "Face used for time grids."
2862 :group 'org-faces)
2863
2864 (defconst org-level-faces
2865 '(org-level-1 org-level-2 org-level-3 org-level-4
2866 org-level-5 org-level-6 org-level-7 org-level-8
2867 ))
2868 (defconst org-n-levels (length org-level-faces))
2869
2870
2871 ;; Variables for pre-computed regular expressions, all buffer local
2872 (defvar org-done-string nil
2873 "The last string in `org-todo-keywords', indicating an item is DONE.")
2874 (make-variable-buffer-local 'org-done-string)
2875 (defvar org-todo-regexp nil
2876 "Matches any of the TODO state keywords.")
2877 (make-variable-buffer-local 'org-todo-regexp)
2878 (defvar org-not-done-regexp nil
2879 "Matches any of the TODO state keywords except the last one.")
2880 (make-variable-buffer-local 'org-not-done-regexp)
2881 (defvar org-todo-line-regexp nil
2882 "Matches a headline and puts TODO state into group 2 if present.")
2883 (make-variable-buffer-local 'org-todo-line-regexp)
2884 (defvar org-todo-line-tags-regexp nil
2885 "Matches a headline and puts TODO state into group 2 if present.
2886 Also put tags into group 4 if tags are present.")
2887 (make-variable-buffer-local 'org-todo-line-tags-regexp)
2888 (defvar org-nl-done-regexp nil
2889 "Matches newline followed by a headline with the DONE keyword.")
2890 (make-variable-buffer-local 'org-nl-done-regexp)
2891 (defvar org-looking-at-done-regexp nil
2892 "Matches the DONE keyword a point.")
2893 (make-variable-buffer-local 'org-looking-at-done-regexp)
2894 (defvar org-todo-kwd-priority-p nil
2895 "Do TODO items have priorities?")
2896 (make-variable-buffer-local 'org-todo-kwd-priority-p)
2897 (defvar org-todo-kwd-max-priority nil
2898 "Maximum priority of TODO items.")
2899 (make-variable-buffer-local 'org-todo-kwd-max-priority)
2900 (defvar org-ds-keyword-length 12
2901 "Maximum length of the Deadline and SCHEDULED keywords.")
2902 (make-variable-buffer-local 'org-ds-keyword-length)
2903 (defvar org-deadline-regexp nil
2904 "Matches the DEADLINE keyword.")
2905 (make-variable-buffer-local 'org-deadline-regexp)
2906 (defvar org-deadline-time-regexp nil
2907 "Matches the DEADLINE keyword together with a time stamp.")
2908 (make-variable-buffer-local 'org-deadline-time-regexp)
2909 (defvar org-deadline-line-regexp nil
2910 "Matches the DEADLINE keyword and the rest of the line.")
2911 (make-variable-buffer-local 'org-deadline-line-regexp)
2912 (defvar org-scheduled-regexp nil
2913 "Matches the SCHEDULED keyword.")
2914 (make-variable-buffer-local 'org-scheduled-regexp)
2915 (defvar org-scheduled-time-regexp nil
2916 "Matches the SCHEDULED keyword together with a time stamp.")
2917 (make-variable-buffer-local 'org-scheduled-time-regexp)
2918 (defvar org-closed-time-regexp nil
2919 "Matches the CLOSED keyword together with a time stamp.")
2920 (make-variable-buffer-local 'org-closed-time-regexp)
2921
2922 (defvar org-keyword-time-regexp nil
2923 "Matches any of the 3 keywords, together with the time stamp.")
2924 (make-variable-buffer-local 'org-keyword-time-regexp)
2925 (defvar org-maybe-keyword-time-regexp nil
2926 "Matches a timestamp, possibly preceeded by a keyword.")
2927 (make-variable-buffer-local 'org-keyword-time-regexp)
2928
2929 (defconst org-rm-props '(invisible t face t keymap t intangible t mouse-face t
2930 rear-nonsticky t mouse-map t)
2931 "Properties to remove when a string without properties is wanted.")
2932
2933 (defsubst org-match-string-no-properties (num &optional string)
2934 (if (featurep 'xemacs)
2935 (let ((s (match-string num string)))
2936 (remove-text-properties 0 (length s) org-rm-props s)
2937 s)
2938 (match-string-no-properties num string)))
2939
2940 (defsubst org-no-properties (s)
2941 (remove-text-properties 0 (length s) org-rm-props s)
2942 s)
2943
2944 (defsubst org-get-alist-option (option key)
2945 (cond ((eq key t) t)
2946 ((eq option t) t)
2947 ((assoc key option) (cdr (assoc key option)))
2948 (t (cdr (assq 'default option)))))
2949
2950 (defsubst org-set-local (var value)
2951 "Make VAR local in current buffer and set it to VALUE."
2952 (set (make-variable-buffer-local var) value))
2953
2954 (defsubst org-mode-p ()
2955 "Check if the current buffer is in Org-mode."
2956 (eq major-mode 'org-mode))
2957
2958 (defsubst org-last (list)
2959 "Return the last element of LIST."
2960 (car (last list)))
2961
2962 (defun org-let (list &rest body)
2963 (eval (cons 'let (cons list body))))
2964 (put 'org-let 'lisp-indent-function 1)
2965
2966 (defun org-let2 (list1 list2 &rest body)
2967 (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body)))))))
2968 (put 'org-let2 'lisp-indent-function 2)
2969
2970 (defconst org-startup-options
2971 '(("fold" org-startup-folded t)
2972 ("overview" org-startup-folded t)
2973 ("nofold" org-startup-folded nil)
2974 ("showall" org-startup-folded nil)
2975 ("content" org-startup-folded content)
2976 ("hidestars" org-hide-leading-stars t)
2977 ("showstars" org-hide-leading-stars nil)
2978 ("odd" org-odd-levels-only t)
2979 ("oddeven" org-odd-levels-only nil)
2980 ("align" org-startup-align-all-tables t)
2981 ("noalign" org-startup-align-all-tables nil)
2982 ("customtime" org-display-custom-times t)
2983 ("logging" org-log-done t)
2984 ("nologging" org-log-done nil)
2985 ("dlcheck" org-startup-with-deadline-check t)
2986 ("nodlcheck" org-startup-with-deadline-check nil)))
2987
2988 (defun org-set-regexps-and-options ()
2989 "Precompute regular expressions for current buffer."
2990 (when (org-mode-p)
2991 (let ((re (org-make-options-regexp
2992 '("CATEGORY" "SEQ_TODO" "PRI_TODO" "TYP_TODO"
2993 "STARTUP" "ARCHIVE" "TAGS" "LINK")))
2994 (splitre "[ \t]+")
2995 kwds int key value cat arch tags links)
2996 (save-excursion
2997 (save-restriction
2998 (widen)
2999 (goto-char (point-min))
3000 (while (re-search-forward re nil t)
3001 (setq key (match-string 1) value (org-match-string-no-properties 2))
3002 (cond
3003 ((equal key "CATEGORY")
3004 (if (string-match "[ \t]+$" value)
3005 (setq value (replace-match "" t t value)))
3006 (setq cat (intern value)))
3007 ((equal key "SEQ_TODO")
3008 (setq int 'sequence
3009 kwds (append kwds (org-split-string value splitre))))
3010 ((equal key "PRI_TODO")
3011 (setq int 'priority
3012 kwds (append kwds (org-split-string value splitre))))
3013 ((equal key "TYP_TODO")
3014 (setq int 'type
3015 kwds (append kwds (org-split-string value splitre))))
3016 ((equal key "TAGS")
3017 (setq tags (append tags (org-split-string value splitre))))
3018 ((equal key "LINK")
3019 (when (string-match "^\\(\\S-+\\)[ \t]+\\(.+\\)" value)
3020 (push (cons (match-string 1 value)
3021 (org-trim (match-string 2 value)))
3022 links)))
3023 ((equal key "STARTUP")
3024 (let ((opts (org-split-string value splitre))
3025 l var val)
3026 (while (setq l (assoc (pop opts) org-startup-options))
3027 (setq var (nth 1 l) val (nth 2 l))
3028 (set (make-local-variable var) val))))
3029 ((equal key "ARCHIVE")
3030 (string-match " *$" value)
3031 (setq arch (replace-match "" t t value))
3032 (remove-text-properties 0 (length arch)
3033 '(face t fontified t) arch)))
3034 )))
3035 (and cat (org-set-local 'org-category cat))
3036 (and kwds (org-set-local 'org-todo-keywords kwds))
3037 (and arch (org-set-local 'org-archive-location arch))
3038 (and int (org-set-local 'org-todo-interpretation int))
3039 (and links (setq org-link-abbrev-alist-local (nreverse links)))
3040 (when tags
3041 (let (e tgs)
3042 (while (setq e (pop tags))
3043 (cond
3044 ((equal e "{") (push '(:startgroup) tgs))
3045 ((equal e "}") (push '(:endgroup) tgs))
3046 ((string-match "^\\([0-9a-zA-Z_@]+\\)(\\(.\\))$" e)
3047 (push (cons (match-string 1 e)
3048 (string-to-char (match-string 2 e)))
3049 tgs))
3050 (t (push (list e) tgs))))
3051 (org-set-local 'org-tag-alist nil)
3052 (while (setq e (pop tgs))
3053 (or (and (stringp (car e))
3054 (assoc (car e) org-tag-alist))
3055 (push e org-tag-alist))))))
3056
3057 ;; Compute the regular expressions and other local variables
3058 (setq org-todo-kwd-priority-p (equal org-todo-interpretation 'priority)
3059 org-todo-kwd-max-priority (1- (length org-todo-keywords))
3060 org-ds-keyword-length (+ 2 (max (length org-deadline-string)
3061 (length org-scheduled-string)))
3062 org-done-string
3063 (nth (1- (length org-todo-keywords)) org-todo-keywords)
3064 org-todo-regexp
3065 (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords
3066 "\\|") "\\)\\>")
3067 org-not-done-regexp
3068 (concat "\\<\\("
3069 (mapconcat 'regexp-quote
3070 (nreverse (cdr (reverse org-todo-keywords)))
3071 "\\|")
3072 "\\)\\>")
3073 org-todo-line-regexp
3074 (concat "^\\(\\*+\\)[ \t]*\\(?:\\("
3075 (mapconcat 'regexp-quote org-todo-keywords "\\|")
3076 "\\)\\>\\)? *\\(.*\\)")
3077 org-nl-done-regexp
3078 (concat "[\r\n]\\*+[ \t]+" org-done-string "\\>")
3079 org-todo-line-tags-regexp
3080 (concat "^\\(\\*+\\)[ \t]*\\(?:\\("
3081 (mapconcat 'regexp-quote org-todo-keywords "\\|")
3082 "\\)\\>\\)? *\\(.*?\\([ \t]:[a-zA-Z0-9:_@]+:[ \t]*\\)?$\\)")
3083 org-looking-at-done-regexp (concat "^" org-done-string "\\>")
3084 org-deadline-regexp (concat "\\<" org-deadline-string)
3085 org-deadline-time-regexp
3086 (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
3087 org-deadline-line-regexp
3088 (concat "\\<\\(" org-deadline-string "\\).*")
3089 org-scheduled-regexp
3090 (concat "\\<" org-scheduled-string)
3091 org-scheduled-time-regexp
3092 (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
3093 org-closed-time-regexp
3094 (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
3095 org-keyword-time-regexp
3096 (concat "\\<\\(" org-scheduled-string
3097 "\\|" org-deadline-string
3098 "\\|" org-closed-string
3099 "\\|" org-clock-string "\\)"
3100 " *[[<]\\([^]>]+\\)[]>]")
3101 org-maybe-keyword-time-regexp
3102 (concat "\\(\\<\\(" org-scheduled-string
3103 "\\|" org-deadline-string
3104 "\\|" org-closed-string
3105 "\\|" org-clock-string "\\)\\)?"
3106 " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^]\r\n>]*?[]>]\\)"))
3107
3108 (org-set-font-lock-defaults)))
3109
3110 ;; Tell the compiler about dynamically scoped variables,
3111 ;; and variables from other packages
3112 (defvar calc-embedded-close-formula) ; defined by the calc package
3113 (defvar calc-embedded-open-formula) ; defined by the calc package
3114 (defvar font-lock-unfontify-region-function) ; defined by font-lock.el
3115 (defvar zmacs-regions) ; XEmacs regions
3116 (defvar original-date) ; dynamically scoped in calendar
3117 (defvar org-old-auto-fill-inhibit-regexp) ; local variable used by `orgtbl-mode'
3118 (defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized
3119 (defvar org-html-entities) ; defined later in this file
3120 (defvar org-goto-start-pos) ; dynamically scoped parameter
3121 (defvar org-time-was-given) ; dynamically scoped parameter
3122 (defvar org-ts-what) ; dynamically scoped parameter
3123 (defvar org-current-export-file) ; dynamically scoped parameter
3124 (defvar org-current-export-dir) ; dynamically scoped parameter
3125 (defvar mark-active) ; Emacs only, not available in XEmacs.
3126 (defvar timecnt) ; dynamically scoped parameter
3127 (defvar levels-open) ; dynamically scoped parameter
3128 (defvar entry) ; dynamically scoped parameter
3129 (defvar state) ; dynamically scoped into `org-after-todo-state-change-hook'
3130 (defvar date) ; dynamically scoped parameter
3131 (defvar description) ; dynamically scoped parameter
3132 (defvar ans1) ; dynamically scoped parameter
3133 (defvar ans2) ; dynamically scoped parameter
3134 (defvar starting-day) ; local variable
3135 (defvar include-all-loc) ; local variable
3136 (defvar vm-message-pointer) ; from vm
3137 (defvar vm-folder-directory) ; from vm
3138 (defvar gnus-other-frame-object) ; from gnus
3139 (defvar wl-summary-buffer-elmo-folder) ; from wanderlust
3140 (defvar wl-summary-buffer-folder-name) ; from wanderlust
3141 (defvar gnus-group-name) ; from gnus
3142 (defvar gnus-article-current) ; from gnus
3143 (defvar w3m-current-url) ; from w3m
3144 (defvar w3m-current-title) ; from w3m
3145 (defvar mh-progs) ; from MH-E
3146 (defvar mh-current-folder) ; from MH-E
3147 (defvar mh-show-folder-buffer) ; from MH-E
3148 (defvar mh-index-folder) ; from MH-E
3149 (defvar mh-searcher) ; from MH-E
3150 (defvar org-selected-point) ; dynamically scoped parameter
3151 (defvar calendar-mode-map) ; from calendar.el
3152 (defvar last-arg) ; local variable
3153 (defvar remember-save-after-remembering) ; from remember.el
3154 (defvar remember-data-file) ; from remember.el
3155 (defvar annotation) ; from remember.el, dynamically scoped in `remember-mode'
3156 (defvar initial) ; from remember.el, dynamically scoped in `remember-mode'
3157 (defvar orgtbl-mode) ; defined later in this file
3158 (defvar Info-current-file) ; from info.el
3159 (defvar Info-current-node) ; from info.el
3160 (defvar texmathp-why) ; from texmathp.el
3161 (defvar org-latex-regexps)
3162 (defvar outline-mode-menu-heading)
3163 (defvar outline-mode-menu-show)
3164 (defvar outline-mode-menu-hide)
3165
3166 ;;; Define the mode
3167
3168 (if (and (not (keymapp outline-mode-map)) (featurep 'allout))
3169 (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."))
3170
3171 (defvar org-struct-menu) ; defined later in this file
3172 (defvar org-org-menu) ; defined later in this file
3173 (defvar org-tbl-menu) ; defined later in this file
3174
3175 ;; We use a before-change function to check if a table might need
3176 ;; an update.
3177 (defvar org-table-may-need-update t
3178 "Indicates that a table might need an update.
3179 This variable is set by `org-before-change-function'.
3180 `org-table-align' sets it back to nil.")
3181 (defvar org-mode-map)
3182 (defvar org-mode-hook nil)
3183 (defvar org-inhibit-startup nil) ; Dynamically-scoped param.
3184 (defvar org-agenda-keep-modes nil) ; Dynamically-scoped param.
3185
3186
3187 ;;;###autoload
3188 (define-derived-mode org-mode outline-mode "Org"
3189 "Outline-based notes management and organizer, alias
3190 \"Carsten's outline-mode for keeping track of everything.\"
3191
3192 Org-mode develops organizational tasks around a NOTES file which
3193 contains information about projects as plain text. Org-mode is
3194 implemented on top of outline-mode, which is ideal to keep the content
3195 of large files well structured. It supports ToDo items, deadlines and
3196 time stamps, which magically appear in the diary listing of the Emacs
3197 calendar. Tables are easily created with a built-in table editor.
3198 Plain text URL-like links connect to websites, emails (VM), Usenet
3199 messages (Gnus), BBDB entries, and any files related to the project.
3200 For printing and sharing of notes, an Org-mode file (or a part of it)
3201 can be exported as a structured ASCII or HTML file.
3202
3203 The following commands are available:
3204
3205 \\{org-mode-map}"
3206
3207 ;; Get rid of Outline menus, they are not needed
3208 ;; Need to do this here because define-derived-mode sets up
3209 ;; the keymap so late. Still, it is a waste to call this each time
3210 ;; we switch another buffer into org-mode.
3211 (if (featurep 'xemacs)
3212 (when (boundp 'outline-mode-menu-heading)
3213 ;; Assume this is Greg's port, it used easymenu
3214 (easy-menu-remove outline-mode-menu-heading)
3215 (easy-menu-remove outline-mode-menu-show)
3216 (easy-menu-remove outline-mode-menu-hide))
3217 (define-key org-mode-map [menu-bar headings] 'undefined)
3218 (define-key org-mode-map [menu-bar hide] 'undefined)
3219 (define-key org-mode-map [menu-bar show] 'undefined))
3220
3221 (easy-menu-add org-org-menu)
3222 (easy-menu-add org-tbl-menu)
3223 (org-install-agenda-files-menu)
3224 (if org-descriptive-links (org-add-to-invisibility-spec '(org-link)))
3225 (org-add-to-invisibility-spec '(org-cwidth))
3226 (when (featurep 'xemacs)
3227 (org-set-local 'line-move-ignore-invisible t))
3228 (setq outline-regexp "\\*+")
3229 ;;(setq outline-regexp "\\(?:\\*+\\|[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\) \\)")
3230 (setq outline-level 'org-outline-level)
3231 (when (and org-ellipsis (stringp org-ellipsis))
3232 (unless org-display-table
3233 (setq org-display-table (make-display-table)))
3234 (set-display-table-slot org-display-table
3235 4 (string-to-vector org-ellipsis))
3236 (setq buffer-display-table org-display-table))
3237 (org-set-regexps-and-options)
3238 ;; Calc embedded
3239 (org-set-local 'calc-embedded-open-mode "# ")
3240 (modify-syntax-entry ?# "<")
3241 (if org-startup-truncated (setq truncate-lines t))
3242 (org-set-local 'font-lock-unfontify-region-function
3243 'org-unfontify-region)
3244 ;; Activate before-change-function
3245 (org-set-local 'org-table-may-need-update t)
3246 (org-add-hook 'before-change-functions 'org-before-change-function nil
3247 'local)
3248 ;; Check for running clock before killing a buffer
3249 (org-add-hook 'kill-buffer-hook 'org-check-running-clock nil 'local)
3250 ;; Paragraphs and auto-filling
3251 (org-set-autofill-regexps)
3252 (org-update-radio-target-regexp)
3253
3254 (if (and org-insert-mode-line-in-empty-file
3255 (interactive-p)
3256 (= (point-min) (point-max)))
3257 (insert " -*- mode: org -*-\n\n"))
3258
3259 (unless org-inhibit-startup
3260 (when org-startup-align-all-tables
3261 (let ((bmp (buffer-modified-p)))
3262 (org-table-map-tables 'org-table-align)
3263 (set-buffer-modified-p bmp)))
3264 (if org-startup-with-deadline-check
3265 (call-interactively 'org-check-deadlines)
3266 (cond
3267 ((eq org-startup-folded t)
3268 (org-cycle '(4)))
3269 ((eq org-startup-folded 'content)
3270 (let ((this-command 'org-cycle) (last-command 'org-cycle))
3271 (org-cycle '(4)) (org-cycle '(4))))))))
3272
3273 (defsubst org-call-with-arg (command arg)
3274 "Call COMMAND interactively, but pretend prefix are was ARG."
3275 (let ((current-prefix-arg arg)) (call-interactively command)))
3276
3277 (defsubst org-current-line (&optional pos)
3278 (+ (if (bolp) 1 0) (count-lines (point-min) (or pos (point)))))
3279
3280 (defun org-current-time ()
3281 "Current time, possibly rounded to `org-time-stamp-rounding-minutes'."
3282 (if (> org-time-stamp-rounding-minutes 0)
3283 (let ((r org-time-stamp-rounding-minutes)
3284 (time (decode-time)))
3285 (apply 'encode-time
3286 (append (list 0 (* r (floor (+ .5 (/ (float (nth 1 time)) r)))))
3287 (nthcdr 2 time))))
3288 (current-time)))
3289
3290 (defun org-add-props (string plist &rest props)
3291 "Add text properties to entire string, from beginning to end.
3292 PLIST may be a list of properties, PROPS are individual properties and values
3293 that will be added to PLIST. Returns the string that was modified."
3294 (add-text-properties
3295 0 (length string) (if props (append plist props) plist) string)
3296 string)
3297 (put 'org-add-props 'lisp-indent-function 2)
3298
3299
3300 ;;; Font-Lock stuff
3301
3302 (defvar org-mouse-map (make-sparse-keymap))
3303 (define-key org-mouse-map
3304 (if (featurep 'xemacs) [button2] [mouse-2]) 'org-open-at-mouse)
3305 (define-key org-mouse-map
3306 (if (featurep 'xemacs) [button3] [mouse-3]) 'org-find-file-at-mouse)
3307 (when org-mouse-1-follows-link
3308 (define-key org-mouse-map [follow-link] 'mouse-face))
3309 (when org-tab-follows-link
3310 (define-key org-mouse-map [(tab)] 'org-open-at-point)
3311 (define-key org-mouse-map "\C-i" 'org-open-at-point))
3312 (when org-return-follows-link
3313 (define-key org-mouse-map [(return)] 'org-open-at-point)
3314 (define-key org-mouse-map "\C-m" 'org-open-at-point))
3315
3316 (require 'font-lock)
3317
3318 (defconst org-non-link-chars "]\t\n\r<>")
3319 (defconst org-link-types '("https?" "ftp" "mailto" "file" "news" "bbdb" "vm"
3320 "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
3321 (defconst org-link-re-with-space
3322 (concat
3323 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
3324 "\\([^" org-non-link-chars " ]"
3325 "[^" org-non-link-chars "]*"
3326 "[^" org-non-link-chars " ]\\)>?")
3327 "Matches a link with spaces, optional angular brackets around it.")
3328
3329 (defconst org-link-re-with-space2
3330 (concat
3331 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
3332 "\\([^" org-non-link-chars " ]"
3333 "[^]\t\n\r]*"
3334 "[^" org-non-link-chars " ]\\)>?")
3335 "Matches a link with spaces, optional angular brackets around it.")
3336
3337 (defconst org-angle-link-re
3338 (concat
3339 "<\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
3340 "\\([^" org-non-link-chars " ]"
3341 "[^" org-non-link-chars "]*"
3342 "\\)>")
3343 "Matches link with angular brackets, spaces are allowed.")
3344 (defconst org-plain-link-re
3345 (concat
3346 "\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
3347 "\\([^]\t\n\r<>,;() ]+\\)")
3348 "Matches plain link, without spaces.")
3349
3350 (defconst org-bracket-link-regexp
3351 "\\[\\[\\([^]]+\\)\\]\\(\\[\\([^]]+\\)\\]\\)?\\]"
3352 "Matches a link in double brackets.")
3353
3354 (defconst org-bracket-link-analytic-regexp
3355 (concat
3356 "\\[\\["
3357 "\\(\\(" (mapconcat 'identity org-link-types "\\|") "\\):\\)?"
3358 "\\([^]]+\\)"
3359 "\\]"
3360 "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
3361 "\\]"))
3362 ; 1: http:
3363 ; 2: http
3364 ; 3: path
3365 ; 4: [desc]
3366 ; 5: desc
3367
3368 (defconst org-ts-lengths
3369 (cons (length (format-time-string (car org-time-stamp-formats)))
3370 (length (format-time-string (cdr org-time-stamp-formats))))
3371 "This holds the lengths of the two different time formats.")
3372 (defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^\r\n>]*?\\)>"
3373 "Regular expression for fast time stamp matching.")
3374 (defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^\r\n>]*?\\)[]>]"
3375 "Regular expression for fast time stamp matching.")
3376 (defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\([^]0-9>\r\n]*\\)\\(\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
3377 "Regular expression matching time strings for analysis.")
3378 (defconst org-ts-regexp2 (concat "<" org-ts-regexp1 ">")
3379 "Regular expression matching time stamps, with groups.")
3380 (defconst org-ts-regexp3 (concat "[[<]" org-ts-regexp1 "[]>]")
3381 "Regular expression matching time stamps (also [..]), with groups.")
3382 (defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp)
3383 "Regular expression matching a time stamp range.")
3384 (defconst org-tr-regexp-both
3385 (concat org-ts-regexp-both "--?-?" org-ts-regexp-both)
3386 "Regular expression matching a time stamp range.")
3387 (defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?"
3388 org-ts-regexp "\\)?")
3389 "Regular expression matching a time stamp or time stamp range.")
3390 (defconst org-tsr-regexp-both (concat org-ts-regexp-both "\\(--?-?"
3391 org-ts-regexp-both "\\)?")
3392 "Regular expression matching a time stamp or time stamp range.
3393 The time stamps may be either active or inactive.")
3394
3395 (defvar org-\81§emph-face nil)
3396
3397 (defun org-do-emphasis-faces (limit)
3398 "Run through the buffer and add overlays to links."
3399 (if (re-search-forward org-emph-re limit t)
3400 (progn
3401 (font-lock-prepend-text-property (match-beginning 2) (match-end 2)
3402 'face
3403 (nth 1 (assoc (match-string 3)
3404 org-emphasis-alist)))
3405 (add-text-properties (match-beginning 2) (match-end 2)
3406 '(font-lock-multiline t))
3407 (backward-char 1)
3408 t)))
3409
3410 (defun org-activate-plain-links (limit)
3411 "Run through the buffer and add overlays to links."
3412 (if (re-search-forward org-plain-link-re limit t)
3413 (progn
3414 (add-text-properties (match-beginning 0) (match-end 0)
3415 (list 'mouse-face 'highlight
3416 'rear-nonsticky t
3417 'keymap org-mouse-map
3418 ))
3419 t)))
3420
3421 (defun org-activate-angle-links (limit)
3422 "Run through the buffer and add overlays to links."
3423 (if (re-search-forward org-angle-link-re limit t)
3424 (progn
3425 (add-text-properties (match-beginning 0) (match-end 0)
3426 (list 'mouse-face 'highlight
3427 'rear-nonsticky t
3428 'keymap org-mouse-map
3429 ))
3430 t)))
3431
3432 (defmacro org-maybe-intangible (props)
3433 "Add '(intangigble t) to PROPS if Emacs version is earlier than Emacs 22.
3434 In emacs 21, invisible text is not avoided by the command loop, so the
3435 intangible property is needed to make sure point skips this text.
3436 In Emacs 22, this is not necessary. The intangible text property has
3437 led to problems with flyspell. These problems are fixed in flyspell.el,
3438 but we still avoid setting the property in Emacs 22 and later.
3439 We use a macro so that the test can happen at compilation time."
3440 (if (< emacs-major-version 22)
3441 `(append '(intangible t) ,props)
3442 props))
3443
3444 (defun org-activate-bracket-links (limit)
3445 "Run through the buffer and add overlays to bracketed links."
3446 (if (re-search-forward org-bracket-link-regexp limit t)
3447 (let* ((help (concat "LINK: "
3448 (org-match-string-no-properties 1)))
3449 ;; FIXME: above we should remove the escapes.
3450 ;; but that requires another match, protecting match data,
3451 ;; a lot of overhead for font-lock.
3452 (ip (org-maybe-intangible
3453 (list 'invisible 'org-link 'rear-nonsticky t
3454 'keymap org-mouse-map 'mouse-face 'highlight
3455 'help-echo help)))
3456 (vp (list 'rear-nonsticky t
3457 'keymap org-mouse-map 'mouse-face 'highlight
3458 'help-echo help)))
3459 ;; We need to remove the invisible property here. Table narrowing
3460 ;; may have made some of this invisible.
3461 (remove-text-properties (match-beginning 0) (match-end 0)
3462 '(invisible nil))
3463 (if (match-end 3)
3464 (progn
3465 (add-text-properties (match-beginning 0) (match-beginning 3) ip)
3466 (add-text-properties (match-beginning 3) (match-end 3) vp)
3467 (add-text-properties (match-end 3) (match-end 0) ip))
3468 (add-text-properties (match-beginning 0) (match-beginning 1) ip)
3469 (add-text-properties (match-beginning 1) (match-end 1) vp)
3470 (add-text-properties (match-end 1) (match-end 0) ip))
3471 t)))
3472
3473 (defun org-activate-dates (limit)
3474 "Run through the buffer and add overlays to dates."
3475 ; (if (re-search-forward org-tsr-regexp limit t)
3476 ; (if (re-search-forward
3477 ; (if org-display-custom-times org-ts-regexp-both org-tsr-regexp-both)
3478 ; limit t)
3479 (if (re-search-forward org-tsr-regexp-both limit t)
3480 (progn
3481 (add-text-properties (match-beginning 0) (match-end 0)
3482 (list 'mouse-face 'highlight
3483 'rear-nonsticky t
3484 'keymap org-mouse-map))
3485 (when org-display-custom-times
3486 (if (match-end 3)
3487 (org-display-custom-time (match-beginning 3) (match-end 3)))
3488 (org-display-custom-time (match-beginning 1) (match-end 1)))
3489 t)))
3490
3491 (defvar org-target-link-regexp nil
3492 "Regular expression matching radio targets in plain text.")
3493 (defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>"
3494 "Regular expression matching a link target.")
3495 (defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>"
3496 "Regular expression matching a link target.")
3497
3498 (defun org-activate-target-links (limit)
3499 "Run through the buffer and add overlays to target matches."
3500 (when org-target-link-regexp
3501 (let ((case-fold-search t))
3502 (if (re-search-forward org-target-link-regexp limit t)
3503 (progn
3504 (add-text-properties (match-beginning 0) (match-end 0)
3505 (list 'mouse-face 'highlight
3506 'rear-nonsticky t
3507 'keymap org-mouse-map
3508 'help-echo "Radio target link"
3509 'org-linked-text t))
3510 t)))))
3511
3512 (defun org-update-radio-target-regexp ()
3513 "Find all radio targets in this file and update the regular expression."
3514 (interactive)
3515 (when (memq 'radio org-activate-links)
3516 (setq org-target-link-regexp
3517 (org-make-target-link-regexp (org-all-targets 'radio)))
3518 (org-restart-font-lock)))
3519
3520 (defun org-hide-wide-columns (limit)
3521 (let (s e)
3522 (setq s (text-property-any (point) (or limit (point-max))
3523 'org-cwidth t))
3524 (when s
3525 (setq e (next-single-property-change s 'org-cwidth))
3526 (add-text-properties s e (org-maybe-intangible '(invisible org-cwidth)))
3527 (goto-char e)
3528 t)))
3529
3530 (defun org-restart-font-lock ()
3531 "Restart font-lock-mode, to force refontification."
3532 (when (and (boundp 'font-lock-mode) font-lock-mode)
3533 (font-lock-mode -1)
3534 (font-lock-mode 1)))
3535
3536 (defun org-all-targets (&optional radio)
3537 "Return a list of all targets in this file.
3538 With optional argument RADIO, only find radio targets."
3539 (let ((re (if radio org-radio-target-regexp org-target-regexp))
3540 rtn)
3541 (save-excursion
3542 (goto-char (point-min))
3543 (while (re-search-forward re nil t)
3544 (add-to-list 'rtn (downcase (org-match-string-no-properties 1))))
3545 rtn)))
3546
3547 (defun org-make-target-link-regexp (targets)
3548 "Make regular expression matching all strings in TARGETS.
3549 The regular expression finds the targets also if there is a line break
3550 between words."
3551 (and targets
3552 (concat
3553 "\\<\\("
3554 (mapconcat
3555 (lambda (x)
3556 (while (string-match " +" x)
3557 (setq x (replace-match "\\s-+" t t x)))
3558 x)
3559 targets
3560 "\\|")
3561 "\\)\\>")))
3562
3563 (defvar org-camel-regexp "\\*?\\<[A-Z]+[a-z]+[A-Z][a-zA-Z]*\\>"
3564 "Matches CamelCase words, possibly with a star before it.")
3565
3566 (defun org-activate-camels (limit)
3567 "Run through the buffer and add overlays to dates."
3568 (if (re-search-forward org-camel-regexp limit t)
3569 (progn
3570 (add-text-properties (match-beginning 0) (match-end 0)
3571 (list 'mouse-face 'highlight
3572 'rear-nonsticky t
3573 'keymap org-mouse-map))
3574 t)))
3575
3576 (defun org-activate-tags (limit)
3577 (if (re-search-forward "[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \r\n]" limit t)
3578 (progn
3579 (add-text-properties (match-beginning 1) (match-end 1)
3580 (list 'mouse-face 'highlight
3581 'rear-nonsticky t
3582 'keymap org-mouse-map))
3583 t)))
3584
3585 (defun org-font-lock-level ()
3586 (save-excursion
3587 (org-back-to-heading t)
3588 (- (match-end 0) (match-beginning 0))))
3589
3590 (defun org-outline-level ()
3591 (save-excursion
3592 (looking-at outline-regexp)
3593 (if (match-beginning 1)
3594 (+ (org-get-string-indentation (match-string 1)) 1000)
3595 (- (match-end 0) (match-beginning 0)))))
3596
3597 (defvar org-font-lock-keywords nil)
3598
3599 (defun org-set-font-lock-defaults ()
3600 (let* ((em org-fontify-emphasized-text)
3601 (lk org-activate-links)
3602 (org-font-lock-extra-keywords
3603 ;; Headlines
3604 (list
3605 '("^\\(\\**\\)\\(\\*\\)\\(.*\\)" (1 (org-get-level-face 1))
3606 (2 (org-get-level-face 2)) (3 (org-get-level-face 3)))
3607 '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)"
3608 (1 'org-table))
3609 ;; Links
3610 (if (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
3611 (if (memq 'plain lk) '(org-activate-plain-links (0 'org-link t)))
3612 (if (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
3613 (if (memq 'radio lk) '(org-activate-target-links (0 'org-link t)))
3614 (if (memq 'date lk) '(org-activate-dates (0 'org-date t)))
3615 (if (memq 'camel lk) '(org-activate-camels (0 'org-link t)))
3616 (if (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
3617 (if org-table-limit-column-width
3618 '(org-hide-wide-columns (0 nil append)))
3619 ;; TODO lines
3620 (list (concat "^\\*+[ \t]*" org-not-done-regexp)
3621 '(1 'org-todo t))
3622 ;; Priorities
3623 (list (concat "\\[#[A-Z]\\]") '(0 'org-special-keyword t))
3624 ;; Special keywords
3625 (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t))
3626 (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword t))
3627 (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t))
3628 (list (concat "\\<" org-clock-string) '(0 'org-special-keyword t))
3629 ;; Emphasis
3630 (if em
3631 (if (featurep 'xemacs)
3632 '(org-do-emphasis-faces (0 nil append))
3633 '(org-do-emphasis-faces)))
3634 ;; Checkboxes, similar to Frank Ruell's org-checklet.el
3635 '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)"
3636 2 'bold prepend)
3637 (if org-provide-checkbox-statistics
3638 '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
3639 (0 (org-get-checkbox-statistics-face) t)))
3640 ;; COMMENT
3641 (list (concat "^\\*+[ \t]*\\<\\(" org-comment-string
3642 "\\|" org-quote-string "\\)\\>")
3643 '(1 'org-special-keyword t))
3644 '("^#.*" (0 'font-lock-comment-face t))
3645 ;; DONE
3646 (if org-fontify-done-headline
3647 (list (concat "^[*]+ +\\<\\(" org-done-string "\\)\\(.*\\)\\>")
3648 '(1 'org-done t) '(2 'org-headline-done t))
3649 (list (concat "^[*]+ +\\<\\(" org-done-string "\\)\\>")
3650 '(1 'org-done t)))
3651 ;; Table stuff
3652 '("^[ \t]*\\(:.*\\)" (1 'org-table t))
3653 '("| *\\(:?=[^|\n]*\\)" (1 'org-formula t))
3654 '("^[ \t]*| *\\([#!$*_^]\\) *|" (1 'org-formula t))
3655 (if org-format-transports-properties-p
3656 '("| *\\(<[0-9]+>\\) *" (1 'org-formula t)))
3657 '("^\\*+ \\(.*:ARCHIVE:.*\\)" (1 'org-archived prepend))
3658 )))
3659 (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords))
3660 ;; Now set the full font-lock-keywords
3661 (org-set-local 'org-font-lock-keywords org-font-lock-extra-keywords)
3662 (org-set-local 'font-lock-defaults
3663 '(org-font-lock-keywords t nil nil backward-paragraph))
3664 (kill-local-variable 'font-lock-keywords) nil))
3665
3666 (defvar org-m nil)
3667 (defvar org-l nil)
3668 (defvar org-f nil)
3669 (defun org-get-level-face (n)
3670 "Get the right face for match N in font-lock matching of healdines."
3671 (setq org-l (- (match-end 2) (match-beginning 1)))
3672 (if org-odd-levels-only (setq org-l (1+ (/ org-l 2))))
3673 ; (setq org-f (nth (1- (% org-l org-n-levels)) org-level-faces))
3674 (setq org-f (nth (% (1- org-l) org-n-levels) org-level-faces))
3675 (cond
3676 ((eq n 1) (if org-hide-leading-stars 'org-hide org-f))
3677 ((eq n 2) org-f)
3678 (t (if org-level-color-stars-only nil org-f))))
3679
3680 (defun org-unfontify-region (beg end &optional maybe_loudly)
3681 "Remove fontification and activation overlays from links."
3682 (font-lock-default-unfontify-region beg end)
3683 (let* ((buffer-undo-list t)
3684 (inhibit-read-only t) (inhibit-point-motion-hooks t)
3685 (inhibit-modification-hooks t)
3686 deactivate-mark buffer-file-name buffer-file-truename)
3687 (remove-text-properties beg end
3688 '(mouse-face t keymap t org-linked-text t
3689 rear-nonsticky t
3690 invisible t intangible t))))
3691
3692 ;;; Visibility cycling
3693
3694 (defvar org-cycle-global-status nil)
3695 (make-variable-buffer-local 'org-cycle-global-status)
3696 (defvar org-cycle-subtree-status nil)
3697 (make-variable-buffer-local 'org-cycle-subtree-status)
3698
3699 ;;;###autoload
3700 (defun org-cycle (&optional arg)
3701 "Visibility cycling for Org-mode.
3702
3703 - When this function is called with a prefix argument, rotate the entire
3704 buffer through 3 states (global cycling)
3705 1. OVERVIEW: Show only top-level headlines.
3706 2. CONTENTS: Show all headlines of all levels, but no body text.
3707 3. SHOW ALL: Show everything.
3708
3709 - When point is at the beginning of a headline, rotate the subtree started
3710 by this line through 3 different states (local cycling)
3711 1. FOLDED: Only the main headline is shown.
3712 2. CHILDREN: The main headline and the direct children are shown.
3713 From this state, you can move to one of the children
3714 and zoom in further.
3715 3. SUBTREE: Show the entire subtree, including body text.
3716
3717 - When there is a numeric prefix, go up to a heading with level ARG, do
3718 a `show-subtree' and return to the previous cursor position. If ARG
3719 is negative, go up that many levels.
3720
3721 - When point is not at the beginning of a headline, execute
3722 `indent-relative', like TAB normally does. See the option
3723 `org-cycle-emulate-tab' for details.
3724
3725 - Special case: if point is the the beginning of the buffer and there is
3726 no headline in line 1, this function will act as if called with prefix arg."
3727 (interactive "P")
3728 (let* ((outline-regexp
3729 (if (and (org-mode-p) org-cycle-include-plain-lists)
3730 "\\(?:\\*+\\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) \\)"
3731 outline-regexp))
3732 (bob-special (and org-cycle-global-at-bob (bobp)
3733 (not (looking-at outline-regexp))))
3734 (org-cycle-hook
3735 (if bob-special
3736 (delq 'org-optimize-window-after-visibility-change
3737 (copy-sequence org-cycle-hook))
3738 org-cycle-hook))
3739 (pos (point)))
3740
3741 (if (or bob-special (equal arg '(4)))
3742 ;; special case: use global cycling
3743 (setq arg t))
3744
3745 (cond
3746
3747 ((org-at-table-p 'any)
3748 ;; Enter the table or move to the next field in the table
3749 (or (org-table-recognize-table.el)
3750 (progn
3751 (if arg (org-table-edit-field t)
3752 (org-table-justify-field-maybe)
3753 (call-interactively 'org-table-next-field)))))
3754
3755 ((eq arg t) ;; Global cycling
3756
3757 (cond
3758 ((and (eq last-command this-command)
3759 (eq org-cycle-global-status 'overview))
3760 ;; We just created the overview - now do table of contents
3761 ;; This can be slow in very large buffers, so indicate action
3762 (message "CONTENTS...")
3763 (org-content)
3764 (message "CONTENTS...done")
3765 (setq org-cycle-global-status 'contents)
3766 (run-hook-with-args 'org-cycle-hook 'contents))
3767
3768 ((and (eq last-command this-command)
3769 (eq org-cycle-global-status 'contents))
3770 ;; We just showed the table of contents - now show everything
3771 (show-all)
3772 (message "SHOW ALL")
3773 (setq org-cycle-global-status 'all)
3774 (run-hook-with-args 'org-cycle-hook 'all))
3775
3776 (t
3777 ;; Default action: go to overview
3778 (org-overview)
3779 (message "OVERVIEW")
3780 (setq org-cycle-global-status 'overview)
3781 (run-hook-with-args 'org-cycle-hook 'overview))))
3782
3783 ((integerp arg)
3784 ;; Show-subtree, ARG levels up from here.
3785 (save-excursion
3786 (org-back-to-heading)
3787 (outline-up-heading (if (< arg 0) (- arg)
3788 (- (funcall outline-level) arg)))
3789 (org-show-subtree)))
3790
3791 ((save-excursion (beginning-of-line 1) (looking-at outline-regexp))
3792 ;; At a heading: rotate between three different views
3793 (org-back-to-heading)
3794 (let ((goal-column 0) eoh eol eos)
3795 ;; First, some boundaries
3796 (save-excursion
3797 (org-back-to-heading)
3798 (save-excursion
3799 (beginning-of-line 2)
3800 (while (and (not (eobp)) ;; this is like `next-line'
3801 (get-char-property (1- (point)) 'invisible))
3802 (beginning-of-line 2)) (setq eol (point)))
3803 (outline-end-of-heading) (setq eoh (point))
3804 (org-end-of-subtree t) (setq eos (point))
3805 (outline-next-heading))
3806 ;; Find out what to do next and set `this-command'
3807 (cond
3808 ((and (= eos eoh)
3809 ;; Nothing is hidden behind this heading
3810 (message "EMPTY ENTRY")
3811 (setq org-cycle-subtree-status nil)))
3812 ((>= eol eos)
3813 ;; Entire subtree is hidden in one line: open it
3814 (org-show-entry)
3815 (show-children)
3816 (message "CHILDREN")
3817 (setq org-cycle-subtree-status 'children)
3818 (run-hook-with-args 'org-cycle-hook 'children))
3819 ((and (eq last-command this-command)
3820 (eq org-cycle-subtree-status 'children))
3821 ;; We just showed the children, now show everything.
3822 (org-show-subtree)
3823 (message "SUBTREE")
3824 (setq org-cycle-subtree-status 'subtree)
3825 (run-hook-with-args 'org-cycle-hook 'subtree))
3826 (t
3827 ;; Default action: hide the subtree.
3828 (hide-subtree)
3829 (message "FOLDED")
3830 (setq org-cycle-subtree-status 'folded)
3831 (run-hook-with-args 'org-cycle-hook 'folded)))))
3832
3833 ;; TAB emulation
3834 (buffer-read-only (org-back-to-heading))
3835
3836 ((org-try-cdlatex-tab))
3837
3838 ((if (and (memq org-cycle-emulate-tab '(white whitestart))
3839 (save-excursion (beginning-of-line 1) (looking-at "[ \t]*"))
3840 (or (and (eq org-cycle-emulate-tab 'white)
3841 (= (match-end 0) (point-at-eol)))
3842 (and (eq org-cycle-emulate-tab 'whitestart)
3843 (>= (match-end 0) pos))))
3844 t
3845 (eq org-cycle-emulate-tab t))
3846 (if (and (looking-at "[ \n\r\t]")
3847 (string-match "^[ \t]*$" (buffer-substring
3848 (point-at-bol) (point))))
3849 (progn
3850 (beginning-of-line 1)
3851 (and (looking-at "[ \t]+") (replace-match ""))))
3852 (indent-relative))
3853
3854 (t (save-excursion
3855 (org-back-to-heading)
3856 (org-cycle))))))
3857
3858 ;;;###autoload
3859 (defun org-global-cycle (&optional arg)
3860 "Cycle the global visibility. For details see `org-cycle'."
3861 (interactive "P")
3862 (let ((org-cycle-include-plain-lists
3863 (if (org-mode-p) org-cycle-include-plain-lists nil)))
3864 (if (integerp arg)
3865 (progn
3866 (show-all)
3867 (hide-sublevels arg)
3868 (setq org-cycle-global-status 'contents))
3869 (org-cycle '(4)))))
3870
3871 (defun org-overview ()
3872 "Switch to overview mode, shoing only top-level headlines.
3873 Really, this shows all headlines with level equal or greater than the level
3874 of the first headline in the buffer. This is important, because if the
3875 first headline is not level one, then (hide-sublevels 1) gives confusing
3876 results."
3877 (interactive)
3878 (hide-sublevels (save-excursion
3879 (goto-char (point-min))
3880 (if (re-search-forward (concat "^" outline-regexp) nil t)
3881 (progn
3882 (goto-char (match-beginning 0))
3883 (funcall outline-level))
3884 1))))
3885
3886 ;; FIXME: allow an argument to give a limiting level for this.
3887 (defun org-content ()
3888 "Show all headlines in the buffer, like a table of contents"
3889 (interactive)
3890 (save-excursion
3891 ;; Visit all headings and show their offspring
3892 (goto-char (point-max))
3893 (catch 'exit
3894 (while (and (progn (condition-case nil
3895 (outline-previous-visible-heading 1)
3896 (error (goto-char (point-min))))
3897 t)
3898 (looking-at outline-regexp))
3899 (show-branches)
3900 (if (bobp) (throw 'exit nil))))))
3901
3902
3903 (defun org-optimize-window-after-visibility-change (state)
3904 "Adjust the window after a change in outline visibility.
3905 This function is the default value of the hook `org-cycle-hook'."
3906 (when (get-buffer-window (current-buffer))
3907 (cond
3908 ((eq state 'overview) (org-first-headline-recenter 1))
3909 ((eq state 'content) nil)
3910 ((eq state 'all) nil)
3911 ((eq state 'folded) nil)
3912 ((eq state 'children) (or (org-subtree-end-visible-p) (recenter 1)))
3913 ((eq state 'subtree) (or (org-subtree-end-visible-p) (recenter 1))))))
3914
3915 (defun org-subtree-end-visible-p ()
3916 "Is the end of the current subtree visible?"
3917 (pos-visible-in-window-p
3918 (save-excursion (org-end-of-subtree t) (point))))
3919
3920 (defun org-first-headline-recenter (&optional N)
3921 "Move cursor to the first headline and recenter the headline.
3922 Optional argument N means, put the headline into the Nth line of the window."
3923 (goto-char (point-min))
3924 (when (re-search-forward (concat "^\\(" outline-regexp "\\)") nil t)
3925 (beginning-of-line)
3926 (recenter (prefix-numeric-value N))))
3927
3928 (defvar org-goto-window-configuration nil)
3929 (defvar org-goto-marker nil)
3930 (defvar org-goto-map (make-sparse-keymap))
3931 (let ((cmds '(isearch-forward isearch-backward)) cmd)
3932 (while (setq cmd (pop cmds))
3933 (substitute-key-definition cmd cmd org-goto-map global-map)))
3934 (define-key org-goto-map "\C-m" 'org-goto-ret)
3935 (define-key org-goto-map [(left)] 'org-goto-left)
3936 (define-key org-goto-map [(right)] 'org-goto-right)
3937 (define-key org-goto-map [(?q)] 'org-goto-quit)
3938 (define-key org-goto-map [(control ?g)] 'org-goto-quit)
3939 (define-key org-goto-map "\C-i" 'org-cycle)
3940 (define-key org-goto-map [(tab)] 'org-cycle)
3941 (define-key org-goto-map [(down)] 'outline-next-visible-heading)
3942 (define-key org-goto-map [(up)] 'outline-previous-visible-heading)
3943 (define-key org-goto-map "n" 'outline-next-visible-heading)
3944 (define-key org-goto-map "p" 'outline-previous-visible-heading)
3945 (define-key org-goto-map "f" 'outline-forward-same-level)
3946 (define-key org-goto-map "b" 'outline-backward-same-level)
3947 (define-key org-goto-map "u" 'outline-up-heading)
3948 (define-key org-goto-map "\C-c\C-n" 'outline-next-visible-heading)
3949 (define-key org-goto-map "\C-c\C-p" 'outline-previous-visible-heading)
3950 (define-key org-goto-map "\C-c\C-f" 'outline-forward-same-level)
3951 (define-key org-goto-map "\C-c\C-b" 'outline-backward-same-level)
3952 (define-key org-goto-map "\C-c\C-u" 'outline-up-heading)
3953 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
3954 (while l (define-key org-goto-map (int-to-string (pop l)) 'digit-argument)))
3955
3956 (defconst org-goto-help
3957 "Select a location to jump to, press RET
3958 \[Up]/[Down]=next/prev headline TAB=cycle visibility RET=select [Q]uit")
3959
3960 (defun org-goto ()
3961 "Go to a different location of the document, keeping current visibility.
3962
3963 When you want to go to a different location in a document, the fastest way
3964 is often to fold the entire buffer and then dive into the tree. This
3965 method has the disadvantage, that the previous location will be folded,
3966 which may not be what you want.
3967
3968 This command works around this by showing a copy of the current buffer in
3969 overview mode. You can dive into the tree in that copy, to find the
3970 location you want to reach. When pressing RET, the command returns to the
3971 original buffer in which the visibility is still unchanged. It then jumps
3972 to the new location, making it and the headline hierarchy above it visible."
3973 (interactive)
3974 (let* ((org-goto-start-pos (point))
3975 (selected-point
3976 (org-get-location (current-buffer) org-goto-help)))
3977 (if selected-point
3978 (progn
3979 (org-mark-ring-push org-goto-start-pos)
3980 (goto-char selected-point)
3981 (if (or (org-invisible-p) (org-invisible-p2))
3982 (org-show-context 'org-goto)))
3983 (error "Quit"))))
3984
3985 (defun org-get-location (buf help)
3986 "Let the user select a location in the Org-mode buffer BUF.
3987 This function uses a recursive edit. It returns the selected position
3988 or nil."
3989 (let (org-selected-point)
3990 (save-excursion
3991 (save-window-excursion
3992 (delete-other-windows)
3993 (switch-to-buffer (get-buffer-create "*org-goto*"))
3994 (with-output-to-temp-buffer "*Help*"
3995 (princ help))
3996 (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*"))
3997 (setq buffer-read-only nil)
3998 (erase-buffer)
3999 (insert-buffer-substring buf)
4000 (let ((org-startup-truncated t)
4001 (org-startup-folded t)
4002 (org-startup-align-all-tables nil)
4003 (org-startup-with-deadline-check nil))
4004 (org-mode))
4005 (setq buffer-read-only t)
4006 (if (boundp 'org-goto-start-pos)
4007 (goto-char org-goto-start-pos)
4008 (goto-char (point-min)))
4009 (org-beginning-of-line)
4010 (message "Select location and press RET")
4011 ;; now we make sure that during selection, ony very few keys work
4012 ;; and that it is impossible to switch to another window.
4013 (let ((gm (current-global-map))
4014 (overriding-local-map org-goto-map))
4015 (unwind-protect
4016 (progn
4017 (use-global-map org-goto-map)
4018 (recursive-edit))
4019 (use-global-map gm)))))
4020 (kill-buffer "*org-goto*")
4021 org-selected-point))
4022
4023 (defun org-goto-ret (&optional arg)
4024 "Finish `org-goto' by going to the new location."
4025 (interactive "P")
4026 (setq org-selected-point (point)
4027 current-prefix-arg arg)
4028 (throw 'exit nil))
4029
4030 (defun org-goto-left ()
4031 "Finish `org-goto' by going to the new location."
4032 (interactive)
4033 (if (org-on-heading-p)
4034 (progn
4035 (beginning-of-line 1)
4036 (setq org-selected-point (point)
4037 current-prefix-arg (- (match-end 0) (match-beginning 0)))
4038 (throw 'exit nil))
4039 (error "Not on a heading")))
4040
4041 (defun org-goto-right ()
4042 "Finish `org-goto' by going to the new location."
4043 (interactive)
4044 (if (org-on-heading-p)
4045 (progn
4046 (outline-end-of-subtree)
4047 (or (eobp) (forward-char 1))
4048 (setq org-selected-point (point)
4049 current-prefix-arg (- (match-end 0) (match-beginning 0)))
4050 (throw 'exit nil))
4051 (error "Not on a heading")))
4052
4053 (defun org-goto-quit ()
4054 "Finish `org-goto' without cursor motion."
4055 (interactive)
4056 (setq org-selected-point nil)
4057 (throw 'exit nil))
4058
4059 ;;; Promotion, Demotion, Inserting new headlines
4060
4061 (defvar org-ignore-region nil
4062 "To temporarily disable the active region.")
4063
4064 (defun org-insert-heading (&optional force-heading)
4065 "Insert a new heading or item with same depth at point.
4066 If point is in a plain list and FORCE-HEADING is nil, create a new list item.
4067 If point is at the beginning of a headline, insert a sibling before the
4068 current headline. If point is in the middle of a headline, split the headline
4069 at that position and make the rest of the headline part of the sibling below
4070 the current headline."
4071 (interactive "P")
4072 (if (= (buffer-size) 0)
4073 (insert "\n* ")
4074 (when (or force-heading (not (org-insert-item)))
4075 (let* ((head (save-excursion
4076 (condition-case nil
4077 (progn
4078 (org-back-to-heading)
4079 (match-string 0))
4080 (error "*"))))
4081 (blank (cdr (assq 'heading org-blank-before-new-entry)))
4082 pos)
4083 (cond
4084 ((and (org-on-heading-p) (bolp)
4085 (save-excursion (backward-char 1) (not (org-invisible-p))))
4086 (open-line (if blank 2 1)))
4087 ((and (bolp) (save-excursion
4088 (backward-char 1) (not (org-invisible-p))))
4089 nil)
4090 (t (newline (if blank 2 1))))
4091 (insert head) (just-one-space)
4092 (setq pos (point))
4093 (end-of-line 1)
4094 (unless (= (point) pos) (just-one-space) (backward-delete-char 1))
4095 (run-hooks 'org-insert-heading-hook)))))
4096
4097 (defun org-in-item-p ()
4098 "It the cursor inside a plain list item.
4099 Does not have to be the first line."
4100 (save-excursion
4101 (condition-case nil
4102 (progn
4103 (org-beginning-of-item)
4104 (org-at-item-p)
4105 t)
4106 (error nil))))
4107
4108 (defun org-insert-item (&optional checkbox)
4109 "Insert a new item at the current level.
4110 Return t when things worked, nil when we are not in an item."
4111 (when (save-excursion
4112 (condition-case nil
4113 (progn
4114 (org-beginning-of-item)
4115 (org-at-item-p)
4116 (if (org-invisible-p) (error "Invisible item"))
4117 t)
4118 (error nil)))
4119 (let* ((bul (match-string 0))
4120 (eow (save-excursion (beginning-of-line 1) (looking-at "[ \t]*")
4121 (match-end 0)))
4122 (blank (cdr (assq 'plain-list-item org-blank-before-new-entry)))
4123 pos)
4124 (cond
4125 ((and (org-at-item-p) (<= (point) eow))
4126 ;; before the bullet
4127 (beginning-of-line 1)
4128 (open-line (if blank 2 1)))
4129 ((<= (point) eow)
4130 (beginning-of-line 1))
4131 (t (newline (if blank 2 1))))
4132 (insert bul (if checkbox "[ ]" ""))
4133 (just-one-space)
4134 (setq pos (point))
4135 (end-of-line 1)
4136 (unless (= (point) pos) (just-one-space) (backward-delete-char 1)))
4137 (org-maybe-renumber-ordered-list)
4138 (and checkbox (org-update-checkbox-count-maybe))
4139 t))
4140
4141 (defun org-insert-todo-heading (arg)
4142 "Insert a new heading with the same level and TODO state as current heading.
4143 If the heading has no TODO state, or if the state is DONE, use the first
4144 state (TODO by default). Also with prefix arg, force first state."
4145 (interactive "P")
4146 (when (not (org-insert-item 'checkbox))
4147 (org-insert-heading)
4148 (save-excursion
4149 (org-back-to-heading)
4150 (outline-previous-heading)
4151 (looking-at org-todo-line-regexp))
4152 (if (or arg
4153 (not (match-beginning 2))
4154 (equal (match-string 2) org-done-string))
4155 (insert (car org-todo-keywords) " ")
4156 (insert (match-string 2) " "))))
4157
4158 (defun org-promote-subtree ()
4159 "Promote the entire subtree.
4160 See also `org-promote'."
4161 (interactive)
4162 (save-excursion
4163 (org-map-tree 'org-promote))
4164 (org-fix-position-after-promote))
4165
4166 (defun org-demote-subtree ()
4167 "Demote the entire subtree. See `org-demote'.
4168 See also `org-promote'."
4169 (interactive)
4170 (save-excursion
4171 (org-map-tree 'org-demote))
4172 (org-fix-position-after-promote))
4173
4174
4175 (defun org-do-promote ()
4176 "Promote the current heading higher up the tree.
4177 If the region is active in `transient-mark-mode', promote all headings
4178 in the region."
4179 (interactive)
4180 (save-excursion
4181 (if (org-region-active-p)
4182 (org-map-region 'org-promote (region-beginning) (region-end))
4183 (org-promote)))
4184 (org-fix-position-after-promote))
4185
4186 (defun org-do-demote ()
4187 "Demote the current heading lower down the tree.
4188 If the region is active in `transient-mark-mode', demote all headings
4189 in the region."
4190 (interactive)
4191 (save-excursion
4192 (if (org-region-active-p)
4193 (org-map-region 'org-demote (region-beginning) (region-end))
4194 (org-demote)))
4195 (org-fix-position-after-promote))
4196
4197 (defun org-fix-position-after-promote ()
4198 "Make sure that after pro/demotion cursor position is right."
4199 (if (and (equal (char-after) ?\n)
4200 (save-excursion
4201 (skip-chars-backward "a-zA-Z0-9_@")
4202 (looking-at org-todo-regexp)))
4203 (insert " "))
4204 (and (equal (char-after) ?\ )
4205 (equal (char-before) ?*)
4206 (forward-char 1)))
4207
4208 (defun org-get-legal-level (level &optional change)
4209 "Rectify a level change under the influence of `org-odd-levels-only'
4210 LEVEL is a current level, CHANGE is by how much the level should be
4211 modified. Even if CHANGE is nil, LEVEL may be returned modified because
4212 even level numbers will become the next higher odd number."
4213 (if org-odd-levels-only
4214 (cond ((or (not change) (= 0 change)) (1+ (* 2 (/ level 2))))
4215 ((> change 0) (1+ (* 2 (/ (+ level (* 2 change)) 2))))
4216 ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2))))))
4217 (max 1 (+ level change))))
4218
4219 (defun org-promote ()
4220 "Promote the current heading higher up the tree.
4221 If the region is active in `transient-mark-mode', promote all headings
4222 in the region."
4223 (org-back-to-heading t)
4224 (let* ((level (save-match-data (funcall outline-level)))
4225 (up-head (make-string (org-get-legal-level level -1) ?*))
4226 (diff (abs (- level (length up-head)))))
4227 (if (= level 1) (error "Cannot promote to level 0. UNDO to recover"))
4228 (replace-match up-head nil t)
4229 ;; Fixup tag positioning
4230 (and org-auto-align-tags (org-set-tags nil t))
4231 (if org-adapt-indentation (org-fixup-indentation (- diff)))))
4232
4233 (defun org-demote ()
4234 "Demote the current heading lower down the tree.
4235 If the region is active in `transient-mark-mode', demote all headings
4236 in the region."
4237 (org-back-to-heading t)
4238 (let* ((level (save-match-data (funcall outline-level)))
4239 (down-head (make-string (org-get-legal-level level 1) ?*))
4240 (diff (abs (- level (length down-head)))))
4241 (replace-match down-head nil t)
4242 ;; Fixup tag positioning
4243 (and org-auto-align-tags (org-set-tags nil t))
4244 (if org-adapt-indentation (org-fixup-indentation diff))))
4245
4246 (defun org-map-tree (fun)
4247 "Call FUN for every heading underneath the current one."
4248 (org-back-to-heading)
4249 (let ((level (funcall outline-level)))
4250 (save-excursion
4251 (funcall fun)
4252 (while (and (progn
4253 (outline-next-heading)
4254 (> (funcall outline-level) level))
4255 (not (eobp)))
4256 (funcall fun)))))
4257
4258 (defun org-map-region (fun beg end)
4259 "Call FUN for every heading between BEG and END."
4260 (let ((org-ignore-region t))
4261 (save-excursion
4262 (setq end (copy-marker end))
4263 (goto-char beg)
4264 (if (and (re-search-forward (concat "^" outline-regexp) nil t)
4265 (< (point) end))
4266 (funcall fun))
4267 (while (and (progn
4268 (outline-next-heading)
4269 (< (point) end))
4270 (not (eobp)))
4271 (funcall fun)))))
4272
4273 (defun org-fixup-indentation (diff)
4274 "Change the indentation in the current entry by DIFF
4275 However, if any line in the current entry has no indentation, or if it
4276 would end up with no indentation after the change, nothing at all is done."
4277 (save-excursion
4278 (let ((end (save-excursion (outline-next-heading)
4279 (point-marker)))
4280 (prohibit (if (> diff 0)
4281 "^\\S-"
4282 (concat "^ \\{0," (int-to-string (- diff)) "\\}\\S-")))
4283 col)
4284 (unless (save-excursion (re-search-forward prohibit end t))
4285 (while (re-search-forward "^[ \t]+" end t)
4286 (goto-char (match-end 0))
4287 (setq col (current-column))
4288 (if (< diff 0) (replace-match ""))
4289 (indent-to (+ diff col))))
4290 (move-marker end nil))))
4291
4292 ;;; Vertical tree motion, cutting and pasting of subtrees
4293
4294 (defun org-move-subtree-up (&optional arg)
4295 "Move the current subtree up past ARG headlines of the same level."
4296 (interactive "p")
4297 (org-move-subtree-down (- (prefix-numeric-value arg))))
4298
4299 (defun org-move-subtree-down (&optional arg)
4300 "Move the current subtree down past ARG headlines of the same level."
4301 (interactive "p")
4302 (setq arg (prefix-numeric-value arg))
4303 (let ((movfunc (if (> arg 0) 'outline-get-next-sibling
4304 'outline-get-last-sibling))
4305 (ins-point (make-marker))
4306 (cnt (abs arg))
4307 beg end txt folded)
4308 ;; Select the tree
4309 (org-back-to-heading)
4310 (setq beg (point))
4311 (save-match-data
4312 (save-excursion (outline-end-of-heading)
4313 (setq folded (org-invisible-p)))
4314 (outline-end-of-subtree))
4315 (outline-next-heading)
4316 (setq end (point))
4317 ;; Find insertion point, with error handling
4318 (goto-char beg)
4319 (while (> cnt 0)
4320 (or (and (funcall movfunc) (looking-at outline-regexp))
4321 (progn (goto-char beg)
4322 (error "Cannot move past superior level or buffer limit")))
4323 (setq cnt (1- cnt)))
4324 (if (> arg 0)
4325 ;; Moving forward - still need to move over subtree
4326 (progn (outline-end-of-subtree)
4327 (outline-next-heading)
4328 (if (not (or (looking-at (concat "^" outline-regexp))
4329 (bolp)))
4330 (newline))))
4331 (move-marker ins-point (point))
4332 (setq txt (buffer-substring beg end))
4333 (delete-region beg end)
4334 (insert txt)
4335 (goto-char ins-point)
4336 (if folded (hide-subtree))
4337 (move-marker ins-point nil)))
4338
4339 (defvar org-subtree-clip ""
4340 "Clipboard for cut and paste of subtrees.
4341 This is actually only a copy of the kill, because we use the normal kill
4342 ring. We need it to check if the kill was created by `org-copy-subtree'.")
4343
4344 (defvar org-subtree-clip-folded nil
4345 "Was the last copied subtree folded?
4346 This is used to fold the tree back after pasting.")
4347
4348 (defun org-cut-subtree ()
4349 "Cut the current subtree into the clipboard.
4350 This is a short-hand for marking the subtree and then cutting it."
4351 (interactive)
4352 (org-copy-subtree 'cut))
4353
4354 (defun org-copy-subtree (&optional cut)
4355 "Cut the current subtree into the clipboard.
4356 This is a short-hand for marking the subtree and then copying it.
4357 If CUT is non-nil, actually cut the subtree."
4358 (interactive)
4359 (let (beg end folded)
4360 (org-back-to-heading)
4361 (setq beg (point))
4362 (save-match-data
4363 (save-excursion (outline-end-of-heading)
4364 (setq folded (org-invisible-p)))
4365 (outline-end-of-subtree))
4366 (if (equal (char-after) ?\n) (forward-char 1))
4367 (setq end (point))
4368 (goto-char beg)
4369 (when (> end beg)
4370 (setq org-subtree-clip-folded folded)
4371 (if cut (kill-region beg end) (copy-region-as-kill beg end))
4372 (setq org-subtree-clip (current-kill 0))
4373 (message "%s: Subtree with %d characters"
4374 (if cut "Cut" "Copied")
4375 (length org-subtree-clip)))))
4376
4377 (defun org-paste-subtree (&optional level tree)
4378 "Paste the clipboard as a subtree, with modification of headline level.
4379 The entire subtree is promoted or demoted in order to match a new headline
4380 level. By default, the new level is derived from the visible headings
4381 before and after the insertion point, and taken to be the inferior headline
4382 level of the two. So if the previous visible heading is level 3 and the
4383 next is level 4 (or vice versa), level 4 will be used for insertion.
4384 This makes sure that the subtree remains an independent subtree and does
4385 not swallow low level entries.
4386
4387 You can also force a different level, either by using a numeric prefix
4388 argument, or by inserting the heading marker by hand. For example, if the
4389 cursor is after \"*****\", then the tree will be shifted to level 5.
4390
4391 If you want to insert the tree as is, just use \\[yank].
4392
4393 If optional TREE is given, use this text instead of the kill ring."
4394 (interactive "P")
4395 (unless (org-kill-is-subtree-p tree)
4396 (error
4397 (substitute-command-keys
4398 "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway")))
4399 (let* ((txt (or tree (and kill-ring (current-kill 0))))
4400 (^re (concat "^\\(" outline-regexp "\\)"))
4401 (re (concat "\\(" outline-regexp "\\)"))
4402 (^re_ (concat "\\(" outline-regexp "\\)[ \t]*"))
4403
4404 (old-level (if (string-match ^re txt)
4405 (- (match-end 0) (match-beginning 0))
4406 -1))
4407 (force-level (cond (level (prefix-numeric-value level))
4408 ((string-match
4409 ^re_ (buffer-substring (point-at-bol) (point)))
4410 (- (match-end 0) (match-beginning 0)))
4411 (t nil)))
4412 (previous-level (save-excursion
4413 (condition-case nil
4414 (progn
4415 (outline-previous-visible-heading 1)
4416 (if (looking-at re)
4417 (- (match-end 0) (match-beginning 0))
4418 1))
4419 (error 1))))
4420 (next-level (save-excursion
4421 (condition-case nil
4422 (progn
4423 (outline-next-visible-heading 1)
4424 (if (looking-at re)
4425 (- (match-end 0) (match-beginning 0))
4426 1))
4427 (error 1))))
4428 (new-level (or force-level (max previous-level next-level)))
4429 (shift (if (or (= old-level -1)
4430 (= new-level -1)
4431 (= old-level new-level))
4432 0
4433 (- new-level old-level)))
4434 (shift1 shift)
4435 (delta (if (> shift 0) -1 1))
4436 (func (if (> shift 0) 'org-demote 'org-promote))
4437 (org-odd-levels-only nil)
4438 beg end)
4439 ;; Remove the forces level indicator
4440 (if force-level
4441 (delete-region (point-at-bol) (point)))
4442 ;; Make sure we start at the beginning of an empty line
4443 (if (not (bolp)) (insert "\n"))
4444 (if (not (looking-at "[ \t]*$"))
4445 (progn (insert "\n") (backward-char 1)))
4446 ;; Paste
4447 (setq beg (point))
4448 (if (string-match "[ \t\r\n]+\\'" txt)
4449 (setq txt (replace-match "\n" t t txt)))
4450 (insert txt)
4451 (setq end (point))
4452 (if (looking-at "[ \t\r\n]+")
4453 (replace-match "\n"))
4454 (goto-char beg)
4455 ;; Shift if necessary
4456 (if (= shift 0)
4457 (message "Pasted at level %d, without shift" new-level)
4458 (save-restriction
4459 (narrow-to-region beg end)
4460 (while (not (= shift 0))
4461 (org-map-region func (point-min) (point-max))
4462 (setq shift (+ delta shift)))
4463 (goto-char (point-min))
4464 (message "Pasted at level %d, with shift by %d levels"
4465 new-level shift1)))
4466 (if (and kill-ring
4467 (eq org-subtree-clip (current-kill 0))
4468 org-subtree-clip-folded)
4469 ;; The tree was folded before it was killed/copied
4470 (hide-subtree))))
4471
4472 (defun org-kill-is-subtree-p (&optional txt)
4473 "Check if the current kill is an outline subtree, or a set of trees.
4474 Returns nil if kill does not start with a headline, or if the first
4475 headline level is not the largest headline level in the tree.
4476 So this will actually accept several entries of equal levels as well,
4477 which is OK for `org-paste-subtree'.
4478 If optional TXT is given, check this string instead of the current kill."
4479 (let* ((kill (or txt (and kill-ring (current-kill 0)) ""))
4480 (start-level (and kill
4481 (string-match (concat "\\`" outline-regexp) kill)
4482 (- (match-end 0) (match-beginning 0))))
4483 (re (concat "^" outline-regexp))
4484 (start 1))
4485 (if (not start-level)
4486 nil ;; does not even start with a heading
4487 (catch 'exit
4488 (while (setq start (string-match re kill (1+ start)))
4489 (if (< (- (match-end 0) (match-beginning 0)) start-level)
4490 (throw 'exit nil)))
4491 t))))
4492
4493 (defun org-narrow-to-subtree ()
4494 "Narrow buffer to the current subtree."
4495 (interactive)
4496 (save-excursion
4497 (narrow-to-region
4498 (progn (org-back-to-heading) (point))
4499 (progn (org-end-of-subtree t) (point)))))
4500
4501 ;;; Plain list items
4502
4503 (defun org-at-item-p ()
4504 "Is point in a line starting a hand-formatted item?"
4505 (let ((llt org-plain-list-ordered-item-terminator))
4506 (save-excursion
4507 (goto-char (point-at-bol))
4508 (looking-at
4509 (cond
4510 ((eq llt t) "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
4511 ((= llt ?.) "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
4512 ((= llt ?\)) "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
4513 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))))))
4514
4515 (defun org-at-item-checkbox-p ()
4516 "Is point at a line starting a plain-list item with a checklet?"
4517 (and (org-at-item-p)
4518 (save-excursion
4519 (goto-char (match-end 0))
4520 (skip-chars-forward " \t")
4521 (looking-at "\\[[ X]\\]"))))
4522
4523 (defun org-toggle-checkbox (&optional arg)
4524 "Toggle the checkbox in the current line."
4525 (interactive "P")
4526 (catch 'exit
4527 (let (beg end status (firstnew 'unknown))
4528 (cond
4529 ((org-region-active-p)
4530 (setq beg (region-beginning) end (region-end)))
4531 ((org-on-heading-p)
4532 (setq beg (point) end (save-excursion (outline-next-heading) (point))))
4533 ((org-at-item-checkbox-p)
4534 (save-excursion
4535 (replace-match (if (equal (match-string 0) "[ ]") "[X]" "[ ]") t t))
4536 (throw 'exit t))
4537 (t (error "Not at a checkbox or heading, and no active region")))
4538 (save-excursion
4539 (goto-char beg)
4540 (while (< (point) end)
4541 (when (org-at-item-checkbox-p)
4542 (setq status (equal (match-string 0) "[X]"))
4543 (when (eq firstnew 'unknown)
4544 (setq firstnew (not status)))
4545 (replace-match
4546 (if (if arg (not status) firstnew) "[X]" "[ ]") t t))
4547 (beginning-of-line 2)))))
4548 (org-update-checkbox-count-maybe))
4549
4550 (defun org-update-checkbox-count-maybe ()
4551 "Update checkbox statistics unless turned off by user."
4552 (when org-provide-checkbox-statistics
4553 (org-update-checkbox-count)))
4554
4555 (defun org-update-checkbox-count (&optional all)
4556 "Update the checkbox statistics in the current section.
4557 This will find all statistic cookies like [57%] and [6/12] and update them
4558 with the current numbers. With optional prefix argument ALL, do this for
4559 the whole buffer."
4560 (interactive "P")
4561 (save-excursion
4562 (let* ((buffer-invisibility-spec nil) ; Emacs 21 compatibility
4563 (beg (progn (outline-back-to-heading) (point)))
4564 (end (move-marker (make-marker)
4565 (progn (outline-next-heading) (point))))
4566 (re "\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)")
4567 (re-box "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)")
4568 b1 e1 f1 c-on c-off lim (cstat 0))
4569 (when all
4570 (goto-char (point-min))
4571 (outline-next-heading)
4572 (setq beg (point) end (point-max)))
4573 (goto-char beg)
4574 (while (re-search-forward re end t)
4575 (setq cstat (1+ cstat)
4576 b1 (match-beginning 0)
4577 e1 (match-end 0)
4578 f1 (match-beginning 1)
4579 lim (cond
4580 ((org-on-heading-p) (outline-next-heading) (point))
4581 ((org-at-item-p) (org-end-of-item) (point))
4582 (t nil))
4583 c-on 0 c-off 0)
4584 (goto-char e1)
4585 (when lim
4586 (while (re-search-forward re-box lim t)
4587 (if (equal (match-string 2) "[ ]")
4588 (setq c-off (1+ c-off))
4589 (setq c-on (1+ c-on))))
4590 (delete-region b1 e1)
4591 (goto-char b1)
4592 (insert (if f1
4593 (format "[%d%%]" (/ (* 100 c-on) (max 1 (+ c-on c-off))))
4594 (format "[%d/%d]" c-on (+ c-on c-off))))))
4595 (when (interactive-p)
4596 (message "Checkbox satistics updated %s (%d places)"
4597 (if all "in entire file" "in current outline entry") cstat)))))
4598
4599 (defun org-get-checkbox-statistics-face ()
4600 "Select the face for checkbox statistics.
4601 The face will be `org-done' when all relevant boxes are checked. Otherwise
4602 it will be `org-todo'."
4603 (if (match-end 1)
4604 (if (equal (match-string 1) "100%") 'org-done 'org-todo)
4605 (if (and (> (match-end 2) (match-beginning 2))
4606 (equal (match-string 2) (match-string 3)))
4607 'org-done
4608 'org-todo)))
4609
4610 (defun org-get-indentation (&optional line)
4611 "Get the indentation of the current line, interpreting tabs.
4612 When LINE is given, assume it represents a line and compute its indentation."
4613 (if line
4614 (if (string-match "^ *" (org-remove-tabs line))
4615 (match-end 0))
4616 (save-excursion
4617 (beginning-of-line 1)
4618 (skip-chars-forward " \t")
4619 (current-column))))
4620
4621 (defun org-remove-tabs (s &optional width)
4622 "Replace tabulators in S with spaces.
4623 Assumes that s is a single line, starting in column 0."
4624 (setq width (or width tab-width))
4625 (while (string-match "\t" s)
4626 (setq s (replace-match
4627 (make-string
4628 (- (* width (/ (+ (match-beginning 0) width) width))
4629 (match-beginning 0)) ?\ )
4630 t t s)))
4631 s)
4632
4633 ;; FIXME: document properly.
4634 (defun org-fix-indentation (line ind)
4635 "If the current indenation is smaller than ind1, leave it alone.
4636 If it is larger than ind, reduce it by ind."
4637 (let* ((l (org-remove-tabs line))
4638 (i (org-get-indentation l))
4639 (i1 (car ind)) (i2 (cdr ind)))
4640 (if (>= i i2) (setq l (substring line i2)))
4641 (if (> i1 0)
4642 (concat (make-string i1 ?\ ) l)
4643 l)))
4644
4645 (defun org-beginning-of-item ()
4646 "Go to the beginning of the current hand-formatted item.
4647 If the cursor is not in an item, throw an error."
4648 (interactive)
4649 (let ((pos (point))
4650 (limit (save-excursion (org-back-to-heading)
4651 (beginning-of-line 2) (point)))
4652 ind ind1)
4653 (if (org-at-item-p)
4654 (beginning-of-line 1)
4655 (beginning-of-line 1)
4656 (skip-chars-forward " \t")
4657 (setq ind (current-column))
4658 (if (catch 'exit
4659 (while t
4660 (beginning-of-line 0)
4661 (if (< (point) limit) (throw 'exit nil))
4662 (unless (looking-at "[ \t]*$")
4663 (skip-chars-forward " \t")
4664 (setq ind1 (current-column))
4665 (if (< ind1 ind)
4666 (throw 'exit (org-at-item-p))))))
4667 nil
4668 (goto-char pos)
4669 (error "Not in an item")))))
4670
4671 (defun org-end-of-item ()
4672 "Go to the end of the current hand-formatted item.
4673 If the cursor is not in an item, throw an error."
4674 (interactive)
4675 (let ((pos (point))
4676 (limit (save-excursion (outline-next-heading) (point)))
4677 (ind (save-excursion
4678 (org-beginning-of-item)
4679 (skip-chars-forward " \t")
4680 (current-column)))
4681 ind1)
4682 (if (catch 'exit
4683 (while t
4684 (beginning-of-line 2)
4685 (if (>= (point) limit) (throw 'exit t))
4686 (unless (looking-at "[ \t]*$")
4687 (skip-chars-forward " \t")
4688 (setq ind1 (current-column))
4689 (if (<= ind1 ind) (throw 'exit t)))))
4690 (beginning-of-line 1)
4691 (goto-char pos)
4692 (error "Not in an item"))))
4693
4694 (defun org-next-item ()
4695 "Move to the beginning of the next item in the current plain list.
4696 Error if not at a plain list, or if this is the last item in the list."
4697 (interactive)
4698 (let (ind ind1 (pos (point)))
4699 (org-beginning-of-item)
4700 (setq ind (org-get-indentation))
4701 (org-end-of-item)
4702 (setq ind1 (org-get-indentation))
4703 (unless (and (org-at-item-p) (= ind ind1))
4704 (goto-char pos)
4705 (error "On last item"))))
4706
4707 (defun org-previous-item ()
4708 "Move to the beginning of the previous item in the current plain list.
4709 Error if not at a plain list, or if this is the last item in the list."
4710 (interactive)
4711 (let (beg ind (pos (point)))
4712 (org-beginning-of-item)
4713 (setq beg (point))
4714 (setq ind (org-get-indentation))
4715 (goto-char beg)
4716 (catch 'exit
4717 (while t
4718 (beginning-of-line 0)
4719 (if (looking-at "[ \t]*$")
4720 nil
4721 (if (<= (org-get-indentation) ind)
4722 (throw 'exit t)))))
4723 (condition-case nil
4724 (org-beginning-of-item)
4725 (error (goto-char pos)
4726 (error "On first item")))))
4727
4728 (defun org-move-item-down ()
4729 "Move the plain list item at point down, i.e. swap with following item.
4730 Subitems (items with larger indentation) are considered part of the item,
4731 so this really moves item trees."
4732 (interactive)
4733 (let (beg end ind ind1 (pos (point)) txt)
4734 (org-beginning-of-item)
4735 (setq beg (point))
4736 (setq ind (org-get-indentation))
4737 (org-end-of-item)
4738 (setq end (point))
4739 (setq ind1 (org-get-indentation))
4740 (if (and (org-at-item-p) (= ind ind1))
4741 (progn
4742 (org-end-of-item)
4743 (setq txt (buffer-substring beg end))
4744 (save-excursion
4745 (delete-region beg end))
4746 (setq pos (point))
4747 (insert txt)
4748 (goto-char pos)
4749 (org-maybe-renumber-ordered-list))
4750 (goto-char pos)
4751 (error "Cannot move this item further down"))))
4752
4753 (defun org-move-item-up (arg)
4754 "Move the plain list item at point up, i.e. swap with previous item.
4755 Subitems (items with larger indentation) are considered part of the item,
4756 so this really moves item trees."
4757 (interactive "p")
4758 (let (beg end ind ind1 (pos (point)) txt)
4759 (org-beginning-of-item)
4760 (setq beg (point))
4761 (setq ind (org-get-indentation))
4762 (org-end-of-item)
4763 (setq end (point))
4764 (goto-char beg)
4765 (catch 'exit
4766 (while t
4767 (beginning-of-line 0)
4768 (if (looking-at "[ \t]*$")
4769 nil
4770 (if (<= (setq ind1 (org-get-indentation)) ind)
4771 (throw 'exit t)))))
4772 (condition-case nil
4773 (org-beginning-of-item)
4774 (error (goto-char beg)
4775 (error "Cannot move this item further up")))
4776 (setq ind1 (org-get-indentation))
4777 (if (and (org-at-item-p) (= ind ind1))
4778 (progn
4779 (setq txt (buffer-substring beg end))
4780 (save-excursion
4781 (delete-region beg end))
4782 (setq pos (point))
4783 (insert txt)
4784 (goto-char pos)
4785 (org-maybe-renumber-ordered-list))
4786 (goto-char pos)
4787 (error "Cannot move this item further up"))))
4788
4789 (defun org-maybe-renumber-ordered-list ()
4790 "Renumber the ordered list at point if setup allows it.
4791 This tests the user option `org-auto-renumber-ordered-lists' before
4792 doing the renumbering."
4793 (and org-auto-renumber-ordered-lists
4794 (org-at-item-p)
4795 (match-beginning 3)
4796 (org-renumber-ordered-list 1)))
4797
4798 (defun org-get-string-indentation (s)
4799 "What indentation has S due to SPACE and TAB at the beginning of the string?"
4800 (let ((n -1) (i 0) (w tab-width) c)
4801 (catch 'exit
4802 (while (< (setq n (1+ n)) (length s))
4803 (setq c (aref s n))
4804 (cond ((= c ?\ ) (setq i (1+ i)))
4805 ((= c ?\t) (setq i (* (/ (+ w i) w) w)))
4806 (t (throw 'exit t)))))
4807 i))
4808
4809 (defun org-renumber-ordered-list (arg)
4810 "Renumber an ordered plain list.
4811 Cursor needs to be in the first line of an item, the line that starts
4812 with something like \"1.\" or \"2)\"."
4813 (interactive "p")
4814 (unless (and (org-at-item-p)
4815 (match-beginning 3))
4816 (error "This is not an ordered list"))
4817 (let ((line (org-current-line))
4818 (col (current-column))
4819 (ind (org-get-string-indentation
4820 (buffer-substring (point-at-bol) (match-beginning 3))))
4821 ;; (term (substring (match-string 3) -1))
4822 ind1 (n (1- arg)))
4823 ;; find where this list begins
4824 (catch 'exit
4825 (while t
4826 (catch 'next
4827 (beginning-of-line 0)
4828 (if (looking-at "[ \t]*$") (throw 'next t))
4829 (skip-chars-forward " \t") (setq ind1 (current-column))
4830 (if (or (< ind1 ind)
4831 (and (= ind1 ind)
4832 (not (org-at-item-p))))
4833 (throw 'exit t)))))
4834 ;; Walk forward and replace these numbers
4835 (catch 'exit
4836 (while t
4837 (catch 'next
4838 (beginning-of-line 2)
4839 (if (eobp) (throw 'exit nil))
4840 (if (looking-at "[ \t]*$") (throw 'next nil))
4841 (skip-chars-forward " \t") (setq ind1 (current-column))
4842 (if (> ind1 ind) (throw 'next t))
4843 (if (< ind1 ind) (throw 'exit t))
4844 (if (not (org-at-item-p)) (throw 'exit nil))
4845 (if (not (match-beginning 3))
4846 (error "unordered bullet in ordered list. Press \\[undo] to recover"))
4847 (delete-region (match-beginning 3) (1- (match-end 3)))
4848 (goto-char (match-beginning 3))
4849 (insert (format "%d" (setq n (1+ n)))))))
4850 (goto-line line)
4851 (move-to-column col)))
4852
4853 (defvar org-last-indent-begin-marker (make-marker))
4854 (defvar org-last-indent-end-marker (make-marker))
4855
4856 (defun org-outdent-item (arg)
4857 "Outdent a local list item."
4858 (interactive "p")
4859 (org-indent-item (- arg)))
4860
4861 (defun org-indent-item (arg)
4862 "Indent a local list item."
4863 (interactive "p")
4864 (unless (org-at-item-p)
4865 (error "Not on an item"))
4866 (save-excursion
4867 (let (beg end ind ind1)
4868 (if (memq last-command '(org-shiftmetaright org-shiftmetaleft))
4869 (setq beg org-last-indent-begin-marker
4870 end org-last-indent-end-marker)
4871 (org-beginning-of-item)
4872 (setq beg (move-marker org-last-indent-begin-marker (point)))
4873 (org-end-of-item)
4874 (setq end (move-marker org-last-indent-end-marker (point))))
4875 (goto-char beg)
4876 (skip-chars-forward " \t") (setq ind (current-column))
4877 (if (< (+ arg ind) 0) (error "Cannot outdent beyond margin"))
4878 (while (< (point) end)
4879 (beginning-of-line 1)
4880 (skip-chars-forward " \t") (setq ind1 (current-column))
4881 (delete-region (point-at-bol) (point))
4882 (indent-to-column (+ ind1 arg))
4883 (beginning-of-line 2)))))
4884
4885 ;;; Archiving
4886
4887 (defun org-archive-subtree (&optional find-done)
4888 "Move the current subtree to the archive.
4889 The archive can be a certain top-level heading in the current file, or in
4890 a different file. The tree will be moved to that location, the subtree
4891 heading be marked DONE, and the current time will be added.
4892
4893 When called with prefix argument FIND-DONE, find whole trees without any
4894 open TODO items and archive them (after getting confirmation from the user).
4895 If the cursor is not at a headline when this comand is called, try all level
4896 1 trees. If the cursor is on a headline, only try the direct children of
4897 this heading. "
4898 (interactive "P")
4899 (if find-done
4900 (org-archive-all-done)
4901 ;; Save all relevant TODO keyword-relatex variables
4902
4903 (let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler
4904 (tr-org-todo-keywords org-todo-keywords)
4905 (tr-org-todo-interpretation org-todo-interpretation)
4906 (tr-org-done-string org-done-string)
4907 (tr-org-todo-regexp org-todo-regexp)
4908 (tr-org-todo-line-regexp org-todo-line-regexp)
4909 (this-buffer (current-buffer))
4910 file heading buffer level newfile-p)
4911 (if (string-match "\\(.*\\)::\\(.*\\)" org-archive-location)
4912 (progn
4913 (setq file (format (match-string 1 org-archive-location)
4914 (file-name-nondirectory buffer-file-name))
4915 heading (match-string 2 org-archive-location)))
4916 (error "Invalid `org-archive-location'"))
4917 (if (> (length file) 0)
4918 (setq newfile-p (not (file-exists-p file))
4919 buffer (find-file-noselect file))
4920 (setq buffer (current-buffer)))
4921 (unless buffer
4922 (error "Cannot access file \"%s\"" file))
4923 (if (and (> (length heading) 0)
4924 (string-match "^\\*+" heading))
4925 (setq level (match-end 0))
4926 (setq heading nil level 0))
4927 (save-excursion
4928 ;; We first only copy, in case something goes wrong
4929 ;; we need to protect this-command, to avoid kill-region sets it,
4930 ;; which would lead to duplication of subtrees
4931 (let (this-command) (org-copy-subtree))
4932 (set-buffer buffer)
4933 ;; Enforce org-mode for the archive buffer
4934 (if (not (org-mode-p))
4935 ;; Force the mode for future visits.
4936 (let ((org-insert-mode-line-in-empty-file t))
4937 (call-interactively 'org-mode)))
4938 (when newfile-p
4939 (goto-char (point-max))
4940 (insert (format "\nArchived entries from file %s\n\n"
4941 (buffer-file-name this-buffer))))
4942 ;; Force the TODO keywords of the original buffer
4943 (let ((org-todo-line-regexp tr-org-todo-line-regexp)
4944 (org-todo-keywords tr-org-todo-keywords)
4945 (org-todo-interpretation tr-org-todo-interpretation)
4946 (org-done-string tr-org-done-string)
4947 (org-todo-regexp tr-org-todo-regexp)
4948 (org-todo-line-regexp tr-org-todo-line-regexp))
4949 (goto-char (point-min))
4950 (if heading
4951 (progn
4952 (if (re-search-forward
4953 (concat "\\(^\\|\r\\)"
4954 (regexp-quote heading) "[ \t]*\\($\\|\r\\)")
4955 nil t)
4956 (goto-char (match-end 0))
4957 ;; Heading not found, just insert it at the end
4958 (goto-char (point-max))
4959 (or (bolp) (insert "\n"))
4960 (insert "\n" heading "\n")
4961 (end-of-line 0))
4962 ;; Make the subtree visible
4963 (show-subtree)
4964 (org-end-of-subtree t)
4965 (skip-chars-backward " \t\r\n")
4966 (and (looking-at "[ \t\r\n]*")
4967 (replace-match "\n\n")))
4968 ;; No specific heading, just go to end of file.
4969 (goto-char (point-max)) (insert "\n"))
4970 ;; Paste
4971 (org-paste-subtree (1+ level))
4972 ;; Mark the entry as done, i.e. set to last work in org-todo-keywords
4973 (if org-archive-mark-done
4974 (org-todo (length org-todo-keywords)))
4975 ;; Move cursor to right after the TODO keyword
4976 (when org-archive-stamp-time
4977 (beginning-of-line 1)
4978 (looking-at org-todo-line-regexp)
4979 (goto-char (or (match-end 2) (match-beginning 3)))
4980 (org-insert-time-stamp (org-current-time) t t "(" ")"))
4981 ;; Save the buffer, if it is not the same buffer.
4982 (if (not (eq this-buffer buffer)) (save-buffer))))
4983 ;; Here we are back in the original buffer. Everything seems to have
4984 ;; worked. So now cut the tree and finish up.
4985 (let (this-command) (org-cut-subtree))
4986 (if (and (not (eobp)) (looking-at "[ \t]*$")) (kill-line))
4987 (message "Subtree archived %s"
4988 (if (eq this-buffer buffer)
4989 (concat "under heading: " heading)
4990 (concat "in file: " (abbreviate-file-name file)))))))
4991
4992 (defun org-archive-all-done (&optional tag)
4993 "Archive sublevels of the current tree without open TODO items.
4994 If the cursor is not on a headline, try all level 1 trees. If
4995 it is on a headline, try all direct children.
4996 When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag."
4997 (let ((re (concat "^\\*+ +" org-not-done-regexp)) re1
4998 (rea (concat ".*:" org-archive-tag ":"))
4999 (begm (make-marker))
5000 (endm (make-marker))
5001 (question (if tag "Set ARCHIVE tag (no open TODO items)? "
5002 "Move subtree to archive (no open TODO items)? "))
5003 beg end (cntarch 0))
5004 (if (org-on-heading-p)
5005 (progn
5006 (setq re1 (concat "^" (regexp-quote
5007 (make-string
5008 (1+ (- (match-end 0) (match-beginning 0)))
5009 ?*))
5010 " "))
5011 (move-marker begm (point))
5012 (move-marker endm (org-end-of-subtree t)))
5013 (setq re1 "^* ")
5014 (move-marker begm (point-min))
5015 (move-marker endm (point-max)))
5016 (save-excursion
5017 (goto-char begm)
5018 (while (re-search-forward re1 endm t)
5019 (setq beg (match-beginning 0)
5020 end (save-excursion (org-end-of-subtree t) (point)))
5021 (goto-char beg)
5022 (if (re-search-forward re end t)
5023 (goto-char end)
5024 (goto-char beg)
5025 (if (and (or (not tag) (not (looking-at rea)))
5026 (y-or-n-p question))
5027 (progn
5028 (if tag
5029 (org-toggle-tag org-archive-tag 'on)
5030 (org-archive-subtree))
5031 (setq cntarch (1+ cntarch)))
5032 (goto-char end)))))
5033 (message "%d trees archived" cntarch)))
5034
5035 (defun org-cycle-hide-archived-subtrees (state)
5036 "Re-hide all archived subtrees after a visibility state change."
5037 (when (and (not org-cycle-open-archived-trees)
5038 (not (memq state '(overview folded))))
5039 (save-excursion
5040 (let* ((globalp (memq state '(contents all)))
5041 (beg (if globalp (point-min) (point)))
5042 (end (if globalp (point-max) (org-end-of-subtree t))))
5043 (org-hide-archived-subtrees beg end)
5044 (goto-char beg)
5045 (if (looking-at (concat ".*:" org-archive-tag ":"))
5046 (message (substitute-command-keys
5047 "Subtree is archived and stays closed. Use \\[org-force-cycle-archived] to cycle it anyway.")))))))
5048
5049 (defun org-force-cycle-archived ()
5050 "Cycle subtree even if it is archived."
5051 (interactive)
5052 (setq this-command 'org-cycle)
5053 (let ((org-cycle-open-archived-trees t))
5054 (call-interactively 'org-cycle)))
5055
5056 (defun org-hide-archived-subtrees (beg end)
5057 "Re-hide all archived subtrees after a visibility state change."
5058 (save-excursion
5059 (let* ((re (concat ":" org-archive-tag ":")))
5060 (goto-char beg)
5061 (while (re-search-forward re end t)
5062 (and (org-on-heading-p) (hide-subtree))
5063 (org-end-of-subtree t)))))
5064
5065 (defun org-toggle-tag (tag &optional onoff)
5066 "Toggle the tag TAG for the current line.
5067 If ONOFF is `on' or `off', don't toggle but set to this state."
5068 (unless (org-on-heading-p) (error "Not on headling"))
5069 (let (res current)
5070 (save-excursion
5071 (beginning-of-line)
5072 (if (re-search-forward "[ \t]:\\([a-zA-Z0-9_@:]+\\):[ \t]*$"
5073 (point-at-eol) t)
5074 (progn
5075 (setq current (match-string 1))
5076 (replace-match ""))
5077 (setq current ""))
5078 (setq current (nreverse (org-split-string current ":")))
5079 (cond
5080 ((eq onoff 'on)
5081 (setq res t)
5082 (or (member tag current) (push tag current)))
5083 ((eq onoff 'off)
5084 (or (not (member tag current)) (setq current (delete tag current))))
5085 (t (if (member tag current)
5086 (setq current (delete tag current))
5087 (setq res t)
5088 (push tag current))))
5089 (end-of-line 1)
5090 (when current
5091 (insert " :" (mapconcat 'identity (nreverse current) ":") ":"))
5092 (org-set-tags nil t))
5093 res))
5094
5095 (defun org-toggle-archive-tag (&optional arg)
5096 "Toggle the archive tag for the current headline.
5097 With prefix ARG, check all children of current headline and offer tagging
5098 the children that do not contain any open TODO items."
5099 (interactive "P")
5100 (if arg
5101 (org-archive-all-done 'tag)
5102 (let (set)
5103 (save-excursion
5104 (org-back-to-heading t)
5105 (setq set (org-toggle-tag org-archive-tag))
5106 (when set (hide-subtree)))
5107 (and set (beginning-of-line 1))
5108 (message "Subtree %s" (if set "archived" "unarchived")))))
5109
5110 (defvar org-agenda-multi nil) ; dynammically scoped
5111 (defvar org-agenda-buffer-name "*Org Agenda*")
5112 (defvar org-pre-agenda-window-conf nil)
5113 (defun org-prepare-agenda ()
5114 (if org-agenda-multi
5115 (progn
5116 (setq buffer-read-only nil)
5117 (goto-char (point-max))
5118 (unless (= (point) 1)
5119 (insert "\n" (make-string (window-width) ?=) "\n"))
5120 (narrow-to-region (point) (point-max)))
5121 (org-agenda-maybe-reset-markers 'force)
5122 (org-prepare-agenda-buffers (org-agenda-files))
5123 (let* ((abuf (get-buffer-create org-agenda-buffer-name))
5124 (awin (get-buffer-window abuf)))
5125 (cond
5126 ((equal (current-buffer) abuf) nil)
5127 (awin (select-window awin))
5128 ((not (setq org-pre-agenda-window-conf (current-window-configuration))))
5129 ((equal org-agenda-window-setup 'current-window)
5130 (switch-to-buffer abuf))
5131 ((equal org-agenda-window-setup 'other-window)
5132 (switch-to-buffer-other-window abuf))
5133 ((equal org-agenda-window-setup 'other-frame)
5134 (switch-to-buffer-other-frame abuf))
5135 ((equal org-agenda-window-setup 'reorganize-frame)
5136 (delete-other-windows)
5137 (switch-to-buffer-other-window abuf))))
5138 (setq buffer-read-only nil)
5139 (erase-buffer)
5140 (org-agenda-mode))
5141 (setq buffer-read-only nil))
5142
5143 (defun org-finalize-agenda ()
5144 "Finishing touch for the agenda buffer, called just before displaying it."
5145 (unless org-agenda-multi
5146 (org-agenda-align-tags)
5147 (save-excursion
5148 (let ((buffer-read-only))
5149 (goto-char (point-min))
5150 (while (org-activate-bracket-links (point-max))
5151 (add-text-properties (match-beginning 0) (match-end 0)
5152 '(face org-link))))
5153 (run-hooks 'org-finalize-agenda-hook))))
5154
5155 (defun org-prepare-agenda-buffers (files)
5156 "Create buffers for all agenda files, protect archived trees and comments."
5157 (interactive)
5158 (let ((pa '(:org-archived t))
5159 (pc '(:org-comment t))
5160 (pall '(:org-archived t :org-comment t))
5161 (rea (concat ":" org-archive-tag ":"))
5162 bmp file re)
5163 (save-excursion
5164 (while (setq file (pop files))
5165 (org-check-agenda-file file)
5166 (set-buffer (org-get-agenda-file-buffer file))
5167 (widen)
5168 (setq bmp (buffer-modified-p))
5169 (save-excursion
5170 (remove-text-properties (point-min) (point-max) pall)
5171 (when org-agenda-skip-archived-trees
5172 (goto-char (point-min))
5173 (while (re-search-forward rea nil t)
5174 (if (org-on-heading-p)
5175 (add-text-properties (point-at-bol) (org-end-of-subtree t) pa))))
5176 (goto-char (point-min))
5177 (setq re (concat "^\\*+ +" org-comment-string "\\>"))
5178 (while (re-search-forward re nil t)
5179 (add-text-properties
5180 (match-beginning 0) (org-end-of-subtree t) pc)))
5181 (set-buffer-modified-p bmp)))))
5182
5183 (defun org-agenda-skip ()
5184 "Throw to `:skip' in places that should be skipped."
5185 (let ((p (point-at-bol)))
5186 (and org-agenda-skip-archived-trees
5187 (get-text-property p :org-archived)
5188 (org-end-of-subtree t)
5189 (throw :skip t))
5190 (and (get-text-property p :org-comment)
5191 (org-end-of-subtree t)
5192 (throw :skip t))
5193 (if (equal (char-after p) ?#) (throw :skip t))))
5194
5195 (defun org-agenda-toggle-archive-tag ()
5196 "Toggle the archive tag for the current entry."
5197 (interactive)
5198 (org-agenda-check-no-diary)
5199 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
5200 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
5201 (org-agenda-error)))
5202 (buffer (marker-buffer hdmarker))
5203 (pos (marker-position hdmarker))
5204 (buffer-read-only nil)
5205 newhead)
5206 (with-current-buffer buffer
5207 (widen)
5208 (goto-char pos)
5209 (org-show-context 'agenda)
5210 (save-excursion
5211 (and (outline-next-heading)
5212 (org-flag-heading nil))) ; show the next heading
5213 (call-interactively 'org-toggle-archive-tag)
5214 (end-of-line 1)
5215 (setq newhead (org-get-heading)))
5216 (org-agenda-change-all-lines newhead hdmarker)
5217 (beginning-of-line 1)))
5218
5219 ;;; Dynamic blocks
5220
5221 (defun org-find-dblock (name)
5222 "Find the first dynamic block with name NAME in the buffer.
5223 If not found, stay at current position and return nil."
5224 (let (pos)
5225 (save-excursion
5226 (goto-char (point-min))
5227 (setq pos (and (re-search-forward (concat "^#\\+BEGIN:[ \t]+" name "\\>")
5228 nil t)
5229 (match-beginning 0))))
5230 (if pos (goto-char pos))
5231 pos))
5232
5233 (defconst org-dblock-start-re
5234 "^#\\+BEGIN:[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?"
5235 "Matches the startline of a dynamic block, with parameters.")
5236
5237 (defconst org-dblock-end-re "^#\\+END\\([: \t\r\n]\\|$\\)"
5238 "Matches the end of a dyhamic block.")
5239
5240 (defun org-create-dblock (plist)
5241 "Create a dynamic block section, with parameters taken from PLIST.
5242 PLIST must containe a :name entry which is used as name of the block."
5243 (unless (bolp) (newline))
5244 (let ((name (plist-get plist :name)))
5245 (insert "#+BEGIN: " name)
5246 (while plist
5247 (if (eq (car plist) :name)
5248 (setq plist (cddr plist))
5249 (insert " " (prin1-to-string (pop plist)))))
5250 (insert "\n\n#+END:\n")
5251 (beginning-of-line -2)))
5252
5253 (defun org-prepare-dblock ()
5254 "Prepare dynamic block for refresh.
5255 This empties the block, puts the cursor at the insert position and returns
5256 the property list including an extra property :name with the block name."
5257 (unless (looking-at org-dblock-start-re)
5258 (error "Not at a dynamic block"))
5259 (let* ((begdel (1+ (match-end 0)))
5260 (name (match-string 1))
5261 (params (append (list :name name)
5262 (read (concat "(" (match-string 3) ")")))))
5263 (unless (re-search-forward org-dblock-end-re nil t)
5264 (error "Dynamic block not terminated"))
5265 (delete-region begdel (match-beginning 0))
5266 (goto-char begdel)
5267 (open-line 1)
5268 params))
5269
5270 (defun org-map-dblocks (&optional command)
5271 "Apply COMMAND to all dynamic blocks in the current buffer.
5272 If COMMAND is not given, use `org-update-dblock'."
5273 (let ((cmd (or command 'org-update-dblock))
5274 pos)
5275 (save-excursion
5276 (goto-char (point-min))
5277 (while (re-search-forward org-dblock-start-re nil t)
5278 (goto-char (setq pos (match-beginning 0)))
5279 (condition-case nil
5280 (funcall cmd)
5281 (error (message "Error during update of dynamic block")))
5282 (goto-char pos)
5283 (unless (re-search-forward org-dblock-end-re nil t)
5284 (error "Dynamic block not terminated"))))))
5285
5286 (defun org-dblock-update (&optional arg)
5287 "User command for updating dynamic blocks.
5288 Update the dynamic block at point. With prefix ARG, update all dynamic
5289 blocks in the buffer."
5290 (interactive "P")
5291 (if arg
5292 (org-update-all-dblocks)
5293 (or (looking-at org-dblock-start-re)
5294 (org-beginning-of-dblock))
5295 (org-update-dblock)))
5296
5297 (defun org-update-dblock ()
5298 "Update the dynamic block at point
5299 This means to empty the block, parse for parameters and then call
5300 the correct writing function."
5301 (let* ((pos (point))
5302 (params (org-prepare-dblock))
5303 (name (plist-get params :name))
5304 (cmd (intern (concat "org-dblock-write:" name))))
5305 (funcall cmd params)
5306 (goto-char pos)))
5307
5308 (defun org-beginning-of-dblock ()
5309 "Find the beginning of the dynamic block at point.
5310 Error if there is no scuh block at point."
5311 (let ((pos (point))
5312 beg)
5313 (end-of-line 1)
5314 (if (and (re-search-backward org-dblock-start-re nil t)
5315 (setq beg (match-beginning 0))
5316 (re-search-forward org-dblock-end-re nil t)
5317 (> (match-end 0) pos))
5318 (goto-char beg)
5319 (goto-char pos)
5320 (error "Not in a dynamic block"))))
5321
5322 (defun org-update-all-dblocks ()
5323 "Update all dynamic blocks in the buffer.
5324 This function can be used in a hook."
5325 (when (org-mode-p)
5326 (org-map-dblocks 'org-update-dblock)))
5327
5328
5329 ;;; Completion
5330
5331 (defun org-complete (&optional arg)
5332 "Perform completion on word at point.
5333 At the beginning of a headline, this completes TODO keywords as given in
5334 `org-todo-keywords'.
5335 If the current word is preceded by a backslash, completes the TeX symbols
5336 that are supported for HTML support.
5337 If the current word is preceded by \"#+\", completes special words for
5338 setting file options.
5339 In the line after \"#+STARTUP:, complete valid keywords.\"
5340 At all other locations, this simply calls `ispell-complete-word'."
5341 (interactive "P")
5342 (catch 'exit
5343 (let* ((end (point))
5344 (beg1 (save-excursion
5345 (skip-chars-backward "a-zA-Z_@0-9")
5346 (point)))
5347 (beg (save-excursion
5348 (skip-chars-backward "a-zA-Z0-9_:$")
5349 (point)))
5350 (confirm (lambda (x) (stringp (car x))))
5351 (camel (equal (char-before beg) ?*))
5352 (tag (equal (char-before beg1) ?:))
5353 (texp (equal (char-before beg) ?\\))
5354 (link (equal (char-before beg) ?\[))
5355 (opt (equal (buffer-substring (max (point-at-bol) (- beg 2))
5356 beg)
5357 "#+"))
5358 (startup (string-match "^#\\+STARTUP:.*"
5359 (buffer-substring (point-at-bol) (point))))
5360 (completion-ignore-case opt)
5361 (type nil)
5362 (tbl nil)
5363 (table (cond
5364 (opt
5365 (setq type :opt)
5366 (mapcar (lambda (x)
5367 (string-match "^#\\+\\(\\([A-Z_]+:?\\).*\\)" x)
5368 (cons (match-string 2 x) (match-string 1 x)))
5369 (org-split-string (org-get-current-options) "\n")))
5370 (startup
5371 (setq type :startup)
5372 org-startup-options)
5373 (link (append org-link-abbrev-alist-local
5374 org-link-abbrev-alist))
5375 (texp
5376 (setq type :tex)
5377 org-html-entities)
5378 ((string-match "\\`\\*+[ \t]*\\'"
5379 (buffer-substring (point-at-bol) beg))
5380 (setq type :todo)
5381 (mapcar 'list org-todo-keywords))
5382 (camel
5383 (setq type :camel)
5384 (save-excursion
5385 (goto-char (point-min))
5386 (while (re-search-forward org-todo-line-regexp nil t)
5387 (push (list
5388 (if org-file-link-context-use-camel-case
5389 (org-make-org-heading-camel (match-string 3) t)
5390 (org-make-org-heading-search-string
5391 (match-string 3) t)))
5392 tbl)))
5393 tbl)
5394 (tag (setq type :tag beg beg1)
5395 (or org-tag-alist (org-get-buffer-tags)))
5396 (t (progn (ispell-complete-word arg) (throw 'exit nil)))))
5397 (pattern (buffer-substring-no-properties beg end))
5398 (completion (try-completion pattern table confirm)))
5399 (cond ((eq completion t)
5400 (if (equal type :opt)
5401 (insert (substring (cdr (assoc (upcase pattern) table))
5402 (length pattern)))))
5403 ((null completion)
5404 (message "Can't find completion for \"%s\"" pattern)
5405 (ding))
5406 ((not (string= pattern completion))
5407 (delete-region beg end)
5408 (if (string-match " +$" completion)
5409 (setq completion (replace-match "" t t completion)))
5410 (insert completion)
5411 (if (get-buffer-window "*Completions*")
5412 (delete-window (get-buffer-window "*Completions*")))
5413 (if (assoc completion table)
5414 (if (eq type :todo) (insert " ")
5415 (if (eq type :tag) (insert ":"))))
5416 (if (and (equal type :opt) (assoc completion table))
5417 (message "%s" (substitute-command-keys
5418 "Press \\[org-complete] again to insert example settings"))))
5419 (t
5420 (message "Making completion list...")
5421 (let ((list (sort (all-completions pattern table confirm)
5422 'string<)))
5423 (with-output-to-temp-buffer "*Completions*"
5424 (condition-case nil
5425 ;; Protection needed for XEmacs and emacs 21
5426 (display-completion-list list pattern)
5427 (error (display-completion-list list)))))
5428 (message "Making completion list...%s" "done"))))))
5429
5430 ;;; Comments, TODO and DEADLINE
5431
5432 (defun org-toggle-comment ()
5433 "Change the COMMENT state of an entry."
5434 (interactive)
5435 (save-excursion
5436 (org-back-to-heading)
5437 (if (looking-at (concat outline-regexp
5438 "\\( +\\<" org-comment-string "\\>\\)"))
5439 (replace-match "" t t nil 1)
5440 (if (looking-at outline-regexp)
5441 (progn
5442 (goto-char (match-end 0))
5443 (insert " " org-comment-string))))))
5444
5445 (defvar org-last-todo-state-is-todo nil
5446 "This is non-nil when the last TODO state change led to a TODO state.
5447 If the last change removed the TODO tag or switched to DONE, then
5448 this is nil.")
5449
5450 (defun org-todo (&optional arg)
5451 "Change the TODO state of an item.
5452 The state of an item is given by a keyword at the start of the heading,
5453 like
5454 *** TODO Write paper
5455 *** DONE Call mom
5456
5457 The different keywords are specified in the variable `org-todo-keywords'.
5458 By default the available states are \"TODO\" and \"DONE\".
5459 So for this example: when the item starts with TODO, it is changed to DONE.
5460 When it starts with DONE, the DONE is removed. And when neither TODO nor
5461 DONE are present, add TODO at the beginning of the heading.
5462
5463 With prefix arg, use completion to determine the new state. With numeric
5464 prefix arg, switch to that state."
5465 (interactive "P")
5466 (save-excursion
5467 (org-back-to-heading)
5468 (if (looking-at outline-regexp) (goto-char (match-end 0)))
5469 (or (looking-at (concat " +" org-todo-regexp " *"))
5470 (looking-at " *"))
5471 (let* ((this (match-string 1))
5472 (completion-ignore-case t)
5473 (member (member this org-todo-keywords))
5474 (tail (cdr member))
5475 (state (cond
5476 ((equal arg '(4))
5477 ;; Read a state with completion
5478 (completing-read "State: " (mapcar (lambda(x) (list x))
5479 org-todo-keywords)
5480 nil t))
5481 ((eq arg 'right)
5482 (if this
5483 (if tail (car tail) nil)
5484 (car org-todo-keywords)))
5485 ((eq arg 'left)
5486 (if (equal member org-todo-keywords)
5487 nil
5488 (if this
5489 (nth (- (length org-todo-keywords) (length tail) 2)
5490 org-todo-keywords)
5491 org-done-string)))
5492 (arg
5493 ;; user requests a specific state
5494 (nth (1- (prefix-numeric-value arg))
5495 org-todo-keywords))
5496 ((null member) (car org-todo-keywords))
5497 ((null tail) nil) ;; -> first entry
5498 ((eq org-todo-interpretation 'sequence)
5499 (car tail))
5500 ((memq org-todo-interpretation '(type priority))
5501 (if (eq this-command last-command)
5502 (car tail)
5503 (if (> (length tail) 0) org-done-string nil)))
5504 (t nil)))
5505 (next (if state (concat " " state " ") " ")))
5506 (replace-match next t t)
5507 (setq org-last-todo-state-is-todo
5508 (not (equal state org-done-string)))
5509 (when org-log-done
5510 (if (equal state org-done-string)
5511 (org-add-planning-info 'closed (org-current-time) 'scheduled)
5512 (if (not this)
5513 (org-add-planning-info nil nil 'closed))))
5514 ;; Fixup tag positioning
5515 (and org-auto-align-tags (org-set-tags nil t))
5516 (run-hooks 'org-after-todo-state-change-hook)))
5517 ;; Fixup cursor location if close to the keyword
5518 (if (and (outline-on-heading-p)
5519 (not (bolp))
5520 (save-excursion (beginning-of-line 1)
5521 (looking-at org-todo-line-regexp))
5522 (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
5523 (progn
5524 (goto-char (or (match-end 2) (match-end 1)))
5525 (just-one-space))))
5526
5527 (defun org-show-todo-tree (arg)
5528 "Make a compact tree which shows all headlines marked with TODO.
5529 The tree will show the lines where the regexp matches, and all higher
5530 headlines above the match.
5531 With \\[universal-argument] prefix, also show the DONE entries.
5532 With a numeric prefix N, construct a sparse tree for the Nth element
5533 of `org-todo-keywords'."
5534 (interactive "P")
5535 (let ((case-fold-search nil)
5536 (kwd-re
5537 (cond ((null arg) org-not-done-regexp)
5538 ((equal arg '(4)) org-todo-regexp)
5539 ((<= (prefix-numeric-value arg) (length org-todo-keywords))
5540 (regexp-quote (nth (1- (prefix-numeric-value arg))
5541 org-todo-keywords)))
5542 (t (error "Invalid prefix argument: %s" arg)))))
5543 (message "%d TODO entries found"
5544 (org-occur (concat "^" outline-regexp " +" kwd-re )))))
5545
5546 (defun org-deadline ()
5547 "Insert the DEADLINE: string to make a deadline.
5548 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
5549 to modify it to the correct date."
5550 (interactive)
5551 (org-add-planning-info 'deadline nil 'closed))
5552
5553 (defun org-schedule ()
5554 "Insert the SCHEDULED: string to schedule a TODO item.
5555 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
5556 to modify it to the correct date."
5557 (interactive)
5558 (org-add-planning-info 'scheduled nil 'closed))
5559
5560 (defun org-add-planning-info (what &optional time &rest remove)
5561 "Insert new timestamp with keyword in the line directly after the headline.
5562 WHAT indicates what kind of time stamp to add. TIME indicated the time to use.
5563 If non is given, the user is prompted for a date.
5564 REMOVE indicates what kind of entries to remove. An old WHAT entry will also
5565 be removed."
5566 (interactive)
5567 (when what (setq time (or time (org-read-date nil 'to-time))))
5568 (when (and org-insert-labeled-timestamps-at-point
5569 (member what '(scheduled deadline)))
5570 (insert
5571 (if (eq what 'scheduled) org-scheduled-string org-deadline-string) " ")
5572 (org-insert-time-stamp time)
5573 (setq what nil))
5574 (save-excursion
5575 (save-restriction
5576 (let (col list elt ts buffer-invisibility-spec)
5577 (org-back-to-heading t)
5578 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"))
5579 (goto-char (match-end 1))
5580 (setq col (current-column))
5581 (goto-char (1+ (match-end 0)))
5582 (if (and (not (looking-at outline-regexp))
5583 (looking-at (concat "[^\r\n]*?" org-keyword-time-regexp
5584 "[^\r\n]*"))
5585 (not (equal (match-string 1) org-clock-string)))
5586 (narrow-to-region (match-beginning 0) (match-end 0))
5587 (insert "\n")
5588 (backward-char 1)
5589 (narrow-to-region (point) (point))
5590 (indent-to-column col))
5591 ;; Check if we have to remove something.
5592 (setq list (cons what remove))
5593 (while list
5594 (setq elt (pop list))
5595 (goto-char (point-min))
5596 (when (or (and (eq elt 'scheduled)
5597 (re-search-forward org-scheduled-time-regexp nil t))
5598 (and (eq elt 'deadline)
5599 (re-search-forward org-deadline-time-regexp nil t))
5600 (and (eq elt 'closed)
5601 (re-search-forward org-closed-time-regexp nil t)))
5602 (replace-match "")
5603 (if (looking-at " +") (replace-match ""))))
5604 (goto-char (point-max))
5605 (when what
5606 (insert
5607 (if (not (equal (char-before) ?\ )) " " "")
5608 (cond ((eq what 'scheduled) org-scheduled-string)
5609 ((eq what 'deadline) org-deadline-string)
5610 ((eq what 'closed) org-closed-string))
5611 " ")
5612 (org-insert-time-stamp time nil (eq what 'closed))
5613 (end-of-line 1)
5614 (org-add-log-maybe 'done))
5615 (goto-char (point-min))
5616 (widen)
5617 (if (looking-at "[ \t]+\r?\n")
5618 (replace-match ""))
5619 ts))))
5620
5621 (defvar org-log-note-marker (make-marker))
5622 (defvar org-log-note-purpose nil)
5623 (defvar org-log-note-window-configuration nil)
5624
5625 (defun org-add-log-maybe (&optional purpose)
5626 (when (and (listp org-log-done)
5627 (memq purpose org-log-done))
5628 (move-marker org-log-note-marker (point))
5629 (setq org-log-note-purpose purpose)
5630 (add-hook 'post-command-hook 'org-add-log-note 'append)))
5631
5632 (defun org-add-log-note (&optional purpose)
5633 "Pop up a window for taking a note, and add this note later at point."
5634 (remove-hook 'post-command-hook 'org-add-log-note)
5635 (setq org-log-note-window-configuration (current-window-configuration))
5636 (delete-other-windows)
5637 (switch-to-buffer (marker-buffer org-log-note-marker))
5638 (goto-char org-log-note-marker)
5639 (switch-to-buffer-other-window "*Org Note*")
5640 (erase-buffer)
5641 (org-mode)
5642 (insert (format "# Insert note for %s, finish with C-c C-c.\n\n"
5643 (cond
5644 ((eq org-log-note-purpose 'clock-out) "stopped clock")
5645 ((eq org-log-note-purpose 'done) "closed todo item")
5646 (t (error "This should not happen")))))
5647 (org-set-local 'org-finish-function 'org-store-log-note))
5648
5649 (defun org-store-log-note ()
5650 "Finish taking a log note, and insert it to where it belongs."
5651 (let ((txt (buffer-string))
5652 (note (cdr (assq org-log-note-purpose org-log-note-headings)))
5653 lines ind)
5654 (kill-buffer (current-buffer))
5655 (if (string-match "^#.*\n[ \t\\n]*" txt)
5656 (setq txt (replace-match "" t t txt)))
5657 (when (string-match "\\S-" txt)
5658 (if (string-match "\\s-+\\'" txt)
5659 (setq txt (replace-match "" t t txt)))
5660 (setq lines (org-split-string txt "\n"))
5661 (and note (string-match "\\S-" note) (push note lines))
5662 (save-excursion
5663 (set-buffer (marker-buffer org-log-note-marker))
5664 (save-excursion
5665 (goto-char org-log-note-marker)
5666 (if (not (bolp)) (newline))
5667 (indent-relative t)
5668 (setq ind (concat (buffer-substring (point-at-bol) (point)) " "))
5669 (insert " - " (pop lines))
5670 (while lines
5671 (insert "\n" ind (pop lines))))))
5672 (set-window-configuration org-log-note-window-configuration)))
5673
5674 (defvar org-occur-highlights nil)
5675 (make-variable-buffer-local 'org-occur-highlights)
5676
5677 (defun org-occur (regexp &optional keep-previous callback)
5678 "Make a compact tree which shows all matches of REGEXP.
5679 The tree will show the lines where the regexp matches, and all higher
5680 headlines above the match. It will also show the heading after the match,
5681 to make sure editing the matching entry is easy.
5682 If KEEP-PREVIOUS is non-nil, highlighting and exposing done by a previous
5683 call to `org-occur' will be kept, to allow stacking of calls to this
5684 command.
5685 If CALLBACK is non-nil, it is a function which is called to confirm
5686 that the match should indeed be shown."
5687 (interactive "sRegexp: \nP")
5688 (or keep-previous (org-remove-occur-highlights nil nil t))
5689 (let ((cnt 0))
5690 (save-excursion
5691 (goto-char (point-min))
5692 (if (or (not keep-previous) ; do not want to keep
5693 (not org-occur-highlights)) ; no previous matches
5694 ;; hide everything
5695 (org-overview))
5696 (while (re-search-forward regexp nil t)
5697 (when (or (not callback)
5698 (save-match-data (funcall callback)))
5699 (setq cnt (1+ cnt))
5700 (org-highlight-new-match (match-beginning 0) (match-end 0))
5701 (org-show-context 'occur-tree))))
5702 (when org-remove-highlights-with-change
5703 (org-add-hook 'before-change-functions 'org-remove-occur-highlights
5704 nil 'local))
5705 (unless org-sparse-tree-open-archived-trees
5706 (org-hide-archived-subtrees (point-min) (point-max)))
5707 (run-hooks 'org-occur-hook)
5708 (if (interactive-p)
5709 (message "%d match(es) for regexp %s" cnt regexp))
5710 cnt))
5711
5712 (defun org-show-context (&optional key siblings)
5713 "Make sure point and context and visible.
5714 How much context is shown depends upon the variables
5715 `org-show-hierarchy-above' and `org-show-following-heading'.
5716 When SIBLINGS is non-nil, show all siblings on each hierarchy level."
5717 (let ((heading-p (org-on-heading-p t))
5718 (hierarchy-p (org-get-alist-option org-show-hierarchy-above key))
5719 (following-p (org-get-alist-option org-show-following-heading key)))
5720 (catch 'exit
5721 ;; Show heading or entry text
5722 (if heading-p
5723 (org-flag-heading nil) ; only show the heading
5724 (and (or (org-invisible-p) (org-invisible-p2))
5725 (org-show-hidden-entry))) ; show entire entry
5726 (when following-p
5727 ;; Show next sibling, or heading below text
5728 (save-excursion
5729 (and (if heading-p (org-goto-sibling) (outline-next-heading))
5730 (org-flag-heading nil))))
5731 (when hierarchy-p
5732 ;; show all higher headings, possibly with siblings
5733 (save-excursion
5734 (while (and (condition-case nil
5735 (progn (org-up-heading-all 1) t)
5736 (error nil))
5737 (not (bobp)))
5738 (org-flag-heading nil)
5739 (when siblings
5740 (save-excursion
5741 (while (org-goto-sibling) (org-flag-heading nil)))
5742 (save-excursion
5743 (while (org-goto-sibling 'previous)
5744 (org-flag-heading nil))))))))))
5745
5746 (defun org-reveal (&optional siblings)
5747 "Show current entry, hierarchy above it, and the following headline.
5748 This can be used to show a consistent set of context around locations
5749 exposed with `org-show-hierarchy-above' or `org-show-following-heading'
5750 not t for the search context.
5751
5752 With optional argument SIBLINGS, on each level of the hierarchy all
5753 siblings are shown. This repairs the tree structure so what it would
5754 look like when opend with successive calls to `org-cycle'."
5755 (interactive "P")
5756 (let ((org-show-hierarchy-above t)
5757 (org-show-following-heading t))
5758 (org-show-context nil siblings)))
5759
5760 ;; Overlay compatibility functions
5761 (defun org-make-overlay (beg end &optional buffer)
5762 (if (featurep 'xemacs)
5763 (make-extent beg end buffer)
5764 (make-overlay beg end buffer)))
5765 (defun org-delete-overlay (ovl)
5766 (if (featurep 'xemacs) (delete-extent ovl) (delete-overlay ovl)))
5767 (defun org-detatch-overlay (ovl)
5768 (if (featurep 'xemacs) (detach-extent ovl) (delete-overlay ovl)))
5769 (defun org-move-overlay (ovl beg end &optional buffer)
5770 (if (featurep 'xemacs)
5771 (set-extent-endpoints ovl beg end (or buffer (current-buffer)))
5772 (move-overlay ovl beg end buffer)))
5773 (defun org-overlay-put (ovl prop value)
5774 (if (featurep 'xemacs)
5775 (set-extent-property ovl prop value)
5776 (overlay-put ovl prop value)))
5777 (defun org-overlay-display (ovl text &optional face)
5778 "Make overlay OVL display TEXT with face FACE."
5779 (if (featurep 'xemacs)
5780 (let ((gl (make-glyph text)))
5781 (and face (set-glyph-face gl face))
5782 (set-extent-property ovl 'invisible t)
5783 (set-extent-property ovl 'end-glyph gl))
5784 (overlay-put ovl 'display text)
5785 (if face (overlay-put ovl 'face face))))
5786 (defun org-overlay-get (ovl prop)
5787 (if (featurep 'xemacs)
5788 (extent-property ovl prop)
5789 (overlay-get ovl prop)))
5790 (defun org-overlays-at (pos)
5791 (if (featurep 'xemacs) (extents-at pos) (overlays-at pos)))
5792 (defun org-overlays-in (&optional start end)
5793 (if (featurep 'xemacs)
5794 (extent-list nil start end)
5795 (overlays-in start end)))
5796 (defun org-overlay-start (o)
5797 (if (featurep 'xemacs) (extent-start-position o) (overlay-start o)))
5798 (defun org-overlay-end (o)
5799 (if (featurep 'xemacs) (extent-end-position o) (overlay-end o)))
5800
5801 (defun org-highlight-new-match (beg end)
5802 "Highlight from BEG to END and mark the highlight is an occur headline."
5803 (let ((ov (org-make-overlay beg end)))
5804 (org-overlay-put ov 'face 'secondary-selection)
5805 (push ov org-occur-highlights)))
5806
5807 (defvar org-inhibit-highlight-removal nil)
5808 (defun org-remove-occur-highlights (&optional beg end noremove)
5809 "Remove the occur highlights from the buffer.
5810 BEG and END are ignored. If NOREMOVE is nil, remove this function
5811 from the `before-change-functions' in the current buffer."
5812 (interactive)
5813 (unless org-inhibit-highlight-removal
5814 (mapc 'org-delete-overlay org-occur-highlights)
5815 (setq org-occur-highlights nil)
5816 (unless noremove
5817 (remove-hook 'before-change-functions
5818 'org-remove-occur-highlights 'local))))
5819
5820 ;;; Priorities
5821
5822 (defvar org-priority-regexp ".*?\\(\\[#\\([A-Z]\\)\\] ?\\)"
5823 "Regular expression matching the priority indicator.")
5824
5825 (defvar org-remove-priority-next-time nil)
5826
5827 (defun org-priority-up ()
5828 "Increase the priority of the current item."
5829 (interactive)
5830 (org-priority 'up))
5831
5832 (defun org-priority-down ()
5833 "Decrease the priority of the current item."
5834 (interactive)
5835 (org-priority 'down))
5836
5837 (defun org-priority (&optional action)
5838 "Change the priority of an item by ARG.
5839 ACTION can be set, up, or down."
5840 (interactive)
5841 (setq action (or action 'set))
5842 (let (current new news have remove)
5843 (save-excursion
5844 (org-back-to-heading)
5845 (if (looking-at org-priority-regexp)
5846 (setq current (string-to-char (match-string 2))
5847 have t)
5848 (setq current org-default-priority))
5849 (cond
5850 ((eq action 'set)
5851 (message "Priority A-%c, SPC to remove: " org-lowest-priority)
5852 (setq new (read-char-exclusive))
5853 (cond ((equal new ?\ ) (setq remove t))
5854 ((or (< (upcase new) ?A) (> (upcase new) org-lowest-priority))
5855 (error "Priority must be between `%c' and `%c'"
5856 ?A org-lowest-priority))))
5857 ((eq action 'up)
5858 (setq new (1- current)))
5859 ((eq action 'down)
5860 (setq new (1+ current)))
5861 (t (error "Invalid action")))
5862 (setq new (min (max ?A (upcase new)) org-lowest-priority))
5863 (setq news (format "%c" new))
5864 (if have
5865 (if remove
5866 (replace-match "" t t nil 1)
5867 (replace-match news t t nil 2))
5868 (if remove
5869 (error "No priority cookie found in line")
5870 (looking-at org-todo-line-regexp)
5871 (if (match-end 2)
5872 (progn
5873 (goto-char (match-end 2))
5874 (insert " [#" news "]"))
5875 (goto-char (match-beginning 3))
5876 (insert "[#" news "] ")))))
5877 (if remove
5878 (message "Priority removed")
5879 (message "Priority of current item set to %s" news))))
5880
5881
5882 (defun org-get-priority (s)
5883 "Find priority cookie and return priority."
5884 (save-match-data
5885 (if (not (string-match org-priority-regexp s))
5886 (* 1000 (- org-lowest-priority org-default-priority))
5887 (* 1000 (- org-lowest-priority
5888 (string-to-char (match-string 2 s)))))))
5889
5890 ;;; Timestamps
5891
5892 (defvar org-last-changed-timestamp nil)
5893
5894 (defun org-time-stamp (arg)
5895 "Prompt for a date/time and insert a time stamp.
5896 If the user specifies a time like HH:MM, or if this command is called
5897 with a prefix argument, the time stamp will contain date and time.
5898 Otherwise, only the date will be included. All parts of a date not
5899 specified by the user will be filled in from the current date/time.
5900 So if you press just return without typing anything, the time stamp
5901 will represent the current date/time. If there is already a timestamp
5902 at the cursor, it will be modified."
5903 (interactive "P")
5904 (let (org-time-was-given time)
5905 (cond
5906 ((and (org-at-timestamp-p)
5907 (eq last-command 'org-time-stamp)
5908 (eq this-command 'org-time-stamp))
5909 (insert "--")
5910 (setq time (let ((this-command this-command))
5911 (org-read-date arg 'totime)))
5912 (org-insert-time-stamp time (or org-time-was-given arg)))
5913 ((org-at-timestamp-p)
5914 (setq time (let ((this-command this-command))
5915 (org-read-date arg 'totime)))
5916 (when (org-at-timestamp-p) ; just to get the match data
5917 (replace-match "")
5918 (setq org-last-changed-timestamp
5919 (org-insert-time-stamp time (or org-time-was-given arg))))
5920 (message "Timestamp updated"))
5921 (t
5922 (setq time (let ((this-command this-command))
5923 (org-read-date arg 'totime)))
5924 (org-insert-time-stamp time (or org-time-was-given arg))))))
5925
5926 (defun org-time-stamp-inactive (&optional arg)
5927 "Insert an inactive time stamp.
5928 An inactive time stamp is enclosed in square brackets instead of angle
5929 brackets. It is inactive in the sense that it does not trigger agenda entries,
5930 does not link to the calendar and cannot be changed with the S-cursor keys.
5931 So these are more for recording a certain time/date."
5932 (interactive "P")
5933 (let (org-time-was-given time)
5934 (setq time (org-read-date arg 'totime))
5935 (org-insert-time-stamp time (or org-time-was-given arg) 'inactive)))
5936
5937 (defvar org-date-ovl (org-make-overlay 1 1))
5938 (org-overlay-put org-date-ovl 'face 'org-warning)
5939 (org-detatch-overlay org-date-ovl)
5940
5941 (defun org-read-date (&optional with-time to-time from-string)
5942 "Read a date and make things smooth for the user.
5943 The prompt will suggest to enter an ISO date, but you can also enter anything
5944 which will at least partially be understood by `parse-time-string'.
5945 Unrecognized parts of the date will default to the current day, month, year,
5946 hour and minute. For example,
5947 3-2-5 --> 2003-02-05
5948 feb 15 --> currentyear-02-15
5949 sep 12 9 --> 2009-09-12
5950 12:45 --> today 12:45
5951 22 sept 0:34 --> currentyear-09-22 0:34
5952 12 --> currentyear-currentmonth-12
5953 Fri --> nearest Friday (today or later)
5954 etc.
5955 The function understands only English month and weekday abbreviations,
5956 but this can be configured with the variables `parse-time-months' and
5957 `parse-time-weekdays'.
5958
5959 While prompting, a calendar is popped up - you can also select the
5960 date with the mouse (button 1). The calendar shows a period of three
5961 months. To scroll it to other months, use the keys `>' and `<'.
5962 If you don't like the calendar, turn it off with
5963 \(setq org-popup-calendar-for-date-prompt Nil)
5964
5965 With optional argument TO-TIME, the date will immediately be converted
5966 to an internal time.
5967 With an optional argument WITH-TIME, the prompt will suggest to also
5968 insert a time. Note that when WITH-TIME is not set, you can still
5969 enter a time, and this function will inform the calling routine about
5970 this change. The calling routine may then choose to change the format
5971 used to insert the time stamp into the buffer to include the time."
5972 (require 'parse-time)
5973 (let* ((org-time-stamp-rounding-minutes
5974 (if (equal with-time '(16)) 0 org-time-stamp-rounding-minutes))
5975 (ct (org-current-time))
5976 (default-time
5977 ;; Default time is either today, or, when entering a range,
5978 ;; the range start.
5979 (if (save-excursion
5980 (re-search-backward
5981 (concat org-ts-regexp "--?-?\\=") ; 1-3 minuses
5982 (- (point) 20) t))
5983 (apply
5984 'encode-time
5985 (mapcar (lambda(x) (or x 0))
5986 (parse-time-string (match-string 1))))
5987 ct))
5988 (calendar-move-hook nil)
5989 (view-diary-entries-initially nil)
5990 (view-calendar-holidays-initially nil)
5991 (timestr (format-time-string
5992 (if with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") default-time))
5993 (prompt (format "YYYY-MM-DD [%s]: " timestr))
5994 ans ans1 ans2
5995 second minute hour day month year tl wday wday1)
5996
5997 (cond
5998 (from-string (setq ans from-string))
5999 (org-popup-calendar-for-date-prompt
6000 (save-excursion
6001 (save-window-excursion
6002 (calendar)
6003 (calendar-forward-day (- (time-to-days default-time)
6004 (calendar-absolute-from-gregorian
6005 (calendar-current-date))))
6006 (org-eval-in-calendar nil)
6007 (let* ((old-map (current-local-map))
6008 (map (copy-keymap calendar-mode-map))
6009 (minibuffer-local-map (copy-keymap minibuffer-local-map)))
6010 (define-key map (kbd "RET") 'org-calendar-select)
6011 (define-key map (if (featurep 'xemacs) [button1] [mouse-1])
6012 'org-calendar-select-mouse)
6013 (define-key map (if (featurep 'xemacs) [button2] [mouse-2])
6014 'org-calendar-select-mouse)
6015 (define-key minibuffer-local-map [(meta shift left)]
6016 (lambda () (interactive)
6017 (org-eval-in-calendar '(calendar-backward-month 1))))
6018 (define-key minibuffer-local-map [(meta shift right)]
6019 (lambda () (interactive)
6020 (org-eval-in-calendar '(calendar-forward-month 1))))
6021 (define-key minibuffer-local-map [(shift up)]
6022 (lambda () (interactive)
6023 (org-eval-in-calendar '(calendar-backward-week 1))))
6024 (define-key minibuffer-local-map [(shift down)]
6025 (lambda () (interactive)
6026 (org-eval-in-calendar '(calendar-forward-week 1))))
6027 (define-key minibuffer-local-map [(shift left)]
6028 (lambda () (interactive)
6029 (org-eval-in-calendar '(calendar-backward-day 1))))
6030 (define-key minibuffer-local-map [(shift right)]
6031 (lambda () (interactive)
6032 (org-eval-in-calendar '(calendar-forward-day 1))))
6033 (define-key minibuffer-local-map ">"
6034 (lambda () (interactive)
6035 (org-eval-in-calendar '(scroll-calendar-left 1))))
6036 (define-key minibuffer-local-map "<"
6037 (lambda () (interactive)
6038 (org-eval-in-calendar '(scroll-calendar-right 1))))
6039 (unwind-protect
6040 (progn
6041 (use-local-map map)
6042 (setq ans (read-string prompt "" nil nil))
6043 (if (not (string-match "\\S-" ans)) (setq ans nil))
6044 (setq ans (or ans1 ans ans2)))
6045 (use-local-map old-map))))))
6046 (t ; Naked prompt only
6047 (setq ans (read-string prompt "" nil timestr))))
6048 (org-detatch-overlay org-date-ovl)
6049
6050 (if (string-match
6051 "^ *\\(\\([0-9]+\\)-\\)?\\([0-1]?[0-9]\\)-\\([0-3]?[0-9]\\)\\([^-0-9]\\|$\\)" ans)
6052 (progn
6053 (setq year (if (match-end 2)
6054 (string-to-number (match-string 2 ans))
6055 (string-to-number (format-time-string "%Y")))
6056 month (string-to-number (match-string 3 ans))
6057 day (string-to-number (match-string 4 ans)))
6058 (if (< year 100) (setq year (+ 2000 year)))
6059 (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
6060 t nil ans))))
6061 (setq tl (parse-time-string ans)
6062 year (or (nth 5 tl) (string-to-number (format-time-string "%Y" ct)))
6063 month (or (nth 4 tl) (string-to-number (format-time-string "%m" ct)))
6064 day (or (nth 3 tl) (string-to-number (format-time-string "%d" ct)))
6065 hour (or (nth 2 tl) (string-to-number (format-time-string "%H" ct)))
6066 minute (or (nth 1 tl) (string-to-number (format-time-string "%M" ct)))
6067 second (or (nth 0 tl) 0)
6068 wday (nth 6 tl))
6069 (when (and wday (not (nth 3 tl)))
6070 ;; Weekday was given, but no day, so pick that day in the week
6071 ;; on or after the derived date.
6072 (setq wday1 (nth 6 (decode-time (encode-time 0 0 0 day month year))))
6073 (unless (equal wday wday1)
6074 (setq day (+ day (% (- wday wday1 -7) 7)))))
6075 (if (and (boundp 'org-time-was-given)
6076 (nth 2 tl))
6077 (setq org-time-was-given t))
6078 (if (< year 100) (setq year (+ 2000 year)))
6079 (if to-time
6080 (encode-time second minute hour day month year)
6081 (if (or (nth 1 tl) (nth 2 tl))
6082 (format "%04d-%02d-%02d %02d:%02d" year month day hour minute)
6083 (format "%04d-%02d-%02d" year month day)))))
6084
6085 (defun org-eval-in-calendar (form)
6086 "Eval FORM in the calendar window and return to current window.
6087 Also, store the cursor date in variable ans2."
6088 (let ((sw (selected-window)))
6089 (select-window (get-buffer-window "*Calendar*"))
6090 (eval form)
6091 (when (calendar-cursor-to-date)
6092 (let* ((date (calendar-cursor-to-date))
6093 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
6094 (setq ans2 (format-time-string "%Y-%m-%d" time))))
6095 (org-move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer))
6096 (select-window sw)))
6097
6098 (defun org-calendar-select ()
6099 "Return to `org-read-date' with the date currently selected.
6100 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
6101 (interactive)
6102 (when (calendar-cursor-to-date)
6103 (let* ((date (calendar-cursor-to-date))
6104 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
6105 (setq ans1 (format-time-string "%Y-%m-%d" time)))
6106 (if (active-minibuffer-window) (exit-minibuffer))))
6107
6108 (defun org-insert-time-stamp (time &optional with-hm inactive pre post)
6109 "Insert a date stamp for the date given by the internal TIME.
6110 WITH-HM means, use the stamp format that includes the time of the day.
6111 INACTIVE means use square brackets instead of angular ones, so that the
6112 stamp will not contribute to the agenda.
6113 PRE and POST are optional strings to be inserted before and after the
6114 stamp.
6115 The command returns the inserted time stamp."
6116 (let ((fmt (funcall (if with-hm 'cdr 'car) org-time-stamp-formats))
6117 stamp)
6118 (if inactive (setq fmt (concat "[" (substring fmt 1 -1) "]")))
6119 (insert (or pre ""))
6120 (insert (setq stamp (format-time-string fmt time)))
6121 (insert (or post ""))
6122 stamp))
6123
6124 (defun org-toggle-time-stamp-overlays ()
6125 "Toggle the use of custom time stamp formats."
6126 (interactive)
6127 (setq org-display-custom-times (not org-display-custom-times))
6128 (unless org-display-custom-times
6129 (let ((p (point-min)) (bmp (buffer-modified-p)))
6130 (while (setq p (next-single-property-change p 'display))
6131 (if (and (get-text-property p 'display)
6132 (eq (get-text-property p 'face) 'org-date))
6133 (remove-text-properties
6134 p (setq p (next-single-property-change p 'display))
6135 '(display t))))
6136 (set-buffer-modified-p bmp)))
6137 (if (featurep 'xemacs)
6138 (remove-text-properties (point-min) (point-max) '(end-glyph t)))
6139 (org-restart-font-lock)
6140 (setq org-table-may-need-update t)
6141 (if org-display-custom-times
6142 (message "Time stamps are overlayed with custom format")
6143 (message "Time stamp overlays removed")))
6144
6145 (defun org-display-custom-time (beg end)
6146 "Overlay modified time stamp format over timestamp between BED and END."
6147 (let* ((t1 (save-match-data
6148 (org-parse-time-string (buffer-substring beg end) t)))
6149 (w1 (- end beg))
6150 (with-hm (and (nth 1 t1) (nth 2 t1)))
6151 (inactive (= (char-before (1- beg)) ?\[))
6152 (tf (funcall (if with-hm 'cdr 'car) org-time-stamp-custom-formats))
6153 (time (mapcar (lambda (x) (or x 0)) t1))
6154 (str (org-add-props
6155 (format-time-string
6156 (substring tf 1 -1) (apply 'encode-time time))
6157 nil 'mouse-face 'highlight))
6158 (w2 (length str)))
6159 (if (not (= w2 w1))
6160 (add-text-properties (1+ beg) (+ 2 beg)
6161 (list 'org-dwidth t 'org-dwidth-n (- w1 w2))))
6162 (if (featurep 'xemacs)
6163 (progn
6164 (put-text-property beg end 'invisible t)
6165 (put-text-property beg end 'end-glyph (make-glyph str)))
6166 (put-text-property beg end 'display str))))
6167
6168 (defun org-days-to-time (timestamp-string)
6169 "Difference between TIMESTAMP-STRING and now in days."
6170 (- (time-to-days (org-time-string-to-time timestamp-string))
6171 (time-to-days (current-time))))
6172
6173 (defun org-deadline-close (timestamp-string &optional ndays)
6174 "Is the time in TIMESTAMP-STRING close to the current date?"
6175 (and (< (org-days-to-time timestamp-string)
6176 (or ndays org-deadline-warning-days))
6177 (not (org-entry-is-done-p))))
6178
6179 (defun org-calendar-select-mouse (ev)
6180 "Return to `org-read-date' with the date currently selected.
6181 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
6182 (interactive "e")
6183 (mouse-set-point ev)
6184 (when (calendar-cursor-to-date)
6185 (let* ((date (calendar-cursor-to-date))
6186 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
6187 (setq ans1 (format-time-string "%Y-%m-%d" time)))
6188 (if (active-minibuffer-window) (exit-minibuffer))))
6189
6190 (defun org-check-deadlines (ndays)
6191 "Check if there are any deadlines due or past due.
6192 A deadline is considered due if it happens within `org-deadline-warning-days'
6193 days from today's date. If the deadline appears in an entry marked DONE,
6194 it is not shown. The prefix arg NDAYS can be used to test that many
6195 days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are shown."
6196 (interactive "P")
6197 (let* ((org-warn-days
6198 (cond
6199 ((equal ndays '(4)) 100000)
6200 (ndays (prefix-numeric-value ndays))
6201 (t org-deadline-warning-days)))
6202 (case-fold-search nil)
6203 (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>"))
6204 (callback
6205 (lambda () (org-deadline-close (match-string 1) org-warn-days))))
6206
6207 (message "%d deadlines past-due or due within %d days"
6208 (org-occur regexp nil callback)
6209 org-warn-days)))
6210
6211 (defun org-evaluate-time-range (&optional to-buffer)
6212 "Evaluate a time range by computing the difference between start and end.
6213 Normally the result is just printed in the echo area, but with prefix arg
6214 TO-BUFFER, the result is inserted just after the date stamp into the buffer.
6215 If the time range is actually in a table, the result is inserted into the
6216 next column.
6217 For time difference computation, a year is assumed to be exactly 365
6218 days in order to avoid rounding problems."
6219 (interactive "P")
6220 (or
6221 (org-clock-update-time-maybe)
6222 (save-excursion
6223 (unless (org-at-date-range-p)
6224 (goto-char (point-at-bol))
6225 (re-search-forward org-tr-regexp (point-at-eol) t))
6226 (if (not (org-at-date-range-p))
6227 (error "Not at a time-stamp range, and none found in current line")))
6228 (let* ((ts1 (match-string 1))
6229 (ts2 (match-string 2))
6230 (havetime (or (> (length ts1) 15) (> (length ts2) 15)))
6231 (match-end (match-end 0))
6232 (time1 (org-time-string-to-time ts1))
6233 (time2 (org-time-string-to-time ts2))
6234 (t1 (time-to-seconds time1))
6235 (t2 (time-to-seconds time2))
6236 (diff (abs (- t2 t1)))
6237 (negative (< (- t2 t1) 0))
6238 ;; (ys (floor (* 365 24 60 60)))
6239 (ds (* 24 60 60))
6240 (hs (* 60 60))
6241 (fy "%dy %dd %02d:%02d")
6242 (fy1 "%dy %dd")
6243 (fd "%dd %02d:%02d")
6244 (fd1 "%dd")
6245 (fh "%02d:%02d")
6246 y d h m align)
6247 (if havetime
6248 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
6249 y 0
6250 d (floor (/ diff ds)) diff (mod diff ds)
6251 h (floor (/ diff hs)) diff (mod diff hs)
6252 m (floor (/ diff 60)))
6253 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
6254 y 0
6255 d (floor (+ (/ diff ds) 0.5))
6256 h 0 m 0))
6257 (if (not to-buffer)
6258 (message (org-make-tdiff-string y d h m))
6259 (when (org-at-table-p)
6260 (goto-char match-end)
6261 (setq align t)
6262 (and (looking-at " *|") (goto-char (match-end 0))))
6263 (if (looking-at
6264 "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]")
6265 (replace-match ""))
6266 (if negative (insert " -"))
6267 (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m))
6268 (if (> d 0) (insert " " (format (if havetime fd fd1) d h m))
6269 (insert " " (format fh h m))))
6270 (if align (org-table-align))
6271 (message "Time difference inserted")))))
6272
6273 (defun org-make-tdiff-string (y d h m)
6274 (let ((fmt "")
6275 (l nil))
6276 (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ")
6277 l (push y l)))
6278 (if (> d 0) (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ")
6279 l (push d l)))
6280 (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ")
6281 l (push h l)))
6282 (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ")
6283 l (push m l)))
6284 (apply 'format fmt (nreverse l))))
6285
6286 (defun org-time-string-to-time (s)
6287 (apply 'encode-time (org-parse-time-string s)))
6288
6289 (defun org-parse-time-string (s &optional nodefault)
6290 "Parse the standard Org-mode time string.
6291 This should be a lot faster than the normal `parse-time-string'.
6292 If time is not given, defaults to 0:00. However, with optional NODEFAULT,
6293 hour and minute fields will be nil if not given."
6294 (if (string-match org-ts-regexp1 s)
6295 (list 0
6296 (if (or (match-beginning 8) (not nodefault))
6297 (string-to-number (or (match-string 8 s) "0")))
6298 (if (or (match-beginning 7) (not nodefault))
6299 (string-to-number (or (match-string 7 s) "0")))
6300 (string-to-number (match-string 4 s))
6301 (string-to-number (match-string 3 s))
6302 (string-to-number (match-string 2 s))
6303 nil nil nil)
6304 (make-list 9 0)))
6305
6306 (defun org-timestamp-up (&optional arg)
6307 "Increase the date item at the cursor by one.
6308 If the cursor is on the year, change the year. If it is on the month or
6309 the day, change that.
6310 With prefix ARG, change by that many units."
6311 (interactive "p")
6312 (org-timestamp-change (prefix-numeric-value arg)))
6313
6314 (defun org-timestamp-down (&optional arg)
6315 "Decrease the date item at the cursor by one.
6316 If the cursor is on the year, change the year. If it is on the month or
6317 the day, change that.
6318 With prefix ARG, change by that many units."
6319 (interactive "p")
6320 (org-timestamp-change (- (prefix-numeric-value arg))))
6321
6322 (defun org-timestamp-up-day (&optional arg)
6323 "Increase the date in the time stamp by one day.
6324 With prefix ARG, change that many days."
6325 (interactive "p")
6326 (if (and (not (org-at-timestamp-p t))
6327 (org-on-heading-p))
6328 (org-todo 'up)
6329 (org-timestamp-change (prefix-numeric-value arg) 'day)))
6330
6331 (defun org-timestamp-down-day (&optional arg)
6332 "Decrease the date in the time stamp by one day.
6333 With prefix ARG, change that many days."
6334 (interactive "p")
6335 (if (and (not (org-at-timestamp-p t))
6336 (org-on-heading-p))
6337 (org-todo 'down)
6338 (org-timestamp-change (- (prefix-numeric-value arg)) 'day)))
6339
6340 (defsubst org-pos-in-match-range (pos n)
6341 (and (match-beginning n)
6342 (<= (match-beginning n) pos)
6343 (>= (match-end n) pos)))
6344
6345 (defun org-at-timestamp-p (&optional inactive-ok)
6346 "Determine if the cursor is in or at a timestamp."
6347 (interactive)
6348 (let* ((tsr (if inactive-ok org-ts-regexp3 org-ts-regexp2))
6349 (pos (point))
6350 (ans (or (looking-at tsr)
6351 (save-excursion
6352 (skip-chars-backward "^[<\n\r\t")
6353 (if (> (point) 1) (backward-char 1))
6354 (and (looking-at tsr)
6355 (> (- (match-end 0) pos) -1))))))
6356 (and (boundp 'org-ts-what)
6357 (setq org-ts-what
6358 (cond
6359 ((org-pos-in-match-range pos 2) 'year)
6360 ((org-pos-in-match-range pos 3) 'month)
6361 ((org-pos-in-match-range pos 7) 'hour)
6362 ((org-pos-in-match-range pos 8) 'minute)
6363 ((or (org-pos-in-match-range pos 4)
6364 (org-pos-in-match-range pos 5)) 'day)
6365 (t 'day))))
6366 ans))
6367
6368 (defun org-timestamp-change (n &optional what)
6369 "Change the date in the time stamp at point.
6370 The date will be changed by N times WHAT. WHAT can be `day', `month',
6371 `year', `minute', `second'. If WHAT is not given, the cursor position
6372 in the timestamp determines what will be changed."
6373 (let ((pos (point))
6374 with-hm inactive
6375 org-ts-what
6376 ts time time0)
6377 (if (not (org-at-timestamp-p t))
6378 (error "Not at a timestamp"))
6379 (if (and (not what) (not (eq org-ts-what 'day))
6380 org-display-custom-times
6381 (get-text-property (point) 'display)
6382 (not (get-text-property (1- (point)) 'display)))
6383 (setq org-ts-what 'day))
6384 (setq org-ts-what (or what org-ts-what)
6385 with-hm (<= (abs (- (cdr org-ts-lengths)
6386 (- (match-end 0) (match-beginning 0))))
6387 1)
6388 inactive (= (char-after (match-beginning 0)) ?\[)
6389 ts (match-string 0))
6390 (replace-match "")
6391 (setq time0 (org-parse-time-string ts))
6392 (setq time
6393 (apply 'encode-time
6394 (append
6395 (list (or (car time0) 0))
6396 (list (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0)))
6397 (list (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0)))
6398 (list (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0)))
6399 (list (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0)))
6400 (list (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0)))
6401 (nthcdr 6 time0))))
6402 (if (eq what 'calendar)
6403 (let ((cal-date
6404 (save-excursion
6405 (save-match-data
6406 (set-buffer "*Calendar*")
6407 (calendar-cursor-to-date)))))
6408 (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month
6409 (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day
6410 (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year
6411 (setcar time0 (or (car time0) 0))
6412 (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
6413 (setcar (nthcdr 2 time0) (or (nth 1 time0) 0))
6414 (setq time (apply 'encode-time time0))))
6415 (org-insert-time-stamp time with-hm inactive)
6416 (org-clock-update-time-maybe)
6417 (goto-char pos)
6418 ;; Try to recenter the calendar window, if any
6419 (if (and org-calendar-follow-timestamp-change
6420 (get-buffer-window "*Calendar*" t)
6421 (memq org-ts-what '(day month year)))
6422 (org-recenter-calendar (time-to-days time)))))
6423
6424 (defun org-recenter-calendar (date)
6425 "If the calendar is visible, recenter it to DATE."
6426 (let* ((win (selected-window))
6427 (cwin (get-buffer-window "*Calendar*" t))
6428 (calendar-move-hook nil))
6429 (when cwin
6430 (select-window cwin)
6431 (calendar-goto-date (if (listp date) date
6432 (calendar-gregorian-from-absolute date)))
6433 (select-window win))))
6434
6435 (defun org-goto-calendar (&optional arg)
6436 "Go to the Emacs calendar at the current date.
6437 If there is a time stamp in the current line, go to that date.
6438 A prefix ARG can be used to force the current date."
6439 (interactive "P")
6440 (let ((tsr org-ts-regexp) diff
6441 (calendar-move-hook nil)
6442 (view-calendar-holidays-initially nil)
6443 (view-diary-entries-initially nil))
6444 (if (or (org-at-timestamp-p)
6445 (save-excursion
6446 (beginning-of-line 1)
6447 (looking-at (concat ".*" tsr))))
6448 (let ((d1 (time-to-days (current-time)))
6449 (d2 (time-to-days
6450 (org-time-string-to-time (match-string 1)))))
6451 (setq diff (- d2 d1))))
6452 (calendar)
6453 (calendar-goto-today)
6454 (if (and diff (not arg)) (calendar-forward-day diff))))
6455
6456 (defun org-date-from-calendar ()
6457 "Insert time stamp corresponding to cursor date in *Calendar* buffer.
6458 If there is already a time stamp at the cursor position, update it."
6459 (interactive)
6460 (org-timestamp-change 0 'calendar))
6461
6462 ;;; The clock for measuring work time.
6463
6464 (defvar org-clock-marker (make-marker)
6465 "Marker recording the last clock-in.")
6466
6467 (defun org-clock-in ()
6468 "Start the clock on the current item.
6469 If necessary, clock-out of the currently active clock."
6470 (interactive)
6471 (org-clock-out t)
6472 (let (ts)
6473 (save-excursion
6474 (org-back-to-heading t)
6475 (beginning-of-line 2)
6476 (if (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
6477 (not (equal (match-string 1) org-clock-string)))
6478 (beginning-of-line 1))
6479 (insert "\n") (backward-char 1)
6480 (indent-relative)
6481 (insert org-clock-string " ")
6482 (setq ts (org-insert-time-stamp (current-time) 'with-hm 'inactive))
6483 (move-marker org-clock-marker (point))
6484 (message "Clock started at %s" ts))))
6485
6486 (defun org-clock-out (&optional fail-quietly)
6487 "Stop the currently running clock.
6488 If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
6489 (interactive)
6490 (catch 'exit
6491 (if (not (marker-buffer org-clock-marker))
6492 (if fail-quietly (throw 'exit t) (error "No active clock")))
6493 (let (ts te s h m)
6494 (save-excursion
6495 (set-buffer (marker-buffer org-clock-marker))
6496 (goto-char org-clock-marker)
6497 (beginning-of-line 1)
6498 (if (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
6499 (equal (match-string 1) org-clock-string))
6500 (setq ts (match-string 2))
6501 (if fail-quietly (throw 'exit nil) (error "Clock start time is gone")))
6502 (goto-char org-clock-marker)
6503 (insert "--")
6504 (setq te (org-insert-time-stamp (current-time) 'with-hm 'inactive))
6505 (setq s (- (time-to-seconds (apply 'encode-time (org-parse-time-string te)))
6506 (time-to-seconds (apply 'encode-time (org-parse-time-string ts))))
6507 h (floor (/ s 3600))
6508 s (- s (* 3600 h))
6509 m (floor (/ s 60))
6510 s (- s (* 60 s)))
6511 (insert " => " (format "%2d:%02d" h m))
6512 (move-marker org-clock-marker nil)
6513 (org-add-log-maybe 'clock-out)
6514 (message "Clock stopped at %s after HH:MM = %d:%02d" te h m)))))
6515
6516 (defun org-clock-cancel ()
6517 "Cancel the running clock be removing the start timestamp."
6518 (interactive)
6519 (if (not (marker-buffer org-clock-marker))
6520 (error "No active clock"))
6521 (save-excursion
6522 (set-buffer (marker-buffer org-clock-marker))
6523 (goto-char org-clock-marker)
6524 (delete-region (1- (point-at-bol)) (point-at-eol)))
6525 (message "Clock canceled"))
6526
6527 (defvar org-clock-file-total-minutes nil
6528 "Holds the file total time in minutes, after a call to `org-clock-sum'.")
6529 (make-variable-buffer-local 'org-clock-file-total-minutes)
6530
6531 (defun org-clock-sum (&optional tstart tend)
6532 "Sum the times for each subtree.
6533 Puts the resulting times in minutes as a text property on each headline."
6534 (interactive)
6535 (let* ((bmp (buffer-modified-p))
6536 (re (concat "^\\(\\*+\\)[ \t]\\|^[ \t]*"
6537 org-clock-string
6538 "[ \t]*\\(\\[.*?\\]\\)-+\\(\\[.*?\\]\\)"))
6539 (lmax 30)
6540 (ltimes (make-vector lmax 0))
6541 (t1 0)
6542 (level 0)
6543 ts te dt
6544 time)
6545 (remove-text-properties (point-min) (point-max) '(:org-clock-minutes t))
6546 (save-excursion
6547 (goto-char (point-max))
6548 (while (re-search-backward re nil t)
6549 (if (match-end 2)
6550 ;; A time
6551 (setq ts (match-string 2)
6552 te (match-string 3)
6553 ts (time-to-seconds
6554 (apply 'encode-time (org-parse-time-string ts)))
6555 te (time-to-seconds
6556 (apply 'encode-time (org-parse-time-string te)))
6557 ts (if tstart (max ts tstart) ts)
6558 te (if tend (min te tend) te)
6559 dt (- te ts)
6560 t1 (if (> dt 0) (+ t1 (floor (/ dt 60))) t1))
6561 ;; A headline
6562 (setq level (- (match-end 1) (match-beginning 1)))
6563 (when (or (> t1 0) (> (aref ltimes level) 0))
6564 (loop for l from 0 to level do
6565 (aset ltimes l (+ (aref ltimes l) t1)))
6566 (setq t1 0 time (aref ltimes level))
6567 (loop for l from level to (1- lmax) do
6568 (aset ltimes l 0))
6569 (goto-char (match-beginning 0))
6570 (put-text-property (point) (point-at-eol) :org-clock-minutes time))))
6571 (setq org-clock-file-total-minutes (aref ltimes 0)))
6572 (set-buffer-modified-p bmp)))
6573
6574 (defun org-clock-display (&optional total-only)
6575 "Show subtree times in the entire buffer.
6576 If TOTAL-ONLY is non-nil, only show the total time for the entire file
6577 in the echo area."
6578 (interactive)
6579 (org-remove-clock-overlays)
6580 (let (time h m p)
6581 (org-clock-sum)
6582 (unless total-only
6583 (save-excursion
6584 (goto-char (point-min))
6585 (while (setq p (next-single-property-change (point) :org-clock-minutes))
6586 (goto-char p)
6587 (when (setq time (get-text-property p :org-clock-minutes))
6588 (org-put-clock-overlay time (funcall outline-level))))
6589 (setq h (/ org-clock-file-total-minutes 60)
6590 m (- org-clock-file-total-minutes (* 60 h)))
6591 ;; Arrange to remove the overlays upon next change.
6592 (when org-remove-highlights-with-change
6593 (org-add-hook 'before-change-functions 'org-remove-clock-overlays
6594 nil 'local))))
6595 (message "Total file time: %d:%02d (%d hours and %d minutes)" h m h m)))
6596
6597 (defvar org-clock-overlays nil)
6598 (make-variable-buffer-local 'org-clock-overlays)
6599
6600 (defun org-put-clock-overlay (time &optional level)
6601 "Put an overlays on the current line, displaying TIME.
6602 If LEVEL is given, prefix time with a corresponding number of stars.
6603 This creates a new overlay and stores it in `org-clock-overlays', so that it
6604 will be easy to remove."
6605 (let* ((c 60) (h (floor (/ time 60))) (m (- time (* 60 h)))
6606 (l (if level (org-get-legal-level level 0) 0))
6607 (off 0)
6608 ov tx)
6609 (move-to-column c)
6610 (unless (eolp) (skip-chars-backward "^ \t"))
6611 (skip-chars-backward " \t")
6612 (setq ov (org-make-overlay (1- (point)) (point-at-eol))
6613 tx (concat (buffer-substring (1- (point)) (point))
6614 (make-string (+ off (max 0 (- c (current-column)))) ?.)
6615 (org-add-props (format "%s %2d:%02d%s"
6616 (make-string l ?*) h m
6617 (make-string (- 10 l) ?\ ))
6618 '(face secondary-selection))
6619 ""))
6620 (if (not (featurep 'xemacs))
6621 (org-overlay-put ov 'display tx)
6622 (org-overlay-put ov 'invisible t)
6623 (org-overlay-put ov 'end-glyph (make-glyph tx)))
6624 (push ov org-clock-overlays)))
6625
6626 (defun org-remove-clock-overlays (&optional beg end noremove)
6627 "Remove the occur highlights from the buffer.
6628 BEG and END are ignored. If NOREMOVE is nil, remove this function
6629 from the `before-change-functions' in the current buffer."
6630 (interactive)
6631 (unless org-inhibit-highlight-removal
6632 (mapc 'org-delete-overlay org-clock-overlays)
6633 (setq org-clock-overlays nil)
6634 (unless noremove
6635 (remove-hook 'before-change-functions
6636 'org-remove-clock-overlays 'local))))
6637
6638 (defun org-clock-out-if-current ()
6639 "Clock out if the current entry contains the running clock.
6640 This is used to stop the clock after a TODO entry is marked DONE."
6641 (when (and (equal state org-done-string)
6642 (equal (marker-buffer org-clock-marker) (current-buffer))
6643 (< (point) org-clock-marker)
6644 (> (save-excursion (outline-next-heading) (point))
6645 org-clock-marker))
6646 ;; Clock out, but don't accept a logging message for this.
6647 (let ((org-log-done (if (and (listp org-log-done)
6648 (member 'clock-out org-log-done))
6649 '(done)
6650 org-log-done)))
6651 (org-clock-out))))
6652
6653 (add-hook 'org-after-todo-state-change-hook
6654 'org-clock-out-if-current)
6655
6656 (defun org-check-running-clock ()
6657 "Check if the current buffer contains the running clock.
6658 If yes, offer to stop it and to save the buffer with the changes."
6659 (when (and (equal (marker-buffer org-clock-marker) (current-buffer))
6660 (y-or-n-p (format "Clock-out in buffer %s before killing it? "
6661 (buffer-name))))
6662 (org-clock-out)
6663 (when (y-or-n-p "Save changed buffer?")
6664 (save-buffer))))
6665
6666 (defun org-clock-report ()
6667 "Create a table containing a report about clocked time.
6668 If the buffer contains lines
6669 #+BEGIN: clocktable :maxlevel 3 :emphasize nil
6670
6671 #+END: clocktable
6672 then the table will be inserted between these lines, replacing whatever
6673 is was there before. If these lines are not in the buffer, the table
6674 is inserted at point, surrounded by the special lines.
6675 The BEGIN line can contain parameters. Allowed are:
6676 :maxlevel The maximum level to be included in the table. Default is 3.
6677 :emphasize t/nil, if levell 1 and level 2 should be bold/italic in the table."
6678 (interactive)
6679 (org-remove-clock-overlays)
6680 (unless (org-find-dblock "clocktable")
6681 (org-create-dblock (list :name "clocktable"
6682 :maxlevel 2 :emphasize nil)))
6683 (org-update-dblock))
6684
6685 (defun org-clock-update-time-maybe ()
6686 "If this is a CLOCK line, update it and return t.
6687 Otherwise, return nil."
6688 (interactive)
6689 (save-excursion
6690 (beginning-of-line 1)
6691 (skip-chars-forward " \t")
6692 (when (looking-at org-clock-string)
6693 (let ((re (concat "[ \t]*" org-clock-string
6694 " *[[<]\\([^]>]+\\)[]>]-+[[<]\\([^]>]+\\)[]>]"
6695 "\\([ \t]*=>.*\\)?"))
6696 ts te h m s)
6697 (if (not (looking-at re))
6698 nil
6699 (and (match-end 3) (delete-region (match-beginning 3) (match-end 3)))
6700 (end-of-line 1)
6701 (setq ts (match-string 1)
6702 te (match-string 2))
6703 (setq s (- (time-to-seconds
6704 (apply 'encode-time (org-parse-time-string te)))
6705 (time-to-seconds
6706 (apply 'encode-time (org-parse-time-string ts))))
6707 h (floor (/ s 3600))
6708 s (- s (* 3600 h))
6709 m (floor (/ s 60))
6710 s (- s (* 60 s)))
6711 (insert " => " (format "%2d:%02d" h m))
6712 t)))))
6713
6714 (defun org-clock-special-range (key &optional time as-strings)
6715 "Return two times bordering a special time range.
6716 Key is a symbol specifying the range and can be one of `today', `yesterday',
6717 `thisweek', `lastweek', `thismonth', `lastmonth', `thisyear', `lastyear'.
6718 A week starts Monday 0:00 and ends Sunday 24:00.
6719 The range is determined relative to TIME. TIME defaults to the current time.
6720 The return value is a cons cell with two internal times like the ones
6721 returned by `current time' or `encode-time'. if AS-STRINGS is non-nil,
6722 the returned times will be formatted strings."
6723 (let* ((tm (decode-time (or time (current-time))))
6724 (s 0) (m (nth 1 tm)) (h (nth 2 tm))
6725 (d (nth 3 tm)) (month (nth 4 tm)) (y (nth 5 tm))
6726 (dow (nth 6 tm))
6727 s1 m1 h1 d1 month1 y1 diff ts te fm)
6728 (cond
6729 ((eq key 'today)
6730 (setq h 0 m 0 h1 24 m1 0))
6731 ((eq key 'yesterday)
6732 (setq d (1- d) h 0 m 0 h1 24 m1 0))
6733 ((eq key 'thisweek)
6734 (setq diff (if (= dow 0) 6 (1- dow))
6735 m 0 h 0 d (- d diff) d1 (+ 7 d)))
6736 ((eq key 'lastweek)
6737 (setq diff (+ 7 (if (= dow 0) 6 (1- dow)))
6738 m 0 h 0 d (- d diff) d1 (+ 7 d)))
6739 ((eq key 'thismonth)
6740 (setq d 1 h 0 m 0 d1 1 month1 (1+ month) h1 0 m1 0))
6741 ((eq key 'lastmonth)
6742 (setq d 1 h 0 m 0 d1 1 month (1- month) month1 (1+ month) h1 0 m1 0))
6743 ((eq key 'thisyear)
6744 (setq m 0 h 0 d 1 month 1 y1 (1+ y)))
6745 ((eq key 'lastyear)
6746 (setq m 0 h 0 d 1 month 1 y (1- y) y1 (1+ y)))
6747 (t (error "No such time block %s" key)))
6748 (setq ts (encode-time s m h d month y)
6749 te (encode-time (or s1 s) (or m1 m) (or h1 h)
6750 (or d1 d) (or month1 month) (or y1 y)))
6751 (setq fm (cdr org-time-stamp-formats))
6752 (if as-strings
6753 (cons (format-time-string fm ts) (format-time-string fm te))
6754 (cons ts te))))
6755
6756 (defun org-dblock-write:clocktable (params)
6757 "Write the standard clocktable."
6758 (let ((hlchars '((1 . "*") (2 . ?/)))
6759 (emph nil)
6760 (ins (make-marker))
6761 ipos time h m p level hlc hdl maxlevel
6762 ts te cc block)
6763 (setq maxlevel (or (plist-get params :maxlevel) 3)
6764 emph (plist-get params :emphasize)
6765 ts (plist-get params :tstart)
6766 te (plist-get params :tend)
6767 block (plist-get params :block))
6768 (when block
6769 (setq cc (org-clock-special-range block nil t)
6770 ts (car cc) te (cdr cc)))
6771 (if ts (setq ts (time-to-seconds
6772 (apply 'encode-time (org-parse-time-string ts)))))
6773 (if te (setq te (time-to-seconds
6774 (apply 'encode-time (org-parse-time-string te)))))
6775 (move-marker ins (point))
6776 (setq ipos (point))
6777 ;; FIXME: does not yet use org-insert-time-stamp or custom format
6778 (insert-before-markers "Clock summary at ["
6779 (substring
6780 (format-time-string (cdr org-time-stamp-formats))
6781 1 -1)
6782 "]."
6783 (if block
6784 (format " Considered range is /%s/." block)
6785 "")
6786 "\n\n|L|Headline|Time|\n")
6787 (org-clock-sum ts te)
6788 (setq h (/ org-clock-file-total-minutes 60)
6789 m (- org-clock-file-total-minutes (* 60 h)))
6790 (insert-before-markers "|-\n|0|" "*Total file time*| "
6791 (format "*%d:%02d*" h m)
6792 "|\n")
6793 (goto-char (point-min))
6794 (while (setq p (next-single-property-change (point) :org-clock-minutes))
6795 (goto-char p)
6796 (when (setq time (get-text-property p :org-clock-minutes))
6797 (save-excursion
6798 (beginning-of-line 1)
6799 (when (and (looking-at "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ \t]+:[0-9a-zA-Z_@:]+:\\)?[ \t]*$")
6800 (setq level (- (match-end 1) (match-beginning 1)))
6801 (<= level maxlevel))
6802 (setq hlc (if emph (or (cdr (assoc level hlchars)) "") "")
6803 hdl (match-string 2)
6804 h (/ time 60)
6805 m (- time (* 60 h)))
6806 (goto-char ins)
6807 (if (= level 1) (insert-before-markers "|-\n"))
6808 (insert-before-markers
6809 "| " (int-to-string level) "|" hlc hdl hlc " |"
6810 (make-string (1- level) ?|)
6811 hlc
6812 (format "%d:%02d" h m)
6813 hlc
6814 " |\n")))))
6815 (goto-char ins)
6816 (backward-delete-char 1)
6817 (goto-char ipos)
6818 (skip-chars-forward "^|")
6819 (org-table-align)))
6820
6821 (defun org-collect-clock-time-entries ()
6822 "Return an internal list with clocking information.
6823 This list has one entry for each CLOCK interval.
6824 FIXME: describe the elements."
6825 (interactive)
6826 (let ((re (concat "^[ \t]*" org-clock-string
6827 " *\\[\\(.*?\\)\\]--\\[\\(.*?\\)\\]"))
6828 rtn beg end next cont level title total closedp leafp
6829 clockpos titlepos h m donep)
6830 (save-excursion
6831 (org-clock-sum)
6832 (goto-char (point-min))
6833 (while (re-search-forward re nil t)
6834 (setq clockpos (match-beginning 0)
6835 beg (match-string 1) end (match-string 2)
6836 cont (match-end 0))
6837 (setq beg (apply 'encode-time (org-parse-time-string beg))
6838 end (apply 'encode-time (org-parse-time-string end)))
6839 (org-back-to-heading t)
6840 (setq donep (org-entry-is-done-p))
6841 (setq titlepos (point)
6842 total (or (get-text-property (1+ (point)) :org-clock-minutes) 0)
6843 h (/ total 60) m (- total (* 60 h))
6844 total (cons h m))
6845 (looking-at "\\(\\*+\\) +\\(.*\\)")
6846 (setq level (- (match-end 1) (match-beginning 1))
6847 title (org-match-string-no-properties 2))
6848 (save-excursion (outline-next-heading) (setq next (point)))
6849 (setq closedp (re-search-forward org-closed-time-regexp next t))
6850 (goto-char next)
6851 (setq leafp (and (looking-at "^\\*+ ")
6852 (<= (- (match-end 0) (point)) level)))
6853 (push (list beg end clockpos closedp donep
6854 total title titlepos level leafp)
6855 rtn)
6856 (goto-char cont)))
6857 (nreverse rtn)))
6858
6859 ;;; Agenda, and Diary Integration
6860
6861 ;;; Define the mode
6862
6863 (defvar org-agenda-mode-map (make-sparse-keymap)
6864 "Keymap for `org-agenda-mode'.")
6865
6866 (defvar org-agenda-menu) ; defined later in this file.
6867 (defvar org-agenda-follow-mode nil)
6868 (defvar org-agenda-show-log nil)
6869 (defvar org-agenda-redo-command nil)
6870 (defvar org-agenda-mode-hook nil)
6871 (defvar org-agenda-type nil)
6872 (defvar org-agenda-force-single-file nil)
6873
6874 (defun org-agenda-mode ()
6875 "Mode for time-sorted view on action items in Org-mode files.
6876
6877 The following commands are available:
6878
6879 \\{org-agenda-mode-map}"
6880 (interactive)
6881 (kill-all-local-variables)
6882 (setq major-mode 'org-agenda-mode)
6883 (setq mode-name "Org-Agenda")
6884 (use-local-map org-agenda-mode-map)
6885 (easy-menu-add org-agenda-menu)
6886 (if org-startup-truncated (setq truncate-lines t))
6887 (org-add-hook 'post-command-hook 'org-agenda-post-command-hook nil 'local)
6888 (org-add-hook 'pre-command-hook 'org-unhighlight nil 'local)
6889 (unless org-agenda-keep-modes
6890 (setq org-agenda-follow-mode org-agenda-start-with-follow-mode
6891 org-agenda-show-log nil))
6892 (easy-menu-change
6893 '("Agenda") "Agenda Files"
6894 (append
6895 (list
6896 (vector
6897 (if (get 'org-agenda-files 'org-restrict)
6898 "Restricted to single file"
6899 "Edit File List")
6900 '(org-edit-agenda-file-list)
6901 (not (get 'org-agenda-files 'org-restrict)))
6902 "--")
6903 (mapcar 'org-file-menu-entry (org-agenda-files))))
6904 (org-agenda-set-mode-name)
6905 (apply
6906 (if (fboundp 'run-mode-hooks) 'run-mode-hooks 'run-hooks)
6907 (list 'org-agenda-mode-hook)))
6908
6909 (define-key org-agenda-mode-map "\C-i" 'org-agenda-goto)
6910 (define-key org-agenda-mode-map [(tab)] 'org-agenda-goto)
6911 (define-key org-agenda-mode-map "\C-m" 'org-agenda-switch-to)
6912 (define-key org-agenda-mode-map " " 'org-agenda-show)
6913 (define-key org-agenda-mode-map "\C-c\C-t" 'org-agenda-todo)
6914 (define-key org-agenda-mode-map "o" 'delete-other-windows)
6915 (define-key org-agenda-mode-map "L" 'org-agenda-recenter)
6916 (define-key org-agenda-mode-map "t" 'org-agenda-todo)
6917 (define-key org-agenda-mode-map "a" 'org-agenda-toggle-archive-tag)
6918 (define-key org-agenda-mode-map ":" 'org-agenda-set-tags)
6919 (define-key org-agenda-mode-map "." 'org-agenda-goto-today)
6920 (define-key org-agenda-mode-map "d" 'org-agenda-day-view)
6921 (define-key org-agenda-mode-map "w" 'org-agenda-week-view)
6922 (define-key org-agenda-mode-map (org-key 'S-right) 'org-agenda-date-later)
6923 (define-key org-agenda-mode-map (org-key 'S-left) 'org-agenda-date-earlier)
6924 (define-key org-agenda-mode-map [?\C-c ?\C-x (right)] 'org-agenda-date-later)
6925 (define-key org-agenda-mode-map [?\C-c ?\C-x (left)] 'org-agenda-date-earlier)
6926
6927 (define-key org-agenda-mode-map ">" 'org-agenda-date-prompt)
6928 (define-key org-agenda-mode-map "\C-c\C-s" 'org-agenda-schedule)
6929 (define-key org-agenda-mode-map "\C-c\C-d" 'org-agenda-deadline)
6930 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
6931 (while l (define-key org-agenda-mode-map
6932 (int-to-string (pop l)) 'digit-argument)))
6933
6934 (define-key org-agenda-mode-map "f" 'org-agenda-follow-mode)
6935 (define-key org-agenda-mode-map "l" 'org-agenda-log-mode)
6936 (define-key org-agenda-mode-map "D" 'org-agenda-toggle-diary)
6937 (define-key org-agenda-mode-map "g" 'org-agenda-toggle-time-grid)
6938 (define-key org-agenda-mode-map "r" 'org-agenda-redo)
6939 (define-key org-agenda-mode-map "q" 'org-agenda-quit)
6940 (define-key org-agenda-mode-map "x" 'org-agenda-exit)
6941 (define-key org-agenda-mode-map "s" 'org-save-all-org-buffers)
6942 (define-key org-agenda-mode-map "P" 'org-agenda-show-priority)
6943 (define-key org-agenda-mode-map "T" 'org-agenda-show-tags)
6944 (define-key org-agenda-mode-map "n" 'next-line)
6945 (define-key org-agenda-mode-map "p" 'previous-line)
6946 (define-key org-agenda-mode-map "\C-n" 'org-agenda-next-date-line)
6947 (define-key org-agenda-mode-map "\C-p" 'org-agenda-previous-date-line)
6948 (define-key org-agenda-mode-map "," 'org-agenda-priority)
6949 (define-key org-agenda-mode-map "\C-c," 'org-agenda-priority)
6950 (define-key org-agenda-mode-map "i" 'org-agenda-diary-entry)
6951 (define-key org-agenda-mode-map "c" 'org-agenda-goto-calendar)
6952 (eval-after-load "calendar"
6953 '(define-key calendar-mode-map org-calendar-to-agenda-key
6954 'org-calendar-goto-agenda))
6955 (define-key org-agenda-mode-map "C" 'org-agenda-convert-date)
6956 (define-key org-agenda-mode-map "m" 'org-agenda-phases-of-moon)
6957 (define-key org-agenda-mode-map "M" 'org-agenda-phases-of-moon)
6958 (define-key org-agenda-mode-map "S" 'org-agenda-sunrise-sunset)
6959 (define-key org-agenda-mode-map "h" 'org-agenda-holidays)
6960 (define-key org-agenda-mode-map "H" 'org-agenda-holidays)
6961 (define-key org-agenda-mode-map "+" 'org-agenda-priority-up)
6962 (define-key org-agenda-mode-map "I" 'org-agenda-clock-in)
6963 (define-key org-agenda-mode-map "O" 'org-clock-out)
6964 (define-key org-agenda-mode-map "X" 'org-clock-cancel)
6965 (define-key org-agenda-mode-map "-" 'org-agenda-priority-down)
6966 (define-key org-agenda-mode-map (org-key 'S-up) 'org-agenda-priority-up)
6967 (define-key org-agenda-mode-map (org-key 'S-down) 'org-agenda-priority-down)
6968 (define-key org-agenda-mode-map [?\C-c ?\C-x (up)] 'org-agenda-priority-up)
6969 (define-key org-agenda-mode-map [?\C-c ?\C-x (down)] 'org-agenda-priority-down)
6970 (define-key org-agenda-mode-map [(right)] 'org-agenda-later)
6971 (define-key org-agenda-mode-map [(left)] 'org-agenda-earlier)
6972 (define-key org-agenda-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files)
6973 (defvar org-agenda-keymap (copy-keymap org-agenda-mode-map)
6974 "Local keymap for agenda entries from Org-mode.")
6975
6976 (define-key org-agenda-keymap
6977 (if (featurep 'xemacs) [(button2)] [(mouse-2)]) 'org-agenda-goto-mouse)
6978 (define-key org-agenda-keymap
6979 (if (featurep 'xemacs) [(button3)] [(mouse-3)]) 'org-agenda-show-mouse)
6980 (when org-agenda-mouse-1-follows-link
6981 (define-key org-agenda-keymap [follow-link] 'mouse-face))
6982 (easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu"
6983 '("Agenda"
6984 ("Agenda Files")
6985 "--"
6986 ["Show" org-agenda-show t]
6987 ["Go To (other window)" org-agenda-goto t]
6988 ["Go To (this window)" org-agenda-switch-to t]
6989 ["Follow Mode" org-agenda-follow-mode
6990 :style toggle :selected org-agenda-follow-mode :active t]
6991 "--"
6992 ["Cycle TODO" org-agenda-todo t]
6993 ("Tags"
6994 ["Show all Tags" org-agenda-show-tags t]
6995 ["Set Tags" org-agenda-set-tags t])
6996 ("Schedule"
6997 ["Schedule" org-agenda-schedule t]
6998 ["Set Deadline" org-agenda-deadline t]
6999 "--"
7000 ["Reschedule +1 day" org-agenda-date-later (org-agenda-check-type nil 'agenda 'timeline)]
7001 ["Reschedule -1 day" org-agenda-date-earlier (org-agenda-check-type nil 'agenda 'timeline)]
7002 ["Reschedule to ..." org-agenda-date-prompt (org-agenda-check-type nil 'agenda 'timeline)])
7003 ("Priority"
7004 ["Set Priority" org-agenda-priority t]
7005 ["Increase Priority" org-agenda-priority-up t]
7006 ["Decrease Priority" org-agenda-priority-down t]
7007 ["Show Priority" org-agenda-show-priority t])
7008 "--"
7009 ;; ["New agenda command" org-agenda t]
7010 ["Rebuild buffer" org-agenda-redo t]
7011 ["Save all Org-mode Buffers" org-save-all-org-buffers t]
7012 "--"
7013 ["Goto Today" org-agenda-goto-today (org-agenda-check-type nil 'agenda 'timeline)]
7014 ["Next Dates" org-agenda-later (org-agenda-check-type nil 'agenda)]
7015 ["Previous Dates" org-agenda-earlier (org-agenda-check-type nil 'agenda)]
7016 "--"
7017 ["Day View" org-agenda-day-view :active (org-agenda-check-type nil 'agenda)
7018 :style radio :selected (equal org-agenda-ndays 1)]
7019 ["Week View" org-agenda-week-view :active (org-agenda-check-type nil 'agenda)
7020 :style radio :selected (equal org-agenda-ndays 7)]
7021 "--"
7022 ["Show Logbook entries" org-agenda-log-mode
7023 :style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)]
7024 ["Include Diary" org-agenda-toggle-diary
7025 :style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)]
7026 ["Use Time Grid" org-agenda-toggle-time-grid
7027 :style toggle :selected org-agenda-use-time-grid :active (org-agenda-check-type nil 'agenda)]
7028 "--"
7029 ["New Diary Entry" org-agenda-diary-entry (org-agenda-check-type nil 'agenda 'timeline)]
7030 ("Calendar Commands"
7031 ["Goto Calendar" org-agenda-goto-calendar (org-agenda-check-type nil 'agenda 'timeline)]
7032 ["Phases of the Moon" org-agenda-phases-of-moon (org-agenda-check-type nil 'agenda 'timeline)]
7033 ["Sunrise/Sunset" org-agenda-sunrise-sunset (org-agenda-check-type nil 'agenda 'timeline)]
7034 ["Holidays" org-agenda-holidays (org-agenda-check-type nil 'agenda 'timeline)]
7035 ["Convert" org-agenda-convert-date (org-agenda-check-type nil 'agenda 'timeline)])
7036 ["Create iCalendar file" org-export-icalendar-combine-agenda-files t]
7037 "--"
7038 ["Quit" org-agenda-quit t]
7039 ["Exit and Release Buffers" org-agenda-exit t]
7040 ))
7041
7042 (defvar org-agenda-restrict nil)
7043 (defvar org-agenda-restrict-begin (make-marker))
7044 (defvar org-agenda-restrict-end (make-marker))
7045 (defvar org-agenda-last-dispatch-buffer nil)
7046
7047 ;;;###autoload
7048 (defun org-agenda (arg)
7049 "Dispatch agenda commands to collect entries to the agenda buffer.
7050 Prompts for a character to select a command. Any prefix arg will be passed
7051 on to the selected command. The default selections are:
7052 g
7053 a Call `org-agenda-list' to display the agenda for current day or week.
7054 t Call `org-todo-list' to display the global todo list.
7055 T Call `org-todo-list' to display the global todo list, select only
7056 entries with a specific TODO keyword (the user gets a prompt).
7057 m Call `org-tags-view' to display headlines with tags matching
7058 a condition (the user is prompted for the condition).
7059 M Like `m', but select only TODO entries, no ordinary headlines.
7060 l Create a timeeline for the current buffer.
7061
7062 More commands can be added by configuring the variable
7063 `org-agenda-custom-commands'. In particular, specific tags and TODO keyword
7064 searches can be pre-defined in this way.
7065
7066 If the current buffer is in Org-mode and visiting a file, you can also
7067 first press `1' to indicate that the agenda should be temporarily (until the
7068 next use of \\[org-agenda]) restricted to the current file."
7069 (interactive "P")
7070 (catch 'exit
7071 (let* ((buf (current-buffer))
7072 (bfn (buffer-file-name (buffer-base-buffer)))
7073 (restrict-ok (and bfn (org-mode-p)))
7074 (custom org-agenda-custom-commands)
7075 c entry key type match lprops)
7076 ;; Turn off restriction
7077 (put 'org-agenda-files 'org-restrict nil)
7078 (setq org-agenda-restrict nil)
7079 (move-marker org-agenda-restrict-begin nil)
7080 (move-marker org-agenda-restrict-end nil)
7081 ;; Remember where this call originated
7082 (setq org-agenda-last-dispatch-buffer (current-buffer))
7083 (save-window-excursion
7084 (delete-other-windows)
7085 (switch-to-buffer-other-window " *Agenda Commands*")
7086 (erase-buffer)
7087 (insert
7088 "Press key for an agenda command:
7089 --------------------------------
7090 a Agenda for current week or day
7091 t List of all TODO entries T Entries with special TODO kwd
7092 m Match a TAGS query M Like m, but only TODO entries
7093 L Timeline for current buffer C Configure custom agenda commands")
7094 (while (setq entry (pop custom))
7095 (setq key (car entry) type (nth 1 entry) match (nth 2 entry))
7096 (insert (format "\n%-4s%-14s: %s"
7097 key
7098 (cond
7099 ((stringp type) type)
7100 ((eq type 'tags) "Tags query")
7101 ((eq type 'todo) "TODO keyword")
7102 ((eq type 'tags-tree) "Tags tree")
7103 ((eq type 'todo-tree) "TODO kwd tree")
7104 ((eq type 'occur-tree) "Occur tree")
7105 (t "???"))
7106 (if (stringp match)
7107 (org-add-props match nil 'face 'org-warning)
7108 (format "set of %d commands" (+ -2 (length entry)))))))
7109 (if restrict-ok
7110 (insert "\n"
7111 (org-add-props "1 Restrict call to current buffer 0 Restrict call to region or subtree" nil 'face 'org-table)))
7112
7113 (goto-char (point-min))
7114 (if (fboundp 'fit-window-to-buffer) (fit-window-to-buffer))
7115 (message "Press key for agenda command%s"
7116 (if restrict-ok ", or [1] or [0] to restrict" ""))
7117 (setq c (read-char-exclusive))
7118 (message "")
7119 (when (memq c '(?L ?1 ?0))
7120 (if restrict-ok
7121 (put 'org-agenda-files 'org-restrict (list bfn))
7122 (error "Cannot restrict agenda to current buffer"))
7123 (with-current-buffer " *Agenda Commands*"
7124 (goto-char (point-max))
7125 (delete-region (point-at-bol) (point))
7126 (goto-char (point-min)))
7127 (when (eq c ?0)
7128 (setq org-agenda-restrict t)
7129 (with-current-buffer buf
7130 (if (org-region-active-p)
7131 (progn
7132 (move-marker org-agenda-restrict-begin (region-beginning))
7133 (move-marker org-agenda-restrict-end (region-end)))
7134 (save-excursion
7135 (org-back-to-heading t)
7136 (move-marker org-agenda-restrict-begin (point))
7137 (move-marker org-agenda-restrict-end
7138 (progn (org-end-of-subtree t)))))))
7139 (unless (eq c ?L)
7140 (message "Press key for agenda command%s"
7141 (if restrict-ok " (restricted to current file)" ""))
7142 (setq c (read-char-exclusive)))
7143 (message "")))
7144 (require 'calendar) ; FIXME: can we avoid this for some commands?
7145 ;; For example the todo list should not need it (but does...)
7146 (cond
7147 ((equal c ?C) (customize-variable 'org-agenda-custom-commands))
7148 ((equal c ?a) (call-interactively 'org-agenda-list))
7149 ((equal c ?t) (call-interactively 'org-todo-list))
7150 ((equal c ?T) (org-call-with-arg 'org-todo-list (or arg '(4))))
7151 ((equal c ?m) (call-interactively 'org-tags-view))
7152 ((equal c ?M) (org-call-with-arg 'org-tags-view (or arg '(4))))
7153 ((equal c ?L)
7154 (unless restrict-ok
7155 (error "This is not an Org-mode file"))
7156 (org-call-with-arg 'org-timeline arg))
7157 ((setq entry (assoc (char-to-string c) org-agenda-custom-commands))
7158 (if (symbolp (nth 1 entry))
7159 (progn
7160 (setq type (nth 1 entry) match (nth 2 entry) lprops (nth 3 entry)
7161 lprops (nth 3 entry))
7162 (cond
7163 ((eq type 'tags)
7164 (org-let lprops '(org-tags-view current-prefix-arg match)))
7165 ((eq type 'tags-todo)
7166 (org-let lprops '(org-tags-view '(4) match)))
7167 ((eq type 'todo)
7168 (org-let lprops '(org-todo-list match)))
7169 ((eq type 'tags-tree)
7170 (org-check-for-org-mode)
7171 (org-let lprops '(org-tags-sparse-tree current-prefix-arg match)))
7172 ((eq type 'todo-tree)
7173 (org-check-for-org-mode)
7174 (org-let lprops
7175 '(org-occur (concat "^" outline-regexp "[ \t]*"
7176 (regexp-quote match) "\\>"))))
7177 ((eq type 'occur-tree)
7178 (org-check-for-org-mode)
7179 (org-let lprops '(org-occur match)))
7180 (t (error "Invalid custom agenda command type %s" type))))
7181 (org-run-agenda-series (cddr entry))))
7182 (t (error "Invalid key"))))))
7183
7184 ;; FIXME: what is the meaning of WINDOW?????
7185 (defun org-run-agenda-series (series &optional window)
7186 (org-prepare-agenda)
7187 (let* ((org-agenda-multi t)
7188 (redo (list 'org-run-agenda-series (list 'quote series)))
7189 (org-select-agenda-window t)
7190 (cmds (car series))
7191 (gprops (nth 1 series))
7192 match ;; The byte compiler incorrectly complains about this. Keep it!
7193 cmd type lprops)
7194 (while (setq cmd (pop cmds))
7195 (setq type (car cmd) match (nth 1 cmd) lprops (nth 2 cmd))
7196 (cond
7197 ((eq type 'agenda)
7198 (call-interactively 'org-agenda-list))
7199 ((eq type 'alltodo)
7200 (call-interactively 'org-todo-list))
7201 ((eq type 'tags)
7202 (org-let2 gprops lprops
7203 '(org-tags-view current-prefix-arg match)))
7204 ((eq type 'tags-todo)
7205 (org-let2 gprops lprops
7206 '(org-tags-view '(4) match)))
7207 ((eq type 'todo)
7208 (org-let2 gprops lprops
7209 '(org-todo-list match)))
7210 (t (error "Invalid type in command series"))))
7211 (widen)
7212 (setq org-agenda-redo-command redo)
7213 (goto-char (point-min)))
7214 (org-finalize-agenda))
7215
7216 ;;;###autoload
7217 (defmacro org-batch-agenda (cmd-key &rest parameters)
7218 "Run an agenda command in batch mode, send result to STDOUT.
7219 CMD-KEY is a string that is also a key in `org-agenda-custom-commands'.
7220 Paramters are alternating variable names and values that will be bound
7221 before running the agenda command."
7222 (let (pars)
7223 (while parameters
7224 (push (list (pop parameters) (if parameters (pop parameters))) pars))
7225 (flet ((read-char-exclusive () (string-to-char cmd-key)))
7226 (eval (list 'let (nreverse pars) '(org-agenda nil))))
7227 (set-buffer "*Org Agenda*")
7228 (princ (buffer-string))))
7229
7230 (defmacro org-no-read-only (&rest body)
7231 "Inhibit read-only for BODY."
7232 `(let ((inhibit-read-only t)) ,@body))
7233
7234 (defun org-check-for-org-mode ()
7235 "Make sure current buffer is in org-mode. Error if not."
7236 (or (org-mode-p)
7237 (error "Cannot execute org-mode agenda command on buffer in %s."
7238 major-mode)))
7239
7240 (defun org-fit-agenda-window ()
7241 "Fit the window to the buffer size."
7242 (and org-fit-agenda-window
7243 (memq org-agenda-window-setup '(reorganize-frame))
7244 (fboundp 'fit-window-to-buffer)
7245 (fit-window-to-buffer nil (/ (* (frame-height) 3) 4)
7246 (/ (frame-height) 2))))
7247
7248 (defun org-agenda-files (&optional unrestricted)
7249 "Get the list of agenda files.
7250 Optional UNRESTRICTED means return the full list even if a restriction
7251 is currently in place."
7252 (cond
7253 ((and (not unrestricted) (get 'org-agenda-files 'org-restrict)))
7254 ((stringp org-agenda-files) (org-read-agenda-file-list))
7255 ((listp org-agenda-files) org-agenda-files)
7256 (t (error "Invalid value of `org-agenda-files'"))))
7257
7258 (defvar org-window-configuration)
7259
7260 (defun org-edit-agenda-file-list ()
7261 "Edit the list of agenda files.
7262 Depending on setup, this either uses customize to edit the variable
7263 `org-agenda-files', or it visits the file that is holding the list. In the
7264 latter case, the buffer is set up in a way that saving it automatically kills
7265 the buffer and restores the previous window configuration."
7266 (interactive)
7267 (if (stringp org-agenda-files)
7268 (let ((cw (current-window-configuration)))
7269 (find-file org-agenda-files)
7270 (org-set-local 'org-window-configuration cw)
7271 (org-add-hook 'after-save-hook
7272 (lambda ()
7273 (set-window-configuration
7274 (prog1 org-window-configuration
7275 (kill-buffer (current-buffer))))
7276 (org-install-agenda-files-menu)
7277 (message "New agenda file list installed"))
7278 nil 'local)
7279 (message (substitute-command-keys
7280 "Edit list and finish with \\[save-buffer]")))
7281 (customize-variable 'org-agenda-files)))
7282
7283 (defun org-store-new-agenda-file-list (list)
7284 "Set new value for the agenda file list and save it correcly."
7285 (if (stringp org-agenda-files)
7286 (let ((f org-agenda-files) b)
7287 (while (setq b (find-buffer-visiting f)) (kill-buffer b))
7288 (with-temp-file f
7289 (insert (mapconcat 'identity list "\n") "\n")))
7290 (let ((org-mode-hook nil) (default-major-mode 'fundamental-mode))
7291 (setq org-agenda-files list)
7292 (customize-save-variable 'org-agenda-files org-agenda-files))))
7293
7294 (defun org-read-agenda-file-list ()
7295 "Read the list of agenda files from a file."
7296 (when (stringp org-agenda-files)
7297 (with-temp-buffer
7298 (insert-file-contents org-agenda-files)
7299 (org-split-string (buffer-string) "[ \t\r\n]*?[\r\n][ \t\r\n]*"))))
7300
7301 (defvar org-agenda-markers nil
7302 "List of all currently active markers created by `org-agenda'.")
7303 (defvar org-agenda-last-marker-time (time-to-seconds (current-time))
7304 "Creation time of the last agenda marker.")
7305
7306 (defun org-agenda-new-marker (&optional pos)
7307 "Return a new agenda marker.
7308 Org-mode keeps a list of these markers and resets them when they are
7309 no longer in use."
7310 (let ((m (copy-marker (or pos (point)))))
7311 (setq org-agenda-last-marker-time (time-to-seconds (current-time)))
7312 (push m org-agenda-markers)
7313 m))
7314
7315 (defun org-agenda-maybe-reset-markers (&optional force)
7316 "Reset markers created by `org-agenda'. But only if they are old enough."
7317 (if (or (and force (not org-agenda-multi))
7318 (> (- (time-to-seconds (current-time))
7319 org-agenda-last-marker-time)
7320 5))
7321 (while org-agenda-markers
7322 (move-marker (pop org-agenda-markers) nil))))
7323
7324 (defvar org-agenda-new-buffers nil
7325 "Buffers created to visit agenda files.")
7326
7327 (defun org-get-agenda-file-buffer (file)
7328 "Get a buffer visiting FILE. If the buffer needs to be created, add
7329 it to the list of buffers which might be released later."
7330 (let ((buf (find-buffer-visiting file)))
7331 (if buf
7332 buf ; just return it
7333 ;; Make a new buffer and remember it
7334 (setq buf (find-file-noselect file))
7335 (if buf (push buf org-agenda-new-buffers))
7336 buf)))
7337
7338 (defun org-release-buffers (blist)
7339 "Release all buffers in list, asking the user for confirmation when needed.
7340 When a buffer is unmodified, it is just killed. When modified, it is saved
7341 \(if the user agrees) and then killed."
7342 (let (buf file)
7343 (while (setq buf (pop blist))
7344 (setq file (buffer-file-name buf))
7345 (when (and (buffer-modified-p buf)
7346 file
7347 (y-or-n-p (format "Save file %s? " file)))
7348 (with-current-buffer buf (save-buffer)))
7349 (kill-buffer buf))))
7350
7351 (defun org-timeline (&optional include-all)
7352 "Show a time-sorted view of the entries in the current org file.
7353 Only entries with a time stamp of today or later will be listed. With
7354 \\[universal-argument] prefix, all unfinished TODO items will also be shown,
7355 under the current date.
7356 If the buffer contains an active region, only check the region for
7357 dates."
7358 (interactive "P")
7359 (require 'calendar)
7360 (org-compile-prefix-format 'timeline)
7361 (org-set-sorting-strategy 'timeline)
7362 (let* ((dopast t)
7363 (dotodo include-all)
7364 (doclosed org-agenda-show-log)
7365 (entry buffer-file-name)
7366 (date (calendar-current-date))
7367 (win (selected-window))
7368 (pos1 (point))
7369 (beg (if (org-region-active-p) (region-beginning) (point-min)))
7370 (end (if (org-region-active-p) (region-end) (point-max)))
7371 (day-numbers (org-get-all-dates beg end 'no-ranges
7372 t doclosed ; always include today
7373 org-timeline-show-empty-dates))
7374 (today (time-to-days (current-time)))
7375 (past t)
7376 args
7377 s e rtn d emptyp)
7378 (setq org-agenda-redo-command
7379 (list 'progn
7380 (list 'switch-to-buffer-other-window (current-buffer))
7381 (list 'org-timeline (list 'quote include-all))))
7382 (if (not dopast)
7383 ;; Remove past dates from the list of dates.
7384 (setq day-numbers (delq nil (mapcar (lambda(x)
7385 (if (>= x today) x nil))
7386 day-numbers))))
7387 (org-prepare-agenda)
7388 (if doclosed (push :closed args))
7389 (push :timestamp args)
7390 (if dotodo (push :todo args))
7391 (while (setq d (pop day-numbers))
7392 (if (and (listp d) (eq (car d) :omitted))
7393 (progn
7394 (setq s (point))
7395 (insert (format "\n[... %d empty days omitted]\n\n" (cdr d)))
7396 (put-text-property s (1- (point)) 'face 'org-level-3))
7397 (if (listp d) (setq d (car d) emptyp t) (setq emptyp nil))
7398 (if (and (>= d today)
7399 dopast
7400 past)
7401 (progn
7402 (setq past nil)
7403 (insert (make-string 79 ?-) "\n")))
7404 (setq date (calendar-gregorian-from-absolute d))
7405 (setq s (point))
7406 (setq rtn (and (not emptyp)
7407 (apply 'org-agenda-get-day-entries
7408 entry date args)))
7409 (if (or rtn (equal d today) org-timeline-show-empty-dates)
7410 (progn
7411 (insert (calendar-day-name date) " "
7412 (number-to-string (extract-calendar-day date)) " "
7413 (calendar-month-name (extract-calendar-month date)) " "
7414 (number-to-string (extract-calendar-year date)) "\n")
7415 (put-text-property s (1- (point)) 'face
7416 'org-level-3)
7417 (if (equal d today)
7418 (put-text-property s (1- (point)) 'org-today t))
7419 (and rtn (insert (org-finalize-agenda-entries rtn) "\n"))
7420 (put-text-property s (1- (point)) 'day d)))))
7421 (goto-char (point-min))
7422 (goto-char (or (text-property-any (point-min) (point-max) 'org-today t)
7423 (point-min)))
7424 (add-text-properties (point-min) (point-max) '(org-agenda-type timeline))
7425 (org-finalize-agenda)
7426 (setq buffer-read-only t)
7427 (when (not org-select-agenda-window)
7428 (select-window win)
7429 (goto-char pos1))))
7430
7431 (defvar org-agenda-overriding-arguments nil) ; dynamically scoped parameter
7432 (defvar org-agenda-last-arguments nil
7433 "The arguments of the previous call to org-agenda")
7434
7435 ;;;###autoload
7436 (defun org-agenda-list (&optional include-all start-day ndays)
7437 "Produce a weekly view from all files in variable `org-agenda-files'.
7438 The view will be for the current week, but from the overview buffer you
7439 will be able to go to other weeks.
7440 With one \\[universal-argument] prefix argument INCLUDE-ALL, all unfinished TODO items will
7441 also be shown, under the current date.
7442 With two \\[universal-argument] prefix argument INCLUDE-ALL, all TODO entries marked DONE
7443 on the days are also shown. See the variable `org-log-done' for how
7444 to turn on logging.
7445 START-DAY defaults to TODAY, or to the most recent match for the weekday
7446 given in `org-agenda-start-on-weekday'.
7447 NDAYS defaults to `org-agenda-ndays'."
7448 (interactive "P")
7449 (if org-agenda-overriding-arguments
7450 (setq include-all (car org-agenda-overriding-arguments)
7451 start-day (nth 1 org-agenda-overriding-arguments)
7452 ndays (nth 2 org-agenda-overriding-arguments)))
7453 (setq org-agenda-last-arguments (list include-all start-day ndays))
7454 (org-compile-prefix-format 'agenda)
7455 (org-set-sorting-strategy 'agenda)
7456 (require 'calendar)
7457 (let* ((org-agenda-start-on-weekday
7458 (if (or (equal ndays 1)
7459 (and (null ndays) (equal 1 org-agenda-ndays)))
7460 nil org-agenda-start-on-weekday))
7461 (thefiles (org-agenda-files))
7462 (files thefiles)
7463 (win (selected-window))
7464 (today (time-to-days (current-time)))
7465 (sd (or start-day today))
7466 (start (if (or (null org-agenda-start-on-weekday)
7467 (< org-agenda-ndays 7))
7468 sd
7469 (let* ((nt (calendar-day-of-week
7470 (calendar-gregorian-from-absolute sd)))
7471 (n1 org-agenda-start-on-weekday)
7472 (d (- nt n1)))
7473 (- sd (+ (if (< d 0) 7 0) d)))))
7474 (day-numbers (list start))
7475 ;FIXME (inhibit-redisplay t)
7476 s e rtn rtnall file date d start-pos end-pos todayp nd)
7477 (setq org-agenda-redo-command
7478 (list 'org-agenda-list (list 'quote include-all) start-day ndays))
7479 ;; Make the list of days
7480 (setq ndays (or ndays org-agenda-ndays)
7481 nd ndays)
7482 (while (> ndays 1)
7483 (push (1+ (car day-numbers)) day-numbers)
7484 (setq ndays (1- ndays)))
7485 (setq day-numbers (nreverse day-numbers))
7486 (org-prepare-agenda)
7487 (org-set-local 'starting-day (car day-numbers))
7488 (org-set-local 'include-all-loc include-all)
7489 (when (and (or include-all org-agenda-include-all-todo)
7490 (member today day-numbers))
7491 (setq files thefiles
7492 rtnall nil)
7493 (while (setq file (pop files))
7494 (catch 'nextfile
7495 (org-check-agenda-file file)
7496 (setq date (calendar-gregorian-from-absolute today)
7497 rtn (org-agenda-get-day-entries
7498 file date :todo))
7499 (setq rtnall (append rtnall rtn))))
7500 (when rtnall
7501 (insert "ALL CURRENTLY OPEN TODO ITEMS:\n")
7502 (add-text-properties (point-min) (1- (point))
7503 (list 'face 'org-level-3))
7504 (insert (org-finalize-agenda-entries rtnall) "\n")))
7505 (setq s (point))
7506 (insert (if (= nd 7) "Week-" "Day-") "agenda:\n")
7507 (add-text-properties s (1- (point)) (list 'face 'org-level-3))
7508 (while (setq d (pop day-numbers))
7509 (setq date (calendar-gregorian-from-absolute d)
7510 s (point))
7511 (if (or (setq todayp (= d today))
7512 (and (not start-pos) (= d sd)))
7513 (setq start-pos (point))
7514 (if (and start-pos (not end-pos))
7515 (setq end-pos (point))))
7516 (setq files thefiles
7517 rtnall nil)
7518 (while (setq file (pop files))
7519 (catch 'nextfile
7520 (org-check-agenda-file file)
7521 (if org-agenda-show-log
7522 (setq rtn (org-agenda-get-day-entries
7523 file date
7524 :deadline :scheduled :timestamp :closed))
7525 (setq rtn (org-agenda-get-day-entries
7526 file date
7527 :deadline :scheduled :timestamp)))
7528 (setq rtnall (append rtnall rtn))))
7529 (if org-agenda-include-diary
7530 (progn
7531 (require 'diary-lib)
7532 (setq rtn (org-get-entries-from-diary date))
7533 (setq rtnall (append rtnall rtn))))
7534 (if (or rtnall org-agenda-show-all-dates)
7535 (progn
7536 (insert (format "%-9s %2d %s %4d\n"
7537 (calendar-day-name date)
7538 (extract-calendar-day date)
7539 (calendar-month-name (extract-calendar-month date))
7540 (extract-calendar-year date)))
7541 (put-text-property s (1- (point)) 'face
7542 'org-level-3)
7543 (if todayp (put-text-property s (1- (point)) 'org-today t))
7544
7545 (if rtnall (insert
7546 (org-finalize-agenda-entries
7547 (org-agenda-add-time-grid-maybe
7548 rtnall nd todayp))
7549 "\n"))
7550 (put-text-property s (1- (point)) 'day d))))
7551 (goto-char (point-min))
7552 (org-fit-agenda-window)
7553 (unless (and (pos-visible-in-window-p (point-min))
7554 (pos-visible-in-window-p (point-max)))
7555 (goto-char (1- (point-max)))
7556 (recenter -1)
7557 (if (not (pos-visible-in-window-p (or start-pos 1)))
7558 (progn
7559 (goto-char (or start-pos 1))
7560 (recenter 1))))
7561 (goto-char (or start-pos 1))
7562 (add-text-properties (point-min) (point-max) '(org-agenda-type agenda))
7563 (org-finalize-agenda)
7564 (setq buffer-read-only t)
7565 (if (not org-select-agenda-window) (select-window win))
7566 (message "")))
7567
7568 (defvar org-select-this-todo-keyword nil)
7569
7570 ;;;###autoload
7571 (defun org-todo-list (arg)
7572 "Show all TODO entries from all agenda file in a single list.
7573 The prefix arg can be used to select a specific TODO keyword and limit
7574 the list to these. When using \\[universal-argument], you will be prompted
7575 for a keyword. A numeric prefix directly selects the Nth keyword in
7576 `org-todo-keywords'."
7577 (interactive "P")
7578 (org-compile-prefix-format 'todo)
7579 (org-set-sorting-strategy 'todo)
7580 (let* ((today (time-to-days (current-time)))
7581 (date (calendar-gregorian-from-absolute today))
7582 (win (selected-window))
7583 (kwds org-todo-keywords)
7584 (completion-ignore-case t)
7585 (org-select-this-todo-keyword
7586 (if (stringp arg) arg
7587 (and arg (integerp arg) (> arg 0)
7588 (nth (1- arg) org-todo-keywords))))
7589 rtn rtnall files file pos)
7590 (when (equal arg '(4))
7591 (setq org-select-this-todo-keyword
7592 (completing-read "Keyword: " (mapcar 'list org-todo-keywords)
7593 nil t)))
7594 (and (equal 0 arg) (setq org-select-this-todo-keyword nil))
7595 (org-prepare-agenda)
7596 (org-set-local 'last-arg arg)
7597 (org-set-local 'org-todo-keywords kwds)
7598 (setq org-agenda-redo-command
7599 '(org-todo-list (or current-prefix-arg last-arg)))
7600 (setq files (org-agenda-files)
7601 rtnall nil)
7602 (while (setq file (pop files))
7603 (catch 'nextfile
7604 (org-check-agenda-file file)
7605 (setq rtn (org-agenda-get-day-entries file date :todo))
7606 (setq rtnall (append rtnall rtn))))
7607 (insert "Global list of TODO items of type: ")
7608 (add-text-properties (point-min) (1- (point))
7609 (list 'face 'org-level-3))
7610 (setq pos (point))
7611 (insert (or org-select-this-todo-keyword "ALL") "\n")
7612 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
7613 (setq pos (point))
7614 (unless org-agenda-multi
7615 (insert
7616 "Available with `N r': (0)ALL "
7617 (let ((n 0))
7618 (mapconcat (lambda (x)
7619 (format "(%d)%s" (setq n (1+ n)) x))
7620 org-todo-keywords " "))
7621 "\n"))
7622 (add-text-properties pos (1- (point)) (list 'face 'org-level-3))
7623 (when rtnall
7624 (insert (org-finalize-agenda-entries rtnall) "\n"))
7625 (goto-char (point-min))
7626 (org-fit-agenda-window)
7627 (add-text-properties (point-min) (point-max) '(org-agenda-type todo))
7628 (org-finalize-agenda)
7629 (setq buffer-read-only t)
7630 (if (not org-select-agenda-window) (select-window win))))
7631
7632 (defun org-check-agenda-file (file)
7633 "Make sure FILE exists. If not, ask user what to do."
7634 (when (not (file-exists-p file))
7635 (message "non-existent file %s. [R]emove from list or [A]bort?"
7636 (abbreviate-file-name file))
7637 (let ((r (downcase (read-char-exclusive))))
7638 (cond
7639 ((equal r ?r)
7640 (org-remove-file file)
7641 (throw 'nextfile t))
7642 (t (error "Abort"))))))
7643
7644 (defun org-agenda-check-type (error &rest types)
7645 "Check if agenda buffer is of allowed type.
7646 If ERROR is non-nil, throw an error, otherwise just return nil."
7647 (if (memq org-agenda-type types)
7648 t
7649 (if error
7650 (error "Not allowed in %s-type agenda buffers" org-agenda-type)
7651 nil)))
7652
7653 (defun org-agenda-quit ()
7654 "Exit agenda by removing the window or the buffer."
7655 (interactive)
7656 (let ((buf (current-buffer)))
7657 (if (not (one-window-p)) (delete-window))
7658 (kill-buffer buf)
7659 (org-agenda-maybe-reset-markers 'force))
7660 ;; Maybe restore the pre-agenda window configuration.
7661 (and org-agenda-restore-windows-after-quit
7662 (not (eq org-agenda-window-setup 'other-frame))
7663 org-pre-agenda-window-conf
7664 (set-window-configuration org-pre-agenda-window-conf)))
7665
7666 (defun org-agenda-exit ()
7667 "Exit agenda by removing the window or the buffer.
7668 Also kill all Org-mode buffers which have been loaded by `org-agenda'.
7669 Org-mode buffers visited directly by the user will not be touched."
7670 (interactive)
7671 (org-release-buffers org-agenda-new-buffers)
7672 (setq org-agenda-new-buffers nil)
7673 (org-agenda-quit))
7674
7675 (defun org-save-all-org-buffers ()
7676 "Save all Org-mode buffers without user confirmation."
7677 (interactive)
7678 (message "Saving all Org-mode buffers...")
7679 (save-some-buffers t 'org-mode-p)
7680 (message "Saving all Org-mode buffers... done"))
7681
7682 (defun org-agenda-redo ()
7683 "Rebuild Agenda.
7684 When this is the global TODO list, a prefix argument will be interpreted."
7685 (interactive)
7686 (let* ((org-agenda-keep-modes t)
7687 (line (org-current-line))
7688 (window-line (- line (org-current-line (window-start)))))
7689 (message "Rebuilding agenda buffer...")
7690 (eval org-agenda-redo-command)
7691 (message "Rebuilding agenda buffer...done")
7692 (goto-line line)
7693 (recenter window-line)))
7694
7695 (defun org-agenda-goto-today ()
7696 "Go to today."
7697 (interactive)
7698 (org-agenda-check-type t 'timeline 'agenda)
7699 (let ((tdpos (text-property-any (point-min) (point-max) 'org-today t)))
7700 (cond
7701 (tdpos (goto-char tdpos))
7702 ((eq org-agenda-type 'agenda)
7703 (let ((org-agenda-overriding-arguments org-agenda-last-arguments))
7704 (setf (nth 1 org-agenda-overriding-arguments) nil)
7705 (org-agenda-redo)
7706 (org-agenda-find-today-or-agenda)))
7707 (t (error "Cannot find today")))))
7708
7709 (defun org-agenda-find-today-or-agenda ()
7710 (goto-char
7711 (or (text-property-any (point-min) (point-max) 'org-today t)
7712 (text-property-any (point-min) (point-max) 'org-agenda-type 'agenda)
7713 (point-min))))
7714
7715 (defun org-agenda-later (arg)
7716 "Go forward in time by `org-agenda-ndays' days.
7717 With prefix ARG, go forward that many times `org-agenda-ndays'."
7718 (interactive "p")
7719 (org-agenda-check-type t 'agenda)
7720 (let ((org-agenda-overriding-arguments
7721 (list (car org-agenda-last-arguments)
7722 (+ starting-day (* arg org-agenda-ndays))
7723 nil t)))
7724 (org-agenda-redo)
7725 (org-agenda-find-today-or-agenda)))
7726
7727 (defun org-agenda-earlier (arg)
7728 "Go back in time by `org-agenda-ndays' days.
7729 With prefix ARG, go back that many times `org-agenda-ndays'."
7730 (interactive "p")
7731 (org-agenda-check-type t 'agenda)
7732 (let ((org-agenda-overriding-arguments
7733 (list (car org-agenda-last-arguments)
7734 (- starting-day (* arg org-agenda-ndays))
7735 nil t)))
7736 (org-agenda-redo)
7737 (org-agenda-find-today-or-agenda)))
7738
7739 (defun org-agenda-week-view ()
7740 "Switch to weekly view for agenda."
7741 (interactive)
7742 (org-agenda-check-type t 'agenda)
7743 (if (= org-agenda-ndays 7)
7744 (error "This is already the week view"))
7745 (setq org-agenda-ndays 7)
7746 (let ((org-agenda-overriding-arguments
7747 (list (car org-agenda-last-arguments)
7748 (or (get-text-property (point) 'day)
7749 starting-day)
7750 nil t)))
7751 (org-agenda-redo)
7752 (org-agenda-find-today-or-agenda))
7753 (org-agenda-set-mode-name)
7754 (message "Switched to week view"))
7755
7756 (defun org-agenda-day-view ()
7757 "Switch to daily view for agenda."
7758 (interactive)
7759 (org-agenda-check-type t 'agenda)
7760 (if (= org-agenda-ndays 1)
7761 (error "This is already the day view"))
7762 (setq org-agenda-ndays 1)
7763 (let ((org-agenda-overriding-arguments
7764 (list (car org-agenda-last-arguments)
7765 (or (get-text-property (point) 'day)
7766 starting-day)
7767 nil t)))
7768 (org-agenda-redo)
7769 (org-agenda-find-today-or-agenda))
7770 (org-agenda-set-mode-name)
7771 (message "Switched to day view"))
7772
7773 (defun org-agenda-next-date-line (&optional arg)
7774 "Jump to the next line indicating a date in agenda buffer."
7775 (interactive "p")
7776 (org-agenda-check-type t 'agenda 'timeline)
7777 (beginning-of-line 1)
7778 (if (looking-at "^\\S-") (forward-char 1))
7779 (if (not (re-search-forward "^\\S-" nil t arg))
7780 (progn
7781 (backward-char 1)
7782 (error "No next date after this line in this buffer")))
7783 (goto-char (match-beginning 0)))
7784
7785 (defun org-agenda-previous-date-line (&optional arg)
7786 "Jump to the previous line indicating a date in agenda buffer."
7787 (interactive "p")
7788 (org-agenda-check-type t 'agenda 'timeline)
7789 (beginning-of-line 1)
7790 (if (not (re-search-backward "^\\S-" nil t arg))
7791 (error "No previous date before this line in this buffer")))
7792
7793 ;; Initialize the highlight
7794 (defvar org-hl (org-make-overlay 1 1))
7795 (org-overlay-put org-hl 'face 'highlight)
7796
7797 (defun org-highlight (begin end &optional buffer)
7798 "Highlight a region with overlay."
7799 (funcall (if (featurep 'xemacs) 'set-extent-endpoints 'move-overlay)
7800 org-hl begin end (or buffer (current-buffer))))
7801
7802 (defun org-unhighlight ()
7803 "Detach overlay INDEX."
7804 (funcall (if (featurep 'xemacs) 'detach-extent 'delete-overlay) org-hl))
7805
7806
7807 (defun org-agenda-follow-mode ()
7808 "Toggle follow mode in an agenda buffer."
7809 (interactive)
7810 (setq org-agenda-follow-mode (not org-agenda-follow-mode))
7811 (org-agenda-set-mode-name)
7812 (message "Follow mode is %s"
7813 (if org-agenda-follow-mode "on" "off")))
7814
7815 (defun org-agenda-log-mode ()
7816 "Toggle log mode in an agenda buffer."
7817 (interactive)
7818 (org-agenda-check-type t 'agenda 'timeline)
7819 (setq org-agenda-show-log (not org-agenda-show-log))
7820 (org-agenda-set-mode-name)
7821 (org-agenda-redo)
7822 (message "Log mode is %s"
7823 (if org-agenda-show-log "on" "off")))
7824
7825 (defun org-agenda-toggle-diary ()
7826 "Toggle diary inclusion in an agenda buffer."
7827 (interactive)
7828 (org-agenda-check-type t 'agenda)
7829 (setq org-agenda-include-diary (not org-agenda-include-diary))
7830 (org-agenda-redo)
7831 (org-agenda-set-mode-name)
7832 (message "Diary inclusion turned %s"
7833 (if org-agenda-include-diary "on" "off")))
7834
7835 (defun org-agenda-toggle-time-grid ()
7836 "Toggle time grid in an agenda buffer."
7837 (interactive)
7838 (org-agenda-check-type t 'agenda)
7839 (setq org-agenda-use-time-grid (not org-agenda-use-time-grid))
7840 (org-agenda-redo)
7841 (org-agenda-set-mode-name)
7842 (message "Time-grid turned %s"
7843 (if org-agenda-use-time-grid "on" "off")))
7844
7845 (defun org-agenda-set-mode-name ()
7846 "Set the mode name to indicate all the small mode settings."
7847 (setq mode-name
7848 (concat "Org-Agenda"
7849 (if (equal org-agenda-ndays 1) " Day" "")
7850 (if (equal org-agenda-ndays 7) " Week" "")
7851 (if org-agenda-follow-mode " Follow" "")
7852 (if org-agenda-include-diary " Diary" "")
7853 (if org-agenda-use-time-grid " Grid" "")
7854 (if org-agenda-show-log " Log" "")))
7855 (force-mode-line-update))
7856
7857 (defun org-agenda-post-command-hook ()
7858 (and (eolp) (not (bolp)) (backward-char 1))
7859 (setq org-agenda-type (get-text-property (point) 'org-agenda-type))
7860 (if (and org-agenda-follow-mode
7861 (get-text-property (point) 'org-marker))
7862 (org-agenda-show)))
7863
7864 (defvar org-disable-agenda-to-diary nil) ;Dynamically-scoped param.
7865
7866 (defun org-get-entries-from-diary (date)
7867 "Get the (Emacs Calendar) diary entries for DATE."
7868 (let* ((fancy-diary-buffer "*temporary-fancy-diary-buffer*")
7869 (diary-display-hook '(fancy-diary-display))
7870 (list-diary-entries-hook
7871 (cons 'org-diary-default-entry list-diary-entries-hook))
7872 (diary-file-name-prefix-function nil) ; turn this feature off
7873 (diary-modify-entry-list-string-function 'org-modify-diary-entry-string)
7874 entries
7875 (org-disable-agenda-to-diary t))
7876 (save-excursion
7877 (save-window-excursion
7878 (list-diary-entries date 1))) ;; Keep this name for now, compatibility
7879 (if (not (get-buffer fancy-diary-buffer))
7880 (setq entries nil)
7881 (with-current-buffer fancy-diary-buffer
7882 (setq buffer-read-only nil)
7883 (if (= (point-max) 1)
7884 ;; No entries
7885 (setq entries nil)
7886 ;; Omit the date and other unnecessary stuff
7887 (org-agenda-cleanup-fancy-diary)
7888 ;; Add prefix to each line and extend the text properties
7889 (if (= (point-max) 1)
7890 (setq entries nil)
7891 (setq entries (buffer-substring (point-min) (- (point-max) 1)))))
7892 (set-buffer-modified-p nil)
7893 (kill-buffer fancy-diary-buffer)))
7894 (when entries
7895 (setq entries (org-split-string entries "\n"))
7896 (setq entries
7897 (mapcar
7898 (lambda (x)
7899 (setq x (org-format-agenda-item "" x "Diary" nil 'time))
7900 ;; Extend the text properties to the beginning of the line
7901 (org-add-props x (text-properties-at (1- (length x)) x)))
7902 entries)))))
7903
7904 (defun org-agenda-cleanup-fancy-diary ()
7905 "Remove unwanted stuff in buffer created by `fancy-diary-display'.
7906 This gets rid of the date, the underline under the date, and
7907 the dummy entry installed by `org-mode' to ensure non-empty diary for each
7908 date. It also removes lines that contain only whitespace."
7909 (goto-char (point-min))
7910 (if (looking-at ".*?:[ \t]*")
7911 (progn
7912 (replace-match "")
7913 (re-search-forward "\n=+$" nil t)
7914 (replace-match "")
7915 (while (re-search-backward "^ +\n?" nil t) (replace-match "")))
7916 (re-search-forward "\n=+$" nil t)
7917 (delete-region (point-min) (min (point-max) (1+ (match-end 0)))))
7918 (goto-char (point-min))
7919 (while (re-search-forward "^ +\n" nil t)
7920 (replace-match ""))
7921 (goto-char (point-min))
7922 (if (re-search-forward "^Org-mode dummy\n?" nil t)
7923 (replace-match "")))
7924
7925 ;; Make sure entries from the diary have the right text properties.
7926 (eval-after-load "diary-lib"
7927 '(if (boundp 'diary-modify-entry-list-string-function)
7928 ;; We can rely on the hook, nothing to do
7929 nil
7930 ;; Hook not avaiable, must use advice to make this work
7931 (defadvice add-to-diary-list (before org-mark-diary-entry activate)
7932 "Make the position visible."
7933 (if (and org-disable-agenda-to-diary ;; called from org-agenda
7934 (stringp string)
7935 buffer-file-name)
7936 (setq string (org-modify-diary-entry-string string))))))
7937
7938 (defun org-modify-diary-entry-string (string)
7939 "Add text properties to string, allowing org-mode to act on it."
7940 (org-add-props string nil
7941 'mouse-face 'highlight
7942 'keymap org-agenda-keymap
7943 'help-echo (format "mouse-2 or RET jump to diary file %s"
7944 (abbreviate-file-name buffer-file-name))
7945 'org-agenda-diary-link t
7946 'org-marker (org-agenda-new-marker (point-at-bol))))
7947
7948 (defun org-diary-default-entry ()
7949 "Add a dummy entry to the diary.
7950 Needed to avoid empty dates which mess up holiday display."
7951 ;; Catch the error if dealing with the new add-to-diary-alist
7952 (when org-disable-agenda-to-diary
7953 (condition-case nil
7954 (add-to-diary-list original-date "Org-mode dummy" "")
7955 (error
7956 (add-to-diary-list original-date "Org-mode dummy" "" nil)))))
7957
7958 ;;;###autoload
7959 (defun org-cycle-agenda-files ()
7960 "Cycle through the files in `org-agenda-files'.
7961 If the current buffer visits an agenda file, find the next one in the list.
7962 If the current buffer does not, find the first agenda file."
7963 (interactive)
7964 (let* ((fs (org-agenda-files t))
7965 (files (append fs (list (car fs))))
7966 (tcf (if buffer-file-name (file-truename buffer-file-name)))
7967 file)
7968 (unless files (error "No agenda files"))
7969 (catch 'exit
7970 (while (setq file (pop files))
7971 (if (equal (file-truename file) tcf)
7972 (when (car files)
7973 (find-file (car files))
7974 (throw 'exit t))))
7975 (find-file (car fs)))))
7976
7977 (defun org-agenda-file-to-end ()
7978 "Move/add the current file to the end of the agenda file list.
7979 If the file is not present in the list, it is appended to the list. If it is
7980 present, it is moved there."
7981 (interactive)
7982 (org-agenda-file-to-front 'to-end))
7983
7984 (defun org-agenda-file-to-front (&optional to-end)
7985 "Move/add the current file to the top of the agenda file list.
7986 If the file is not present in the list, it is added to the front. If it is
7987 present, it is moved there. With optional argument TO-END, add/move to the
7988 end of the list."
7989 (interactive "P")
7990 (let ((file-alist (mapcar (lambda (x)
7991 (cons (file-truename x) x))
7992 (org-agenda-files t)))
7993 (ctf (file-truename buffer-file-name))
7994 x had)
7995 (setq x (assoc ctf file-alist) had x)
7996
7997 (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name))))
7998 (if to-end
7999 (setq file-alist (append (delq x file-alist) (list x)))
8000 (setq file-alist (cons x (delq x file-alist))))
8001 (org-store-new-agenda-file-list (mapcar 'cdr file-alist))
8002 (org-install-agenda-files-menu)
8003 (message "File %s to %s of agenda file list"
8004 (if had "moved" "added") (if to-end "end" "front"))))
8005
8006 (defun org-remove-file (&optional file)
8007 "Remove current file from the list of files in variable `org-agenda-files'.
8008 These are the files which are being checked for agenda entries.
8009 Optional argument FILE means, use this file instead of the current."
8010 (interactive)
8011 (let* ((file (or file buffer-file-name))
8012 (true-file (file-truename file))
8013 (afile (abbreviate-file-name file))
8014 (files (delq nil (mapcar
8015 (lambda (x)
8016 (if (equal true-file
8017 (file-truename x))
8018 nil x))
8019 (org-agenda-files t)))))
8020 (if (not (= (length files) (length (org-agenda-files t))))
8021 (progn
8022 (org-store-new-agenda-file-list files)
8023 (org-install-agenda-files-menu)
8024 (message "Removed file: %s" afile))
8025 (message "File was not in list: %s" afile))))
8026
8027 (defun org-file-menu-entry (file)
8028 (vector file (list 'find-file file) t))
8029
8030 (defun org-get-all-dates (beg end &optional no-ranges force-today inactive empty)
8031 "Return a list of all relevant day numbers from BEG to END buffer positions.
8032 If NO-RANGES is non-nil, include only the start and end dates of a range,
8033 not every single day in the range. If FORCE-TODAY is non-nil, make
8034 sure that TODAY is included in the list. If INACTIVE is non-nil, also
8035 inactive time stamps (those in square brackets) are included.
8036 When EMPTY is non-nil, also include days without any entries."
8037 (let ((re (if inactive org-ts-regexp-both org-ts-regexp))
8038 dates dates1 date day day1 day2 ts1 ts2)
8039 (if force-today
8040 (setq dates (list (time-to-days (current-time)))))
8041 (save-excursion
8042 (goto-char beg)
8043 (while (re-search-forward re end t)
8044 (setq day (time-to-days (org-time-string-to-time
8045 (substring (match-string 1) 0 10))))
8046 (or (memq day dates) (push day dates)))
8047 (unless no-ranges
8048 (goto-char beg)
8049 (while (re-search-forward org-tr-regexp end t)
8050 (setq ts1 (substring (match-string 1) 0 10)
8051 ts2 (substring (match-string 2) 0 10)
8052 day1 (time-to-days (org-time-string-to-time ts1))
8053 day2 (time-to-days (org-time-string-to-time ts2)))
8054 (while (< (setq day1 (1+ day1)) day2)
8055 (or (memq day1 dates) (push day1 dates)))))
8056 (setq dates (sort dates '<))
8057 (when empty
8058 (while (setq day (pop dates))
8059 (setq day2 (car dates))
8060 (push day dates1)
8061 (when (and day2 empty)
8062 (if (or (eq empty t)
8063 (and (numberp empty) (<= (- day2 day) empty)))
8064 (while (< (setq day (1+ day)) day2)
8065 (push (list day) dates1))
8066 (push (cons :omitted (- day2 day)) dates1))))
8067 (setq dates (nreverse dates1)))
8068 dates)))
8069
8070 ;;;###autoload
8071 (defun org-diary (&rest args)
8072 "Return diary information from org-files.
8073 This function can be used in a \"sexp\" diary entry in the Emacs calendar.
8074 It accesses org files and extracts information from those files to be
8075 listed in the diary. The function accepts arguments specifying what
8076 items should be listed. The following arguments are allowed:
8077
8078 :timestamp List the headlines of items containing a date stamp or
8079 date range matching the selected date. Deadlines will
8080 also be listed, on the expiration day.
8081
8082 :deadline List any deadlines past due, or due within
8083 `org-deadline-warning-days'. The listing occurs only
8084 in the diary for *today*, not at any other date. If
8085 an entry is marked DONE, it is no longer listed.
8086
8087 :scheduled List all items which are scheduled for the given date.
8088 The diary for *today* also contains items which were
8089 scheduled earlier and are not yet marked DONE.
8090
8091 :todo List all TODO items from the org-file. This may be a
8092 long list - so this is not turned on by default.
8093 Like deadlines, these entries only show up in the
8094 diary for *today*, not at any other date.
8095
8096 The call in the diary file should look like this:
8097
8098 &%%(org-diary) ~/path/to/some/orgfile.org
8099
8100 Use a separate line for each org file to check. Or, if you omit the file name,
8101 all files listed in `org-agenda-files' will be checked automatically:
8102
8103 &%%(org-diary)
8104
8105 If you don't give any arguments (as in the example above), the default
8106 arguments (:deadline :scheduled :timestamp) are used. So the example above may
8107 also be written as
8108
8109 &%%(org-diary :deadline :timestamp :scheduled)
8110
8111 The function expects the lisp variables `entry' and `date' to be provided
8112 by the caller, because this is how the calendar works. Don't use this
8113 function from a program - use `org-agenda-get-day-entries' instead."
8114 (org-agenda-maybe-reset-markers)
8115 (org-compile-prefix-format 'agenda)
8116 (org-set-sorting-strategy 'agenda)
8117 (setq args (or args '(:deadline :scheduled :timestamp)))
8118 (let* ((files (if (and entry (stringp entry) (string-match "\\S-" entry))
8119 (list entry)
8120 (org-agenda-files t)))
8121 file rtn results)
8122 ;; If this is called during org-agenda, don't return any entries to
8123 ;; the calendar. Org Agenda will list these entries itself.
8124 (if org-disable-agenda-to-diary (setq files nil))
8125 (while (setq file (pop files))
8126 (setq rtn (apply 'org-agenda-get-day-entries file date args))
8127 (setq results (append results rtn)))
8128 (if results
8129 (concat (org-finalize-agenda-entries results) "\n"))))
8130 (defvar org-category-table nil)
8131 (defun org-get-category-table ()
8132 "Get the table of categories and positions in current buffer."
8133 (let (tbl)
8134 (save-excursion
8135 (goto-char (point-min))
8136 (while (re-search-forward "\\(^\\|\r\\)#\\+CATEGORY:[ \t]*\\(.*\\)" nil t)
8137 (push (cons (point) (org-trim (match-string 2))) tbl)))
8138 tbl))
8139 (defun org-get-category (&optional pos)
8140 "Get the category applying to position POS."
8141 (if (not org-category-table)
8142 (cond
8143 ((null org-category)
8144 (setq org-category
8145 (if buffer-file-name
8146 (file-name-sans-extension
8147 (file-name-nondirectory buffer-file-name))
8148 "???")))
8149 ((symbolp org-category) (symbol-name org-category))
8150 (t org-category))
8151 (let ((tbl org-category-table)
8152 (pos (or pos (point))))
8153 (while (and tbl (> (caar tbl) pos))
8154 (pop tbl))
8155 (or (cdar tbl) (cdr (nth (1- (length org-category-table))
8156 org-category-table))))))
8157
8158 (defun org-agenda-get-day-entries (file date &rest args)
8159 "Does the work for `org-diary' and `org-agenda'.
8160 FILE is the path to a file to be checked for entries. DATE is date like
8161 the one returned by `calendar-current-date'. ARGS are symbols indicating
8162 which kind of entries should be extracted. For details about these, see
8163 the documentation of `org-diary'."
8164 (setq args (or args '(:deadline :scheduled :timestamp)))
8165 (let* ((org-startup-with-deadline-check nil)
8166 (org-startup-folded nil)
8167 (org-startup-align-all-tables nil)
8168 (buffer (if (file-exists-p file)
8169 (org-get-agenda-file-buffer file)
8170 (error "No such file %s" file)))
8171 arg results rtn)
8172 (if (not buffer)
8173 ;; If file does not exist, make sure an error message ends up in diary
8174 (list (format "ORG-AGENDA-ERROR: No such org-file %s" file))
8175 (with-current-buffer buffer
8176 (unless (org-mode-p)
8177 (error "Agenda file %s is not in `org-mode'" file))
8178 (setq org-category-table (org-get-category-table))
8179 (let ((case-fold-search nil))
8180 (save-excursion
8181 (save-restriction
8182 (if org-agenda-restrict
8183 (narrow-to-region org-agenda-restrict-begin
8184 org-agenda-restrict-end)
8185 (widen))
8186 ;; The way we repeatedly append to `results' makes it O(n^2) :-(
8187 (while (setq arg (pop args))
8188 (cond
8189 ((and (eq arg :todo)
8190 (equal date (calendar-current-date)))
8191 (setq rtn (org-agenda-get-todos))
8192 (setq results (append results rtn)))
8193 ((eq arg :timestamp)
8194 (setq rtn (org-agenda-get-blocks))
8195 (setq results (append results rtn))
8196 (setq rtn (org-agenda-get-timestamps))
8197 (setq results (append results rtn)))
8198 ((eq arg :scheduled)
8199 (setq rtn (org-agenda-get-scheduled))
8200 (setq results (append results rtn)))
8201 ((eq arg :closed)
8202 (setq rtn (org-agenda-get-closed))
8203 (setq results (append results rtn)))
8204 ((and (eq arg :deadline)
8205 (equal date (calendar-current-date)))
8206 (setq rtn (org-agenda-get-deadlines))
8207 (setq results (append results rtn))))))))
8208 results))))
8209
8210 (defun org-entry-is-done-p ()
8211 "Is the current entry marked DONE?"
8212 (save-excursion
8213 (and (re-search-backward "[\r\n]\\*" nil t)
8214 (looking-at org-nl-done-regexp))))
8215
8216 (defun org-at-date-range-p (&optional inactive-ok)
8217 "Is the cursor inside a date range?"
8218 (interactive)
8219 (save-excursion
8220 (catch 'exit
8221 (let ((pos (point)))
8222 (skip-chars-backward "^[<\r\n")
8223 (skip-chars-backward "<[")
8224 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
8225 (>= (match-end 0) pos)
8226 (throw 'exit t))
8227 (skip-chars-backward "^<[\r\n")
8228 (skip-chars-backward "<[")
8229 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
8230 (>= (match-end 0) pos)
8231 (throw 'exit t)))
8232 nil)))
8233
8234 (defun org-agenda-get-todos ()
8235 "Return the TODO information for agenda display."
8236 (let* ((props (list 'face nil
8237 'done-face 'org-done
8238 'org-not-done-regexp org-not-done-regexp
8239 'mouse-face 'highlight
8240 'keymap org-agenda-keymap
8241 'help-echo
8242 (format "mouse-2 or RET jump to org file %s"
8243 (abbreviate-file-name buffer-file-name))))
8244 (regexp (concat "[\n\r]\\*+ *\\("
8245 (if org-select-this-todo-keyword
8246 (concat "\\<\\(" org-select-this-todo-keyword
8247 "\\)\\>")
8248 org-not-done-regexp)
8249 "[^\n\r]*\\)"))
8250 (deadline-re (concat ".*\\(\n[^*].*\\)?" org-deadline-time-regexp))
8251 (sched-re (concat ".*\\(\n[^*].*\\)?" org-scheduled-time-regexp))
8252 ; FIXME why was this wriong? (sched-re (concat ".*\n?.*?" org-scheduled-time-regexp))
8253 marker priority category tags
8254 ee txt)
8255 (goto-char (point-min))
8256 (while (re-search-forward regexp nil t)
8257 (catch :skip
8258 (save-match-data
8259 (beginning-of-line)
8260 (when (or (and org-agenda-todo-ignore-scheduled
8261 (looking-at sched-re))
8262 (and org-agenda-todo-ignore-deadlines
8263 (looking-at deadline-re)
8264 (org-deadline-close (match-string 2))))
8265
8266 ;; FIXME: the following test also happens below, but we need it here
8267 (or org-agenda-todo-list-sublevels (org-end-of-subtree 'invisible))
8268 (throw :skip nil)))
8269 (org-agenda-skip)
8270 (goto-char (match-beginning 1))
8271 (setq marker (org-agenda-new-marker (1+ (match-beginning 0)))
8272 category (org-get-category)
8273 tags (org-get-tags-at (point))
8274 txt (org-format-agenda-item "" (match-string 1) category tags)
8275 priority
8276 (+ (org-get-priority txt)
8277 (if org-todo-kwd-priority-p
8278 (- org-todo-kwd-max-priority -2
8279 (length
8280 (member (match-string 2) org-todo-keywords)))
8281 1)))
8282 (org-add-props txt props
8283 'org-marker marker 'org-hd-marker marker
8284 'priority priority 'category category)
8285 (push txt ee)
8286 (if org-agenda-todo-list-sublevels
8287 (goto-char (match-end 1))
8288 (org-end-of-subtree 'invisible))))
8289 (nreverse ee)))
8290
8291 (defconst org-agenda-no-heading-message
8292 "No heading for this item in buffer or region.")
8293
8294 (defun org-agenda-get-timestamps ()
8295 "Return the date stamp information for agenda display."
8296 (let* ((props (list 'face nil
8297 'org-not-done-regexp org-not-done-regexp
8298 'mouse-face 'highlight
8299 'keymap org-agenda-keymap
8300 'help-echo
8301 (format "mouse-2 or RET jump to org file %s"
8302 (abbreviate-file-name buffer-file-name))))
8303 (regexp (regexp-quote
8304 (substring
8305 (format-time-string
8306 (car org-time-stamp-formats)
8307 (apply 'encode-time ; DATE bound by calendar
8308 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
8309 0 11)))
8310 marker hdmarker deadlinep scheduledp donep tmp priority category
8311 ee txt timestr tags)
8312 (goto-char (point-min))
8313 (while (re-search-forward regexp nil t)
8314 (catch :skip
8315 (and (save-match-data (org-at-date-range-p)) (throw :skip nil))
8316 (org-agenda-skip)
8317 (setq marker (org-agenda-new-marker (match-beginning 0))
8318 category (org-get-category (match-beginning 0))
8319 tmp (buffer-substring (max (point-min)
8320 (- (match-beginning 0)
8321 org-ds-keyword-length))
8322 (match-beginning 0))
8323 timestr (buffer-substring (match-beginning 0) (point-at-eol))
8324 deadlinep (string-match org-deadline-regexp tmp)
8325 scheduledp (string-match org-scheduled-regexp tmp)
8326 donep (org-entry-is-done-p))
8327 (if (string-match ">" timestr)
8328 ;; substring should only run to end of time stamp
8329 (setq timestr (substring timestr 0 (match-end 0))))
8330 (save-excursion
8331 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
8332 (progn
8333 (goto-char (match-end 1))
8334 (setq hdmarker (org-agenda-new-marker)
8335 tags (org-get-tags-at))
8336 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
8337 (setq txt (org-format-agenda-item
8338 (format "%s%s"
8339 (if deadlinep "Deadline: " "")
8340 (if scheduledp "Scheduled: " ""))
8341 (match-string 1) category tags timestr)))
8342 (setq txt org-agenda-no-heading-message))
8343 (setq priority (org-get-priority txt))
8344 (org-add-props txt props
8345 'org-marker marker 'org-hd-marker hdmarker)
8346 (if deadlinep
8347 (org-add-props txt nil
8348 'face (if donep 'org-done 'org-warning)
8349 'undone-face 'org-warning 'done-face 'org-done
8350 'category category 'priority (+ 100 priority))
8351 (if scheduledp
8352 (org-add-props txt nil
8353 'face 'org-scheduled-today
8354 'undone-face 'org-scheduled-today 'done-face 'org-done
8355 'category category 'priority (+ 99 priority))
8356 (org-add-props txt nil 'priority priority 'category category)))
8357 (push txt ee))
8358 (outline-next-heading)))
8359 (nreverse ee)))
8360
8361 (defun org-agenda-get-closed ()
8362 "Return the logged TODO entries for agenda display."
8363 (let* ((props (list 'mouse-face 'highlight
8364 'org-not-done-regexp org-not-done-regexp
8365 'keymap org-agenda-keymap
8366 'help-echo
8367 (format "mouse-2 or RET jump to org file %s"
8368 (abbreviate-file-name buffer-file-name))))
8369 (regexp (concat
8370 "\\<\\(" org-closed-string "\\|" org-clock-string "\\) *\\["
8371 (regexp-quote
8372 (substring
8373 (format-time-string
8374 (car org-time-stamp-formats)
8375 (apply 'encode-time ; DATE bound by calendar
8376 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
8377 1 11))))
8378 marker hdmarker priority category tags closedp
8379 ee txt timestr)
8380 (goto-char (point-min))
8381 (while (re-search-forward regexp nil t)
8382 (catch :skip
8383 (org-agenda-skip)
8384 (setq marker (org-agenda-new-marker (match-beginning 0))
8385 closedp (equal (match-string 1) org-closed-string)
8386 category (org-get-category (match-beginning 0))
8387 timestr (buffer-substring (match-beginning 0) (point-at-eol))
8388 ;; donep (org-entry-is-done-p)
8389 )
8390 (if (string-match "\\]" timestr)
8391 ;; substring should only run to end of time stamp
8392 (setq timestr (substring timestr 0 (match-end 0))))
8393 (save-excursion
8394 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
8395 (progn
8396 (goto-char (match-end 1))
8397 (setq hdmarker (org-agenda-new-marker)
8398 tags (org-get-tags-at))
8399 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
8400 (setq txt (org-format-agenda-item
8401 (if closedp "Closed: " "Clocked: ")
8402 (match-string 1) category tags timestr)))
8403 (setq txt org-agenda-no-heading-message))
8404 (setq priority 100000)
8405 (org-add-props txt props
8406 'org-marker marker 'org-hd-marker hdmarker 'face 'org-done
8407 'priority priority 'category category
8408 'undone-face 'org-warning 'done-face 'org-done)
8409 (push txt ee))
8410 (outline-next-heading)))
8411 (nreverse ee)))
8412
8413 (defun org-agenda-get-deadlines ()
8414 "Return the deadline information for agenda display."
8415 (let* ((wdays org-deadline-warning-days)
8416 (props (list 'mouse-face 'highlight
8417 'org-not-done-regexp org-not-done-regexp
8418 'keymap org-agenda-keymap
8419 'help-echo
8420 (format "mouse-2 or RET jump to org file %s"
8421 (abbreviate-file-name buffer-file-name))))
8422 (regexp org-deadline-time-regexp)
8423 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
8424 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
8425 d2 diff pos pos1 category tags
8426 ee txt head face)
8427 (goto-char (point-min))
8428 (while (re-search-forward regexp nil t)
8429 (catch :skip
8430 (org-agenda-skip)
8431 (setq pos (1- (match-beginning 1))
8432 d2 (time-to-days
8433 (org-time-string-to-time (match-string 1)))
8434 diff (- d2 d1))
8435 ;; When to show a deadline in the calendar:
8436 ;; If the expiration is within wdays warning time.
8437 ;; Past-due deadlines are only shown on the current date
8438 (if (and (< diff wdays) todayp (not (= diff 0)))
8439 (save-excursion
8440 (setq category (org-get-category))
8441 (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t)
8442 (progn
8443 (goto-char (match-end 0))
8444 (setq pos1 (match-end 1))
8445 (setq tags (org-get-tags-at pos1))
8446 (setq head (buffer-substring-no-properties
8447 (point)
8448 (progn (skip-chars-forward "^\r\n")
8449 (point))))
8450 (if (string-match org-looking-at-done-regexp head)
8451 (setq txt nil)
8452 (setq txt (org-format-agenda-item
8453 (format "In %3d d.: " diff) head category tags))))
8454 (setq txt org-agenda-no-heading-message))
8455 (when txt
8456 (setq face (cond ((<= diff 0) 'org-warning)
8457 ((<= diff 5) 'org-upcoming-deadline)
8458 (t nil)))
8459 (org-add-props txt props
8460 'org-marker (org-agenda-new-marker pos)
8461 'org-hd-marker (org-agenda-new-marker pos1)
8462 'priority (+ (- 10 diff) (org-get-priority txt))
8463 'category category
8464 'face face 'undone-face face 'done-face 'org-done)
8465 (push txt ee))))))
8466 ee))
8467
8468 (defun org-agenda-get-scheduled ()
8469 "Return the scheduled information for agenda display."
8470 (let* ((props (list 'face 'org-scheduled-previously
8471 'org-not-done-regexp org-not-done-regexp
8472 'undone-face 'org-scheduled-previously
8473 'done-face 'org-done
8474 'mouse-face 'highlight
8475 'keymap org-agenda-keymap
8476 'help-echo
8477 (format "mouse-2 or RET jump to org file %s"
8478 (abbreviate-file-name buffer-file-name))))
8479 (regexp org-scheduled-time-regexp)
8480 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
8481 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
8482 d2 diff pos pos1 category tags
8483 ee txt head)
8484 (goto-char (point-min))
8485 (while (re-search-forward regexp nil t)
8486 (catch :skip
8487 (org-agenda-skip)
8488 (setq pos (1- (match-beginning 1))
8489 d2 (time-to-days
8490 (org-time-string-to-time (match-string 1)))
8491 diff (- d2 d1))
8492 ;; When to show a scheduled item in the calendar:
8493 ;; If it is on or past the date.
8494 (if (and (< diff 0) todayp)
8495 (save-excursion
8496 (setq category (org-get-category))
8497 (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t)
8498 (progn
8499 (goto-char (match-end 0))
8500 (setq pos1 (match-end 1))
8501 (setq tags (org-get-tags-at))
8502 (setq head (buffer-substring-no-properties
8503 (point)
8504 (progn (skip-chars-forward "^\r\n") (point))))
8505 (if (string-match org-looking-at-done-regexp head)
8506 (setq txt nil)
8507 (setq txt (org-format-agenda-item
8508 (format "Sched.%2dx: " (- 1 diff)) head
8509 category tags))))
8510 (setq txt org-agenda-no-heading-message))
8511 (when txt
8512 (org-add-props txt props
8513 'org-marker (org-agenda-new-marker pos)
8514 'org-hd-marker (org-agenda-new-marker pos1)
8515 'priority (+ (- 5 diff) (org-get-priority txt))
8516 'category category)
8517 (push txt ee))))))
8518 ee))
8519
8520 (defun org-agenda-get-blocks ()
8521 "Return the date-range information for agenda display."
8522 (let* ((props (list 'face nil
8523 'org-not-done-regexp org-not-done-regexp
8524 'mouse-face 'highlight
8525 'keymap org-agenda-keymap
8526 'help-echo
8527 (format "mouse-2 or RET jump to org file %s"
8528 (abbreviate-file-name buffer-file-name))))
8529 (regexp org-tr-regexp)
8530 (d0 (calendar-absolute-from-gregorian date))
8531 marker hdmarker ee txt d1 d2 s1 s2 timestr category tags pos)
8532 (goto-char (point-min))
8533 (while (re-search-forward regexp nil t)
8534 (catch :skip
8535 (org-agenda-skip)
8536 (setq pos (point))
8537 (setq timestr (match-string 0)
8538 s1 (match-string 1)
8539 s2 (match-string 2)
8540 d1 (time-to-days (org-time-string-to-time s1))
8541 d2 (time-to-days (org-time-string-to-time s2)))
8542 (if (and (> (- d0 d1) -1) (> (- d2 d0) -1))
8543 ;; Only allow days between the limits, because the normal
8544 ;; date stamps will catch the limits.
8545 (save-excursion
8546 (setq marker (org-agenda-new-marker (point)))
8547 (setq category (org-get-category))
8548 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
8549 (progn
8550 (setq hdmarker (org-agenda-new-marker (match-end 1)))
8551 (goto-char (match-end 1))
8552 (setq tags (org-get-tags-at))
8553 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
8554 (setq txt (org-format-agenda-item
8555 (format (if (= d1 d2) "" "(%d/%d): ")
8556 (1+ (- d0 d1)) (1+ (- d2 d1)))
8557 (match-string 1) category tags
8558 (if (= d0 d1) timestr))))
8559 (setq txt org-agenda-no-heading-message))
8560 (org-add-props txt props
8561 'org-marker marker 'org-hd-marker hdmarker
8562 'priority (org-get-priority txt) 'category category)
8563 (push txt ee)))
8564 (goto-char pos)))
8565 ;; Sort the entries by expiration date.
8566 (nreverse ee)))
8567
8568 (defconst org-plain-time-of-day-regexp
8569 (concat
8570 "\\(\\<[012]?[0-9]"
8571 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
8572 "\\(--?"
8573 "\\(\\<[012]?[0-9]"
8574 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
8575 "\\)?")
8576 "Regular expression to match a plain time or time range.
8577 Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
8578 groups carry important information:
8579 0 the full match
8580 1 the first time, range or not
8581 8 the second time, if it is a range.")
8582
8583 (defconst org-stamp-time-of-day-regexp
8584 (concat
8585 "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +\\sw+ +\\)"
8586 "\\([012][0-9]:[0-5][0-9]\\)>"
8587 "\\(--?"
8588 "<\\1\\([012][0-9]:[0-5][0-9]\\)>\\)?")
8589 "Regular expression to match a timestamp time or time range.
8590 After a match, the following groups carry important information:
8591 0 the full match
8592 1 date plus weekday, for backreferencing to make sure both times on same day
8593 2 the first time, range or not
8594 4 the second time, if it is a range.")
8595
8596 (defvar org-prefix-has-time nil
8597 "A flag, set by `org-compile-prefix-format'.
8598 The flag is set if the currently compiled format contains a `%t'.")
8599 (defvar org-prefix-has-tag nil
8600 "A flag, set by `org-compile-prefix-format'.
8601 The flag is set if the currently compiled format contains a `%T'.")
8602
8603 (defun org-format-agenda-item (extra txt &optional category tags dotime
8604 noprefix)
8605 "Format TXT to be inserted into the agenda buffer.
8606 In particular, it adds the prefix and corresponding text properties. EXTRA
8607 must be a string and replaces the `%s' specifier in the prefix format.
8608 CATEGORY (string, symbol or nil) may be used to overrule the default
8609 category taken from local variable or file name. It will replace the `%c'
8610 specifier in the format. DOTIME, when non-nil, indicates that a
8611 time-of-day should be extracted from TXT for sorting of this entry, and for
8612 the `%t' specifier in the format. When DOTIME is a string, this string is
8613 searched for a time before TXT is. NOPREFIX is a flag and indicates that
8614 only the correctly processes TXT should be returned - this is used by
8615 `org-agenda-change-all-lines'. TAGS can be the tags of the headline."
8616 (save-match-data
8617 ;; Diary entries sometimes have extra whitespace at the beginning
8618 (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt)))
8619 (let* ((category (or category
8620 org-category
8621 (if buffer-file-name
8622 (file-name-sans-extension
8623 (file-name-nondirectory buffer-file-name))
8624 "")))
8625 (tag (if tags (nth (1- (length tags)) tags) ""))
8626 time ;; needed for the eval of the prefix format
8627 (ts (if dotime (concat (if (stringp dotime) dotime "") txt)))
8628 (time-of-day (and dotime (org-get-time-of-day ts)))
8629 stamp plain s0 s1 s2 rtn)
8630 (when (and dotime time-of-day org-prefix-has-time)
8631 ;; Extract starting and ending time and move them to prefix
8632 (when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts))
8633 (setq plain (string-match org-plain-time-of-day-regexp ts)))
8634 (setq s0 (match-string 0 ts)
8635 s1 (match-string (if plain 1 2) ts)
8636 s2 (match-string (if plain 8 4) ts))
8637
8638 ;; If the times are in TXT (not in DOTIMES), and the prefix will list
8639 ;; them, we might want to remove them there to avoid duplication.
8640 ;; The user can turn this off with a variable.
8641 (if (and org-agenda-remove-times-when-in-prefix (or stamp plain)
8642 (string-match (concat (regexp-quote s0) " *") txt)
8643 (if (eq org-agenda-remove-times-when-in-prefix 'beg)
8644 (= (match-beginning 0) 0)
8645 t))
8646 (setq txt (replace-match "" nil nil txt))))
8647 ;; Normalize the time(s) to 24 hour
8648 (if s1 (setq s1 (org-get-time-of-day s1 'string t)))
8649 (if s2 (setq s2 (org-get-time-of-day s2 'string t))))
8650
8651 (when (string-match "\\([ \t]+\\)\\(:[a-zA-Z_@0-9:]+:\\)[ \t]*$" txt)
8652 ;; Tags are in the string
8653 (if (or (eq org-agenda-remove-tags-when-in-prefix t)
8654 (and org-agenda-remove-tags-when-in-prefix
8655 org-prefix-has-tag))
8656 (setq txt (replace-match "" t t txt))
8657 (setq txt (replace-match
8658 (concat (make-string (max (- 50 (length txt)) 1) ?\ )
8659 (match-string 2 txt))
8660 t t txt))))
8661
8662 ;; Create the final string
8663 (if noprefix
8664 (setq rtn txt)
8665 ;; Prepare the variables needed in the eval of the compiled format
8666 (setq time (cond (s2 (concat s1 "-" s2))
8667 (s1 (concat s1 "......"))
8668 (t ""))
8669 extra (or extra "")
8670 category (if (symbolp category) (symbol-name category) category))
8671 ;; Evaluate the compiled format
8672 (setq rtn (concat (eval org-prefix-format-compiled) txt)))
8673
8674 ;; And finally add the text properties
8675 (org-add-props rtn nil
8676 'category (downcase category) 'tags tags
8677 'prefix-length (- (length rtn) (length txt))
8678 'time-of-day time-of-day
8679 'dotime dotime))))
8680
8681 (defvar org-agenda-sorting-strategy)
8682 (defvar org-agenda-sorting-strategy-selected nil)
8683
8684 (defun org-agenda-add-time-grid-maybe (list ndays todayp)
8685 (catch 'exit
8686 (cond ((not org-agenda-use-time-grid) (throw 'exit list))
8687 ((and todayp (member 'today (car org-agenda-time-grid))))
8688 ((and (= ndays 1) (member 'daily (car org-agenda-time-grid))))
8689 ((member 'weekly (car org-agenda-time-grid)))
8690 (t (throw 'exit list)))
8691 (let* ((have (delq nil (mapcar
8692 (lambda (x) (get-text-property 1 'time-of-day x))
8693 list)))
8694 (string (nth 1 org-agenda-time-grid))
8695 (gridtimes (nth 2 org-agenda-time-grid))
8696 (req (car org-agenda-time-grid))
8697 (remove (member 'remove-match req))
8698 new time)
8699 (if (and (member 'require-timed req) (not have))
8700 ;; don't show empty grid
8701 (throw 'exit list))
8702 (while (setq time (pop gridtimes))
8703 (unless (and remove (member time have))
8704 (setq time (int-to-string time))
8705 (push (org-format-agenda-item
8706 nil string "" nil
8707 (concat (substring time 0 -2) ":" (substring time -2)))
8708 new)
8709 (put-text-property
8710 1 (length (car new)) 'face 'org-time-grid (car new))))
8711 (if (member 'time-up org-agenda-sorting-strategy-selected)
8712 (append new list)
8713 (append list new)))))
8714
8715 (defun org-compile-prefix-format (key)
8716 "Compile the prefix format into a Lisp form that can be evaluated.
8717 The resulting form is returned and stored in the variable
8718 `org-prefix-format-compiled'."
8719 (setq org-prefix-has-time nil org-prefix-has-tag nil)
8720 (let ((s (cond
8721 ((stringp org-agenda-prefix-format)
8722 org-agenda-prefix-format)
8723 ((assq key org-agenda-prefix-format)
8724 (cdr (assq key org-agenda-prefix-format)))
8725 (t " %-12:c%?-12t% s")))
8726 (start 0)
8727 varform vars var e c f opt)
8728 (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([cts]\\)"
8729 s start)
8730 (setq var (cdr (assoc (match-string 4 s)
8731 '(("c" . category) ("t" . time) ("s" . extra)
8732 ("T" . tag))))
8733 c (or (match-string 3 s) "")
8734 opt (match-beginning 1)
8735 start (1+ (match-beginning 0)))
8736 (if (equal var 'time) (setq org-prefix-has-time t))
8737 (if (equal var 'tag) (setq org-prefix-has-tag t))
8738 (setq f (concat "%" (match-string 2 s) "s"))
8739 (if opt
8740 (setq varform
8741 `(if (equal "" ,var)
8742 ""
8743 (format ,f (if (equal "" ,var) "" (concat ,var ,c)))))
8744 (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c)))))
8745 (setq s (replace-match "%s" t nil s))
8746 (push varform vars))
8747 (setq vars (nreverse vars))
8748 (setq org-prefix-format-compiled `(format ,s ,@vars))))
8749
8750 (defun org-set-sorting-strategy (key)
8751 (if (symbolp (car org-agenda-sorting-strategy))
8752 ;; the old format
8753 (setq org-agenda-sorting-strategy-selected org-agenda-sorting-strategy)
8754 (setq org-agenda-sorting-strategy-selected
8755 (or (cdr (assq key org-agenda-sorting-strategy))
8756 (cdr (assq 'agenda org-agenda-sorting-strategy))
8757 '(time-up category-keep priority-down)))))
8758
8759 (defun org-get-time-of-day (s &optional string mod24)
8760 "Check string S for a time of day.
8761 If found, return it as a military time number between 0 and 2400.
8762 If not found, return nil.
8763 The optional STRING argument forces conversion into a 5 character wide string
8764 HH:MM."
8765 (save-match-data
8766 (when
8767 (or
8768 (string-match
8769 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)\\([AaPp][Mm]\\)?\\> *" s)
8770 (string-match
8771 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\([AaPp][Mm]\\)\\> *" s))
8772 (let* ((h (string-to-number (match-string 1 s)))
8773 (m (if (match-end 3) (string-to-number (match-string 3 s)) 0))
8774 (ampm (if (match-end 4) (downcase (match-string 4 s))))
8775 (am-p (equal ampm "am"))
8776 (h1 (cond ((not ampm) h)
8777 ((= h 12) (if am-p 0 12))
8778 (t (+ h (if am-p 0 12)))))
8779 (h2 (if (and string mod24 (not (and (= m 0) (= h1 24))))
8780 (mod h1 24) h1))
8781 (t0 (+ (* 100 h2) m))
8782 (t1 (concat (if (>= h1 24) "+" " ")
8783 (if (< t0 100) "0" "")
8784 (if (< t0 10) "0" "")
8785 (int-to-string t0))))
8786 (if string (concat (substring t1 -4 -2) ":" (substring t1 -2)) t0)))))
8787
8788 (defun org-finalize-agenda-entries (list &optional nosort)
8789 "Sort and concatenate the agenda items."
8790 (setq list (mapcar 'org-agenda-highlight-todo list))
8791 (if nosort
8792 list
8793 (mapconcat 'identity (sort list 'org-entries-lessp) "\n")))
8794
8795 (defun org-agenda-highlight-todo (x)
8796 (let (re pl)
8797 (if (eq x 'line)
8798 (save-excursion
8799 (beginning-of-line 1)
8800 (setq re (get-text-property (point) 'org-not-done-regexp))
8801 (goto-char (+ (point) (or (get-text-property (point) 'prefix-length) 0)))
8802 (and (looking-at (concat "[ \t]*\\.*" re))
8803 (add-text-properties (match-beginning 0) (match-end 0)
8804 '(face org-todo))))
8805 (setq re (concat (get-text-property 0 'org-not-done-regexp x))
8806 pl (get-text-property 0 'prefix-length x))
8807 (and re (equal (string-match (concat "\\(\\.*\\)" re) x (or pl 0)) pl)
8808 (add-text-properties (or (match-end 1) (match-end 0)) (match-end 0)
8809 '(face org-todo) x))
8810 x)))
8811
8812 (defsubst org-cmp-priority (a b)
8813 "Compare the priorities of string A and B."
8814 (let ((pa (or (get-text-property 1 'priority a) 0))
8815 (pb (or (get-text-property 1 'priority b) 0)))
8816 (cond ((> pa pb) +1)
8817 ((< pa pb) -1)
8818 (t nil))))
8819
8820 (defsubst org-cmp-category (a b)
8821 "Compare the string values of categories of strings A and B."
8822 (let ((ca (or (get-text-property 1 'category a) ""))
8823 (cb (or (get-text-property 1 'category b) "")))
8824 (cond ((string-lessp ca cb) -1)
8825 ((string-lessp cb ca) +1)
8826 (t nil))))
8827
8828 (defsubst org-cmp-tag (a b)
8829 "Compare the string values of categories of strings A and B."
8830 (let ((ta (car (last (get-text-property 1 'tags a))))
8831 (tb (car (last (get-text-property 1 'tags b)))))
8832 (cond ((not ta) +1)
8833 ((not tb) -1)
8834 ((string-lessp ta tb) -1)
8835 ((string-lessp tb ta) +1)
8836 (t nil))))
8837
8838 (defsubst org-cmp-time (a b)
8839 "Compare the time-of-day values of strings A and B."
8840 (let* ((def (if org-sort-agenda-notime-is-late 9901 -1))
8841 (ta (or (get-text-property 1 'time-of-day a) def))
8842 (tb (or (get-text-property 1 'time-of-day b) def)))
8843 (cond ((< ta tb) -1)
8844 ((< tb ta) +1)
8845 (t nil))))
8846
8847 (defun org-entries-lessp (a b)
8848 "Predicate for sorting agenda entries."
8849 ;; The following variables will be used when the form is evaluated.
8850 (let* ((time-up (org-cmp-time a b))
8851 (time-down (if time-up (- time-up) nil))
8852 (priority-up (org-cmp-priority a b))
8853 (priority-down (if priority-up (- priority-up) nil))
8854 (category-up (org-cmp-category a b))
8855 (category-down (if category-up (- category-up) nil))
8856 (category-keep (if category-up +1 nil))
8857 (tag-up (org-cmp-tag a b))
8858 (tag-down (if tag-up (- tag-up) nil)))
8859 (cdr (assoc
8860 (eval (cons 'or org-agenda-sorting-strategy-selected))
8861 '((-1 . t) (1 . nil) (nil . nil))))))
8862
8863 (defun org-agenda-show-priority ()
8864 "Show the priority of the current item.
8865 This priority is composed of the main priority given with the [#A] cookies,
8866 and by additional input from the age of a schedules or deadline entry."
8867 (interactive)
8868 (let* ((pri (get-text-property (point-at-bol) 'priority)))
8869 (message "Priority is %d" (if pri pri -1000))))
8870
8871 (defun org-agenda-show-tags ()
8872 "Show the tags applicable to the current item."
8873 (interactive)
8874 (let* ((tags (get-text-property (point-at-bol) 'tags)))
8875 (if tags
8876 (message "Tags are :%s:"
8877 (org-no-properties (mapconcat 'identity tags ":")))
8878 (message "No tags associated with this line"))))
8879
8880 (defun org-agenda-goto (&optional highlight)
8881 "Go to the Org-mode file which contains the item at point."
8882 (interactive)
8883 (let* ((marker (or (get-text-property (point) 'org-marker)
8884 (org-agenda-error)))
8885 (buffer (marker-buffer marker))
8886 (pos (marker-position marker)))
8887 (switch-to-buffer-other-window buffer)
8888 (widen)
8889 (goto-char pos)
8890 (when (org-mode-p)
8891 (org-show-context 'agenda)
8892 (save-excursion
8893 (and (outline-next-heading)
8894 (org-flag-heading nil)))) ; show the next heading
8895 (and highlight (org-highlight (point-at-bol) (point-at-eol)))))
8896
8897 (defun org-agenda-switch-to (&optional delete-other-windows)
8898 "Go to the Org-mode file which contains the item at point."
8899 (interactive)
8900 (let* ((marker (or (get-text-property (point) 'org-marker)
8901 (org-agenda-error)))
8902 (buffer (marker-buffer marker))
8903 (pos (marker-position marker)))
8904 (switch-to-buffer buffer)
8905 (and delete-other-windows (delete-other-windows))
8906 (widen)
8907 (goto-char pos)
8908 (when (org-mode-p)
8909 (org-show-context 'agenda)
8910 (save-excursion
8911 (and (outline-next-heading)
8912 (org-flag-heading nil)))))) ; show the next heading
8913
8914 (defun org-agenda-goto-mouse (ev)
8915 "Go to the Org-mode file which contains the item at the mouse click."
8916 (interactive "e")
8917 (mouse-set-point ev)
8918 (org-agenda-goto))
8919
8920 (defun org-agenda-show ()
8921 "Display the Org-mode file which contains the item at point."
8922 (interactive)
8923 (let ((win (selected-window)))
8924 (org-agenda-goto t)
8925 (select-window win)))
8926
8927 (defun org-agenda-recenter (arg)
8928 "Display the Org-mode file which contains the item at point and recenter."
8929 (interactive "P")
8930 (let ((win (selected-window)))
8931 (org-agenda-goto t)
8932 (recenter arg)
8933 (select-window win)))
8934
8935 (defun org-agenda-show-mouse (ev)
8936 "Display the Org-mode file which contains the item at the mouse click."
8937 (interactive "e")
8938 (mouse-set-point ev)
8939 (org-agenda-show))
8940
8941 (defun org-agenda-check-no-diary ()
8942 "Check if the entry is a diary link and abort if yes."
8943 (if (get-text-property (point) 'org-agenda-diary-link)
8944 (org-agenda-error)))
8945
8946 (defun org-agenda-error ()
8947 (error "Command not allowed in this line"))
8948
8949 (defvar org-last-heading-marker (make-marker)
8950 "Marker pointing to the headline that last changed its TODO state
8951 by a remote command from the agenda.")
8952
8953 (defun org-agenda-todo (&optional arg)
8954 "Cycle TODO state of line at point, also in Org-mode file.
8955 This changes the line at point, all other lines in the agenda referring to
8956 the same tree node, and the headline of the tree node in the Org-mode file."
8957 (interactive "P")
8958 (org-agenda-check-no-diary)
8959 (let* ((col (current-column))
8960 (marker (or (get-text-property (point) 'org-marker)
8961 (org-agenda-error)))
8962 (buffer (marker-buffer marker))
8963 (pos (marker-position marker))
8964 (hdmarker (get-text-property (point) 'org-hd-marker))
8965 (buffer-read-only nil)
8966 newhead)
8967 (with-current-buffer buffer
8968 (widen)
8969 (goto-char pos)
8970 (org-show-context 'agenda)
8971 (save-excursion
8972 (and (outline-next-heading)
8973 (org-flag-heading nil))) ; show the next heading
8974 (org-todo arg)
8975 (and (bolp) (forward-char 1))
8976 (setq newhead (org-get-heading))
8977 (save-excursion
8978 (org-back-to-heading)
8979 (move-marker org-last-heading-marker (point))))
8980 (beginning-of-line 1)
8981 (save-excursion
8982 (org-agenda-change-all-lines newhead hdmarker 'fixface))
8983 (move-to-column col)))
8984
8985 (defun org-agenda-change-all-lines (newhead hdmarker &optional fixface)
8986 "Change all lines in the agenda buffer which match HDMARKER.
8987 The new content of the line will be NEWHEAD (as modified by
8988 `org-format-agenda-item'). HDMARKER is checked with
8989 `equal' against all `org-hd-marker' text properties in the file.
8990 If FIXFACE is non-nil, the face of each item is modified acording to
8991 the new TODO state."
8992 (let* (props m pl undone-face done-face finish new dotime cat tags)
8993 ; (setq newhead (org-format-agenda-item "x" newhead "x" nil 'noprefix))
8994 (save-excursion
8995 (goto-char (point-max))
8996 (beginning-of-line 1)
8997 (while (not finish)
8998 (setq finish (bobp))
8999 (when (and (setq m (get-text-property (point) 'org-hd-marker))
9000 (equal m hdmarker))
9001 (setq props (text-properties-at (point))
9002 dotime (get-text-property (point) 'dotime)
9003 cat (get-text-property (point) 'category)
9004 tags (get-text-property (point) 'tags)
9005 new (org-format-agenda-item "x" newhead cat tags dotime 'noprefix)
9006 pl (get-text-property (point) 'prefix-length)
9007 undone-face (get-text-property (point) 'undone-face)
9008 done-face (get-text-property (point) 'done-face))
9009 (move-to-column pl)
9010 (if (looking-at ".*")
9011 (progn
9012 (replace-match new t t)
9013 (beginning-of-line 1)
9014 (add-text-properties (point-at-bol) (point-at-eol) props)
9015 (when fixface
9016 (add-text-properties
9017 (point-at-bol) (point-at-eol)
9018 (list 'face
9019 (if org-last-todo-state-is-todo
9020 undone-face done-face)))
9021 (org-agenda-highlight-todo 'line))
9022 ;; (org-agenda-align-tags 'line) ;; done below by finalize
9023 (beginning-of-line 1))
9024 (error "Line update did not work")))
9025 (beginning-of-line 0)))
9026 (org-finalize-agenda)))
9027
9028 (defun org-agenda-align-tags (&optional line)
9029 "Align all tags in agenda items to `org-agenda-align-tags-to-column'."
9030 (let ((buffer-read-only))
9031 (save-excursion
9032 (goto-char (if line (point-at-bol) (point-min)))
9033 (while (re-search-forward "\\([ \t]+\\):[a-zA-Z0-9_@:]+:[ \t]*$"
9034 (if line (point-at-eol) nil) t)
9035 (delete-region (match-beginning 1) (match-end 1))
9036 (goto-char (match-beginning 1))
9037 (insert (org-add-props
9038 (make-string (max 1 (- org-agenda-align-tags-to-column
9039 (current-column))) ?\ )
9040 (text-properties-at (point))))))))
9041
9042 (defun org-agenda-priority-up ()
9043 "Increase the priority of line at point, also in Org-mode file."
9044 (interactive)
9045 (org-agenda-priority 'up))
9046
9047 (defun org-agenda-priority-down ()
9048 "Decrease the priority of line at point, also in Org-mode file."
9049 (interactive)
9050 (org-agenda-priority 'down))
9051
9052 (defun org-agenda-priority (&optional force-direction)
9053 "Set the priority of line at point, also in Org-mode file.
9054 This changes the line at point, all other lines in the agenda referring to
9055 the same tree node, and the headline of the tree node in the Org-mode file."
9056 (interactive)
9057 (org-agenda-check-no-diary)
9058 (let* ((marker (or (get-text-property (point) 'org-marker)
9059 (org-agenda-error)))
9060 (buffer (marker-buffer marker))
9061 (pos (marker-position marker))
9062 (hdmarker (get-text-property (point) 'org-hd-marker))
9063 (buffer-read-only nil)
9064 newhead)
9065 (with-current-buffer buffer
9066 (widen)
9067 (goto-char pos)
9068 (org-show-context 'agenda)
9069 (save-excursion
9070 (and (outline-next-heading)
9071 (org-flag-heading nil))) ; show the next heading
9072 (funcall 'org-priority force-direction)
9073 (end-of-line 1)
9074 (setq newhead (org-get-heading)))
9075 (org-agenda-change-all-lines newhead hdmarker)
9076 (beginning-of-line 1)))
9077
9078 (defun org-get-tags-at (&optional pos)
9079 "Get a list of all headline tags applicable at POS.
9080 POS defaults to point. If tags are inherited, the list contains
9081 the targets in the same sequence as the headlines appear, i.e.
9082 the tags of the current headline come last."
9083 (interactive)
9084 (let (tags)
9085 (save-excursion
9086 (goto-char (or pos (point)))
9087 (save-match-data
9088 (org-back-to-heading t)
9089 (condition-case nil
9090 (while t
9091 (if (looking-at "[^\r\n]+?:\\([a-zA-Z_@0-9:]+\\):[ \t]*\\([\n\r]\\|\\'\\)")
9092 (setq tags (append (org-split-string
9093 (org-match-string-no-properties 1) ":")
9094 tags)))
9095 (or org-use-tag-inheritance (error ""))
9096 (org-up-heading-all 1))
9097 (error nil))))
9098 tags))
9099
9100 (defun org-agenda-set-tags ()
9101 "Set tags for the current headline."
9102 (interactive)
9103 (org-agenda-check-no-diary)
9104 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
9105 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
9106 (org-agenda-error)))
9107 (buffer (marker-buffer hdmarker))
9108 (pos (marker-position hdmarker))
9109 (buffer-read-only nil)
9110 newhead)
9111 (with-current-buffer buffer
9112 (widen)
9113 (goto-char pos)
9114 (org-show-context 'agenda)
9115 (save-excursion
9116 (and (outline-next-heading)
9117 (org-flag-heading nil))) ; show the next heading
9118 (call-interactively 'org-set-tags)
9119 (end-of-line 1)
9120 (setq newhead (org-get-heading)))
9121 (org-agenda-change-all-lines newhead hdmarker)
9122 (beginning-of-line 1)))
9123
9124 (defun org-agenda-date-later (arg &optional what)
9125 "Change the date of this item to one day later."
9126 (interactive "p")
9127 (org-agenda-check-type t 'agenda 'timeline)
9128 (org-agenda-check-no-diary)
9129 (let* ((marker (or (get-text-property (point) 'org-marker)
9130 (org-agenda-error)))
9131 (buffer (marker-buffer marker))
9132 (pos (marker-position marker)))
9133 (with-current-buffer buffer
9134 (widen)
9135 (goto-char pos)
9136 (if (not (org-at-timestamp-p))
9137 (error "Cannot find time stamp"))
9138 (org-timestamp-change arg (or what 'day))
9139 (message "Time stamp changed to %s" org-last-changed-timestamp))))
9140
9141 (defun org-agenda-date-earlier (arg &optional what)
9142 "Change the date of this item to one day earlier."
9143 (interactive "p")
9144 (org-agenda-date-later (- arg) what))
9145
9146 (defun org-agenda-date-prompt (arg)
9147 "Change the date of this item. Date is prompted for, with default today.
9148 The prefix ARG is passed to the `org-time-stamp' command and can therefore
9149 be used to request time specification in the time stamp."
9150 (interactive "P")
9151 (org-agenda-check-type t 'agenda 'timeline)
9152 (org-agenda-check-no-diary)
9153 (let* ((marker (or (get-text-property (point) 'org-marker)
9154 (org-agenda-error)))
9155 (buffer (marker-buffer marker))
9156 (pos (marker-position marker)))
9157 (with-current-buffer buffer
9158 (widen)
9159 (goto-char pos)
9160 (if (not (org-at-timestamp-p))
9161 (error "Cannot find time stamp"))
9162 (org-time-stamp arg)
9163 (message "Time stamp changed to %s" org-last-changed-timestamp))))
9164
9165 (defun org-agenda-schedule (arg)
9166 "Schedule the item at point."
9167 (interactive "P")
9168 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
9169 (org-agenda-check-no-diary)
9170 (let* ((marker (or (get-text-property (point) 'org-marker)
9171 (org-agenda-error)))
9172 (buffer (marker-buffer marker))
9173 (pos (marker-position marker))
9174 (org-insert-labeled-timestamps-at-point nil)
9175 ts)
9176 (with-current-buffer buffer
9177 (widen)
9178 (goto-char pos)
9179 (setq ts (org-schedule))
9180 (message "Item scheduled for %s" ts))))
9181
9182 (defun org-agenda-deadline (arg)
9183 "Schedule the item at point."
9184 (interactive "P")
9185 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
9186 (org-agenda-check-no-diary)
9187 (let* ((marker (or (get-text-property (point) 'org-marker)
9188 (org-agenda-error)))
9189 (buffer (marker-buffer marker))
9190 (pos (marker-position marker))
9191 (org-insert-labeled-timestamps-at-point nil)
9192 ts)
9193 (with-current-buffer buffer
9194 (widen)
9195 (goto-char pos)
9196 (setq ts (org-deadline))
9197 (message "Deadline for this item set to %s" ts))))
9198
9199 (defun org-get-heading ()
9200 "Return the heading of the current entry, without the stars."
9201 (save-excursion
9202 (and (memq (char-before) '(?\n ?\r)) (skip-chars-forward "^\n\r"))
9203 (if (and (re-search-backward "[\r\n]\\*" nil t)
9204 (looking-at "[\r\n]\\*+[ \t]+\\([^\r\n]*\\)"))
9205 (match-string 1)
9206 "")))
9207
9208 (defun org-agenda-clock-in (&optional arg)
9209 "Start the clock on the currently selected item."
9210 (interactive "P")
9211 (org-agenda-check-no-diary)
9212 (let* ((marker (or (get-text-property (point) 'org-marker)
9213 (org-agenda-error)))
9214 (pos (marker-position marker)))
9215 (with-current-buffer (marker-buffer marker)
9216 (widen)
9217 (goto-char pos)
9218 (org-clock-in))))
9219
9220 (defun org-agenda-diary-entry ()
9221 "Make a diary entry, like the `i' command from the calendar.
9222 All the standard commands work: block, weekly etc."
9223 (interactive)
9224 (org-agenda-check-type t 'agenda 'timeline)
9225 (require 'diary-lib)
9226 (let* ((char (progn
9227 (message "Diary entry: [d]ay [w]eekly [m]onthly [y]early [a]nniversary [b]lock [c]yclic")
9228 (read-char-exclusive)))
9229 (cmd (cdr (assoc char
9230 '((?d . insert-diary-entry)
9231 (?w . insert-weekly-diary-entry)
9232 (?m . insert-monthly-diary-entry)
9233 (?y . insert-yearly-diary-entry)
9234 (?a . insert-anniversary-diary-entry)
9235 (?b . insert-block-diary-entry)
9236 (?c . insert-cyclic-diary-entry)))))
9237 (oldf (symbol-function 'calendar-cursor-to-date))
9238 (point (point))
9239 (mark (or (mark t) (point))))
9240 (unless cmd
9241 (error "No command associated with <%c>" char))
9242 (unless (and (get-text-property point 'day)
9243 (or (not (equal ?b char))
9244 (get-text-property mark 'day)))
9245 (error "Don't know which date to use for diary entry"))
9246 ;; We implement this by hacking the `calendar-cursor-to-date' function
9247 ;; and the `calendar-mark-ring' variable. Saves a lot of code.
9248 (let ((calendar-mark-ring
9249 (list (calendar-gregorian-from-absolute
9250 (or (get-text-property mark 'day)
9251 (get-text-property point 'day))))))
9252 (unwind-protect
9253 (progn
9254 (fset 'calendar-cursor-to-date
9255 (lambda (&optional error)
9256 (calendar-gregorian-from-absolute
9257 (get-text-property point 'day))))
9258 (call-interactively cmd))
9259 (fset 'calendar-cursor-to-date oldf)))))
9260
9261
9262 (defun org-agenda-execute-calendar-command (cmd)
9263 "Execute a calendar command from the agenda, with the date associated to
9264 the cursor position."
9265 (org-agenda-check-type t 'agenda 'timeline)
9266 (require 'diary-lib)
9267 (unless (get-text-property (point) 'day)
9268 (error "Don't know which date to use for calendar command"))
9269 (let* ((oldf (symbol-function 'calendar-cursor-to-date))
9270 (point (point))
9271 (date (calendar-gregorian-from-absolute
9272 (get-text-property point 'day)))
9273 (displayed-day (extract-calendar-day date))
9274 (displayed-month (extract-calendar-month date))
9275 (displayed-year (extract-calendar-year date)))
9276 (unwind-protect
9277 (progn
9278 (fset 'calendar-cursor-to-date
9279 (lambda (&optional error)
9280 (calendar-gregorian-from-absolute
9281 (get-text-property point 'day))))
9282 (call-interactively cmd))
9283 (fset 'calendar-cursor-to-date oldf))))
9284
9285 (defun org-agenda-phases-of-moon ()
9286 "Display the phases of the moon for the 3 months around the cursor date."
9287 (interactive)
9288 (org-agenda-execute-calendar-command 'calendar-phases-of-moon))
9289
9290 (defun org-agenda-holidays ()
9291 "Display the holidays for the 3 months around the cursor date."
9292 (interactive)
9293 (org-agenda-execute-calendar-command 'list-calendar-holidays))
9294
9295 (defun org-agenda-sunrise-sunset (arg)
9296 "Display sunrise and sunset for the cursor date.
9297 Latitude and longitude can be specified with the variables
9298 `calendar-latitude' and `calendar-longitude'. When called with prefix
9299 argument, latitude and longitude will be prompted for."
9300 (interactive "P")
9301 (let ((calendar-longitude (if arg nil calendar-longitude))
9302 (calendar-latitude (if arg nil calendar-latitude))
9303 (calendar-location-name
9304 (if arg "the given coordinates" calendar-location-name)))
9305 (org-agenda-execute-calendar-command 'calendar-sunrise-sunset)))
9306
9307 (defun org-agenda-goto-calendar ()
9308 "Open the Emacs calendar with the date at the cursor."
9309 (interactive)
9310 (org-agenda-check-type t 'agenda 'timeline)
9311 (let* ((day (or (get-text-property (point) 'day)
9312 (error "Don't know which date to open in calendar")))
9313 (date (calendar-gregorian-from-absolute day))
9314 (calendar-move-hook nil)
9315 (view-calendar-holidays-initially nil)
9316 (view-diary-entries-initially nil))
9317 (calendar)
9318 (calendar-goto-date date)))
9319
9320 (defun org-calendar-goto-agenda ()
9321 "Compute the Org-mode agenda for the calendar date displayed at the cursor.
9322 This is a command that has to be installed in `calendar-mode-map'."
9323 (interactive)
9324 (org-agenda-list nil (calendar-absolute-from-gregorian
9325 (calendar-cursor-to-date))
9326 nil))
9327
9328 (defun org-agenda-convert-date ()
9329 (interactive)
9330 (org-agenda-check-type t 'agenda 'timeline)
9331 (let ((day (get-text-property (point) 'day))
9332 date s)
9333 (unless day
9334 (error "Don't know which date to convert"))
9335 (setq date (calendar-gregorian-from-absolute day))
9336 (setq s (concat
9337 "Gregorian: " (calendar-date-string date) "\n"
9338 "ISO: " (calendar-iso-date-string date) "\n"
9339 "Day of Yr: " (calendar-day-of-year-string date) "\n"
9340 "Julian: " (calendar-julian-date-string date) "\n"
9341 "Astron. JD: " (calendar-astro-date-string date)
9342 " (Julian date number at noon UTC)\n"
9343 "Hebrew: " (calendar-hebrew-date-string date) " (until sunset)\n"
9344 "Islamic: " (calendar-islamic-date-string date) " (until sunset)\n"
9345 "French: " (calendar-french-date-string date) "\n"
9346 "Mayan: " (calendar-mayan-date-string date) "\n"
9347 "Coptic: " (calendar-coptic-date-string date) "\n"
9348 "Ethiopic: " (calendar-ethiopic-date-string date) "\n"
9349 "Persian: " (calendar-persian-date-string date) "\n"
9350 "Chinese: " (calendar-chinese-date-string date) "\n"))
9351 (with-output-to-temp-buffer "*Dates*"
9352 (princ s))
9353 (if (fboundp 'fit-window-to-buffer)
9354 (fit-window-to-buffer (get-buffer-window "*Dates*")))))
9355
9356 ;;; Tags
9357
9358 (defun org-scan-tags (action matcher &optional todo-only)
9359 "Scan headline tags with inheritance and produce output ACTION.
9360 ACTION can be `sparse-tree' or `agenda'. MATCHER is a Lisp form to be
9361 evaluated, testing if a given set of tags qualifies a headline for
9362 inclusion. When TODO-ONLY is non-nil, only lines with a TODO keyword
9363 are included in the output."
9364 (let* ((re (concat "[\n\r]" outline-regexp " *\\(\\<\\("
9365 (mapconcat 'regexp-quote
9366 (nreverse (cdr (reverse org-todo-keywords)))
9367 "\\|")
9368 "\\>\\)\\)? *\\(.*?\\)\\(:[A-Za-z_@0-9:]+:\\)?[ \t]*$")) ;;FIXME: was [\n\r] instead of $
9369 (props (list 'face nil
9370 'done-face 'org-done
9371 'undone-face nil
9372 'mouse-face 'highlight
9373 'org-not-done-regexp org-not-done-regexp
9374 'keymap org-agenda-keymap
9375 'help-echo
9376 (format "mouse-2 or RET jump to org file %s"
9377 (abbreviate-file-name buffer-file-name))))
9378 (case-fold-search nil)
9379 lspos
9380 tags tags-list tags-alist (llast 0) rtn level category i txt
9381 todo marker)
9382 (save-excursion
9383 (goto-char (point-min))
9384 (when (eq action 'sparse-tree) (org-overview))
9385 (while (re-search-forward re nil t)
9386 (catch :skip
9387 (and (eq action 'agenda) (org-agenda-skip))
9388 (setq todo (if (match-end 1) (match-string 2))
9389 tags (if (match-end 4) (match-string 4)))
9390 (goto-char (setq lspos (1+ (match-beginning 0))))
9391 (setq level (funcall outline-level)
9392 category (org-get-category))
9393 (setq i llast llast level)
9394 ;; remove tag lists from same and sublevels
9395 (while (>= i level)
9396 (when (setq entry (assoc i tags-alist))
9397 (setq tags-alist (delete entry tags-alist)))
9398 (setq i (1- i)))
9399 ;; add the nex tags
9400 (when tags
9401 (setq tags (mapcar 'downcase (org-split-string tags ":"))
9402 tags-alist
9403 (cons (cons level tags) tags-alist)))
9404 ;; compile tags for current headline
9405 (setq tags-list
9406 (if org-use-tag-inheritance
9407 (apply 'append (mapcar 'cdr tags-alist))
9408 tags))
9409 (when (and (or (not todo-only) todo)
9410 (eval matcher)
9411 (or (not org-agenda-skip-archived-trees)
9412 (not (member org-archive-tag tags-list))))
9413 ;; list this headline
9414 (if (eq action 'sparse-tree)
9415 (progn
9416 (org-show-context 'tags-tree))
9417 (setq txt (org-format-agenda-item
9418 ""
9419 (concat
9420 (if org-tags-match-list-sublevels
9421 (make-string (1- level) ?.) "")
9422 (org-get-heading))
9423 category tags-list))
9424 (goto-char lspos)
9425 (setq marker (org-agenda-new-marker))
9426 (org-add-props txt props
9427 'org-marker marker 'org-hd-marker marker 'category category)
9428 (push txt rtn))
9429 ;; if we are to skip sublevels, jump to end of subtree
9430 (or org-tags-match-list-sublevels (org-end-of-subtree t))))))
9431 (when (and (eq action 'sparse-tree)
9432 (not org-sparse-tree-open-archived-trees))
9433 (org-hide-archived-subtrees (point-min) (point-max)))
9434 (nreverse rtn)))
9435
9436 (defun org-tags-sparse-tree (&optional arg match)
9437 "Create a sparse tree according to tags string MATCH.
9438 MATCH can contain positive and negative selection of tags, like
9439 \"+WORK+URGENT-WITHBOSS\"."
9440 (interactive "P")
9441 (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match))))
9442
9443 ;; FIXME: remove this function.
9444 (defun org-make-tags-matcher-old (match)
9445 "Create the TAGS matcher form for the tags-selecting string MATCH."
9446 (unless match
9447 ;; Get a new match request, with completion
9448 (setq org-last-tags-completion-table
9449 (or org-tag-alist
9450 org-last-tags-completion-table))
9451 (setq match (completing-read
9452 "Tags: " 'org-tags-completion-function nil nil nil
9453 'org-tags-history)))
9454 ;; parse the string and create a lisp form
9455 (let ((match0 match) minus tag mm matcher orterms term orlist)
9456 (setq orterms (org-split-string match "|"))
9457 (while (setq term (pop orterms))
9458 (while (string-match "^&?\\([-+:]\\)?\\([A-Za-z_@0-9]+\\)" term)
9459 (setq minus (and (match-end 1)
9460 (equal (match-string 1 term) "-"))
9461 tag (match-string 2 term)
9462 term (substring term (match-end 0))
9463 mm (list 'member (downcase tag) 'tags-list)
9464 mm (if minus (list 'not mm) mm))
9465 (push mm matcher))
9466 (push (if (> (length matcher) 1) (cons 'and matcher) (car matcher))
9467 orlist)
9468 (setq matcher nil))
9469 (setq matcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist)))
9470 ;; Return the string and lisp forms of the matcher
9471 (cons match0 matcher)))
9472
9473
9474 (defun org-make-tags-matcher (match)
9475 "Create the TAGS//TODO matcher form for the selection string MATCH."
9476 (unless match
9477 ;; Get a new match request, with completion
9478 (setq org-last-tags-completion-table
9479 (or org-tag-alist
9480 org-last-tags-completion-table))
9481 (setq match (completing-read
9482 "Match: " 'org-tags-completion-function nil nil nil
9483 'org-tags-history))) ; FIXME: SHould we have a separate history for this?
9484
9485 ;; Parse the string and create a lisp form
9486 (let ((match0 match) minus tag mm
9487 tagsmatch todomatch tagsmatcher todomatcher kwd matcher
9488 orterms term orlist)
9489 (if (string-match "/+" match)
9490 ;; match contains also a todo-matching request
9491 (setq tagsmatch (substring match 0 (match-beginning 0))
9492 todomatch (substring match (match-end 0)))
9493 ;; only matching tags
9494 (setq tagsmatch match todomatch nil))
9495
9496 ;; Make the tags matcher
9497 (if (or (not tagsmatch) (not (string-match "\\S-" tagsmatch)))
9498 (setq tagsmatcher t)
9499 (setq orterms (org-split-string tagsmatch "|") orlist nil)
9500 (while (setq term (pop orterms))
9501 (while (string-match "^&?\\([-+:]\\)?\\([A-Za-z_@0-9]+\\)" term)
9502 (setq minus (and (match-end 1)
9503 (equal (match-string 1 term) "-"))
9504 tag (match-string 2 term)
9505 term (substring term (match-end 0))
9506 mm (list 'member (downcase tag) 'tags-list)
9507 mm (if minus (list 'not mm) mm))
9508 (push mm tagsmatcher))
9509 (push (if (> (length tagsmatcher) 1)
9510 (cons 'and tagsmatcher)
9511 (car tagsmatcher))
9512 orlist)
9513 (setq tagsmatcher nil))
9514 (setq tagsmatcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist))))
9515
9516 ;; Make the todo matcher ;; FIXME: reduce syntax richness?
9517 (if (or (not todomatch) (not (string-match "\\S-" todomatch)))
9518 (setq todomatcher t)
9519 (setq orterms (org-split-string todomatch "|") orlist nil)
9520 (while (setq term (pop orterms))
9521 (while (string-match "^&?\\([-+:]\\)?\\([A-Za-z_@0-9]+\\)" term)
9522 (setq minus (and (match-end 1)
9523 (equal (match-string 1 term) "-"))
9524 kwd (match-string 2 term)
9525 term (substring term (match-end 0))
9526 mm (list 'equal 'todo kwd)
9527 mm (if minus (list 'not mm) mm))
9528 (push mm todomatcher))
9529 (push (if (> (length todomatcher) 1)
9530 (cons 'and todomatcher)
9531 (car todomatcher))
9532 orlist)
9533 (setq todomatcher nil))
9534 (setq todomatcher (if (> (length orlist) 1)
9535 (cons 'or orlist) (car orlist))))
9536
9537 ;; Return the string and lisp forms of the matcher
9538 (setq matcher (if todomatcher
9539 (list 'and tagsmatcher todomatcher)
9540 tagsmatcher))
9541 (cons match0 matcher)))
9542
9543 ;;;###autoload
9544 (defun org-tags-view (&optional todo-only match)
9545 "Show all headlines for all `org-agenda-files' matching a TAGS criterion.
9546 The prefix arg TODO-ONLY limits the search to TODO entries."
9547 (interactive "P")
9548 (org-compile-prefix-format 'tags)
9549 (org-set-sorting-strategy 'tags)
9550 (let* ((org-tags-match-list-sublevels
9551 (if todo-only t org-tags-match-list-sublevels))
9552 (win (selected-window))
9553 (completion-ignore-case t)
9554 rtn rtnall files file pos matcher
9555 buffer)
9556 (setq matcher (org-make-tags-matcher match)
9557 match (car matcher) matcher (cdr matcher))
9558 (org-prepare-agenda)
9559 (setq org-agenda-redo-command
9560 (list 'org-tags-view (list 'quote todo-only)
9561 (list 'if 'current-prefix-arg nil match)))
9562 (setq files (org-agenda-files)
9563 rtnall nil)
9564 (while (setq file (pop files))
9565 (catch 'nextfile
9566 (org-check-agenda-file file)
9567 (setq buffer (if (file-exists-p file)
9568 (org-get-agenda-file-buffer file)
9569 (error "No such file %s" file)))
9570 (if (not buffer)
9571 ;; If file does not exist, merror message to agenda
9572 (setq rtn (list
9573 (format "ORG-AGENDA-ERROR: No such org-file %s" file))
9574 rtnall (append rtnall rtn))
9575 (with-current-buffer buffer
9576 (unless (org-mode-p)
9577 (error "Agenda file %s is not in `org-mode'" file))
9578 (setq org-category-table (org-get-category-table))
9579 (save-excursion
9580 (save-restriction
9581 (if org-agenda-restrict
9582 (narrow-to-region org-agenda-restrict-begin
9583 org-agenda-restrict-end)
9584 (widen))
9585 (setq rtn (org-scan-tags 'agenda matcher todo-only))
9586 (setq rtnall (append rtnall rtn))))))))
9587 (insert "Headlines with TAGS match: ")
9588 (add-text-properties (point-min) (1- (point))
9589 (list 'face 'org-level-3))
9590 (setq pos (point))
9591 (insert match "\n")
9592 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
9593 (setq pos (point))
9594 (unless org-agenda-multi
9595 (insert "Press `C-u r' to search again with new search string\n"))
9596 (add-text-properties pos (1- (point)) (list 'face 'org-level-3))
9597 (when rtnall
9598 (insert (org-finalize-agenda-entries rtnall) "\n"))
9599 (goto-char (point-min))
9600 (org-fit-agenda-window)
9601 (add-text-properties (point-min) (point-max) '(org-agenda-type tags))
9602 (org-finalize-agenda)
9603 (setq buffer-read-only t)
9604 (if (not org-select-agenda-window) (select-window win))))
9605
9606 (defvar org-add-colon-after-tag-completion nil) ;; dynamically skoped param
9607 (defvar org-tags-overlay (org-make-overlay 1 1))
9608 ;(org-overlay-put org-tags-overlay 'face 'org-warning)
9609 (org-detatch-overlay org-tags-overlay)
9610
9611 (defun org-set-tags (&optional arg just-align)
9612 "Set the tags for the current headline.
9613 With prefix ARG, realign all tags in headings in the current buffer."
9614 (interactive "P")
9615 (let* ((re (concat "^" outline-regexp))
9616 (col (current-column))
9617 (current (org-get-tags))
9618 table current-tags inherited-tags ; computed below when needed
9619 tags empty invis)
9620 (if arg
9621 (save-excursion
9622 (goto-char (point-min))
9623 (let (buffer-invisibility-spec) ; Emacs 21 compatibility
9624 (while (re-search-forward re nil t)
9625 (org-set-tags nil t)))
9626 (message "All tags realigned to column %d" org-tags-column))
9627 (if just-align
9628 (setq tags current)
9629 (setq table (or org-tag-alist (org-get-buffer-tags))
9630 org-last-tags-completion-table table
9631 current-tags (org-split-string current ":")
9632 inherited-tags (nreverse
9633 (nthcdr (length current-tags)
9634 (nreverse (org-get-tags-at))))
9635 tags
9636 (if (or (eq t org-use-fast-tag-selection)
9637 (and org-use-fast-tag-selection
9638 (delq nil (mapcar 'cdr table))))
9639 (org-fast-tag-selection current-tags inherited-tags table)
9640 (let ((org-add-colon-after-tag-completion t))
9641 (completing-read "Tags: " 'org-tags-completion-function
9642 nil nil current 'org-tags-history))))
9643 (while (string-match "[-+&]+" tags)
9644 (setq tags (replace-match ":" t t tags))))
9645 (unless (setq empty (string-match "\\`[\t ]*\\'" tags))
9646 (unless (string-match ":$" tags) (setq tags (concat tags ":")))
9647 (unless (string-match "^:" tags) (setq tags (concat ":" tags))))
9648 (if (equal current "")
9649 (progn
9650 (end-of-line 1)
9651 (or empty (insert " ")))
9652 (beginning-of-line 1)
9653 (setq invis (org-invisible-p))
9654 (looking-at (concat ".*?\\([ \t]*" (regexp-quote current) "\\)[ \t]*"))
9655 (delete-region (match-beginning 1) (match-end 1))
9656 (goto-char (match-beginning 1))
9657 (insert (if empty "" " ")))
9658 (if (equal tags "")
9659 (save-excursion
9660 (beginning-of-line 1)
9661 (skip-chars-forward "*")
9662 (if (= (char-after) ?\ ) (forward-char 1))
9663 (and (re-search-forward "[ \t]+$" (point-at-eol) t)
9664 (replace-match "")))
9665 (let (buffer-invisibility-spec) ; Emacs 21 compatibility
9666 (move-to-column (max (current-column)
9667 (if (> org-tags-column 0)
9668 org-tags-column
9669 (- (- org-tags-column) (length tags))))
9670 t))
9671 (insert tags)
9672 (if (and (not invis) (org-invisible-p))
9673 (outline-flag-region (point) (point-at-bol) nil))) ; show
9674 (move-to-column col))))
9675
9676 (defun org-tags-completion-function (string predicate &optional flag)
9677 (let (s1 s2 rtn (ctable org-last-tags-completion-table)
9678 (confirm (lambda (x) (stringp (car x)))))
9679 (if (string-match "^\\(.*[-+:&|]\\)\\([^-+:&|]*\\)$" string)
9680 (setq s1 (match-string 1 string)
9681 s2 (match-string 2 string))
9682 (setq s1 "" s2 string))
9683 (cond
9684 ((eq flag nil)
9685 ;; try completion
9686 (setq rtn (try-completion s2 ctable confirm))
9687 (if (stringp rtn)
9688 (concat s1 s2 (substring rtn (length s2))
9689 (if (and org-add-colon-after-tag-completion
9690 (assoc rtn ctable))
9691 ":" "")))
9692 )
9693 ((eq flag t)
9694 ;; all-completions
9695 (all-completions s2 ctable confirm)
9696 )
9697 ((eq flag 'lambda)
9698 ;; exact match?
9699 (assoc s2 ctable)))
9700 ))
9701
9702 (defun org-fast-tag-insert (kwd tags face &optional end)
9703 "Insert KDW, and the TAGS, the latter with face FACE. Also inser END."
9704 (insert (format "%-12s" (concat kwd ":"))
9705 (org-add-props (mapconcat 'identity tags " ") nil 'face face)
9706 (or end "")))
9707
9708 (defun org-fast-tag-show-exit (flag)
9709 (save-excursion
9710 (goto-line 3)
9711 (if (re-search-forward "[ \t]+Next change exits" (point-at-eol) t)
9712 (replace-match ""))
9713 (when flag
9714 (end-of-line 1)
9715 (move-to-column (- (window-width) 19) t)
9716 (insert (org-add-props " Next change exits" nil 'face 'org-warning)))))
9717
9718 (defun org-set-current-tags-overlay (current prefix)
9719 (let ((s (concat ":" (mapconcat 'identity current ":") ":")))
9720 (if (featurep 'xemacs)
9721 (org-overlay-display org-tags-overlay (concat prefix s)
9722 'secondary-selection)
9723 (put-text-property 0 (length s) 'face '(secondary-selection org-tag) s)
9724 (org-overlay-display org-tags-overlay (concat prefix s)))))
9725
9726 (defun org-fast-tag-selection (current inherited table)
9727 "Fast tag selection with single keys.
9728 CURRENT is the current list of tags in the headline, INHERITED is the
9729 list of inherited tags, and TABLE is an alist of tags and corresponding keys,
9730 possibly with grouping information.
9731 If the keys are nil, a-z are automatically assigned.
9732 Returns the new tags string, or nil to not change the current settings."
9733 (let* ((maxlen (apply 'max (mapcar
9734 (lambda (x)
9735 (if (stringp (car x)) (string-width (car x)) 0))
9736 table)))
9737 (buf (current-buffer))
9738 (buffer-tags nil)
9739 (fwidth (+ maxlen 3 1 3))
9740 (ncol (/ (- (window-width) 4) fwidth))
9741 (i-face 'org-done)
9742 (c-face 'org-tag)
9743 tg cnt e c char c1 c2 ntable tbl rtn
9744 ov-start ov-end ov-prefix
9745 (exit-after-next org-fast-tag-selection-single-key)
9746 groups ingroup)
9747 (save-excursion
9748 (beginning-of-line 1)
9749 (if (looking-at ".*[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \t]*\\(\r\\|$\\)")
9750 (setq ov-start (match-beginning 1)
9751 ov-end (match-end 1)
9752 ov-prefix "")
9753 (setq ov-start (1- (point-at-eol))
9754 ov-end (1+ ov-start))
9755 (skip-chars-forward "^\n\r")
9756 (setq ov-prefix
9757 (concat
9758 (buffer-substring (1- (point)) (point))
9759 (if (> (current-column) org-tags-column)
9760 " "
9761 (make-string (- org-tags-column (current-column)) ?\ ))))))
9762 (org-move-overlay org-tags-overlay ov-start ov-end)
9763 (save-window-excursion
9764 ;; FIXME: would it be better to keep the other windows?
9765 (delete-other-windows)
9766 (split-window-vertically)
9767 (switch-to-buffer-other-window (get-buffer-create " *Org tags*"))
9768 (erase-buffer)
9769 (org-fast-tag-insert "Inherited" inherited i-face "\n")
9770 (org-fast-tag-insert "Current" current c-face "\n\n")
9771 (org-fast-tag-show-exit exit-after-next)
9772 (org-set-current-tags-overlay current ov-prefix)
9773 (setq tbl table char ?a cnt 0)
9774 (while (setq e (pop tbl))
9775 (cond
9776 ((equal e '(:startgroup))
9777 (push '() groups) (setq ingroup t)
9778 (when (not (= cnt 0))
9779 (setq cnt 0)
9780 (insert "\n"))
9781 (insert "{ "))
9782 ((equal e '(:endgroup))
9783 (setq ingroup nil cnt 0)
9784 (insert "}\n"))
9785 (t
9786 (setq tg (car e) c2 nil)
9787 (if (cdr e)
9788 (setq c (cdr e))
9789 ;; automatically assign a character.
9790 (setq c1 (string-to-char
9791 (downcase (substring
9792 tg (if (= (string-to-char tg) ?@) 1 0)))))
9793 (if (or (rassoc c1 ntable) (rassoc c1 table))
9794 (while (or (rassoc char ntable) (rassoc char table))
9795 (setq char (1+ char)))
9796 (setq c2 c1))
9797 (setq c (or c2 char)))
9798 (if ingroup (push tg (car groups)))
9799 (setq tg (org-add-props tg nil 'face
9800 (cond
9801 ((member tg current) c-face)
9802 ((member tg inherited) i-face)
9803 (t nil))))
9804 (if (and (= cnt 0) (not ingroup)) (insert " "))
9805 (insert "[" c "] " tg (make-string
9806 (- fwidth 4 (length tg)) ?\ ))
9807 (push (cons tg c) ntable)
9808 (when (= (setq cnt (1+ cnt)) ncol)
9809 (insert "\n")
9810 (if ingroup (insert " "))
9811 (setq cnt 0)))))
9812 (setq ntable (nreverse ntable))
9813 (insert "\n")
9814 (goto-char (point-min))
9815 (if (fboundp 'fit-window-to-buffer) (fit-window-to-buffer))
9816 (setq rtn
9817 (catch 'exit
9818 (while t
9819 (message "[a-z..]:Toggle [SPC]:clear [RET]:accept [TAB]:free [C-c]: multi%s"
9820 (if groups " [!] no groups" ""))
9821 (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
9822 (cond
9823 ((= c ?\r) (throw 'exit t))
9824 ((= c ?!)
9825 (setq groups nil)
9826 (goto-char (point-min))
9827 (while (re-search-forward "[{}]" nil t) (replace-match " ")))
9828 ((= c ?\C-c)
9829 (org-fast-tag-show-exit
9830 (setq exit-after-next (not exit-after-next))))
9831 ((or (= c ?\C-g)
9832 (and (= c ?q) (not (rassoc c ntable))))
9833 (org-detatch-overlay org-tags-overlay)
9834 (setq quit-flag t))
9835 ((= c ?\ )
9836 (setq current nil)
9837 (if exit-after-next (setq exit-after-next 'now)))
9838 ((= c ?\t)
9839 (condition-case nil
9840 (setq tg (completing-read
9841 "Tag: "
9842 (or buffer-tags
9843 (with-current-buffer buf
9844 (org-get-buffer-tags)))))
9845 (quit (setq tg "")))
9846 (when (string-match "\\S-" tg)
9847 (add-to-list 'buffer-tags (list tg))
9848 (if (member tg current)
9849 (setq current (delete tg current))
9850 (push tg current)))
9851 (if exit-after-next (setq exit-after-next 'now)))
9852 ((setq e (rassoc c ntable) tg (car e))
9853 (if (member tg current)
9854 (setq current (delete tg current))
9855 (loop for g in groups do
9856 (if (member tg g)
9857 (mapcar (lambda (x)
9858 (setq current (delete x current)))
9859 g)))
9860 (push tg current))
9861 (if exit-after-next (setq exit-after-next 'now))))
9862
9863 ;; Create a sorted list
9864 (setq current
9865 (sort current
9866 (lambda (a b)
9867 (assoc b (cdr (memq (assoc a ntable) ntable))))))
9868 (if (eq exit-after-next 'now) (throw 'exit t))
9869 (goto-char (point-min))
9870 (beginning-of-line 2)
9871 (delete-region (point) (point-at-eol))
9872 (org-fast-tag-insert "Current" current c-face)
9873 (org-set-current-tags-overlay current ov-prefix)
9874 (while (re-search-forward "\\[.\\] \\([a-zA-Z0-9_@]+\\)" nil t)
9875 (setq tg (match-string 1))
9876 (add-text-properties (match-beginning 1) (match-end 1)
9877 (list 'face
9878 (cond
9879 ((member tg current) c-face)
9880 ((member tg inherited) i-face)
9881 (t nil)))))
9882 (goto-char (point-min)))))
9883 (org-detatch-overlay org-tags-overlay)
9884 (if rtn
9885 (mapconcat 'identity current ":")
9886 nil))))
9887
9888 (defun org-get-tags ()
9889 "Get the TAGS string in the current headline."
9890 (unless (org-on-heading-p t)
9891 (error "Not on a heading"))
9892 (save-excursion
9893 (beginning-of-line 1)
9894 (if (looking-at ".*[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \t]*\\(\r\\|$\\)")
9895 (org-match-string-no-properties 1)
9896 "")))
9897
9898 (defun org-get-buffer-tags ()
9899 "Get a table of all tags used in the buffer, for completion."
9900 (let (tags)
9901 (save-excursion
9902 (goto-char (point-min))
9903 (while (re-search-forward "[ \t]:\\([A-Za-z_@0-9:]+\\):[ \t\r\n]" nil t)
9904 (mapc (lambda (x) (add-to-list 'tags x))
9905 (org-split-string (org-match-string-no-properties 1) ":"))))
9906 (mapcar 'list tags)))
9907
9908 ;;; Link Stuff
9909
9910 (defvar org-create-file-search-functions nil
9911 "List of functions to construct the right search string for a file link.
9912 These functions are called in turn with point at the location to
9913 which the link should point.
9914
9915 A function in the hook should first test if it would like to
9916 handle this file type, for example by checking the major-mode or
9917 the file extension. If it decides not to handle this file, it
9918 should just return nil to give other functions a chance. If it
9919 does handle the file, it must return the search string to be used
9920 when following the link. The search string will be part of the
9921 file link, given after a double colon, and `org-open-at-point'
9922 will automatically search for it. If special measures must be
9923 taken to make the search successful, another function should be
9924 added to the companion hook `org-execute-file-search-functions',
9925 which see.
9926
9927 A function in this hook may also use `setq' to set the variable
9928 `description' to provide a suggestion for the descriptive text to
9929 be used for this link when it gets inserted into an Org-mode
9930 buffer with \\[org-insert-link].")
9931
9932 (defvar org-execute-file-search-functions nil
9933 "List of functions to execute a file search triggered by a link.
9934
9935 Functions added to this hook must accept a single argument, the
9936 search string that was part of the file link, the part after the
9937 double colon. The function must first check if it would like to
9938 handle this search, for example by checking the major-mode or the
9939 file extension. If it decides not to handle this search, it
9940 should just return nil to give other functions a chance. If it
9941 does handle the search, it must return a non-nil value to keep
9942 other functions from trying.
9943
9944 Each function can access the current prefix argument through the
9945 variable `current-prefix-argument'. Note that a single prefix is
9946 used to force opening a link in Emacs, so it may be good to only
9947 use a numeric or double prefix to guide the search function.
9948
9949 In case this is needed, a function in this hook can also restore
9950 the window configuration before `org-open-at-point' was called using:
9951
9952 (set-window-configuration org-window-config-before-follow-link)")
9953
9954 (defun org-find-file-at-mouse (ev)
9955 "Open file link or URL at mouse."
9956 (interactive "e")
9957 (mouse-set-point ev)
9958 (org-open-at-point 'in-emacs))
9959
9960 (defun org-open-at-mouse (ev)
9961 "Open file link or URL at mouse."
9962 (interactive "e")
9963 (mouse-set-point ev)
9964 (org-open-at-point))
9965
9966 (defvar org-window-config-before-follow-link nil
9967 "The window configuration before following a link.
9968 This is saved in case the need arises to restore it.")
9969
9970 ;; FIXME: IN-EMACS is used for many purposes, maybe rename this argument???
9971 (defun org-open-at-point (&optional in-emacs)
9972 "Open link at or after point.
9973 If there is no link at point, this function will search forward up to
9974 the end of the current subtree.
9975 Normally, files will be opened by an appropriate application. If the
9976 optional argument IN-EMACS is non-nil, Emacs will visit the file."
9977 (interactive "P")
9978 (setq org-window-config-before-follow-link (current-window-configuration))
9979 (org-remove-occur-highlights nil nil t)
9980 (if (org-at-timestamp-p t)
9981 (org-follow-timestamp-link)
9982 (let (type path link line search (pos (point)))
9983 (catch 'match
9984 (save-excursion
9985 (skip-chars-forward "^]\n\r")
9986 (when (and (re-search-backward "\\[\\[" nil t)
9987 (looking-at org-bracket-link-regexp)
9988 (<= (match-beginning 0) pos)
9989 (>= (match-end 0) pos))
9990 (setq link (org-link-unescape (org-match-string-no-properties 1)))
9991 (while (string-match " *\n *" link)
9992 (setq link (replace-match " " t t link)))
9993 (setq link (org-link-expand-abbrev link))
9994 (if (string-match org-link-re-with-space2 link)
9995 (setq type (match-string 1 link)
9996 path (match-string 2 link))
9997 (setq type "thisfile"
9998 path link))
9999 (throw 'match t)))
10000
10001 (when (get-text-property (point) 'org-linked-text)
10002 (setq type "thisfile"
10003 pos (if (get-text-property (1+ (point)) 'org-linked-text)
10004 (1+ (point)) (point))
10005 path (buffer-substring
10006 (previous-single-property-change pos 'org-linked-text)
10007 (next-single-property-change pos 'org-linked-text)))
10008 (throw 'match t))
10009
10010 (save-excursion
10011 (skip-chars-backward (concat "^[]" org-non-link-chars " "))
10012 (if (equal (char-before) ?<) (backward-char 1))
10013 (when (or (looking-at org-angle-link-re)
10014 (looking-at org-plain-link-re)
10015 (and (or (re-search-forward org-angle-link-re (point-at-eol) t)
10016 (re-search-forward org-plain-link-re (point-at-eol) t))
10017 (<= (match-beginning 0) pos)
10018 (>= (match-end 0) pos)))
10019 (setq type (match-string 1)
10020 path (match-string 2))
10021 (throw 'match t)))
10022 (save-excursion
10023 (skip-chars-backward "^ \t\n\r")
10024 (when (looking-at "\\(:[A-Za-z_@0-9:]+\\):[ \t\r\n]")
10025 (setq type "tags"
10026 path (match-string 1))
10027 (while (string-match ":" path)
10028 (setq path (replace-match "+" t t path)))
10029 (throw 'match t)))
10030 (save-excursion
10031 (skip-chars-backward "a-zA-Z_")
10032 (when (and (memq 'camel org-activate-links)
10033 (looking-at org-camel-regexp))
10034 (setq type "camel" path (match-string 0))
10035 (if (equal (char-before) ?*)
10036 (setq path (concat "*" path))))
10037 (throw 'match t)))
10038 (unless path
10039 (error "No link found"))
10040 ;; Remove any trailing spaces in path
10041 (if (string-match " +\\'" path)
10042 (setq path (replace-match "" t t path)))
10043
10044 (cond
10045
10046 ((equal type "mailto")
10047 (let ((cmd (car org-link-mailto-program))
10048 (args (cdr org-link-mailto-program)) args1
10049 (address path) (subject "") a)
10050 (if (string-match "\\(.*\\)::\\(.*\\)" path)
10051 (setq address (match-string 1 path)
10052 subject (org-link-escape (match-string 2 path))))
10053 (while args
10054 (cond
10055 ((not (stringp (car args))) (push (pop args) args1))
10056 (t (setq a (pop args))
10057 (if (string-match "%a" a)
10058 (setq a (replace-match address t t a)))
10059 (if (string-match "%s" a)
10060 (setq a (replace-match subject t t a)))
10061 (push a args1))))
10062 (apply cmd (nreverse args1))))
10063
10064 ((member type '("http" "https" "ftp" "news"))
10065 (browse-url (concat type ":" path)))
10066
10067 ((string= type "tags")
10068 (org-tags-view in-emacs path))
10069 ((or (string= type "camel")
10070 (string= type "thisfile"))
10071 (if in-emacs
10072 (switch-to-buffer-other-window
10073 (org-get-buffer-for-internal-link (current-buffer)))
10074 (org-mark-ring-push))
10075 (org-link-search
10076 path
10077 (cond ((equal in-emacs '(4)) 'occur)
10078 ((equal in-emacs '(16)) 'org-occur)
10079 (t nil))))
10080
10081 ((string= type "file")
10082 (if (string-match "::\\([0-9]+\\)\\'" path)
10083 (setq line (string-to-number (match-string 1 path))
10084 path (substring path 0 (match-beginning 0)))
10085 (if (string-match "::\\(.+\\)\\'" path)
10086 (setq search (match-string 1 path)
10087 path (substring path 0 (match-beginning 0)))))
10088 (org-open-file path in-emacs line search))
10089
10090 ((string= type "news")
10091 (org-follow-gnus-link path))
10092
10093 ((string= type "bbdb")
10094 (org-follow-bbdb-link path))
10095
10096 ((string= type "info")
10097 (org-follow-info-link path))
10098
10099 ((string= type "gnus")
10100 (let (group article)
10101 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10102 (error "Error in Gnus link"))
10103 (setq group (match-string 1 path)
10104 article (match-string 3 path))
10105 (org-follow-gnus-link group article)))
10106
10107 ((string= type "vm")
10108 (let (folder article)
10109 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10110 (error "Error in VM link"))
10111 (setq folder (match-string 1 path)
10112 article (match-string 3 path))
10113 ;; in-emacs is the prefix arg, will be interpreted as read-only
10114 (org-follow-vm-link folder article in-emacs)))
10115
10116 ((string= type "wl")
10117 (let (folder article)
10118 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10119 (error "Error in Wanderlust link"))
10120 (setq folder (match-string 1 path)
10121 article (match-string 3 path))
10122 (org-follow-wl-link folder article)))
10123
10124 ((string= type "mhe")
10125 (let (folder article)
10126 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10127 (error "Error in MHE link"))
10128 (setq folder (match-string 1 path)
10129 article (match-string 3 path))
10130 (org-follow-mhe-link folder article)))
10131
10132 ((string= type "rmail")
10133 (let (folder article)
10134 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
10135 (error "Error in RMAIL link"))
10136 (setq folder (match-string 1 path)
10137 article (match-string 3 path))
10138 (org-follow-rmail-link folder article)))
10139
10140 ((string= type "shell")
10141 (let ((cmd path))
10142 (while (string-match "@{" cmd) ; FIXME: not needed for [[]] links
10143 (setq cmd (replace-match "<" t t cmd)))
10144 (while (string-match "@}" cmd) ; FIXME: not needed for [[]] links
10145 (setq cmd (replace-match ">" t t cmd)))
10146 (if (or (not org-confirm-shell-link-function)
10147 (funcall org-confirm-shell-link-function
10148 (format "Execute \"%s\" in shell? "
10149 (org-add-props cmd nil
10150 'face 'org-warning))))
10151 (progn
10152 (message "Executing %s" cmd)
10153 (shell-command cmd))
10154 (error "Abort"))))
10155
10156 ((string= type "elisp")
10157 (let ((cmd path))
10158 (if (or (not org-confirm-elisp-link-function)
10159 (funcall org-confirm-elisp-link-function
10160 (format "Execute \"%s\" as elisp? "
10161 (org-add-props cmd nil
10162 'face 'org-warning))))
10163 (message "%s => %s" cmd (eval (read cmd)))
10164 (error "Abort"))))
10165
10166 (t
10167 (browse-url-at-point))))))
10168
10169 (defun org-link-expand-abbrev (link)
10170 "Apply replacements as defined in `org-link-abbrev-alist."
10171 (if (string-match "^\\([a-zA-Z]+\\)\\(::\\(.*\\)\\)?$" link)
10172 (let* ((key (match-string 1 link))
10173 (as (or (assoc key org-link-abbrev-alist-local)
10174 (assoc key org-link-abbrev-alist)))
10175 (tag (and (match-end 2) (match-string 3 link)))
10176 rpl)
10177 (if (not as)
10178 link
10179 (setq rpl (cdr as))
10180 (cond
10181 ((symbolp rpl) (funcall rpl tag))
10182 ((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
10183 (t (concat rpl tag)))))
10184 link))
10185
10186 (defun org-link-search (s &optional type)
10187 "Search for a link search option.
10188 When S is a CamelCaseWord, search for a target, or for a sentence containing
10189 the words. If S is surrounded by forward slashes, it is interpreted as a
10190 regular expression. In org-mode files, this will create an `org-occur'
10191 sparse tree. In ordinary files, `occur' will be used to list matches.
10192 If the current buffer is in `dired-mode', grep will be used to search
10193 in all files."
10194 (let ((case-fold-search t)
10195 (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " "))
10196 (pos (point))
10197 (pre "") (post "")
10198 words re0 re1 re2 re3 re4 re5 re2a reall camel)
10199 (cond
10200 ;; First check if there are any special
10201 ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
10202 ;; Now try the builtin stuff
10203 ((save-excursion
10204 (goto-char (point-min))
10205 (and
10206 (re-search-forward
10207 (concat "<<" (regexp-quote s0) ">>") nil t)
10208 (setq pos (match-beginning 0))))
10209 ;; There is an exact target for this
10210 (goto-char pos))
10211 ((string-match "^/\\(.*\\)/$" s)
10212 ;; A regular expression
10213 (cond
10214 ((org-mode-p)
10215 (org-occur (match-string 1 s)))
10216 ;;((eq major-mode 'dired-mode)
10217 ;; (grep (concat "grep -n -e '" (match-string 1 s) "' *")))
10218 (t (org-do-occur (match-string 1 s)))))
10219 ((or (setq camel (string-match (concat "^" org-camel-regexp "$") s))
10220 t)
10221 ;; A camel or a normal search string
10222 (when (equal (string-to-char s) ?*)
10223 ;; Anchor on headlines, post may include tags.
10224 (setq pre "^\\*+[ \t]*\\(?:\\sw+\\)?[ \t]*"
10225 post "[ \t]*\\(?:[ \t]+:[a-zA-Z_@0-9:+]:[ \t]*\\)?$"
10226 s (substring s 1)))
10227 (remove-text-properties
10228 0 (length s)
10229 '(face nil mouse-face nil keymap nil fontified nil) s)
10230 ;; Make a series of regular expressions to find a match
10231 (setq words
10232 (if camel
10233 (org-camel-to-words s)
10234 (org-split-string s "[ \n\r\t]+"))
10235 re0 (concat "\\(<<" (regexp-quote s0) ">>\\)")
10236 re2 (concat "[ \t\r\n]\\(" (mapconcat 'downcase words "[ \t]+") "\\)[ \t\r\n]")
10237 re2a (concat "[ \t\r\n]\\(" (mapconcat 'downcase words "[ \t\r\n]+") "\\)[ \t\r\n]")
10238 re4 (concat "[^a-zA-Z_]\\(" (mapconcat 'downcase words "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
10239 re1 (concat pre re2 post)
10240 re3 (concat pre re4 post)
10241 re5 (concat pre ".*" re4)
10242 re2 (concat pre re2)
10243 re2a (concat pre re2a)
10244 re4 (concat pre re4)
10245 reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2
10246 "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\("
10247 re5 "\\)"
10248 ))
10249 (cond
10250 ((eq type 'org-occur) (org-occur reall))
10251 ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
10252 (t (goto-char (point-min))
10253 (if (or (org-search-not-link re0 nil t)
10254 (org-search-not-link re1 nil t)
10255 (org-search-not-link re2 nil t)
10256 (org-search-not-link re2a nil t)
10257 (org-search-not-link re3 nil t)
10258 (org-search-not-link re4 nil t)
10259 (org-search-not-link re5 nil t)
10260 )
10261 (goto-char (match-beginning 1))
10262 (goto-char pos)
10263 (error "No match")))))
10264 (t
10265 ;; Normal string-search
10266 (goto-char (point-min))
10267 (if (search-forward s nil t)
10268 (goto-char (match-beginning 0))
10269 (error "No match"))))
10270 (and (org-mode-p) (org-show-context 'link-search))))
10271
10272 (defun org-search-not-link (&rest args)
10273 "Execute `re-search-forward', but only accept matches that are not a link."
10274 (catch 'exit
10275 (let (p1)
10276 (while (apply 're-search-forward args)
10277 (setq p1 (point))
10278 (if (not (save-match-data
10279 (and (re-search-backward "\\[\\[" nil t)
10280 (looking-at org-bracket-link-regexp)
10281 (<= (match-beginning 0) p1)
10282 (>= (match-end 0) p1))))
10283 (progn (goto-char (match-end 0))
10284 (throw 'exit (point)))
10285 (goto-char (match-end 0)))))))
10286
10287 (defun org-get-buffer-for-internal-link (buffer)
10288 "Return a buffer to be used for displaying the link target of internal links."
10289 (cond
10290 ((not org-display-internal-link-with-indirect-buffer)
10291 buffer)
10292 ((string-match "(Clone)$" (buffer-name buffer))
10293 (message "Buffer is already a clone, not making another one")
10294 ;; we also do not modify visibility in this case
10295 buffer)
10296 (t ; make a new indirect buffer for displaying the link
10297 (let* ((bn (buffer-name buffer))
10298 (ibn (concat bn "(Clone)"))
10299 (ib (or (get-buffer ibn) (make-indirect-buffer buffer ibn 'clone))))
10300 (with-current-buffer ib (org-overview))
10301 ib))))
10302
10303 (defun org-do-occur (regexp &optional cleanup)
10304 "Call the Emacs command `occur'.
10305 If CLEANUP is non-nil, remove the printout of the regular expression
10306 in the *Occur* buffer. This is useful if the regex is long and not useful
10307 to read."
10308 (occur regexp)
10309 (when cleanup
10310 (let ((cwin (selected-window)) win beg end)
10311 (when (setq win (get-buffer-window "*Occur*"))
10312 (select-window win))
10313 (goto-char (point-min))
10314 (when (re-search-forward "match[a-z]+" nil t)
10315 (setq beg (match-end 0))
10316 (if (re-search-forward "^[ \t]*[0-9]+" nil t)
10317 (setq end (1- (match-beginning 0)))))
10318 (and beg end (let ((buffer-read-only)) (delete-region beg end)))
10319 (goto-char (point-min))
10320 (select-window cwin))))
10321
10322 (defvar org-mark-ring nil
10323 "Mark ring for positions before jumps in Org-mode.")
10324 (defvar org-mark-ring-last-goto nil
10325 "Last position in the mark ring used to go back.")
10326 ;; Fill and close the ring
10327 (setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is reloaded
10328 (loop for i from 1 to org-mark-ring-length do
10329 (push (make-marker) org-mark-ring))
10330 (setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring)
10331 org-mark-ring)
10332
10333 (defun org-mark-ring-push (&optional pos buffer)
10334 "Put the current position or POS into the mark ring and rotate it."
10335 (interactive)
10336 (setq pos (or pos (point)))
10337 (setq org-mark-ring (nthcdr (1- org-mark-ring-length) org-mark-ring))
10338 (move-marker (car org-mark-ring)
10339 (or pos (point))
10340 (or buffer (current-buffer)))
10341 (message
10342 (substitute-command-keys
10343 "Position saved to mark ring, go back with \\[org-mark-ring-goto].")))
10344
10345 (defun org-mark-ring-goto (&optional n)
10346 "Jump to the previous position in the mark ring.
10347 With prefix arg N, jump back that many stored positions. When
10348 called several times in succession, walk through the entire ring.
10349 Org-mode commands jumping to a different position in the current file,
10350 or to another Org-mode file, automatically push the old position
10351 onto the ring."
10352 (interactive "p")
10353 (let (p m)
10354 (if (eq last-command this-command)
10355 (setq p (nthcdr n (or org-mark-ring-last-goto org-mark-ring)))
10356 (setq p org-mark-ring))
10357 (setq org-mark-ring-last-goto p)
10358 (setq m (car p))
10359 (switch-to-buffer (marker-buffer m))
10360 (goto-char m)
10361 (if (or (org-invisible-p) (org-invisible-p2)) (org-show-context 'mark-goto))))
10362
10363 (defun org-camel-to-words (s)
10364 "Split \"CamelCaseWords\" to (\"Camel\" \"Case\" \"Words\")."
10365 (let ((case-fold-search nil)
10366 words)
10367 (while (string-match "[a-z][A-Z]" s)
10368 (push (substring s 0 (1+ (match-beginning 0))) words)
10369 (setq s (substring s (1+ (match-beginning 0)))))
10370 (nreverse (cons s words))))
10371
10372 (defun org-remove-angle-brackets (s)
10373 (if (equal (substring s 0 1) "<") (setq s (substring s 1)))
10374 (if (equal (substring s -1) ">") (setq s (substring s 0 -1)))
10375 s)
10376 (defun org-add-angle-brackets (s)
10377 (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s)))
10378 (if (equal (substring s -1) ">") nil (setq s (concat s ">")))
10379 s)
10380
10381 (defun org-follow-timestamp-link ()
10382 (cond
10383 ((org-at-date-range-p t)
10384 (let ((org-agenda-start-on-weekday)
10385 (t1 (match-string 1))
10386 (t2 (match-string 2)))
10387 (setq t1 (time-to-days (org-time-string-to-time t1))
10388 t2 (time-to-days (org-time-string-to-time t2)))
10389 (org-agenda-list nil t1 (1+ (- t2 t1)))))
10390 ((org-at-timestamp-p t)
10391 (org-agenda-list nil (time-to-days (org-time-string-to-time
10392 (substring (match-string 1) 0 10)))
10393 1))
10394 (t (error "This should not happen"))))
10395
10396
10397 (defun org-follow-bbdb-link (name)
10398 "Follow a BBDB link to NAME."
10399 (require 'bbdb)
10400 (let ((inhibit-redisplay t)
10401 (bbdb-electric-p nil))
10402 (catch 'exit
10403 ;; Exact match on name
10404 (bbdb-name (concat "\\`" name "\\'") nil)
10405 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
10406 ;; Exact match on name
10407 (bbdb-company (concat "\\`" name "\\'") nil)
10408 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
10409 ;; Partial match on name
10410 (bbdb-name name nil)
10411 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
10412 ;; Partial match on company
10413 (bbdb-company name nil)
10414 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
10415 ;; General match including network address and notes
10416 (bbdb name nil)
10417 (when (= 0 (buffer-size (get-buffer "*BBDB*")))
10418 (delete-window (get-buffer-window "*BBDB*"))
10419 (error "No matching BBDB record")))))
10420
10421
10422 (defun org-follow-info-link (name)
10423 "Follow an info file & node link to NAME."
10424 (if (or (string-match "\\(.*\\)::?\\(.*\\)" name)
10425 (string-match "\\(.*\\)" name))
10426 (progn
10427 (require 'info)
10428 (if (match-string 2 name) ; If there isn't a node, choose "Top"
10429 (Info-find-node (match-string 1 name) (match-string 2 name))
10430 (Info-find-node (match-string 1 name) "Top")))
10431 (message (concat "Could not open: " name))))
10432
10433 (defun org-follow-gnus-link (&optional group article)
10434 "Follow a Gnus link to GROUP and ARTICLE."
10435 (require 'gnus)
10436 (funcall (cdr (assq 'gnus org-link-frame-setup)))
10437 (if gnus-other-frame-object (select-frame gnus-other-frame-object))
10438 (if group (gnus-fetch-group group))
10439 (if article
10440 (or (gnus-summary-goto-article article nil 'force)
10441 (if (fboundp 'gnus-summary-insert-cached-articles)
10442 (progn
10443 (gnus-summary-insert-cached-articles)
10444 (gnus-summary-goto-article article nil 'force))
10445 (message "Message could not be found.")))))
10446
10447 (defun org-follow-vm-link (&optional folder article readonly)
10448 "Follow a VM link to FOLDER and ARTICLE."
10449 (require 'vm)
10450 (setq article (org-add-angle-brackets article))
10451 (if (string-match "^//\\([a-zA-Z]+@\\)?\\([^:]+\\):\\(.*\\)" folder)
10452 ;; ange-ftp or efs or tramp access
10453 (let ((user (or (match-string 1 folder) (user-login-name)))
10454 (host (match-string 2 folder))
10455 (file (match-string 3 folder)))
10456 (cond
10457 ((featurep 'tramp)
10458 ;; use tramp to access the file
10459 (if (featurep 'xemacs)
10460 (setq folder (format "[%s@%s]%s" user host file))
10461 (setq folder (format "/%s@%s:%s" user host file))))
10462 (t
10463 ;; use ange-ftp or efs
10464 (require (if (featurep 'xemacs) 'efs 'ange-ftp))
10465 (setq folder (format "/%s@%s:%s" user host file))))))
10466 (when folder
10467 (funcall (cdr (assq 'vm org-link-frame-setup)) folder readonly)
10468 (sit-for 0.1)
10469 (when article
10470 (vm-select-folder-buffer)
10471 (widen)
10472 (let ((case-fold-search t))
10473 (goto-char (point-min))
10474 (if (not (re-search-forward
10475 (concat "^" "message-id: *" (regexp-quote article))))
10476 (error "Could not find the specified message in this folder"))
10477 (vm-isearch-update)
10478 (vm-isearch-narrow)
10479 (vm-beginning-of-message)
10480 (vm-summarize)))))
10481
10482 (defun org-follow-wl-link (folder article)
10483 "Follow a Wanderlust link to FOLDER and ARTICLE."
10484 (setq article (org-add-angle-brackets article))
10485 (wl-summary-goto-folder-subr folder 'no-sync t nil t)
10486 (if article (wl-summary-jump-to-msg-by-message-id article ">"))
10487 (wl-summary-redisplay))
10488
10489 (defun org-follow-rmail-link (folder article)
10490 "Follow an RMAIL link to FOLDER and ARTICLE."
10491 (setq article (org-add-angle-brackets article))
10492 (let (message-number)
10493 (save-excursion
10494 (save-window-excursion
10495 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
10496 (setq message-number
10497 (save-restriction
10498 (widen)
10499 (goto-char (point-max))
10500 (if (re-search-backward
10501 (concat "^Message-ID:\\s-+" (regexp-quote
10502 (or article "")))
10503 nil t)
10504 (rmail-what-message))))))
10505 (if message-number
10506 (progn
10507 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
10508 (rmail-show-message message-number)
10509 message-number)
10510 (error "Message not found"))))
10511
10512 ;; mh-e integration based on planner-mode
10513 (defun org-mhe-get-message-real-folder ()
10514 "Return the name of the current message real folder, so if you use
10515 sequences, it will now work."
10516 (save-excursion
10517 (let* ((folder
10518 (if (equal major-mode 'mh-folder-mode)
10519 mh-current-folder
10520 ;; Refer to the show buffer
10521 mh-show-folder-buffer))
10522 (end-index
10523 (if (boundp 'mh-index-folder)
10524 (min (length mh-index-folder) (length folder))))
10525 )
10526 ;; a simple test on mh-index-data does not work, because
10527 ;; mh-index-data is always nil in a show buffer.
10528 (if (and (boundp 'mh-index-folder)
10529 (string= mh-index-folder (substring folder 0 end-index)))
10530 (if (equal major-mode 'mh-show-mode)
10531 (save-window-excursion
10532 (when (buffer-live-p (get-buffer folder))
10533 (progn
10534 (pop-to-buffer folder)
10535 (org-mhe-get-message-folder-from-index)
10536 )
10537 ))
10538 (org-mhe-get-message-folder-from-index)
10539 )
10540 folder
10541 )
10542 )))
10543
10544 (defun org-mhe-get-message-folder-from-index ()
10545 "Returns the name of the message folder in a index folder buffer."
10546 (save-excursion
10547 (mh-index-previous-folder)
10548 (re-search-forward "^\\(+.*\\)$" nil t)
10549 (message (match-string 1))))
10550
10551 (defun org-mhe-get-message-folder ()
10552 "Return the name of the current message folder. Be careful if you
10553 use sequences."
10554 (save-excursion
10555 (if (equal major-mode 'mh-folder-mode)
10556 mh-current-folder
10557 ;; Refer to the show buffer
10558 mh-show-folder-buffer)))
10559
10560 (defun org-mhe-get-message-num ()
10561 "Return the number of the current message. Be careful if you
10562 use sequences."
10563 (save-excursion
10564 (if (equal major-mode 'mh-folder-mode)
10565 (mh-get-msg-num nil)
10566 ;; Refer to the show buffer
10567 (mh-show-buffer-message-number))))
10568
10569 (defun org-mhe-get-header (header)
10570 "Return a header of the message in folder mode. This will create a
10571 show buffer for the corresponding message. If you have a more clever
10572 idea..."
10573 (let* ((folder (org-mhe-get-message-folder))
10574 (num (org-mhe-get-message-num))
10575 (buffer (get-buffer-create (concat "show-" folder)))
10576 (header-field))
10577 (with-current-buffer buffer
10578 (mh-display-msg num folder)
10579 (if (equal major-mode 'mh-folder-mode)
10580 (mh-header-display)
10581 (mh-show-header-display))
10582 (set-buffer buffer)
10583 (setq header-field (mh-get-header-field header))
10584 (if (equal major-mode 'mh-folder-mode)
10585 (mh-show)
10586 (mh-show-show))
10587 header-field)))
10588
10589 (defun org-follow-mhe-link (folder article)
10590 "Follow an MHE link to FOLDER and ARTICLE.
10591 If ARTICLE is nil FOLDER is shown. If the configuration variable
10592 `org-mhe-search-all-folders' is t and `mh-searcher' is pick,
10593 ARTICLE is searched in all folders. Indexed searches (swish++,
10594 namazu, and others supported by MH-E) will always search in all
10595 folders."
10596 (require 'mh-e)
10597 (require 'mh-search)
10598 (require 'mh-utils)
10599 (mh-find-path)
10600 (if (not article)
10601 (mh-visit-folder (mh-normalize-folder-name folder))
10602 (setq article (org-add-angle-brackets article))
10603 (mh-search-choose)
10604 (if (equal mh-searcher 'pick)
10605 (progn
10606 (mh-search folder (list "--message-id" article))
10607 (when (and org-mhe-search-all-folders
10608 (not (org-mhe-get-message-real-folder)))
10609 (kill-this-buffer)
10610 (mh-search "+" (list "--message-id" article))))
10611 (mh-search "+" article))
10612 (if (org-mhe-get-message-real-folder)
10613 (mh-show-msg 1)
10614 (kill-this-buffer)
10615 (error "Message not found"))))
10616
10617 ;; BibTeX links
10618
10619 ;; Use the custom search meachnism to construct and use search strings for
10620 ;; file links to BibTeX database entries.
10621
10622 (defun org-create-file-search-in-bibtex ()
10623 "Create the search string and description for a BibTeX database entry."
10624 (when (eq major-mode 'bibtex-mode)
10625 ;; yes, we want to construct this search string.
10626 ;; Make a good description for this entry, using names, year and the title
10627 ;; Put it into the `description' variable which is dynamically scoped.
10628 (let ((bibtex-autokey-names 1)
10629 (bibtex-autokey-names-stretch 1)
10630 (bibtex-autokey-name-case-convert-function 'identity)
10631 (bibtex-autokey-name-separator " & ")
10632 (bibtex-autokey-additional-names " et al.")
10633 (bibtex-autokey-year-length 4)
10634 (bibtex-autokey-name-year-separator " ")
10635 (bibtex-autokey-titlewords 3)
10636 (bibtex-autokey-titleword-separator " ")
10637 (bibtex-autokey-titleword-case-convert-function 'identity)
10638 (bibtex-autokey-titleword-length 'infty)
10639 (bibtex-autokey-year-title-separator ": "))
10640 (setq description (bibtex-generate-autokey)))
10641 ;; Now parse the entry, get the key and return it.
10642 (save-excursion
10643 (bibtex-beginning-of-entry)
10644 (cdr (assoc "=key=" (bibtex-parse-entry))))))
10645
10646 (defun org-execute-file-search-in-bibtex (s)
10647 "Find the link search string S as a key for a database entry."
10648 (when (eq major-mode 'bibtex-mode)
10649 ;; Yes, we want to do the search in this file.
10650 ;; We construct a regexp that searches for "@entrytype{" followed by the key
10651 (goto-char (point-min))
10652 (and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*"
10653 (regexp-quote s) "[ \t\n]*,") nil t)
10654 (goto-char (match-beginning 0)))
10655 (if (and (match-beginning 0) (equal current-prefix-arg '(16)))
10656 ;; Use double prefix to indicate that any web link should be browsed
10657 (let ((b (current-buffer)) (p (point)))
10658 ;; Restore the window configuration because we just use the web link
10659 (set-window-configuration org-window-config-before-follow-link)
10660 (save-excursion (set-buffer b) (goto-char p)
10661 (bibtex-url)))
10662 (recenter 0)) ; Move entry start to beginning of window
10663 ;; return t to indicate that the search is done.
10664 t))
10665
10666 ;; Finally add the functions to the right hooks.
10667 (add-hook 'org-create-file-search-functions 'org-create-file-search-in-bibtex)
10668 (add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-bibtex)
10669
10670 ;; end of Bibtex link setup
10671
10672 (defun org-upgrade-old-links (&optional query-description)
10673 "Transfer old <...> style links to new [[...]] style links.
10674 With arg query-description, ask at each match for a description text to use
10675 for this link."
10676 (interactive (list (y-or-n-p "Would you like to be queried for a description at each link?")))
10677 (save-excursion
10678 (goto-char (point-min))
10679 (let ((re (concat "\\([^[]\\)<\\("
10680 "\\(" (mapconcat 'identity org-link-types "\\|")
10681 "\\):"
10682 "[^" org-non-link-chars "]+\\)>"))
10683 l1 l2 (cnt 0))
10684 (while (re-search-forward re nil t)
10685 (setq cnt (1+ cnt)
10686 l1 (org-match-string-no-properties 2)
10687 l2 (save-match-data (org-link-escape l1)))
10688 (when query-description (setq l1 (read-string "Desc: " l1)))
10689 (if (equal l1 l2)
10690 (replace-match (concat (match-string 1) "[[" l1 "]]") t t)
10691 (replace-match (concat (match-string 1) "[[" l2 "][" l1 "]]") t t)))
10692 (message "%d matches have beed treated" cnt))))
10693
10694 (defun org-open-file (path &optional in-emacs line search)
10695 "Open the file at PATH.
10696 First, this expands any special file name abbreviations. Then the
10697 configuration variable `org-file-apps' is checked if it contains an
10698 entry for this file type, and if yes, the corresponding command is launched.
10699 If no application is found, Emacs simply visits the file.
10700 With optional argument IN-EMACS, Emacs will visit the file.
10701 Optional LINE specifies a line to go to, optional SEARCH a string to
10702 search for. If LINE or SEARCH is given, the file will always be
10703 opened in Emacs.
10704 If the file does not exist, an error is thrown."
10705 (setq in-emacs (or in-emacs line search))
10706 (let* ((file (if (equal path "")
10707 buffer-file-name
10708 (substitute-in-file-name (expand-file-name path))))
10709 (apps (append org-file-apps (org-default-apps)))
10710 (remp (and (assq 'remote apps) (org-file-remote-p file)))
10711 (dirp (if remp nil (file-directory-p file)))
10712 (dfile (downcase file))
10713 (old-buffer (current-buffer))
10714 (old-pos (point))
10715 (old-mode major-mode)
10716 ext cmd)
10717 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
10718 (setq ext (match-string 1 dfile))
10719 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
10720 (setq ext (match-string 1 dfile))))
10721 (if in-emacs
10722 (setq cmd 'emacs)
10723 (setq cmd (or (and remp (cdr (assoc 'remote apps)))
10724 (and dirp (cdr (assoc 'directory apps)))
10725 (cdr (assoc ext apps))
10726 (cdr (assoc t apps)))))
10727 (when (eq cmd 'mailcap)
10728 (require 'mailcap)
10729 (mailcap-parse-mailcaps)
10730 (let* ((mime-type (mailcap-extension-to-mime (or ext "")))
10731 (command (mailcap-mime-info mime-type)))
10732 (if (stringp command)
10733 (setq cmd command)
10734 (setq cmd 'emacs))))
10735 (if (and (not (eq cmd 'emacs)) ; Emacs has not problems with non-ex files
10736 (not (file-exists-p file))
10737 (not org-open-non-existing-files))
10738 (error "No such file: %s" file))
10739 (cond
10740 ((and (stringp cmd) (not (string-match "^\\s-*$" cmd)))
10741 ;; Remove quotes around the file name - we'll use shell-quote-argument.
10742 (if (string-match "['\"]%s['\"]" cmd)
10743 (setq cmd (replace-match "%s" t t cmd)))
10744 (setq cmd (format cmd (shell-quote-argument file)))
10745 (save-window-excursion
10746 (shell-command (concat cmd " &"))))
10747 ((or (stringp cmd)
10748 (eq cmd 'emacs))
10749 ; (unless (equal (file-truename file) (file-truename (or buffer-file-name "")))
10750 ; (funcall (cdr (assq 'file org-link-frame-setup)) file))
10751 (funcall (cdr (assq 'file org-link-frame-setup)) file)
10752 (if line (goto-line line)
10753 (if search (org-link-search search))))
10754 ((consp cmd)
10755 (eval cmd))
10756 (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
10757 (and (org-mode-p) (eq old-mode 'org-mode)
10758 (or (not (equal old-buffer (current-buffer)))
10759 (not (equal old-pos (point))))
10760 (org-mark-ring-push old-pos old-buffer))))
10761
10762 (defun org-default-apps ()
10763 "Return the default applications for this operating system."
10764 (cond
10765 ((eq system-type 'darwin)
10766 org-file-apps-defaults-macosx)
10767 ((eq system-type 'windows-nt)
10768 org-file-apps-defaults-windowsnt)
10769 (t org-file-apps-defaults-gnu)))
10770
10771 (defun org-expand-file-name (path)
10772 "Replace special path abbreviations and expand the file name."
10773 (expand-file-name path))
10774
10775 (defvar ange-ftp-name-format) ; to silence the XEmacs compiler.
10776 (defun org-file-remote-p (file)
10777 "Test whether FILE specifies a location on a remote system.
10778 Return non-nil if the location is indeed remote.
10779
10780 For example, the filename \"/user@host:/foo\" specifies a location
10781 on the system \"/user@host:\"."
10782 (cond ((fboundp 'file-remote-p)
10783 (file-remote-p file))
10784 ((fboundp 'tramp-handle-file-remote-p)
10785 (tramp-handle-file-remote-p file))
10786 ((and (boundp 'ange-ftp-name-format)
10787 (string-match (car ange-ftp-name-format) file))
10788 t)
10789 (t nil)))
10790
10791 (defvar org-insert-link-history nil
10792 "Minibuffer history for links inserted with `org-insert-link'.")
10793
10794 (defvar org-stored-links nil
10795 "Contains the links stored with `org-store-link'.")
10796
10797 ;;;###autoload
10798 (defun org-store-link (arg)
10799 "\\<org-mode-map>Store an org-link to the current location.
10800 This link can later be inserted into an org-buffer with
10801 \\[org-insert-link].
10802 For some link types, a prefix arg is interpreted:
10803 For links to usenet articles, arg negates `org-usenet-links-prefer-google'.
10804 For file links, arg negates `org-context-in-file-links'."
10805 (interactive "P")
10806 (let (link cpltxt desc description search txt (pos (point)))
10807 (cond
10808
10809 ((eq major-mode 'bbdb-mode)
10810 (setq cpltxt (concat
10811 "bbdb:"
10812 (or (bbdb-record-name (bbdb-current-record))
10813 (bbdb-record-company (bbdb-current-record))))
10814 link (org-make-link cpltxt)))
10815
10816 ((eq major-mode 'Info-mode)
10817 (setq link (org-make-link "info:"
10818 (file-name-nondirectory Info-current-file)
10819 ":" Info-current-node))
10820 (setq cpltxt (concat (file-name-nondirectory Info-current-file)
10821 ":" Info-current-node)))
10822
10823 ((eq major-mode 'calendar-mode)
10824 (let ((cd (calendar-cursor-to-date)))
10825 (setq link
10826 (format-time-string
10827 (car org-time-stamp-formats)
10828 (apply 'encode-time
10829 (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
10830 nil nil nil))))))
10831
10832 ((or (eq major-mode 'vm-summary-mode)
10833 (eq major-mode 'vm-presentation-mode))
10834 (and (eq major-mode 'vm-presentation-mode) (vm-summarize))
10835 (vm-follow-summary-cursor)
10836 (save-excursion
10837 (vm-select-folder-buffer)
10838 (let* ((message (car vm-message-pointer))
10839 (folder buffer-file-name)
10840 (subject (vm-su-subject message))
10841 (author (vm-su-full-name message))
10842 (message-id (vm-su-message-id message)))
10843 (setq message-id (org-remove-angle-brackets message-id))
10844 (setq folder (abbreviate-file-name folder))
10845 (if (string-match (concat "^" (regexp-quote vm-folder-directory))
10846 folder)
10847 (setq folder (replace-match "" t t folder)))
10848 (setq cpltxt (concat author " on: " subject))
10849 (setq link (org-make-link "vm:" folder "#" message-id)))))
10850
10851 ((eq major-mode 'wl-summary-mode)
10852 (let* ((msgnum (wl-summary-message-number))
10853 (message-id (elmo-message-field wl-summary-buffer-elmo-folder
10854 msgnum 'message-id))
10855 (wl-message-entity (elmo-msgdb-overview-get-entity
10856 msgnum (wl-summary-buffer-msgdb)))
10857 (author (wl-summary-line-from)) ; FIXME: correct?
10858 (subject "???")) ; FIXME:
10859 (setq message-id (org-remove-angle-brackets message-id))
10860 (setq cpltxt (concat author " on: " subject))
10861 (setq link (org-make-link "wl:" wl-summary-buffer-folder-name
10862 "#" message-id))))
10863
10864 ((or (equal major-mode 'mh-folder-mode)
10865 (equal major-mode 'mh-show-mode))
10866 (let ((from-header (org-mhe-get-header "From:"))
10867 (to-header (org-mhe-get-header "To:"))
10868 (subject (org-mhe-get-header "Subject:")))
10869 (setq cpltxt (concat from-header " on: " subject))
10870 (setq link (org-make-link "mhe:" (org-mhe-get-message-real-folder) "#"
10871 (org-remove-angle-brackets
10872 (org-mhe-get-header "Message-Id:"))))))
10873
10874 ((eq major-mode 'rmail-mode)
10875 (save-excursion
10876 (save-restriction
10877 (rmail-narrow-to-non-pruned-header)
10878 (let ((folder buffer-file-name)
10879 (message-id (mail-fetch-field "message-id"))
10880 (author (mail-fetch-field "from"))
10881 (subject (mail-fetch-field "subject")))
10882 (setq message-id (org-remove-angle-brackets message-id))
10883 (setq cpltxt (concat author " on: " subject))
10884 (setq link (org-make-link "rmail:" folder "#" message-id))))))
10885
10886 ((eq major-mode 'gnus-group-mode)
10887 (let ((group (cond ((fboundp 'gnus-group-group-name) ; depending on Gnus
10888 (gnus-group-group-name)) ; version
10889 ((fboundp 'gnus-group-name)
10890 (gnus-group-name))
10891 (t "???"))))
10892 (setq cpltxt (concat
10893 (if (org-xor arg org-usenet-links-prefer-google)
10894 "http://groups.google.com/groups?group="
10895 "gnus:")
10896 group)
10897 link (org-make-link cpltxt))))
10898
10899 ((memq major-mode '(gnus-summary-mode gnus-article-mode))
10900 (require 'gnus-sum)
10901 (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary))
10902 (gnus-summary-beginning-of-article)
10903 (let* ((group (car gnus-article-current))
10904 (article (cdr gnus-article-current))
10905 (header (gnus-summary-article-header article))
10906 (author (mail-header-from header))
10907 (message-id (mail-header-id header))
10908 (date (mail-header-date header))
10909 (subject (gnus-summary-subject-string)))
10910 (setq cpltxt (concat author " on: " subject))
10911 (if (org-xor arg org-usenet-links-prefer-google)
10912 (setq link
10913 (concat
10914 cpltxt "\n "
10915 (format "http://groups.google.com/groups?as_umsgid=%s"
10916 (org-fixup-message-id-for-http message-id))))
10917 (setq link (org-make-link "gnus:" group
10918 "#" (number-to-string article))))))
10919
10920 ((eq major-mode 'w3-mode)
10921 (setq cpltxt (url-view-url t)
10922 link (org-make-link cpltxt)))
10923 ((eq major-mode 'w3m-mode)
10924 (setq cpltxt (or w3m-current-title w3m-current-url)
10925 link (org-make-link w3m-current-url)))
10926
10927 ((setq search (run-hook-with-args-until-success
10928 'org-create-file-search-functions))
10929 (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
10930 "::" search))
10931 (setq cpltxt (or description link)))
10932
10933 ((eq major-mode 'image-mode)
10934 (setq cpltxt (concat "file:"
10935 (abbreviate-file-name buffer-file-name))
10936 link (org-make-link cpltxt)))
10937
10938 ((eq major-mode 'dired-mode)
10939 ;; link to the file in the current line
10940 (setq cpltxt (concat "file:"
10941 (abbreviate-file-name
10942 (expand-file-name
10943 (dired-get-filename nil t))))
10944 link (org-make-link cpltxt)))
10945
10946 ((and buffer-file-name (org-mode-p))
10947 ;; Just link to current headline
10948 (setq cpltxt (concat "file:"
10949 (abbreviate-file-name buffer-file-name)))
10950 ;; Add a context search string
10951 (when (org-xor org-context-in-file-links arg)
10952 ;; Check if we are on a target
10953 (if (save-excursion
10954 (skip-chars-forward "^>\n\r")
10955 (and (re-search-backward "<<" nil t)
10956 (looking-at "<<\\(.*?\\)>>")
10957 (<= (match-beginning 0) pos)
10958 (>= (match-end 0) pos)))
10959 (setq cpltxt (concat cpltxt "::" (match-string 1)))
10960 (setq txt (cond
10961 ((org-on-heading-p) nil)
10962 ((org-region-active-p)
10963 (buffer-substring (region-beginning) (region-end)))
10964 (t (buffer-substring (point-at-bol) (point-at-eol)))))
10965 (when (or (null txt) (string-match "\\S-" txt))
10966 (setq cpltxt
10967 (concat cpltxt "::"
10968 (if org-file-link-context-use-camel-case
10969 (org-make-org-heading-camel txt)
10970 (org-make-org-heading-search-string txt)))
10971 desc "NONE"))))
10972 (if (string-match "::\\'" cpltxt)
10973 (setq cpltxt (substring cpltxt 0 -2)))
10974 (setq link (org-make-link cpltxt)))
10975
10976 (buffer-file-name
10977 ;; Just link to this file here.
10978 (setq cpltxt (concat "file:"
10979 (abbreviate-file-name buffer-file-name)))
10980 ;; Add a context string
10981 (when (org-xor org-context-in-file-links arg)
10982 (setq txt (if (org-region-active-p)
10983 (buffer-substring (region-beginning) (region-end))
10984 (buffer-substring (point-at-bol) (point-at-eol))))
10985 ;; Only use search option if there is some text.
10986 (when (string-match "\\S-" txt)
10987 (setq cpltxt
10988 (concat cpltxt "::"
10989 (if org-file-link-context-use-camel-case
10990 (org-make-org-heading-camel txt)
10991 (org-make-org-heading-search-string txt)))
10992 desc "NONE")))
10993 (setq link (org-make-link cpltxt)))
10994
10995 ((interactive-p)
10996 (error "Cannot link to a buffer which is not visiting a file"))
10997
10998 (t (setq link nil)))
10999
11000 (if (consp link) (setq cpltxt (car link) link (cdr link)))
11001 (setq link (or link cpltxt)
11002 desc (or desc cpltxt))
11003 (if (equal desc "NONE") (setq desc nil))
11004
11005 (if (and (interactive-p) link)
11006 (progn
11007 (setq org-stored-links
11008 (cons (list cpltxt link desc) org-stored-links))
11009 (message "Stored: %s" (or cpltxt link)))
11010 (org-make-link-string link desc))))
11011
11012 (defun org-make-org-heading-search-string (&optional string heading)
11013 "Make search string for STRING or current headline."
11014 (interactive)
11015 (let ((s (or string (org-get-heading))))
11016 (unless (and string (not heading))
11017 ;; We are using a headline, clean up garbage in there.
11018 (if (string-match org-todo-regexp s)
11019 (setq s (replace-match "" t t s)))
11020 (if (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" s)
11021 (setq s (replace-match "" t t s)))
11022 (setq s (org-trim s))
11023 (if (string-match (concat "^\\(" org-quote-string "\\|"
11024 org-comment-string "\\)") s)
11025 (setq s (replace-match "" t t s)))
11026 (while (string-match org-ts-regexp s)
11027 (setq s (replace-match "" t t s))))
11028 (while (string-match "[^a-zA-Z_0-9 \t]+" s)
11029 (setq s (replace-match " " t t s)))
11030 (or string (setq s (concat "*" s))) ; Add * for headlines
11031 (mapconcat 'identity (org-split-string s "[ \t]+") " ")))
11032
11033 (defun org-make-org-heading-camel (&optional string heading)
11034 "Make a CamelCase string for STRING or the current headline."
11035 (interactive)
11036 (let ((s (or string (org-get-heading))))
11037 (unless (and string (not heading))
11038 ;; We are using a headline, clean up garbage in there.
11039 (if (string-match org-todo-regexp s)
11040 (setq s (replace-match "" t t s)))
11041 (if (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" s)
11042 (setq s (replace-match "" t t s)))
11043 (setq s (org-trim s))
11044 (if (string-match (concat "^\\(" org-quote-string "\\|"
11045 org-comment-string "\\)") s)
11046 (setq s (replace-match "" t t s)))
11047 (while (string-match org-ts-regexp s)
11048 (setq s (replace-match "" t t s))))
11049 (while (string-match "[^a-zA-Z_ \t]+" s)
11050 (setq s (replace-match " " t t s)))
11051 (or string (setq s (concat "*" s))) ; Add * for headlines
11052 (mapconcat 'capitalize (org-split-string s "[ \t]+") "")))
11053
11054 (defun org-make-link (&rest strings)
11055 "Concatenate STRINGS, format resulting string with `org-link-format'."
11056 (format org-link-format (apply 'concat strings)))
11057
11058 (defun org-make-link-string (link &optional description)
11059 "Make a link with brackets, consisting of LINK and DESCRIPTION."
11060 (if (eq org-link-style 'plain)
11061 (if (equal description link)
11062 link
11063 (concat description "\n" link))
11064 (when (stringp description)
11065 ;; Remove brackets from the description, they are fatal.
11066 (while (string-match "\\[\\|\\]" description)
11067 (setq description (replace-match "" t t description))))
11068 (when (equal (org-link-escape link) description)
11069 ;; No description needed, it is identical
11070 (setq description nil))
11071 (when (and (not description)
11072 (not (equal link (org-link-escape link))))
11073 (setq description link))
11074 (concat "[[" (org-link-escape link) "]"
11075 (if description (concat "[" description "]") "")
11076 "]")))
11077
11078 (defconst org-link-escape-chars '(("[" . "%5B") ("]" . "%5D") (" " . "%20"))
11079 "Association list of escapes for some characters problematic in links.")
11080
11081 (defun org-link-escape (text)
11082 "Escape charaters in TEXT that are problematic for links."
11083 (when text
11084 (let ((re (mapconcat (lambda (x) (regexp-quote (car x)))
11085 org-link-escape-chars "\\|")))
11086 (while (string-match re text)
11087 (setq text
11088 (replace-match
11089 (cdr (assoc (match-string 0 text) org-link-escape-chars))
11090 t t text)))
11091 text)))
11092
11093 (defun org-link-unescape (text)
11094 "Reverse the action of `org-link-escape'."
11095 (when text
11096 (let ((re (mapconcat (lambda (x) (regexp-quote (cdr x)))
11097 org-link-escape-chars "\\|")))
11098 (while (string-match re text)
11099 (setq text
11100 (replace-match
11101 (car (rassoc (match-string 0 text) org-link-escape-chars))
11102 t t text)))
11103 text)))
11104
11105 (defun org-xor (a b)
11106 "Exclusive or."
11107 (if a (not b) b))
11108
11109 (defun org-get-header (header)
11110 "Find a header field in the current buffer."
11111 (save-excursion
11112 (goto-char (point-min))
11113 (let ((case-fold-search t) s)
11114 (cond
11115 ((eq header 'from)
11116 (if (re-search-forward "^From:\\s-+\\(.*\\)" nil t)
11117 (setq s (match-string 1)))
11118 (while (string-match "\"" s)
11119 (setq s (replace-match "" t t s)))
11120 (if (string-match "[<(].*" s)
11121 (setq s (replace-match "" t t s))))
11122 ((eq header 'message-id)
11123 (if (re-search-forward "^message-id:\\s-+\\(.*\\)" nil t)
11124 (setq s (match-string 1))))
11125 ((eq header 'subject)
11126 (if (re-search-forward "^subject:\\s-+\\(.*\\)" nil t)
11127 (setq s (match-string 1)))))
11128 (if (string-match "\\`[ \t\]+" s) (setq s (replace-match "" t t s)))
11129 (if (string-match "[ \t\]+\\'" s) (setq s (replace-match "" t t s)))
11130 s)))
11131
11132
11133 (defun org-fixup-message-id-for-http (s)
11134 "Replace special characters in a message id, so it can be used in an http query."
11135 (while (string-match "<" s)
11136 (setq s (replace-match "%3C" t t s)))
11137 (while (string-match ">" s)
11138 (setq s (replace-match "%3E" t t s)))
11139 (while (string-match "@" s)
11140 (setq s (replace-match "%40" t t s)))
11141 s)
11142
11143 (defun org-insert-link (&optional complete-file)
11144 "Insert a link. At the prompt, enter the link.
11145
11146 Completion can be used to select a link previously stored with
11147 `org-store-link'. When the empty string is entered (i.e. if you just
11148 press RET at the prompt), the link defaults to the most recently
11149 stored link. As SPC triggers completion in the minibuffer, you need to
11150 use M-SPC or C-q SPC to force the insertion of a space character.
11151
11152 You will also be prompted for a description, and if one is given, it will
11153 be displayed in the buffer instead of the link.
11154
11155 If there is already a link at point, this command will allow you to edit link
11156 and description parts.
11157
11158 With a \\[universal-argument] prefix, prompts for a file to link to. The file name can be
11159 selected using completion. The path to the file will be relative to
11160 the current directory if the file is in the current directory or a
11161 subdirectory. Otherwise, the link will be the absolute path as
11162 completed in the minibuffer (i.e. normally ~/path/to/file).
11163
11164 With two \\[universal-argument] prefixes, enforce an absolute path even if the file
11165 is in the current directory or below.
11166 With three \\[universal-argument] prefixes, negate the meaning of
11167 `org-keep-stored-link-after-insertion'."
11168 (interactive "P")
11169 (let (link desc entry remove file (pos (point)))
11170 (cond
11171 ((save-excursion
11172 (skip-chars-forward "^]\n\r")
11173 (and (re-search-backward "\\[\\[" nil t)
11174 (looking-at org-bracket-link-regexp)
11175 (<= (match-beginning 0) pos)
11176 (>= (match-end 0) pos)))
11177 ;; We do have a link at point, and we are going to edit it.
11178 (setq remove (list (match-beginning 0) (match-end 0)))
11179 (setq desc (if (match-end 3) (org-match-string-no-properties 3)))
11180 (setq link (read-string "Link: "
11181 (org-link-unescape
11182 (org-match-string-no-properties 1)))))
11183 ((equal complete-file '(4))
11184 ;; Completing read for file names.
11185 (setq file (read-file-name "File: "))
11186 (let ((pwd (file-name-as-directory (expand-file-name ".")))
11187 (pwd1 (file-name-as-directory (abbreviate-file-name
11188 (expand-file-name ".")))))
11189 (cond
11190 ((equal complete-file '(16))
11191 (setq link (org-make-link
11192 "file:"
11193 (abbreviate-file-name (expand-file-name file)))))
11194 ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
11195 (setq link (org-make-link "file:" (match-string 1 file))))
11196 ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
11197 (expand-file-name file))
11198 (setq link (org-make-link
11199 "file:" (match-string 1 (expand-file-name file)))))
11200 (t (setq link (org-make-link "file:" file))))))
11201 (t
11202 ;; Read link, with completion for stored links.
11203 (setq link (org-completing-read
11204 "Link: " org-stored-links nil nil nil
11205 org-insert-link-history
11206 (or (car (car org-stored-links)))))
11207 (setq entry (assoc link org-stored-links))
11208 (if (funcall (if (equal complete-file '(64)) 'not 'identity)
11209 (not org-keep-stored-link-after-insertion))
11210 (setq org-stored-links (delq (assoc link org-stored-links)
11211 org-stored-links)))
11212 (setq link (if entry (nth 1 entry) link)
11213 desc (or desc (nth 2 entry)))))
11214
11215 (if (string-match org-plain-link-re link)
11216 ;; URL-like link, normalize the use of angular brackets.
11217 (setq link (org-make-link (org-remove-angle-brackets link))))
11218
11219 ;; Check if we are linking to the current file with a search option
11220 ;; If yes, simplify the link by using only the search option.
11221 (when (and buffer-file-name
11222 (string-match "\\<file:\\(.+?\\)::\\([^>]+\\)" link))
11223 (let* ((path (match-string 1 link))
11224 (case-fold-search nil)
11225 (search (match-string 2 link)))
11226 (save-match-data
11227 (if (equal (file-truename buffer-file-name) (file-truename path))
11228 ;; We are linking to this same file, with a search option
11229 (setq link search)))))
11230
11231 ;; Check if we can/should use a relative path. If yes, simplify the link
11232 (when (string-match "\\<file:\\(.*\\)" link)
11233 (let* ((path (match-string 1 link))
11234 (case-fold-search nil))
11235 (cond
11236 ((eq org-link-file-path-type 'absolute)
11237 (setq path (abbreviate-file-name (expand-file-name path))))
11238 ((eq org-link-file-path-type 'noabbrev)
11239 (setq path (expand-file-name path)))
11240 ((eq org-link-file-path-type 'relative)
11241 (setq path (file-relative-name path)))
11242 (t
11243 (save-match-data
11244 (if (string-match (concat "^" (regexp-quote
11245 (file-name-as-directory
11246 (expand-file-name "."))))
11247 (expand-file-name path))
11248 ;; We are linking a file with relative path name.
11249 (setq path (substring (expand-file-name path)
11250 (match-end 0)))))))
11251 (setq link (concat "file:" path))))
11252
11253 (setq desc (read-string "Description: " desc))
11254 (unless (string-match "\\S-" desc) (setq desc nil))
11255 (if remove (apply 'delete-region remove))
11256 (insert (org-make-link-string link desc))))
11257
11258 (defun org-completing-read (&rest args)
11259 (let ((minibuffer-local-completion-map
11260 (copy-keymap minibuffer-local-completion-map)))
11261 (define-key minibuffer-local-completion-map " " 'self-insert-command)
11262 (apply 'completing-read args)))
11263
11264 ;;; Hooks for remember.el
11265
11266 (defvar org-finish-function nil)
11267
11268 ;;;###autoload
11269 (defun org-remember-annotation ()
11270 "Return a link to the current location as an annotation for remember.el.
11271 If you are using Org-mode files as target for data storage with
11272 remember.el, then the annotations should include a link compatible with the
11273 conventions in Org-mode. This function returns such a link."
11274 (org-store-link nil))
11275
11276 (defconst org-remember-help
11277 "Select a destination location for the note.
11278 UP/DOWN=headline TAB=cycle visibility [Q]uit RET/<left>/<right>=Store
11279 RET at beg-of-buf -> Append to file as level 2 headline
11280 RET on headline -> Store as sublevel entry to current headline
11281 <left>/<right> -> before/after current headline, same headings level")
11282
11283 ;;;###autoload
11284 (defun org-remember-apply-template ()
11285 "Initialize *remember* buffer with template, invoke `org-mode'.
11286 This function should be placed into `remember-mode-hook' and in fact requires
11287 to be run from that hook to fucntion properly."
11288 (if org-remember-templates
11289
11290 (let* ((entry (if (= (length org-remember-templates) 1)
11291 (cdar org-remember-templates)
11292 (message "Select template: %s"
11293 (mapconcat
11294 (lambda (x) (char-to-string (car x)))
11295 org-remember-templates " "))
11296 (cdr (assoc (read-char-exclusive) org-remember-templates))))
11297 (tpl (car entry))
11298 (file (if (consp (cdr entry)) (nth 1 entry)))
11299 (v-t (format-time-string (car org-time-stamp-formats) (org-current-time)))
11300 (v-T (format-time-string (cdr org-time-stamp-formats) (org-current-time)))
11301 (v-u (concat "[" (substring v-t 1 -1) "]"))
11302 (v-U (concat "[" (substring v-T 1 -1) "]"))
11303 (v-a annotation) ; defined in `remember-mode'
11304 (v-i initial) ; defined in `remember-mode'
11305 (v-n user-full-name)
11306 )
11307 (unless tpl (setq tpl "") (message "No template") (ding))
11308 (insert tpl) (goto-char (point-min))
11309 (while (re-search-forward "%\\([tTuTai]\\)" nil t)
11310 (when (and initial (equal (match-string 0) "%i"))
11311 (save-match-data
11312 (let* ((lead (buffer-substring
11313 (point-at-bol) (match-beginning 0))))
11314 (setq v-i (mapconcat 'identity
11315 (org-split-string initial "\n")
11316 (concat "\n" lead))))))
11317 (replace-match
11318 (or (eval (intern (concat "v-" (match-string 1)))) "")
11319 t t))
11320 (let ((org-startup-folded nil)
11321 (org-startup-with-deadline-check nil))
11322 (org-mode))
11323 (if (and file (string-match "\\S-" file) (not (file-directory-p file)))
11324 (org-set-local 'org-default-notes-file file))
11325 (goto-char (point-min))
11326 (if (re-search-forward "%\\?" nil t) (replace-match "")))
11327 (let ((org-startup-folded nil)
11328 (org-startup-with-deadline-check nil))
11329 (org-mode)))
11330 (org-set-local 'org-finish-function 'remember-buffer))
11331
11332 ;;;###autoload
11333 (defun org-remember-handler ()
11334 "Store stuff from remember.el into an org file.
11335 First prompts for an org file. If the user just presses return, the value
11336 of `org-default-notes-file' is used.
11337 Then the command offers the headings tree of the selected file in order to
11338 file the text at a specific location.
11339 You can either immediately press RET to get the note appended to the
11340 file, or you can use vertical cursor motion and visibility cycling (TAB) to
11341 find a better place. Then press RET or <left> or <right> in insert the note.
11342
11343 Key Cursor position Note gets inserted
11344 -----------------------------------------------------------------------------
11345 RET buffer-start as level 2 heading at end of file
11346 RET on headline as sublevel of the heading at cursor
11347 RET no heading at cursor position, level taken from context.
11348 Or use prefix arg to specify level manually.
11349 <left> on headline as same level, before current heading
11350 <right> on headline as same level, after current heading
11351
11352 So the fastest way to store the note is to press RET RET to append it to
11353 the default file. This way your current train of thought is not
11354 interrupted, in accordance with the principles of remember.el. But with
11355 little extra effort, you can push it directly to the correct location.
11356
11357 Before being stored away, the function ensures that the text has a
11358 headline, i.e. a first line that starts with a \"*\". If not, a headline
11359 is constructed from the current date and some additional data.
11360
11361 If the variable `org-adapt-indentation' is non-nil, the entire text is
11362 also indented so that it starts in the same column as the headline
11363 \(i.e. after the stars).
11364
11365 See also the variable `org-reverse-note-order'."
11366 (catch 'quit
11367 (let* ((txt (buffer-substring (point-min) (point-max)))
11368 (fastp current-prefix-arg)
11369 (file (if fastp org-default-notes-file (org-get-org-file)))
11370 (visiting (find-buffer-visiting file))
11371 (org-startup-with-deadline-check nil)
11372 (org-startup-folded nil)
11373 (org-startup-align-all-tables nil)
11374 spos level indent reversed)
11375 ;; Modify text so that it becomes a nice subtree which can be inserted
11376 ;; into an org tree.
11377 (let* ((lines (split-string txt "\n"))
11378 first)
11379 ;; remove empty lines at the beginning
11380 (while (and lines (string-match "^[ \t]*\n" (car lines)))
11381 (setq lines (cdr lines)))
11382 (setq first (car lines) lines (cdr lines))
11383 (if (string-match "^\\*+" first)
11384 ;; Is already a headline
11385 (setq indent nil)
11386 ;; We need to add a headline: Use time and first buffer line
11387 (setq lines (cons first lines)
11388 first (concat "* " (current-time-string)
11389 " (" (remember-buffer-desc) ")")
11390 indent " "))
11391 (if (and org-adapt-indentation indent)
11392 (setq lines (mapcar (lambda (x) (concat indent x)) lines)))
11393 (setq txt (concat first "\n"
11394 (mapconcat 'identity lines "\n"))))
11395 ;; Find the file
11396 (if (not visiting)
11397 (find-file-noselect file))
11398 (with-current-buffer (get-file-buffer file)
11399 (save-excursion (and (goto-char (point-min))
11400 (not (re-search-forward "^\\* " nil t))
11401 (insert "\n* Notes\n")))
11402 (setq reversed (org-notes-order-reversed-p))
11403 (save-excursion
11404 (save-restriction
11405 (widen)
11406 ;; Ask the User for a location
11407 (setq spos (if fastp 1 (org-get-location
11408 (current-buffer)
11409 org-remember-help)))
11410 (if (not spos) (throw 'quit nil)) ; return nil to show we did
11411 ; not handle this note
11412 (goto-char spos)
11413 (cond ((bobp)
11414 ;; Put it at the start or end, as level 2
11415 (save-restriction
11416 (widen)
11417 (goto-char (if reversed (point-min) (point-max)))
11418 (if (not (bolp)) (newline))
11419 (org-paste-subtree 2 txt)))
11420 ((and (org-on-heading-p nil) (not current-prefix-arg))
11421 ;; Put it below this entry, at the beg/end of the subtree
11422 (org-back-to-heading)
11423 (setq level (funcall outline-level))
11424 (if reversed
11425 (outline-end-of-heading)
11426 (outline-end-of-subtree))
11427 (if (not (bolp)) (newline))
11428 (beginning-of-line 1)
11429 (org-paste-subtree (org-get-legal-level level 1) txt))
11430 (t
11431 ;; Put it right there, with automatic level determined by
11432 ;; org-paste-subtree or from prefix arg
11433 (org-paste-subtree current-prefix-arg txt)))
11434 (when remember-save-after-remembering
11435 (save-buffer)
11436 (if (not visiting) (kill-buffer (current-buffer)))))))))
11437 t) ;; return t to indicate that we took care of this note.
11438
11439 (defun org-get-org-file ()
11440 "Read a filename, with default directory `org-directory'."
11441 (let ((default (or org-default-notes-file remember-data-file)))
11442 (read-file-name (format "File name [%s]: " default)
11443 (file-name-as-directory org-directory)
11444 default)))
11445
11446 (defun org-notes-order-reversed-p ()
11447 "Check if the current file should receive notes in reversed order."
11448 (cond
11449 ((not org-reverse-note-order) nil)
11450 ((eq t org-reverse-note-order) t)
11451 ((not (listp org-reverse-note-order)) nil)
11452 (t (catch 'exit
11453 (let ((all org-reverse-note-order)
11454 entry)
11455 (while (setq entry (pop all))
11456 (if (string-match (car entry) buffer-file-name)
11457 (throw 'exit (cdr entry))))
11458 nil)))))
11459
11460 ;;; Tables
11461
11462 ;; Watch out: Here we are talking about two different kind of tables.
11463 ;; Most of the code is for the tables created with the Org-mode table editor.
11464 ;; Sometimes, we talk about tables created and edited with the table.el
11465 ;; Emacs package. We call the former org-type tables, and the latter
11466 ;; table.el-type tables.
11467
11468
11469 (defun org-before-change-function (beg end)
11470 "Every change indicates that a table might need an update."
11471 (setq org-table-may-need-update t))
11472
11473 (defconst org-table-line-regexp "^[ \t]*|"
11474 "Detects an org-type table line.")
11475 (defconst org-table-dataline-regexp "^[ \t]*|[^-]"
11476 "Detects an org-type table line.")
11477 (defconst org-table-auto-recalculate-regexp "^[ \t]*| *# *\\(|\\|$\\)"
11478 "Detects a table line marked for automatic recalculation.")
11479 (defconst org-table-recalculate-regexp "^[ \t]*| *[#*] *\\(|\\|$\\)"
11480 "Detects a table line marked for automatic recalculation.")
11481 (defconst org-table-calculate-mark-regexp "^[ \t]*| *[!$^_#*] *\\(|\\|$\\)"
11482 "Detects a table line marked for automatic recalculation.")
11483 (defconst org-table-hline-regexp "^[ \t]*|-"
11484 "Detects an org-type table hline.")
11485 (defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]"
11486 "Detects a table-type table hline.")
11487 (defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)"
11488 "Detects an org-type or table-type table.")
11489 (defconst org-table-border-regexp "^[ \t]*[^| \t]"
11490 "Searching from within a table (any type) this finds the first line
11491 outside the table.")
11492 (defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]"
11493 "Searching from within a table (any type) this finds the first line
11494 outside the table.")
11495
11496 (defun org-table-create-with-table.el ()
11497 "Use the table.el package to insert a new table.
11498 If there is already a table at point, convert between Org-mode tables
11499 and table.el tables."
11500 (interactive)
11501 (require 'table)
11502 (cond
11503 ((org-at-table.el-p)
11504 (if (y-or-n-p "Convert table to Org-mode table? ")
11505 (org-table-convert)))
11506 ((org-at-table-p)
11507 (if (y-or-n-p "Convert table to table.el table? ")
11508 (org-table-convert)))
11509 (t (call-interactively 'table-insert))))
11510
11511 (defun org-table-create-or-convert-from-region (arg)
11512 "Convert region to table, or create an empty table.
11513 If there is an active region, convert it to a table. If there is no such
11514 region, create an empty table."
11515 (interactive "P")
11516 (if (org-region-active-p)
11517 (org-table-convert-region (region-beginning) (region-end) arg)
11518 (org-table-create arg)))
11519
11520 (defun org-table-create (&optional size)
11521 "Query for a size and insert a table skeleton.
11522 SIZE is a string Columns x Rows like for example \"3x2\"."
11523 (interactive "P")
11524 (unless size
11525 (setq size (read-string
11526 (concat "Table size Columns x Rows [e.g. "
11527 org-table-default-size "]: ")
11528 "" nil org-table-default-size)))
11529
11530 (let* ((pos (point))
11531 (indent (make-string (current-column) ?\ ))
11532 (split (org-split-string size " *x *"))
11533 (rows (string-to-number (nth 1 split)))
11534 (columns (string-to-number (car split)))
11535 (line (concat (apply 'concat indent "|" (make-list columns " |"))
11536 "\n")))
11537 (if (string-match "^[ \t]*$" (buffer-substring-no-properties
11538 (point-at-bol) (point)))
11539 (beginning-of-line 1)
11540 (newline))
11541 ;; (mapcar (lambda (x) (insert line)) (make-list rows t))
11542 (dotimes (i rows) (insert line))
11543 (goto-char pos)
11544 (if (> rows 1)
11545 ;; Insert a hline after the first row.
11546 (progn
11547 (end-of-line 1)
11548 (insert "\n|-")
11549 (goto-char pos)))
11550 (org-table-align)))
11551
11552 (defun org-table-convert-region (beg0 end0 &optional nspace)
11553 "Convert region to a table.
11554 The region goes from BEG0 to END0, but these borders will be moved
11555 slightly, to make sure a beginning of line in the first line is included.
11556 When NSPACE is non-nil, it indicates the minimum number of spaces that
11557 separate columns (default: just one space)."
11558 (interactive "rP")
11559 (let* ((beg (min beg0 end0))
11560 (end (max beg0 end0))
11561 (tabsep t)
11562 re)
11563 (goto-char beg)
11564 (beginning-of-line 1)
11565 (setq beg (move-marker (make-marker) (point)))
11566 (goto-char end)
11567 (if (bolp) (backward-char 1) (end-of-line 1))
11568 (setq end (move-marker (make-marker) (point)))
11569 ;; Lets see if this is tab-separated material. If every nonempty line
11570 ;; contains a tab, we will assume that it is tab-separated material
11571 (if nspace
11572 (setq tabsep nil)
11573 (goto-char beg)
11574 (and (re-search-forward "^[^\n\t]+$" end t) (setq tabsep nil)))
11575 (if nspace (setq tabsep nil))
11576 (if tabsep
11577 (setq re "^\\|\t")
11578 (setq re (format "^ *\\| *\t *\\| \\{%d,\\}"
11579 (max 1 (prefix-numeric-value nspace)))))
11580 (goto-char beg)
11581 (while (re-search-forward re end t)
11582 (replace-match "|" t t))
11583 (goto-char beg)
11584 (insert " ")
11585 (org-table-align)))
11586
11587 (defun org-table-import (file arg)
11588 "Import FILE as a table.
11589 The file is assumed to be tab-separated. Such files can be produced by most
11590 spreadsheet and database applications. If no tabs (at least one per line)
11591 are found, lines will be split on whitespace into fields."
11592 (interactive "f\nP")
11593 (or (bolp) (newline))
11594 (let ((beg (point))
11595 (pm (point-max)))
11596 (insert-file-contents file)
11597 (org-table-convert-region beg (+ (point) (- (point-max) pm)) arg)))
11598
11599 (defun org-table-export ()
11600 "Export table as a tab-separated file.
11601 Such a file can be imported into a spreadsheet program like Excel."
11602 (interactive)
11603 (let* ((beg (org-table-begin))
11604 (end (org-table-end))
11605 (table (buffer-substring beg end))
11606 (file (read-file-name "Export table to: "))
11607 buf)
11608 (unless (or (not (file-exists-p file))
11609 (y-or-n-p (format "Overwrite file %s? " file)))
11610 (error "Abort"))
11611 (with-current-buffer (find-file-noselect file)
11612 (setq buf (current-buffer))
11613 (erase-buffer)
11614 (fundamental-mode)
11615 (insert table)
11616 (goto-char (point-min))
11617 (while (re-search-forward "^[ \t]*|[ \t]*" nil t)
11618 (replace-match "" t t)
11619 (end-of-line 1))
11620 (goto-char (point-min))
11621 (while (re-search-forward "[ \t]*|[ \t]*$" nil t)
11622 (replace-match "" t t)
11623 (goto-char (min (1+ (point)) (point-max))))
11624 (goto-char (point-min))
11625 (while (re-search-forward "^-[-+]*$" nil t)
11626 (replace-match "")
11627 (if (looking-at "\n")
11628 (delete-char 1)))
11629 (goto-char (point-min))
11630 (while (re-search-forward "[ \t]*|[ \t]*" nil t)
11631 (replace-match "\t" t t))
11632 (save-buffer))
11633 (kill-buffer buf)))
11634
11635 (defvar org-table-aligned-begin-marker (make-marker)
11636 "Marker at the beginning of the table last aligned.
11637 Used to check if cursor still is in that table, to minimize realignment.")
11638 (defvar org-table-aligned-end-marker (make-marker)
11639 "Marker at the end of the table last aligned.
11640 Used to check if cursor still is in that table, to minimize realignment.")
11641 (defvar org-table-last-alignment nil
11642 "List of flags for flushright alignment, from the last re-alignment.
11643 This is being used to correctly align a single field after TAB or RET.")
11644 (defvar org-table-last-column-widths nil
11645 "List of max width of fields in each column.
11646 This is being used to correctly align a single field after TAB or RET.")
11647
11648 (defvar org-last-recalc-line nil)
11649 (defconst org-narrow-column-arrow "=>"
11650 "Used as display property in narrowed table columns.")
11651
11652 (defun org-table-align ()
11653 "Align the table at point by aligning all vertical bars."
11654 (interactive)
11655 (let* (
11656 ;; Limits of table
11657 (beg (org-table-begin))
11658 (end (org-table-end))
11659 ;; Current cursor position
11660 (linepos (org-current-line))
11661 (colpos (org-table-current-column))
11662 (winstart (window-start))
11663 (winstartline (org-current-line (min winstart (1- (point-max)))))
11664 lines (new "") lengths l typenums ty fields maxfields i
11665 column
11666 (indent "") cnt frac
11667 rfmt hfmt
11668 (spaces '(1 . 1))
11669 (sp1 (car spaces))
11670 (sp2 (cdr spaces))
11671 (rfmt1 (concat
11672 (make-string sp2 ?\ ) "%%%s%ds" (make-string sp1 ?\ ) "|"))
11673 (hfmt1 (concat
11674 (make-string sp2 ?-) "%s" (make-string sp1 ?-) "+"))
11675 emptystrings links dates narrow fmax f1 len c e)
11676 (untabify beg end)
11677 (remove-text-properties beg end '(org-cwidth t org-dwidth t display t))
11678 ;; Check if we have links or dates
11679 (goto-char beg)
11680 (setq links (re-search-forward org-bracket-link-regexp end t))
11681 (goto-char beg)
11682 (setq dates (and org-display-custom-times
11683 (re-search-forward org-ts-regexp-both end t)))
11684 ;; Make sure the link properties are right
11685 (when links (goto-char beg) (while (org-activate-bracket-links end)))
11686 ;; Make sure the date properties are right
11687 (when dates (goto-char beg) (while (org-activate-dates end)))
11688
11689 ;; Check if we are narrowing any columns
11690 (goto-char beg)
11691 (setq narrow (and org-format-transports-properties-p
11692 (re-search-forward "<[0-9]+>" end t)))
11693 ;; Get the rows
11694 (setq lines (org-split-string
11695 (buffer-substring beg end) "\n"))
11696 ;; Store the indentation of the first line
11697 (if (string-match "^ *" (car lines))
11698 (setq indent (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
11699 ;; Mark the hlines by setting the corresponding element to nil
11700 ;; At the same time, we remove trailing space.
11701 (setq lines (mapcar (lambda (l)
11702 (if (string-match "^ *|-" l)
11703 nil
11704 (if (string-match "[ \t]+$" l)
11705 (substring l 0 (match-beginning 0))
11706 l)))
11707 lines))
11708 ;; Get the data fields by splitting the lines.
11709 (setq fields (mapcar
11710 (lambda (l)
11711 (org-split-string l " *| *"))
11712 (delq nil (copy-sequence lines))))
11713 ;; How many fields in the longest line?
11714 (condition-case nil
11715 (setq maxfields (apply 'max (mapcar 'length fields)))
11716 (error
11717 (kill-region beg end)
11718 (org-table-create org-table-default-size)
11719 (error "Empty table - created default table")))
11720 ;; A list of empty strings to fill any short rows on output
11721 (setq emptystrings (make-list maxfields ""))
11722 ;; Check for special formatting.
11723 (setq i -1)
11724 (while (< (setq i (1+ i)) maxfields) ;; Loop over all columns
11725 (setq column (mapcar (lambda (x) (or (nth i x) "")) fields))
11726 ;; Check if there is an explicit width specified
11727 (when (and org-table-limit-column-width narrow)
11728 (setq c column fmax nil)
11729 (while c
11730 (setq e (pop c))
11731 (if (and (stringp e) (string-match "^<\\([0-9]+\\)>$" e))
11732 (setq fmax (string-to-number (match-string 1 e)) c nil)))
11733 ;; Find fields that are wider than fmax, and shorten them
11734 (when fmax
11735 (loop for xx in column do
11736 (when (and (stringp xx)
11737 (> (org-string-width xx) fmax))
11738 (org-add-props xx nil
11739 'help-echo
11740 (concat "Clipped table field, use C-c ` to edit. Full value is:\n" (org-no-properties (copy-sequence xx))))
11741 (setq f1 (min fmax (or (string-match org-bracket-link-regexp xx) fmax)))
11742 (unless (> f1 1)
11743 (error "Cannot narrow field starting with wide link \"%s\""
11744 (match-string 0 xx)))
11745 (add-text-properties f1 (length xx) (list 'org-cwidth t) xx)
11746 (add-text-properties (- f1 2) f1
11747 (list 'display org-narrow-column-arrow)
11748 xx)))))
11749 ;; Get the maximum width for each column
11750 (push (apply 'max 1 (mapcar 'org-string-width column)) lengths)
11751 ;; Get the fraction of numbers, to decide about alignment of the column
11752 (setq cnt 0 frac 0.0)
11753 (loop for x in column do
11754 (if (equal x "")
11755 nil
11756 (setq frac ( / (+ (* frac cnt)
11757 (if (string-match org-table-number-regexp x) 1 0))
11758 (setq cnt (1+ cnt))))))
11759 (push (>= frac org-table-number-fraction) typenums))
11760 (setq lengths (nreverse lengths) typenums (nreverse typenums))
11761
11762 ;; Store the alignment of this table, for later editing of single fields
11763 (setq org-table-last-alignment typenums
11764 org-table-last-column-widths lengths)
11765
11766 ;; With invisible characters, `format' does not get the field width right
11767 ;; So we need to make these fields wide by hand.
11768 (when links
11769 (loop for i from 0 upto (1- maxfields) do
11770 (setq len (nth i lengths))
11771 (loop for j from 0 upto (1- (length fields)) do
11772 (setq c (nthcdr i (car (nthcdr j fields))))
11773 (if (and (stringp (car c))
11774 (string-match org-bracket-link-regexp (car c))
11775 (< (org-string-width (car c)) len))
11776 (setcar c (concat (car c) (make-string (- len (org-string-width (car c))) ?\ )))))))
11777
11778 ;; Compute the formats needed for output of the table
11779 (setq rfmt (concat indent "|") hfmt (concat indent "|"))
11780 (while (setq l (pop lengths))
11781 (setq ty (if (pop typenums) "" "-")) ; number types flushright
11782 (setq rfmt (concat rfmt (format rfmt1 ty l))
11783 hfmt (concat hfmt (format hfmt1 (make-string l ?-)))))
11784 (setq rfmt (concat rfmt "\n")
11785 hfmt (concat (substring hfmt 0 -1) "|\n"))
11786
11787 (setq new (mapconcat
11788 (lambda (l)
11789 (if l (apply 'format rfmt
11790 (append (pop fields) emptystrings))
11791 hfmt))
11792 lines ""))
11793 ;; Replace the old one
11794 (delete-region beg end)
11795 (move-marker end nil)
11796 (move-marker org-table-aligned-begin-marker (point))
11797 (insert new)
11798 (move-marker org-table-aligned-end-marker (point))
11799 (when (and orgtbl-mode (not (org-mode-p)))
11800 (goto-char org-table-aligned-begin-marker)
11801 (while (org-hide-wide-columns org-table-aligned-end-marker)))
11802 ;; Try to move to the old location
11803 (goto-line winstartline)
11804 (setq winstart (point-at-bol))
11805 (goto-line linepos)
11806 (set-window-start (selected-window) winstart 'noforce)
11807 (org-table-goto-column colpos)
11808 (setq org-table-may-need-update nil)
11809 ))
11810
11811 (defun org-string-width (s)
11812 "Compute width of string, ignoring invisible characters.
11813 This ignores character with invisibility property `org-link', and also
11814 characters with property `org-cwidth', because these will become invisible
11815 upon the next fontification round."
11816 (let (b l)
11817 (when (or (eq t buffer-invisibility-spec)
11818 (assq 'org-link buffer-invisibility-spec))
11819 (while (setq b (text-property-any 0 (length s)
11820 'invisible 'org-link s))
11821 (setq s (concat (substring s 0 b)
11822 (substring s (or (next-single-property-change
11823 b 'invisible s) (length s)))))))
11824 (while (setq b (text-property-any 0 (length s) 'org-cwidth t s))
11825 (setq s (concat (substring s 0 b)
11826 (substring s (or (next-single-property-change
11827 b 'org-cwidth s) (length s))))))
11828 (setq l (string-width s) b -1)
11829 (while (setq b (text-property-any (1+ b) (length s) 'org-dwidth t s))
11830 (setq l (- l (get-text-property b 'org-dwidth-n s))))
11831 l))
11832
11833 (defun org-table-begin (&optional table-type)
11834 "Find the beginning of the table and return its position.
11835 With argument TABLE-TYPE, go to the beginning of a table.el-type table."
11836 (save-excursion
11837 (if (not (re-search-backward
11838 (if table-type org-table-any-border-regexp
11839 org-table-border-regexp)
11840 nil t))
11841 (progn (goto-char (point-min)) (point))
11842 (goto-char (match-beginning 0))
11843 (beginning-of-line 2)
11844 (point))))
11845
11846 (defun org-table-end (&optional table-type)
11847 "Find the end of the table and return its position.
11848 With argument TABLE-TYPE, go to the end of a table.el-type table."
11849 (save-excursion
11850 (if (not (re-search-forward
11851 (if table-type org-table-any-border-regexp
11852 org-table-border-regexp)
11853 nil t))
11854 (goto-char (point-max))
11855 (goto-char (match-beginning 0)))
11856 (point-marker)))
11857
11858 (defun org-table-justify-field-maybe (&optional new)
11859 "Justify the current field, text to left, number to right.
11860 Optional argument NEW may specify text to replace the current field content."
11861 (cond
11862 ((and (not new) org-table-may-need-update)) ; Realignment will happen anyway
11863 ((org-at-table-hline-p))
11864 ((and (not new)
11865 (or (not (equal (marker-buffer org-table-aligned-begin-marker)
11866 (current-buffer)))
11867 (< (point) org-table-aligned-begin-marker)
11868 (>= (point) org-table-aligned-end-marker)))
11869 ;; This is not the same table, force a full re-align
11870 (setq org-table-may-need-update t))
11871 (t ;; realign the current field, based on previous full realign
11872 (let* ((pos (point)) s
11873 (col (org-table-current-column))
11874 (num (if (> col 0) (nth (1- col) org-table-last-alignment)))
11875 l f n o e)
11876 (when (> col 0)
11877 (skip-chars-backward "^|\n")
11878 (if (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)")
11879 (progn
11880 (setq s (match-string 1)
11881 o (match-string 0)
11882 l (max 1 (- (match-end 0) (match-beginning 0) 3))
11883 e (not (= (match-beginning 2) (match-end 2))))
11884 (setq f (format (if num " %%%ds %s" " %%-%ds %s")
11885 l (if e "|" (setq org-table-may-need-update t) ""))
11886 n (format f s))
11887 (if new
11888 (if (<= (length new) l) ;; FIXME: length -> str-width?
11889 (setq n (format f new))
11890 (setq n (concat new "|") org-table-may-need-update t)))
11891 (or (equal n o)
11892 (let (org-table-may-need-update)
11893 (replace-match n))))
11894 (setq org-table-may-need-update t))
11895 (goto-char pos))))))
11896
11897 (defun org-table-next-field ()
11898 "Go to the next field in the current table, creating new lines as needed.
11899 Before doing so, re-align the table if necessary."
11900 (interactive)
11901 (org-table-maybe-eval-formula)
11902 (org-table-maybe-recalculate-line)
11903 (if (and org-table-automatic-realign
11904 org-table-may-need-update)
11905 (org-table-align))
11906 (let ((end (org-table-end)))
11907 (if (org-at-table-hline-p)
11908 (end-of-line 1))
11909 (condition-case nil
11910 (progn
11911 (re-search-forward "|" end)
11912 (if (looking-at "[ \t]*$")
11913 (re-search-forward "|" end))
11914 (if (and (looking-at "-")
11915 org-table-tab-jumps-over-hlines
11916 (re-search-forward "^[ \t]*|\\([^-]\\)" end t))
11917 (goto-char (match-beginning 1)))
11918 (if (looking-at "-")
11919 (progn
11920 (beginning-of-line 0)
11921 (org-table-insert-row 'below))
11922 (if (looking-at " ") (forward-char 1))))
11923 (error
11924 (org-table-insert-row 'below)))))
11925
11926 (defun org-table-previous-field ()
11927 "Go to the previous field in the table.
11928 Before doing so, re-align the table if necessary."
11929 (interactive)
11930 (org-table-justify-field-maybe)
11931 (org-table-maybe-recalculate-line)
11932 (if (and org-table-automatic-realign
11933 org-table-may-need-update)
11934 (org-table-align))
11935 (if (org-at-table-hline-p)
11936 (end-of-line 1))
11937 (re-search-backward "|" (org-table-begin))
11938 (re-search-backward "|" (org-table-begin))
11939 (while (looking-at "|\\(-\\|[ \t]*$\\)")
11940 (re-search-backward "|" (org-table-begin)))
11941 (if (looking-at "| ?")
11942 (goto-char (match-end 0))))
11943
11944 (defun org-table-next-row ()
11945 "Go to the next row (same column) in the current table.
11946 Before doing so, re-align the table if necessary."
11947 (interactive)
11948 (org-table-maybe-eval-formula)
11949 (org-table-maybe-recalculate-line)
11950 (if (or (looking-at "[ \t]*$")
11951 (save-excursion (skip-chars-backward " \t") (bolp)))
11952 (newline)
11953 (if (and org-table-automatic-realign
11954 org-table-may-need-update)
11955 (org-table-align))
11956 (let ((col (org-table-current-column)))
11957 (beginning-of-line 2)
11958 (if (or (not (org-at-table-p))
11959 (org-at-table-hline-p))
11960 (progn
11961 (beginning-of-line 0)
11962 (org-table-insert-row 'below)))
11963 (org-table-goto-column col)
11964 (skip-chars-backward "^|\n\r")
11965 (if (looking-at " ") (forward-char 1)))))
11966
11967 (defun org-table-copy-down (n)
11968 "Copy a field down in the current column.
11969 If the field at the cursor is empty, copy into it the content of the nearest
11970 non-empty field above. With argument N, use the Nth non-empty field.
11971 If the current field is not empty, it is copied down to the next row, and
11972 the cursor is moved with it. Therefore, repeating this command causes the
11973 column to be filled row-by-row.
11974 If the variable `org-table-copy-increment' is non-nil and the field is an
11975 integer, it will be incremented while copying."
11976 (interactive "p")
11977 (let* ((colpos (org-table-current-column))
11978 (field (org-table-get-field))
11979 (non-empty (string-match "[^ \t]" field))
11980 (beg (org-table-begin))
11981 txt)
11982 (org-table-check-inside-data-field)
11983 (if non-empty
11984 (progn
11985 (setq txt (org-trim field))
11986 (org-table-next-row)
11987 (org-table-blank-field))
11988 (save-excursion
11989 (setq txt
11990 (catch 'exit
11991 (while (progn (beginning-of-line 1)
11992 (re-search-backward org-table-dataline-regexp
11993 beg t))
11994 (org-table-goto-column colpos t)
11995 (if (and (looking-at
11996 "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|")
11997 (= (setq n (1- n)) 0))
11998 (throw 'exit (match-string 1))))))))
11999 (if txt
12000 (progn
12001 (if (and org-table-copy-increment
12002 (string-match "^[0-9]+$" txt))
12003 (setq txt (format "%d" (+ (string-to-number txt) 1))))
12004 (insert txt)
12005 (org-table-maybe-recalculate-line)
12006 (org-table-align))
12007 (error "No non-empty field found"))))
12008
12009 (defun org-table-check-inside-data-field ()
12010 "Is point inside a table data field?
12011 I.e. not on a hline or before the first or after the last column?
12012 This actually throws an error, so it aborts the current command."
12013 (if (or (not (org-at-table-p))
12014 (= (org-table-current-column) 0)
12015 (org-at-table-hline-p)
12016 (looking-at "[ \t]*$"))
12017 (error "Not in table data field")))
12018
12019 (defvar org-table-clip nil
12020 "Clipboard for table regions.")
12021
12022 (defun org-table-blank-field ()
12023 "Blank the current table field or active region."
12024 (interactive)
12025 (org-table-check-inside-data-field)
12026 (if (and (interactive-p) (org-region-active-p))
12027 (let (org-table-clip)
12028 (org-table-cut-region (region-beginning) (region-end)))
12029 (skip-chars-backward "^|")
12030 (backward-char 1)
12031 (if (looking-at "|[^|\n]+")
12032 (let* ((pos (match-beginning 0))
12033 (match (match-string 0))
12034 (len (org-string-width match)))
12035 (replace-match (concat "|" (make-string (1- len) ?\ )))
12036 (goto-char (+ 2 pos))
12037 (substring match 1)))))
12038
12039 (defun org-table-get-field (&optional n replace)
12040 "Return the value of the field in column N of current row.
12041 N defaults to current field.
12042 If REPLACE is a string, replace field with this value. The return value
12043 is always the old value."
12044 (and n (org-table-goto-column n))
12045 (skip-chars-backward "^|\n")
12046 (backward-char 1)
12047 (if (looking-at "|[^|\r\n]*")
12048 (let* ((pos (match-beginning 0))
12049 (val (buffer-substring (1+ pos) (match-end 0))))
12050 (if replace
12051 (replace-match (concat "|" replace)))
12052 (goto-char (min (point-at-eol) (+ 2 pos)))
12053 val)
12054 (forward-char 1) ""))
12055
12056 (defun org-table-current-column ()
12057 "Find out which column we are in.
12058 When called interactively, column is also displayed in echo area."
12059 (interactive)
12060 (if (interactive-p) (org-table-check-inside-data-field))
12061 (save-excursion
12062 (let ((cnt 0) (pos (point)))
12063 (beginning-of-line 1)
12064 (while (search-forward "|" pos t)
12065 (setq cnt (1+ cnt)))
12066 (if (interactive-p) (message "This is table column %d" cnt))
12067 cnt)))
12068
12069 (defun org-table-goto-column (n &optional on-delim force)
12070 "Move the cursor to the Nth column in the current table line.
12071 With optional argument ON-DELIM, stop with point before the left delimiter
12072 of the field.
12073 If there are less than N fields, just go to after the last delimiter.
12074 However, when FORCE is non-nil, create new columns if necessary."
12075 (interactive "p")
12076 (let ((pos (point-at-eol)))
12077 (beginning-of-line 1)
12078 (when (> n 0)
12079 (while (and (> (setq n (1- n)) -1)
12080 (or (search-forward "|" pos t)
12081 (and force
12082 (progn (end-of-line 1)
12083 (skip-chars-backward "^|")
12084 (insert " | "))))))
12085 ; (backward-char 2) t)))))
12086 (when (and force (not (looking-at ".*|")))
12087 (save-excursion (end-of-line 1) (insert " | ")))
12088 (if on-delim
12089 (backward-char 1)
12090 (if (looking-at " ") (forward-char 1))))))
12091
12092 (defun org-at-table-p (&optional table-type)
12093 "Return t if the cursor is inside an org-type table.
12094 If TABLE-TYPE is non-nil, also check for table.el-type tables."
12095 (if org-enable-table-editor
12096 (save-excursion
12097 (beginning-of-line 1)
12098 (looking-at (if table-type org-table-any-line-regexp
12099 org-table-line-regexp)))
12100 nil))
12101
12102 (defun org-at-table.el-p ()
12103 "Return t if and only if we are at a table.el table."
12104 (and (org-at-table-p 'any)
12105 (save-excursion
12106 (goto-char (org-table-begin 'any))
12107 (looking-at org-table1-hline-regexp))))
12108
12109 (defun org-table-recognize-table.el ()
12110 "If there is a table.el table nearby, recognize it and move into it."
12111 (if org-table-tab-recognizes-table.el
12112 (if (org-at-table.el-p)
12113 (progn
12114 (beginning-of-line 1)
12115 (if (looking-at org-table-dataline-regexp)
12116 nil
12117 (if (looking-at org-table1-hline-regexp)
12118 (progn
12119 (beginning-of-line 2)
12120 (if (looking-at org-table-any-border-regexp)
12121 (beginning-of-line -1)))))
12122 (if (re-search-forward "|" (org-table-end t) t)
12123 (progn
12124 (require 'table)
12125 (if (table--at-cell-p (point))
12126 t
12127 (message "recognizing table.el table...")
12128 (table-recognize-table)
12129 (message "recognizing table.el table...done")))
12130 (error "This should not happen..."))
12131 t)
12132 nil)
12133 nil))
12134
12135 (defun org-at-table-hline-p ()
12136 "Return t if the cursor is inside a hline in a table."
12137 (if org-enable-table-editor
12138 (save-excursion
12139 (beginning-of-line 1)
12140 (looking-at org-table-hline-regexp))
12141 nil))
12142
12143 (defun org-table-insert-column ()
12144 "Insert a new column into the table."
12145 (interactive)
12146 (if (not (org-at-table-p))
12147 (error "Not at a table"))
12148 (org-table-find-dataline)
12149 (let* ((col (max 1 (org-table-current-column)))
12150 (beg (org-table-begin))
12151 (end (org-table-end))
12152 ;; Current cursor position
12153 (linepos (org-current-line))
12154 (colpos col))
12155 (goto-char beg)
12156 (while (< (point) end)
12157 (if (org-at-table-hline-p)
12158 nil
12159 (org-table-goto-column col t)
12160 (insert "| "))
12161 (beginning-of-line 2))
12162 (move-marker end nil)
12163 (goto-line linepos)
12164 (org-table-goto-column colpos)
12165 (org-table-align)
12166 (org-table-modify-formulas 'insert col)))
12167
12168 (defun org-table-find-dataline ()
12169 "Find a dataline in the current table, which is needed for column commands."
12170 (if (and (org-at-table-p)
12171 (not (org-at-table-hline-p)))
12172 t
12173 (let ((col (current-column))
12174 (end (org-table-end)))
12175 (move-to-column col)
12176 (while (and (< (point) end)
12177 (or (not (= (current-column) col))
12178 (org-at-table-hline-p)))
12179 (beginning-of-line 2)
12180 (move-to-column col))
12181 (if (and (org-at-table-p)
12182 (not (org-at-table-hline-p)))
12183 t
12184 (error
12185 "Please position cursor in a data line for column operations")))))
12186
12187 (defun org-table-delete-column ()
12188 "Delete a column from the table."
12189 (interactive)
12190 (if (not (org-at-table-p))
12191 (error "Not at a table"))
12192 (org-table-find-dataline)
12193 (org-table-check-inside-data-field)
12194 (let* ((col (org-table-current-column))
12195 (beg (org-table-begin))
12196 (end (org-table-end))
12197 ;; Current cursor position
12198 (linepos (org-current-line))
12199 (colpos col))
12200 (goto-char beg)
12201 (while (< (point) end)
12202 (if (org-at-table-hline-p)
12203 nil
12204 (org-table-goto-column col t)
12205 (and (looking-at "|[^|\n]+|")
12206 (replace-match "|")))
12207 (beginning-of-line 2))
12208 (move-marker end nil)
12209 (goto-line linepos)
12210 (org-table-goto-column colpos)
12211 (org-table-align)
12212 (org-table-modify-formulas 'remove col)))
12213
12214 (defun org-table-move-column-right ()
12215 "Move column to the right."
12216 (interactive)
12217 (org-table-move-column nil))
12218 (defun org-table-move-column-left ()
12219 "Move column to the left."
12220 (interactive)
12221 (org-table-move-column 'left))
12222
12223 (defun org-table-move-column (&optional left)
12224 "Move the current column to the right. With arg LEFT, move to the left."
12225 (interactive "P")
12226 (if (not (org-at-table-p))
12227 (error "Not at a table"))
12228 (org-table-find-dataline)
12229 (org-table-check-inside-data-field)
12230 (let* ((col (org-table-current-column))
12231 (col1 (if left (1- col) col))
12232 (beg (org-table-begin))
12233 (end (org-table-end))
12234 ;; Current cursor position
12235 (linepos (org-current-line))
12236 (colpos (if left (1- col) (1+ col))))
12237 (if (and left (= col 1))
12238 (error "Cannot move column further left"))
12239 (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$"))
12240 (error "Cannot move column further right"))
12241 (goto-char beg)
12242 (while (< (point) end)
12243 (if (org-at-table-hline-p)
12244 nil
12245 (org-table-goto-column col1 t)
12246 (and (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|")
12247 (replace-match "|\\2|\\1|")))
12248 (beginning-of-line 2))
12249 (move-marker end nil)
12250 (goto-line linepos)
12251 (org-table-goto-column colpos)
12252 (org-table-align)
12253 (org-table-modify-formulas 'swap col (if left (1- col) (1+ col)))))
12254
12255 (defun org-table-move-row-down ()
12256 "Move table row down."
12257 (interactive)
12258 (org-table-move-row nil))
12259 (defun org-table-move-row-up ()
12260 "Move table row up."
12261 (interactive)
12262 (org-table-move-row 'up))
12263
12264 (defun org-table-move-row (&optional up)
12265 "Move the current table line down. With arg UP, move it up."
12266 (interactive "P")
12267 (let ((col (current-column))
12268 (pos (point))
12269 (tonew (if up 0 2))
12270 txt)
12271 (beginning-of-line tonew)
12272 (if (not (org-at-table-p))
12273 (progn
12274 (goto-char pos)
12275 (error "Cannot move row further")))
12276 (goto-char pos)
12277 (beginning-of-line 1)
12278 (setq pos (point))
12279 (setq txt (buffer-substring (point) (1+ (point-at-eol))))
12280 (delete-region (point) (1+ (point-at-eol)))
12281 (beginning-of-line tonew)
12282 (insert txt)
12283 (beginning-of-line 0)
12284 (move-to-column col)))
12285
12286 (defun org-table-insert-row (&optional arg)
12287 "Insert a new row above the current line into the table.
12288 With prefix ARG, insert below the current line."
12289 (interactive "P")
12290 (if (not (org-at-table-p))
12291 (error "Not at a table"))
12292 (let* ((line (buffer-substring (point-at-bol) (point-at-eol)))
12293 (new (org-table-clean-line line)))
12294 ;; Fix the first field if necessary
12295 (if (string-match "^[ \t]*| *[#$] *|" line)
12296 (setq new (replace-match (match-string 0 line) t t new)))
12297 (beginning-of-line (if arg 2 1))
12298 (let (org-table-may-need-update) (insert-before-markers new "\n"))
12299 (beginning-of-line 0)
12300 (re-search-forward "| ?" (point-at-eol) t)
12301 (and org-table-may-need-update (org-table-align))))
12302
12303 (defun org-table-insert-hline (&optional arg)
12304 "Insert a horizontal-line below the current line into the table.
12305 With prefix ARG, insert above the current line."
12306 (interactive "P")
12307 (if (not (org-at-table-p))
12308 (error "Not at a table"))
12309 (let ((line (org-table-clean-line
12310 (buffer-substring (point-at-bol) (point-at-eol))))
12311 (col (current-column)))
12312 (while (string-match "|\\( +\\)|" line)
12313 (setq line (replace-match
12314 (concat "+" (make-string (- (match-end 1) (match-beginning 1))
12315 ?-) "|") t t line)))
12316 (and (string-match "\\+" line) (setq line (replace-match "|" t t line)))
12317 (beginning-of-line (if arg 1 2))
12318 (insert line "\n")
12319 (beginning-of-line (if arg 1 -1))
12320 (move-to-column col)))
12321
12322 (defun org-table-clean-line (s)
12323 "Convert a table line S into a string with only \"|\" and space.
12324 In particular, this does handle wide and invisible characters."
12325 (if (string-match "^[ \t]*|-" s)
12326 ;; It's a hline, just map the characters
12327 (setq s (mapconcat (lambda (x) (if (member x '(?| ?+)) "|" " ")) s ""))
12328 (while (string-match "|\\([ \t]*?[^ \t\r\n|][^\r\n|]*\\)|" s)
12329 (setq s (replace-match
12330 (concat "|" (make-string (org-string-width (match-string 1 s))
12331 ?\ ) "|")
12332 t t s)))
12333 s))
12334
12335 (defun org-table-kill-row ()
12336 "Delete the current row or horizontal line from the table."
12337 (interactive)
12338 (if (not (org-at-table-p))
12339 (error "Not at a table"))
12340 (let ((col (current-column)))
12341 (kill-region (point-at-bol) (min (1+ (point-at-eol)) (point-max)))
12342 (if (not (org-at-table-p)) (beginning-of-line 0))
12343 (move-to-column col)))
12344
12345 (defun org-table-sort-lines (beg end numericp)
12346 "Sort table lines in region.
12347 Point and mark define the first and last line to include. Both point and
12348 mark should be in the column that is used for sorting. For example, to
12349 sort according to column 3, put the mark in the first line to sort, in
12350 table column 3. Put point into the last line to be included in the sorting,
12351 also in table column 3. The command will prompt for the sorting method
12352 \(n for numerical, a for alphanumeric)."
12353 (interactive "r\nsSorting method: [n]=numeric [a]=alpha: ")
12354 (setq numericp (string-match "[nN]" numericp))
12355 (org-table-align) ;; Just to be safe
12356 (let* (bcol ecol cmp column lns)
12357 (goto-char beg)
12358 (org-table-check-inside-data-field)
12359 (setq column (org-table-current-column)
12360 beg (move-marker (make-marker) (point-at-bol)))
12361 (goto-char end)
12362 (org-table-check-inside-data-field)
12363 (setq end (move-marker (make-marker) (1+ (point-at-eol))))
12364 (untabify beg end)
12365 (goto-char beg)
12366 (org-table-goto-column column)
12367 (skip-chars-backward "^|")
12368 (setq bcol (current-column))
12369 (org-table-goto-column (1+ column))
12370 (skip-chars-backward "^|")
12371 (setq ecol (1- (current-column)))
12372 (setq cmp (if numericp
12373 (lambda (a b) (< (car a) (car b)))
12374 (lambda (a b) (string< (car a) (car b)))))
12375 (setq lns (mapcar (lambda(x) (cons (org-trim (substring x bcol ecol)) x))
12376 (org-split-string (buffer-substring beg end) "\n")))
12377 (if numericp
12378 (setq lns (mapcar (lambda(x)
12379 (cons (string-to-number (car x)) (cdr x)))
12380 lns)))
12381 (delete-region beg end)
12382 (move-marker beg nil)
12383 (move-marker end nil)
12384 (insert (mapconcat 'cdr (setq lns (sort lns cmp)) "\n") "\n")
12385 (message "%d lines sorted %s based on column %d"
12386 (length lns)
12387 (if numericp "numerically" "alphabetically") column)))
12388
12389 (defun org-table-cut-region (beg end)
12390 "Copy region in table to the clipboard and blank all relevant fields."
12391 (interactive "r")
12392 (org-table-copy-region beg end 'cut))
12393
12394 (defun org-table-copy-region (beg end &optional cut)
12395 "Copy rectangular region in table to clipboard.
12396 A special clipboard is used which can only be accessed
12397 with `org-table-paste-rectangle'."
12398 (interactive "rP")
12399 (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2
12400 region cols
12401 (rpl (if cut " " nil)))
12402 (goto-char beg)
12403 (org-table-check-inside-data-field)
12404 (setq l01 (count-lines (point-min) (point))
12405 c01 (org-table-current-column))
12406 (goto-char end)
12407 (org-table-check-inside-data-field)
12408 (setq l02 (count-lines (point-min) (point))
12409 c02 (org-table-current-column))
12410 (setq l1 (min l01 l02) l2 (max l01 l02)
12411 c1 (min c01 c02) c2 (max c01 c02))
12412 (catch 'exit
12413 (while t
12414 (catch 'nextline
12415 (if (> l1 l2) (throw 'exit t))
12416 (goto-line l1)
12417 (if (org-at-table-hline-p) (throw 'nextline (setq l1 (1+ l1))))
12418 (setq cols nil ic1 c1 ic2 c2)
12419 (while (< ic1 (1+ ic2))
12420 (push (org-table-get-field ic1 rpl) cols)
12421 (setq ic1 (1+ ic1)))
12422 (push (nreverse cols) region)
12423 (setq l1 (1+ l1)))))
12424 (setq org-table-clip (nreverse region))
12425 (if cut (org-table-align))
12426 org-table-clip))
12427
12428 (defun org-table-paste-rectangle ()
12429 "Paste a rectangular region into a table.
12430 The upper right corner ends up in the current field. All involved fields
12431 will be overwritten. If the rectangle does not fit into the present table,
12432 the table is enlarged as needed. The process ignores horizontal separator
12433 lines."
12434 (interactive)
12435 (unless (and org-table-clip (listp org-table-clip))
12436 (error "First cut/copy a region to paste!"))
12437 (org-table-check-inside-data-field)
12438 (let* ((clip org-table-clip)
12439 (line (count-lines (point-min) (point)))
12440 (col (org-table-current-column))
12441 (org-enable-table-editor t)
12442 (org-table-automatic-realign nil)
12443 c cols field)
12444 (while (setq cols (pop clip))
12445 (while (org-at-table-hline-p) (beginning-of-line 2))
12446 (if (not (org-at-table-p))
12447 (progn (end-of-line 0) (org-table-next-field)))
12448 (setq c col)
12449 (while (setq field (pop cols))
12450 (org-table-goto-column c nil 'force)
12451 (org-table-get-field nil field)
12452 (setq c (1+ c)))
12453 (beginning-of-line 2))
12454 (goto-line line)
12455 (org-table-goto-column col)
12456 (org-table-align)))
12457
12458 (defun org-table-convert ()
12459 "Convert from `org-mode' table to table.el and back.
12460 Obviously, this only works within limits. When an Org-mode table is
12461 converted to table.el, all horizontal separator lines get lost, because
12462 table.el uses these as cell boundaries and has no notion of horizontal lines.
12463 A table.el table can be converted to an Org-mode table only if it does not
12464 do row or column spanning. Multiline cells will become multiple cells.
12465 Beware, Org-mode does not test if the table can be successfully converted - it
12466 blindly applies a recipe that works for simple tables."
12467 (interactive)
12468 (require 'table)
12469 (if (org-at-table.el-p)
12470 ;; convert to Org-mode table
12471 (let ((beg (move-marker (make-marker) (org-table-begin t)))
12472 (end (move-marker (make-marker) (org-table-end t))))
12473 (table-unrecognize-region beg end)
12474 (goto-char beg)
12475 (while (re-search-forward "^\\([ \t]*\\)\\+-.*\n" end t)
12476 (replace-match ""))
12477 (goto-char beg))
12478 (if (org-at-table-p)
12479 ;; convert to table.el table
12480 (let ((beg (move-marker (make-marker) (org-table-begin)))
12481 (end (move-marker (make-marker) (org-table-end))))
12482 ;; first, get rid of all horizontal lines
12483 (goto-char beg)
12484 (while (re-search-forward "^\\([ \t]*\\)|-.*\n" end t)
12485 (replace-match ""))
12486 ;; insert a hline before first
12487 (goto-char beg)
12488 (org-table-insert-hline 'above)
12489 (beginning-of-line -1)
12490 ;; insert a hline after each line
12491 (while (progn (beginning-of-line 3) (< (point) end))
12492 (org-table-insert-hline))
12493 (goto-char beg)
12494 (setq end (move-marker end (org-table-end)))
12495 ;; replace "+" at beginning and ending of hlines
12496 (while (re-search-forward "^\\([ \t]*\\)|-" end t)
12497 (replace-match "\\1+-"))
12498 (goto-char beg)
12499 (while (re-search-forward "-|[ \t]*$" end t)
12500 (replace-match "-+"))
12501 (goto-char beg)))))
12502
12503 (defun org-table-wrap-region (arg)
12504 "Wrap several fields in a column like a paragraph.
12505 This is useful if you'd like to spread the contents of a field over several
12506 lines, in order to keep the table compact.
12507
12508 If there is an active region, and both point and mark are in the same column,
12509 the text in the column is wrapped to minimum width for the given number of
12510 lines. Generally, this makes the table more compact. A prefix ARG may be
12511 used to change the number of desired lines. For example, `C-2 \\[org-table-wrap]'
12512 formats the selected text to two lines. If the region was longer than two
12513 lines, the remaining lines remain empty. A negative prefix argument reduces
12514 the current number of lines by that amount. The wrapped text is pasted back
12515 into the table. If you formatted it to more lines than it was before, fields
12516 further down in the table get overwritten - so you might need to make space in
12517 the table first.
12518
12519 If there is no region, the current field is split at the cursor position and
12520 the text fragment to the right of the cursor is prepended to the field one
12521 line down.
12522
12523 If there is no region, but you specify a prefix ARG, the current field gets
12524 blank, and the content is appended to the field above."
12525 (interactive "P")
12526 (org-table-check-inside-data-field)
12527 (if (org-region-active-p)
12528 ;; There is a region: fill as a paragraph
12529 (let ((beg (region-beginning))
12530 nlines)
12531 (org-table-cut-region (region-beginning) (region-end))
12532 (if (> (length (car org-table-clip)) 1)
12533 (error "Region must be limited to single column"))
12534 (setq nlines (if arg
12535 (if (< arg 1)
12536 (+ (length org-table-clip) arg)
12537 arg)
12538 (length org-table-clip)))
12539 (setq org-table-clip
12540 (mapcar 'list (org-wrap (mapconcat 'car org-table-clip " ")
12541 nil nlines)))
12542 (goto-char beg)
12543 (org-table-paste-rectangle))
12544 ;; No region, split the current field at point
12545 (if arg
12546 ;; combine with field above
12547 (let ((s (org-table-blank-field))
12548 (col (org-table-current-column)))
12549 (beginning-of-line 0)
12550 (while (org-at-table-hline-p) (beginning-of-line 0))
12551 (org-table-goto-column col)
12552 (skip-chars-forward "^|")
12553 (skip-chars-backward " ")
12554 (insert " " (org-trim s))
12555 (org-table-align))
12556 ;; split field
12557 (when (looking-at "\\([^|]+\\)+|")
12558 (let ((s (match-string 1)))
12559 (replace-match " |")
12560 (goto-char (match-beginning 0))
12561 (org-table-next-row)
12562 (insert (org-trim s) " ")
12563 (org-table-align))))))
12564
12565 (defvar org-field-marker nil)
12566
12567 (defun org-table-edit-field (arg)
12568 "Edit table field in a different window.
12569 This is mainly useful for fields that contain hidden parts.
12570 When called with a \\[universal-argument] prefix, just make the full field visible so that
12571 it can be edited in place."
12572 (interactive "P")
12573 (if arg
12574 (let ((b (save-excursion (skip-chars-backward "^|") (point)))
12575 (e (save-excursion (skip-chars-forward "^|\r\n") (point))))
12576 (remove-text-properties b e '(org-cwidth t invisible t
12577 display t intangible t))
12578 (if (and (boundp 'font-lock-mode) font-lock-mode)
12579 (font-lock-fontify-block)))
12580 (let ((pos (move-marker (make-marker) (point)))
12581 (field (org-table-get-field))
12582 (cw (current-window-configuration))
12583 p)
12584 (switch-to-buffer-other-window "*Org tmp*")
12585 (erase-buffer)
12586 (insert "#\n# Edit field and finish with C-c C-c\n#\n")
12587 (org-mode)
12588 (goto-char (setq p (point-max)))
12589 (insert (org-trim field))
12590 (remove-text-properties p (point-max)
12591 '(invisible t org-cwidth t display t
12592 intangible t))
12593 (goto-char p)
12594 (org-set-local 'org-finish-function
12595 'org-table-finish-edit-field)
12596 (org-set-local 'org-window-configuration cw)
12597 (org-set-local 'org-field-marker pos)
12598 (message "Edit and finish with C-c C-c"))))
12599
12600 (defun org-table-finish-edit-field ()
12601 "Finish editing a table data field.
12602 Remove all newline characters, insert the result into the table, realign
12603 the table and kill the editing buffer."
12604 (let ((pos org-field-marker)
12605 (cw org-window-configuration)
12606 (cb (current-buffer))
12607 text)
12608 (goto-char (point-min))
12609 (while (re-search-forward "^#.*\n?" nil t) (replace-match ""))
12610 (while (re-search-forward "\\([ \t]*\n[ \t]*\\)+" nil t)
12611 (replace-match " "))
12612 (setq text (org-trim (buffer-string)))
12613 (set-window-configuration cw)
12614 (kill-buffer cb)
12615 (select-window (get-buffer-window (marker-buffer pos)))
12616 (goto-char pos)
12617 (move-marker pos nil)
12618 (org-table-check-inside-data-field)
12619 (org-table-get-field nil text)
12620 (org-table-align)
12621 (message "New field value inserted")))
12622
12623 (defun org-trim (s)
12624 "Remove whitespace at beginning and end of string."
12625 (if (string-match "^[ \t]+" s) (setq s (replace-match "" t t s)))
12626 (if (string-match "[ \t]+$" s) (setq s (replace-match "" t t s)))
12627 s)
12628
12629 (defun org-wrap (string &optional width lines)
12630 "Wrap string to either a number of lines, or a width in characters.
12631 If WIDTH is non-nil, the string is wrapped to that width, however many lines
12632 that costs. If there is a word longer than WIDTH, the text is actually
12633 wrapped to the length of that word.
12634 IF WIDTH is nil and LINES is non-nil, the string is forced into at most that
12635 many lines, whatever width that takes.
12636 The return value is a list of lines, without newlines at the end."
12637 (let* ((words (org-split-string string "[ \t\n]+"))
12638 (maxword (apply 'max (mapcar 'org-string-width words)))
12639 w ll)
12640 (cond (width
12641 (org-do-wrap words (max maxword width)))
12642 (lines
12643 (setq w maxword)
12644 (setq ll (org-do-wrap words maxword))
12645 (if (<= (length ll) lines)
12646 ll
12647 (setq ll words)
12648 (while (> (length ll) lines)
12649 (setq w (1+ w))
12650 (setq ll (org-do-wrap words w)))
12651 ll))
12652 (t (error "Cannot wrap this")))))
12653
12654
12655 (defun org-do-wrap (words width)
12656 "Create lines of maximum width WIDTH (in characters) from word list WORDS."
12657 (let (lines line)
12658 (while words
12659 (setq line (pop words))
12660 (while (and words (< (+ (length line) (length (car words))) width))
12661 (setq line (concat line " " (pop words))))
12662 (setq lines (push line lines)))
12663 (nreverse lines)))
12664
12665 (defun org-split-string (string &optional separators)
12666 "Splits STRING into substrings at SEPARATORS.
12667 No empty strings are returned if there are matches at the beginning
12668 and end of string."
12669 (let ((rexp (or separators "[ \f\t\n\r\v]+"))
12670 (start 0)
12671 notfirst
12672 (list nil))
12673 (while (and (string-match rexp string
12674 (if (and notfirst
12675 (= start (match-beginning 0))
12676 (< start (length string)))
12677 (1+ start) start))
12678 (< (match-beginning 0) (length string)))
12679 (setq notfirst t)
12680 (or (eq (match-beginning 0) 0)
12681 (and (eq (match-beginning 0) (match-end 0))
12682 (eq (match-beginning 0) start))
12683 (setq list
12684 (cons (substring string start (match-beginning 0))
12685 list)))
12686 (setq start (match-end 0)))
12687 (or (eq start (length string))
12688 (setq list
12689 (cons (substring string start)
12690 list)))
12691 (nreverse list)))
12692
12693 (defun org-table-map-tables (function)
12694 "Apply FUNCTION to the start of all tables in the buffer."
12695 (save-excursion
12696 (save-restriction
12697 (widen)
12698 (goto-char (point-min))
12699 (while (re-search-forward org-table-any-line-regexp nil t)
12700 (message "Mapping tables: %d%%" (/ (* 100.0 (point)) (buffer-size)))
12701 (beginning-of-line 1)
12702 (if (looking-at org-table-line-regexp)
12703 (save-excursion (funcall function)))
12704 (re-search-forward org-table-any-border-regexp nil 1))))
12705 (message "Mapping tables: done"))
12706
12707 (defun org-table-sum (&optional beg end nlast)
12708 "Sum numbers in region of current table column.
12709 The result will be displayed in the echo area, and will be available
12710 as kill to be inserted with \\[yank].
12711
12712 If there is an active region, it is interpreted as a rectangle and all
12713 numbers in that rectangle will be summed. If there is no active
12714 region and point is located in a table column, sum all numbers in that
12715 column.
12716
12717 If at least one number looks like a time HH:MM or HH:MM:SS, all other
12718 numbers are assumed to be times as well (in decimal hours) and the
12719 numbers are added as such.
12720
12721 If NLAST is a number, only the NLAST fields will actually be summed."
12722 (interactive)
12723 (save-excursion
12724 (let (col (timecnt 0) diff h m s org-table-clip)
12725 (cond
12726 ((and beg end)) ; beg and end given explicitly
12727 ((org-region-active-p)
12728 (setq beg (region-beginning) end (region-end)))
12729 (t
12730 (setq col (org-table-current-column))
12731 (goto-char (org-table-begin))
12732 (unless (re-search-forward "^[ \t]*|[^-]" nil t)
12733 (error "No table data"))
12734 (org-table-goto-column col)
12735 ;not needed? (skip-chars-backward "^|")
12736 (setq beg (point))
12737 (goto-char (org-table-end))
12738 (unless (re-search-backward "^[ \t]*|[^-]" nil t)
12739 (error "No table data"))
12740 (org-table-goto-column col)
12741 ;not needed? (skip-chars-forward "^|")
12742 (setq end (point))))
12743 (let* ((items (apply 'append (org-table-copy-region beg end)))
12744 (items1 (cond ((not nlast) items)
12745 ((>= nlast (length items)) items)
12746 (t (setq items (reverse items))
12747 (setcdr (nthcdr (1- nlast) items) nil)
12748 (nreverse items))))
12749 (numbers (delq nil (mapcar 'org-table-get-number-for-summing
12750 items1)))
12751 (res (apply '+ numbers))
12752 (sres (if (= timecnt 0)
12753 (format "%g" res)
12754 (setq diff (* 3600 res)
12755 h (floor (/ diff 3600)) diff (mod diff 3600)
12756 m (floor (/ diff 60)) diff (mod diff 60)
12757 s diff)
12758 (format "%d:%02d:%02d" h m s))))
12759 (kill-new sres)
12760 (if (interactive-p)
12761 (message "%s"
12762 (substitute-command-keys
12763 (format "Sum of %d items: %-20s (\\[yank] will insert result into buffer)"
12764 (length numbers) sres))))
12765 sres))))
12766
12767 (defun org-table-get-number-for-summing (s)
12768 (let (n)
12769 (if (string-match "^ *|? *" s)
12770 (setq s (replace-match "" nil nil s)))
12771 (if (string-match " *|? *$" s)
12772 (setq s (replace-match "" nil nil s)))
12773 (setq n (string-to-number s))
12774 (cond
12775 ((and (string-match "0" s)
12776 (string-match "\\`[-+ \t0.edED]+\\'" s)) 0)
12777 ((string-match "\\`[ \t]+\\'" s) nil)
12778 ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?\\'" s)
12779 (let ((h (string-to-number (or (match-string 1 s) "0")))
12780 (m (string-to-number (or (match-string 2 s) "0")))
12781 (s (string-to-number (or (match-string 4 s) "0"))))
12782 (if (boundp 'timecnt) (setq timecnt (1+ timecnt)))
12783 (* 1.0 (+ h (/ m 60.0) (/ s 3600.0)))))
12784 ((equal n 0) nil)
12785 (t n))))
12786
12787 (defun org-table-get-vertical-vector (desc &optional tbeg col)
12788 "Get a calc vector from a column, accorting to descriptor DESC.
12789 Optional arguments TBEG and COL can give the beginning of the table and
12790 the current column, to avoid unnecessary parsing."
12791 (save-excursion
12792 (or tbeg (setq tbeg (org-table-begin)))
12793 (or col (setq col (org-table-current-column)))
12794 (let (beg end nn n n1 n2 l (thisline (org-current-line)) hline-list)
12795 (cond
12796 ((string-match "\\(I+\\)\\(-\\(I+\\)\\)?" desc)
12797 (setq n1 (- (match-end 1) (match-beginning 1)))
12798 (if (match-beginning 3)
12799 (setq n2 (- (match-end 2) (match-beginning 3))))
12800 (setq n (if n2 (max n1 n2) n1))
12801 (setq n1 (if n2 (min n1 n2)))
12802 (setq nn n)
12803 (while (and (> nn 0)
12804 (re-search-backward org-table-hline-regexp tbeg t))
12805 (push (org-current-line) hline-list)
12806 (setq nn (1- nn)))
12807 (setq hline-list (nreverse hline-list))
12808 (goto-line (nth (1- n) hline-list))
12809 (when (re-search-forward org-table-dataline-regexp)
12810 (org-table-goto-column col)
12811 (setq beg (point)))
12812 (goto-line (if n1 (nth (1- n1) hline-list) thisline))
12813 (when (re-search-backward org-table-dataline-regexp)
12814 (org-table-goto-column col)
12815 (setq end (point)))
12816 (setq l (apply 'append (org-table-copy-region beg end)))
12817 (concat "[" (mapconcat (lambda (x) (setq x (org-trim x))
12818 (if (equal x "") "0" x))
12819 l ",") "]"))
12820 ((string-match "\\([0-9]+\\)-\\([0-9]+\\)" desc)
12821 (setq n1 (string-to-number (match-string 1 desc))
12822 n2 (string-to-number (match-string 2 desc)))
12823 (beginning-of-line 1)
12824 (save-excursion
12825 (when (re-search-backward org-table-dataline-regexp tbeg t n1)
12826 (org-table-goto-column col)
12827 (setq beg (point))))
12828 (when (re-search-backward org-table-dataline-regexp tbeg t n2)
12829 (org-table-goto-column col)
12830 (setq end (point)))
12831 (setq l (apply 'append (org-table-copy-region beg end)))
12832 (concat "[" (mapconcat
12833 (lambda (x) (setq x (org-trim x))
12834 (if (equal x "") "0" x))
12835 l ",") "]"))
12836 ((string-match "\\([0-9]+\\)" desc)
12837 (beginning-of-line 1)
12838 (when (re-search-backward org-table-dataline-regexp tbeg t
12839 (string-to-number (match-string 0 desc)))
12840 (org-table-goto-column col)
12841 (org-trim (org-table-get-field))))))))
12842
12843 (defvar org-table-formula-history nil)
12844
12845 (defvar org-table-column-names nil
12846 "Alist with column names, derived from the `!' line.")
12847 (defvar org-table-column-name-regexp nil
12848 "Regular expression matching the current column names.")
12849 (defvar org-table-local-parameters nil
12850 "Alist with parameter names, derived from the `$' line.")
12851 (defvar org-table-named-field-locations nil
12852 "Alist with locations of named fields.")
12853
12854 (defun org-table-get-formula (&optional equation named)
12855 "Read a formula from the minibuffer, offer stored formula as default."
12856 (let* ((name (car (rassoc (list (org-current-line)
12857 (org-table-current-column))
12858 org-table-named-field-locations)))
12859 (scol (if named
12860 (if name name
12861 (error "Not in a named field"))
12862 (int-to-string (org-table-current-column))))
12863 (dummy (and name (not named)
12864 (not (y-or-n-p "Replace named-field formula with column equation? " ))
12865 (error "Abort")))
12866 (org-table-may-need-update nil)
12867 (stored-list (org-table-get-stored-formulas))
12868 (stored (cdr (assoc scol stored-list)))
12869 (eq (cond
12870 ((and stored equation (string-match "^ *=? *$" equation))
12871 stored)
12872 ((stringp equation)
12873 equation)
12874 (t (read-string
12875 (format "%s formula $%s=" (if named "Field" "Column") scol)
12876 (or stored "") 'org-table-formula-history
12877 ;stored
12878 ))))
12879 mustsave)
12880 (when (not (string-match "\\S-" eq))
12881 ;; remove formula
12882 (setq stored-list (delq (assoc scol stored-list) stored-list))
12883 (org-table-store-formulas stored-list)
12884 (error "Formula removed"))
12885 (if (string-match "^ *=?" eq) (setq eq (replace-match "" t t eq)))
12886 (if (string-match " *$" eq) (setq eq (replace-match "" t t eq)))
12887 (if (and name (not named))
12888 ;; We set the column equation, delete the named one.
12889 (setq stored-list (delq (assoc name stored-list) stored-list)
12890 mustsave t))
12891 (if stored
12892 (setcdr (assoc scol stored-list) eq)
12893 (setq stored-list (cons (cons scol eq) stored-list)))
12894 (if (or mustsave (not (equal stored eq)))
12895 (org-table-store-formulas stored-list))
12896 eq))
12897
12898 (defun org-table-store-formulas (alist)
12899 "Store the list of formulas below the current table."
12900 (setq alist (sort alist (lambda (a b) (string< (car a) (car b)))))
12901 (save-excursion
12902 (goto-char (org-table-end))
12903 (if (looking-at "\\([ \t]*\n\\)*#\\+TBLFM:.*\n?")
12904 (delete-region (point) (match-end 0)))
12905 (insert "#+TBLFM: "
12906 (mapconcat (lambda (x)
12907 (concat "$" (car x) "=" (cdr x)))
12908 alist "::")
12909 "\n")))
12910
12911 (defun org-table-get-stored-formulas ()
12912 "Return an alist with the stored formulas directly after current table."
12913 (interactive)
12914 (let (scol eq eq-alist strings string seen)
12915 (save-excursion
12916 (goto-char (org-table-end))
12917 (when (looking-at "\\([ \t]*\n\\)*#\\+TBLFM: *\\(.*\\)")
12918 (setq strings (org-split-string (match-string 2) " *:: *"))
12919 (while (setq string (pop strings))
12920 (when (string-match "\\$\\([a-zA-Z0-9]+\\) *= *\\(.*[^ \t]\\)" string)
12921 (setq scol (match-string 1 string)
12922 eq (match-string 2 string)
12923 eq-alist (cons (cons scol eq) eq-alist))
12924 (if (member scol seen)
12925 (error "Double definition `$%s=' in TBLFM line, please fix by hand" scol)
12926 (push scol seen))))))
12927 (nreverse eq-alist)))
12928
12929 (defun org-table-modify-formulas (action &rest columns)
12930 "Modify the formulas stored below the current table.
12931 ACTION can be `remove', `insert', `swap'. For `swap', two column numbers are
12932 expected, for the other actions only a single column number is needed."
12933 (let ((list (org-table-get-stored-formulas))
12934 (nmax (length (org-split-string
12935 (buffer-substring (point-at-bol) (point-at-eol))
12936 "|")))
12937 col col1 col2 scol si sc1 sc2)
12938 (cond
12939 ((null list)) ; No action needed if there are no stored formulas
12940 ((eq action 'remove)
12941 (setq col (car columns)
12942 scol (int-to-string col))
12943 (org-table-replace-in-formulas list scol "INVALID")
12944 (if (assoc scol list) (setq list (delq (assoc scol list) list)))
12945 (loop for i from (1+ col) upto nmax by 1 do
12946 (setq si (int-to-string i))
12947 (org-table-replace-in-formulas list si (int-to-string (1- i)))
12948 (if (assoc si list) (setcar (assoc si list)
12949 (int-to-string (1- i))))))
12950 ((eq action 'insert)
12951 (setq col (car columns))
12952 (loop for i from nmax downto col by 1 do
12953 (setq si (int-to-string i))
12954 (org-table-replace-in-formulas list si (int-to-string (1+ i)))
12955 (if (assoc si list) (setcar (assoc si list)
12956 (int-to-string (1+ i))))))
12957 ((eq action 'swap)
12958 (setq col1 (car columns) col2 (nth 1 columns)
12959 sc1 (int-to-string col1) sc2 (int-to-string col2))
12960 ;; Hopefully, ZqZtZ will never be a name in a table
12961 (org-table-replace-in-formulas list sc1 "ZqZtZ")
12962 (org-table-replace-in-formulas list sc2 sc1)
12963 (org-table-replace-in-formulas list "ZqZtZ" sc2)
12964 (if (assoc sc1 list) (setcar (assoc sc1 list) "ZqZtZ"))
12965 (if (assoc sc2 list) (setcar (assoc sc2 list) sc1))
12966 (if (assoc "ZqZtZ" list) (setcar (assoc "ZqZtZ" list) sc2)))
12967 (t (error "Invalid action in `org-table-modify-formulas'")))
12968 (if list (org-table-store-formulas list))))
12969
12970 (defun org-table-replace-in-formulas (list s1 s2)
12971 (let (elt re s)
12972 (setq s1 (concat "$" (if (integerp s1) (int-to-string s1) s1))
12973 s2 (concat "$" (if (integerp s2) (int-to-string s2) s2))
12974 re (concat (regexp-quote s1) "\\>"))
12975 (while (setq elt (pop list))
12976 (setq s (cdr elt))
12977 (while (string-match re s)
12978 (setq s (replace-match s2 t t s)))
12979 (setcdr elt s))))
12980
12981 (defun org-table-get-specials ()
12982 "Get the column names and local parameters for this table."
12983 (save-excursion
12984 (let ((beg (org-table-begin)) (end (org-table-end))
12985 names name fields fields1 field cnt c v line col)
12986 (setq org-table-column-names nil
12987 org-table-local-parameters nil
12988 org-table-named-field-locations nil)
12989 (goto-char beg)
12990 (when (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t)
12991 (setq names (org-split-string (match-string 1) " *| *")
12992 cnt 1)
12993 (while (setq name (pop names))
12994 (setq cnt (1+ cnt))
12995 (if (string-match "^[a-zA-Z][a-zA-Z0-9]*$" name)
12996 (push (cons name (int-to-string cnt)) org-table-column-names))))
12997 (setq org-table-column-names (nreverse org-table-column-names))
12998 (setq org-table-column-name-regexp
12999 (concat "\\$\\(" (mapconcat 'car org-table-column-names "\\|") "\\)\\>"))
13000 (goto-char beg)
13001 (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t)
13002 (setq fields (org-split-string (match-string 1) " *| *"))
13003 (while (setq field (pop fields))
13004 (if (string-match "^\\([a-zA-Z][a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field)
13005 (push (cons (match-string 1 field) (match-string 2 field))
13006 org-table-local-parameters))))
13007 (goto-char beg)
13008 (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t)
13009 (setq c (match-string 1)
13010 fields (org-split-string (match-string 2) " *| *"))
13011 (save-excursion
13012 (beginning-of-line (if (equal c "_") 2 0))
13013 (setq line (org-current-line) col 1)
13014 (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)")
13015 (setq fields1 (org-split-string (match-string 1) " *| *"))))
13016 (while (and fields1 (setq field (pop fields)))
13017 (setq v (pop fields1) col (1+ col))
13018 (when (and (stringp field) (stringp v)
13019 (string-match "^[a-zA-Z][a-zA-Z0-9]*$" field))
13020 (push (cons field v) org-table-local-parameters)
13021 (push (list field line col) org-table-named-field-locations)))))))
13022
13023 (defun org-this-word ()
13024 ;; Get the current word
13025 (save-excursion
13026 (let ((beg (progn (skip-chars-backward "^ \t\n") (point)))
13027 (end (progn (skip-chars-forward "^ \t\n") (point))))
13028 (buffer-substring-no-properties beg end))))
13029
13030 (defun org-table-maybe-eval-formula ()
13031 "Check if the current field starts with \"=\" or \":=\".
13032 If yes, store the formula and apply it."
13033 ;; We already know we are in a table. Get field will only return a formula
13034 ;; when appropriate. It might return a separator line, but no problem.
13035 (when org-table-formula-evaluate-inline
13036 (let* ((field (org-trim (or (org-table-get-field) "")))
13037 named eq)
13038 (when (string-match "^:?=\\(.*\\)" field)
13039 (setq named (equal (string-to-char field) ?:)
13040 eq (match-string 1 field))
13041 (if (fboundp 'calc-eval)
13042 (org-table-eval-formula (if named '(4) nil) eq))))))
13043
13044 (defvar org-recalc-commands nil
13045 "List of commands triggering the recalculation of a line.
13046 Will be filled automatically during use.")
13047
13048 (defvar org-recalc-marks
13049 '((" " . "Unmarked: no special line, no automatic recalculation")
13050 ("#" . "Automatically recalculate this line upon TAB, RET, and C-c C-c in the line")
13051 ("*" . "Recalculate only when entire table is recalculated with `C-u C-c *'")
13052 ("!" . "Column name definition line. Reference in formula as $name.")
13053 ("$" . "Parameter definition line name=value. Reference in formula as $name.")
13054 ("_" . "Names for values in row below this one.")
13055 ("^" . "Names for values in row above this one.")))
13056
13057 (defun org-table-rotate-recalc-marks (&optional newchar)
13058 "Rotate the recalculation mark in the first column.
13059 If in any row, the first field is not consistent with a mark,
13060 insert a new column for the markers.
13061 When there is an active region, change all the lines in the region,
13062 after prompting for the marking character.
13063 After each change, a message will be displayed indicating the meaning
13064 of the new mark."
13065 (interactive)
13066 (unless (org-at-table-p) (error "Not at a table"))
13067 (let* ((marks (append (mapcar 'car org-recalc-marks) '(" ")))
13068 (beg (org-table-begin))
13069 (end (org-table-end))
13070 (l (org-current-line))
13071 (l1 (if (org-region-active-p) (org-current-line (region-beginning))))
13072 (l2 (if (org-region-active-p) (org-current-line (region-end))))
13073 (have-col
13074 (save-excursion
13075 (goto-char beg)
13076 (not (re-search-forward "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" end t))))
13077 (col (org-table-current-column))
13078 (forcenew (car (assoc newchar org-recalc-marks)))
13079 epos new)
13080 (when l1
13081 (message "Change region to what mark? Type # * ! $ or SPC: ")
13082 (setq newchar (char-to-string (read-char-exclusive))
13083 forcenew (car (assoc newchar org-recalc-marks))))
13084 (if (and newchar (not forcenew))
13085 (error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'"
13086 newchar))
13087 (if l1 (goto-line l1))
13088 (save-excursion
13089 (beginning-of-line 1)
13090 (unless (looking-at org-table-dataline-regexp)
13091 (error "Not at a table data line")))
13092 (unless have-col
13093 (org-table-goto-column 1)
13094 (org-table-insert-column)
13095 (org-table-goto-column (1+ col)))
13096 (setq epos (point-at-eol))
13097 (save-excursion
13098 (beginning-of-line 1)
13099 (org-table-get-field
13100 1 (if (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|")
13101 (concat " "
13102 (setq new (or forcenew
13103 (cadr (member (match-string 1) marks))))
13104 " ")
13105 " # ")))
13106 (if (and l1 l2)
13107 (progn
13108 (goto-line l1)
13109 (while (progn (beginning-of-line 2) (not (= (org-current-line) l2)))
13110 (and (looking-at org-table-dataline-regexp)
13111 (org-table-get-field 1 (concat " " new " "))))
13112 (goto-line l1)))
13113 (if (not (= epos (point-at-eol))) (org-table-align))
13114 (goto-line l)
13115 (and (interactive-p) (message (cdr (assoc new org-recalc-marks))))))
13116
13117 (defun org-table-maybe-recalculate-line ()
13118 "Recompute the current line if marked for it, and if we haven't just done it."
13119 (interactive)
13120 (and org-table-allow-automatic-line-recalculation
13121 (not (and (memq last-command org-recalc-commands)
13122 (equal org-last-recalc-line (org-current-line))))
13123 (save-excursion (beginning-of-line 1)
13124 (looking-at org-table-auto-recalculate-regexp))
13125 (fboundp 'calc-eval)
13126 (org-table-recalculate) t))
13127
13128 (defvar org-table-formula-debug nil
13129 "Non-nil means, debug table formulas.
13130 When nil, simply write \"#ERROR\" in corrupted fields.")
13131
13132 (defvar modes)
13133 (defsubst org-set-calc-mode (var &optional value)
13134 (if (stringp var)
13135 (setq var (assoc var '(("D" calc-angle-mode deg)
13136 ("R" calc-angle-mode rad)
13137 ("F" calc-prefer-frac t)
13138 ("S" calc-symbolic-mode t)))
13139 value (nth 2 var) var (nth 1 var)))
13140 (if (memq var modes)
13141 (setcar (cdr (memq var modes)) value)
13142 (cons var (cons value modes)))
13143 modes)
13144
13145 (defun org-table-eval-formula (&optional arg equation
13146 suppress-align suppress-const
13147 suppress-store)
13148 "Replace the table field value at the cursor by the result of a calculation.
13149
13150 This function makes use of Dave Gillespie's Calc package, in my view the
13151 most exciting program ever written for GNU Emacs. So you need to have Calc
13152 installed in order to use this function.
13153
13154 In a table, this command replaces the value in the current field with the
13155 result of a formula. It also installs the formula as the \"current\" column
13156 formula, by storing it in a special line below the table. When called
13157 with a `C-u' prefix, the current field must ba a named field, and the
13158 formula is installed as valid in only this specific field.
13159
13160 When called, the command first prompts for a formula, which is read in
13161 the minibuffer. Previously entered formulas are available through the
13162 history list, and the last used formula is offered as a default.
13163 These stored formulas are adapted correctly when moving, inserting, or
13164 deleting columns with the corresponding commands.
13165
13166 The formula can be any algebraic expression understood by the Calc package.
13167 For details, see the Org-mode manual.
13168
13169 This function can also be called from Lisp programs and offers
13170 additional arguments: EQUATION can be the formula to apply. If this
13171 argument is given, the user will not be prompted. SUPPRESS-ALIGN is
13172 used to speed-up recursive calls by by-passing unnecessary aligns.
13173 SUPPRESS-CONST suppresses the interpretation of constants in the
13174 formula, assuming that this has been done already outside the function.
13175 SUPPRESS-STORE means the formula should not be stored, either because
13176 it is already stored, or because it is a modified equation that should
13177 not overwrite the stored one."
13178 (interactive "P")
13179 (require 'calc)
13180 (org-table-check-inside-data-field)
13181 (org-table-get-specials)
13182 (let* (fields
13183 (ndown (if (integerp arg) arg 1))
13184 (org-table-automatic-realign nil)
13185 (case-fold-search nil)
13186 (down (> ndown 1))
13187 (formula (if (and equation suppress-store)
13188 equation
13189 (org-table-get-formula equation (equal arg '(4)))))
13190 (n0 (org-table-current-column))
13191 (modes (copy-sequence org-calc-default-modes))
13192 n form fmt x ev orig c lispp)
13193 ;; Parse the format string. Since we have a lot of modes, this is
13194 ;; a lot of work. However, I think calc still uses most of the time.
13195 (if (string-match ";" formula)
13196 (let ((tmp (org-split-string formula ";")))
13197 (setq formula (car tmp)
13198 fmt (concat (cdr (assoc "%" org-table-local-parameters))
13199 (nth 1 tmp)))
13200 (while (string-match "\\([pnfse]\\)\\(-?[0-9]+\\)" fmt)
13201 (setq c (string-to-char (match-string 1 fmt))
13202 n (string-to-number (match-string 2 fmt)))
13203 (if (= c ?p)
13204 (setq modes (org-set-calc-mode 'calc-internal-prec n))
13205 (setq modes (org-set-calc-mode
13206 'calc-float-format
13207 (list (cdr (assoc c '((?n . float) (?f . fix)
13208 (?s . sci) (?e . eng))))
13209 n))))
13210 (setq fmt (replace-match "" t t fmt)))
13211 (while (string-match "[DRFS]" fmt)
13212 (setq modes (org-set-calc-mode (match-string 0 fmt)))
13213 (setq fmt (replace-match "" t t fmt)))
13214 (unless (string-match "\\S-" fmt)
13215 (setq fmt nil))))
13216 (if (and (not suppress-const) org-table-formula-use-constants)
13217 (setq formula (org-table-formula-substitute-names formula)))
13218 (setq orig (or (get-text-property 1 :orig-formula formula) "?"))
13219 (while (> ndown 0)
13220 (setq fields (org-split-string
13221 (buffer-substring
13222 (point-at-bol) (point-at-eol)) " *| *"))
13223 (if org-table-formula-numbers-only
13224 (setq fields (mapcar
13225 (lambda (x) (number-to-string (string-to-number x)))
13226 fields)))
13227 (setq ndown (1- ndown))
13228 (setq form (copy-sequence formula)
13229 lispp (equal (substring form 0 2) "'("))
13230 ;; Insert the references to fields in same row
13231 (while (string-match "\\$\\([0-9]+\\)?" form)
13232 (setq n (if (match-beginning 1)
13233 (string-to-number (match-string 1 form))
13234 n0)
13235 x (nth (1- n) fields))
13236 (unless x (error "Invalid field specifier \"%s\""
13237 (match-string 0 form)))
13238 (if (equal x "") (setq x "0"))
13239 (setq form (replace-match
13240 (if lispp x (concat "(" x ")"))
13241 t t form)))
13242 ;; Insert ranges in current column
13243 (while (string-match "\\&[-I0-9]+" form)
13244 (setq form (replace-match
13245 (save-match-data
13246 (org-table-get-vertical-vector (match-string 0 form)
13247 nil n0))
13248 t t form)))
13249 (if lispp
13250 (setq ev (eval (eval (read form)))
13251 ev (if (numberp ev) (number-to-string ev) ev))
13252 (setq ev (calc-eval (cons form modes)
13253 (if org-table-formula-numbers-only 'num))))
13254
13255 (when org-table-formula-debug
13256 (with-output-to-temp-buffer "*Help*"
13257 (princ (format "Substitution history of formula
13258 Orig: %s
13259 $xyz-> %s
13260 $1-> %s\n" orig formula form))
13261 (if (listp ev)
13262 (princ (format " %s^\nError: %s"
13263 (make-string (car ev) ?\-) (nth 1 ev)))
13264 (princ (format "Result: %s\nFormat: %s\nFinal: %s"
13265 ev (or fmt "NONE")
13266 (if fmt (format fmt (string-to-number ev)) ev)))))
13267 (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*"))
13268 (unless (and (interactive-p) (not ndown))
13269 (unless (let (inhibit-redisplay)
13270 (y-or-n-p "Debugging Formula. Continue to next? "))
13271 (org-table-align)
13272 (error "Abort"))
13273 (delete-window (get-buffer-window "*Help*"))
13274 (message "")))
13275 (if (listp ev) (setq fmt nil ev "#ERROR"))
13276 (org-table-justify-field-maybe
13277 (if fmt (format fmt (string-to-number ev)) ev))
13278 (if (and down (> ndown 0) (looking-at ".*\n[ \t]*|[^-]"))
13279 (call-interactively 'org-return)
13280 (setq ndown 0)))
13281 (and down (org-table-maybe-recalculate-line))
13282 (or suppress-align (and org-table-may-need-update
13283 (org-table-align)))))
13284
13285 (defun org-table-recalculate (&optional all noalign)
13286 "Recalculate the current table line by applying all stored formulas.
13287 With prefix arg ALL, do this for all lines in the table."
13288 (interactive "P")
13289 (or (memq this-command org-recalc-commands)
13290 (setq org-recalc-commands (cons this-command org-recalc-commands)))
13291 (unless (org-at-table-p) (error "Not at a table"))
13292 (org-table-get-specials)
13293 (let* ((eqlist (sort (org-table-get-stored-formulas)
13294 (lambda (a b) (string< (car a) (car b)))))
13295 (inhibit-redisplay t)
13296 (line-re org-table-dataline-regexp)
13297 (thisline (org-current-line))
13298 (thiscol (org-table-current-column))
13299 beg end entry eqlnum eqlname eql (cnt 0) eq a name)
13300 ;; Insert constants in all formulas
13301 (setq eqlist
13302 (mapcar (lambda (x)
13303 (setcdr x (org-table-formula-substitute-names (cdr x)))
13304 x)
13305 eqlist))
13306 ;; Split the equation list
13307 (while (setq eq (pop eqlist))
13308 (if (<= (string-to-char (car eq)) ?9)
13309 (push eq eqlnum)
13310 (push eq eqlname)))
13311 (setq eqlnum (nreverse eqlnum) eqlname (nreverse eqlname))
13312 (if all
13313 (progn
13314 (setq end (move-marker (make-marker) (1+ (org-table-end))))
13315 (goto-char (setq beg (org-table-begin)))
13316 (if (re-search-forward org-table-calculate-mark-regexp end t)
13317 ;; This is a table with marked lines, only compute selected lines
13318 (setq line-re org-table-recalculate-regexp)
13319 ;; Move forward to the first non-header line
13320 (if (and (re-search-forward org-table-dataline-regexp end t)
13321 (re-search-forward org-table-hline-regexp end t)
13322 (re-search-forward org-table-dataline-regexp end t))
13323 (setq beg (match-beginning 0))
13324 nil))) ;; just leave beg where it is
13325 (setq beg (point-at-bol)
13326 end (move-marker (make-marker) (1+ (point-at-eol)))))
13327 (goto-char beg)
13328 (and all (message "Re-applying formulas to full table..."))
13329 (while (re-search-forward line-re end t)
13330 (unless (string-match "^ *[_^!$] *$" (org-table-get-field 1))
13331 ;; Unprotected line, recalculate
13332 (and all (message "Re-applying formulas to full table...(line %d)"
13333 (setq cnt (1+ cnt))))
13334 (setq org-last-recalc-line (org-current-line))
13335 (setq eql eqlnum)
13336 (while (setq entry (pop eql))
13337 (goto-line org-last-recalc-line)
13338 (org-table-goto-column (string-to-number (car entry)) nil 'force)
13339 (org-table-eval-formula nil (cdr entry) 'noalign 'nocst 'nostore))))
13340 (goto-line thisline)
13341 (org-table-goto-column thiscol)
13342 (or noalign (and org-table-may-need-update (org-table-align))
13343 (and all (message "Re-applying formulas to %d lines...done" cnt)))
13344 ;; Now do the names fields
13345 (while (setq eq (pop eqlname))
13346 (setq name (car eq)
13347 a (assoc name org-table-named-field-locations))
13348 (when a
13349 (message "Re-applying formula to named field: %s" name)
13350 (goto-line (nth 1 a))
13351 (org-table-goto-column (nth 2 a))
13352 (org-table-eval-formula nil (cdr eq) 'noalign 'nocst 'nostore)))
13353 ;; back to initial position
13354 (goto-line thisline)
13355 (org-table-goto-column thiscol)
13356 (or noalign (and org-table-may-need-update (org-table-align))
13357 (and all (message "Re-applying formulas...done")))))
13358
13359 (defun org-table-formula-substitute-names (f)
13360 "Replace $const with values in string F."
13361 (let ((start 0) a n1 n2 nn1 nn2 s (f1 f))
13362 ;; First, check for column names
13363 (while (setq start (string-match org-table-column-name-regexp f start))
13364 (setq start (1+ start))
13365 (setq a (assoc (match-string 1 f) org-table-column-names))
13366 (setq f (replace-match (concat "$" (cdr a)) t t f)))
13367 ;; Expand ranges to vectors
13368 (while (string-match "\\$\\([0-9]+\\)\\.\\.\\.?\\$\\([0-9]+\\)" f)
13369 (setq n1 (string-to-number (match-string 1 f))
13370 n2 (string-to-number (match-string 2 f))
13371 nn1 (1+ (min n1 n2)) nn2 (max n1 n2)
13372 s (concat "[($" (number-to-string (1- nn1)) ")"))
13373 (loop for i from nn1 upto nn2 do
13374 (setq s (concat s ",($" (int-to-string i) ")")))
13375 (setq s (concat s "]"))
13376 (if (< n2 n1) (setq s (concat "rev(" s ")")))
13377 (setq f (replace-match s t t f)))
13378 ;; Parameters and constants
13379 (setq start 0)
13380 (while (setq start (string-match "\\$\\([a-zA-Z][a-zA-Z0-9]*\\)" f start))
13381 (setq start (1+ start))
13382 (if (setq a (save-match-data
13383 (org-table-get-constant (match-string 1 f))))
13384 (setq f (replace-match (concat "(" a ")") t t f))))
13385 (if org-table-formula-debug
13386 (put-text-property 0 (length f) :orig-formula f1 f))
13387 f))
13388
13389 (defun org-table-get-constant (const)
13390 "Find the value for a parameter or constant in a formula.
13391 Parameters get priority."
13392 (or (cdr (assoc const org-table-local-parameters))
13393 (cdr (assoc const org-table-formula-constants))
13394 (and (fboundp 'constants-get) (constants-get const))
13395 "#UNDEFINED_NAME"))
13396
13397 (defvar org-edit-formulas-map (make-sparse-keymap))
13398 (define-key org-edit-formulas-map "\C-c\C-c" 'org-finish-edit-formulas)
13399 (define-key org-edit-formulas-map "\C-c\C-q" 'org-abort-edit-formulas)
13400 (define-key org-edit-formulas-map "\C-c?" 'org-show-variable)
13401
13402 (defvar org-pos)
13403
13404 (defun org-table-edit-formulas ()
13405 "Edit the formulas of the current table in a separate buffer."
13406 (interactive)
13407 (unless (org-at-table-p)
13408 (error "Not at a table"))
13409 (org-table-get-specials)
13410 (let ((eql (org-table-get-stored-formulas))
13411 (pos (move-marker (make-marker) (point)))
13412 (wc (current-window-configuration))
13413 entry loc s)
13414 (switch-to-buffer-other-window "*Edit Formulas*")
13415 (erase-buffer)
13416 (fundamental-mode)
13417 (org-set-local 'org-pos pos)
13418 (org-set-local 'org-window-configuration wc)
13419 (use-local-map org-edit-formulas-map)
13420 (setq s "# Edit formulas and finish with `C-c C-c'.
13421 # Use `C-u C-c C-c' to also appy them immediately to the entire table.
13422 # Use `C-c ?' to get information about $name at point.
13423 # To cancel editing, press `C-c C-q'.\n")
13424 (put-text-property 0 (length s) 'face 'font-lock-comment-face s)
13425 (insert s)
13426 (while (setq entry (pop eql))
13427 (when (setq loc (assoc (car entry) org-table-named-field-locations))
13428 (setq s (format "# Named formula, referring to column %d in line %d\n"
13429 (nth 2 loc) (nth 1 loc)))
13430 (put-text-property 0 (length s) 'face 'font-lock-comment-face s)
13431 (insert s))
13432 (setq s (concat "$" (car entry) "=" (cdr entry) "\n"))
13433 (remove-text-properties 0 (length s) '(face nil) s)
13434 (insert s))
13435 (goto-char (point-min))
13436 (message "Edit formulas and finish with `C-c C-c'.")))
13437
13438 (defun org-show-variable ()
13439 "Show the location/value of the $ expression at point."
13440 (interactive)
13441 (let (var (pos org-pos) (win (selected-window)) e)
13442 (save-excursion
13443 (or (looking-at "\\$") (skip-chars-backward "$a-zA-Z0-9"))
13444 (if (looking-at "\\$\\([a-zA-Z0-9]+\\)")
13445 (setq var (match-string 1))
13446 (error "No variable at point")))
13447 (cond
13448 ((setq e (assoc var org-table-named-field-locations))
13449 (switch-to-buffer-other-window (marker-buffer pos))
13450 (goto-line (nth 1 e))
13451 (org-table-goto-column (nth 2 e))
13452 (select-window win)
13453 (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e)))
13454 ((setq e (assoc var org-table-column-names))
13455 (switch-to-buffer-other-window (marker-buffer pos))
13456 (goto-char pos)
13457 (goto-char (org-table-begin))
13458 (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|")
13459 (org-table-end) t)
13460 (progn
13461 (goto-char (match-beginning 1))
13462 (message "Named column (column %s)" (cdr e)))
13463 (error "Column name not found"))
13464 (select-window win))
13465 ((string-match "^[0-9]$" var)
13466 ;; column number
13467 (switch-to-buffer-other-window (marker-buffer pos))
13468 (goto-char pos)
13469 (goto-char (org-table-begin))
13470 (recenter 1)
13471 (if (re-search-forward org-table-dataline-regexp
13472 (org-table-end) t)
13473 (progn
13474 (goto-char (match-beginning 0))
13475 (org-table-goto-column (string-to-number var))
13476 (message "Column %s" var))
13477 (error "Column name not found"))
13478 (select-window win))
13479 ((setq e (assoc var org-table-local-parameters))
13480 (switch-to-buffer-other-window (marker-buffer pos))
13481 (goto-char pos)
13482 (goto-char (org-table-begin))
13483 (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") nil t)
13484 (progn
13485 (goto-char (match-beginning 1))
13486 (message "Local parameter."))
13487 (error "Parameter not found"))
13488 (select-window win))
13489 (t
13490 (cond
13491 ((setq e (assoc var org-table-formula-constants))
13492 (message "Constant: $%s=%s in `org-table-formula-constants'." var (cdr e)))
13493 ((setq e (and (fboundp 'constants-get) (constants-get var)))
13494 (message "Constant: $%s=%s, retrieved from `constants.el'." var e))
13495 (t (error "Undefined name $%s" var)))))))
13496
13497 (defun org-finish-edit-formulas (&optional arg)
13498 "Parse the buffer for formula definitions and install them.
13499 With prefix ARG, apply the new formulas to the table."
13500 (interactive "P")
13501 (let ((pos org-pos) eql)
13502 (goto-char (point-min))
13503 (while (re-search-forward "^\\$\\([a-zA-Z0-9]+\\) *= *\\(.*?\\) *$" nil t)
13504 (push (cons (match-string 1) (match-string 2)) eql))
13505 (set-window-configuration org-window-configuration)
13506 (select-window (get-buffer-window (marker-buffer pos)))
13507 (goto-char pos)
13508 (unless (org-at-table-p)
13509 (error "Lost table position - cannot install formulae"))
13510 (org-table-store-formulas eql)
13511 (move-marker pos nil)
13512 (kill-buffer "*Edit Formulas*")
13513 (if arg
13514 (org-table-recalculate 'all)
13515 (message "New formulas installed - press C-u C-c C-c to apply."))))
13516
13517 (defun org-abort-edit-formulas ()
13518 "Abort editing formulas, without installing the changes."
13519 (interactive)
13520 (let ((pos org-pos))
13521 (set-window-configuration org-window-configuration)
13522 (select-window (get-buffer-window (marker-buffer pos)))
13523 (goto-char pos)
13524 (message "Formula editing aborted without installing changes")))
13525
13526 ;;; The orgtbl minor mode
13527
13528 ;; Define a minor mode which can be used in other modes in order to
13529 ;; integrate the org-mode table editor.
13530
13531 ;; This is really a hack, because the org-mode table editor uses several
13532 ;; keys which normally belong to the major mode, for example the TAB and
13533 ;; RET keys. Here is how it works: The minor mode defines all the keys
13534 ;; necessary to operate the table editor, but wraps the commands into a
13535 ;; function which tests if the cursor is currently inside a table. If that
13536 ;; is the case, the table editor command is executed. However, when any of
13537 ;; those keys is used outside a table, the function uses `key-binding' to
13538 ;; look up if the key has an associated command in another currently active
13539 ;; keymap (minor modes, major mode, global), and executes that command.
13540 ;; There might be problems if any of the keys used by the table editor is
13541 ;; otherwise used as a prefix key.
13542
13543 ;; Another challenge is that the key binding for TAB can be tab or \C-i,
13544 ;; likewise the binding for RET can be return or \C-m. Orgtbl-mode
13545 ;; addresses this by checking explicitly for both bindings.
13546
13547 ;; The optimized version (see variable `orgtbl-optimized') takes over
13548 ;; all keys which are bound to `self-insert-command' in the *global map*.
13549 ;; Some modes bind other commands to simple characters, for example
13550 ;; AUCTeX binds the double quote to `Tex-insert-quote'. With orgtbl-mode
13551 ;; active, this binding is ignored inside tables and replaced with a
13552 ;; modified self-insert.
13553
13554 (defvar orgtbl-mode nil
13555 "Variable controlling `orgtbl-mode', a minor mode enabling the `org-mode'
13556 table editor in arbitrary modes.")
13557 (make-variable-buffer-local 'orgtbl-mode)
13558
13559 (defvar orgtbl-mode-map (make-keymap)
13560 "Keymap for `orgtbl-mode'.")
13561
13562 ;;;###autoload
13563 (defun turn-on-orgtbl ()
13564 "Unconditionally turn on `orgtbl-mode'."
13565 (orgtbl-mode 1))
13566
13567 ;;;###autoload
13568 (defun orgtbl-mode (&optional arg)
13569 "The `org-mode' table editor as a minor mode for use in other modes."
13570 (interactive)
13571 (if (org-mode-p)
13572 ;; Exit without error, in case some hook functions calls this
13573 ;; by accident in org-mode.
13574 (message "Orgtbl-mode is not useful in org-mode, command ignored")
13575 (setq orgtbl-mode
13576 (if arg (> (prefix-numeric-value arg) 0) (not orgtbl-mode)))
13577 (if orgtbl-mode
13578 (progn
13579 (and (orgtbl-setup) (defun orgtbl-setup () nil))
13580 ;; Make sure we are first in minor-mode-map-alist
13581 (let ((c (assq 'orgtbl-mode minor-mode-map-alist)))
13582 (and c (setq minor-mode-map-alist
13583 (cons c (delq c minor-mode-map-alist)))))
13584 (org-set-local (quote org-table-may-need-update) t)
13585 (org-add-hook 'before-change-functions 'org-before-change-function
13586 nil 'local)
13587 (org-set-local 'org-old-auto-fill-inhibit-regexp
13588 auto-fill-inhibit-regexp)
13589 (org-set-local 'auto-fill-inhibit-regexp
13590 (if auto-fill-inhibit-regexp
13591 (concat "\\([ \t]*|\\|" auto-fill-inhibit-regexp)
13592 "[ \t]*|"))
13593 (org-add-to-invisibility-spec '(org-cwidth))
13594 (easy-menu-add orgtbl-mode-menu)
13595 (run-hooks 'orgtbl-mode-hook))
13596 (setq auto-fill-inhibit-regexp org-old-auto-fill-inhibit-regexp)
13597 (org-cleanup-narrow-column-properties)
13598 (org-remove-from-invisibility-spec '(org-cwidth))
13599 (remove-hook 'before-change-functions 'org-before-change-function t)
13600 (easy-menu-remove orgtbl-mode-menu)
13601 (force-mode-line-update 'all))))
13602
13603 (defun org-cleanup-narrow-column-properties ()
13604 "Remove all properties related to narrow-column invisibility."
13605 (let ((s 1))
13606 (while (setq s (text-property-any s (point-max)
13607 'display org-narrow-column-arrow))
13608 (remove-text-properties s (1+ s) '(display t)))
13609 (setq s 1)
13610 (while (setq s (text-property-any s (point-max) 'org-cwidth 1))
13611 (remove-text-properties s (1+ s) '(org-cwidth t)))
13612 (setq s 1)
13613 (while (setq s (text-property-any s (point-max) 'invisible 'org-cwidth))
13614 (remove-text-properties s (1+ s) '(invisible t)))))
13615
13616 ;; Install it as a minor mode.
13617 (put 'orgtbl-mode :included t)
13618 (put 'orgtbl-mode :menu-tag "Org Table Mode")
13619 (add-minor-mode 'orgtbl-mode " OrgTbl" orgtbl-mode-map)
13620
13621 (defun orgtbl-make-binding (fun n &rest keys)
13622 "Create a function for binding in the table minor mode.
13623 FUN is the command to call inside a table. N is used to create a unique
13624 command name. KEYS are keys that should be checked in for a command
13625 to execute outside of tables."
13626 (eval
13627 (list 'defun
13628 (intern (concat "orgtbl-hijacker-command-" (int-to-string n)))
13629 '(arg)
13630 (concat "In tables, run `" (symbol-name fun) "'.\n"
13631 "Outside of tables, run the binding of `"
13632 (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
13633 "'.")
13634 '(interactive "p")
13635 (list 'if
13636 '(org-at-table-p)
13637 (list 'call-interactively (list 'quote fun))
13638 (list 'let '(orgtbl-mode)
13639 (list 'call-interactively
13640 (append '(or)
13641 (mapcar (lambda (k)
13642 (list 'key-binding k))
13643 keys)
13644 '('orgtbl-error))))))))
13645
13646 (defun orgtbl-error ()
13647 "Error when there is no default binding for a table key."
13648 (interactive)
13649 (error "This key is has no function outside tables"))
13650
13651 (defun orgtbl-setup ()
13652 "Setup orgtbl keymaps."
13653 (let ((nfunc 0)
13654 (bindings
13655 (list
13656 '([(meta shift left)] org-table-delete-column)
13657 '([(meta left)] org-table-move-column-left)
13658 '([(meta right)] org-table-move-column-right)
13659 '([(meta shift right)] org-table-insert-column)
13660 '([(meta shift up)] org-table-kill-row)
13661 '([(meta shift down)] org-table-insert-row)
13662 '([(meta up)] org-table-move-row-up)
13663 '([(meta down)] org-table-move-row-down)
13664 '("\C-c\C-w" org-table-cut-region)
13665 '("\C-c\M-w" org-table-copy-region)
13666 '("\C-c\C-y" org-table-paste-rectangle)
13667 '("\C-c-" org-table-insert-hline)
13668 ; '([(shift tab)] org-table-previous-field)
13669 '("\C-m" org-table-next-row)
13670 (list (org-key 'S-return) 'org-table-copy-down)
13671 '([(meta return)] org-table-wrap-region)
13672 '("\C-c\C-q" org-table-wrap-region)
13673 '("\C-c?" org-table-current-column)
13674 '("\C-c " org-table-blank-field)
13675 '("\C-c+" org-table-sum)
13676 '("\C-c=" org-table-eval-formula)
13677 '("\C-c'" org-table-edit-formulas)
13678 '("\C-c`" org-table-edit-field)
13679 '("\C-c*" org-table-recalculate)
13680 '("\C-c|" org-table-create-or-convert-from-region)
13681 '("\C-c^" org-table-sort-lines)
13682 '([(control ?#)] org-table-rotate-recalc-marks)))
13683 elt key fun cmd)
13684 (while (setq elt (pop bindings))
13685 (setq nfunc (1+ nfunc))
13686 (setq key (car elt)
13687 fun (nth 1 elt)
13688 cmd (orgtbl-make-binding fun nfunc key))
13689 (define-key orgtbl-mode-map key cmd))
13690 ;; Special treatment needed for TAB and RET
13691 (define-key orgtbl-mode-map [(return)]
13692 (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m"))
13693 (define-key orgtbl-mode-map "\C-m"
13694 (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)]))
13695 (define-key orgtbl-mode-map [(tab)]
13696 (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i"))
13697 (define-key orgtbl-mode-map "\C-i"
13698 (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)])))
13699 (define-key orgtbl-mode-map "\C-i"
13700 (orgtbl-make-binding 'orgtbl-tab 104 [(shift tab)]))
13701 (define-key orgtbl-mode-map "\C-c\C-c"
13702 (orgtbl-make-binding 'org-ctrl-c-ctrl-c 105 "\C-c\C-c"))
13703 (when orgtbl-optimized
13704 ;; If the user wants maximum table support, we need to hijack
13705 ;; some standard editing functions
13706 (org-remap orgtbl-mode-map
13707 'self-insert-command 'orgtbl-self-insert-command
13708 'delete-char 'org-delete-char
13709 'delete-backward-char 'org-delete-backward-char)
13710 (define-key orgtbl-mode-map "|" 'org-force-self-insert))
13711 (easy-menu-define orgtbl-mode-menu orgtbl-mode-map "OrgTbl menu"
13712 '("OrgTbl"
13713 ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p) :keys "C-c C-c"]
13714 ["Next Field" org-cycle :active (org-at-table-p) :keys "TAB"]
13715 ["Previous Field" org-shifttab :active (org-at-table-p) :keys "S-TAB"]
13716 ["Next Row" org-return :active (org-at-table-p) :keys "RET"]
13717 "--"
13718 ["Blank Field" org-table-blank-field :active (org-at-table-p) :keys "C-c SPC"]
13719 ["Edit Field" org-table-edit-field :active (org-at-table-p) :keys "C-c ` "]
13720 ["Copy Field from Above"
13721 org-table-copy-down :active (org-at-table-p) :keys "S-RET"]
13722 "--"
13723 ("Column"
13724 ["Move Column Left" org-metaleft :active (org-at-table-p) :keys "M-<left>"]
13725 ["Move Column Right" org-metaright :active (org-at-table-p) :keys "M-<right>"]
13726 ["Delete Column" org-shiftmetaleft :active (org-at-table-p) :keys "M-S-<left>"]
13727 ["Insert Column" org-shiftmetaright :active (org-at-table-p) :keys "M-S-<right>"]
13728 "--"
13729 ["Enable Narrowing" (setq org-table-limit-column-width (not org-table-limit-column-width)) :active (org-at-table-p) :selected org-table-limit-column-width :style toggle])
13730 ("Row"
13731 ["Move Row Up" org-metaup :active (org-at-table-p) :keys "M-<up>"]
13732 ["Move Row Down" org-metadown :active (org-at-table-p) :keys "M-<down>"]
13733 ["Delete Row" org-shiftmetaup :active (org-at-table-p) :keys "M-S-<up>"]
13734 ["Insert Row" org-shiftmetadown :active (org-at-table-p) :keys "M-S-<down>"]
13735 ["Sort lines in region" org-table-sort-lines (org-at-table-p) :keys "C-c ^"]
13736 "--"
13737 ["Insert Hline" org-table-insert-hline :active (org-at-table-p) :keys "C-c -"])
13738 ("Rectangle"
13739 ["Copy Rectangle" org-copy-special :active (org-at-table-p)]
13740 ["Cut Rectangle" org-cut-special :active (org-at-table-p)]
13741 ["Paste Rectangle" org-paste-special :active (org-at-table-p)]
13742 ["Fill Rectangle" org-table-wrap-region :active (org-at-table-p)])
13743 "--"
13744 ["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="]
13745 ["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
13746 ["Edit Formulas" org-table-edit-formulas :active (org-at-table-p) :keys "C-c '"]
13747 ["Recalculate line" org-table-recalculate :active (org-at-table-p) :keys "C-c *"]
13748 ["Recalculate all" (org-table-recalculate '(4)) :active (org-at-table-p) :keys "C-u C-c *"]
13749 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks :active (org-at-table-p) :keys "C-c #"]
13750 ["Sum Column/Rectangle" org-table-sum
13751 :active (or (org-at-table-p) (org-region-active-p)) :keys "C-c +"]
13752 ["Which Column?" org-table-current-column :active (org-at-table-p) :keys "C-c ?"]
13753 ["Debug Formulas"
13754 (setq org-table-formula-debug (not org-table-formula-debug))
13755 :style toggle :selected org-table-formula-debug]
13756 ))
13757 t)
13758
13759 (defun orgtbl-tab (arg)
13760 "Justification and field motion for `orgtbl-mode'."
13761 (interactive "P")
13762 (if arg (org-table-edit-field t)
13763 (org-table-justify-field-maybe)
13764 (org-table-next-field)))
13765
13766 (defun orgtbl-ret ()
13767 "Justification and field motion for `orgtbl-mode'."
13768 (interactive)
13769 (org-table-justify-field-maybe)
13770 (org-table-next-row))
13771
13772 (defun orgtbl-self-insert-command (N)
13773 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
13774 If the cursor is in a table looking at whitespace, the whitespace is
13775 overwritten, and the table is not marked as requiring realignment."
13776 (interactive "p")
13777 (if (and (org-at-table-p)
13778 (or
13779 (and org-table-auto-blank-field
13780 (member last-command
13781 '(orgtbl-hijacker-command-100
13782 orgtbl-hijacker-command-101
13783 orgtbl-hijacker-command-102
13784 orgtbl-hijacker-command-103
13785 orgtbl-hijacker-command-104
13786 orgtbl-hijacker-command-105))
13787 (org-table-blank-field))
13788 t)
13789 (eq N 1)
13790 (looking-at "[^|\n]* +|"))
13791 (let (org-table-may-need-update)
13792 (goto-char (1- (match-end 0)))
13793 (delete-backward-char 1)
13794 (goto-char (match-beginning 0))
13795 (self-insert-command N))
13796 (setq org-table-may-need-update t)
13797 (let (orgtbl-mode)
13798 (call-interactively (key-binding (vector last-input-event))))))
13799
13800 (defun org-force-self-insert (N)
13801 "Needed to enforce self-insert under remapping."
13802 (interactive "p")
13803 (self-insert-command N))
13804
13805 ;;; Exporting
13806
13807 (defconst org-level-max 20)
13808
13809 (defvar org-export-html-preamble nil
13810 "Preamble, to be inserted just after <body>. Set by publishing functions.")
13811 (defvar org-export-html-postamble nil
13812 "Preamble, to be inserted just before </body>. Set by publishing functions.")
13813 (defvar org-export-html-auto-preamble t
13814 "Should default preamble be inserted? Set by publishing functions.")
13815 (defvar org-export-html-auto-postamble t
13816 "Should default postamble be inserted? Set by publishing functions.")
13817
13818 (defconst org-export-plist-vars
13819 '((:language . org-export-default-language)
13820 (:headline-levels . org-export-headline-levels)
13821 (:section-numbers . org-export-with-section-numbers)
13822 (:table-of-contents . org-export-with-toc)
13823 (:archived-trees . org-export-with-archived-trees)
13824 (:emphasize . org-export-with-emphasize)
13825 (:sub-superscript . org-export-with-sub-superscripts)
13826 (:TeX-macros . org-export-with-TeX-macros)
13827 (:LaTeX-fragments . org-export-with-LaTeX-fragments)
13828 (:fixed-width . org-export-with-fixed-width)
13829 (:timestamps . org-export-with-timestamps)
13830 (:tables . org-export-with-tables)
13831 (:table-auto-headline . org-export-highlight-first-table-line)
13832 (:style . org-export-html-style)
13833 (:convert-org-links . org-export-html-link-org-files-as-html)
13834 (:inline-images . org-export-html-inline-images)
13835 (:expand-quoted-html . org-export-html-expand)
13836 (:timestamp . org-export-html-with-timestamp)
13837 (:publishing-directory . org-export-publishing-directory)
13838 (:preamble . org-export-html-preamble)
13839 (:postamble . org-export-html-postamble)
13840 (:auto-preamble . org-export-html-auto-preamble)
13841 (:auto-postamble . org-export-html-auto-postamble)
13842 (:author . user-full-name)
13843 (:email . user-mail-address)))
13844
13845 (defun org-default-export-plist ()
13846 "Return the property list with default settings for the export variables."
13847 (let ((l org-export-plist-vars) rtn e)
13848 (while (setq e (pop l))
13849 (setq rtn (cons (car e) (cons (symbol-value (cdr e)) rtn))))
13850 rtn))
13851
13852 (defun org-infile-export-plist ()
13853 "Return the property list with file-local settings for export."
13854 (save-excursion
13855 (goto-char 0)
13856 (let ((re (org-make-options-regexp
13857 '("TITLE" "AUTHOR" "EMAIL" "TEXT" "OPTIONS" "LANGUAGE")))
13858 p key val text options)
13859 (while (re-search-forward re nil t)
13860 (setq key (org-match-string-no-properties 1)
13861 val (org-match-string-no-properties 2))
13862 (cond
13863 ((string-equal key "TITLE") (setq p (plist-put p :title val)))
13864 ((string-equal key "AUTHOR")(setq p (plist-put p :author val)))
13865 ((string-equal key "EMAIL") (setq p (plist-put p :email val)))
13866 ((string-equal key "LANGUAGE") (setq p (plist-put p :language val)))
13867 ((string-equal key "TEXT")
13868 (setq text (if text (concat text "\n" val) val)))
13869 ((string-equal key "OPTIONS") (setq options val))))
13870 (setq p (plist-put p :text text))
13871 (when options
13872 (let ((op '(("H" . :headline-levels)
13873 ("num" . :section-numbers)
13874 ("toc" . :table-of-contents)
13875 ("\\n" . :preserve-breaks)
13876 ("@" . :expand-quoted-html)
13877 (":" . :fixed-width)
13878 ("|" . :tables)
13879 ("^" . :sub-superscript)
13880 ("*" . :emphasize)
13881 ("TeX" . :TeX-macros)
13882 ("LaTeX" . :LaTeX-fragments)))
13883 o)
13884 (while (setq o (pop op))
13885 (if (string-match (concat (regexp-quote (car o))
13886 ":\\([^ \t\n\r;,.]*\\)")
13887 options)
13888 (setq p (plist-put p (cdr o)
13889 (car (read-from-string
13890 (match-string 1 options)))))))))
13891 p)))
13892
13893 (defun org-combine-plists (&rest plists)
13894 "Create a single property list from all plists in PLISTS.
13895 The process starts by copying the last list, and then setting properties
13896 from the other lists. Settings in the first list are the most significant
13897 ones and overrule settings in the other lists."
13898 (let ((rtn (copy-sequence (pop plists)))
13899 p v ls)
13900 (while plists
13901 (setq ls (pop plists))
13902 (while ls
13903 (setq p (pop ls) v (pop ls))
13904 (setq rtn (plist-put rtn p v))))
13905 rtn))
13906
13907 (defun org-export-directory (type plist)
13908 (let* ((val (plist-get plist :publishing-directory))
13909 (dir (if (listp val)
13910 (or (cdr (assoc type val)) ".")
13911 val)))
13912 dir))
13913
13914 (defun org-export-find-first-heading-line (list)
13915 "Remove all lines from LIST which are before the first headline."
13916 (let ((orig-list list)
13917 (re (concat "^" outline-regexp)))
13918 (while (and list
13919 (not (string-match re (car list))))
13920 (pop list))
13921 (or list orig-list)))
13922
13923 (defun org-skip-comments (lines)
13924 "Skip lines starting with \"#\" and subtrees starting with COMMENT."
13925 (let ((re1 (concat "^\\(\\*+\\)[ \t]+" org-comment-string))
13926 (re2 "^\\(\\*+\\)[ \t\n\r]")
13927 rtn line level)
13928 (while (setq line (pop lines))
13929 (cond
13930 ((and (string-match re1 line)
13931 (setq level (- (match-end 1) (match-beginning 1))))
13932 ;; Beginning of a COMMENT subtree. Skip it.
13933 (while (and (setq line (pop lines))
13934 (or (not (string-match re2 line))
13935 (> (- (match-end 1) (match-beginning 1)) level))))
13936 (setq lines (cons line lines)))
13937 ((string-match "^#" line)
13938 ;; an ordinary comment line
13939 )
13940 ((and org-export-table-remove-special-lines
13941 (string-match "^[ \t]*|" line)
13942 (or (string-match "^[ \t]*| *[!_^] *|" line)
13943 (and (string-match "| *<[0-9]+> *|" line)
13944 (not (string-match "| *[^ <|]" line)))))
13945 ;; a special table line that should be removed
13946 )
13947 (t (setq rtn (cons line rtn)))))
13948 (nreverse rtn)))
13949
13950 (defun org-export (&optional arg)
13951 (interactive)
13952 (let ((help "[t] insert the export option template
13953 \[v] limit export to visible part of outline tree
13954
13955 \[a] export as ASCII
13956 \[h] export as HTML
13957 \[b] export as HTML and browse immediately
13958 \[x] export as XOXO
13959
13960 \[i] export current file as iCalendar file
13961 \[I] export all agenda files as iCalendar files
13962 \[c] export agenda files into combined iCalendar file
13963
13964 \[F] publish current file
13965 \[P] publish current project
13966 \[X] publish... (project will be prompted for)
13967 \[A] publish all projects")
13968 (cmds
13969 '((?t . org-insert-export-options-template)
13970 (?v . org-export-visible)
13971 (?a . org-export-as-ascii)
13972 (?h . org-export-as-html)
13973 (?b . org-export-as-html-and-open)
13974 (?x . org-export-as-xoxo)
13975 (?i . org-export-icalendar-this-file)
13976 (?I . org-export-icalendar-all-agenda-files)
13977 (?c . org-export-icalendar-combine-agenda-files)
13978 (?F . org-publish-current-file)
13979 (?P . org-publish-current-project)
13980 (?X . org-publish)
13981 (?A . org-publish-all)))
13982 r1 r2 ass)
13983 (save-window-excursion
13984 (delete-other-windows)
13985 (with-output-to-temp-buffer "*Org Export/Publishing Help*"
13986 (princ help))
13987 (message "Select command: ")
13988 (setq r1 (read-char-exclusive)))
13989 (setq r2 (if (< r1 27) (+ r1 96) r1))
13990 (if (setq ass (assq r2 cmds))
13991 (call-interactively (cdr ass))
13992 (error "No command associated with key %c" r1))))
13993
13994 ;; ASCII
13995
13996 (defconst org-html-entities
13997 '(("nbsp")
13998 ("iexcl")
13999 ("cent")
14000 ("pound")
14001 ("curren")
14002 ("yen")
14003 ("brvbar")
14004 ("sect")
14005 ("uml")
14006 ("copy")
14007 ("ordf")
14008 ("laquo")
14009 ("not")
14010 ("shy")
14011 ("reg")
14012 ("macr")
14013 ("deg")
14014 ("plusmn")
14015 ("sup2")
14016 ("sup3")
14017 ("acute")
14018 ("micro")
14019 ("para")
14020 ("middot")
14021 ("odot"."o")
14022 ("star"."*")
14023 ("cedil")
14024 ("sup1")
14025 ("ordm")
14026 ("raquo")
14027 ("frac14")
14028 ("frac12")
14029 ("frac34")
14030 ("iquest")
14031 ("Agrave")
14032 ("Aacute")
14033 ("Acirc")
14034 ("Atilde")
14035 ("Auml")
14036 ("Aring") ("AA"."&Aring;")
14037 ("AElig")
14038 ("Ccedil")
14039 ("Egrave")
14040 ("Eacute")
14041 ("Ecirc")
14042 ("Euml")
14043 ("Igrave")
14044 ("Iacute")
14045 ("Icirc")
14046 ("Iuml")
14047 ("ETH")
14048 ("Ntilde")
14049 ("Ograve")
14050 ("Oacute")
14051 ("Ocirc")
14052 ("Otilde")
14053 ("Ouml")
14054 ("times")
14055 ("Oslash")
14056 ("Ugrave")
14057 ("Uacute")
14058 ("Ucirc")
14059 ("Uuml")
14060 ("Yacute")
14061 ("THORN")
14062 ("szlig")
14063 ("agrave")
14064 ("aacute")
14065 ("acirc")
14066 ("atilde")
14067 ("auml")
14068 ("aring")
14069 ("aelig")
14070 ("ccedil")
14071 ("egrave")
14072 ("eacute")
14073 ("ecirc")
14074 ("euml")
14075 ("igrave")
14076 ("iacute")
14077 ("icirc")
14078 ("iuml")
14079 ("eth")
14080 ("ntilde")
14081 ("ograve")
14082 ("oacute")
14083 ("ocirc")
14084 ("otilde")
14085 ("ouml")
14086 ("divide")
14087 ("oslash")
14088 ("ugrave")
14089 ("uacute")
14090 ("ucirc")
14091 ("uuml")
14092 ("yacute")
14093 ("thorn")
14094 ("yuml")
14095 ("fnof")
14096 ("Alpha")
14097 ("Beta")
14098 ("Gamma")
14099 ("Delta")
14100 ("Epsilon")
14101 ("Zeta")
14102 ("Eta")
14103 ("Theta")
14104 ("Iota")
14105 ("Kappa")
14106 ("Lambda")
14107 ("Mu")
14108 ("Nu")
14109 ("Xi")
14110 ("Omicron")
14111 ("Pi")
14112 ("Rho")
14113 ("Sigma")
14114 ("Tau")
14115 ("Upsilon")
14116 ("Phi")
14117 ("Chi")
14118 ("Psi")
14119 ("Omega")
14120 ("alpha")
14121 ("beta")
14122 ("gamma")
14123 ("delta")
14124 ("epsilon")
14125 ("varepsilon"."&epsilon;")
14126 ("zeta")
14127 ("eta")
14128 ("theta")
14129 ("iota")
14130 ("kappa")
14131 ("lambda")
14132 ("mu")
14133 ("nu")
14134 ("xi")
14135 ("omicron")
14136 ("pi")
14137 ("rho")
14138 ("sigmaf") ("varsigma"."&sigmaf;")
14139 ("sigma")
14140 ("tau")
14141 ("upsilon")
14142 ("phi")
14143 ("chi")
14144 ("psi")
14145 ("omega")
14146 ("thetasym") ("vartheta"."&thetasym;")
14147 ("upsih")
14148 ("piv")
14149 ("bull") ("bullet"."&bull;")
14150 ("hellip") ("dots"."&hellip;")
14151 ("prime")
14152 ("Prime")
14153 ("oline")
14154 ("frasl")
14155 ("weierp")
14156 ("image")
14157 ("real")
14158 ("trade")
14159 ("alefsym")
14160 ("larr") ("leftarrow"."&larr;") ("gets"."&larr;")
14161 ("uarr") ("uparrow"."&uarr;")
14162 ("rarr") ("to"."&rarr;") ("rightarrow"."&rarr;")
14163 ("darr")("downarrow"."&darr;")
14164 ("harr") ("leftrightarrow"."&harr;")
14165 ("crarr") ("hookleftarrow"."&crarr;") ; has round hook, not quite CR
14166 ("lArr") ("Leftarrow"."&lArr;")
14167 ("uArr") ("Uparrow"."&uArr;")
14168 ("rArr") ("Rightarrow"."&rArr;")
14169 ("dArr") ("Downarrow"."&dArr;")
14170 ("hArr") ("Leftrightarrow"."&hArr;")
14171 ("forall")
14172 ("part") ("partial"."&part;")
14173 ("exist") ("exists"."&exist;")
14174 ("empty") ("emptyset"."&empty;")
14175 ("nabla")
14176 ("isin") ("in"."&isin;")
14177 ("notin")
14178 ("ni")
14179 ("prod")
14180 ("sum")
14181 ("minus")
14182 ("lowast") ("ast"."&lowast;")
14183 ("radic")
14184 ("prop") ("proptp"."&prop;")
14185 ("infin") ("infty"."&infin;")
14186 ("ang") ("angle"."&ang;")
14187 ("and") ("vee"."&and;")
14188 ("or") ("wedge"."&or;")
14189 ("cap")
14190 ("cup")
14191 ("int")
14192 ("there4")
14193 ("sim")
14194 ("cong") ("simeq"."&cong;")
14195 ("asymp")("approx"."&asymp;")
14196 ("ne") ("neq"."&ne;")
14197 ("equiv")
14198 ("le")
14199 ("ge")
14200 ("sub") ("subset"."&sub;")
14201 ("sup") ("supset"."&sup;")
14202 ("nsub")
14203 ("sube")
14204 ("supe")
14205 ("oplus")
14206 ("otimes")
14207 ("perp")
14208 ("sdot") ("cdot"."&sdot;")
14209 ("lceil")
14210 ("rceil")
14211 ("lfloor")
14212 ("rfloor")
14213 ("lang")
14214 ("rang")
14215 ("loz") ("Diamond"."&loz;")
14216 ("spades") ("spadesuit"."&spades;")
14217 ("clubs") ("clubsuit"."&clubs;")
14218 ("hearts") ("diamondsuit"."&hearts;")
14219 ("diams") ("diamondsuit"."&diams;")
14220 ("quot")
14221 ("amp")
14222 ("lt")
14223 ("gt")
14224 ("OElig")
14225 ("oelig")
14226 ("Scaron")
14227 ("scaron")
14228 ("Yuml")
14229 ("circ")
14230 ("tilde")
14231 ("ensp")
14232 ("emsp")
14233 ("thinsp")
14234 ("zwnj")
14235 ("zwj")
14236 ("lrm")
14237 ("rlm")
14238 ("ndash")
14239 ("mdash")
14240 ("lsquo")
14241 ("rsquo")
14242 ("sbquo")
14243 ("ldquo")
14244 ("rdquo")
14245 ("bdquo")
14246 ("dagger")
14247 ("Dagger")
14248 ("permil")
14249 ("lsaquo")
14250 ("rsaquo")
14251 ("euro")
14252
14253 ("arccos"."arccos")
14254 ("arcsin"."arcsin")
14255 ("arctan"."arctan")
14256 ("arg"."arg")
14257 ("cos"."cos")
14258 ("cosh"."cosh")
14259 ("cot"."cot")
14260 ("coth"."coth")
14261 ("csc"."csc")
14262 ("deg"."deg")
14263 ("det"."det")
14264 ("dim"."dim")
14265 ("exp"."exp")
14266 ("gcd"."gcd")
14267 ("hom"."hom")
14268 ("inf"."inf")
14269 ("ker"."ker")
14270 ("lg"."lg")
14271 ("lim"."lim")
14272 ("liminf"."liminf")
14273 ("limsup"."limsup")
14274 ("ln"."ln")
14275 ("log"."log")
14276 ("max"."max")
14277 ("min"."min")
14278 ("Pr"."Pr")
14279 ("sec"."sec")
14280 ("sin"."sin")
14281 ("sinh"."sinh")
14282 ("sup"."sup")
14283 ("tan"."tan")
14284 ("tanh"."tanh")
14285 )
14286 "Entities for TeX->HTML translation.
14287 Entries can be like (\"ent\"), in which case \"\\ent\" will be translated to
14288 \"&ent;\". An entry can also be a dotted pair like (\"ent\".\"&other;\").
14289 In that case, \"\\ent\" will be translated to \"&other;\".
14290 The list contains HTML entities for Latin-1, Greek and other symbols.
14291 It is supplemented by a number of commonly used TeX macros with appropriate
14292 translations. There is currently no way for users to extend this.")
14293
14294 (defun org-cleaned-string-for-export (string &rest parameters)
14295 "Cleanup a buffer substring so that links can be created safely."
14296 (interactive)
14297 (let* ((re-radio (and org-target-link-regexp
14298 (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)")))
14299 (re-plain-link (concat "\\([^[<]\\)" org-plain-link-re))
14300 (re-angle-link (concat "\\([^[]\\)" org-angle-link-re))
14301 (re-archive (concat ":" org-archive-tag ":"))
14302 rtn)
14303 (save-excursion
14304 (set-buffer (get-buffer-create " org-mode-tmp"))
14305 (erase-buffer)
14306 (insert string)
14307 (let ((org-inhibit-startup t)) (org-mode))
14308
14309 ;; Get rid of archived trees
14310 (when (not (eq org-export-with-archived-trees t))
14311 (goto-char (point-min))
14312 (while (re-search-forward re-archive nil t)
14313 (if (not (org-on-heading-p))
14314 (org-end-of-subtree t)
14315 (beginning-of-line 1)
14316 (delete-region
14317 (if org-export-with-archived-trees (1+ (point-at-eol)) (point))
14318 (org-end-of-subtree t)))))
14319
14320 ;; Find targets in comments and move them out of comments,
14321 ;; but mark them as targets that should be invisible
14322 (goto-char (point-min))
14323 (while (re-search-forward "^#.*?\\(<<<?[^>\r\n]+>>>?\\).*" nil t)
14324 (replace-match "\\1(INVISIBLE)"))
14325
14326 ;; Remove comments
14327 (goto-char (point-min))
14328 (while (re-search-forward "^#.*\n?" nil t)
14329 (replace-match ""))
14330
14331 ;; Find matches for radio targets and turn them into internal links
14332 (goto-char (point-min))
14333 (when re-radio
14334 (while (re-search-forward re-radio nil t)
14335 (replace-match "\\1[[\\2]]")))
14336
14337 ;; Find all links that contain a newline and put them into a single line
14338 (goto-char (point-min))
14339 (while (re-search-forward "\\(\\(\\[\\|\\]\\)\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\(\\[\\|\\]\\)\\)" nil t)
14340 (replace-match "\\1 \\3")
14341 (goto-char (match-beginning 0)))
14342
14343 ;; Convert LaTeX fragments to images
14344 (when (memq :LaTeX-fragments parameters)
14345 (org-format-latex
14346 (concat "ltxpng/" (file-name-sans-extension
14347 (file-name-nondirectory
14348 org-current-export-file)))
14349 org-current-export-dir nil "Creating LaTeX image %s"))
14350 (message "Exporting...")
14351
14352 ;; Normalize links: Convert angle and plain links into bracket links
14353 ;; Expand link abbreviations
14354 (goto-char (point-min))
14355 (while (re-search-forward re-plain-link nil t)
14356 (replace-match
14357 (concat
14358 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
14359 t t))
14360 (goto-char (point-min))
14361 (while (re-search-forward re-angle-link nil t)
14362 (replace-match
14363 (concat
14364 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
14365 t t))
14366 (goto-char (point-min))
14367 (while (re-search-forward org-bracket-link-regexp nil t)
14368 (replace-match
14369 (concat "[[" (save-match-data
14370 (org-link-expand-abbrev (match-string 1)))
14371 "]"
14372 (if (match-end 3)
14373 (match-string 2)
14374 (concat "[" (match-string 1) "]"))
14375 "]")
14376 t t))
14377
14378 ;; Find multiline emphasis and put them into single line
14379 (when (memq :emph-multiline parameters)
14380 (goto-char (point-min))
14381 (while (re-search-forward org-emph-re nil t)
14382 (subst-char-in-region (match-beginning 0) (match-end 0) ?\n ?\ t)
14383 (goto-char (1- (match-end 0)))))
14384
14385 (setq rtn (buffer-string)))
14386 (kill-buffer " org-mode-tmp")
14387 rtn))
14388
14389 (defun org-solidify-link-text (s &optional alist)
14390 "Take link text and make a safe target out of it."
14391 (save-match-data
14392 (let* ((rtn
14393 (mapconcat
14394 'identity
14395 (org-split-string s "[ \t\r\n]+") "--"))
14396 (a (assoc rtn alist)))
14397 (or (cdr a) rtn))))
14398
14399 (defun org-convert-to-odd-levels ()
14400 "Convert an org-mode file with all levels allowed to one with odd levels.
14401 This will leave level 1 alone, convert level 2 to level 3, level 3 to
14402 level 5 etc."
14403 (interactive)
14404 (when (yes-or-no-p "Are you sure you want to globally change levels to odd? ")
14405 (let ((org-odd-levels-only nil) n)
14406 (save-excursion
14407 (goto-char (point-min))
14408 (while (re-search-forward "^\\*\\*+" nil t)
14409 (setq n (1- (length (match-string 0))))
14410 (while (>= (setq n (1- n)) 0)
14411 (org-demote))
14412 (end-of-line 1))))))
14413
14414
14415 (defun org-convert-to-oddeven-levels ()
14416 "Convert an org-mode file with only odd levels to one with odd and even levels.
14417 This promotes level 3 to level 2, level 5 to level 3 etc. If the file contains a
14418 section with an even level, conversion would destroy the structure of the file. An error
14419 is signaled in this case."
14420 (interactive)
14421 (goto-char (point-min))
14422 ;; First check if there are no even levels
14423 (when (re-search-forward "^\\(\\*\\*\\)+[^*]" nil t)
14424 (org-show-context t)
14425 (error "Not all levels are odd in this file. Conversion not possible."))
14426 (when (yes-or-no-p "Are you sure you want to globally change levels to odd-even? ")
14427 (let ((org-odd-levels-only nil) n)
14428 (save-excursion
14429 (goto-char (point-min))
14430 (while (re-search-forward "^\\*\\*+" nil t)
14431 (setq n (/ (length (match-string 0)) 2))
14432 (while (>= (setq n (1- n)) 0)
14433 (org-promote))
14434 (end-of-line 1))))))
14435
14436 (defun org-tr-level (n)
14437 "Make N odd if required."
14438 (if org-odd-levels-only (1+ (/ n 2)) n))
14439
14440 (defvar org-last-level nil) ; dynamically scoped variable
14441 (defvar org-ascii-current-indentation nil) ; For communication
14442
14443 (defun org-export-as-ascii (arg)
14444 "Export the outline as a pretty ASCII file.
14445 If there is an active region, export only the region.
14446 The prefix ARG specifies how many levels of the outline should become
14447 underlined headlines. The default is 3."
14448 (interactive "P")
14449 (setq-default org-todo-line-regexp org-todo-line-regexp)
14450 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
14451 (org-infile-export-plist)))
14452 (region
14453 (buffer-substring
14454 (if (org-region-active-p) (region-beginning) (point-min))
14455 (if (org-region-active-p) (region-end) (point-max))))
14456 (lines (org-export-find-first-heading-line
14457 (org-skip-comments
14458 (org-split-string
14459 (org-cleaned-string-for-export region)
14460 "[\r\n]"))))
14461 (org-ascii-current-indentation '(0 . 0))
14462 (org-startup-with-deadline-check nil)
14463 (level 0) line txt
14464 (umax nil)
14465 (case-fold-search nil)
14466 (filename (concat (file-name-as-directory
14467 (org-export-directory :ascii opt-plist))
14468 (file-name-sans-extension
14469 (file-name-nondirectory buffer-file-name))
14470 ".txt"))
14471 (buffer (find-file-noselect filename))
14472 (levels-open (make-vector org-level-max nil))
14473 (odd org-odd-levels-only)
14474 (date (format-time-string "%Y/%m/%d" (current-time)))
14475 (time (format-time-string "%X" (org-current-time)))
14476 (author (plist-get opt-plist :author))
14477 (title (or (plist-get opt-plist :title)
14478 (file-name-sans-extension
14479 (file-name-nondirectory buffer-file-name))))
14480 (email (plist-get opt-plist :email))
14481 (language (plist-get opt-plist :language))
14482 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
14483 (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
14484 (text nil)
14485 (todo nil)
14486 (lang-words nil))
14487
14488 (setq org-last-level 1)
14489 (org-init-section-numbers)
14490
14491 (find-file-noselect filename)
14492
14493 (setq lang-words (or (assoc language org-export-language-setup)
14494 (assoc "en" org-export-language-setup)))
14495 (if org-export-ascii-show-new-buffer
14496 (switch-to-buffer-other-window buffer)
14497 (set-buffer buffer))
14498 (erase-buffer)
14499 (fundamental-mode)
14500 ;; create local variables for all options, to make sure all called
14501 ;; functions get the correct information
14502 (mapcar (lambda (x)
14503 (set (make-local-variable (cdr x))
14504 (plist-get opt-plist (car x))))
14505 org-export-plist-vars)
14506 (org-set-local 'org-odd-levels-only odd)
14507 (setq umax (if arg (prefix-numeric-value arg)
14508 org-export-headline-levels))
14509
14510 ;; File header
14511 (if title (org-insert-centered title ?=))
14512 (insert "\n")
14513 (if (or author email)
14514 (insert (concat (nth 1 lang-words) ": " (or author "")
14515 (if email (concat " <" email ">") "")
14516 "\n")))
14517 (if (and date time)
14518 (insert (concat (nth 2 lang-words) ": " date " " time "\n")))
14519 (if text (insert (concat (org-html-expand-for-ascii text) "\n\n")))
14520
14521 (insert "\n\n")
14522
14523 (if org-export-with-toc
14524 (progn
14525 (insert (nth 3 lang-words) "\n"
14526 (make-string (length (nth 3 lang-words)) ?=) "\n")
14527 (mapcar '(lambda (line)
14528 (if (string-match org-todo-line-regexp
14529 line)
14530 ;; This is a headline
14531 (progn
14532 (setq level (- (match-end 1) (match-beginning 1))
14533 level (org-tr-level level)
14534 txt (match-string 3 line)
14535 todo
14536 (or (and org-export-mark-todo-in-toc
14537 (match-beginning 2)
14538 (not (equal (match-string 2 line)
14539 org-done-string)))
14540 ; TODO, not DONE
14541 (and org-export-mark-todo-in-toc
14542 (= level umax)
14543 (org-search-todo-below
14544 line lines level))))
14545 (setq txt (org-html-expand-for-ascii txt))
14546
14547 (if (and (memq org-export-with-tags '(not-in-toc nil))
14548 (string-match "[ \t]+:[a-zA-Z0-9_@:]+:[ \t]*$" txt))
14549 (setq txt (replace-match "" t t txt)))
14550 (if (string-match quote-re0 txt)
14551 (setq txt (replace-match "" t t txt)))
14552
14553 (if org-export-with-section-numbers
14554 (setq txt (concat (org-section-number level)
14555 " " txt)))
14556 (if (<= level umax)
14557 (progn
14558 (insert
14559 (make-string (* (1- level) 4) ?\ )
14560 (format (if todo "%s (*)\n" "%s\n") txt))
14561 (setq org-last-level level))
14562 ))))
14563 lines)))
14564
14565 (org-init-section-numbers)
14566 (while (setq line (pop lines))
14567 ;; Remove the quoted HTML tags.
14568 (setq line (org-html-expand-for-ascii line))
14569 ;; Remove targets
14570 (while (string-match "<<<?[^<>]*>>>?[ \t]*\n?" line)
14571 (setq line (replace-match "" t t line)))
14572 ;; Replace internal links
14573 (while (string-match org-bracket-link-regexp line)
14574 (setq line (replace-match
14575 (if (match-end 3) "[\\3]" "[\\1]")
14576 t nil line)))
14577 (cond
14578 ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line)
14579 ;; a Headline
14580 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
14581 txt (match-string 2 line))
14582 (org-ascii-level-start level txt umax lines))
14583 (t
14584 (insert (org-fix-indentation line org-ascii-current-indentation) "\n"))))
14585 (normal-mode)
14586 (save-buffer)
14587 ;; remove display and invisible chars
14588 (let (beg end)
14589 (goto-char (point-min))
14590 (while (setq beg (next-single-property-change (point) 'display))
14591 (setq end (next-single-property-change beg 'display))
14592 (delete-region beg end)
14593 (goto-char beg)
14594 (insert "=>"))
14595 (goto-char (point-min))
14596 (while (setq beg (next-single-property-change (point) 'org-cwidth))
14597 (setq end (next-single-property-change beg 'org-cwidth))
14598 (delete-region beg end)
14599 (goto-char beg)))
14600 (goto-char (point-min))))
14601
14602 (defun org-search-todo-below (line lines level)
14603 "Search the subtree below LINE for any TODO entries."
14604 (let ((rest (cdr (memq line lines)))
14605 (re org-todo-line-regexp)
14606 line lv todo)
14607 (catch 'exit
14608 (while (setq line (pop rest))
14609 (if (string-match re line)
14610 (progn
14611 (setq lv (- (match-end 1) (match-beginning 1))
14612 todo (and (match-beginning 2)
14613 (not (equal (match-string 2 line)
14614 org-done-string))))
14615 ; TODO, not DONE
14616 (if (<= lv level) (throw 'exit nil))
14617 (if todo (throw 'exit t))))))))
14618
14619 (defun org-html-expand-for-ascii (line)
14620 "Handle quoted HTML for ASCII export."
14621 (if org-export-html-expand
14622 (while (string-match "@<[^<>\n]*>" line)
14623 ;; We just remove the tags for now.
14624 (setq line (replace-match "" nil nil line))))
14625 line)
14626
14627 (defun org-insert-centered (s &optional underline)
14628 "Insert the string S centered and underline it with character UNDERLINE."
14629 (let ((ind (max (/ (- 80 (string-width s)) 2) 0)))
14630 (insert (make-string ind ?\ ) s "\n")
14631 (if underline
14632 (insert (make-string ind ?\ )
14633 (make-string (string-width s) underline)
14634 "\n"))))
14635
14636 (defun org-ascii-level-start (level title umax &optional lines)
14637 "Insert a new level in ASCII export."
14638 (let (char (n (- level umax 1)) (ind 0))
14639 (if (> level umax)
14640 (progn
14641 (insert (make-string (* 2 n) ?\ )
14642 (char-to-string (nth (% n (length org-export-ascii-bullets))
14643 org-export-ascii-bullets))
14644 " " title "\n")
14645 ;; find the indentation of the next non-empty line
14646 (catch 'stop
14647 (while lines
14648 (if (string-match "^\\*" (car lines)) (throw 'stop nil))
14649 (if (string-match "^\\([ \t]*\\)\\S-" (car lines))
14650 (throw 'stop (setq ind (org-get-indentation (car lines)))))
14651 (pop lines)))
14652 (setq org-ascii-current-indentation (cons (* 2 (1+ n)) ind)))
14653 (if (or (not (equal (char-before) ?\n))
14654 (not (equal (char-before (1- (point))) ?\n)))
14655 (insert "\n"))
14656 (setq char (nth (- umax level) (reverse org-export-ascii-underline)))
14657 (unless org-export-with-tags
14658 (if (string-match "[ \t]+\\(:[a-zA-Z0-9_@:]+:\\)[ \t]*$" title)
14659 (setq title (replace-match "" t t title))))
14660 (if org-export-with-section-numbers
14661 (setq title (concat (org-section-number level) " " title)))
14662 (insert title "\n" (make-string (string-width title) char) "\n")
14663 (setq org-ascii-current-indentation '(0 . 0)))))
14664
14665 (defun org-export-visible (type arg)
14666 "Create a copy of the visible part of the current buffer, and export it.
14667 The copy is created in a temporary buffer and removed after use.
14668 TYPE is the final key (as a string) that also select the export command in
14669 the `C-c C-e' export dispatcher.
14670 As a special case, if the you type SPC at the prompt, the temporary
14671 org-mode file will not be removed but presented to you so that you can
14672 continue to use it. The prefix arg ARG is passed through to the exporting
14673 command."
14674 (interactive
14675 (list (progn
14676 (message "Export visible: [a]SCII [h]tml [b]rowse HTML [x]OXO [ ]keep buffer")
14677 (read-char-exclusive))
14678 current-prefix-arg))
14679 (if (not (member type '(?a ?\C-a ?b ?\C-b ?h ?x ?\ )))
14680 (error "Invalid export key"))
14681 (let* ((binding (cdr (assoc type
14682 '((?a . org-export-as-ascii)
14683 (?\C-a . org-export-as-ascii)
14684 (?b . org-export-as-html-and-open)
14685 (?\C-b . org-export-as-html-and-open)
14686 (?h . org-export-as-html)
14687 (?x . org-export-as-xoxo)))))
14688 (keepp (equal type ?\ ))
14689 (file buffer-file-name)
14690 (buffer (get-buffer-create "*Org Export Visible*"))
14691 s e)
14692 (with-current-buffer buffer (erase-buffer))
14693 (save-excursion
14694 (setq s (goto-char (point-min)))
14695 (while (not (= (point) (point-max)))
14696 (goto-char (org-find-invisible))
14697 (append-to-buffer buffer s (point))
14698 (setq s (goto-char (org-find-visible))))
14699 (goto-char (point-min))
14700 (unless keepp
14701 ;; Copy all comment lines to the end, to make sure #+ settings are
14702 ;; still available for the second export step. Kind of a hack, but
14703 ;; does do the trick.
14704 (if (looking-at "#[^\r\n]*")
14705 (append-to-buffer buffer (match-beginning 0) (1+ (match-end 0))))
14706 (while (re-search-forward "[\n\r]#[^\n\r]*" nil t)
14707 (append-to-buffer buffer (1+ (match-beginning 0))
14708 (min (point-max) (1+ (match-end 0))))))
14709 (set-buffer buffer)
14710 (let ((buffer-file-name file)
14711 (org-inhibit-startup t))
14712 (org-mode)
14713 (show-all)
14714 (unless keepp (funcall binding arg))))
14715 (if (not keepp)
14716 (kill-buffer buffer)
14717 (switch-to-buffer-other-window buffer)
14718 (goto-char (point-min)))))
14719
14720 (defun org-find-visible ()
14721 (let ((s (point)))
14722 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
14723 (get-char-property s 'invisible)))
14724 s))
14725 (defun org-find-invisible ()
14726 (let ((s (point)))
14727 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
14728 (not (get-char-property s 'invisible))))
14729 s))
14730
14731 ;; HTML
14732
14733 (defun org-get-current-options ()
14734 "Return a string with current options as keyword options.
14735 Does include HTML export options as well as TODO and CATEGORY stuff."
14736 (format
14737 "#+TITLE: %s
14738 #+AUTHOR: %s
14739 #+EMAIL: %s
14740 #+LANGUAGE: %s
14741 #+TEXT: Some descriptive text to be emitted. Several lines OK.
14742 #+OPTIONS: H:%d num:%s toc:%s \\n:%s @:%s ::%s |:%s ^:%s *:%s TeX:%s LaTeX:%s
14743 #+CATEGORY: %s
14744 #+SEQ_TODO: %s
14745 #+TYP_TODO: %s
14746 #+STARTUP: %s %s %s %s %s %s
14747 #+TAGS: %s
14748 #+ARCHIVE: %s
14749 #+LINK: %s
14750 "
14751 (buffer-name) (user-full-name) user-mail-address org-export-default-language
14752 org-export-headline-levels
14753 org-export-with-section-numbers
14754 org-export-with-toc
14755 org-export-preserve-breaks
14756 org-export-html-expand
14757 org-export-with-fixed-width
14758 org-export-with-tables
14759 org-export-with-sub-superscripts
14760 org-export-with-emphasize
14761 org-export-with-TeX-macros
14762 org-export-with-LaTeX-fragments
14763 (file-name-nondirectory buffer-file-name)
14764 (if (equal org-todo-interpretation 'sequence)
14765 (mapconcat 'identity org-todo-keywords " ")
14766 "TODO FEEDBACK VERIFY DONE")
14767 (if (equal org-todo-interpretation 'type)
14768 (mapconcat 'identity org-todo-keywords " ")
14769 "Me Jason Marie DONE")
14770 (cdr (assoc org-startup-folded
14771 '((nil . "showall") (t . "overview") (content . "content"))))
14772 (if org-startup-with-deadline-check "dlcheck" "nodlcheck")
14773 (if org-odd-levels-only "odd" "oddeven")
14774 (if org-hide-leading-stars "hidestars" "showstars")
14775 (if org-startup-align-all-tables "align" "noalign")
14776 (if org-log-done "logging" "nologging")
14777 (or (mapconcat (lambda (x)
14778 (cond
14779 ((equal '(:startgroup) x) "{")
14780 ((equal '(:endgroup) x) "}")
14781 ((cdr x) (format "%s(%c)" (car x) (cdr x)))
14782 (t (car x))))
14783 (or org-tag-alist (org-get-buffer-tags)) " ") "")
14784 org-archive-location
14785 "org file:~/org/%s.org"
14786 ))
14787
14788 (defun org-insert-export-options-template ()
14789 "Insert into the buffer a template with information for exporting."
14790 (interactive)
14791 (if (not (bolp)) (newline))
14792 (let ((s (org-get-current-options)))
14793 (and (string-match "#\\+CATEGORY" s)
14794 (setq s (substring s 0 (match-beginning 0))))
14795 (insert s)))
14796
14797 (defun org-toggle-fixed-width-section (arg)
14798 "Toggle the fixed-width export.
14799 If there is no active region, the QUOTE keyword at the current headline is
14800 inserted or removed. When present, it causes the text between this headline
14801 and the next to be exported as fixed-width text, and unmodified.
14802 If there is an active region, this command adds or removes a colon as the
14803 first character of this line. If the first character of a line is a colon,
14804 this line is also exported in fixed-width font."
14805 (interactive "P")
14806 (let* ((cc 0)
14807 (regionp (org-region-active-p))
14808 (beg (if regionp (region-beginning) (point)))
14809 (end (if regionp (region-end)))
14810 (nlines (or arg (if (and beg end) (count-lines beg end) 1)))
14811 (re "[ \t]*\\(:\\)")
14812 off)
14813 (if regionp
14814 (save-excursion
14815 (goto-char beg)
14816 (setq cc (current-column))
14817 (beginning-of-line 1)
14818 (setq off (looking-at re))
14819 (while (> nlines 0)
14820 (setq nlines (1- nlines))
14821 (beginning-of-line 1)
14822 (cond
14823 (arg
14824 (move-to-column cc t)
14825 (insert ":\n")
14826 (forward-line -1))
14827 ((and off (looking-at re))
14828 (replace-match "" t t nil 1))
14829 ((not off) (move-to-column cc t) (insert ":")))
14830 (forward-line 1)))
14831 (save-excursion
14832 (org-back-to-heading)
14833 (if (looking-at (concat outline-regexp
14834 "\\( +\\<" org-quote-string "\\>\\)"))
14835 (replace-match "" t t nil 1)
14836 (if (looking-at outline-regexp)
14837 (progn
14838 (goto-char (match-end 0))
14839 (insert " " org-quote-string))))))))
14840
14841 (defun org-export-as-html-and-open (arg)
14842 "Export the outline as HTML and immediately open it with a browser.
14843 If there is an active region, export only the region.
14844 The prefix ARG specifies how many levels of the outline should become
14845 headlines. The default is 3. Lower levels will become bulleted lists."
14846 (interactive "P")
14847 (org-export-as-html arg 'hidden)
14848 (org-open-file buffer-file-name))
14849
14850 (defun org-export-as-html-batch ()
14851 "Call `org-export-as-html', may be used in batch processing as
14852 emacs --batch
14853 --load=$HOME/lib/emacs/org.el
14854 --eval \"(setq org-export-headline-levels 2)\"
14855 --visit=MyFile --funcall org-export-as-html-batch"
14856 (org-export-as-html org-export-headline-levels 'hidden))
14857
14858 (defun org-export-as-html (arg &optional hidden ext-plist)
14859 "Export the outline as a pretty HTML file.
14860 If there is an active region, export only the region.
14861 The prefix ARG specifies how many levels of the outline should become
14862 headlines. The default is 3. Lower levels will become bulleted lists.
14863 When HIDDEN is non-nil, don't display the HTML buffer.
14864 EXT-PLIST is a property list with external parameters overriding
14865 org-mode's default settings, but still inferior to file-local settings."
14866 (interactive "P")
14867 (message "Exporting...")
14868 (setq-default org-todo-line-regexp org-todo-line-regexp)
14869 (setq-default org-deadline-line-regexp org-deadline-line-regexp)
14870 (setq-default org-done-string org-done-string)
14871 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
14872 ext-plist
14873 (org-infile-export-plist)))
14874
14875 (style (plist-get opt-plist :style))
14876 (link-validate (plist-get opt-plist :link-validation-function))
14877 valid
14878 (odd org-odd-levels-only)
14879 (region-p (org-region-active-p))
14880 (region
14881 (buffer-substring
14882 (if region-p (region-beginning) (point-min))
14883 (if region-p (region-end) (point-max))))
14884 ;; The following two are dynamically scoped into other
14885 ;; routines below.
14886 (org-current-export-dir (org-export-directory :html opt-plist))
14887 (org-current-export-file buffer-file-name)
14888 (all_lines
14889 (org-skip-comments (org-split-string
14890 (org-cleaned-string-for-export
14891 region :emph-multiline
14892 (if (plist-get opt-plist :LaTeX-fragments)
14893 :LaTeX-fragments))
14894 "[\r\n]")))
14895 (lines (org-export-find-first-heading-line all_lines))
14896 (level 0) (line "") (origline "") txt todo
14897 (umax nil)
14898 (filename (concat (file-name-as-directory
14899 (org-export-directory :html opt-plist))
14900 (file-name-sans-extension
14901 (file-name-nondirectory buffer-file-name))
14902 ".html"))
14903 (current-dir (file-name-directory buffer-file-name))
14904 (buffer (find-file-noselect filename))
14905 (levels-open (make-vector org-level-max nil))
14906 (date (format-time-string "%Y/%m/%d" (current-time)))
14907 (time (format-time-string "%X" (org-current-time)))
14908 (author (plist-get opt-plist :author))
14909 (title (or (plist-get opt-plist :title)
14910 (file-name-sans-extension
14911 (file-name-nondirectory buffer-file-name))))
14912 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
14913 (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
14914 (inquote nil)
14915 (infixed nil)
14916 (in-local-list nil)
14917 (local-list-num nil)
14918 (local-list-indent nil)
14919 (llt org-plain-list-ordered-item-terminator)
14920 (email (plist-get opt-plist :email))
14921 (language (plist-get opt-plist :language))
14922 (text (plist-get opt-plist :text))
14923 (lang-words nil)
14924 (target-alist nil) tg
14925 (head-count 0) cnt
14926 (start 0)
14927 (coding-system (and (boundp 'buffer-file-coding-system)
14928 buffer-file-coding-system))
14929 (coding-system-for-write coding-system)
14930 (save-buffer-coding-system coding-system)
14931 (charset (and coding-system
14932 (fboundp 'coding-system-get)
14933 (coding-system-get coding-system 'mime-charset)))
14934 table-open type
14935 table-buffer table-orig-buffer
14936 ind start-is-num starter
14937 rpl path desc descp desc1 desc2 link
14938 )
14939 (message "Exporting...")
14940
14941 (setq org-last-level 1)
14942 (org-init-section-numbers)
14943
14944 ;; Get the language-dependent settings
14945 (setq lang-words (or (assoc language org-export-language-setup)
14946 (assoc "en" org-export-language-setup)))
14947
14948 ;; Switch to the output buffer
14949 (if (or hidden (not org-export-html-show-new-buffer))
14950 (set-buffer buffer)
14951 (switch-to-buffer-other-window buffer))
14952 (erase-buffer)
14953 (fundamental-mode)
14954 (let ((case-fold-search nil)
14955 (org-odd-levels-only odd))
14956 ;; create local variables for all options, to make sure all called
14957 ;; functions get the correct information
14958 (mapcar (lambda (x)
14959 (set (make-local-variable (cdr x))
14960 (plist-get opt-plist (car x))))
14961 org-export-plist-vars)
14962 (setq umax (if arg (prefix-numeric-value arg)
14963 org-export-headline-levels))
14964
14965 ;; File header
14966 (insert (format
14967 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
14968 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
14969 <html xmlns=\"http://www.w3.org/1999/xhtml\"
14970 lang=\"%s\" xml:lang=\"%s\">
14971 <head>
14972 <title>%s</title>
14973 <meta http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"/>
14974 <meta name=\"generator\" content=\"Org-mode\"/>
14975 <meta name=\"generated\" content=\"%s %s\"/>
14976 <meta name=\"author\" content=\"%s\"/>
14977 %s
14978 </head><body>
14979 "
14980 language language (org-html-expand title) (or charset "iso-8859-1")
14981 date time author style))
14982
14983
14984 (insert (or (plist-get opt-plist :preamble) ""))
14985
14986 (when (plist-get opt-plist :auto-preamble)
14987 (if title (insert (format org-export-html-title-format
14988 (org-html-expand title))))
14989 (if text (insert "<p>\n" (org-html-expand text) "</p>")))
14990
14991 (if org-export-with-toc
14992 (progn
14993 (insert (format "<h%d>%s</h%d>\n"
14994 org-export-html-toplevel-hlevel
14995 (nth 3 lang-words)
14996 org-export-html-toplevel-hlevel))
14997 (insert "<ul>\n<li>")
14998 (setq lines
14999 (mapcar '(lambda (line)
15000 (if (string-match org-todo-line-regexp line)
15001 ;; This is a headline
15002 (progn
15003 (setq level (- (match-end 1) (match-beginning 1))
15004 level (org-tr-level level)
15005 txt (save-match-data
15006 (org-html-expand
15007 (org-export-cleanup-toc-line
15008 (match-string 3 line))))
15009 todo
15010 (or (and org-export-mark-todo-in-toc
15011 (match-beginning 2)
15012 (not (equal (match-string 2 line)
15013 org-done-string)))
15014 ; TODO, not DONE
15015 (and org-export-mark-todo-in-toc
15016 (= level umax)
15017 (org-search-todo-below
15018 line lines level))))
15019 (if (and (memq org-export-with-tags '(not-in-toc nil))
15020 (string-match "[ \t]+:[a-zA-Z0-9_@:]+:[ \t]*$" txt))
15021 (setq txt (replace-match "" t t txt)))
15022 (if (string-match quote-re0 txt)
15023 (setq txt (replace-match "" t t txt)))
15024 (if org-export-with-section-numbers
15025 (setq txt (concat (org-section-number level)
15026 " " txt)))
15027 (if (<= level umax)
15028 (progn
15029 (setq head-count (+ head-count 1))
15030 (if (> level org-last-level)
15031 (progn
15032 (setq cnt (- level org-last-level))
15033 (while (>= (setq cnt (1- cnt)) 0)
15034 (insert "\n<ul>\n<li>"))
15035 (insert "\n")))
15036 (if (< level org-last-level)
15037 (progn
15038 (setq cnt (- org-last-level level))
15039 (while (>= (setq cnt (1- cnt)) 0)
15040 (insert "</li>\n</ul>"))
15041 (insert "\n")))
15042 ;; Check for targets
15043 (while (string-match org-target-regexp line)
15044 (setq tg (match-string 1 line)
15045 line (replace-match
15046 (concat "@<span class=\"target\">" tg "@</span> ")
15047 t t line))
15048 (push (cons (org-solidify-link-text tg)
15049 (format "sec-%d" head-count))
15050 target-alist))
15051 (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
15052 (setq txt (replace-match "" t t txt)))
15053 (insert
15054 (format
15055 (if todo
15056 "</li>\n<li><a href=\"#sec-%d\"><span class=\"todo\">%s</span></a>"
15057 "</li>\n<li><a href=\"#sec-%d\">%s</a>")
15058 head-count txt))
15059
15060 (setq org-last-level level))
15061 )))
15062 line)
15063 lines))
15064 (while (> org-last-level 0)
15065 (setq org-last-level (1- org-last-level))
15066 (insert "</li>\n</ul>\n"))
15067 ))
15068 (setq head-count 0)
15069 (org-init-section-numbers)
15070
15071 (while (setq line (pop lines) origline line)
15072 (catch 'nextline
15073
15074 ;; end of quote section?
15075 (when (and inquote (string-match "^\\*+" line))
15076 (insert "</pre>\n")
15077 (setq inquote nil))
15078 ;; inside a quote section?
15079 (when inquote
15080 (insert (org-html-protect line) "\n")
15081 (throw 'nextline nil))
15082
15083 ;; verbatim lines
15084 (when (and org-export-with-fixed-width
15085 (string-match "^[ \t]*:\\(.*\\)" line))
15086 (when (not infixed)
15087 (setq infixed t)
15088 (insert "<pre>\n"))
15089 (insert (org-html-protect (match-string 1 line)) "\n")
15090 (when (and lines
15091 (not (string-match "^[ \t]*\\(:.*\\)"
15092 (car lines))))
15093 (setq infixed nil)
15094 (insert "</pre>\n"))
15095 (throw 'nextline nil))
15096
15097
15098 ;; make targets to anchors
15099 (while (string-match "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line)
15100 (cond
15101 ((match-end 2)
15102 (setq line (replace-match
15103 (concat "@<a name=\""
15104 (org-solidify-link-text (match-string 1 line))
15105 "\">\\nbsp@</a>")
15106 t t line)))
15107 ((and org-export-with-toc (equal (string-to-char line) ?*))
15108 (setq line (replace-match
15109 (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
15110 ; (concat "@<i>" (match-string 1 line) "@</i> ")
15111 t t line)))
15112 (t
15113 (setq line (replace-match
15114 (concat "@<a name=\""
15115 (org-solidify-link-text (match-string 1 line))
15116 "\" class=\"target\">" (match-string 1 line) "@</a> ")
15117 t t line)))))
15118
15119 (setq line (org-html-handle-time-stamps line))
15120
15121 ;; replace "&" by "&amp;", "<" and ">" by "&lt;" and "&gt;"
15122 ;; handle @<..> HTML tags (replace "@&gt;..&lt;" by "<..>")
15123 ;; Also handle sub_superscripts and checkboxes
15124 (setq line (org-html-expand line))
15125
15126 ;; Format the links
15127 (setq start 0)
15128 (while (string-match org-bracket-link-analytic-regexp line start)
15129 (setq start (match-beginning 0))
15130 (setq type (if (match-end 2) (match-string 2 line) "internal"))
15131 (setq path (match-string 3 line))
15132 (setq desc1 (if (match-end 5) (match-string 5 line))
15133 desc2 (if (match-end 2) (concat type ":" path) path)
15134 descp (and desc1 (not (equal desc1 desc2)))
15135 desc (or desc1 desc2))
15136 ;; FIXME: do we need to unescape here somewhere?
15137 (cond
15138 ((equal type "internal")
15139 (setq rpl
15140 (concat
15141 "<a href=\"#"
15142 (org-solidify-link-text path target-alist)
15143 "\">" desc "</a>")))
15144 ((member type '("http" "https" "ftp" "mailto" "news"))
15145 ;; standard URL
15146 (setq link (concat type ":" path))
15147 (setq rpl (concat "<a href=\"" link "\">" desc "</a>")))
15148 ((string= type "file")
15149 ;; FILE link
15150 (let* ((filename path)
15151 (abs-p (file-name-absolute-p filename))
15152 thefile file-is-image-p search)
15153 (save-match-data
15154 (if (string-match "::\\(.*\\)" filename)
15155 (setq search (match-string 1 filename)
15156 filename (replace-match "" t nil filename)))
15157 (setq valid
15158 (if (functionp link-validate)
15159 (funcall link-validate filename current-dir)
15160 t))
15161 (setq file-is-image-p
15162 (string-match (org-image-file-name-regexp) filename))
15163 (setq thefile (if abs-p (expand-file-name filename) filename))
15164 (when (and org-export-html-link-org-files-as-html
15165 (string-match "\\.org$" thefile))
15166 (setq thefile (concat (substring thefile 0
15167 (match-beginning 0))
15168 ".html"))
15169 (if (and search
15170 ;; make sure this is can be used as target search
15171 (not (string-match "^[0-9]*$" search))
15172 (not (string-match "^\\*" search))
15173 (not (string-match "^/.*/$" search)))
15174 (setq thefile (concat thefile "#"
15175 (org-solidify-link-text
15176 (org-link-unescape search)))))
15177 (when (string-match "^file:" desc)
15178 (setq desc (replace-match "" t t desc))
15179 (if (string-match "\\.org$" desc)
15180 (setq desc (replace-match "" t t desc))))))
15181 (setq rpl (if (and file-is-image-p
15182 (or (eq t org-export-html-inline-images)
15183 (and org-export-html-inline-images
15184 (not descp))))
15185 (concat "<img src=\"" thefile "\"/>")
15186 (concat "<a href=\"" thefile "\">" desc "</a>")))
15187 (if (not valid) (setq rpl desc))))
15188 ((member type '("bbdb" "vm" "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
15189 (setq rpl (concat "<i>&lt;" type ":"
15190 (save-match-data (org-link-unescape path))
15191 "&gt;</i>"))))
15192 (setq line (replace-match rpl t t line)
15193 start (+ start (length rpl))))
15194 ;; TODO items
15195 (if (and (string-match org-todo-line-regexp line)
15196 (match-beginning 2))
15197 (if (equal (match-string 2 line) org-done-string)
15198 (setq line (replace-match
15199 "<span class=\"done\">\\2</span>"
15200 t nil line 2))
15201 (setq line (replace-match "<span class=\"todo\">\\2</span>"
15202 t nil line 2))))
15203
15204 (cond
15205 ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line)
15206 ;; This is a headline
15207 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
15208 txt (match-string 2 line))
15209 (if (string-match quote-re0 txt)
15210 (setq txt (replace-match "" t t txt)))
15211 (if (<= level umax) (setq head-count (+ head-count 1)))
15212 (when in-local-list
15213 ;; Close any local lists before inserting a new header line
15214 (while local-list-num
15215 (org-close-li)
15216 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
15217 (pop local-list-num))
15218 (setq local-list-indent nil
15219 in-local-list nil))
15220 (org-html-level-start level txt umax
15221 (and org-export-with-toc (<= level umax))
15222 head-count)
15223 ;; QUOTES
15224 (when (string-match quote-re line)
15225 (insert "<pre>")
15226 (setq inquote t)))
15227
15228 ((and org-export-with-tables
15229 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
15230 (if (not table-open)
15231 ;; New table starts
15232 (setq table-open t table-buffer nil table-orig-buffer nil))
15233 ;; Accumulate lines
15234 (setq table-buffer (cons line table-buffer)
15235 table-orig-buffer (cons origline table-orig-buffer))
15236 (when (or (not lines)
15237 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
15238 (car lines))))
15239 (setq table-open nil
15240 table-buffer (nreverse table-buffer)
15241 table-orig-buffer (nreverse table-orig-buffer))
15242 (org-close-par-maybe)
15243 (insert (org-format-table-html table-buffer table-orig-buffer))))
15244 (t
15245 ;; Normal lines
15246 (when (string-match
15247 (cond
15248 ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
15249 ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
15250 ((= llt ?\)) "^\\( \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
15251 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
15252 line)
15253 (setq ind (org-get-string-indentation line)
15254 start-is-num (match-beginning 4)
15255 starter (if (match-beginning 2)
15256 (substring (match-string 2 line) 0 -1))
15257 line (substring line (match-beginning 5)))
15258 (unless (string-match "[^ \t]" line)
15259 ;; empty line. Pretend indentation is large.
15260 (setq ind (1+ (or (car local-list-indent) 1))))
15261 (while (and in-local-list
15262 (or (and (= ind (car local-list-indent))
15263 (not starter))
15264 (< ind (car local-list-indent))))
15265 (org-close-li)
15266 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
15267 (pop local-list-num) (pop local-list-indent)
15268 (setq in-local-list local-list-indent))
15269 (cond
15270 ((and starter
15271 (or (not in-local-list)
15272 (> ind (car local-list-indent))))
15273 ;; Start new (level of ) list
15274 (org-close-par-maybe)
15275 (insert (if start-is-num "<ol>\n<li>\n" "<ul>\n<li>\n"))
15276 (push start-is-num local-list-num)
15277 (push ind local-list-indent)
15278 (setq in-local-list t))
15279 (starter
15280 ;; continue current list
15281 (org-close-li)
15282 (insert "<li>\n")))
15283 (if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
15284 (setq line
15285 (replace-match
15286 (if (equal (match-string 1 line) "X")
15287 "<b>[X]</b>"
15288 "<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
15289 t t line))))
15290
15291 ;; Empty lines start a new paragraph. If hand-formatted lists
15292 ;; are not fully interpreted, lines starting with "-", "+", "*"
15293 ;; also start a new paragraph.
15294 (if (string-match "^ [-+*]-\\|^[ \t]*$" line) (org-open-par))
15295
15296 ;; Check if the line break needs to be conserved
15297 (cond
15298 ((string-match "\\\\\\\\[ \t]*$" line)
15299 (setq line (replace-match "<br/>" t t line)))
15300 (org-export-preserve-breaks
15301 (setq line (concat line "<br/>"))))
15302
15303 (insert line "\n")))))
15304
15305 ;; Properly close all local lists and other lists
15306 (when inquote (insert "</pre>\n"))
15307 (when in-local-list
15308 ;; Close any local lists before inserting a new header line
15309 (while local-list-num
15310 (org-close-li)
15311 (insert (if (car local-list-num) "</ol>\n" "</ul>\n"))
15312 (pop local-list-num))
15313 (setq local-list-indent nil
15314 in-local-list nil))
15315 (org-html-level-start 1 nil umax
15316 (and org-export-with-toc (<= level umax))
15317 head-count)
15318
15319 (when (plist-get opt-plist :auto-postamble)
15320 (when author
15321 (insert "<p class=\"author\"> "
15322 (nth 1 lang-words) ": " author "\n")
15323 (when email
15324 (insert "<a href=\"mailto:" email "\">&lt;"
15325 email "&gt;</a>\n"))
15326 (insert "</p>\n"))
15327 (when (and date time)
15328 (insert "<p class=\"date\"> "
15329 (nth 2 lang-words) ": "
15330 date " " time "</p>\n")))
15331
15332 (if org-export-html-with-timestamp
15333 (insert org-export-html-html-helper-timestamp))
15334 (insert (or (plist-get opt-plist :postamble) ""))
15335 (insert "</body>\n</html>\n")
15336 (normal-mode)
15337 ;; remove empty paragraphs and lists
15338 (goto-char (point-min))
15339 (while (re-search-forward "<p>[ \r\n\t]*</p>" nil t)
15340 (replace-match ""))
15341 (goto-char (point-min))
15342 (while (re-search-forward "<li>[ \r\n\t]*</li>\n?" nil t)
15343 (replace-match ""))
15344 (save-buffer)
15345 (goto-char (point-min))
15346 (message "Exporting... done"))))
15347
15348
15349 (defun org-format-table-html (lines olines)
15350 "Find out which HTML converter to use and return the HTML code."
15351 (if (string-match "^[ \t]*|" (car lines))
15352 ;; A normal org table
15353 (org-format-org-table-html lines)
15354 ;; Table made by table.el - test for spanning
15355 (let* ((hlines (delq nil (mapcar
15356 (lambda (x)
15357 (if (string-match "^[ \t]*\\+-" x) x
15358 nil))
15359 lines)))
15360 (first (car hlines))
15361 (ll (and (string-match "\\S-+" first)
15362 (match-string 0 first)))
15363 (re (concat "^[ \t]*" (regexp-quote ll)))
15364 (spanning (delq nil (mapcar (lambda (x) (not (string-match re x)))
15365 hlines))))
15366 (if (and (not spanning)
15367 (not org-export-prefer-native-exporter-for-tables))
15368 ;; We can use my own converter with HTML conversions
15369 (org-format-table-table-html lines)
15370 ;; Need to use the code generator in table.el, with the original text.
15371 (org-format-table-table-html-using-table-generate-source olines)))))
15372
15373 (defun org-format-org-table-html (lines)
15374 "Format a table into HTML."
15375 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
15376 (setq lines (nreverse lines))
15377 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
15378 (setq lines (nreverse lines))
15379 (when org-export-table-remove-special-lines
15380 ;; Check if the table has a marking column. If yes remove the
15381 ;; column and the special lines
15382 (let* ((special
15383 (not
15384 (memq nil
15385 (mapcar
15386 (lambda (x)
15387 (or (string-match "^[ \t]*|-" x)
15388 (string-match "^[ \t]*| *\\([#!$*_^ ]\\) *|" x)))
15389 lines)))))
15390 (if special
15391 (setq lines
15392 (delq nil
15393 (mapcar
15394 (lambda (x)
15395 (if (string-match "^[ \t]*| *[!_^] *|" x)
15396 nil ; ignore this line
15397 (and (or (string-match "^[ \t]*|-+\\+" x)
15398 (string-match "^[ \t]*|[^|]*|" x))
15399 (replace-match "|" t t x))))
15400 lines))))))
15401
15402 (let ((head (and org-export-highlight-first-table-line
15403 (delq nil (mapcar
15404 (lambda (x) (string-match "^[ \t]*|-" x))
15405 (cdr lines)))))
15406 line fields html)
15407 (setq html (concat org-export-html-table-tag "\n"))
15408 (while (setq line (pop lines))
15409 (catch 'next-line
15410 (if (string-match "^[ \t]*|-" line)
15411 (progn
15412 (setq head nil) ;; head ends here, first time around
15413 ;; ignore this line
15414 (throw 'next-line t)))
15415 ;; Break the line into fields
15416 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
15417 (setq html (concat
15418 html
15419 "<tr>"
15420 (mapconcat (lambda (x)
15421 (if head
15422 (concat "<th>" x "</th>")
15423 (concat "<td>" x "</td>")))
15424 fields "")
15425 "</tr>\n"))))
15426 (setq html (concat html "</table>\n"))
15427 html))
15428
15429 (defun org-fake-empty-table-line (line)
15430 "Replace everything except \"|\" with spaces."
15431 (let ((i (length line))
15432 (newstr (copy-sequence line)))
15433 (while (> i 0)
15434 (setq i (1- i))
15435 (if (not (eq (aref newstr i) ?|))
15436 (aset newstr i ?\ )))
15437 newstr))
15438
15439 (defun org-format-table-table-html (lines)
15440 "Format a table generated by table.el into HTML.
15441 This conversion does *not* use `table-generate-source' from table.el.
15442 This has the advantage that Org-mode's HTML conversions can be used.
15443 But it has the disadvantage, that no cell- or row-spanning is allowed."
15444 (let (line field-buffer
15445 (head org-export-highlight-first-table-line)
15446 fields html empty)
15447 (setq html (concat org-export-html-table-tag "\n"))
15448 (while (setq line (pop lines))
15449 (setq empty "&nbsp;")
15450 (catch 'next-line
15451 (if (string-match "^[ \t]*\\+-" line)
15452 (progn
15453 (if field-buffer
15454 (progn
15455 (setq html (concat
15456 html
15457 "<tr>"
15458 (mapconcat
15459 (lambda (x)
15460 (if (equal x "") (setq x empty))
15461 (if head
15462 (concat "<th>" x "</th>\n")
15463 (concat "<td>" x "</td>\n")))
15464 field-buffer "\n")
15465 "</tr>\n"))
15466 (setq head nil)
15467 (setq field-buffer nil)))
15468 ;; Ignore this line
15469 (throw 'next-line t)))
15470 ;; Break the line into fields and store the fields
15471 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
15472 (if field-buffer
15473 (setq field-buffer (mapcar
15474 (lambda (x)
15475 (concat x "<br/>" (pop fields)))
15476 field-buffer))
15477 (setq field-buffer fields))))
15478 (setq html (concat html "</table>\n"))
15479 html))
15480
15481 (defun org-format-table-table-html-using-table-generate-source (lines)
15482 "Format a table into html, using `table-generate-source' from table.el.
15483 This has the advantage that cell- or row-spanning is allowed.
15484 But it has the disadvantage, that Org-mode's HTML conversions cannot be used."
15485 (require 'table)
15486 (with-current-buffer (get-buffer-create " org-tmp1 ")
15487 (erase-buffer)
15488 (insert (mapconcat 'identity lines "\n"))
15489 (goto-char (point-min))
15490 (if (not (re-search-forward "|[^+]" nil t))
15491 (error "Error processing table"))
15492 (table-recognize-table)
15493 (with-current-buffer (get-buffer-create " org-tmp2 ") (erase-buffer))
15494 (table-generate-source 'html " org-tmp2 ")
15495 (set-buffer " org-tmp2 ")
15496 (buffer-substring (point-min) (point-max))))
15497
15498 (defun org-html-handle-time-stamps (s)
15499 "Format time stamps in string S, or remove them."
15500 (catch 'exit
15501 (let (r b)
15502 (while (string-match org-maybe-keyword-time-regexp s)
15503 (if (and (match-end 1) (equal (match-string 1 s) org-clock-string))
15504 ;; never export CLOCK
15505 (throw 'exit ""))
15506 (or b (setq b (substring s 0 (match-beginning 0))))
15507 (if (not org-export-with-timestamps)
15508 (setq r (concat r (substring s 0 (match-beginning 0)))
15509 s (substring s (match-end 0)))
15510 (setq r (concat
15511 r (substring s 0 (match-beginning 0))
15512 (if (match-end 1)
15513 (format "@<span class=\"timestamp-kwd\">%s @</span>"
15514 (match-string 1 s)))
15515 (format " @<span class=\"timestamp\">%s@</span>"
15516 (substring (match-string 3 s) 1 -1)))
15517 s (substring s (match-end 0)))))
15518 ;; Line break if line started and ended with time stamp stuff
15519 (if (not r)
15520 s
15521 (setq r (concat r s))
15522 (unless (string-match "\\S-" (concat b s))
15523 (setq r (concat r "@<br/>")))
15524 r))))
15525
15526 (defun org-html-protect (s)
15527 ;; convert & to &amp;, < to &lt; and > to &gt;
15528 (let ((start 0))
15529 (while (string-match "&" s start)
15530 (setq s (replace-match "&amp;" t t s)
15531 start (1+ (match-beginning 0))))
15532 (while (string-match "<" s)
15533 (setq s (replace-match "&lt;" t t s)))
15534 (while (string-match ">" s)
15535 (setq s (replace-match "&gt;" t t s))))
15536 s)
15537
15538 (defun org-export-cleanup-toc-line (s)
15539 "Remove tags and time staps from lines going into the toc."
15540 (if (string-match " +:[a-zA-Z0-9_@:]+: *$" s)
15541 (setq s (replace-match "" t t s)))
15542 (when org-export-remove-timestamps-from-toc
15543 (while (string-match org-maybe-keyword-time-regexp s)
15544 (setq s (replace-match "" t t s))))
15545 s)
15546
15547 (defun org-html-expand (string)
15548 "Prepare STRING for HTML export. Applies all active conversions.
15549 If there are links in the string, don't modify these."
15550 (let* (m s l res)
15551 (while (setq m (string-match org-bracket-link-regexp string))
15552 (setq s (substring string 0 m)
15553 l (match-string 0 string)
15554 string (substring string (match-end 0)))
15555 (push (org-html-do-expand s) res)
15556 (push l res))
15557 (push (org-html-do-expand string) res)
15558 (apply 'concat (nreverse res))))
15559
15560 (defun org-html-do-expand (s)
15561 "Apply all active conversions to translate special ASCII to HTML."
15562 (setq s (org-html-protect s))
15563 (if org-export-html-expand
15564 (while (string-match "@&lt;\\([^&]*\\)&gt;" s)
15565 (setq s (replace-match "<\\1>" t nil s))))
15566 (if org-export-with-emphasize
15567 (setq s (org-export-html-convert-emphasize s)))
15568 (if org-export-with-sub-superscripts
15569 (setq s (org-export-html-convert-sub-super s)))
15570 (if org-export-with-TeX-macros
15571 (let ((start 0) wd ass)
15572 (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)" s start))
15573 (setq wd (match-string 1 s))
15574 (if (setq ass (assoc wd org-html-entities))
15575 (setq s (replace-match (or (cdr ass)
15576 (concat "&" (car ass) ";"))
15577 t t s))
15578 (setq start (+ start (length wd)))))))
15579 s)
15580
15581 (defun org-create-multibrace-regexp (left right n)
15582 "Create a regular expression which will match a balanced sexp.
15583 Opening delimiter is LEFT, and closing delimiter is RIGHT, both given
15584 as single character strings.
15585 The regexp returned will match the entire expression including the
15586 delimiters. It will also define a single group which contains the
15587 match except for the outermost delimiters. The maximum depth of
15588 stacked delimiters is N. Escaping delimiters is not possible."
15589 (let* ((nothing (concat "[^" "\\" left "\\" right "]*?"))
15590 (or "\\|")
15591 (re nothing)
15592 (next (concat "\\(?:" nothing left nothing right "\\)+" nothing)))
15593 (while (> n 1)
15594 (setq n (1- n)
15595 re (concat re or next)
15596 next (concat "\\(?:" nothing left next right "\\)+" nothing)))
15597 (concat left "\\(" re "\\)" right)))
15598
15599 (defvar org-match-substring-regexp
15600 (concat
15601 "\\([^\\]\\)\\([_^]\\)\\("
15602 "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
15603 "\\|"
15604 "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
15605 "\\|"
15606 "\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
15607 "The regular expression matching a sub- or superscript.")
15608
15609 (defun org-export-html-convert-sub-super (string)
15610 "Convert sub- and superscripts in STRING to HTML."
15611 (let (key c)
15612 (while (string-match org-match-substring-regexp string)
15613 (setq key (if (string= (match-string 2 string) "_") "sub" "sup"))
15614 (setq c (or (match-string 8 string)
15615 (match-string 6 string)
15616 (match-string 5 string)))
15617 (setq string (replace-match
15618 (concat (match-string 1 string)
15619 "<" key ">" c "</" key ">")
15620 t t string)))
15621 (while (string-match "\\\\\\([_^]\\)" string)
15622 (setq string (replace-match (match-string 1 string) t t string))))
15623 string)
15624
15625 (defun org-export-html-convert-emphasize (string)
15626 "Apply emphasis."
15627 (while (string-match org-emph-re string)
15628 (setq string (replace-match (concat "\\1" (nth 2 (assoc (match-string 3 string) org-emphasis-alist)) "\\4" (nth 3 (assoc (match-string 3 string) org-emphasis-alist)) "\\5") t nil string)))
15629 string)
15630
15631 (defvar org-par-open nil)
15632 (defun org-open-par ()
15633 "Insert <p>, but first close previous paragraph if any."
15634 (org-close-par-maybe)
15635 (insert "\n<p>")
15636 (setq org-par-open t))
15637 (defun org-close-par-maybe ()
15638 "Close paragraph if there is one open."
15639 (when org-par-open
15640 (insert "</p>")
15641 (setq org-par-open nil)))
15642 (defun org-close-li ()
15643 "Close <li> if necessary."
15644 (org-close-par-maybe)
15645 (insert "</li>\n"))
15646 ; (when (save-excursion
15647 ; (re-search-backward "</?\\(ul\\|ol\\|li\\|[hH][0-9]\\)>" nil t))
15648 ; (if (member (match-string 0) '("</ul>" "</ol>" "<li>"))
15649 ; (insert "</li>"))))
15650
15651 (defun org-html-level-start (level title umax with-toc head-count)
15652 "Insert a new level in HTML export.
15653 When TITLE is nil, just close all open levels."
15654 (org-close-par-maybe)
15655 (let ((l (1+ (max level umax))))
15656 (while (<= l org-level-max)
15657 (if (aref levels-open (1- l))
15658 (progn
15659 (org-html-level-close l)
15660 (aset levels-open (1- l) nil)))
15661 (setq l (1+ l)))
15662 (when title
15663 ;; If title is nil, this means this function is called to close
15664 ;; all levels, so the rest is done only if title is given
15665 (when (string-match "\\(:[a-zA-Z0-9_@:]+:\\)[ \t]*$" title)
15666 (setq title (replace-match
15667 (if org-export-with-tags
15668 (save-match-data
15669 (concat
15670 "&nbsp;&nbsp;&nbsp;<span class=\"tag\">"
15671 (mapconcat 'identity (org-split-string
15672 (match-string 1 title) ":")
15673 "&nbsp;")
15674 "</span>"))
15675 "")
15676 t t title)))
15677 (if (> level umax)
15678 (progn
15679 (if (aref levels-open (1- level))
15680 (progn
15681 (org-close-li)
15682 (insert "<li>" title "<br/>\n"))
15683 (aset levels-open (1- level) t)
15684 (org-close-par-maybe)
15685 (insert "<ul>\n<li>" title "<br/>\n")))
15686 (if org-export-with-section-numbers
15687 (setq title (concat (org-section-number level) " " title)))
15688 (setq level (+ level org-export-html-toplevel-hlevel -1))
15689 (if with-toc
15690 (insert (format "\n<h%d><a name=\"sec-%d\">%s</a></h%d>\n"
15691 level head-count title level))
15692 (insert (format "\n<h%d>%s</h%d>\n" level title level)))
15693 (org-open-par)))))
15694
15695 (defun org-html-level-close (&rest args)
15696 "Terminate one level in HTML export."
15697 (org-close-li)
15698 (insert "</ul>"))
15699
15700 ;; Variable holding the vector with section numbers
15701 (defvar org-section-numbers (make-vector org-level-max 0))
15702
15703 (defun org-init-section-numbers ()
15704 "Initialize the vector for the section numbers."
15705 (let* ((level -1)
15706 (numbers (nreverse (org-split-string "" "\\.")))
15707 (depth (1- (length org-section-numbers)))
15708 (i depth) number-string)
15709 (while (>= i 0)
15710 (if (> i level)
15711 (aset org-section-numbers i 0)
15712 (setq number-string (or (car numbers) "0"))
15713 (if (string-match "\\`[A-Z]\\'" number-string)
15714 (aset org-section-numbers i
15715 (- (string-to-char number-string) ?A -1))
15716 (aset org-section-numbers i (string-to-number number-string)))
15717 (pop numbers))
15718 (setq i (1- i)))))
15719
15720 (defun org-section-number (&optional level)
15721 "Return a string with the current section number.
15722 When LEVEL is non-nil, increase section numbers on that level."
15723 (let* ((depth (1- (length org-section-numbers))) idx n (string ""))
15724 (when level
15725 (when (> level -1)
15726 (aset org-section-numbers
15727 level (1+ (aref org-section-numbers level))))
15728 (setq idx (1+ level))
15729 (while (<= idx depth)
15730 (if (not (= idx 1))
15731 (aset org-section-numbers idx 0))
15732 (setq idx (1+ idx))))
15733 (setq idx 0)
15734 (while (<= idx depth)
15735 (setq n (aref org-section-numbers idx))
15736 (setq string (concat string (if (not (string= string "")) "." "")
15737 (int-to-string n)))
15738 (setq idx (1+ idx)))
15739 (save-match-data
15740 (if (string-match "\\`\\([@0]\\.\\)+" string)
15741 (setq string (replace-match "" t nil string)))
15742 (if (string-match "\\(\\.0\\)+\\'" string)
15743 (setq string (replace-match "" t nil string))))
15744 string))
15745
15746
15747 ;;;###autoload
15748 (defun org-export-icalendar-this-file ()
15749 "Export current file as an iCalendar file.
15750 The iCalendar file will be located in the same directory as the Org-mode
15751 file, but with extension `.ics'."
15752 (interactive)
15753 (org-export-icalendar nil buffer-file-name))
15754
15755 (defun org-export-as-xoxo-insert-into (buffer &rest output)
15756 (with-current-buffer buffer
15757 (apply 'insert output)))
15758 (put 'org-export-as-xoxo-insert-into 'lisp-indent-function 1)
15759
15760 (defun org-export-as-xoxo (&optional buffer)
15761 "Export the org buffer as XOXO.
15762 The XOXO buffer is named *xoxo-<source buffer name>*"
15763 (interactive (list (current-buffer)))
15764 ;; A quickie abstraction
15765
15766 ;; Output everything as XOXO
15767 (with-current-buffer (get-buffer buffer)
15768 (goto-char (point-min)) ;; CD: beginning-of-buffer is not allowed.
15769 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
15770 (org-infile-export-plist)))
15771 (filename (concat (file-name-as-directory
15772 (org-export-directory :xoxo opt-plist))
15773 (file-name-sans-extension
15774 (file-name-nondirectory buffer-file-name))
15775 ".html"))
15776 (out (find-file-noselect filename))
15777 (last-level 1)
15778 (hanging-li nil))
15779 ;; Check the output buffer is empty.
15780 (with-current-buffer out (erase-buffer))
15781 ;; Kick off the output
15782 (org-export-as-xoxo-insert-into out "<ol class='xoxo'>\n")
15783 (while (re-search-forward "^\\(\\*+\\) \\(.+\\)" (point-max) 't)
15784 (let* ((hd (match-string-no-properties 1))
15785 (level (length hd))
15786 (text (concat
15787 (match-string-no-properties 2)
15788 (save-excursion
15789 (goto-char (match-end 0))
15790 (let ((str ""))
15791 (catch 'loop
15792 (while 't
15793 (forward-line)
15794 (if (looking-at "^[ \t]\\(.*\\)")
15795 (setq str (concat str (match-string-no-properties 1)))
15796 (throw 'loop str)))))))))
15797
15798 ;; Handle level rendering
15799 (cond
15800 ((> level last-level)
15801 (org-export-as-xoxo-insert-into out "\n<ol>\n"))
15802
15803 ((< level last-level)
15804 (dotimes (- (- last-level level) 1)
15805 (if hanging-li
15806 (org-export-as-xoxo-insert-into out "</li>\n"))
15807 (org-export-as-xoxo-insert-into out "</ol>\n"))
15808 (when hanging-li
15809 (org-export-as-xoxo-insert-into out "</li>\n")
15810 (setq hanging-li nil)))
15811
15812 ((equal level last-level)
15813 (if hanging-li
15814 (org-export-as-xoxo-insert-into out "</li>\n")))
15815 )
15816
15817 (setq last-level level)
15818
15819 ;; And output the new li
15820 (setq hanging-li 't)
15821 (if (equal ?+ (elt text 0))
15822 (org-export-as-xoxo-insert-into out "<li class='" (substring text 1) "'>")
15823 (org-export-as-xoxo-insert-into out "<li>" text))))
15824
15825 ;; Finally finish off the ol
15826 (dotimes (- last-level 1)
15827 (if hanging-li
15828 (org-export-as-xoxo-insert-into out "</li>\n"))
15829 (org-export-as-xoxo-insert-into out "</ol>\n"))
15830
15831 ;; Finish the buffer off and clean it up.
15832 (switch-to-buffer-other-window out)
15833 (indent-region (point-min) (point-max) nil)
15834 (save-buffer)
15835 (goto-char (point-min))
15836 )))
15837
15838 ;;;###autoload
15839 (defun org-export-icalendar-all-agenda-files ()
15840 "Export all files in `org-agenda-files' to iCalendar .ics files.
15841 Each iCalendar file will be located in the same directory as the Org-mode
15842 file, but with extension `.ics'."
15843 (interactive)
15844 (apply 'org-export-icalendar nil (org-agenda-files t)))
15845
15846 ;;;###autoload
15847 (defun org-export-icalendar-combine-agenda-files ()
15848 "Export all files in `org-agenda-files' to a single combined iCalendar file.
15849 The file is stored under the name `org-combined-agenda-icalendar-file'."
15850 (interactive)
15851 (apply 'org-export-icalendar t (org-agenda-files t)))
15852
15853 (defun org-export-icalendar (combine &rest files)
15854 "Create iCalendar files for all elements of FILES.
15855 If COMBINE is non-nil, combine all calendar entries into a single large
15856 file and store it under the name `org-combined-agenda-icalendar-file'."
15857 (save-excursion
15858 (let* ((dir (org-export-directory
15859 :ical (list :publishing-directory
15860 org-export-publishing-directory)))
15861 file ical-file ical-buffer category started org-agenda-new-buffers)
15862
15863 (when combine
15864 (setq ical-file
15865 (if (file-name-absolute-p org-combined-agenda-icalendar-file)
15866 org-combined-agenda-icalendar-file
15867 (expand-file-name org-combined-agenda-icalendar-file dir))
15868 ical-buffer (org-get-agenda-file-buffer ical-file))
15869 (set-buffer ical-buffer) (erase-buffer))
15870 (while (setq file (pop files))
15871 (catch 'nextfile
15872 (org-check-agenda-file file)
15873 (set-buffer (org-get-agenda-file-buffer file))
15874 (unless combine
15875 (setq ical-file (concat (file-name-as-directory dir)
15876 (file-name-sans-extension
15877 (file-name-nondirectory buffer-file-name))
15878 ".ics"))
15879 (setq ical-buffer (org-get-agenda-file-buffer ical-file))
15880 (with-current-buffer ical-buffer (erase-buffer)))
15881 (setq category (or org-category
15882 (file-name-sans-extension
15883 (file-name-nondirectory buffer-file-name))))
15884 (if (symbolp category) (setq category (symbol-name category)))
15885 (let ((standard-output ical-buffer))
15886 (if combine
15887 (and (not started) (setq started t)
15888 (org-start-icalendar-file org-icalendar-combined-name))
15889 (org-start-icalendar-file category))
15890 (org-print-icalendar-entries combine category)
15891 (when (or (and combine (not files)) (not combine))
15892 (org-finish-icalendar-file)
15893 (set-buffer ical-buffer)
15894 (save-buffer)
15895 (run-hooks 'org-after-save-iCalendar-file-hook)))))
15896 (org-release-buffers org-agenda-new-buffers))))
15897
15898 (defvar org-after-save-iCalendar-file-hook nil
15899 "Hook run after an iCalendar file has been saved.
15900 The iCalendar buffer is still current when this hook is run.
15901 A good way to use this is to tell a desktop calenndar application to re-read
15902 the iCalendar file.")
15903
15904 (defun org-print-icalendar-entries (&optional combine category)
15905 "Print iCalendar entries for the current Org-mode file to `standard-output'.
15906 When COMBINE is non nil, add the category to each line."
15907 (let ((re2 (concat "--?-?\\(" org-ts-regexp "\\)"))
15908 (dts (org-ical-ts-to-string
15909 (format-time-string (cdr org-time-stamp-formats) (current-time))
15910 "DTSTART"))
15911 hd ts ts2 state (inc t) pos scheduledp deadlinep tmp pri)
15912 (save-excursion
15913 (goto-char (point-min))
15914 (while (re-search-forward org-ts-regexp nil t)
15915 (setq pos (match-beginning 0)
15916 ts (match-string 0)
15917 inc t
15918 hd (org-get-heading))
15919 (if (looking-at re2)
15920 (progn
15921 (goto-char (match-end 0))
15922 (setq ts2 (match-string 1) inc nil))
15923 (setq ts2 ts
15924 tmp (buffer-substring (max (point-min)
15925 (- pos org-ds-keyword-length))
15926 pos)
15927 deadlinep (string-match org-deadline-regexp tmp)
15928 scheduledp (string-match org-scheduled-regexp tmp)
15929 ;; donep (org-entry-is-done-p)
15930 ))
15931 (if (or (string-match org-tr-regexp hd)
15932 (string-match org-ts-regexp hd))
15933 (setq hd (replace-match "" t t hd)))
15934 (if combine
15935 (setq hd (concat hd " (category " category ")")))
15936 (if deadlinep (setq hd (concat "DL: " hd " This is a deadline")))
15937 (if scheduledp (setq hd (concat "S: " hd " Scheduled for this date")))
15938 (princ (format "BEGIN:VEVENT
15939 %s
15940 %s
15941 SUMMARY:%s
15942 END:VEVENT\n"
15943 (org-ical-ts-to-string ts "DTSTART")
15944 (org-ical-ts-to-string ts2 "DTEND" inc)
15945 hd)))
15946 (when org-icalendar-include-todo
15947 (goto-char (point-min))
15948 (while (re-search-forward org-todo-line-regexp nil t)
15949 (setq state (match-string 1))
15950 (unless (equal state org-done-string)
15951 (setq hd (match-string 3))
15952 (if (string-match org-priority-regexp hd)
15953 (setq pri (string-to-char (match-string 2 hd))
15954 hd (concat (substring hd 0 (match-beginning 1))
15955 (substring hd (- (match-end 1)))))
15956 (setq pri org-default-priority))
15957 (setq pri (floor (1+ (* 8. (/ (float (- org-lowest-priority pri))
15958 (- org-lowest-priority ?A))))))
15959
15960 (princ (format "BEGIN:VTODO
15961 %s
15962 SUMMARY:%s
15963 SEQUENCE:1
15964 PRIORITY:%d
15965 END:VTODO\n"
15966 dts hd pri))))))))
15967
15968 (defun org-start-icalendar-file (name)
15969 "Start an iCalendar file by inserting the header."
15970 (let ((user user-full-name)
15971 (name (or name "unknown"))
15972 (timezone (cadr (current-time-zone))))
15973 (princ
15974 (format "BEGIN:VCALENDAR
15975 VERSION:2.0
15976 X-WR-CALNAME:%s
15977 PRODID:-//%s//Emacs with Org-mode//EN
15978 X-WR-TIMEZONE:%s
15979 CALSCALE:GREGORIAN\n" name user timezone))))
15980
15981 (defun org-finish-icalendar-file ()
15982 "Finish an iCalendar file by inserting the END statement."
15983 (princ "END:VCALENDAR\n"))
15984
15985 (defun org-ical-ts-to-string (s keyword &optional inc)
15986 "Take a time string S and convert it to iCalendar format.
15987 KEYWORD is added in front, to make a complete line like DTSTART....
15988 When INC is non-nil, increase the hour by two (if time string contains
15989 a time), or the day by one (if it does not contain a time)."
15990 (let ((t1 (org-parse-time-string s 'nodefault))
15991 t2 fmt have-time time)
15992 (if (and (car t1) (nth 1 t1) (nth 2 t1))
15993 (setq t2 t1 have-time t)
15994 (setq t2 (org-parse-time-string s)))
15995 (let ((s (car t2)) (mi (nth 1 t2)) (h (nth 2 t2))
15996 (d (nth 3 t2)) (m (nth 4 t2)) (y (nth 5 t2)))
15997 (when inc
15998 (if have-time (setq h (+ 2 h)) (setq d (1+ d))))
15999 (setq time (encode-time s mi h d m y)))
16000 (setq fmt (if have-time ":%Y%m%dT%H%M%S" ";VALUE=DATE:%Y%m%d"))
16001 (concat keyword (format-time-string fmt time))))
16002
16003 ;;; LaTeX stuff
16004
16005 (defvar org-cdlatex-mode-map (make-sparse-keymap)
16006 "Keymap for the minor `org-cdlatex-mode'.")
16007
16008 (define-key org-cdlatex-mode-map "_" 'org-cdlatex-underscore-caret)
16009 (define-key org-cdlatex-mode-map "^" 'org-cdlatex-underscore-caret)
16010 (define-key org-cdlatex-mode-map "`" 'cdlatex-math-symbol)
16011 (define-key org-cdlatex-mode-map "'" 'org-cdlatex-math-modify)
16012 (define-key org-cdlatex-mode-map "\C-c{" 'cdlatex-environment)
16013
16014 (defvar org-cdlatex-texmathp-advice-is-done nil
16015 "Flag remembering if we have applied the advice to texmathp already.")
16016
16017 (define-minor-mode org-cdlatex-mode
16018 "Toggle the minor `org-cdlatex-mode'.
16019 This mode supports entering LaTeX environment and math in LaTeX fragments
16020 in Org-mode.
16021 \\{org-cdlatex-mode-map}"
16022 nil " OCDL" nil
16023 (when org-cdlatex-mode (require 'cdlatex))
16024 (unless org-cdlatex-texmathp-advice-is-done
16025 (setq org-cdlatex-texmathp-advice-is-done t)
16026 (defadvice texmathp (around org-math-always-on activate)
16027 "Always return t in org-mode buffers.
16028 This is because we want to insert math symbols without dollars even outside
16029 the LaTeX math segments. If Orgmode thinks that point is actually inside
16030 en embedded LaTeX fragement, let texmathp do its job.
16031 \\[org-cdlatex-mode-map]"
16032 (interactive)
16033 (let (p)
16034 (cond
16035 ((not (org-mode-p)) ad-do-it)
16036 ((eq this-command 'cdlatex-math-symbol)
16037 (setq ad-return-value t
16038 texmathp-why '("cdlatex-math-symbol in org-mode" . 0)))
16039 (t
16040 (let ((p (org-inside-LaTeX-fragment-p)))
16041 (if (and p (member (car p) (plist-get org-format-latex-options :matchers)))
16042 (setq ad-return-value t
16043 texmathp-why '("Org-mode embedded math" . 0))
16044 (if p ad-do-it)))))))))
16045
16046 (defun turn-on-org-cdlatex ()
16047 "Unconditionally turn on `org-cdlatex-mode'."
16048 (org-cdlatex-mode 1))
16049
16050 (defun org-inside-LaTeX-fragment-p ()
16051 "Test if point is inside a LaTeX fragment.
16052 I.e. after a \\begin, \\(, \\[, $, or $$, without the corresponding closing
16053 sequence appearing also before point.
16054 Even though the matchers for math are configurable, this function assumes
16055 that \\begin, \\(, \\[, and $$ are always used. Only the single dollar
16056 delimiters are skipped when they have been removed by customization.
16057 The return value is nil, or a cons cell with the delimiter and
16058 and the position of this delimiter.
16059
16060 This function does a reasonably good job, but can locally be fooled by
16061 for example currency specifications. For example it will assume being in
16062 inline math after \"$22.34\". The LaTeX fragment formatter will only format
16063 fragments that are properly closed, but during editing, we have to live
16064 with the uncertainty caused by missing closing delimiters. This function
16065 looks only before point, not after."
16066 (catch 'exit
16067 (let ((pos (point))
16068 (dodollar (member "$" (plist-get org-format-latex-options :matchers)))
16069 (lim (progn
16070 (re-search-backward (concat "^\\(" paragraph-start "\\)") nil t)
16071 (point)))
16072 dd-on str (start 0) m re)
16073 (goto-char pos)
16074 (when dodollar
16075 (setq str (concat (buffer-substring lim (point)) "\000 X$.")
16076 re (nth 1 (assoc "$" org-latex-regexps)))
16077 (while (string-match re str start)
16078 (cond
16079 ((= (match-end 0) (length str))
16080 (throw 'exit (cons "$" (+ lim (match-beginning 0)))))
16081 ((= (match-end 0) (- (length str) 5))
16082 (throw 'exit nil))
16083 (t (setq start (match-end 0))))))
16084 (when (setq m (re-search-backward "\\(\\\\begin{[^}]*}\\|\\\\(\\|\\\\\\[\\)\\|\\(\\\\end{[^}]*}\\|\\\\)\\|\\\\\\]\\)\\|\\(\\$\\$\\)" lim t))
16085 (goto-char pos)
16086 (and (match-beginning 1) (throw 'exit (cons (match-string 1) m)))
16087 (and (match-beginning 2) (throw 'exit nil))
16088 ;; count $$
16089 (while (re-search-backward "\\$\\$" lim t)
16090 (setq dd-on (not dd-on)))
16091 (goto-char pos)
16092 (if dd-on (cons "$$" m))))))
16093
16094
16095 (defun org-try-cdlatex-tab ()
16096 "Check if it makes sense to execute `cdlatex-tab', and do it if yes.
16097 It makes sense to do so if `org-cdlatex-mode' is active and if the cursor is
16098 - inside a LaTeX fragment, or
16099 - after the first word in a line, where an abbreviation expansion could
16100 insert a LaTeX environment."
16101 (when org-cdlatex-mode
16102 (cond
16103 ((save-excursion
16104 (skip-chars-backward "a-zA-Z0-9*")
16105 (skip-chars-backward " \t")
16106 (bolp))
16107 (cdlatex-tab) t)
16108 ((org-inside-LaTeX-fragment-p)
16109 (cdlatex-tab) t)
16110 (t nil))))
16111
16112 (defun org-cdlatex-underscore-caret (&optional arg)
16113 "Execute `cdlatex-sub-superscript' in LaTeX fragments.
16114 Revert to the normal definition outside of these fragments."
16115 (interactive "P")
16116 (if (org-inside-LaTeX-fragment-p)
16117 (call-interactively 'cdlatex-sub-superscript)
16118 (let (org-cdlatex-mode)
16119 (call-interactively (key-binding (vector last-input-event))))))
16120
16121 (defun org-cdlatex-math-modify (&optional arg)
16122 "Execute `cdlatex-math-modify' in LaTeX fragments.
16123 Revert to the normal definition outside of these fragments."
16124 (interactive "P")
16125 (if (org-inside-LaTeX-fragment-p)
16126 (call-interactively 'cdlatex-math-modify)
16127 (let (org-cdlatex-mode)
16128 (call-interactively (key-binding (vector last-input-event))))))
16129
16130 (defvar org-latex-fragment-image-overlays nil
16131 "List of overlays carrying the images of latex fragments.")
16132 (make-variable-buffer-local 'org-latex-fragment-image-overlays)
16133
16134 (defun org-remove-latex-fragment-image-overlays ()
16135 "Remove all overlays with LaTeX fragment images in current buffer."
16136 (mapc 'org-delete-overlay org-latex-fragment-image-overlays)
16137 (setq org-latex-fragment-image-overlays nil))
16138
16139 (defun org-preview-latex-fragment (&optional subtree)
16140 "Preview the LaTeX fragment at point, or all locally or globally.
16141 If the cursor is in a LaTeX fragment, create the image and overlay
16142 it over the source code. If there is no fragment at point, display
16143 all fragments in the current text, from one headline to the next. With
16144 prefix SUBTREE, display all fragments in the current subtree. With a
16145 double prefix `C-u C-u', or when the cursor is before the first headline,
16146 display all fragments in the buffer.
16147 The images can be removed again with \\[org-ctrl-c-ctrl-c]."
16148 (interactive "P")
16149 (org-remove-latex-fragment-image-overlays)
16150 (save-excursion
16151 (save-restriction
16152 (let (beg end at msg)
16153 (cond
16154 ((or (equal subtree '(16))
16155 (not (save-excursion
16156 (re-search-backward (concat "^" outline-regexp) nil t))))
16157 (setq beg (point-min) end (point-max)
16158 msg "Creating images for buffer...%s"))
16159 ((equal subtree '(4))
16160 (org-back-to-heading)
16161 (setq beg (point) end (org-end-of-subtree t)
16162 msg "Creating images for subtree...%s"))
16163 (t
16164 (if (setq at (org-inside-LaTeX-fragment-p))
16165 (goto-char (max (point-min) (- (cdr at) 2)))
16166 (org-back-to-heading))
16167 (setq beg (point) end (progn (outline-next-heading) (point))
16168 msg (if at "Creating image...%s"
16169 "Creating images for entry...%s"))))
16170 (message msg "")
16171 (narrow-to-region beg end)
16172 (org-format-latex
16173 (concat "ltxpng/" (file-name-sans-extension
16174 (file-name-nondirectory
16175 buffer-file-name)))
16176 default-directory 'overlays msg at)
16177 (message msg "done. Use `C-c C-c' to remove images.")))))
16178
16179 (defvar org-latex-regexps
16180 '(("begin" "^[ \t]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^\000]+?\\\\end{\\2}\\)" 1 t)
16181 ;; ("$" "\\([ (]\\|^\\)\\(\\(\\([$]\\)\\([^ \r\n,.$].*?\\(\n.*?\\)\\{0,5\\}[^ \r\n,.$]\\)\\4\\)\\)\\([ .,?;:'\")]\\|$\\)" 2 nil)
16182 ;; \000 in the following regex is needed for org-inside-LaTeX-fragment-p
16183 ("$" "\\([^$]\\)\\(\\(\\$\\([^ \r\n,;.$][^$\n\r]*?\\(\n[^$\n\r]*?\\)\\{0,2\\}[^ \r\n,.$]\\)\\$\\)\\)\\([ .,?;:'\")\000]\\|$\\)" 2 nil)
16184 ("\\(" "\\\\([^\000]*?\\\\)" 0 nil)
16185 ("\\[" "\\\\\\[[^\000]*?\\\\\\]" 0 t)
16186 ("$$" "\\$\\$[^\000]*?\\$\\$" 0 t))
16187 "Regular expressions for matching embedded LaTeX.")
16188
16189 (defun org-format-latex (prefix &optional dir overlays msg at)
16190 "Replace LaTeX fragments with links to an image, and produce images."
16191 (if (and overlays (fboundp 'clear-image-cache)) (clear-image-cache))
16192 (let* ((prefixnodir (file-name-nondirectory prefix))
16193 (absprefix (expand-file-name prefix dir))
16194 (todir (file-name-directory absprefix))
16195 (opt org-format-latex-options)
16196 (matchers (plist-get opt :matchers))
16197 (re-list org-latex-regexps)
16198 (cnt 0) txt link beg end re e oldfiles
16199 m n block linkfile movefile ov)
16200 ;; Make sure the directory exists
16201 (or (file-directory-p todir) (make-directory todir))
16202 ;; Check if there are old images files with this prefix, and remove them
16203 (setq oldfiles (directory-files
16204 todir 'full
16205 (concat (regexp-quote prefixnodir) "_[0-9]+\\.png$")))
16206 (while oldfiles (delete-file (pop oldfiles)))
16207 ;; Check the different regular expressions
16208 (while (setq e (pop re-list))
16209 (setq m (car e) re (nth 1 e) n (nth 2 e)
16210 block (if (nth 3 e) "\n\n" ""))
16211 (when (member m matchers)
16212 (goto-char (point-min))
16213 (while (re-search-forward re nil t)
16214 (when (or (not at) (equal (cdr at) (match-beginning n)))
16215 (setq txt (match-string n)
16216 beg (match-beginning n) end (match-end n)
16217 cnt (1+ cnt)
16218 linkfile (format "%s_%04d.png" prefix cnt)
16219 movefile (format "%s_%04d.png" absprefix cnt)
16220 link (concat block "[[file:" linkfile "]]" block))
16221 (if msg (message msg cnt))
16222 (goto-char beg)
16223 (org-create-formula-image
16224 txt movefile opt)
16225 (if overlays
16226 (progn
16227 (setq ov (org-make-overlay beg end))
16228 (if (featurep 'xemacs)
16229 (progn
16230 (org-overlay-put ov 'invisible t)
16231 (org-overlay-put
16232 ov 'end-glyph
16233 (make-glyph (vector 'png :file movefile))))
16234 (org-overlay-put
16235 ov 'display
16236 (list 'image :type 'png :file movefile :ascent 'center)))
16237 (push ov org-latex-fragment-image-overlays)
16238 (goto-char end))
16239 (delete-region beg end)
16240 (insert link))))))))
16241
16242 ;; This function borrows from Ganesh Swami's latex2png.el
16243 (defun org-create-formula-image (string tofile options)
16244 (let* ((tmpdir (if (featurep 'xemacs)
16245 (temp-directory)
16246 temporary-file-directory))
16247 (texfilebase (make-temp-name
16248 (expand-file-name "orgtex" tmpdir)))
16249
16250 ;(texfilebase (make-temp-file "orgtex"))
16251 ; (dummy (delete-file texfilebase))
16252 (texfile (concat texfilebase ".tex"))
16253 (dvifile (concat texfilebase ".dvi"))
16254 (pngfile (concat texfilebase ".png"))
16255 (scale (number-to-string (* 1000 (or (plist-get options :scale) 1.0))))
16256 (fg (or (plist-get options :foreground) "Black"))
16257 (bg (or (plist-get options :background) "Transparent")))
16258 (with-temp-file texfile
16259 (insert "\\documentclass{article}
16260 \\usepackage{fullpage}
16261 \\usepackage{amssymb}
16262 \\usepackage[usenames]{color}
16263 \\usepackage{amsmath}
16264 \\usepackage{latexsym}
16265 \\usepackage[mathscr]{eucal}
16266 \\pagestyle{empty}
16267 \\begin{document}\n" string "\n\\end{document}\n"))
16268 (let ((dir default-directory))
16269 (condition-case nil
16270 (progn
16271 (cd tmpdir)
16272 (call-process "latex" nil nil nil texfile))
16273 (error nil))
16274 (cd dir))
16275 (if (not (file-exists-p dvifile))
16276 (progn (message "Failed to create dvi file from %s" texfile) nil)
16277 (call-process "dvipng" nil nil nil
16278 "-E" "-fg" fg "-bg" bg
16279 "-x" scale "-y" scale "-T" "tight"
16280 "-o" pngfile
16281 dvifile)
16282 (if (not (file-exists-p pngfile))
16283 (progn (message "Failed to create png file from %s" texfile) nil)
16284 ;; Use the requested file name and clean up
16285 (copy-file pngfile tofile 'replace)
16286 (loop for e in '(".dvi" ".tex" ".aux" ".log" ".png") do
16287 (delete-file (concat texfilebase e)))
16288 pngfile))))
16289
16290 ;;; Key bindings
16291
16292 ;; - Bindings in Org-mode map are currently
16293 ;; 0123456789abcdefghijklmnopqrstuvwxyz!?@#$%^&-+*/=()_{}[]:;"|,.<>~`'\t the alphabet
16294 ;; abcd fgh j lmnopqrstuvwxyz!? #$ ^ -+*/= [] ; |,.<>~ '\t necessary bindings
16295 ;; e (?) useful from outline-mode
16296 ;; i k @ expendable from outline-mode
16297 ;; 0123456789 % & ()_{} " ` free
16298
16299 ;; Make `C-c C-x' a prefix key
16300 (define-key org-mode-map "\C-c\C-x" (make-sparse-keymap))
16301
16302 ;; TAB key with modifiers
16303 (define-key org-mode-map "\C-i" 'org-cycle)
16304 (define-key org-mode-map [(tab)] 'org-cycle)
16305 (define-key org-mode-map [(control tab)] 'org-force-cycle-archived)
16306 (define-key org-mode-map [(meta tab)] 'org-complete)
16307 ;; The following line is necessary under Suse GNU/Linux
16308 (unless (featurep 'xemacs)
16309 (define-key org-mode-map [S-iso-lefttab] 'org-shifttab))
16310 (define-key org-mode-map [(shift tab)] 'org-shifttab)
16311
16312 (define-key org-mode-map (org-key 'S-return) 'org-table-copy-down)
16313 (define-key org-mode-map [(meta shift return)] 'org-insert-todo-heading)
16314 (define-key org-mode-map [(meta return)] 'org-meta-return)
16315
16316 ;; Cursor keys with modifiers
16317 (define-key org-mode-map [(meta left)] 'org-metaleft)
16318 (define-key org-mode-map [(meta right)] 'org-metaright)
16319 (define-key org-mode-map [(meta up)] 'org-metaup)
16320 (define-key org-mode-map [(meta down)] 'org-metadown)
16321
16322 (define-key org-mode-map [(meta shift left)] 'org-shiftmetaleft)
16323 (define-key org-mode-map [(meta shift right)] 'org-shiftmetaright)
16324 (define-key org-mode-map [(meta shift up)] 'org-shiftmetaup)
16325 (define-key org-mode-map [(meta shift down)] 'org-shiftmetadown)
16326
16327 (define-key org-mode-map (org-key 'S-up) 'org-shiftup)
16328 (define-key org-mode-map (org-key 'S-down) 'org-shiftdown)
16329 (define-key org-mode-map (org-key 'S-left) 'org-shiftleft)
16330 (define-key org-mode-map (org-key 'S-right) 'org-shiftright)
16331
16332 ;; Extra keys for tty access. We only set them when really needed
16333 ;; because otherwise the menus don't show the simple keys
16334
16335 (when (or (featurep 'xemacs) ;; because XEmacs supports multi-device stuff
16336 (not window-system))
16337 (define-key org-mode-map "\M-\C-i" 'org-complete)
16338 (define-key org-mode-map "\C-c\C-xc" 'org-table-copy-down)
16339 (define-key org-mode-map "\C-c\C-xM" 'org-insert-todo-heading)
16340 (define-key org-mode-map "\C-c\C-xm" 'org-meta-return)
16341 (define-key org-mode-map [?\e (return)] 'org-meta-return)
16342 (define-key org-mode-map [?\e (left)] 'org-metaleft)
16343 (define-key org-mode-map "\C-c\C-xl" 'org-metaleft)
16344 (define-key org-mode-map [?\e (right)] 'org-metaright)
16345 (define-key org-mode-map "\C-c\C-xr" 'org-metaright)
16346 (define-key org-mode-map [?\e (up)] 'org-metaup)
16347 (define-key org-mode-map "\C-c\C-xu" 'org-metaup)
16348 (define-key org-mode-map [?\e (down)] 'org-metadown)
16349 (define-key org-mode-map "\C-c\C-xd" 'org-metadown)
16350 (define-key org-mode-map "\C-c\C-xL" 'org-shiftmetaleft)
16351 (define-key org-mode-map "\C-c\C-xR" 'org-shiftmetaright)
16352 (define-key org-mode-map "\C-c\C-xU" 'org-shiftmetaup)
16353 (define-key org-mode-map "\C-c\C-xD" 'org-shiftmetadown)
16354 (define-key org-mode-map [?\C-c ?\C-x (up)] 'org-shiftup)
16355 (define-key org-mode-map [?\C-c ?\C-x (down)] 'org-shiftdown)
16356 (define-key org-mode-map [?\C-c ?\C-x (left)] 'org-shiftleft)
16357 (define-key org-mode-map [?\C-c ?\C-x (right)] 'org-shiftright))
16358
16359 ;; All the other keys
16360
16361 (define-key org-mode-map "\C-c\C-a" 'show-all) ; in case allout messed up.
16362 (define-key org-mode-map "\C-c\C-r" 'org-reveal)
16363 (define-key org-mode-map "\C-xns" 'org-narrow-to-subtree)
16364 (define-key org-mode-map "\C-c$" 'org-archive-subtree)
16365 (define-key org-mode-map "\C-c\C-x\C-a" 'org-toggle-archive-tag)
16366 (define-key org-mode-map "\C-c\C-j" 'org-goto)
16367 (define-key org-mode-map "\C-c\C-t" 'org-todo)
16368 (define-key org-mode-map "\C-c\C-s" 'org-schedule)
16369 (define-key org-mode-map "\C-c\C-d" 'org-deadline)
16370 (define-key org-mode-map "\C-c;" 'org-toggle-comment)
16371 (define-key org-mode-map "\C-c\C-v" 'org-show-todo-tree)
16372 (define-key org-mode-map "\C-c\C-w" 'org-check-deadlines)
16373 (define-key org-mode-map "\C-c/" 'org-occur) ; Minor-mode reserved
16374 (define-key org-mode-map "\C-c\\" 'org-tags-sparse-tree) ; Minor-mode res.
16375 (define-key org-mode-map "\C-c\C-m" 'org-insert-heading)
16376 (define-key org-mode-map "\M-\C-m" 'org-insert-heading)
16377 (define-key org-mode-map "\C-c\C-l" 'org-insert-link)
16378 (define-key org-mode-map "\C-c\C-o" 'org-open-at-point)
16379 (define-key org-mode-map "\C-c%" 'org-mark-ring-push)
16380 (define-key org-mode-map "\C-c&" 'org-mark-ring-goto)
16381 (define-key org-mode-map "\C-c\C-z" 'org-time-stamp) ; Alternative binding
16382 (define-key org-mode-map "\C-c." 'org-time-stamp) ; Minor-mode reserved
16383 (define-key org-mode-map "\C-c!" 'org-time-stamp-inactive) ; Minor-mode r.
16384 (define-key org-mode-map "\C-c," 'org-priority) ; Minor-mode reserved
16385 (define-key org-mode-map "\C-c\C-y" 'org-evaluate-time-range)
16386 (define-key org-mode-map "\C-c>" 'org-goto-calendar)
16387 (define-key org-mode-map "\C-c<" 'org-date-from-calendar)
16388 (define-key org-mode-map [(control ?,)] 'org-cycle-agenda-files)
16389 (define-key org-mode-map "\C-c[" 'org-agenda-file-to-front)
16390 (define-key org-mode-map "\C-c]" 'org-remove-file)
16391 (define-key org-mode-map "\C-c-" 'org-table-insert-hline)
16392 (define-key org-mode-map "\C-c^" 'org-table-sort-lines)
16393 (define-key org-mode-map "\C-c\C-c" 'org-ctrl-c-ctrl-c)
16394 (define-key org-mode-map "\C-c#" 'org-update-checkbox-count)
16395 (define-key org-mode-map "\C-m" 'org-return)
16396 (define-key org-mode-map "\C-c?" 'org-table-current-column)
16397 (define-key org-mode-map "\C-c " 'org-table-blank-field)
16398 (define-key org-mode-map "\C-c+" 'org-table-sum)
16399 (define-key org-mode-map "\C-c=" 'org-table-eval-formula)
16400 (define-key org-mode-map "\C-c'" 'org-table-edit-formulas)
16401 (define-key org-mode-map "\C-c`" 'org-table-edit-field)
16402 (define-key org-mode-map "\C-c|" 'org-table-create-or-convert-from-region)
16403 (define-key org-mode-map "\C-c*" 'org-table-recalculate)
16404 (define-key org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks)
16405 (define-key org-mode-map "\C-c~" 'org-table-create-with-table.el)
16406 (define-key org-mode-map "\C-c\C-q" 'org-table-wrap-region)
16407 (define-key org-mode-map "\C-c\C-e" 'org-export)
16408 (define-key org-mode-map "\C-c:" 'org-toggle-fixed-width-section)
16409
16410 (define-key org-mode-map "\C-c\C-x\C-k" 'org-cut-special)
16411 (define-key org-mode-map "\C-c\C-x\C-w" 'org-cut-special)
16412 (define-key org-mode-map "\C-c\C-x\M-w" 'org-copy-special)
16413 (define-key org-mode-map "\C-c\C-x\C-y" 'org-paste-special)
16414
16415 (define-key org-mode-map "\C-c\C-x\C-t" 'org-toggle-time-stamp-overlays)
16416 (define-key org-mode-map "\C-c\C-x\C-i" 'org-clock-in)
16417 (define-key org-mode-map "\C-c\C-x\C-o" 'org-clock-out)
16418 (define-key org-mode-map "\C-c\C-x\C-x" 'org-clock-cancel)
16419 (define-key org-mode-map "\C-c\C-x\C-d" 'org-clock-display)
16420 (define-key org-mode-map "\C-c\C-x\C-r" 'org-clock-report)
16421 (define-key org-mode-map "\C-c\C-x\C-u" 'org-dblock-update)
16422 (define-key org-mode-map "\C-c\C-x\C-l" 'org-preview-latex-fragment)
16423 (define-key org-mode-map "\C-c\C-x\C-b" 'org-toggle-checkbox)
16424
16425 (when (featurep 'xemacs)
16426 (define-key org-mode-map 'button3 'popup-mode-menu))
16427
16428 (defsubst org-table-p () (org-at-table-p))
16429
16430 (defun org-self-insert-command (N)
16431 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
16432 If the cursor is in a table looking at whitespace, the whitespace is
16433 overwritten, and the table is not marked as requiring realignment."
16434 (interactive "p")
16435 (if (and (org-table-p)
16436 (progn
16437 ;; check if we blank the field, and if that triggers align
16438 (and org-table-auto-blank-field
16439 (member last-command
16440 '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c))
16441 (if (or (equal (char-after) ?\ ) (looking-at "[^|\n]* |"))
16442 ;; got extra space, this field does not determine column width
16443 (let (org-table-may-need-update) (org-table-blank-field))
16444 ;; no extra space, this field may determine column width
16445 (org-table-blank-field)))
16446 t)
16447 (eq N 1)
16448 (looking-at "[^|\n]* |"))
16449 (let (org-table-may-need-update)
16450 (goto-char (1- (match-end 0)))
16451 (delete-backward-char 1)
16452 (goto-char (match-beginning 0))
16453 (self-insert-command N))
16454 (setq org-table-may-need-update t)
16455 (self-insert-command N)))
16456
16457 (defun org-delete-backward-char (N)
16458 "Like `delete-backward-char', insert whitespace at field end in tables.
16459 When deleting backwards, in tables this function will insert whitespace in
16460 front of the next \"|\" separator, to keep the table aligned. The table will
16461 still be marked for re-alignment if the field did fill the entire column,
16462 because, in this case the deletion might narrow the column."
16463 (interactive "p")
16464 (if (and (org-table-p)
16465 (eq N 1)
16466 (string-match "|" (buffer-substring (point-at-bol) (point)))
16467 (looking-at ".*?|"))
16468 (let ((pos (point))
16469 (noalign (looking-at "[^|\n\r]* |"))
16470 (c org-table-may-need-update))
16471 (backward-delete-char N)
16472 (skip-chars-forward "^|")
16473 (insert " ")
16474 (goto-char (1- pos))
16475 ;; noalign: if there were two spaces at the end, this field
16476 ;; does not determine the width of the column.
16477 (if noalign (setq org-table-may-need-update c)))
16478 (backward-delete-char N)))
16479
16480 (defun org-delete-char (N)
16481 "Like `delete-char', but insert whitespace at field end in tables.
16482 When deleting characters, in tables this function will insert whitespace in
16483 front of the next \"|\" separator, to keep the table aligned. The table will
16484 still be marked for re-alignment if the field did fill the entire column,
16485 because, in this case the deletion might narrow the column."
16486 (interactive "p")
16487 (if (and (org-table-p)
16488 (not (bolp))
16489 (not (= (char-after) ?|))
16490 (eq N 1))
16491 (if (looking-at ".*?|")
16492 (let ((pos (point))
16493 (noalign (looking-at "[^|\n\r]* |"))
16494 (c org-table-may-need-update))
16495 (replace-match (concat
16496 (substring (match-string 0) 1 -1)
16497 " |"))
16498 (goto-char pos)
16499 ;; noalign: if there were two spaces at the end, this field
16500 ;; does not determine the width of the column.
16501 (if noalign (setq org-table-may-need-update c)))
16502 (delete-char N))
16503 (delete-char N)))
16504
16505 ;; Make `delete-selection-mode' work with org-mode and orgtbl-mode
16506 (put 'org-self-insert-command 'delete-selection t)
16507 (put 'orgtbl-self-insert-command 'delete-selection t)
16508 (put 'org-delete-char 'delete-selection 'supersede)
16509 (put 'org-delete-backward-char 'delete-selection 'supersede)
16510
16511 ;; How to do this: Measure non-white length of current string
16512 ;; If equal to column width, we should realign.
16513
16514 (defun org-remap (map &rest commands)
16515 "In MAP, remap the functions given in COMMANDS.
16516 COMMANDS is a list of alternating OLDDEF NEWDEF command names."
16517 (let (new old)
16518 (while commands
16519 (setq old (pop commands) new (pop commands))
16520 (if (fboundp 'command-remapping)
16521 (define-key map (vector 'remap old) new)
16522 (substitute-key-definition old new map global-map)))))
16523
16524 (when (eq org-enable-table-editor 'optimized)
16525 ;; If the user wants maximum table support, we need to hijack
16526 ;; some standard editing functions
16527 (org-remap org-mode-map
16528 'self-insert-command 'org-self-insert-command
16529 'delete-char 'org-delete-char
16530 'delete-backward-char 'org-delete-backward-char)
16531 (define-key org-mode-map "|" 'org-force-self-insert))
16532
16533 (defun org-shiftcursor-error ()
16534 "Throw an error because Shift-Cursor command was applied in wrong context."
16535 (error "This command is active in special context like tables, headlines or timestamps"))
16536
16537 (defun org-shifttab (&optional arg)
16538 "Global visibility cycling or move to previous table field.
16539 Calls `org-cycle' with argument t, or `org-table-previous-field', depending
16540 on context.
16541 See the individual commands for more information."
16542 (interactive "P")
16543 (cond
16544 ((org-at-table-p) (call-interactively 'org-table-previous-field))
16545 (t (call-interactively 'org-global-cycle))))
16546
16547 (defun org-shiftmetaleft ()
16548 "Promote subtree or delete table column.
16549 Calls `org-promote-subtree' or `org-table-delete-column', depending on context.
16550 See the individual commands for more information."
16551 (interactive)
16552 (cond
16553 ((org-at-table-p) (call-interactively 'org-table-delete-column))
16554 ((org-on-heading-p) (call-interactively 'org-promote-subtree))
16555 ((org-at-item-p) (call-interactively 'org-outdent-item))
16556 (t (org-shiftcursor-error))))
16557
16558 (defun org-shiftmetaright ()
16559 "Demote subtree or insert table column.
16560 Calls `org-demote-subtree' or `org-table-insert-column', depending on context.
16561 See the individual commands for more information."
16562 (interactive)
16563 (cond
16564 ((org-at-table-p) (call-interactively 'org-table-insert-column))
16565 ((org-on-heading-p) (call-interactively 'org-demote-subtree))
16566 ((org-at-item-p) (call-interactively 'org-indent-item))
16567 (t (org-shiftcursor-error))))
16568
16569 (defun org-shiftmetaup (&optional arg)
16570 "Move subtree up or kill table row.
16571 Calls `org-move-subtree-up' or `org-table-kill-row' or
16572 `org-move-item-up' depending on context. See the individual commands
16573 for more information."
16574 (interactive "P")
16575 (cond
16576 ((org-at-table-p) (call-interactively 'org-table-kill-row))
16577 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
16578 ((org-at-item-p) (call-interactively 'org-move-item-up))
16579 (t (org-shiftcursor-error))))
16580 (defun org-shiftmetadown (&optional arg)
16581 "Move subtree down or insert table row.
16582 Calls `org-move-subtree-down' or `org-table-insert-row' or
16583 `org-move-item-down', depending on context. See the individual
16584 commands for more information."
16585 (interactive "P")
16586 (cond
16587 ((org-at-table-p) (call-interactively 'org-table-insert-row))
16588 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
16589 ((org-at-item-p) (call-interactively 'org-move-item-down))
16590 (t (org-shiftcursor-error))))
16591
16592 (defun org-metaleft (&optional arg)
16593 "Promote heading or move table column to left.
16594 Calls `org-do-promote' or `org-table-move-column', depending on context.
16595 With no specific context, calls the Emacs default `backward-word'.
16596 See the individual commands for more information."
16597 (interactive "P")
16598 (cond
16599 ((org-at-table-p) (org-call-with-arg 'org-table-move-column 'left))
16600 ((or (org-on-heading-p) (org-region-active-p))
16601 (call-interactively 'org-do-promote))
16602 (t (call-interactively 'backward-word))))
16603
16604 (defun org-metaright (&optional arg)
16605 "Demote subtree or move table column to right.
16606 Calls `org-do-demote' or `org-table-move-column', depending on context.
16607 With no specific context, calls the Emacs default `forward-word'.
16608 See the individual commands for more information."
16609 (interactive "P")
16610 (cond
16611 ((org-at-table-p) (call-interactively 'org-table-move-column))
16612 ((or (org-on-heading-p) (org-region-active-p))
16613 (call-interactively 'org-do-demote))
16614 (t (call-interactively 'forward-word))))
16615
16616 (defun org-metaup (&optional arg)
16617 "Move subtree up or move table row up.
16618 Calls `org-move-subtree-up' or `org-table-move-row' or
16619 `org-move-item-up', depending on context. See the individual commands
16620 for more information."
16621 (interactive "P")
16622 (cond
16623 ((org-at-table-p) (org-call-with-arg 'org-table-move-row 'up))
16624 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
16625 ((org-at-item-p) (call-interactively 'org-move-item-up))
16626 (t (org-shiftcursor-error))))
16627
16628 (defun org-metadown (&optional arg)
16629 "Move subtree down or move table row down.
16630 Calls `org-move-subtree-down' or `org-table-move-row' or
16631 `org-move-item-down', depending on context. See the individual
16632 commands for more information."
16633 (interactive "P")
16634 (cond
16635 ((org-at-table-p) (call-interactively 'org-table-move-row))
16636 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
16637 ((org-at-item-p) (call-interactively 'org-move-item-down))
16638 (t (org-shiftcursor-error))))
16639
16640 (defun org-shiftup (&optional arg)
16641 "Increase item in timestamp or increase priority of current headline.
16642 Calls `org-timestamp-up' or `org-priority-up', depending on context.
16643 See the individual commands for more information."
16644 (interactive "P")
16645 (cond
16646 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-up))
16647 ((org-on-heading-p) (call-interactively 'org-priority-up))
16648 ((org-at-item-p) (call-interactively 'org-previous-item))
16649 (t (call-interactively 'org-beginning-of-item) (beginning-of-line 1))))
16650
16651 (defun org-shiftdown (&optional arg)
16652 "Decrease item in timestamp or decrease priority of current headline.
16653 Calls `org-timestamp-down' or `org-priority-down', depending on context.
16654 See the individual commands for more information."
16655 (interactive "P")
16656 (cond
16657 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-down))
16658 ((org-on-heading-p) (call-interactively 'org-priority-down))
16659 (t (call-interactively 'org-next-item))))
16660
16661 (defun org-shiftright ()
16662 "Next TODO keyword or timestamp one day later, depending on context."
16663 (interactive)
16664 (cond
16665 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-up-day))
16666 ((org-on-heading-p) (org-call-with-arg 'org-todo 'right))
16667 (t (org-shiftcursor-error))))
16668
16669 (defun org-shiftleft ()
16670 "Previous TODO keyword or timestamp one day earlier, depending on context."
16671 (interactive)
16672 (cond
16673 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-down-day))
16674 ((org-on-heading-p) (org-call-with-arg 'org-todo 'left))
16675 (t (org-shiftcursor-error))))
16676
16677 (defun org-copy-special ()
16678 "Copy region in table or copy current subtree.
16679 Calls `org-table-copy' or `org-copy-subtree', depending on context.
16680 See the individual commands for more information."
16681 (interactive)
16682 (call-interactively
16683 (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree)))
16684
16685 (defun org-cut-special ()
16686 "Cut region in table or cut current subtree.
16687 Calls `org-table-copy' or `org-cut-subtree', depending on context.
16688 See the individual commands for more information."
16689 (interactive)
16690 (call-interactively
16691 (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree)))
16692
16693 (defun org-paste-special (arg)
16694 "Paste rectangular region into table, or past subtree relative to level.
16695 Calls `org-table-paste-rectangle' or `org-paste-subtree', depending on context.
16696 See the individual commands for more information."
16697 (interactive "P")
16698 (if (org-at-table-p)
16699 (org-table-paste-rectangle)
16700 (org-paste-subtree arg)))
16701
16702 (defun org-ctrl-c-ctrl-c (&optional arg)
16703 "Set tags in headline, or update according to changed information at point.
16704
16705 This command does many different things, depending on context:
16706
16707 - If the cursor is in a headline, prompt for tags and insert them
16708 into the current line, aligned to `org-tags-column'. When called
16709 with prefix arg, realign all tags in the current buffer.
16710
16711 - If the cursor is in one of the special #+KEYWORD lines, this
16712 triggers scanning the buffer for these lines and updating the
16713 information.
16714
16715 - If the cursor is inside a table, realign the table. This command
16716 works even if the automatic table editor has been turned off.
16717
16718 - If the cursor is on a #+TBLFM line, re-apply the formulas to
16719 the entire table.
16720
16721 - If the cursor is inside a table created by the table.el package,
16722 activate that table.
16723
16724 - If the current buffer is a remember buffer, close note and file it.
16725 with a prefix argument, file it without further interaction to the default
16726 location.
16727
16728 - If the cursor is on a <<<target>>>, update radio targets and corresponding
16729 links in this buffer.
16730
16731 - If the cursor is on a numbered item in a plain list, renumber the
16732 ordered list."
16733 (interactive "P")
16734 (let ((org-enable-table-editor t))
16735 (cond
16736 ((or org-clock-overlays
16737 org-occur-highlights
16738 org-latex-fragment-image-overlays)
16739 (org-remove-clock-overlays)
16740 (org-remove-occur-highlights)
16741 (org-remove-latex-fragment-image-overlays)
16742 (message "Temporary highlights/overlays removed from current buffer"))
16743 ((and (local-variable-p 'org-finish-function (current-buffer))
16744 (fboundp org-finish-function))
16745 (funcall org-finish-function))
16746 ((org-on-target-p) (call-interactively 'org-update-radio-target-regexp))
16747 ((org-on-heading-p) (call-interactively 'org-set-tags))
16748 ((org-at-table.el-p)
16749 (require 'table)
16750 (beginning-of-line 1)
16751 (re-search-forward "|" (save-excursion (end-of-line 2) (point)))
16752 (call-interactively 'table-recognize-table))
16753 ((org-at-table-p)
16754 (org-table-maybe-eval-formula)
16755 (if arg
16756 (call-interactively 'org-table-recalculate)
16757 (org-table-maybe-recalculate-line))
16758 (call-interactively 'org-table-align))
16759 ((org-at-item-checkbox-p)
16760 (call-interactively 'org-toggle-checkbox))
16761 ((org-at-item-p)
16762 (call-interactively 'org-renumber-ordered-list))
16763 ((save-excursion (beginning-of-line 1) (looking-at "#\\+\\([A-Z]+\\)"))
16764 (cond
16765 ((equal (match-string 1) "TBLFM")
16766 ;; Recalculate the table before this line
16767 (save-excursion
16768 (beginning-of-line 1)
16769 (skip-chars-backward " \r\n\t")
16770 (if (org-at-table-p)
16771 (org-call-with-arg 'org-table-recalculate t))))
16772 (t
16773 (call-interactively 'org-mode-restart))))
16774 (t (error "C-c C-c can do nothing useful at this location.")))))
16775
16776 (defun org-mode-restart ()
16777 "Restart Org-mode, to scan again for special lines.
16778 Also updates the keyword regular expressions."
16779 (interactive)
16780 (let ((org-inhibit-startup t)) (org-mode))
16781 (message "Org-mode restarted to refresh keyword and special line setup"))
16782
16783 (defun org-return ()
16784 "Goto next table row or insert a newline.
16785 Calls `org-table-next-row' or `newline', depending on context.
16786 See the individual commands for more information."
16787 (interactive)
16788 (cond
16789 ((org-at-table-p)
16790 (org-table-justify-field-maybe)
16791 (call-interactively 'org-table-next-row))
16792 (t (newline))))
16793
16794 (defun org-meta-return (&optional arg)
16795 "Insert a new heading or wrap a region in a table.
16796 Calls `org-insert-heading' or `org-table-wrap-region', depending on context.
16797 See the individual commands for more information."
16798 (interactive "P")
16799 (cond
16800 ((org-at-table-p)
16801 (call-interactively 'org-table-wrap-region))
16802 (t (call-interactively 'org-insert-heading))))
16803
16804 ;;; Menu entries
16805
16806 ;; Define the Org-mode menus
16807 (easy-menu-define org-tbl-menu org-mode-map "Tbl menu"
16808 '("Tbl"
16809 ["Align" org-ctrl-c-ctrl-c (org-at-table-p)]
16810 ["Next Field" org-cycle (org-at-table-p)]
16811 ["Previous Field" org-shifttab (org-at-table-p)]
16812 ["Next Row" org-return (org-at-table-p)]
16813 "--"
16814 ["Blank Field" org-table-blank-field (org-at-table-p)]
16815 ["Edit Field" org-table-edit-field (org-at-table-p)]
16816 ["Copy Field from Above" org-table-copy-down (org-at-table-p)]
16817 "--"
16818 ("Column"
16819 ["Move Column Left" org-metaleft (org-at-table-p)]
16820 ["Move Column Right" org-metaright (org-at-table-p)]
16821 ["Delete Column" org-shiftmetaleft (org-at-table-p)]
16822 ["Insert Column" org-shiftmetaright (org-at-table-p)]
16823 "--"
16824 ["Enable Narrowing" (setq org-table-limit-column-width (not org-table-limit-column-width)) :active (org-at-table-p) :selected org-table-limit-column-width :style toggle])
16825 ("Row"
16826 ["Move Row Up" org-metaup (org-at-table-p)]
16827 ["Move Row Down" org-metadown (org-at-table-p)]
16828 ["Delete Row" org-shiftmetaup (org-at-table-p)]
16829 ["Insert Row" org-shiftmetadown (org-at-table-p)]
16830 ["Sort lines in region" org-table-sort-lines (org-at-table-p)]
16831 "--"
16832 ["Insert Hline" org-table-insert-hline (org-at-table-p)])
16833 ("Rectangle"
16834 ["Copy Rectangle" org-copy-special (org-at-table-p)]
16835 ["Cut Rectangle" org-cut-special (org-at-table-p)]
16836 ["Paste Rectangle" org-paste-special (org-at-table-p)]
16837 ["Fill Rectangle" org-table-wrap-region (org-at-table-p)])
16838 "--"
16839 ("Calculate"
16840 ["Set Column Formula" org-table-eval-formula (org-at-table-p)]
16841 ["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
16842 ["Edit Formulas" org-table-edit-formulas (org-at-table-p)]
16843 "--"
16844 ["Recalculate line" org-table-recalculate (org-at-table-p)]
16845 ["Recalculate all" (lambda () (interactive) (org-table-recalculate '(4))) :active (org-at-table-p) :keys "C-u C-c *"]
16846 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks (org-at-table-p)]
16847 "--"
16848 ["Sum Column/Rectangle" org-table-sum
16849 (or (org-at-table-p) (org-region-active-p))]
16850 ["Which Column?" org-table-current-column (org-at-table-p)])
16851 ["Debug Formulas"
16852 (setq org-table-formula-debug (not org-table-formula-debug))
16853 :style toggle :selected org-table-formula-debug]
16854 "--"
16855 ["Create" org-table-create (and (not (org-at-table-p))
16856 org-enable-table-editor)]
16857 ["Convert Region" org-table-convert-region (not (org-at-table-p 'any))]
16858 ["Import from File" org-table-import (not (org-at-table-p))]
16859 ["Export to File" org-table-export (org-at-table-p)]
16860 "--"
16861 ["Create/Convert from/to table.el" org-table-create-with-table.el t]))
16862
16863 (easy-menu-define org-org-menu org-mode-map "Org menu"
16864 '("Org"
16865 ("Show/Hide"
16866 ["Cycle Visibility" org-cycle (or (bobp) (outline-on-heading-p))]
16867 ["Cycle Global Visibility" org-shifttab (not (org-at-table-p))]
16868 ["Sparse Tree" org-occur t]
16869 ["Reveal Context" org-reveal t]
16870 ["Show All" show-all t])
16871 "--"
16872 ["New Heading" org-insert-heading t]
16873 ("Navigate Headings"
16874 ["Up" outline-up-heading t]
16875 ["Next" outline-next-visible-heading t]
16876 ["Previous" outline-previous-visible-heading t]
16877 ["Next Same Level" outline-forward-same-level t]
16878 ["Previous Same Level" outline-backward-same-level t]
16879 "--"
16880 ["Jump" org-goto t])
16881 ("Edit Structure"
16882 ["Move Subtree Up" org-shiftmetaup (not (org-at-table-p))]
16883 ["Move Subtree Down" org-shiftmetadown (not (org-at-table-p))]
16884 "--"
16885 ["Copy Subtree" org-copy-special (not (org-at-table-p))]
16886 ["Cut Subtree" org-cut-special (not (org-at-table-p))]
16887 ["Paste Subtree" org-paste-special (not (org-at-table-p))]
16888 "--"
16889 ["Promote Heading" org-metaleft (not (org-at-table-p))]
16890 ["Promote Subtree" org-shiftmetaleft (not (org-at-table-p))]
16891 ["Demote Heading" org-metaright (not (org-at-table-p))]
16892 ["Demote Subtree" org-shiftmetaright (not (org-at-table-p))]
16893 "--"
16894 ["Convert to odd levels" org-convert-to-odd-levels t]
16895 ["Convert to odd/even levels" org-convert-to-oddeven-levels t])
16896 ("Archive"
16897 ["Toggle ARCHIVE tag" org-toggle-archive-tag t]
16898 ["Check and Tag Children" (org-toggle-archive-tag (4))
16899 :active t :keys "C-u C-c C-x C-a"]
16900 ["Sparse trees open ARCHIVE trees"
16901 (setq org-sparse-tree-open-archived-trees
16902 (not org-sparse-tree-open-archived-trees))
16903 :style toggle :selected org-sparse-tree-open-archived-trees]
16904 ["Cycling opens ARCHIVE trees"
16905 (setq org-cycle-open-archived-trees (not org-cycle-open-archived-trees))
16906 :style toggle :selected org-cycle-open-archived-trees]
16907 ["Agenda includes ARCHIVE trees"
16908 (setq org-agenda-skip-archived-trees (not org-agenda-skip-archived-trees))
16909 :style toggle :selected (not org-agenda-skip-archived-trees)]
16910 "--"
16911 ["Move Subtree to Archive" org-archive-subtree t]
16912 ["Check and Move Children" (org-archive-subtree '(4))
16913 :active t :keys "C-u C-c $"])
16914 "--"
16915 ("TODO Lists"
16916 ["TODO/DONE/-" org-todo t]
16917 ("Select keyword"
16918 ["Next keyword" org-shiftright (org-on-heading-p)]
16919 ["Previous keyword" org-shiftleft (org-on-heading-p)]
16920 ["Complete Keyword" org-complete (assq :todo-keyword (org-context))])
16921 ["Show TODO Tree" org-show-todo-tree t]
16922 ["Global TODO list" org-todo-list t]
16923 "--"
16924 ["Set Priority" org-priority t]
16925 ["Priority Up" org-shiftup t]
16926 ["Priority Down" org-shiftdown t]
16927 "--"
16928 ; ["Insert Checkbox" org-insert-todo-heading (org-in-item-p)]
16929 ; ["Toggle Checkbox" org-ctrl-c-ctrl-c (org-at-item-checkbox-p)]
16930 ; ["Insert [n/m] cookie" (progn (insert "[/]") (org-update-checkbox-count))
16931 ; (or (org-on-heading-p) (org-at-item-p))]
16932 ; ["Insert [%] cookie" (progn (insert "[%]") (org-update-checkbox-count))
16933 ; (or (org-on-heading-p) (org-at-item-p))]
16934 ; ["Update Statistics" org-update-checkbox-count t]
16935 )
16936 ("Dates and Scheduling"
16937 ["Timestamp" org-time-stamp t]
16938 ["Timestamp (inactive)" org-time-stamp-inactive t]
16939 ("Change Date"
16940 ["1 Day Later" org-shiftright t]
16941 ["1 Day Earlier" org-shiftleft t]
16942 ["1 ... Later" org-shiftup t]
16943 ["1 ... Earlier" org-shiftdown t])
16944 ["Compute Time Range" org-evaluate-time-range t]
16945 ["Schedule Item" org-schedule t]
16946 ["Deadline" org-deadline t]
16947 "--"
16948 ["Custom time format" org-toggle-time-stamp-overlays
16949 :style radio :selected org-display-custom-times]
16950 "--"
16951 ["Goto Calendar" org-goto-calendar t]
16952 ["Date from Calendar" org-date-from-calendar t])
16953 ("Logging work"
16954 ["Clock in" org-clock-in t]
16955 ["Clock out" org-clock-out t]
16956 ["Clock cancel" org-clock-cancel t]
16957 ["Display times" org-clock-display t]
16958 ["Create clock table" org-clock-report t]
16959 "--"
16960 ["Record DONE time"
16961 (progn (setq org-log-done (not org-log-done))
16962 (message "Switching to %s will %s record a timestamp"
16963 org-done-string
16964 (if org-log-done "automatically" "not")))
16965 :style toggle :selected org-log-done])
16966 "--"
16967 ["Agenda Command..." org-agenda t]
16968 ("File List for Agenda")
16969 ("Special views current file"
16970 ["TODO Tree" org-show-todo-tree t]
16971 ["Check Deadlines" org-check-deadlines t]
16972 ["Timeline" org-timeline t]
16973 ["Tags Tree" org-tags-sparse-tree t])
16974 "--"
16975 ("Hyperlinks"
16976 ["Store Link (Global)" org-store-link t]
16977 ["Insert Link" org-insert-link t]
16978 ["Follow Link" org-open-at-point t]
16979 "--"
16980 ["Descriptive Links"
16981 (progn (org-add-to-invisibility-spec '(org-link)) (org-restart-font-lock))
16982 :style radio :selected (member '(org-link) buffer-invisibility-spec)]
16983 ["Literal Links"
16984 (progn
16985 (org-remove-from-invisibility-spec '(org-link)) (org-restart-font-lock))
16986 :style radio :selected (not (member '(org-link) buffer-invisibility-spec))]
16987 "--"
16988 ["Upgrade all <link> to [[link][desc]]" org-upgrade-old-links
16989 (save-excursion (goto-char (point-min))
16990 (re-search-forward "<[a-z]+:" nil t))])
16991 "--"
16992 ["Export/Publish..." org-export t]
16993 ("LaTeX"
16994 ["Org CDLaTeX mode" org-cdlatex-mode :style toggle
16995 :selected org-cdlatex-mode]
16996 ["Insert Environment" cdlatex-environment (fboundp 'cdlatex-environment)]
16997 ["Insert math symbol" cdlatex-math-symbol (fboundp 'cdlatex-math-symbol)]
16998 ["Modify math symbol" org-cdlatex-math-modify
16999 (org-inside-LaTeX-fragment-p)]
17000 ["Export LaTeX fragments as images"
17001 (setq org-export-with-LaTeX-fragments (not org-export-with-LaTeX-fragments))
17002 :style toggle :selected org-export-with-LaTeX-fragments])
17003 "--"
17004 ("Documentation"
17005 ["Show Version" org-version t]
17006 ["Info Documentation" org-info t])
17007 ("Customize"
17008 ["Browse Org Group" org-customize t]
17009 "--"
17010 ["Expand This Menu" org-create-customize-menu
17011 (fboundp 'customize-menu-create)])
17012 "--"
17013 ["Refresh setup" org-mode-restart t]
17014 ))
17015
17016 (defun org-info (&optional node)
17017 "Read documentation for Org-mode in the info system.
17018 With optional NODE, go directly to that node."
17019 (interactive)
17020 (require 'info)
17021 (Info-goto-node (format "(org)%s" (or node ""))))
17022
17023 (defun org-install-agenda-files-menu ()
17024 (let ((bl (buffer-list)))
17025 (save-excursion
17026 (while bl
17027 (set-buffer (pop bl))
17028 (if (org-mode-p) (setq bl nil)))
17029 (when (org-mode-p)
17030 (easy-menu-change
17031 '("Org") "File List for Agenda"
17032 (append
17033 (list
17034 ["Edit File List" (org-edit-agenda-file-list) t]
17035 ["Add/Move Current File to Front of List" org-agenda-file-to-front t]
17036 ["Remove Current File from List" org-remove-file t]
17037 ["Cycle through agenda files" org-cycle-agenda-files t]
17038 "--")
17039 (mapcar 'org-file-menu-entry (org-agenda-files t))))))))
17040
17041 ;;; Documentation
17042
17043 (defun org-customize ()
17044 "Call the customize function with org as argument."
17045 (interactive)
17046 (customize-browse 'org))
17047
17048 (defun org-create-customize-menu ()
17049 "Create a full customization menu for Org-mode, insert it into the menu."
17050 (interactive)
17051 (if (fboundp 'customize-menu-create)
17052 (progn
17053 (easy-menu-change
17054 '("Org") "Customize"
17055 `(["Browse Org group" org-customize t]
17056 "--"
17057 ,(customize-menu-create 'org)
17058 ["Set" Custom-set t]
17059 ["Save" Custom-save t]
17060 ["Reset to Current" Custom-reset-current t]
17061 ["Reset to Saved" Custom-reset-saved t]
17062 ["Reset to Standard Settings" Custom-reset-standard t]))
17063 (message "\"Org\"-menu now contains full customization menu"))
17064 (error "Cannot expand menu (outdated version of cus-edit.el)")))
17065
17066 ;;; Miscellaneous stuff
17067
17068 (defun org-context ()
17069 "Return a list of contexts of the current cursor position.
17070 If several contexts apply, all are returned.
17071 Each context entry is a list with a symbol naming the context, and
17072 two positions indicating start and end of the context. Possible
17073 contexts are:
17074
17075 :headline anywhere in a headline
17076 :headline-stars on the leading stars in a headline
17077 :todo-keyword on a TODO keyword (including DONE) in a headline
17078 :tags on the TAGS in a headline
17079 :priority on the priority cookie in a headline
17080 :item on the first line of a plain list item
17081 :item-bullet on the bullet/number of a plain list item
17082 :checkbox on the checkbox in a plain list item
17083 :table in an org-mode table
17084 :table-special on a special filed in a table
17085 :table-table in a table.el table
17086 :link on a hyperline
17087 :keyword on a keyword: SCHEDULED, DEADLINE, CLOSE,COMMENT, QUOTE.
17088 :target on a <<target>>
17089 :radio-target on a <<<radio-target>>>
17090 :latex-fragment on a LaTeX fragment
17091 :latex-preview on a LaTeX fragment with overlayed preview image
17092
17093 This function expects the position to be visible because it uses font-lock
17094 faces as a help to recognize the following contexts: :table-special, :link,
17095 and :keyword."
17096 (let* ((f (get-text-property (point) 'face))
17097 (faces (if (listp f) f (list f)))
17098 (p (point)) clist o)
17099 ;; First the large context
17100 (cond
17101 ((org-on-heading-p)
17102 (push (list :headline (point-at-bol) (point-at-eol)) clist)
17103 (when (progn
17104 (beginning-of-line 1)
17105 (looking-at org-todo-line-tags-regexp))
17106 (push (org-point-in-group p 1 :headline-stars) clist)
17107 (push (org-point-in-group p 2 :todo-keyword) clist)
17108 (push (org-point-in-group p 4 :tags) clist))
17109 (goto-char p)
17110 (skip-chars-backward "^[\n\r \t") (or (eobp) (backward-char 1))
17111 (if (looking-at "\\[#[A-Z]\\]")
17112 (push (org-point-in-group p 0 :priority) clist)))
17113
17114 ((org-at-item-p)
17115 (push (org-point-in-group p 2 :item-bullet) clist)
17116 (push (list :item (point-at-bol)
17117 (save-excursion (org-end-of-item) (point)))
17118 clist)
17119 (and (org-at-item-checkbox-p)
17120 (push (org-point-in-group p 0 :checkbox) clist)))
17121
17122 ((org-at-table-p)
17123 (push (list :table (org-table-begin) (org-table-end)) clist)
17124 (if (memq 'org-formula faces)
17125 (push (list :table-special
17126 (previous-single-property-change p 'face)
17127 (next-single-property-change p 'face)) clist)))
17128 ((org-at-table-p 'any)
17129 (push (list :table-table) clist)))
17130 (goto-char p)
17131
17132 ;; Now the small context
17133 (cond
17134 ((org-at-timestamp-p)
17135 (push (org-point-in-group p 0 :timestamp) clist))
17136 ((memq 'org-link faces)
17137 (push (list :link
17138 (previous-single-property-change p 'face)
17139 (next-single-property-change p 'face)) clist))
17140 ((memq 'org-special-keyword faces)
17141 (push (list :keyword
17142 (previous-single-property-change p 'face)
17143 (next-single-property-change p 'face)) clist))
17144 ((org-on-target-p)
17145 (push (org-point-in-group p 0 :target) clist)
17146 (goto-char (1- (match-beginning 0)))
17147 (if (looking-at org-radio-target-regexp)
17148 (push (org-point-in-group p 0 :radio-target) clist))
17149 (goto-char p))
17150 ((setq o (car (delq nil
17151 (mapcar
17152 (lambda (x)
17153 (if (memq x org-latex-fragment-image-overlays) x))
17154 (org-overlays-at (point))))))
17155 (push (list :latex-fragment
17156 (org-overlay-start o) (org-overlay-end o)) clist)
17157 (push (list :latex-preview
17158 (org-overlay-start o) (org-overlay-end o)) clist))
17159 ((org-inside-LaTeX-fragment-p)
17160 ;; FIXME: positions wrong.
17161 (push (list :latex-fragment (point) (point)) clist)))
17162
17163 (setq clist (nreverse (delq nil clist)))
17164 clist))
17165
17166 (defun org-point-in-group (point group &optional context)
17167 "Check if POINT is in match-group GROUP.
17168 If CONTEXT is non-nil, return a list with CONTEXT and the boundaries of the
17169 match. If the match group does ot exist or point is not inside it,
17170 return nil."
17171 (and (match-beginning group)
17172 (>= point (match-beginning group))
17173 (<= point (match-end group))
17174 (if context
17175 (list context (match-beginning group) (match-end group))
17176 t)))
17177
17178 (defun org-move-line-down (arg)
17179 "Move the current line down. With prefix argument, move it past ARG lines."
17180 (interactive "p")
17181 (let ((col (current-column))
17182 beg end pos)
17183 (beginning-of-line 1) (setq beg (point))
17184 (beginning-of-line 2) (setq end (point))
17185 (beginning-of-line (+ 1 arg))
17186 (setq pos (move-marker (make-marker) (point)))
17187 (insert (delete-and-extract-region beg end))
17188 (goto-char pos)
17189 (move-to-column col)))
17190
17191 (defun org-move-line-up (arg)
17192 "Move the current line up. With prefix argument, move it past ARG lines."
17193 (interactive "p")
17194 (let ((col (current-column))
17195 beg end pos)
17196 (beginning-of-line 1) (setq beg (point))
17197 (beginning-of-line 2) (setq end (point))
17198 (beginning-of-line (- arg))
17199 (setq pos (move-marker (make-marker) (point)))
17200 (insert (delete-and-extract-region beg end))
17201 (goto-char pos)
17202 (move-to-column col)))
17203
17204 ;; Paragraph filling stuff.
17205 ;; We want this to be just right, so use the full arsenal.
17206
17207 (defun org-set-autofill-regexps ()
17208 (interactive)
17209 ;; In the paragraph separator we include headlines, because filling
17210 ;; text in a line directly attached to a headline would otherwise
17211 ;; fill the headline as well.
17212 (org-set-local 'comment-start-skip "^#+[ \t]*")
17213 (org-set-local 'paragraph-separate "\f\\|\\*\\|[ ]*$\\|[ \t]*[:|]")
17214 ;; The paragraph starter includes hand-formatted lists.
17215 (org-set-local 'paragraph-start
17216 "\f\\|[ ]*$\\|\\([*\f]+\\)\\|[ \t]*\\([-+*][ \t]+\\|[0-9]+[.)][ \t]+\\)\\|[ \t]*[:|]")
17217 ;; Inhibit auto-fill for headers, tables and fixed-width lines.
17218 ;; But only if the user has not turned off tables or fixed-width regions
17219 (org-set-local
17220 'auto-fill-inhibit-regexp
17221 (concat "\\*\\|#"
17222 "\\|[ \t]*" org-keyword-time-regexp
17223 (if (or org-enable-table-editor org-enable-fixed-width-editor)
17224 (concat
17225 "\\|[ \t]*["
17226 (if org-enable-table-editor "|" "")
17227 (if org-enable-fixed-width-editor ":" "")
17228 "]"))))
17229 ;; We use our own fill-paragraph function, to make sure that tables
17230 ;; and fixed-width regions are not wrapped. That function will pass
17231 ;; through to `fill-paragraph' when appropriate.
17232 (org-set-local 'fill-paragraph-function 'org-fill-paragraph)
17233 ; Adaptive filling: To get full control, first make sure that
17234 ;; `adaptive-fill-regexp' never matches. Then install our own matcher.
17235 (org-set-local 'adaptive-fill-regexp "\000")
17236 (org-set-local 'adaptive-fill-function
17237 'org-adaptive-fill-function))
17238
17239 (defun org-fill-paragraph (&optional justify)
17240 "Re-align a table, pass through to fill-paragraph if no table."
17241 (let ((table-p (org-at-table-p))
17242 (table.el-p (org-at-table.el-p)))
17243 (cond ((equal (char-after (point-at-bol)) ?*) t) ; skip headlines
17244 (table.el-p t) ; skip table.el tables
17245 (table-p (org-table-align) t) ; align org-mode tables
17246 (t nil)))) ; call paragraph-fill
17247
17248 ;; For reference, this is the default value of adaptive-fill-regexp
17249 ;; "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*"
17250
17251 (defun org-adaptive-fill-function ()
17252 "Return a fill prefix for org-mode files.
17253 In particular, this makes sure hanging paragraphs for hand-formatted lists
17254 work correctly."
17255 (if (looking-at " *\\([-*+] \\|[0-9]+[.)] \\)?")
17256 (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
17257
17258 ;; Functions needed for Emacs/XEmacs region compatibility
17259
17260 (defun org-add-hook (hook function &optional append local)
17261 "Add-hook, compatible with both Emacsen."
17262 (if (and local (featurep 'xemacs))
17263 (add-local-hook hook function append)
17264 (add-hook hook function append local)))
17265
17266 (defun org-region-active-p ()
17267 "Is `transient-mark-mode' on and the region active?
17268 Works on both Emacs and XEmacs."
17269 (if org-ignore-region
17270 nil
17271 (if (featurep 'xemacs)
17272 (and zmacs-regions (region-active-p))
17273 (and transient-mark-mode mark-active))))
17274
17275 (defun org-add-to-invisibility-spec (arg)
17276 "Add elements to `buffer-invisibility-spec'.
17277 See documentation for `buffer-invisibility-spec' for the kind of elements
17278 that can be added."
17279 (cond
17280 ((fboundp 'add-to-invisibility-spec)
17281 (add-to-invisibility-spec arg))
17282 ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t))
17283 (setq buffer-invisibility-spec (list arg)))
17284 (t
17285 (setq buffer-invisibility-spec
17286 (cons arg buffer-invisibility-spec)))))
17287
17288 (defun org-remove-from-invisibility-spec (arg)
17289 "Remove elements from `buffer-invisibility-spec'."
17290 (if (fboundp 'remove-from-invisibility-spec)
17291 (remove-from-invisibility-spec arg)
17292 (if (consp buffer-invisibility-spec)
17293 (setq buffer-invisibility-spec
17294 (delete arg buffer-invisibility-spec)))))
17295
17296 (defun org-in-invisibility-spec-p (arg)
17297 "Is ARG a member of `buffer-invisibility-spec'?"
17298 (if (consp buffer-invisibility-spec)
17299 (member arg buffer-invisibility-spec)
17300 nil))
17301
17302 (defun org-image-file-name-regexp ()
17303 "Return regexp matching the file names of images."
17304 (if (fboundp 'image-file-name-regexp)
17305 (image-file-name-regexp)
17306 (let ((image-file-name-extensions
17307 '("png" "jpeg" "jpg" "gif" "tiff" "tif"
17308 "xbm" "xpm" "pbm" "pgm" "ppm")))
17309 (concat "\\."
17310 (regexp-opt (nconc (mapcar 'upcase
17311 image-file-name-extensions)
17312 image-file-name-extensions)
17313 t)
17314 "\\'"))))
17315
17316 ;; Functions extending outline functionality
17317
17318 ;; C-a should go to the beginning of a *visible* line, also in the
17319 ;; new outline.el. I guess this should be patched into Emacs?
17320 (defun org-beginning-of-line ()
17321 "Go to the beginning of the current line. If that is invisible, continue
17322 to a visible line beginning. This makes the function of C-a more intuitive."
17323 (interactive)
17324 (beginning-of-line 1)
17325 (if (bobp)
17326 nil
17327 (backward-char 1)
17328 (if (org-invisible-p)
17329 (while (and (not (bobp)) (org-invisible-p))
17330 (backward-char 1)
17331 (beginning-of-line 1))
17332 (forward-char 1))))
17333
17334 (define-key org-mode-map "\C-a" 'org-beginning-of-line)
17335
17336 (defun org-invisible-p ()
17337 "Check if point is at a character currently not visible."
17338 ;; Early versions of noutline don't have `outline-invisible-p'.
17339 (if (fboundp 'outline-invisible-p)
17340 (outline-invisible-p)
17341 (get-char-property (point) 'invisible)))
17342
17343 (defun org-invisible-p2 ()
17344 "Check if point is at a character currently not visible."
17345 (save-excursion
17346 (if (and (eolp) (not (bobp))) (backward-char 1))
17347 ;; Early versions of noutline don't have `outline-invisible-p'.
17348 (if (fboundp 'outline-invisible-p)
17349 (outline-invisible-p)
17350 (get-char-property (point) 'invisible))))
17351
17352 (defalias 'org-back-to-heading 'outline-back-to-heading)
17353 (defalias 'org-on-heading-p 'outline-on-heading-p)
17354
17355 (defun org-on-target-p ()
17356 (let ((pos (point)))
17357 (save-excursion
17358 (skip-chars-forward "<")
17359 (and (re-search-backward "<<" nil t)
17360 (or (looking-at org-radio-target-regexp)
17361 (looking-at org-target-regexp))
17362 (<= (match-beginning 0) pos)
17363 (>= (1+ (match-end 0)) pos)))))
17364
17365 (defun org-up-heading-all (arg)
17366 "Move to the heading line of which the present line is a subheading.
17367 This function considers both visible and invisible heading lines.
17368 With argument, move up ARG levels."
17369 (if (fboundp 'outline-up-heading-all)
17370 (outline-up-heading-all arg) ; emacs 21 version of outline.el
17371 (outline-up-heading arg t))) ; emacs 22 version of outline.el
17372
17373 (defun org-goto-sibling (&optional previous)
17374 "Goto the next sibling, even if it is invisible.
17375 When PREVIOUS is set, go to the previous sibling instead. Returns t
17376 when a sibling was found. When none is found, return nil and don't
17377 move point."
17378 (let ((fun (if previous 're-search-backward 're-search-forward))
17379 (pos (point))
17380 (re (concat "^" outline-regexp))
17381 level l)
17382 (org-back-to-heading t)
17383 (setq level (funcall outline-level))
17384 (catch 'exit
17385 (or previous (forward-char 1))
17386 (while (funcall fun re nil t)
17387 (setq l (funcall outline-level))
17388 (when (< l level) (goto-char pos) (throw 'exit nil))
17389 (when (= l level) (goto-char (match-beginning 0)) (throw 'exit t)))
17390 (goto-char pos)
17391 nil)))
17392
17393 (defun org-show-hidden-entry ()
17394 "Show an entry where even the heading is hidden."
17395 (save-excursion
17396 (org-show-entry)))
17397
17398 (defun org-flag-heading (flag &optional entry)
17399 "Flag the current heading. FLAG non-nil means make invisible.
17400 When ENTRY is non-nil, show the entire entry."
17401 (save-excursion
17402 (org-back-to-heading t)
17403 ;; Check if we should show the entire entry
17404 (if entry
17405 (progn
17406 (org-show-entry)
17407 (save-excursion
17408 (and (outline-next-heading)
17409 (org-flag-heading nil))))
17410 (outline-flag-region (max 1 (1- (point)))
17411 (save-excursion (outline-end-of-heading) (point))
17412 flag))))
17413
17414 (defun org-end-of-subtree (&optional invisible-OK)
17415 ;; This is an exact copy of the original function, but it uses
17416 ;; `org-back-to-heading', to make it work also in invisible
17417 ;; trees. And is uses an invisible-OK argument.
17418 ;; Under Emacs this is not needed, but the old outline.el needs this fix.
17419 (org-back-to-heading invisible-OK)
17420 (let ((first t)
17421 (level (funcall outline-level)))
17422 (while (and (not (eobp))
17423 (or first (> (funcall outline-level) level)))
17424 (setq first nil)
17425 (outline-next-heading))
17426 (if (memq (preceding-char) '(?\n ?\^M))
17427 (progn
17428 ;; Go to end of line before heading
17429 (forward-char -1)
17430 (if (memq (preceding-char) '(?\n ?\^M))
17431 ;; leave blank line before heading
17432 (forward-char -1)))))
17433 (point))
17434
17435 (defun org-show-subtree ()
17436 "Show everything after this heading at deeper levels."
17437 (outline-flag-region
17438 (point)
17439 (save-excursion
17440 (outline-end-of-subtree) (outline-next-heading) (point))
17441 nil))
17442
17443 (defun org-show-entry ()
17444 "Show the body directly following this heading.
17445 Show the heading too, if it is currently invisible."
17446 (interactive)
17447 (save-excursion
17448 (org-back-to-heading t)
17449 (outline-flag-region
17450 (max 1 (1- (point)))
17451 (save-excursion
17452 (re-search-forward (concat "[\r\n]\\(" outline-regexp "\\)") nil 'move)
17453 (or (match-beginning 1) (point-max)))
17454 nil)))
17455
17456 (defun org-make-options-regexp (kwds)
17457 "Make a regular expression for keyword lines."
17458 (concat
17459 "^"
17460 "#?[ \t]*\\+\\("
17461 (mapconcat 'regexp-quote kwds "\\|")
17462 "\\):[ \t]*"
17463 "\\(.+\\)"))
17464
17465 ;; Make `bookmark-jump' show the jump location if it was hidden.
17466 (eval-after-load "bookmark"
17467 '(if (boundp 'bookmark-after-jump-hook)
17468 ;; We can use the hook
17469 (add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide)
17470 ;; Hook not available, use advice
17471 (defadvice bookmark-jump (after org-make-visible activate)
17472 "Make the position visible."
17473 (org-bookmark-jump-unhide))))
17474
17475 (defun org-bookmark-jump-unhide ()
17476 "Unhide the current position, to show the bookmark location."
17477 (and (org-mode-p)
17478 (or (org-invisible-p)
17479 (save-excursion (goto-char (max (point-min) (1- (point))))
17480 (org-invisible-p)))
17481 (org-show-context 'bookmark-jump)))
17482
17483 ;; Make session.el ignore our circular variable
17484 (eval-after-load "session"
17485 '(add-to-list 'session-globals-exclude 'org-mark-ring))
17486
17487 ;;; Experimental code
17488
17489 ;;; Finish up
17490
17491 (provide 'org)
17492
17493 (run-hooks 'org-load-hook)
17494
17495 ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
17496 ;;; org.el ends here