]> code.delx.au - gnu-emacs/blob - lisp/textmodes/org.el
(org-agenda-highlight-todo): Make sure regexp
[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.35
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 ;;
49 ;; Installation
50 ;; ------------
51 ;; If Org-mode is part of the Emacs distribution or an XEmacs package, you
52 ;; only need to copy the following lines to your .emacs file. The last two
53 ;; lines define *global* keys for the commands `org-store-link' and
54 ;; `org-agenda' - please choose suitable keys yourself.
55 ;;
56 ;; (add-to-list 'auto-mode-alist '("\\.org$" . org-mode))
57 ;; (define-key global-map "\C-cl" 'org-store-link)
58 ;; (define-key global-map "\C-ca" 'org-agenda)
59 ;;
60 ;; Furthermore you need to activate font-lock-mode in org-mode buffers.
61 ;; either of the following two lins will do the trick:
62 ;;
63 ;; (global-font-lock-mode 1) ; for all buffers
64 ;; (add-hook 'org-mode-hook 'turn-on-font-lock) ; org-mode buffers only
65 ;;
66 ;; If you have downloaded Org-mode from the Web, you have to take additional
67 ;; action: Byte-compile org.el and org-publish.el and put them together with
68 ;; org-install.el on your load path. Then also add to your .emacs file:
69 ;;
70 ;; (require 'org-install)
71 ;;
72 ;;
73 ;; Activation
74 ;; ----------
75 ;; The setup above will put all files with extension ".org" into Org-mode.
76 ;; As an alternative, make the first line of a file look like this:
77 ;;
78 ;; MY PROJECTS -*- mode: org; -*-
79 ;;
80 ;; which will select Org-mode for this buffer no matter what the file's
81 ;; name is.
82 ;;
83 ;; Documentation
84 ;; -------------
85 ;; The documentation of Org-mode can be found in the TeXInfo file. The
86 ;; distribution also contains a PDF version of it. At the homepage of
87 ;; Org-mode, you can read the same text online as HTML. There is also an
88 ;; excellent reference card made by Philip Rooke. This card can be found
89 ;; in the etc/ directory of Emacs 22.
90 ;;
91 ;; Recent changes
92 ;; --------------
93 ;; Version 4.35
94 ;; - HTML export is now valid XHTML.
95 ;; - Timeline can also show dates without entries. See new option
96 ;; `org-timeline-show-empty-dates'.
97 ;; - The bullets created by the ASCII exporter can now be configured.
98 ;; See the new option `org-export-ascii-bullets'.
99 ;; - New face `org-upcoming-deadline' (was `org-scheduled-previously').
100 ;; - New function `org-context' to allow testing for local context.
101 ;;
102 ;; Version 4.34
103 ;; - Bug fixes.
104 ;;
105 ;; Version 4.33
106 ;; - New commands to move through plain lists: S-up and S-down.
107 ;; - Bug fixes and documentation update.
108 ;;
109 ;; Version 4.32
110 ;; - Fast (single-key-per-tag) interface for setting TAGS.
111 ;; - The list of legal tags can be configured globally and locally.
112 ;; - Elisp and Info links (thanks to Todd Neal).
113 ;; - `org-export-publishing-directory' can be an alist, with different
114 ;; directories for different export types.
115 ;; - All context-sensitive commands use `call-interactively' to dispatch.
116 ;; - `org-confirm-shell-links' renamed to `org-confirm-shell-link-function'.
117 ;; - Bug fixes.
118 ;;
119 ;; Version 4.31
120 ;; - Bug fixes.
121 ;;
122 ;; Version 4.30
123 ;; - Modified installation: Autoloads have been collected in org-install.el.
124 ;; - Logging (org-log-done) is now a #+STARTUP option.
125 ;; - Checkboxes in plain list items, following up on Frank Ruell's idea.
126 ;; - File links inserted with C-c C-l will use relative paths if the linked
127 ;; file is in the current directory or a subdirectory of it.
128 ;; - New variable `org-link-file-path-type' to specify preference for
129 ;; relative and absolute paths.
130 ;; - New CSS classes for tags, timestamps, timestamp keywords.
131 ;; - Bug and typo fixes.
132 ;;
133 ;; Version 4.29
134 ;; - Inlining images in HTML export now depends on wheather the link
135 ;; contains a description or not.
136 ;; - TODO items can be scheduled from the global TODO list using C-c C-s.
137 ;; - TODO items already scheduled can be made to disappear from the global
138 ;; todo list, see `org-agenda-todo-ignore-scheduled'.
139 ;; - In Tables, formulas may also be Lisp forms.
140 ;; - Exporting the visible part of an outline with `C-c C-x v' works now
141 ;; for all available exporters.
142 ;; - Bug fixes, lots of them :-(
143 ;;
144 ;; Version 4.28
145 ;; - Bug fixes.
146 ;;
147 ;; Version 4.27
148 ;; - HTML exporter generalized to receive external options.
149 ;; As part of the process, author, email and date have been moved to the
150 ;; end of the HTML file.
151 ;; - Support for customizable file search in file links.
152 ;; - BibTeX database links as first application of the above.
153 ;; - New option `org-agenda-todo-list-sublevels' to turn off listing TODO
154 ;; entries that are sublevels of another TODO entry.
155 ;;
156 ;;
157 ;;; Code:
158
159 (eval-when-compile
160 (require 'cl)
161 (require 'calendar))
162 (require 'outline)
163 (require 'time-date)
164 (require 'easymenu)
165
166 ;;; Customization variables
167
168 (defvar org-version "4.35"
169 "The version number of the file org.el.")
170 (defun org-version ()
171 (interactive)
172 (message "Org-mode version %s" org-version))
173
174 ;; The following constant is for compatibility with different versions
175 ;; of outline.el.
176 (defconst org-noutline-p (featurep 'noutline)
177 "Are we using the new outline mode?")
178 (defconst org-xemacs-p (featurep 'xemacs)) ; not used by org.el itself
179 (defconst org-format-transports-properties-p
180 (let ((x "a"))
181 (add-text-properties 0 1 '(test t) x)
182 (get-text-property 0 'test (format "%s" x)))
183 "Does format transport text properties?")
184
185 (defgroup org nil
186 "Outline-based notes management and organizer."
187 :tag "Org"
188 :group 'outlines
189 :group 'hypermedia
190 :group 'calendar)
191
192 (defgroup org-startup nil
193 "Options concerning startup of Org-mode."
194 :tag "Org Startup"
195 :group 'org)
196
197 (defcustom org-startup-folded t
198 "Non-nil means, entering Org-mode will switch to OVERVIEW.
199 This can also be configured on a per-file basis by adding one of
200 the following lines anywhere in the buffer:
201
202 #+STARTUP: fold
203 #+STARTUP: nofold
204 #+STARTUP: content"
205 :group 'org-startup
206 :type '(choice
207 (const :tag "nofold: show all" nil)
208 (const :tag "fold: overview" t)
209 (const :tag "content: all headlines" content)))
210
211 (defcustom org-startup-truncated t
212 "Non-nil means, entering Org-mode will set `truncate-lines'.
213 This is useful since some lines containing links can be very long and
214 uninteresting. Also tables look terrible when wrapped."
215 :group 'org-startup
216 :type 'boolean)
217
218 (defcustom org-startup-align-all-tables nil
219 "Non-nil means, align all tables when visiting a file.
220 This is useful when the column width in tables is forced with <N> cookies
221 in table fields. Such tables will look correct only after the first re-align.
222 This can also be configured on a per-file basis by adding one of
223 the following lines anywhere in the buffer:
224 #+STARTUP: align
225 #+STARTUP: noalign"
226 :group 'org-startup
227 :type 'boolean)
228
229 (defcustom org-startup-with-deadline-check nil
230 "Non-nil means, entering Org-mode will run the deadline check.
231 This means, if you start editing an org file, you will get an
232 immediate reminder of any due deadlines.
233 This can also be configured on a per-file basis by adding one of
234 the following lines anywhere in the buffer:
235 #+STARTUP: dlcheck
236 #+STARTUP: nodlcheck"
237 :group 'org-startup
238 :type 'boolean)
239
240 (defcustom org-insert-mode-line-in-empty-file nil
241 "Non-nil means insert the first line setting Org-mode in empty files.
242 When the function `org-mode' is called interactively in an empty file, this
243 normally means that the file name does not automatically trigger Org-mode.
244 To ensure that the file will always be in Org-mode in the future, a
245 line enforcing Org-mode will be inserted into the buffer, if this option
246 has been set."
247 :group 'org-startup
248 :type 'boolean)
249
250 (defcustom org-CUA-compatible nil
251 "Non-nil means use alternative key bindings for S-<cursor movement>.
252 Org-mode used S-<cursor movement> for changing timestamps and priorities.
253 S-<cursor movement> is also used for example by `CUA-mode' to select text.
254 If you want to use Org-mode together with `CUA-mode', Org-mode needs to use
255 alternative bindings. Setting this variable to t will replace the following
256 keys both in Org-mode and in the Org-agenda buffer.
257
258 S-RET -> C-S-RET
259 S-up -> M-p
260 S-down -> M-n
261 S-left -> M--
262 S-right -> M-+
263
264 If you do not like the alternative keys, take a look at the variable
265 `org-disputed-keys'.
266
267 This option is only relevant at load-time of Org-mode. Changing it requires
268 a restart of Emacs to become effective."
269 :group 'org-startup
270 :type 'boolean)
271
272 (defvar org-disputed-keys
273 '((S-up [(shift up)] [(meta ?p)])
274 (S-down [(shift down)] [(meta ?n)])
275 (S-left [(shift left)] [(meta ?-)])
276 (S-right [(shift right)] [(meta ?+)])
277 (S-return [(shift return)] [(control shift return)]))
278 "Keys for which Org-mode and other modes compete.
279 This is an alist, cars are symbols for lookup, 1st element is the default key,
280 second element will be used when `org-CUA-compatible' is t.")
281
282 (defun org-key (key)
283 "Select a key according to `org-CUA-compatible'."
284 (nth (if org-CUA-compatible 2 1)
285 (or (assq key org-disputed-keys)
286 (error "Invalid Key %s in `org-key'" key))))
287
288 (defcustom org-ellipsis nil
289 "The ellipsis to use in the Org-mode outline.
290 When nil, just use the standard three dots. When a string, use that instead,
291 and just in Org-mode (which will then use its own display table).
292 Changing this requires executing `M-x org-mode' in a buffer to become
293 effective."
294 :group 'org-startup
295 :type '(choice (const :tag "Default" nil)
296 (string :tag "String" :value "...#")))
297
298 (defvar org-display-table nil
299 "The display table for org-mode, in case `org-ellipsis' is non-nil.")
300
301 (defgroup org-keywords nil
302 "Keywords in Org-mode."
303 :tag "Org Keywords"
304 :group 'org)
305
306 (defcustom org-deadline-string "DEADLINE:"
307 "String to mark deadline entries.
308 A deadline is this string, followed by a time stamp. Should be a word,
309 terminated by a colon. You can insert a schedule keyword and
310 a timestamp with \\[org-deadline].
311 Changes become only effective after restarting Emacs."
312 :group 'org-keywords
313 :type 'string)
314
315 (defcustom org-scheduled-string "SCHEDULED:"
316 "String to mark scheduled TODO entries.
317 A schedule is this string, followed by a time stamp. Should be a word,
318 terminated by a colon. You can insert a schedule keyword and
319 a timestamp with \\[org-schedule].
320 Changes become only effective after restarting Emacs."
321 :group 'org-keywords
322 :type 'string)
323
324 (defcustom org-closed-string "CLOSED:"
325 "String used as the prefix for timestamps logging closing a TODO entry."
326 :group 'org-keywords
327 :type 'string)
328
329 (defcustom org-comment-string "COMMENT"
330 "Entries starting with this keyword will never be exported.
331 An entry can be toggled between COMMENT and normal with
332 \\[org-toggle-comment].
333 Changes become only effective after restarting Emacs."
334 :group 'org-keywords
335 :type 'string)
336
337 (defcustom org-quote-string "QUOTE"
338 "Entries starting with this keyword will be exported in fixed-width font.
339 Quoting applies only to the text in the entry following the headline, and does
340 not extend beyond the next headline, even if that is lower level.
341 An entry can be toggled between QUOTE and normal with
342 \\[org-toggle-fixed-width-section]."
343 :group 'org-keywords
344 :type 'string)
345
346 (defgroup org-structure nil
347 "Options concerning the general structure of Org-mode files."
348 :tag "Org Structure"
349 :group 'org)
350
351 (defgroup org-cycle nil
352 "Options concerning visibility cycling in Org-mode."
353 :tag "Org Cycle"
354 :group 'org-structure)
355
356 (defcustom org-cycle-global-at-bob t
357 "Cycle globally if cursor is at beginning of buffer and not at a headline.
358 This makes it possible to do global cycling without having to use S-TAB or
359 C-u TAB. For this special case to work, the first line of the buffer
360 must not be a headline - it may be empty ot some other text. When used in
361 this way, `org-cycle-hook' is disables temporarily, to make sure the
362 cursor stays at the beginning of the buffer.
363 When this option is nil, don't do anything special at the beginning
364 of the buffer."
365 :group 'org-cycle
366 :type 'boolean)
367
368 (defcustom org-cycle-emulate-tab t
369 "Where should `org-cycle' emulate TAB.
370 nil Never
371 white Only in completely white lines
372 t Everywhere except in headlines"
373 :group 'org-cycle
374 :type '(choice (const :tag "Never" nil)
375 (const :tag "Only in completely white lines" white)
376 (const :tag "Everywhere except in headlines" t)
377 ))
378
379 (defcustom org-cycle-hook '(org-optimize-window-after-visibility-change)
380 "Hook that is run after `org-cycle' has changed the buffer visibility.
381 The function(s) in this hook must accept a single argument which indicates
382 the new state that was set by the most recent `org-cycle' command. The
383 argument is a symbol. After a global state change, it can have the values
384 `overview', `content', or `all'. After a local state change, it can have
385 the values `folded', `children', or `subtree'."
386 :group 'org-cycle
387 :type 'hook)
388
389 (defgroup org-edit-structure nil
390 "Options concerning structure editing in Org-mode."
391 :tag "Org Edit Structure"
392 :group 'org-structure)
393
394 (defcustom org-odd-levels-only nil
395 "Non-nil means, skip even levels and only use odd levels for the outline.
396 This has the effect that two stars are being added/taken away in
397 promotion/demotion commands. It also influences how levels are
398 handled by the exporters.
399 Changing it requires restart of `font-lock-mode' to become effective
400 for fontification also in regions already fontified.
401 You may also set this on a per-file basis by adding one of the following
402 lines to the buffer:
403
404 #+STARTUP: odd
405 #+STARTUP: oddeven"
406 :group 'org-edit-structure
407 :group 'org-font-lock
408 :type 'boolean)
409
410 (defcustom org-adapt-indentation t
411 "Non-nil means, adapt indentation when promoting and demoting.
412 When this is set and the *entire* text in an entry is indented, the
413 indentation is increased by one space in a demotion command, and
414 decreased by one in a promotion command. If any line in the entry
415 body starts at column 0, indentation is not changed at all."
416 :group 'org-edit-structure
417 :type 'boolean)
418
419 (defcustom org-insert-heading-hook nil
420 "Hook being run after inserting a new heading."
421 :group 'org-edit-structure
422 :type 'boolean)
423
424 (defcustom org-enable-fixed-width-editor t
425 "Non-nil means, lines starting with \":\" are treated as fixed-width.
426 This currently only means, they are never auto-wrapped.
427 When nil, such lines will be treated like ordinary lines.
428 See also the QUOTE keyword."
429 :group 'org-edit-structure
430 :type 'boolean)
431
432 (defgroup org-sparse-trees nil
433 "Options concerning sparse trees in Org-mode."
434 :tag "Org Sparse Trees"
435 :group 'org-structure)
436
437 (defcustom org-highlight-sparse-tree-matches t
438 "Non-nil means, highlight all matches that define a sparse tree.
439 The highlights will automatically disappear the next time the buffer is
440 changed by an edit command."
441 :group 'org-sparse-trees
442 :type 'boolean)
443
444 (defcustom org-show-hierarchy-above t
445 "Non-nil means, show full hierarchy when showing a spot in the tree.
446 Turning this off makes sparse trees more compact, but also less clear."
447 :group 'org-sparse-trees
448 :type 'boolean)
449
450 (defcustom org-show-following-heading t
451 "Non-nil means, show heading following match in `org-occur'.
452 When doing an `org-occur' it is useful to show the headline which
453 follows the match, even if they do not match the regexp. This makes it
454 easier to edit directly inside the sparse tree. However, if you use
455 `org-occur' mainly as an overview, the following headlines are
456 unnecessary clutter."
457 :group 'org-sparse-trees
458 :type 'boolean)
459
460 (defcustom org-occur-hook '(org-first-headline-recenter)
461 "Hook that is run after `org-occur' has constructed a sparse tree.
462 This can be used to recenter the window to show as much of the structure
463 as possible."
464 :group 'org-sparse-trees
465 :type 'hook)
466
467 (defgroup org-plain-lists nil
468 "Options concerning plain lists in Org-mode."
469 :tag "Org Plain lists"
470 :group 'org-structure)
471
472 (defcustom org-cycle-include-plain-lists nil
473 "Non-nil means, include plain lists into visibility cycling.
474 This means that during cycling, plain list items will *temporarily* be
475 interpreted as outline headlines with a level given by 1000+i where i is the
476 indentation of the bullet. In all other operations, plain list items are
477 not seen as headlines. For example, you cannot assign a TODO keyword to
478 such an item."
479 :group 'org-plain-lists
480 :type 'boolean)
481
482
483 (defcustom org-plain-list-ordered-item-terminator t
484 "The character that makes a line with leading number an ordered list item.
485 Valid values are ?. and ?\). To get both terminators, use t. While
486 ?. may look nicer, it creates the danger that a line with leading
487 number may be incorrectly interpreted as an item. ?\) therefore is
488 the safe choice."
489 :group 'org-plain-lists
490 :type '(choice (const :tag "dot like in \"2.\"" ?.)
491 (const :tag "paren like in \"2)\"" ?\))
492 (const :tab "both" t)))
493
494 (defcustom org-auto-renumber-ordered-lists t
495 "Non-nil means, automatically renumber ordered plain lists.
496 Renumbering happens when the sequence have been changed with
497 \\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands,
498 use \\[org-ctrl-c-ctrl-c] to trigger renumbering."
499 :group 'org-plain-lists
500 :type 'boolean)
501
502 (defgroup org-archive nil
503 "Options concerning archiving in Org-mode."
504 :tag "Org Archive"
505 :group 'org-structure)
506
507 (defcustom org-archive-location "%s_archive::"
508 "The location where subtrees should be archived.
509 This string consists of two parts, separated by a double-colon.
510
511 The first part is a file name - when omitted, archiving happens in the same
512 file. %s will be replaced by the current file name (without directory part).
513 Archiving to a different file is useful to keep archived entries from
514 contributing to the Org-mode Agenda.
515
516 The part after the double colon is a headline. The archived entries will be
517 filed under that headline. When omitted, the subtrees are simply filed away
518 at the end of the file, as top-level entries.
519
520 Here are a few examples:
521 \"%s_archive::\"
522 If the current file is Projects.org, archive in file
523 Projects.org_archive, as top-level trees. This is the default.
524
525 \"::* Archived Tasks\"
526 Archive in the current file, under the top-level headline
527 \"* Archived Tasks\".
528
529 \"~/org/archive.org::\"
530 Archive in file ~/org/archive.org (absolute path), as top-level trees.
531
532 \"basement::** Finished Tasks\"
533 Archive in file ./basement (relative path), as level 3 trees
534 below the level 2 heading \"** Finished Tasks\".
535
536 You may set this option on a per-file basis by adding to the buffer a
537 line like
538
539 #+ARCHIVE: basement::** Finished Tasks"
540 :group 'org-archive
541 :type 'string)
542
543 (defcustom org-archive-mark-done t
544 "Non-nil means, mark archived entries as DONE."
545 :group 'org-archive
546 :type 'boolean)
547
548 (defcustom org-archive-stamp-time t
549 "Non-nil means, add a time stamp to archived entries.
550 The time stamp will be added directly after the TODO state keyword in the
551 first line, so it is probably best to use this in combinations with
552 `org-archive-mark-done'."
553 :group 'org-archive
554 :type 'boolean)
555
556 (defgroup org-table nil
557 "Options concerning tables in Org-mode."
558 :tag "Org Table"
559 :group 'org)
560
561 (defcustom org-enable-table-editor 'optimized
562 "Non-nil means, lines starting with \"|\" are handled by the table editor.
563 When nil, such lines will be treated like ordinary lines.
564
565 When equal to the symbol `optimized', the table editor will be optimized to
566 do the following:
567 - Use automatic overwrite mode in front of whitespace in table fields.
568 This make the structure of the table stay in tact as long as the edited
569 field does not exceed the column width.
570 - Minimize the number of realigns. Normally, the table is aligned each time
571 TAB or RET are pressed to move to another field. With optimization this
572 happens only if changes to a field might have changed the column width.
573 Optimization requires replacing the functions `self-insert-command',
574 `delete-char', and `backward-delete-char' in Org-mode buffers, with a
575 slight (in fact: unnoticeable) speed impact for normal typing. Org-mode is
576 very good at guessing when a re-align will be necessary, but you can always
577 force one with \\[org-ctrl-c-ctrl-c].
578
579 If you would like to use the optimized version in Org-mode, but the
580 un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'.
581
582 This variable can be used to turn on and off the table editor during a session,
583 but in order to toggle optimization, a restart is required.
584
585 See also the variable `org-table-auto-blank-field'."
586 :group 'org-table
587 :type '(choice
588 (const :tag "off" nil)
589 (const :tag "on" t)
590 (const :tag "on, optimized" optimized)))
591
592 (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized)
593 "Non-nil means, use the optimized table editor version for `orgtbl-mode'.
594 In the optimized version, the table editor takes over all simple keys that
595 normally just insert a character. In tables, the characters are inserted
596 in a way to minimize disturbing the table structure (i.e. in overwrite mode
597 for empty fields). Outside tables, the correct binding of the keys is
598 restored.
599
600 The default for this option is t if the optimized version is also used in
601 Org-mode. See the variable `org-enable-table-editor' for details. Changing
602 this variable requires a restart of Emacs to become effective."
603 :group 'org-table
604 :type 'boolean)
605
606 (defgroup org-table-settings nil
607 "Settings for tables in Org-mode."
608 :tag "Org Table Settings"
609 :group 'org-table)
610
611 (defcustom org-table-default-size "5x2"
612 "The default size for newly created tables, Columns x Rows."
613 :group 'org-table-settings
614 :type 'string)
615
616 (defcustom org-table-number-regexp "^[<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*$"
617 "Regular expression for recognizing numbers in table columns.
618 If a table column contains mostly numbers, it will be aligned to the
619 right. If not, it will be aligned to the left.
620
621 The default value of this option is a regular expression which allows
622 anything which looks remotely like a number as used in scientific
623 context. For example, all of the following will be considered a
624 number:
625 12 12.2 2.4e-08 2x10^12 4.034+-0.02 2.7(10) >3.5
626
627 Other options offered by the customize interface are more restrictive."
628 :group 'org-table-settings
629 :type '(choice
630 (const :tag "Positive Integers"
631 "^[0-9]+$")
632 (const :tag "Integers"
633 "^[-+]?[0-9]+$")
634 (const :tag "Floating Point Numbers"
635 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.[0-9]*\\)$")
636 (const :tag "Floating Point Number or Integer"
637 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.?[0-9]*\\)$")
638 (const :tag "Exponential, Floating point, Integer"
639 "^[-+]?[0-9.]+\\([eEdD][-+0-9]+\\)?$")
640 (const :tag "Very General Number-Like"
641 "^[<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*$")
642 (string :tag "Regexp:")))
643
644 (defcustom org-table-number-fraction 0.5
645 "Fraction of numbers in a column required to make the column align right.
646 In a column all non-white fields are considered. If at least this
647 fraction of fields is matched by `org-table-number-fraction',
648 alignment to the right border applies."
649 :group 'org-table-settings
650 :type 'number)
651
652 (defgroup org-table-editing nil
653 "Bahavior of tables during editing in Org-mode."
654 :tag "Org Table Editing"
655 :group 'org-table)
656
657 (defcustom org-table-automatic-realign t
658 "Non-nil means, automatically re-align table when pressing TAB or RETURN.
659 When nil, aligning is only done with \\[org-table-align], or after column
660 removal/insertion."
661 :group 'org-table-editing
662 :type 'boolean)
663
664 (defcustom org-table-limit-column-width t ;kw
665 "Non-nil means, allow to limit the width of table columns with <N> fields."
666 :group 'org-table-editing
667 :type 'boolean)
668
669 (defcustom org-table-auto-blank-field t
670 "Non-nil means, automatically blank table field when starting to type into it.
671 This only happens when typing immediately after a field motion
672 command (TAB, S-TAB or RET).
673 Only relevant when `org-enable-table-editor' is equal to `optimized'."
674 :group 'org-table-editing
675 :type 'boolean)
676
677 (defcustom org-table-tab-jumps-over-hlines t
678 "Non-nil means, tab in the last column of a table with jump over a hline.
679 If a horizontal separator line is following the current line,
680 `org-table-next-field' can either create a new row before that line, or jump
681 over the line. When this option is nil, a new line will be created before
682 this line."
683 :group 'org-table-editing
684 :type 'boolean)
685
686 (defcustom org-table-tab-recognizes-table.el t
687 "Non-nil means, TAB will automatically notice a table.el table.
688 When it sees such a table, it moves point into it and - if necessary -
689 calls `table-recognize-table'."
690 :group 'org-table-editing
691 :type 'boolean)
692
693 (defgroup org-table-calculation nil
694 "Options concerning tables in Org-mode."
695 :tag "Org Table Calculation"
696 :group 'org-table)
697
698 (defcustom org-table-copy-increment t
699 "Non-nil means, increment when copying current field with \\[org-table-copy-down]."
700 :group 'org-table-calculation
701 :type 'boolean)
702
703 (defcustom org-calc-default-modes
704 '(calc-internal-prec 12
705 calc-float-format (float 5)
706 calc-angle-mode deg
707 calc-prefer-frac nil
708 calc-symbolic-mode nil
709 calc-date-format (YYYY "-" MM "-" DD " " Www (" " HH ":" mm))
710 calc-display-working-message t
711 )
712 "List with Calc mode settings for use in calc-eval for table formulas.
713 The list must contain alternating symbols (Calc modes variables and values).
714 Don't remove any of the default settings, just change the values. Org-mode
715 relies on the variables to be present in the list."
716 :group 'org-table-calculation
717 :type 'plist)
718
719 (defcustom org-table-formula-evaluate-inline t
720 "Non-nil means, TAB and RET evaluate a formula in current table field.
721 If the current field starts with an equal sign, it is assumed to be a formula
722 which should be evaluated as described in the manual and in the documentation
723 string of the command `org-table-eval-formula'. This feature requires the
724 Emacs calc package.
725 When this variable is nil, formula calculation is only available through
726 the command \\[org-table-eval-formula]."
727 :group 'org-table-calculation
728 :type 'boolean)
729
730
731 (defcustom org-table-formula-use-constants t
732 "Non-nil means, interpret constants in formulas in tables.
733 A constant looks like `$c' or `$Grav' and will be replaced before evaluation
734 by the value given in `org-table-formula-constants', or by a value obtained
735 from the `constants.el' package."
736 :group 'org-table-calculation
737 :type 'boolean)
738
739 (defcustom org-table-formula-constants nil
740 "Alist with constant names and values, for use in table formulas.
741 The car of each element is a name of a constant, without the `$' before it.
742 The cdr is the value as a string. For example, if you'd like to use the
743 speed of light in a formula, you would configure
744
745 (setq org-table-formula-constants '((\"c\" . \"299792458.\")))
746
747 and then use it in an equation like `$1*$c'."
748 :group 'org-table-calculation
749 :type '(repeat
750 (cons (string :tag "name")
751 (string :tag "value"))))
752
753 (defcustom org-table-formula-numbers-only nil
754 "Non-nil means, calculate only with numbers in table formulas.
755 Then all input fields will be converted to a number, and the result
756 must also be a number. When nil, calc's full potential is available
757 in table calculations, including symbolics etc."
758 :group 'org-table-calculation
759 :type 'boolean)
760
761 (defcustom org-table-allow-automatic-line-recalculation t
762 "Non-nil means, lines marked with |#| or |*| will be recomputed automatically.
763 Automatically means, when TAB or RET or C-c C-c are pressed in the line."
764 :group 'org-table-calculation
765 :type 'boolean)
766
767 (defgroup org-link nil
768 "Options concerning links in Org-mode."
769 :tag "Org Link"
770 :group 'org)
771
772 (defcustom org-descriptive-links t
773 "Non-nil means, hide link part and only show description of bracket links.
774 Bracket links are like [[link][descritpion]]. This variable sets the initial
775 state in new org-mode buffers. The setting can then be toggled on a
776 per-buffer basis from the Org->Hyperlinks menu."
777 :group 'org-link
778 :type 'boolean)
779
780 (defcustom org-link-style 'bracket
781 "The style of links to be inserted with \\[org-insert-link].
782 Possible values are:
783 bracket [[link][description]]. This is recommended
784 plain Description \\n link. The old way, no longer recommended."
785 :group 'org-link
786 :type '(choice
787 (const :tag "Bracket (recommended)" bracket)
788 (const :tag "Plain (no longer recommended)" plain)))
789
790 (defcustom org-link-format "%s"
791 "Default format for external, URL-like linkes in the buffer.
792 This is a format string for printf, %s will be replaced by the link text.
793 The recommended value is just \"%s\", since links will be protected by
794 enclosing them in double brackets. If you prefer plain links (see variable
795 `org-link-style'), \"<%s>\" is useful. Some people also recommend an
796 additional URL: prefix, so the format would be \"<URL:%s>\"."
797 :group 'org-link
798 :type '(choice
799 (const :tag "\"%s\" (e.g. http://www.there.com)" "%s")
800 (const :tag "\"<%s>\" (e.g. <http://www.there.com>)" "<%s>")
801 (const :tag "\"<URL:%s>\" (e.g. <URL:http://www.there.com>)" "<URL:%s>")
802 (string :tag "Other" :value "<%s>")))
803
804 (defcustom org-link-file-path-type 'adaptive
805 "How the path name in file links should be stored.
806 Valid values are:
807
808 relative relative to the current directory, i.e. the directory of the file
809 into which the link is being inserted.
810 absolute absolute path, if possible with ~ for home directory.
811 noabbrev absolute path, no abbreviation of home directory.
812 adaptive Use relative path for files in the current directory and sub-
813 directories of it. For other files, use an absolute path."
814 :group 'org-link
815 :type '(choice
816 (const relative)
817 (const absolute)
818 (const noabbrev)
819 (const adaptive)))
820
821 (defcustom org-activate-links '(bracket angle plain radio tag date)
822 "Types of links that should be activated in Org-mode files.
823 This is a list of symbols, each leading to the activation of a certain link
824 type. In principle, it does not hurt to turn on most link types - there may
825 be a small gain when turning off unused link types. The types are:
826
827 bracket The recommended [[link][description]] or [[link]] links with hiding.
828 angular Links in angular brackes that may contain whitespace like
829 <bbdb:Carsten Dominik>.
830 plain Plain links in normal text, no whitespace, like http://google.com.
831 radio Text that is matched by a radio target, see manual for details.
832 tag Tag settings in a headline (link to tag search).
833 date Time stamps (link to calendar).
834 camel CamelCase words defining text searches.
835
836 Changing this variable requires a restart of Emacs to become effective."
837 :group 'org-link
838 :type '(set (const :tag "Double bracket links (new style)" bracket)
839 (const :tag "Angular bracket links (old style)" angular)
840 (const :tag "plain text links" plain)
841 (const :tag "Radio target matches" radio)
842 (const :tag "Tags" tag)
843 (const :tag "Timestamps" date)
844 (const :tag "CamelCase words" camel)))
845
846 (defgroup org-link-store nil
847 "Options concerning storing links in Org-mode"
848 :tag "Org Store Link"
849 :group 'org-link)
850
851 (defcustom org-context-in-file-links t
852 "Non-nil means, file links from `org-store-link' contain context.
853 A search string will be added to the file name with :: as separator and
854 used to find the context when the link is activated by the command
855 `org-open-at-point'.
856 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
857 negates this setting for the duration of the command."
858 :group 'org-link-store
859 :type 'boolean)
860
861 (defcustom org-file-link-context-use-camel-case nil
862 "Non-nil means, use CamelCase to store a search context in a file link.
863 When nil, the search string simply consists of the words of the string.
864 CamelCase is deprecated, and support for it may be dropped in the future."
865 :group 'org-link-store
866 :type 'boolean)
867
868 (defcustom org-keep-stored-link-after-insertion nil
869 "Non-nil means, keep link in list for entire session.
870
871 The command `org-store-link' adds a link pointing to the current
872 location to an internal list. These links accumulate during a session.
873 The command `org-insert-link' can be used to insert links into any
874 Org-mode file (offering completion for all stored links). When this
875 option is nil, every link which has been inserted once using \\[org-insert-link]
876 will be removed from the list, to make completing the unused links
877 more efficient."
878 :group 'org-link-store
879 :type 'boolean)
880
881 (defcustom org-usenet-links-prefer-google nil
882 "Non-nil means, `org-store-link' will create web links to Google groups.
883 When nil, Gnus will be used for such links.
884 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
885 negates this setting for the duration of the command."
886 :group 'org-link-store
887 :type 'boolean)
888
889 (defgroup org-link-follow nil
890 "Options concerning following links in Org-mode"
891 :tag "Org Follow Link"
892 :group 'org-link)
893
894 (defcustom org-tab-follows-link nil
895 "Non-nil means, on links TAB will follow the link.
896 Needs to be set before org.el is loaded."
897 :group 'org-link-follow
898 :type 'boolean)
899
900 (defcustom org-return-follows-link nil
901 "Non-nil means, on links RET will follow the link.
902 Needs to be set before org.el is loaded."
903 :group 'org-link-follow
904 :type 'boolean)
905
906 (defcustom org-mouse-1-follows-link t
907 "Non-nil means, mouse-1 on a link will follow the link.
908 A longer mouse click will still set point. Does not wortk on XEmacs.
909 Needs to be set before org.el is loaded."
910 :group 'org-link-follow
911 :type 'boolean)
912
913 (defcustom org-mark-ring-length 4
914 "Number of different positions to be recorded in the ring
915 Changing this requires a restart of Emacs to work correctly."
916 :group 'org-link-follow
917 :type 'interger)
918
919 (defcustom org-link-frame-setup
920 '((vm . vm-visit-folder-other-frame)
921 (gnus . gnus-other-frame)
922 (file . find-file-other-window))
923 "Setup the frame configuration for following links.
924 When following a link with Emacs, it may often be useful to display
925 this link in another window or frame. This variable can be used to
926 set this up for the different types of links.
927 For VM, use any of
928 `vm-visit-folder'
929 `vm-visit-folder-other-frame'
930 For Gnus, use any of
931 `gnus'
932 `gnus-other-frame'
933 For FILE, use any of
934 `find-file'
935 `find-file-other-window'
936 `find-file-other-frame'
937 For the calendar, use the variable `calendar-setup'.
938 For BBDB, it is currently only possible to display the matches in
939 another window."
940 :group 'org-link-follow
941 :type '(list
942 (cons (const vm)
943 (choice
944 (const vm-visit-folder)
945 (const vm-visit-folder-other-window)
946 (const vm-visit-folder-other-frame)))
947 (cons (const gnus)
948 (choice
949 (const gnus)
950 (const gnus-other-frame)))
951 (cons (const file)
952 (choice
953 (const find-file)
954 (const find-file-other-window)
955 (const find-file-other-frame)))))
956
957 (defcustom org-open-non-existing-files nil
958 "Non-nil means, `org-open-file' will open non-existing file.
959 When nil, an error will be generated."
960 :group 'org-link-follow
961 :type 'boolean)
962
963 (defcustom org-confirm-shell-link-function 'yes-or-no-p
964 "Non-nil means, ask for confirmation before executing shell links.
965 Shell links can be dangerous, just thing about a link
966
967 [[shell:rm -rf ~/*][Google Search]]
968
969 This link would show up in your Org-mode document as \"Google Search\"
970 but really it would remove your entire home directory.
971 Therefore I *definitely* advise against setting this variable to nil.
972 Just change it to `y-or-n-p' of you want to confirm with a single key press
973 rather than having to type \"yes\"."
974 :group 'org-link-follow
975 :type '(choice
976 (const :tag "with yes-or-no (safer)" yes-or-no-p)
977 (const :tag "with y-or-n (faster)" y-or-n-p)
978 (const :tag "no confirmation (dangerous)" nil)))
979
980 (defcustom org-confirm-elisp-link-function 'yes-or-no-p
981 "Non-nil means, ask for confirmation before executing elisp links.
982 Elisp links can be dangerous, just thing about a link
983
984 [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]]
985
986 This link would show up in your Org-mode document as \"Google Search\"
987 but really it would remove your entire home directory.
988 Therefore I *definitely* advise against setting this variable to nil.
989 Just change it to `y-or-n-p' of you want to confirm with a single key press
990 rather than having to type \"yes\"."
991 :group 'org-link-follow
992 :type '(choice
993 (const :tag "with yes-or-no (safer)" yes-or-no-p)
994 (const :tag "with y-or-n (faster)" y-or-n-p)
995 (const :tag "no confirmation (dangerous)" nil)))
996
997 (defconst org-file-apps-defaults-gnu
998 '((t . mailcap))
999 "Default file applications on a UNIX or GNU/Linux system.
1000 See `org-file-apps'.")
1001
1002 (defconst org-file-apps-defaults-macosx
1003 '((t . "open %s")
1004 ("ps" . "gv %s")
1005 ("ps.gz" . "gv %s")
1006 ("eps" . "gv %s")
1007 ("eps.gz" . "gv %s")
1008 ("dvi" . "xdvi %s")
1009 ("fig" . "xfig %s"))
1010 "Default file applications on a MacOS X system.
1011 The system \"open\" is known as a default, but we use X11 applications
1012 for some files for which the OS does not have a good default.
1013 See `org-file-apps'.")
1014
1015 (defconst org-file-apps-defaults-windowsnt
1016 (list (cons t
1017 (list (if (featurep 'xemacs)
1018 'mswindows-shell-execute
1019 'w32-shell-execute)
1020 "open" 'file)))
1021 "Default file applications on a Windows NT system.
1022 The system \"open\" is used for most files.
1023 See `org-file-apps'.")
1024
1025 (defcustom org-file-apps
1026 '(
1027 ("txt" . emacs)
1028 ("tex" . emacs)
1029 ("ltx" . emacs)
1030 ("org" . emacs)
1031 ("el" . emacs)
1032 ("bib" . emacs)
1033 )
1034 "External applications for opening `file:path' items in a document.
1035 Org-mode uses system defaults for different file types, but
1036 you can use this variable to set the application for a given file
1037 extension. The entries in this list are cons cells where the car identifies
1038 files and the cdr the corresponding command. Possible values for the
1039 file identifier are
1040 \"ext\" A string identifying an extension
1041 `directory' Matches a directory
1042 t Default for all remaining files
1043
1044 Possible values for the command are:
1045 `emacs' The file will be visited by the current Emacs process.
1046 `default' Use the default application for this file type.
1047 string A command to be executed by a shell; %s will be replaced
1048 by the path to the file.
1049 sexp A Lisp form which will be evaluated. The file path will
1050 be available in the Lisp variable `file'.
1051 For more examples, see the system specific constants
1052 `org-file-apps-defaults-macosx'
1053 `org-file-apps-defaults-windowsnt'
1054 `org-file-apps-defaults-gnu'."
1055 :group 'org-link-follow
1056 :type '(repeat
1057 (cons (choice :value ""
1058 (string :tag "Extension")
1059 (const :tag "Default for unrecognized files" t)
1060 (const :tag "Links to a directory" directory))
1061 (choice :value ""
1062 (const :tag "Visit with Emacs" emacs)
1063 (const :tag "Use system default" default)
1064 (string :tag "Command")
1065 (sexp :tag "Lisp form")))))
1066
1067 (defcustom org-mhe-search-all-folders nil
1068 "Non-nil means, that the search for the mh-message will be extended to
1069 all folders if the message cannot be found in the folder given in the link.
1070 Searching all folders is very effective with one of the search engines
1071 supported by MH-E, but will be slow with pick."
1072 :group 'org-link-follow
1073 :type 'boolean)
1074
1075 (defgroup org-remember nil
1076 "Options concerning interaction with remember.el."
1077 :tag "Org Remember"
1078 :group 'org)
1079
1080 (defcustom org-directory "~/org"
1081 "Directory with org files.
1082 This directory will be used as default to prompt for org files.
1083 Used by the hooks for remember.el."
1084 :group 'org-remember
1085 :type 'directory)
1086
1087 (defcustom org-default-notes-file "~/.notes"
1088 "Default target for storing notes.
1089 Used by the hooks for remember.el. This can be a string, or nil to mean
1090 the value of `remember-data-file'."
1091 :group 'org-remember
1092 :type '(choice
1093 (const :tag "Default from remember-data-file" nil)
1094 file))
1095
1096 (defcustom org-remember-templates nil
1097 "Templates for the creation of remember buffers.
1098 When nil, just let remember make the buffer.
1099 When not nil, this is a list of 3-element lists. In each entry, the first
1100 element is a character, a unique key to select this template.
1101 The second element is the template. The third element is optional and can
1102 specify a destination file for remember items created with this template.
1103 The default file is given by `org-default-notes-file'.
1104
1105 The template specifies the structure of the remember buffer. It should have
1106 a first line starting with a star, to act as the org-mode headline.
1107 Furthermore, the following %-escapes will be replaced with content:
1108 %t time stamp, date only
1109 %T time stamp with date and time
1110 %u inactive time stamp, date only
1111 %U inactive time stamp with date and time
1112 %n user name
1113 %a annotation, normally the link created with org-store-link
1114 %i initial content, the region when remember is called with C-u.
1115 If %i is indented, the entire inserted text will be indented as well.
1116 %? This will be removed, and the cursor placed at this position."
1117 :group 'org-remember
1118 :type '(repeat :tag "enabled"
1119 (list :value (?a "\n" nil)
1120 (character :tag "Selection Key")
1121 (string :tag "Template")
1122 (file :tag "Destination file (optional)"))))
1123
1124 (defcustom org-reverse-note-order nil
1125 "Non-nil means, store new notes at the beginning of a file or entry.
1126 When nil, new notes will be filed to the end of a file or entry."
1127 :group 'org-remember
1128 :type '(choice
1129 (const :tag "Reverse always" t)
1130 (const :tag "Reverse never" nil)
1131 (repeat :tag "By file name regexp"
1132 (cons regexp boolean))))
1133
1134 (defgroup org-todo nil
1135 "Options concerning TODO items in Org-mode."
1136 :tag "Org TODO"
1137 :group 'org)
1138
1139 (defcustom org-todo-keywords '("TODO" "DONE")
1140 "List of TODO entry keywords.
1141 \\<org-mode-map>By default, this is '(\"TODO\" \"DONE\"). The last entry in the list is
1142 considered to mean that the entry is \"done\". All the other mean that
1143 action is required, and will make the entry show up in todo lists, diaries
1144 etc.
1145 The command \\[org-todo] cycles an entry through these states, and an
1146 additional state where no keyword is present. For details about this
1147 cycling, see also the variable `org-todo-interpretation'
1148 Changes become only effective after restarting Emacs."
1149 :group 'org-todo
1150 :group 'org-keywords
1151 :type '(repeat (string :tag "Keyword")))
1152
1153 (defcustom org-todo-interpretation 'sequence
1154 "Controls how TODO keywords are interpreted.
1155 This variable is only relevant if `org-todo-keywords' contains more than two
1156 states. \\<org-mode-map>Possible values are `sequence' and `type'.
1157
1158 When `sequence', \\[org-todo] will always switch to the next state in the
1159 `org-todo-keywords' list. When `type', \\[org-todo] only cycles from state
1160 to state when executed several times in direct succession. Otherwise, it
1161 switches directly to DONE from any state.
1162 See the manual for more information."
1163 :group 'org-todo
1164 :group 'org-keywords
1165 :type '(choice (const sequence)
1166 (const type)))
1167
1168 (defcustom org-after-todo-state-change-hook nil
1169 "Hook which is run after the state of a TODO item was changed.
1170 The new state (a string with a TODO keyword, or nil) is available in the
1171 Lisp variable `state'."
1172 :group 'org-todo
1173 :type 'hook)
1174
1175 (defcustom org-log-done nil
1176 "When set, insert a (non-active) time stamp when TODO entry is marked DONE.
1177 When the state of an entry is changed from nothing to TODO, remove a previous
1178 closing date.
1179 This can also be configured on a per-file basis by adding one of
1180 the following lines anywhere in the buffer:
1181
1182 #+STARTUP: logging
1183 #+STARTUP: nologging"
1184 :group 'org-todo
1185 :type 'boolean)
1186
1187 (defgroup org-priorities nil
1188 "Priorities in Org-mode."
1189 :tag "Org Priorities"
1190 :group 'org-todo)
1191
1192 (defcustom org-default-priority ?B
1193 "The default priority of TODO items.
1194 This is the priority an item get if no explicit priority is given."
1195 :group 'org-priorities
1196 :type 'character)
1197
1198 (defcustom org-lowest-priority ?C
1199 "The lowest priority of TODO items. A character like ?A, ?B etc."
1200 :group 'org-priorities
1201 :type 'character)
1202
1203 (defgroup org-time nil
1204 "Options concerning time stamps and deadlines in Org-mode."
1205 :tag "Org Time"
1206 :group 'org)
1207
1208 (defcustom org-insert-labeled-timestamps-at-point nil
1209 "Non-nil means, SCHEDULED and DEADLINE timestamps are inserted at point.
1210 When nil, these labeled time stamps are forces into the second line of an
1211 entry, just after the headline. When scheduling from the global TODO list,
1212 the time stamp will always be forced into the second line."
1213 :group 'org-time
1214 :type 'boolean)
1215
1216 (defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
1217 "Formats for `format-time-string' which are used for time stamps.
1218 It is not recommended to change this constant.")
1219
1220 (defcustom org-time-stamp-rounding-minutes 0
1221 "Number of minutes to round time stamps to upon insertion.
1222 When zero, insert the time unmodified. Useful rounding numbers
1223 should be factors of 60, so for example 5, 10, 15.
1224 When this is not zero, you can still force an exact time-stamp by using
1225 a double prefix argument to a time-stamp command like `C-c .' or `C-c !'."
1226 :group 'org-time
1227 :type 'integer)
1228
1229 (defcustom org-deadline-warning-days 30
1230 "No. of days before expiration during which a deadline becomes active.
1231 This variable governs the display in the org file."
1232 :group 'org-time
1233 :type 'number)
1234
1235 (defcustom org-popup-calendar-for-date-prompt t
1236 "Non-nil means, pop up a calendar when prompting for a date.
1237 In the calendar, the date can be selected with mouse-1. However, the
1238 minibuffer will also be active, and you can simply enter the date as well.
1239 When nil, only the minibuffer will be available."
1240 :group 'org-time
1241 :type 'boolean)
1242
1243 (defcustom org-calendar-follow-timestamp-change t
1244 "Non-nil means, make the calendar window follow timestamp changes.
1245 When a timestamp is modified and the calendar window is visible, it will be
1246 moved to the new date."
1247 :group 'org-time
1248 :type 'boolean)
1249
1250 (defgroup org-tags nil
1251 "Options concerning tags in Org-mode."
1252 :tag "Org Tags"
1253 :group 'org)
1254
1255 (defcustom org-tag-alist nil
1256 "List of tags allowed in Org-mode files.
1257 When this list is nil, Org-mode will base TAG input on what is already in the
1258 buffer.
1259 The value of this variable is an alist, the car may be (and should) be a
1260 character that is used to select that tag through the fast-tag-selection
1261 interface. See the manual for details."
1262 :group 'org-tags
1263 :type '(repeat
1264 (cons (character) (string :tag "Tag"))))
1265
1266 (defcustom org-use-fast-tag-selection 'auto
1267 "Non-nil means, use fast tag selection scheme.
1268 This is a special interface to select and deselect tags with single keys.
1269 When nil, fast selection is never used.
1270 When the symbol `auto', fast selection is used if and only if selection
1271 characters for tags have been configured, either through the variable
1272 `org-tag-alist' or through a #+TAGS line in the buffer.
1273 When t, fast selection is always used and selection keys are assigned
1274 automatically if necessary."
1275 :group 'org-tags
1276 :type '(choice
1277 (const :tag "Always" t)
1278 (const :tag "Never" nil)
1279 (const :tag "When selection characters are configured" 'auto)))
1280
1281 (defcustom org-tags-column 48
1282 "The column to which tags should be indented in a headline.
1283 If this number is positive, it specifies the column. If it is negative,
1284 it means that the tags should be flushright to that column. For example,
1285 -79 works well for a normal 80 character screen."
1286 :group 'org-tags
1287 :type 'integer)
1288
1289 (defcustom org-auto-align-tags t
1290 "Non-nil means, realign tags after pro/demotion of TODO state change.
1291 These operations change the length of a headline and therefore shift
1292 the tags around. With this options turned on, after each such operation
1293 the tags are again aligned to `org-tags-column'."
1294 :group 'org-tags
1295 :type 'boolean)
1296
1297 (defcustom org-use-tag-inheritance t
1298 "Non-nil means, tags in levels apply also for sublevels.
1299 When nil, only the tags directly given in a specific line apply there.
1300 If you turn off this option, you very likely want to turn on the
1301 companion option `org-tags-match-list-sublevels'."
1302 :group 'org-tags
1303 :type 'boolean)
1304
1305 (defcustom org-tags-match-list-sublevels nil
1306 "Non-nil means list also sublevels of headlines matching tag search.
1307 Because of tag inheritance (see variable `org-use-tag-inheritance'),
1308 the sublevels of a headline matching a tag search often also match
1309 the same search. Listing all of them can create very long lists.
1310 Setting this variable to nil causes subtrees of a match to be skipped.
1311 This option is off by default, because inheritance in on. If you turn
1312 inheritance off, you very likely want to turn this option on.
1313
1314 As a special case, if the tag search is restricted to TODO items, the
1315 value of this variable is ignored and sublevels are always checked, to
1316 make sure all corresponding TODO items find their way into the list."
1317 :group 'org-tags
1318 :type 'boolean)
1319
1320 (defvar org-tags-history nil
1321 "History of minibuffer reads for tags.")
1322 (defvar org-last-tags-completion-table nil
1323 "The last used completion table for tags.")
1324
1325 (defgroup org-agenda nil
1326 "Options concerning agenda display Org-mode."
1327 :tag "Org Agenda"
1328 :group 'org)
1329
1330 (defvar org-category nil
1331 "Variable used by org files to set a category for agenda display.
1332 Such files should use a file variable to set it, for example
1333
1334 -*- mode: org; org-category: \"ELisp\"
1335
1336 or contain a special line
1337
1338 #+CATEGORY: ELisp
1339
1340 If the file does not specify a category, then file's base name
1341 is used instead.")
1342 (make-variable-buffer-local 'org-category)
1343
1344 (defcustom org-agenda-files nil
1345 "The files to be used for agenda display.
1346 Entries may be added to this list with \\[org-agenda-file-to-front] and removed with
1347 \\[org-remove-file]. You can also use customize to edit the list.
1348
1349 If the value of the variable is not a list but a single file name, then
1350 the list of agenda files is actually stored and maintained in that file, one
1351 agenda file per line."
1352 :group 'org-agenda
1353 :type '(choice
1354 (repeat :tag "List of files" file)
1355 (file :tag "Store list in a file\n" :value "~/.agenda_files")))
1356
1357 (defcustom org-agenda-custom-commands '(("w" todo "WAITING"))
1358 "Custom commands for the agenda.
1359 These commands will be offered on the splash screen displayed by the
1360 agenda dispatcher \\[org-agenda]. Each entry is a list of 3 items:
1361
1362 key The key (a single char as a string) to be associated with the command.
1363 type The command type, any of the following symbols:
1364 todo Entries with a specific TODO keyword, in all agenda files.
1365 tags Tags match in all agenda files.
1366 tags-todo Tags match in all agenda files, TODO entries only.
1367 todo-tree Sparse tree of specific TODO keyword in *current* file.
1368 tags-tree Sparse tree with all tags matches in *current* file.
1369 occur-tree Occur sparse tree for current file.
1370 match What to search for:
1371 - a single keyword for TODO keyword searches
1372 - a tags match expression for tags searches
1373 - a regular expression for occur searches"
1374 :group 'org-agenda
1375 :type '(repeat
1376 (list (string :tag "Key")
1377 (choice :tag "Type"
1378 (const :tag "Tags search in all agenda files" tags)
1379 (const :tag "Tags search of TODO entries, all agenda files" tags-todo)
1380 (const :tag "TODO keyword search in all agenda files" todo)
1381 (const :tag "Tags sparse tree in current buffer" tags-tree)
1382 (const :tag "TODO keyword tree in current buffer" todo-tree)
1383 (const :tag "Occur tree in current buffer" occur-tree))
1384 (string :tag "Match"))))
1385
1386 ;; FIXME: Need a toggle for this variable, maybe a mode in the agenda buffer?
1387 (defcustom org-agenda-todo-list-sublevels t
1388 "Non-nil means, check also the sublevels of a TODO entry for TODO entries.
1389 When nil, the sublevels of a TODO entry are not checked, resulting in
1390 potentially much shorter TODO lists."
1391 :group 'org-agenda
1392 :group 'org-todo
1393 :type 'boolean)
1394
1395 (defcustom org-agenda-todo-ignore-scheduled nil
1396 "Non-nil means, don't show scheduled entries in the global todo list.
1397 The idea behind this is that by scheduling it, you have already taken care
1398 of this item."
1399 :group 'org-agenda
1400 :group 'org-todo
1401 :type 'boolean)
1402
1403 (defcustom org-agenda-include-all-todo nil
1404 "Non-nil means, the agenda will always contain all TODO entries.
1405 When nil, date-less entries will only be shown if `org-agenda' is called
1406 with a prefix argument.
1407 When non-nil, the TODO entries will be listed at the top of the agenda, before
1408 the entries for specific days."
1409 :group 'org-agenda
1410 :type 'boolean)
1411
1412 (defcustom org-agenda-include-diary nil
1413 "If non-nil, include in the agenda entries from the Emacs Calendar's diary."
1414 :group 'org-agenda
1415 :type 'boolean)
1416
1417 (defcustom org-calendar-to-agenda-key [?c]
1418 "The key to be installed in `calendar-mode-map' for switching to the agenda.
1419 The command `org-calendar-goto-agenda' will be bound to this key. The
1420 default is the character `c' because then `c' can be used to switch back and
1421 forth between agenda and calendar."
1422 :group 'org-agenda
1423 :type 'sexp)
1424
1425 (defgroup org-agenda-setup nil
1426 "Options concerning setting up the Agenda window in Org Mode."
1427 :tag "Org Agenda Window Setup"
1428 :group 'org-agenda)
1429
1430 (defcustom org-agenda-mouse-1-follows-link nil
1431 "Non-nil means, mouse-1 on a link will follow the link in the agenda.
1432 A longer mouse click will still set point. Does not wortk on XEmacs.
1433 Needs to be set before org.el is loaded."
1434 :group 'org-agenda-setup
1435 :type 'boolean)
1436
1437 (defcustom org-agenda-start-with-follow-mode nil
1438 "The initial value of follwo-mode in a newly created agenda window."
1439 :group 'org-agenda-setup
1440 :type 'boolean)
1441
1442 (defcustom org-select-agenda-window t
1443 "Non-nil means, after creating an agenda, move cursor into Agenda window.
1444 When nil, cursor will remain in the current window."
1445 :group 'org-agenda-setup
1446 :type 'boolean)
1447
1448 (defcustom org-fit-agenda-window t
1449 "Non-nil means, change window size of agenda to fit content."
1450 :group 'org-agenda-setup
1451 :type 'boolean)
1452
1453 (defgroup org-agenda-display nil
1454 "Options concerning what to display initially in Agenda."
1455 :tag "Org Agenda Display"
1456 :group 'org-agenda)
1457
1458 (defcustom org-agenda-show-all-dates t
1459 "Non-nil means, `org-agenda' shows every day in the selected range.
1460 When nil, only the days which actually have entries are shown."
1461 :group 'org-agenda-display
1462 :type 'boolean)
1463
1464 (defcustom org-agenda-start-on-weekday 1
1465 "Non-nil means, start the overview always on the specified weekday.
1466 0 denotes Sunday, 1 denotes Monday etc.
1467 When nil, always start on the current day."
1468 :group 'org-agenda-display
1469 :type '(choice (const :tag "Today" nil)
1470 (number :tag "Weekday No.")))
1471
1472 (defcustom org-agenda-ndays 7
1473 "Number of days to include in overview display.
1474 Should be 1 or 7."
1475 :group 'org-agenda-display
1476 :type 'number)
1477
1478 (defcustom org-agenda-use-time-grid t
1479 "Non-nil means, show a time grid in the agenda schedule.
1480 A time grid is a set of lines for specific times (like every two hours between
1481 8:00 and 20:00). The items scheduled for a day at specific times are
1482 sorted in between these lines.
1483 For details about when the grid will be shown, and what it will look like, see
1484 the variable `org-agenda-time-grid'."
1485 :group 'org-agenda-display
1486 :type 'boolean)
1487
1488 (defcustom org-agenda-time-grid
1489 '((daily today require-timed)
1490 "----------------"
1491 (800 1000 1200 1400 1600 1800 2000))
1492
1493 "The settings for time grid for agenda display.
1494 This is a list of three items. The first item is again a list. It contains
1495 symbols specifying conditions when the grid should be displayed:
1496
1497 daily if the agenda shows a single day
1498 weekly if the agenda shows an entire week
1499 today show grid on current date, independent of daily/weekly display
1500 require-timed show grid only if at least on item has a time specification
1501
1502 The second item is a string which will be places behing the grid time.
1503
1504 The third item is a list of integers, indicating the times that should have
1505 a grid line."
1506 :group 'org-agenda-display
1507 :type
1508 '(list
1509 (set :greedy t :tag "Grid Display Options"
1510 (const :tag "Show grid in single day agenda display" daily)
1511 (const :tag "Show grid in weekly agenda display" weekly)
1512 (const :tag "Always show grid for today" today)
1513 (const :tag "Show grid only if any timed entries are present"
1514 require-timed)
1515 (const :tag "Skip grid times already present in an entry"
1516 remove-match))
1517 (string :tag "Grid String")
1518 (repeat :tag "Grid Times" (integer :tag "Time"))))
1519
1520 (defcustom org-agenda-sorting-strategy '(time-up category-keep priority-down)
1521 "Sorting structure for the agenda items of a single day.
1522 This is a list of symbols which will be used in sequence to determine
1523 if an entry should be listed before another entry. The following
1524 symbols are recognized:
1525
1526 time-up Put entries with time-of-day indications first, early first
1527 time-down Put entries with time-of-day indications first, late first
1528 category-keep Keep the default order of categories, corresponding to the
1529 sequence in `org-agenda-files'.
1530 category-up Sort alphabetically by category, A-Z.
1531 category-down Sort alphabetically by category, Z-A.
1532 priority-up Sort numerically by priority, high priority last.
1533 priority-down Sort numerically by priority, high priority first.
1534
1535 The different possibilities will be tried in sequence, and testing stops
1536 if one comparison returns a \"not-equal\". For example, the default
1537 '(time-up category-keep priority-down)
1538 means: Pull out all entries having a specified time of day and sort them,
1539 in order to make a time schedule for the current day the first thing in the
1540 agenda listing for the day. Of the entries without a time indication, keep
1541 the grouped in categories, don't sort the categories, but keep them in
1542 the sequence given in `org-agenda-files'. Within each category sort by
1543 priority.
1544
1545 Leaving out `category-keep' would mean that items will be sorted across
1546 categories by priority."
1547 :group 'org-agenda-display
1548 :type '(repeat
1549 (choice
1550 (const time-up)
1551 (const time-down)
1552 (const category-keep)
1553 (const category-up)
1554 (const category-down)
1555 (const priority-up)
1556 (const priority-down))))
1557
1558 (defcustom org-sort-agenda-notime-is-late t
1559 "Non-nil means, items without time are considered late.
1560 This is only relevant for sorting. When t, items which have no explicit
1561 time like 15:30 will be considered as 24:01, i.e. later than any items which
1562 do have a time. When nil, the default time is before 0:00. You can use this
1563 option to decide if the schedule for today should come before or after timeless
1564 agenda entries."
1565 :group 'org-agenda-display
1566 :type 'boolean)
1567
1568
1569 (defgroup org-agenda-prefix nil
1570 "Options concerning the entry prefix in the Org-mode agenda display."
1571 :tag "Org Agenda Prefix"
1572 :group 'org-agenda)
1573
1574 (defcustom org-agenda-prefix-format " %-12:c%?-12t% s"
1575 "Format specification for the prefix of items in the agenda buffer.
1576 This format works similar to a printf format, with the following meaning:
1577
1578 %c the category of the item, \"Diary\" for entries from the diary, or
1579 as given by the CATEGORY keyword or derived from the file name.
1580 %T the first tag of the item.
1581 %t the time-of-day specification if one applies to the entry, in the
1582 format HH:MM
1583 %s Scheduling/Deadline information, a short string
1584
1585 All specifiers work basically like the standard `%s' of printf, but may
1586 contain two additional characters: A question mark just after the `%' and
1587 a whitespace/punctuation character just before the final letter.
1588
1589 If the first character after `%' is a question mark, the entire field
1590 will only be included if the corresponding value applies to the
1591 current entry. This is useful for fields which should have fixed
1592 width when present, but zero width when absent. For example,
1593 \"%?-12t\" will result in a 12 character time field if a time of the
1594 day is specified, but will completely disappear in entries which do
1595 not contain a time.
1596
1597 If there is punctuation or whitespace character just before the final
1598 format letter, this character will be appended to the field value if
1599 the value is not empty. For example, the format \"%-12:c\" leads to
1600 \"Diary: \" if the category is \"Diary\". If the category were be
1601 empty, no additional colon would be interted.
1602
1603 The default value of this option is \" %-12:c%?-12t% s\", meaning:
1604 - Indent the line with two space characters
1605 - Give the category in a 12 chars wide field, padded with whitespace on
1606 the right (because of `-'). Append a colon if there is a category
1607 (because of `:').
1608 - If there is a time-of-day, put it into a 12 chars wide field. If no
1609 time, don't put in an empty field, just skip it (because of '?').
1610 - Finally, put the scheduling information and append a whitespace.
1611
1612 As another example, if you don't want the time-of-day of entries in
1613 the prefix, you could use:
1614
1615 (setq org-agenda-prefix-format \" %-11:c% s\")
1616
1617 See also the variables `org-agenda-remove-times-when-in-prefix' and
1618 `org-agenda-remove-tags-when-in-prefix'."
1619 :type 'string
1620 :group 'org-agenda-prefix)
1621
1622 (defvar org-prefix-format-compiled nil
1623 "The compiled version of the most recently used prefix format.
1624 Depending on which command was used last, this may be the compiled version
1625 of `org-agenda-prefix-format' or `org-timeline-prefix-format'.")
1626
1627 ;; FIXME: There seem to be situations where this does not work.
1628 (defcustom org-agenda-remove-times-when-in-prefix t
1629 "Non-nil means, remove duplicate time specifications in agenda items.
1630 When the format `org-agenda-prefix-format' contains a `%t' specifier, a
1631 time-of-day specification in a headline or diary entry is extracted and
1632 placed into the prefix. If this option is non-nil, the original specification
1633 \(a timestamp or -range, or just a plain time(range) specification like
1634 11:30-4pm) will be removed for agenda display. This makes the agenda less
1635 cluttered.
1636 The option can be t or nil. It may also be the symbol `beg', indicating
1637 that the time should only be removed what it is located at the beginning of
1638 the headline/diary entry."
1639 :group 'org-agenda-prefix
1640 :type '(choice
1641 (const :tag "Always" t)
1642 (const :tag "Never" nil)
1643 (const :tag "When at beginning of entry" beg)))
1644
1645 (defcustom org-agenda-remove-tags-when-in-prefix nil
1646 "Non-nil means, remove the tags from the headline copy in the agenda.
1647 When this is the symbol `prefix', only remove tags when
1648 `org-agenda-prefix-format' contains a `%T' specifier."
1649 :group 'org-agenda-prefix
1650 :type '(choice
1651 (const :tag "Always" t)
1652 (const :tag "Never" nil)
1653 (const :tag "When prefix format contains %T" prefix)))
1654
1655 (defgroup org-agenda-timeline nil
1656 "Options concerning the timeline buffer in Org Mode."
1657 :tag "Org Agenda Timeline"
1658 :group 'org-agenda)
1659
1660 (defcustom org-timeline-prefix-format " % s"
1661 "Like `org-agenda-prefix-format', but for the timeline of a single file."
1662 :type 'string
1663 :group 'org-agenda-timeline)
1664
1665 (defcustom org-select-timeline-window t
1666 "Non-nil means, after creating a timeline, move cursor into Timeline window.
1667 When nil, cursor will remain in the current window."
1668 :group 'org-agenda-timeline
1669 :type 'boolean)
1670
1671 (defcustom org-timeline-show-empty-dates 3
1672 "Non-nil means, `org-timeline' also shows dates without an entry.
1673 When nil, only the days which actually have entries are shown.
1674 When t, all days between the first and the last date are shown.
1675 When an integer, show also empty dates, but if there is a gap of more than
1676 N days, just insert a special line indicating the size of the gap."
1677 :group 'org-agenda-timeline
1678 :type '(choice
1679 (const :tag "None" nil)
1680 (const :tag "All" t)
1681 (number :tag "at most")))
1682
1683 (defgroup org-export nil
1684 "Options for exporting org-listings."
1685 :tag "Org Export"
1686 :group 'org)
1687
1688 (defgroup org-export-general nil
1689 "General options for exporting Org-mode files."
1690 :tag "Org Export General"
1691 :group 'org-export)
1692
1693 (defcustom org-export-publishing-directory "."
1694 "Path to the location where exported files should be located.
1695 This path may be relative to the directory where the Org-mode file lives.
1696 The default is to put them into the same directory as the Org-mode file.
1697 The variable may also be an alist with export types `:html', `:ascii',
1698 `:ical', or `:xoxo' and the corresponding directories. If a direcoty path
1699 is relative, it is interpreted relative to the directory where the exported
1700 Org-mode files lives."
1701 :group 'org-export-general
1702 :type '(choice
1703 (directory)
1704 (repeat
1705 (cons
1706 (choice :tag "Type"
1707 (const :html) (const :ascii) (const :ical) (const :xoxo))
1708 (directory)))))
1709
1710 (defcustom org-export-language-setup
1711 '(("en" "Author" "Date" "Table of Contents")
1712 ("da" "Ophavsmand" "Dato" "Indhold")
1713 ("de" "Autor" "Datum" "Inhaltsverzeichnis")
1714 ("es" "Autor" "Fecha" "\xccndice")
1715 ("fr" "Auteur" "Date" "Table des Mati\xe8res")
1716 ("it" "Autore" "Data" "Indice")
1717 ("nl" "Auteur" "Datum" "Inhoudsopgave")
1718 ("nn" "Forfattar" "Dato" "Innhold") ;; nn = Norsk (nynorsk)
1719 ("sv" "F\xf6rfattarens" "Datum" "Inneh\xe5ll"))
1720 "Terms used in export text, translated to different languages.
1721 Use the variable `org-export-default-language' to set the language,
1722 or use the +OPTION lines for a per-file setting."
1723 :group 'org-export-general
1724 :type '(repeat
1725 (list
1726 (string :tag "HTML language tag")
1727 (string :tag "Author")
1728 (string :tag "Date")
1729 (string :tag "Table of Contents"))))
1730
1731 (defcustom org-export-default-language "en"
1732 "The default language of HTML export, as a string.
1733 This should have an association in `org-export-language-setup'."
1734 :group 'org-export-general
1735 :type 'string)
1736
1737 (defcustom org-export-headline-levels 3
1738 "The last level which is still exported as a headline.
1739 Inferior levels will produce itemize lists when exported.
1740 Note that a numeric prefix argument to an exporter function overrides
1741 this setting.
1742
1743 This option can also be set with the +OPTIONS line, e.g. \"H:2\"."
1744 :group 'org-export-general
1745 :type 'number)
1746
1747 (defcustom org-export-with-section-numbers t
1748 "Non-nil means, add section numbers to headlines when exporting.
1749
1750 This option can also be set with the +OPTIONS line, e.g. \"num:t\"."
1751 :group 'org-export-general
1752 :type 'boolean)
1753
1754 (defcustom org-export-with-toc t
1755 "Non-nil means, create a table of contents in exported files.
1756 The TOC contains headlines with levels up to`org-export-headline-levels'.
1757
1758 Headlines which contain any TODO items will be marked with \"(*)\" in
1759 ASCII export, and with red color in HTML output.
1760
1761 In HTML output, the TOC will be clickable.
1762
1763 This option can also be set with the +OPTIONS line, e.g. \"toc:nil\"."
1764 :group 'org-export-general
1765 :type 'boolean)
1766
1767 (defcustom org-export-mark-todo-in-toc nil
1768 "Non-nil means, mark TOC lines that contain any open TODO items."
1769 :group 'org-export-general
1770 :type 'boolean)
1771
1772 (defcustom org-export-preserve-breaks nil
1773 "Non-nil means, preserve all line breaks when exporting.
1774 Normally, in HTML output paragraphs will be reformatted. In ASCII
1775 export, line breaks will always be preserved, regardless of this variable.
1776
1777 This option can also be set with the +OPTIONS line, e.g. \"\\n:t\"."
1778 :group 'org-export-general
1779 :type 'boolean)
1780
1781 (defcustom org-export-with-timestamps t
1782 "Nil means, do not export time stamps and associated keywords."
1783 :group 'org-export
1784 :type 'boolean)
1785
1786 (defcustom org-export-with-tags t
1787 "Nil means, do not export tags, just remove them from headlines."
1788 :group 'org-export-general
1789 :type 'boolean)
1790
1791 (defcustom org-export-with-timestamps t
1792 "Nil means, do not export timestamps and associated keywords."
1793 :group 'org-export-general
1794 :type 'boolean)
1795
1796 (defgroup org-export-translation nil
1797 "Options for translating special ascii sequences for the export backends."
1798 :tag "Org Export Translation"
1799 :group 'org-export)
1800
1801 (defcustom org-export-with-emphasize t
1802 "Non-nil means, interpret *word*, /word/, and _word_ as emphasized text.
1803 If the export target supports emphasizing text, the word will be
1804 typeset in bold, italic, or underlined, respectively. Works only for
1805 single words, but you can say: I *really* *mean* *this*.
1806 Not all export backends support this.
1807
1808 This option can also be set with the +OPTIONS line, e.g. \"*:nil\"."
1809 :group 'org-export-translation
1810 :type 'boolean)
1811
1812 (defcustom org-export-with-sub-superscripts t
1813 "Non-nil means, interpret \"_\" and \"^\" for export.
1814 When this option is turned on, you can use TeX-like syntax for sub- and
1815 superscripts. Several characters after \"_\" or \"^\" will be
1816 considered as a single item - so grouping with {} is normally not
1817 needed. For example, the following things will be parsed as single
1818 sub- or superscripts.
1819
1820 10^24 or 10^tau several digits will be considered 1 item.
1821 10^-12 or 10^-tau a leading sign with digits or a word
1822 x^2-y^3 will be read as x^2 - y^3, because items are
1823 terminated by almost any nonword/nondigit char.
1824 x_{i^2} or x^(2-i) braces or parenthesis do grouping.
1825
1826 Still, ambiguity is possible - so when in doubt use {} to enclose the
1827 sub/superscript.
1828 Not all export backends support this, but HTML does.
1829
1830 This option can also be set with the +OPTIONS line, e.g. \"^:nil\"."
1831 :group 'org-export-translation
1832 :type 'boolean)
1833
1834 (defcustom org-export-with-TeX-macros t
1835 "Non-nil means, interpret simple TeX-like macros when exporting.
1836 For example, HTML export converts \\alpha to &alpha; and \\AA to &Aring;.
1837 No only real TeX macros will work here, but the standard HTML entities
1838 for math can be used as macro names as well. For a list of supported
1839 names in HTML export, see the constant `org-html-entities'.
1840 Not all export backends support this.
1841
1842 This option can also be set with the +OPTIONS line, e.g. \"TeX:nil\"."
1843 :group 'org-export-translation
1844 :type 'boolean)
1845
1846 (defcustom org-export-with-fixed-width t
1847 "Non-nil means, lines starting with \":\" will be in fixed width font.
1848 This can be used to have pre-formatted text, fragments of code etc. For
1849 example:
1850 : ;; Some Lisp examples
1851 : (while (defc cnt)
1852 : (ding))
1853 will be looking just like this in also HTML. See also the QUOTE keyword.
1854 Not all export backends support this.
1855
1856 This option can also be set with the +OPTIONS line, e.g. \"::nil\"."
1857 :group 'org-export-translation
1858 :type 'boolean)
1859
1860 (defcustom org-match-sexp-depth 3
1861 "Number of stacked braces for sub/superscript matching.
1862 This has to be set before loading org.el to be effective."
1863 :group 'org-export-translation
1864 :type 'integer)
1865
1866 (defgroup org-export-tables nil
1867 "Options for exporting tables in Org-mode."
1868 :tag "Org Export Tables"
1869 :group 'org-export)
1870
1871 (defcustom org-export-with-tables t
1872 "If non-nil, lines starting with \"|\" define a table.
1873 For example:
1874
1875 | Name | Address | Birthday |
1876 |-------------+----------+-----------|
1877 | Arthur Dent | England | 29.2.2100 |
1878
1879 Not all export backends support this.
1880
1881 This option can also be set with the +OPTIONS line, e.g. \"|:nil\"."
1882 :group 'org-export-tables
1883 :type 'boolean)
1884
1885 (defcustom org-export-highlight-first-table-line t
1886 "Non-nil means, highlight the first table line.
1887 In HTML export, this means use <th> instead of <td>.
1888 In tables created with table.el, this applies to the first table line.
1889 In Org-mode tables, all lines before the first horizontal separator
1890 line will be formatted with <th> tags."
1891 :group 'org-export-tables
1892 :type 'boolean)
1893
1894 (defcustom org-export-table-remove-special-lines t
1895 "Remove special lines and marking characters in calculating tables.
1896 This removes the special marking character column from tables that are set
1897 up for spreadsheet calculations. It also removes the entire lines
1898 marked with `!', `_', or `^'. The lines with `$' are kept, because
1899 the values of constants may be useful to have."
1900 :group 'org-export-tables
1901 :type 'boolean)
1902
1903 (defcustom org-export-prefer-native-exporter-for-tables nil
1904 "Non-nil means, always export tables created with table.el natively.
1905 Natively means, use the HTML code generator in table.el.
1906 When nil, Org-mode's own HTML generator is used when possible (i.e. if
1907 the table does not use row- or column-spanning). This has the
1908 advantage, that the automatic HTML conversions for math symbols and
1909 sub/superscripts can be applied. Org-mode's HTML generator is also
1910 much faster."
1911 :group 'org-export-tables
1912 :type 'boolean)
1913
1914 (defgroup org-export-ascii nil
1915 "Options specific for ASCII export of Org-mode files."
1916 :tag "Org Export ASCII"
1917 :group 'org-export)
1918
1919 (defcustom org-export-ascii-underline '(?\$ ?\# ?^ ?\~ ?\= ?\-)
1920 "Characters for underlining headings in ASCII export.
1921 In the given sequence, these characters will be used for level 1, 2, ..."
1922 :group 'org-export-ascii
1923 :type '(repeat character))
1924
1925 (defcustom org-export-ascii-bullets '(?* ?o ?-)
1926 "Bullet characters for headlines converted to lists in ASCII export.
1927 The first character is is used for the first lest level generated in this
1928 way, and so on. If there are more levels than characters given here,
1929 the list will be repeated.
1930 Note that plain lists will keep the same bullets as the have in the
1931 Org-mode file."
1932 :group 'org-export-ascii
1933 :type '(repeat character))
1934
1935 (defcustom org-export-ascii-show-new-buffer t
1936 "Non-nil means, popup buffer containing the exported ASCII text.
1937 Otherwise the buffer will just be saved to a file and stay hidden."
1938 :group 'org-export-ascii
1939 :type 'boolean)
1940
1941 (defgroup org-export-xml nil
1942 "Options specific for XML export of Org-mode files."
1943 :tag "Org Export XML"
1944 :group 'org-export)
1945
1946 ;; FIXME: I am told XOXO is not XML, it is semantic-only HTML.
1947 (defcustom org-export-xml-type 'xoxo
1948 "The kind of XML to be produced by the XML exporter.
1949 Allowed values are:
1950 xoxo The XOXO exporter."
1951 :group 'org-export-xml
1952 :type '(choice
1953 (const :tag "XOXO" xoxo)))
1954
1955 (defgroup org-export-html nil
1956 "Options specific for HTML export of Org-mode files."
1957 :tag "Org Export HTML"
1958 :group 'org-export)
1959
1960 (defcustom org-export-html-style
1961 "<style type=\"text/css\">
1962 html {
1963 font-family: Times, serif;
1964 font-size: 12pt;
1965 }
1966 .title { text-align: center; }
1967 .todo { color: red; }
1968 .done { color: green; }
1969 .timestamp { color: grey }
1970 .timestamp-kwd { color: CadetBlue }
1971 .tag { background-color:lightblue; font-weight:normal }
1972 .target { background-color: lavender; }
1973 pre {
1974 border: 1pt solid #AEBDCC;
1975 background-color: #F3F5F7;
1976 padding: 5pt;
1977 font-family: courier, monospace;
1978 }
1979 table { border-collapse: collapse; }
1980 td, th {
1981 vertical-align: top;
1982 border: 1pt solid #ADB9CC;
1983 }
1984 </style>"
1985 "The default style specification for exported HTML files.
1986 Since there are different ways of setting style information, this variable
1987 needs to contain the full HTML structure to provide a style, including the
1988 surrounding HTML tags. The style specifications should include definitions
1989 for new classes todo, done, title, and deadline. For example, legal values
1990 would be:
1991
1992 <style type=\"text/css\">
1993 p { font-weight: normal; color: gray; }
1994 h1 { color: black; }
1995 .title { text-align: center; }
1996 .todo, .deadline { color: red; }
1997 .done { color: green; }
1998 </style>
1999
2000 or, if you want to keep the style in a file,
2001
2002 <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\">
2003
2004 As the value of this option simply gets inserted into the HTML <head> header,
2005 you can \"misuse\" it to add arbitrary text to the header."
2006 :group 'org-export-html
2007 :type 'string)
2008
2009 (defcustom org-export-html-link-org-files-as-html t
2010 "Non-nil means, make file links to `file.org' point to `file.html'.
2011 When org-mode is exporting an org-mode file to HTML, links to
2012 non-html files are directly put into a href tag in HTML.
2013 However, links to other Org-mode files (recognized by the
2014 extension `.org.) should become links to the corresponding html
2015 file, assuming that the linked org-mode file will also be
2016 converted to HTML.
2017 When nil, the links still point to the plain `.org' file."
2018 :group 'org-export-html
2019 :type 'boolean)
2020
2021 (defcustom org-export-html-inline-images 'maybe
2022 "Non-nil means, inline images into exported HTML pages.
2023 This is done using an <img> tag. When nil, an anchor with href is used to
2024 link to the image. If this option is `maybe', then images in links with
2025 an empty description will be inlined, while images with a description will
2026 be linked only."
2027 :group 'org-export-html
2028 :type '(choice (const :tag "Never" nil)
2029 (const :tag "Always" t)
2030 (const :tag "When there is no description" maybe)))
2031
2032 (defcustom org-export-html-expand t
2033 "Non-nil means, for HTML export, treat @<...> as HTML tag.
2034 When nil, these tags will be exported as plain text and therefore
2035 not be interpreted by a browser.
2036
2037 This option can also be set with the +OPTIONS line, e.g. \"@:nil\"."
2038 :group 'org-export-html
2039 :type 'boolean)
2040
2041 (defcustom org-export-html-table-tag
2042 "<table border=\"1\" cellspacing=\"0\" cellpadding=\"6\">"
2043 "The HTML tag used to start a table.
2044 This must be a <table> tag, but you may change the options like
2045 borders and spacing."
2046 :group 'org-export-html
2047 :type 'string)
2048
2049 (defcustom org-export-html-with-timestamp nil
2050 "If non-nil, write `org-export-html-html-helper-timestamp'
2051 into the exported HTML text. Otherwise, the buffer will just be saved
2052 to a file."
2053 :group 'org-export-html
2054 :type 'boolean)
2055
2056 ;; FIXME: <br><br> is not pretty.
2057 (defcustom org-export-html-html-helper-timestamp
2058 "<br/><br/><hr><p><!-- hhmts start --> <!-- hhmts end --></p>\n"
2059 "The HTML tag used as timestamp delimiter for HTML-helper-mode."
2060 :group 'org-export-html
2061 :type 'string)
2062
2063 (defcustom org-export-html-show-new-buffer nil
2064 "Non-nil means, popup buffer containing the exported html text.
2065 Otherwise, the buffer will just be saved to a file and stay hidden."
2066 :group 'org-export-html
2067 :type 'boolean)
2068
2069 (defgroup org-export-icalendar nil
2070 "Options specific for iCalendar export of Org-mode files."
2071 :tag "Org Export iCalendar"
2072 :group 'org-export)
2073
2074 (defcustom org-combined-agenda-icalendar-file "~/org.ics"
2075 "The file name for the iCalendar file covering all agenda files.
2076 This file is created with the command \\[org-export-icalendar-all-agenda-files].
2077 The file name should be absolute."
2078 :group 'org-export-icalendar
2079 :type 'file)
2080
2081 (defcustom org-icalendar-include-todo nil
2082 "Non-nil means, export to iCalendar files should also cover TODO items."
2083 :group 'org-export-icalendar
2084 :type 'boolean)
2085
2086 (defcustom org-icalendar-combined-name "OrgMode"
2087 "Calendar name for the combined iCalendar representing all agenda files."
2088 :group 'org-export-icalendar
2089 :type 'string)
2090
2091 (defgroup org-font-lock nil
2092 "Font-lock settings for highlighting in Org-mode."
2093 :tag "Org Font Lock"
2094 :group 'org)
2095
2096 (defcustom org-level-color-stars-only nil
2097 "Non-nil means fontify only the stars in each headline.
2098 When nil, the entire headline is fontified.
2099 Changing it requires restart of `font-lock-mode' to become effective
2100 also in regions already fontified."
2101 :group 'org-font-lock
2102 :type 'boolean)
2103
2104 (defcustom org-hide-leading-stars nil
2105 "Non-nil means, hide the first N-1 stars in a headline.
2106 This works by using the face `org-hide' for these stars. This
2107 face is white for a light background, and black for a dark
2108 background. You may have to customize the face `org-hide' to
2109 make this work.
2110 Changing it requires restart of `font-lock-mode' to become effective
2111 also in regions already fontified.
2112 You may also set this on a per-file basis by adding one of the following
2113 lines to the buffer:
2114
2115 #+STARTUP: hidestars
2116 #+STARTUP: showstars"
2117 :group 'org-font-lock
2118 :type 'boolean)
2119
2120 (defcustom org-fontify-done-headline nil
2121 "Non-nil means, change the face of a headline if it is marked DONE.
2122 Normally, only the TODO/DONE keyword indicates the state of a headline.
2123 When this is non-nil, the headline after the keyword is set to the
2124 `org-headline-done' as an additional indication."
2125 :group 'org-font-lock
2126 :type 'boolean)
2127
2128 (defcustom org-fontify-emphasized-text t
2129 "Non-nil means fontify *bold*, /italic/ and _underlined_ text.
2130 Changing this variable requires a restart of Emacs to take effect."
2131 :group 'org-font-lock
2132 :type 'boolean)
2133
2134 (defgroup org-faces nil
2135 "Faces in Org-mode."
2136 :tag "Org Faces"
2137 :group 'org-font-lock)
2138
2139 (defun org-compatible-face (specs)
2140 "Make a compatible face specification.
2141 XEmacs and Emacs 21 do not know about the `min-colors' attribute.
2142 For them we convert a (min-colors 8) entry to a `tty' entry and move it
2143 to the top of the list. The `min-colors' attribute will be removed from
2144 any other entries, and any resulting duplicates will be removed entirely."
2145 (if (or (featurep 'xemacs) (< emacs-major-version 22))
2146 (let (r e a)
2147 (while (setq e (pop specs))
2148 (cond
2149 ((memq (car e) '(t default)) (push e r))
2150 ((setq a (member '(min-colors 8) (car e)))
2151 (nconc r (list (cons (cons '(type tty) (delq (car a) (car e)))
2152 (cdr e)))))
2153 ((setq a (assq 'min-colors (car e)))
2154 (setq e (cons (delq a (car e)) (cdr e)))
2155 (or (assoc (car e) r) (push e r)))
2156 (t (or (assoc (car e) r) (push e r)))))
2157 (nreverse r))
2158 specs))
2159
2160 (defface org-hide
2161 '((((background light)) (:foreground "white"))
2162 (((background dark)) (:foreground "black")))
2163 "Face used to hide leading stars in headlines.
2164 The forground color of this face should be equal to the background
2165 color of the frame."
2166 :group 'org-faces)
2167
2168 (defface org-level-1 ;; font-lock-function-name-face
2169 (org-compatible-face
2170 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
2171 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
2172 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
2173 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
2174 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
2175 (t (:bold t))))
2176 "Face used for level 1 headlines."
2177 :group 'org-faces)
2178
2179 (defface org-level-2 ;; font-lock-variable-name-face
2180 (org-compatible-face
2181 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
2182 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
2183 (((class color) (min-colors 8) (background light)) (:foreground "yellow"))
2184 (((class color) (min-colors 8) (background dark)) (:foreground "yellow" :bold t))
2185 (t (:bold t))))
2186 "Face used for level 2 headlines."
2187 :group 'org-faces)
2188
2189 (defface org-level-3 ;; font-lock-keyword-face
2190 (org-compatible-face
2191 '((((class color) (min-colors 88) (background light)) (:foreground "Purple"))
2192 (((class color) (min-colors 88) (background dark)) (:foreground "Cyan1"))
2193 (((class color) (min-colors 16) (background light)) (:foreground "Purple"))
2194 (((class color) (min-colors 16) (background dark)) (:foreground "Cyan"))
2195 (((class color) (min-colors 8) (background light)) (:foreground "purple" :bold t))
2196 (((class color) (min-colors 8) (background dark)) (:foreground "cyan" :bold t))
2197 (t (:bold t))))
2198 "Face used for level 3 headlines."
2199 :group 'org-faces)
2200
2201 (defface org-level-4 ;; font-lock-comment-face
2202 (org-compatible-face
2203 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2204 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2205 (((class color) (min-colors 16) (background light)) (:foreground "red"))
2206 (((class color) (min-colors 16) (background dark)) (:foreground "red1"))
2207 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
2208 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2209 (t (:bold t))))
2210 "Face used for level 4 headlines."
2211 :group 'org-faces)
2212
2213 (defface org-level-5 ;; font-lock-type-face
2214 (org-compatible-face
2215 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
2216 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
2217 (((class color) (min-colors 8)) (:foreground "green"))))
2218 "Face used for level 5 headlines."
2219 :group 'org-faces)
2220
2221 (defface org-level-6 ;; font-lock-constant-face
2222 (org-compatible-face
2223 '((((class color) (min-colors 16) (background light)) (:foreground "CadetBlue"))
2224 (((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine"))
2225 (((class color) (min-colors 8)) (:foreground "magenta"))))
2226 "Face used for level 6 headlines."
2227 :group 'org-faces)
2228
2229 (defface org-level-7 ;; font-lock-builtin-face
2230 (org-compatible-face
2231 '((((class color) (min-colors 16) (background light)) (:foreground "Orchid"))
2232 (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue"))
2233 (((class color) (min-colors 8)) (:foreground "blue"))))
2234 "Face used for level 7 headlines."
2235 :group 'org-faces)
2236
2237 (defface org-level-8 ;; font-lock-string-face
2238 (org-compatible-face
2239 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
2240 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
2241 (((class color) (min-colors 8)) (:foreground "green"))))
2242 "Face used for level 8 headlines."
2243 :group 'org-faces)
2244
2245 (defface org-special-keyword ;; font-lock-string-face
2246 (org-compatible-face
2247 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
2248 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
2249 (t (:italic t))))
2250 "Face used for special keywords."
2251 :group 'org-faces)
2252
2253 (defface org-warning ;; font-lock-warning-face
2254 (org-compatible-face
2255 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
2256 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
2257 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
2258 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2259 (t (:bold t))))
2260 "Face for deadlines and TODO keywords."
2261 :group 'org-faces)
2262
2263 (defface org-headline-done ;; font-lock-string-face
2264 (org-compatible-face
2265 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
2266 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
2267 (((class color) (min-colors 8) (background light)) (:bold nil))))
2268 "Face used to indicate that a headline is DONE.
2269 This face is only used if `org-fontify-done-headline' is set."
2270 :group 'org-faces)
2271
2272 (defface org-link
2273 '((((class color) (background light)) (:foreground "Purple" :underline t))
2274 (((class color) (background dark)) (:foreground "Cyan" :underline t))
2275 (t (:underline t)))
2276 "Face for links."
2277 :group 'org-faces)
2278
2279 (defface org-date
2280 '((((class color) (background light)) (:foreground "Purple" :underline t))
2281 (((class color) (background dark)) (:foreground "Cyan" :underline t))
2282 (t (:underline t)))
2283 "Face for links."
2284 :group 'org-faces)
2285
2286 (defface org-tag
2287 '((t (:bold t)))
2288 "Face for tags."
2289 :group 'org-faces)
2290
2291 (defface org-todo ;; font-lock-warning-face
2292 (org-compatible-face
2293 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
2294 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
2295 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
2296 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2297 (t (:inverse-video t :bold t))))
2298 "Face for TODO keywords."
2299 :group 'org-faces)
2300
2301 (defface org-done ;; font-lock-type-face
2302 (org-compatible-face
2303 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
2304 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
2305 (((class color) (min-colors 8)) (:foreground "green"))
2306 (t (:bold t))))
2307 "Face used for DONE."
2308 :group 'org-faces)
2309
2310 (defface org-table ;; font-lock-function-name-face
2311 (org-compatible-face
2312 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
2313 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
2314 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
2315 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
2316 (((class color) (min-colors 8) (background light)) (:foreground "blue"))
2317 (((class color) (min-colors 8) (background dark)))))
2318 "Face used for tables."
2319 :group 'org-faces)
2320
2321 (defface org-formula
2322 (org-compatible-face
2323 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2324 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2325 (((class color) (min-colors 8) (background light)) (:foreground "red"))
2326 (((class color) (min-colors 8) (background dark)) (:foreground "red"))
2327 (t (:bold t :italic t))))
2328 "Face for formulas."
2329 :group 'org-faces)
2330
2331 (defface org-scheduled-today
2332 (org-compatible-face
2333 '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen"))
2334 (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen"))
2335 (((class color) (min-colors 8)) (:foreground "green"))
2336 (t (:bold t :italic t))))
2337 "Face for items scheduled for a certain day."
2338 :group 'org-faces)
2339
2340 (defface org-scheduled-previously
2341 (org-compatible-face
2342 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2343 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2344 (((class color) (min-colors 8) (background light)) (:foreground "red"))
2345 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2346 (t (:bold t))))
2347 "Face for items scheduled previously, and not yet done."
2348 :group 'org-faces)
2349
2350 (defface org-upcoming-deadline
2351 (org-compatible-face
2352 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2353 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2354 (((class color) (min-colors 8) (background light)) (:foreground "red"))
2355 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2356 (t (:bold t))))
2357 "Face for items scheduled previously, and not yet done."
2358 :group 'org-faces)
2359
2360 (defface org-time-grid ;; font-lock-variable-name-face
2361 (org-compatible-face
2362 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
2363 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
2364 (((class color) (min-colors 8)) (:foreground "yellow" :weight light))))
2365 "Face used for time grids."
2366 :group 'org-faces)
2367
2368 (defconst org-level-faces
2369 '(org-level-1 org-level-2 org-level-3 org-level-4
2370 org-level-5 org-level-6 org-level-7 org-level-8
2371 ))
2372 (defconst org-n-levels (length org-level-faces))
2373
2374 (defconst org-bold-re
2375 (if (featurep 'xemacs)
2376 "\\([ ]\\|^\\)\\(\\*\\(\\w[a-zA-Z0-9-_ ]*?\\w\\)\\*\\)\\([ ,.]\\|$\\)"
2377 "\\([ ]\\|^\\)\\(\\*\\(\\w[[:word:] -_]*?\\w\\)\\*\\)\\([ ,.]\\|$\\)")
2378 "Regular expression for bold emphasis.")
2379 (defconst org-italic-re
2380 (if (featurep 'xemacs)
2381 "\\([ ]\\|^\\)\\(/\\(\\w[a-zA-Z0-9-_ ]*?\\w\\)/\\)\\([ ,.]\\|$\\)"
2382 "\\([ ]\\|^\\)\\(/\\(\\w[[:word:] -_]*?\\w\\)/\\)\\([ ,.]\\|$\\)")
2383 "Regular expression for italic emphasis.")
2384 (defconst org-underline-re
2385 (if (featurep 'xemacs)
2386 "\\([ ]\\|^\\)\\(_\\(\\w[a-zA-Z0-9-_ ]*?\\w\\)_\\)\\([ ,.]\\|$\\)"
2387 "\\([ ]\\|^\\)\\(_\\(\\w[[:word:] -_]*?\\w\\)_\\)\\([ ,.]\\|$\\)")
2388 "Regular expression for underline emphasis.")
2389
2390 ;; Variables for pre-computed regular expressions, all buffer local
2391 (defvar org-done-string nil
2392 "The last string in `org-todo-keywords', indicating an item is DONE.")
2393 (make-variable-buffer-local 'org-done-string)
2394 (defvar org-todo-regexp nil
2395 "Matches any of the TODO state keywords.")
2396 (make-variable-buffer-local 'org-todo-regexp)
2397 (defvar org-not-done-regexp nil
2398 "Matches any of the TODO state keywords except the last one.")
2399 (make-variable-buffer-local 'org-not-done-regexp)
2400 (defvar org-todo-line-regexp nil
2401 "Matches a headline and puts TODO state into group 2 if present.")
2402 (make-variable-buffer-local 'org-todo-line-regexp)
2403 (defvar org-todo-line-tags-regexp nil
2404 "Matches a headline and puts TODO state into group 2 if present.
2405 Also put tags into group 4 if tags are present.")
2406 (make-variable-buffer-local 'org-todo-line-tags-regexp)
2407 (defvar org-nl-done-regexp nil
2408 "Matches newline followed by a headline with the DONE keyword.")
2409 (make-variable-buffer-local 'org-nl-done-regexp)
2410 (defvar org-looking-at-done-regexp nil
2411 "Matches the DONE keyword a point.")
2412 (make-variable-buffer-local 'org-looking-at-done-regexp)
2413 (defvar org-todo-kwd-priority-p nil
2414 "Do TODO items have priorities?")
2415 (make-variable-buffer-local 'org-todo-kwd-priority-p)
2416 (defvar org-todo-kwd-max-priority nil
2417 "Maximum priority of TODO items.")
2418 (make-variable-buffer-local 'org-todo-kwd-max-priority)
2419 (defvar org-ds-keyword-length 12
2420 "Maximum length of the Deadline and SCHEDULED keywords.")
2421 (make-variable-buffer-local 'org-ds-keyword-length)
2422 (defvar org-deadline-regexp nil
2423 "Matches the DEADLINE keyword.")
2424 (make-variable-buffer-local 'org-deadline-regexp)
2425 (defvar org-deadline-time-regexp nil
2426 "Matches the DEADLINE keyword together with a time stamp.")
2427 (make-variable-buffer-local 'org-deadline-time-regexp)
2428 (defvar org-deadline-line-regexp nil
2429 "Matches the DEADLINE keyword and the rest of the line.")
2430 (make-variable-buffer-local 'org-deadline-line-regexp)
2431 (defvar org-scheduled-regexp nil
2432 "Matches the SCHEDULED keyword.")
2433 (make-variable-buffer-local 'org-scheduled-regexp)
2434 (defvar org-scheduled-time-regexp nil
2435 "Matches the SCHEDULED keyword together with a time stamp.")
2436 (make-variable-buffer-local 'org-scheduled-time-regexp)
2437 (defvar org-closed-time-regexp nil
2438 "Matches the CLOSED keyword together with a time stamp.")
2439 (make-variable-buffer-local 'org-closed-time-regexp)
2440
2441 (defvar org-keyword-time-regexp nil
2442 "Matches any of the 3 keywords, together with the time stamp.")
2443 (make-variable-buffer-local 'org-keyword-time-regexp)
2444 (defvar org-maybe-keyword-time-regexp nil
2445 "Matches a timestamp, possibly preceeded by a keyword.")
2446 (make-variable-buffer-local 'org-keyword-time-regexp)
2447
2448 (defconst org-rm-props '(invisible t face t keymap t intangible t mouse-face t
2449 mouse-map t)
2450 "Properties to remove when a string without properties is wanted.")
2451
2452 (defsubst org-match-string-no-properties (num &optional string)
2453 (if (featurep 'xemacs)
2454 (let ((s (match-string num string)))
2455 (remove-text-properties 0 (length s) org-rm-props s)
2456 s)
2457 (match-string-no-properties num string)))
2458
2459 (defsubst org-no-properties (s)
2460 (remove-text-properties 0 (length s) org-rm-props s)
2461 s)
2462
2463 (defun org-set-regexps-and-options ()
2464 "Precompute regular expressions for current buffer."
2465 (when (eq major-mode 'org-mode)
2466 (let ((re (org-make-options-regexp
2467 '("CATEGORY" "SEQ_TODO" "PRI_TODO" "TYP_TODO"
2468 "STARTUP" "ARCHIVE" "TAGS")))
2469 (splitre "[ \t]+")
2470 kwds int key value cat arch tags)
2471 (save-excursion
2472 (save-restriction
2473 (widen)
2474 (goto-char (point-min))
2475 (while (re-search-forward re nil t)
2476 (setq key (match-string 1) value (org-match-string-no-properties 2))
2477 (cond
2478 ((equal key "CATEGORY")
2479 (if (string-match "[ \t]+$" value)
2480 (setq value (replace-match "" t t value)))
2481 (setq cat (intern value)))
2482 ((equal key "SEQ_TODO")
2483 (setq int 'sequence
2484 kwds (append kwds (org-split-string value splitre))))
2485 ((equal key "PRI_TODO")
2486 (setq int 'priority
2487 kwds (append kwds (org-split-string value splitre))))
2488 ((equal key "TYP_TODO")
2489 (setq int 'type
2490 kwds (append kwds (org-split-string value splitre))))
2491 ((equal key "TAGS")
2492 (setq tags (append tags (org-split-string value splitre))))
2493 ((equal key "STARTUP")
2494 (let ((opts (org-split-string value splitre))
2495 (set '(("fold" org-startup-folded t)
2496 ("overview" org-startup-folded t)
2497 ("nofold" org-startup-folded nil)
2498 ("showall" org-startup-folded nil)
2499 ("content" org-startup-folded content)
2500 ("hidestars" org-hide-leading-stars t)
2501 ("showstars" org-hide-leading-stars nil)
2502 ("odd" org-odd-levels-only t)
2503 ("oddeven" org-odd-levels-only nil)
2504 ("align" org-startup-align-all-tables t)
2505 ("noalign" org-startup-align-all-tables nil)
2506 ("logging" org-log-done t)
2507 ("nologging" org-log-done nil)
2508 ("dlcheck" org-startup-with-deadline-check t)
2509 ("nodlcheck" org-startup-with-deadline-check nil)))
2510 l var val)
2511 (while (setq l (assoc (pop opts) set))
2512 (setq var (nth 1 l) val (nth 2 l))
2513 (set (make-local-variable var) val))))
2514 ((equal key "ARCHIVE")
2515 (string-match " *$" value)
2516 (setq arch (replace-match "" t t value))
2517 (remove-text-properties 0 (length arch)
2518 '(face t fontified t) arch)))
2519 )))
2520 (and cat (set (make-local-variable 'org-category) cat))
2521 (and kwds (set (make-local-variable 'org-todo-keywords) kwds))
2522 (and arch (set (make-local-variable 'org-archive-location) arch))
2523 (and int (set (make-local-variable 'org-todo-interpretation) int))
2524 (when tags
2525 (let (e tg c tgs)
2526 (while (setq e (pop tags))
2527 (if (string-match "^\\([0-9a-zA-Z_@]+\\)(\\(.\\))$" e)
2528 (push (cons (match-string 1 e)
2529 (string-to-char (match-string 2 e)))
2530 tgs)
2531 (push (list e) tgs)))
2532 (set (make-local-variable 'org-tag-alist) nil)
2533 (while (setq e (pop tgs))
2534 (or (assoc (car e) org-tag-alist)
2535 (push e org-tag-alist))))))
2536
2537 ;; Compute the regular expressions and other local variables
2538 (setq org-todo-kwd-priority-p (equal org-todo-interpretation 'priority)
2539 org-todo-kwd-max-priority (1- (length org-todo-keywords))
2540 org-ds-keyword-length (+ 2 (max (length org-deadline-string)
2541 (length org-scheduled-string)))
2542 org-done-string
2543 (nth (1- (length org-todo-keywords)) org-todo-keywords)
2544 org-todo-regexp
2545 (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords
2546 "\\|") "\\)\\>")
2547 org-not-done-regexp
2548 (concat "\\<\\("
2549 (mapconcat 'regexp-quote
2550 (nreverse (cdr (reverse org-todo-keywords)))
2551 "\\|")
2552 "\\)\\>")
2553 org-todo-line-regexp
2554 (concat "^\\(\\*+\\)[ \t]*\\("
2555 (mapconcat 'regexp-quote org-todo-keywords "\\|")
2556 "\\)? *\\(.*\\)")
2557 org-nl-done-regexp
2558 (concat "[\r\n]\\*+[ \t]+" org-done-string "\\>")
2559 org-todo-line-tags-regexp
2560 (concat "^\\(\\*+\\)[ \t]*\\("
2561 (mapconcat 'regexp-quote org-todo-keywords "\\|")
2562 "\\)? *\\(.*?\\([ \t]:[a-zA-Z0-9:_@]+:[ \t]*\\)?$\\)")
2563 org-looking-at-done-regexp (concat "^" org-done-string "\\>")
2564 org-deadline-regexp (concat "\\<" org-deadline-string)
2565 org-deadline-time-regexp
2566 (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
2567 org-deadline-line-regexp
2568 (concat "\\<\\(" org-deadline-string "\\).*")
2569 org-scheduled-regexp
2570 (concat "\\<" org-scheduled-string)
2571 org-scheduled-time-regexp
2572 (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
2573 org-closed-time-regexp
2574 (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
2575 org-keyword-time-regexp
2576 (concat "\\<\\(" org-scheduled-string
2577 "\\|" org-deadline-string
2578 "\\|" org-closed-string "\\)"
2579 " *[[<]\\([^]>]+\\)[]>]")
2580 org-maybe-keyword-time-regexp
2581 (concat "\\(\\<\\(" org-scheduled-string
2582 "\\|" org-deadline-string
2583 "\\|" org-closed-string "\\)\\)?"
2584 " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^]\r\n>]*?[]>]\\)"))
2585
2586 (org-set-font-lock-defaults)))
2587
2588 ;; Tell the compiler about dynamically scoped variables,
2589 ;; and variables from other packages
2590 (defvar calc-embedded-close-formula) ; defined by the calc package
2591 (defvar calc-embedded-open-formula) ; defined by the calc package
2592 (defvar font-lock-unfontify-region-function) ; defined by font-lock.el
2593 (defvar zmacs-regions) ; XEmacs regions
2594 (defvar original-date) ; dynamically scoped in calendar
2595 (defvar org-old-auto-fill-inhibit-regexp) ; local variable used by `orgtbl-mode'
2596 (defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized
2597 (defvar org-html-entities) ; defined later in this file
2598 (defvar org-goto-start-pos) ; dynamically scoped parameter
2599 (defvar org-time-was-given) ; dynamically scoped parameter
2600 (defvar org-ts-what) ; dynamically scoped parameter
2601 (defvar mark-active) ; Emacs only, not available in XEmacs.
2602 (defvar timecnt) ; dynamically scoped parameter
2603 (defvar levels-open) ; dynamically scoped parameter
2604 (defvar entry) ; dynamically scoped parameter
2605 (defvar date) ; dynamically scoped parameter
2606 (defvar description) ; dynamically scoped parameter
2607 (defvar ans1) ; dynamically scoped parameter
2608 (defvar ans2) ; dynamically scoped parameter
2609 (defvar starting-day) ; local variable
2610 (defvar include-all-loc) ; local variable
2611 (defvar vm-message-pointer) ; from vm
2612 (defvar vm-folder-directory) ; from vm
2613 (defvar wl-summary-buffer-elmo-folder) ; from wanderlust
2614 (defvar wl-summary-buffer-folder-name) ; from wanderlust
2615 (defvar gnus-group-name) ; from gnus
2616 (defvar gnus-article-current) ; from gnus
2617 (defvar w3m-current-url) ; from w3m
2618 (defvar mh-progs) ; from MH-E
2619 (defvar mh-current-folder) ; from MH-E
2620 (defvar mh-show-folder-buffer) ; from MH-E
2621 (defvar mh-index-folder) ; from MH-E
2622 (defvar mh-searcher) ; from MH-E
2623 (defvar org-selected-point) ; dynamically scoped parameter
2624 (defvar calendar-mode-map) ; from calendar.el
2625 (defvar last-arg) ; local variable
2626 (defvar remember-save-after-remembering) ; from remember.el
2627 (defvar remember-data-file) ; from remember.el
2628 (defvar annotation) ; from remember.el, dynamically scoped in `remember-mode'
2629 (defvar initial) ; from remember.el, dynamically scoped in `remember-mode'
2630 (defvar orgtbl-mode) ; defined later in this file
2631 (defvar Info-current-file) ; from info.el
2632 (defvar Info-current-node) ; from info.el
2633
2634 ;;; Define the mode
2635
2636 (defvar org-mode-map
2637 (if (and (not (keymapp outline-mode-map)) (featurep 'allout))
2638 (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.")
2639 (copy-keymap outline-mode-map))
2640 "Keymap for Org-mode.")
2641
2642 (defvar org-struct-menu) ; defined later in this file
2643 (defvar org-org-menu) ; defined later in this file
2644 (defvar org-tbl-menu) ; defined later in this file
2645
2646 ;; We use a before-change function to check if a table might need
2647 ;; an update.
2648 (defvar org-table-may-need-update t
2649 "Indicates that a table might need an update.
2650 This variable is set by `org-before-change-function'.
2651 `org-table-align' sets it back to nil.")
2652 (defvar org-mode-hook nil)
2653 (defvar org-inhibit-startup nil) ; Dynamically-scoped param.
2654 (defvar org-agenda-keep-modes nil) ; Dynamically-scoped param.
2655
2656
2657 ;;;###autoload
2658 (define-derived-mode org-mode outline-mode "Org"
2659 "Outline-based notes management and organizer, alias
2660 \"Carsten's outline-mode for keeping track of everything.\"
2661
2662 Org-mode develops organizational tasks around a NOTES file which
2663 contains information about projects as plain text. Org-mode is
2664 implemented on top of outline-mode, which is ideal to keep the content
2665 of large files well structured. It supports ToDo items, deadlines and
2666 time stamps, which magically appear in the diary listing of the Emacs
2667 calendar. Tables are easily created with a built-in table editor.
2668 Plain text URL-like links connect to websites, emails (VM), Usenet
2669 messages (Gnus), BBDB entries, and any files related to the project.
2670 For printing and sharing of notes, an Org-mode file (or a part of it)
2671 can be exported as a structured ASCII or HTML file.
2672
2673 The following commands are available:
2674
2675 \\{org-mode-map}"
2676
2677 ;; Get rid of Outline menus, they are not needed
2678 ;; Need to do this here because define-derived-mode sets up
2679 ;; the keymap so late.
2680 (if (featurep 'xemacs)
2681 (if org-noutline-p
2682 (progn
2683 (easy-menu-remove outline-mode-menu-heading)
2684 (easy-menu-remove outline-mode-menu-show)
2685 (easy-menu-remove outline-mode-menu-hide))
2686 (delete-menu-item '("Headings"))
2687 (delete-menu-item '("Show"))
2688 (delete-menu-item '("Hide"))
2689 (set-menubar-dirty-flag))
2690 (define-key org-mode-map [menu-bar headings] 'undefined)
2691 (define-key org-mode-map [menu-bar hide] 'undefined)
2692 (define-key org-mode-map [menu-bar show] 'undefined))
2693
2694 (easy-menu-add org-org-menu)
2695 (easy-menu-add org-tbl-menu)
2696 (org-install-agenda-files-menu)
2697 (if org-descriptive-links (org-add-to-invisibility-spec '(org-link)))
2698 (org-add-to-invisibility-spec '(org-cwidth))
2699 (when (featurep 'xemacs)
2700 (set (make-local-variable 'line-move-ignore-invisible) t))
2701 (setq outline-regexp "\\*+")
2702 ;;(setq outline-regexp "\\(?:\\*+\\|[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\) \\)")
2703 (setq outline-level 'org-outline-level)
2704 (when (and org-ellipsis (stringp org-ellipsis))
2705 (unless org-display-table
2706 (setq org-display-table (make-display-table)))
2707 (set-display-table-slot org-display-table
2708 4 (string-to-vector org-ellipsis))
2709 (setq buffer-display-table org-display-table))
2710 (org-set-regexps-and-options)
2711 (if org-startup-truncated (setq truncate-lines t))
2712 (set (make-local-variable 'font-lock-unfontify-region-function)
2713 'org-unfontify-region)
2714 ;; Activate before-change-function
2715 (set (make-local-variable 'org-table-may-need-update) t)
2716 (org-add-hook 'before-change-functions 'org-before-change-function nil
2717 'local)
2718 ;; Paragraphs and auto-filling
2719 (org-set-autofill-regexps)
2720 (org-update-radio-target-regexp)
2721 ;; Settings for Calc embedded mode
2722 (set (make-local-variable 'calc-embedded-open-formula) "|\\|\n")
2723 (set (make-local-variable 'calc-embedded-close-formula) "|\\|\n")
2724 (if (and org-insert-mode-line-in-empty-file
2725 (interactive-p)
2726 (= (point-min) (point-max)))
2727 (insert " -*- mode: org -*-\n\n"))
2728
2729 (unless org-inhibit-startup
2730 (if org-startup-align-all-tables
2731 (org-table-map-tables 'org-table-align))
2732 (if org-startup-with-deadline-check
2733 (call-interactively 'org-check-deadlines)
2734 (cond
2735 ((eq org-startup-folded t)
2736 (org-cycle '(4)))
2737 ((eq org-startup-folded 'content)
2738 (let ((this-command 'org-cycle) (last-command 'org-cycle))
2739 (org-cycle '(4)) (org-cycle '(4))))))))
2740
2741 (defsubst org-call-with-arg (command arg)
2742 "Call COMMAND interactively, but pretend prefix are was ARG."
2743 (let ((current-prefix-arg arg)) (call-interactively command)))
2744
2745 (defsubst org-current-line (&optional pos)
2746 (+ (if (bolp) 1 0) (count-lines (point-min) (or pos (point)))))
2747
2748 (defun org-current-time ()
2749 "Current time, possibly rounded to `org-time-stamp-rounding-minutes'."
2750 (if (> org-time-stamp-rounding-minutes 0)
2751 (let ((r org-time-stamp-rounding-minutes)
2752 (time (decode-time)))
2753 (apply 'encode-time
2754 (append (list 0 (* r (floor (+ .5 (/ (float (nth 1 time)) r)))))
2755 (nthcdr 2 time))))
2756 (current-time)))
2757
2758 (defun org-add-props (string plist &rest props)
2759 "Add text properties to entire string, from beginning to end.
2760 PLIST may be a list of properties, PROPS are individual properties and values
2761 that will be added to PLIST. Returns the string that was modified."
2762 (add-text-properties
2763 0 (length string) (if props (append plist props) plist) string)
2764 string)
2765 (put 'org-add-props 'lisp-indent-function 2)
2766
2767
2768 ;;; Font-Lock stuff
2769
2770 (defvar org-mouse-map (make-sparse-keymap))
2771 (define-key org-mouse-map
2772 (if (featurep 'xemacs) [button2] [mouse-2]) 'org-open-at-mouse)
2773 (define-key org-mouse-map
2774 (if (featurep 'xemacs) [button3] [mouse-3]) 'org-find-file-at-mouse)
2775 (when org-mouse-1-follows-link
2776 (define-key org-mouse-map [follow-link] 'mouse-face))
2777 (when org-tab-follows-link
2778 (define-key org-mouse-map [(tab)] 'org-open-at-point)
2779 (define-key org-mouse-map "\C-i" 'org-open-at-point))
2780 (when org-return-follows-link
2781 (define-key org-mouse-map [(return)] 'org-open-at-point)
2782 (define-key org-mouse-map "\C-m" 'org-open-at-point))
2783
2784 (require 'font-lock)
2785
2786 (defconst org-non-link-chars "]\t\n\r<>")
2787 (defconst org-link-types '("https?" "ftp" "mailto" "file" "news" "bbdb" "vm"
2788 "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
2789 (defconst org-link-re-with-space
2790 (concat
2791 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
2792 "\\([^" org-non-link-chars " ]"
2793 "[^" org-non-link-chars "]*"
2794 "[^" org-non-link-chars " ]\\)>?")
2795 "Matches a link with spaces, optional angular brackets around it.")
2796
2797 (defconst org-link-re-with-space2
2798 (concat
2799 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
2800 "\\([^" org-non-link-chars " ]"
2801 "[^]\t\n\r]*"
2802 "[^" org-non-link-chars " ]\\)>?")
2803 "Matches a link with spaces, optional angular brackets around it.")
2804
2805 (defconst org-angle-link-re
2806 (concat
2807 "<\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
2808 "\\([^" org-non-link-chars " ]"
2809 "[^" org-non-link-chars "]*"
2810 "\\)>")
2811 "Matches link with angular brackets, spaces are allowed.")
2812 (defconst org-plain-link-re
2813 (concat
2814 "\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
2815 "\\([^]\t\n\r<>,;() ]+\\)")
2816 "Matches plain link, without spaces.")
2817
2818 (defconst org-bracket-link-regexp
2819 "\\[\\[\\([^]]+\\)\\]\\(\\[\\([^]]+\\)\\]\\)?\\]"
2820 "Matches a link in double brackets.")
2821
2822 (defconst org-bracket-link-analytic-regexp
2823 (concat
2824 "\\[\\["
2825 "\\(\\(" (mapconcat 'identity org-link-types "\\|") "\\):\\)?"
2826 "\\([^]]+\\)"
2827 "\\]"
2828 "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
2829 "\\]"))
2830 ; 1: http:
2831 ; 2: http
2832 ; 3: path
2833 ; 4: [desc]
2834 ; 5: desc
2835
2836
2837 (defconst org-ts-lengths
2838 (cons (length (format-time-string (car org-time-stamp-formats)))
2839 (length (format-time-string (cdr org-time-stamp-formats))))
2840 "This holds the lengths of the two different time formats.")
2841 (defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^\r\n>]*?\\)>"
2842 "Regular expression for fast time stamp matching.")
2843 (defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^\r\n>]*?\\)[]>]"
2844 "Regular expression for fast time stamp matching.")
2845 (defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\([^0-9>\r\n]*\\)\\(\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
2846 "Regular expression matching time strings for analysis.")
2847 (defconst org-ts-regexp2 (concat "<" org-ts-regexp1 ">")
2848 "Regular expression matching time stamps, with groups.")
2849 (defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp)
2850 "Regular expression matching a time stamp range.")
2851 (defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?"
2852 org-ts-regexp "\\)?")
2853 "Regular expression matching a time stamp or time stamp range.")
2854
2855 (defun org-activate-plain-links (limit)
2856 "Run through the buffer and add overlays to links."
2857 (if (re-search-forward org-plain-link-re limit t)
2858 (progn
2859 (add-text-properties (match-beginning 0) (match-end 0)
2860 (list 'mouse-face 'highlight
2861 'keymap org-mouse-map
2862 ))
2863 t)))
2864
2865 (defun org-activate-angle-links (limit)
2866 "Run through the buffer and add overlays to links."
2867 (if (re-search-forward org-angle-link-re limit t)
2868 (progn
2869 (add-text-properties (match-beginning 0) (match-end 0)
2870 (list 'mouse-face 'highlight
2871 'keymap org-mouse-map
2872 ))
2873 t)))
2874
2875 (defun org-activate-bracket-links (limit)
2876 "Run through the buffer and add overlays to bracketed links."
2877 (if (re-search-forward org-bracket-link-regexp limit t)
2878 (let* ((help (concat "LINK: "
2879 (org-match-string-no-properties 1)))
2880 ;; FIXME: above we should remove the escapes.
2881 (ip (list 'invisible 'org-link 'intangible t 'rear-nonsticky t
2882 'keymap org-mouse-map 'mouse-face 'highlight
2883 'help-echo help))
2884 (vp (list 'rear-nonsticky t
2885 'keymap org-mouse-map 'mouse-face 'highlight
2886 'help-echo help)))
2887 ;; We need to remove the invisible property here. Table narrowing
2888 ;; may have made some of this invisible.
2889 (remove-text-properties (match-beginning 0) (match-end 0)
2890 '(invisible nil))
2891 (if (match-end 3)
2892 (progn
2893 (add-text-properties (match-beginning 0) (match-beginning 3) ip)
2894 (add-text-properties (match-beginning 3) (match-end 3) vp)
2895 (add-text-properties (match-end 3) (match-end 0) ip))
2896 (add-text-properties (match-beginning 0) (match-beginning 1) ip)
2897 (add-text-properties (match-beginning 1) (match-end 1) vp)
2898 (add-text-properties (match-end 1) (match-end 0) ip))
2899 t)))
2900
2901 (defun org-activate-dates (limit)
2902 "Run through the buffer and add overlays to dates."
2903 (if (re-search-forward org-tsr-regexp limit t)
2904 (progn
2905 (add-text-properties (match-beginning 0) (match-end 0)
2906 (list 'mouse-face 'highlight
2907 'keymap org-mouse-map))
2908 t)))
2909
2910 (defvar org-target-link-regexp nil
2911 "Regular expression matching radio targets in plain text.")
2912 (defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>"
2913 "Regular expression matching a link target.")
2914 (defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>"
2915 "Regular expression matching a link target.")
2916
2917 (defun org-activate-target-links (limit)
2918 "Run through the buffer and add overlays to target matches."
2919 (when org-target-link-regexp
2920 (let ((case-fold-search t))
2921 (if (re-search-forward org-target-link-regexp limit t)
2922 (progn
2923 (add-text-properties (match-beginning 0) (match-end 0)
2924 (list 'mouse-face 'highlight
2925 'keymap org-mouse-map
2926 'help-echo "Radio target link"
2927 'org-linked-text t))
2928 t)))))
2929
2930 (defun org-update-radio-target-regexp ()
2931 "Find all radio targets in this file and update the regular expression."
2932 (interactive)
2933 (when (memq 'radio org-activate-links)
2934 (setq org-target-link-regexp
2935 (org-make-target-link-regexp (org-all-targets 'radio)))
2936 (org-restart-font-lock)))
2937
2938 (defun org-hide-wide-columns (limit)
2939 (let (s e)
2940 (setq s (text-property-any (point) (or limit (point-max))
2941 'org-cwidth t))
2942 (when s
2943 (setq e (next-single-property-change s 'org-cwidth))
2944 (add-text-properties s e '(invisible org-cwidth intangible t))
2945 (goto-char e)
2946 t)))
2947
2948 (defun org-restart-font-lock ()
2949 "Restart font-lock-mode, to force refontification."
2950 (when (and (boundp 'font-lock-mode) font-lock-mode)
2951 (font-lock-mode -1)
2952 (font-lock-mode 1)))
2953
2954 (defun org-all-targets (&optional radio)
2955 "Return a list of all targets in this file.
2956 With optional argument RADIO, only find radio targets."
2957 (let ((re (if radio org-radio-target-regexp org-target-regexp))
2958 rtn)
2959 (save-excursion
2960 (goto-char (point-min))
2961 (while (re-search-forward re nil t)
2962 (add-to-list 'rtn (downcase (org-match-string-no-properties 1))))
2963 rtn)))
2964
2965 (defun org-make-target-link-regexp (targets)
2966 "Make regular expression matching all strings in TARGETS.
2967 The regular expression finds the targets also if there is a line break
2968 between words."
2969 (and targets
2970 (concat
2971 "\\<\\("
2972 (mapconcat
2973 (lambda (x)
2974 (while (string-match " +" x)
2975 (setq x (replace-match "\\s-+" t t x)))
2976 x)
2977 targets
2978 "\\|")
2979 "\\)\\>")))
2980
2981 (defvar org-camel-regexp "\\*?\\<[A-Z]+[a-z]+[A-Z][a-zA-Z]*\\>"
2982 "Matches CamelCase words, possibly with a star before it.")
2983
2984 (defun org-activate-camels (limit)
2985 "Run through the buffer and add overlays to dates."
2986 (if (re-search-forward org-camel-regexp limit t)
2987 (progn
2988 (add-text-properties (match-beginning 0) (match-end 0)
2989 (list 'mouse-face 'highlight
2990 'keymap org-mouse-map))
2991 t)))
2992
2993 (defun org-activate-tags (limit)
2994 (if (re-search-forward "[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \r\n]" limit t)
2995 (progn
2996 (add-text-properties (match-beginning 1) (match-end 1)
2997 (list 'mouse-face 'highlight
2998 'keymap org-mouse-map))
2999 t)))
3000
3001 (defun org-font-lock-level ()
3002 (save-excursion
3003 (org-back-to-heading t)
3004 (- (match-end 0) (match-beginning 0))))
3005
3006 (defun org-outline-level ()
3007 (save-excursion
3008 (looking-at outline-regexp)
3009 (if (match-beginning 1)
3010 (+ (org-get-string-indentation (match-string 1)) 1000)
3011 (- (match-end 0) (match-beginning 0)))))
3012
3013 (defvar org-font-lock-keywords nil)
3014
3015 (defun org-set-font-lock-defaults ()
3016 (let* ((em org-fontify-emphasized-text)
3017 (lk org-activate-links)
3018 (org-font-lock-extra-keywords
3019 ;; Headlines
3020 (list
3021 '("^\\(\\**\\)\\(\\*\\)\\(.*\\)" (1 (org-get-level-face 1))
3022 (2 (org-get-level-face 2)) (3 (org-get-level-face 3)))
3023 '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)"
3024 (1 'org-table))
3025 ;; Links
3026 (if (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
3027 (if (memq 'plain lk) '(org-activate-plain-links (0 'org-link t)))
3028 (if (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
3029 (if (memq 'radio lk) '(org-activate-target-links (0 'org-link t)))
3030 (if (memq 'date lk) '(org-activate-dates (0 'org-date t)))
3031 (if (memq 'camel lk) '(org-activate-camels (0 'org-link t)))
3032 (if (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
3033 (if org-table-limit-column-width
3034 '(org-hide-wide-columns (0 nil append)))
3035 ;; TODO lines
3036 (list (concat "^\\*+[ \t]*" org-not-done-regexp)
3037 '(1 'org-todo t))
3038 ;; Priorities
3039 (list (concat "\\[#[A-Z]\\]") '(0 'org-special-keyword t))
3040 ;; Special keywords
3041 (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t))
3042 (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword t))
3043 (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t))
3044 ;; Emphasis
3045 (if em (list org-bold-re 2 ''bold 'prepend))
3046 (if em (list org-italic-re 2 ''italic 'prepend))
3047 (if em (list org-underline-re 2 ''underline 'prepend))
3048 ;; Checkboxes, similar to Frank Ruell's org-checklet.el
3049 '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)"
3050 2 'bold prepend)
3051 ;; COMMENT
3052 (list (concat "^\\*+[ \t]*\\<\\(" org-comment-string
3053 "\\|" org-quote-string "\\)\\>")
3054 '(1 'org-special-keyword t))
3055 '("^#.*" (0 'font-lock-comment-face t))
3056 ;; DONE
3057 (if org-fontify-done-headline
3058 (list (concat "^[*]+ +\\<\\(" org-done-string "\\)\\(.*\\)\\>")
3059 '(1 'org-done t) '(2 'org-headline-done t))
3060 (list (concat "^[*]+ +\\<\\(" org-done-string "\\)\\>")
3061 '(1 'org-done t)))
3062 ;; Table stuff
3063 '("^[ \t]*\\(:.*\\)" (1 'org-table t))
3064 '("| *\\(:?=[^|\n]*\\)" (1 'org-formula t))
3065 '("^[ \t]*| *\\([#!$*_^]\\) *|" (1 'org-formula t))
3066 (if org-format-transports-properties-p
3067 '("| *\\(<[0-9]+>\\) *" (1 'org-formula t)))
3068 )))
3069 (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords))
3070 ;; Now set the full font-lock-keywords
3071 (set (make-local-variable 'org-font-lock-keywords)
3072 org-font-lock-extra-keywords)
3073 (set (make-local-variable 'font-lock-defaults)
3074 '(org-font-lock-keywords t nil nil backward-paragraph))
3075 (kill-local-variable 'font-lock-keywords) nil))
3076
3077 (defvar org-m nil)
3078 (defvar org-l nil)
3079 (defvar org-f nil)
3080 (defun org-get-level-face (n)
3081 "Get the right face for match N in font-lock matching of healdines."
3082 (setq org-l (- (match-end 2) (match-beginning 1)))
3083 (if org-odd-levels-only (setq org-l (1+ (/ org-l 2))))
3084 ; (setq org-f (nth (1- (% org-l org-n-levels)) org-level-faces))
3085 (setq org-f (nth (% (1- org-l) org-n-levels) org-level-faces))
3086 (cond
3087 ((eq n 1) (if org-hide-leading-stars 'org-hide org-f))
3088 ((eq n 2) org-f)
3089 (t (if org-level-color-stars-only nil org-f))))
3090
3091 (defun org-unfontify-region (beg end &optional maybe_loudly)
3092 "Remove fontification and activation overlays from links."
3093 (font-lock-default-unfontify-region beg end)
3094 (let* ((buffer-undo-list t)
3095 (inhibit-read-only t) (inhibit-point-motion-hooks t)
3096 (inhibit-modification-hooks t)
3097 deactivate-mark buffer-file-name buffer-file-truename)
3098 (remove-text-properties beg end
3099 '(mouse-face nil keymap nil org-linked-text nil
3100 invisible nil intangible nil))))
3101 ;;; Visibility cycling
3102
3103 (defvar org-cycle-global-status nil)
3104 (make-variable-buffer-local 'org-cycle-global-status)
3105 (defvar org-cycle-subtree-status nil)
3106 (make-variable-buffer-local 'org-cycle-subtree-status)
3107
3108 ;;;###autoload
3109 (defun org-cycle (&optional arg)
3110 "Visibility cycling for Org-mode.
3111
3112 - When this function is called with a prefix argument, rotate the entire
3113 buffer through 3 states (global cycling)
3114 1. OVERVIEW: Show only top-level headlines.
3115 2. CONTENTS: Show all headlines of all levels, but no body text.
3116 3. SHOW ALL: Show everything.
3117
3118 - When point is at the beginning of a headline, rotate the subtree started
3119 by this line through 3 different states (local cycling)
3120 1. FOLDED: Only the main headline is shown.
3121 2. CHILDREN: The main headline and the direct children are shown.
3122 From this state, you can move to one of the children
3123 and zoom in further.
3124 3. SUBTREE: Show the entire subtree, including body text.
3125
3126 - When there is a numeric prefix, go up to a heading with level ARG, do
3127 a `show-subtree' and return to the previous cursor position. If ARG
3128 is negative, go up that many levels.
3129
3130 - When point is not at the beginning of a headline, execute
3131 `indent-relative', like TAB normally does. See the option
3132 `org-cycle-emulate-tab' for details.
3133
3134 - Special case: if point is the the beginning of the buffer and there is
3135 no headline in line 1, this function will act as if called with prefix arg."
3136 (interactive "P")
3137
3138 (let* ((outline-regexp
3139 (if org-cycle-include-plain-lists
3140 "\\*+\\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) "
3141 outline-regexp))
3142 (bob-special (and org-cycle-global-at-bob (bobp)
3143 (not (looking-at outline-regexp))))
3144 (org-cycle-hook (if bob-special nil org-cycle-hook)))
3145
3146 (if (or bob-special (equal arg '(4)))
3147 ;; special case: use global cycling
3148 (setq arg t))
3149
3150 (cond
3151
3152 ((org-at-table-p 'any)
3153 ;; Enter the table or move to the next field in the table
3154 (or (org-table-recognize-table.el)
3155 (progn
3156 (if arg (org-table-edit-field t)
3157 (org-table-justify-field-maybe)
3158 (call-interactively 'org-table-next-field)))))
3159
3160 ((eq arg t) ;; Global cycling
3161
3162 (cond
3163 ((and (eq last-command this-command)
3164 (eq org-cycle-global-status 'overview))
3165 ;; We just created the overview - now do table of contents
3166 ;; This can be slow in very large buffers, so indicate action
3167 (message "CONTENTS...")
3168 (org-content)
3169 (message "CONTENTS...done")
3170 (setq org-cycle-global-status 'contents)
3171 (run-hook-with-args 'org-cycle-hook 'contents))
3172
3173 ((and (eq last-command this-command)
3174 (eq org-cycle-global-status 'contents))
3175 ;; We just showed the table of contents - now show everything
3176 (show-all)
3177 (message "SHOW ALL")
3178 (setq org-cycle-global-status 'all)
3179 (run-hook-with-args 'org-cycle-hook 'all))
3180
3181 (t
3182 ;; Default action: go to overview
3183 (org-overview)
3184 (message "OVERVIEW")
3185 (setq org-cycle-global-status 'overview)
3186 (run-hook-with-args 'org-cycle-hook 'overview))))
3187
3188 ((integerp arg)
3189 ;; Show-subtree, ARG levels up from here.
3190 (save-excursion
3191 (org-back-to-heading)
3192 (outline-up-heading (if (< arg 0) (- arg)
3193 (- (funcall outline-level) arg)))
3194 (org-show-subtree)))
3195
3196 ((save-excursion (beginning-of-line 1) (looking-at outline-regexp))
3197 ;; At a heading: rotate between three different views
3198 (org-back-to-heading)
3199 (let ((goal-column 0) eoh eol eos)
3200 ;; First, some boundaries
3201 (save-excursion
3202 (org-back-to-heading)
3203 (save-excursion
3204 (beginning-of-line 2)
3205 (while (and (not (eobp)) ;; this is like `next-line'
3206 (get-char-property (1- (point)) 'invisible))
3207 (beginning-of-line 2)) (setq eol (point)))
3208 (outline-end-of-heading) (setq eoh (point))
3209 (org-end-of-subtree t) (setq eos (point))
3210 (outline-next-heading))
3211 ;; Find out what to do next and set `this-command'
3212 (cond
3213 ((and (= eos eoh)
3214 ;; Nothing is hidden behind this heading
3215 (message "EMPTY ENTRY")
3216 (setq org-cycle-subtree-status nil)))
3217 ((>= eol eos)
3218 ;; Entire subtree is hidden in one line: open it
3219 (org-show-entry)
3220 (show-children)
3221 (message "CHILDREN")
3222 (setq org-cycle-subtree-status 'children)
3223 (run-hook-with-args 'org-cycle-hook 'children))
3224 ((and (eq last-command this-command)
3225 (eq org-cycle-subtree-status 'children))
3226 ;; We just showed the children, now show everything.
3227 (org-show-subtree)
3228 (message "SUBTREE")
3229 (setq org-cycle-subtree-status 'subtree)
3230 (run-hook-with-args 'org-cycle-hook 'subtree))
3231 (t
3232 ;; Default action: hide the subtree.
3233 (hide-subtree)
3234 (message "FOLDED")
3235 (setq org-cycle-subtree-status 'folded)
3236 (run-hook-with-args 'org-cycle-hook 'folded)))))
3237
3238 ;; TAB emulation
3239 (buffer-read-only (org-back-to-heading))
3240 ((if (and (eq org-cycle-emulate-tab 'white)
3241 (save-excursion (beginning-of-line 1) (looking-at "[ \t]+$")))
3242 t
3243 (eq org-cycle-emulate-tab t))
3244 (if (and (looking-at "[ \n\r\t]")
3245 (string-match "^[ \t]*$" (buffer-substring
3246 (point-at-bol) (point))))
3247 (progn
3248 (beginning-of-line 1)
3249 (and (looking-at "[ \t]+") (replace-match ""))))
3250 (indent-relative))
3251
3252 (t (save-excursion
3253 (org-back-to-heading)
3254 (org-cycle))))))
3255
3256 ;;;###autoload
3257 (defun org-global-cycle ()
3258 "Cycle the global visibility. For details see `org-cycle'."
3259 (interactive)
3260 (org-cycle '(4)))
3261
3262 (defun org-overview ()
3263 "Switch to overview mode, shoing only top-level headlines.
3264 Really, this shows all headlines with level equal or greater than the level
3265 of the first headline in the buffer. This is important, because if the
3266 first headline is not level one, then (hide-sublevels 1) gives confusing
3267 results."
3268 (interactive)
3269 (hide-sublevels (save-excursion
3270 (goto-char (point-min))
3271 (if (re-search-forward (concat "^" outline-regexp) nil t)
3272 (progn
3273 (goto-char (match-beginning 0))
3274 (funcall outline-level))
3275 1))))
3276
3277 ;; FIXME: allow an argument to give a limiting level for this.
3278 (defun org-content ()
3279 "Show all headlines in the buffer, like a table of contents"
3280 (interactive)
3281 (save-excursion
3282 ;; Visit all headings and show their offspring
3283 (goto-char (point-max))
3284 (catch 'exit
3285 (while (and (progn (condition-case nil
3286 (outline-previous-visible-heading 1)
3287 (error (goto-char (point-min))))
3288 t)
3289 (looking-at outline-regexp))
3290 (show-branches)
3291 (if (bobp) (throw 'exit nil))))))
3292
3293
3294 (defun org-optimize-window-after-visibility-change (state)
3295 "Adjust the window after a change in outline visibility.
3296 This function is the default value of the hook `org-cycle-hook'."
3297 (when (get-buffer-window (current-buffer))
3298 (cond
3299 ((eq state 'overview) (org-first-headline-recenter 1))
3300 ((eq state 'content) nil)
3301 ((eq state 'all) nil)
3302 ((eq state 'folded) nil)
3303 ((eq state 'children) (or (org-subtree-end-visible-p) (recenter 1)))
3304 ((eq state 'subtree) (or (org-subtree-end-visible-p) (recenter 1))))))
3305
3306 (defun org-subtree-end-visible-p ()
3307 "Is the end of the current subtree visible?"
3308 (pos-visible-in-window-p
3309 (save-excursion (org-end-of-subtree t) (point))))
3310
3311 (defun org-first-headline-recenter (&optional N)
3312 "Move cursor to the first headline and recenter the headline.
3313 Optional argument N means, put the headline into the Nth line of the window."
3314 (goto-char (point-min))
3315 (when (re-search-forward (concat "^" outline-regexp) nil t)
3316 (beginning-of-line)
3317 (recenter (prefix-numeric-value N))))
3318
3319 (defvar org-goto-window-configuration nil)
3320 (defvar org-goto-marker nil)
3321 (defvar org-goto-map (make-sparse-keymap))
3322 (let ((cmds '(isearch-forward isearch-backward)) cmd)
3323 (while (setq cmd (pop cmds))
3324 (substitute-key-definition cmd cmd org-goto-map global-map)))
3325 (define-key org-goto-map "\C-m" 'org-goto-ret)
3326 (define-key org-goto-map [(left)] 'org-goto-left)
3327 (define-key org-goto-map [(right)] 'org-goto-right)
3328 (define-key org-goto-map [(?q)] 'org-goto-quit)
3329 (define-key org-goto-map [(control ?g)] 'org-goto-quit)
3330 (define-key org-goto-map "\C-i" 'org-cycle)
3331 (define-key org-goto-map [(tab)] 'org-cycle)
3332 (define-key org-goto-map [(down)] 'outline-next-visible-heading)
3333 (define-key org-goto-map [(up)] 'outline-previous-visible-heading)
3334 (define-key org-goto-map "n" 'outline-next-visible-heading)
3335 (define-key org-goto-map "p" 'outline-previous-visible-heading)
3336 (define-key org-goto-map "f" 'outline-forward-same-level)
3337 (define-key org-goto-map "b" 'outline-backward-same-level)
3338 (define-key org-goto-map "u" 'outline-up-heading)
3339 (define-key org-goto-map "\C-c\C-n" 'outline-next-visible-heading)
3340 (define-key org-goto-map "\C-c\C-p" 'outline-previous-visible-heading)
3341 (define-key org-goto-map "\C-c\C-f" 'outline-forward-same-level)
3342 (define-key org-goto-map "\C-c\C-b" 'outline-backward-same-level)
3343 (define-key org-goto-map "\C-c\C-u" 'outline-up-heading)
3344 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
3345 (while l (define-key org-goto-map (int-to-string (pop l)) 'digit-argument)))
3346
3347 (defconst org-goto-help
3348 "Select a location to jump to, press RET
3349 \[Up]/[Down]=next/prev headline TAB=cycle visibility RET=select [Q]uit")
3350
3351 (defun org-goto ()
3352 "Go to a different location of the document, keeping current visibility.
3353
3354 When you want to go to a different location in a document, the fastest way
3355 is often to fold the entire buffer and then dive into the tree. This
3356 method has the disadvantage, that the previous location will be folded,
3357 which may not be what you want.
3358
3359 This command works around this by showing a copy of the current buffer in
3360 overview mode. You can dive into the tree in that copy, to find the
3361 location you want to reach. When pressing RET, the command returns to the
3362 original buffer in which the visibility is still unchanged. It then jumps
3363 to the new location, making it and the headline hierarchy above it visible."
3364 (interactive)
3365 (let* ((org-goto-start-pos (point))
3366 (selected-point
3367 (org-get-location (current-buffer) org-goto-help)))
3368 (if selected-point
3369 (progn
3370 (org-mark-ring-push org-goto-start-pos)
3371 (goto-char selected-point)
3372 (if (or (org-invisible-p) (org-invisible-p2))
3373 (org-show-hierarchy-above)))
3374 (error "Quit"))))
3375
3376 (defun org-get-location (buf help)
3377 "Let the user select a location in the Org-mode buffer BUF.
3378 This function uses a recursive edit. It returns the selected position
3379 or nil."
3380 (let (org-selected-point)
3381 (save-excursion
3382 (save-window-excursion
3383 (delete-other-windows)
3384 (switch-to-buffer (get-buffer-create "*org-goto*"))
3385 (with-output-to-temp-buffer "*Help*"
3386 (princ help))
3387 (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*"))
3388 (setq buffer-read-only nil)
3389 (erase-buffer)
3390 (insert-buffer-substring buf)
3391 (let ((org-startup-truncated t)
3392 (org-startup-folded t)
3393 (org-startup-align-all-tables nil)
3394 (org-startup-with-deadline-check nil))
3395 (org-mode))
3396 (setq buffer-read-only t)
3397 (if (boundp 'org-goto-start-pos)
3398 (goto-char org-goto-start-pos)
3399 (goto-char (point-min)))
3400 (org-beginning-of-line)
3401 (message "Select location and press RET")
3402 ;; now we make sure that during selection, ony very few keys work
3403 ;; and that it is impossible to switch to another window.
3404 (let ((gm (current-global-map))
3405 (overriding-local-map org-goto-map))
3406 (unwind-protect
3407 (progn
3408 (use-global-map org-goto-map)
3409 (recursive-edit))
3410 (use-global-map gm)))))
3411 (kill-buffer "*org-goto*")
3412 org-selected-point))
3413
3414 (defun org-goto-ret (&optional arg)
3415 "Finish `org-goto' by going to the new location."
3416 (interactive "P")
3417 (setq org-selected-point (point)
3418 current-prefix-arg arg)
3419 (throw 'exit nil))
3420
3421 (defun org-goto-left ()
3422 "Finish `org-goto' by going to the new location."
3423 (interactive)
3424 (if (org-on-heading-p)
3425 (progn
3426 (beginning-of-line 1)
3427 (setq org-selected-point (point)
3428 current-prefix-arg (- (match-end 0) (match-beginning 0)))
3429 (throw 'exit nil))
3430 (error "Not on a heading")))
3431
3432 (defun org-goto-right ()
3433 "Finish `org-goto' by going to the new location."
3434 (interactive)
3435 (if (org-on-heading-p)
3436 (progn
3437 (outline-end-of-subtree)
3438 (or (eobp) (forward-char 1))
3439 (setq org-selected-point (point)
3440 current-prefix-arg (- (match-end 0) (match-beginning 0)))
3441 (throw 'exit nil))
3442 (error "Not on a heading")))
3443
3444 (defun org-goto-quit ()
3445 "Finish `org-goto' without cursor motion."
3446 (interactive)
3447 (setq org-selected-point nil)
3448 (throw 'exit nil))
3449
3450 ;;; Promotion, Demotion, Inserting new headlines
3451
3452 (defvar org-ignore-region nil
3453 "To temporarily disable the active region.")
3454
3455 (defun org-insert-heading (&optional force-heading)
3456 "Insert a new heading or item with same depth at point.
3457 If point is in a plain list and FORCE-HEADING is nil, create a new list item.
3458 If point is at the beginning of a headline, insert a sibling before the
3459 current headline. If point is in the middle of a headline, split the headline
3460 at that position and make the rest of the headline part of the sibling below
3461 the current headline."
3462 (interactive "P")
3463 (if (= (buffer-size) 0)
3464 (insert "\n* ")
3465 (when (or force-heading (not (org-insert-item)))
3466 (let* ((head (save-excursion
3467 (condition-case nil
3468 (progn
3469 (org-back-to-heading)
3470 (match-string 0))
3471 (error "*"))))
3472 pos)
3473 (cond
3474 ((and (org-on-heading-p) (bolp)
3475 (save-excursion (backward-char 1) (not (org-invisible-p))))
3476 (open-line 1))
3477 ((bolp) nil)
3478 (t (newline)))
3479 (insert head) (just-one-space)
3480 (setq pos (point))
3481 (end-of-line 1)
3482 (unless (= (point) pos) (just-one-space) (backward-delete-char 1))
3483 (run-hooks 'org-insert-heading-hook)))))
3484
3485 (defun org-insert-item (&optional checkbox)
3486 "Insert a new item at the current level.
3487 Return t when things worked, nil when we are not in an item."
3488 (when (save-excursion
3489 (condition-case nil
3490 (progn
3491 (org-beginning-of-item)
3492 (org-at-item-p)
3493 t)
3494 (error nil)))
3495 (let* ((bul (match-string 0))
3496 (end (match-end 0))
3497 (eow (save-excursion (beginning-of-line 1) (looking-at "[ \t]*")
3498 (match-end 0)))
3499 (eowcol (save-excursion (goto-char eow) (current-column)))
3500 pos)
3501 (cond
3502 ((and (org-at-item-p) (<= (point) eow))
3503 ;; before the bullet
3504 (beginning-of-line 1)
3505 (open-line 1))
3506 ((<= (point) eow)
3507 (beginning-of-line 1))
3508 (t (newline)))
3509 (insert bul (if checkbox "[ ]" ""))
3510 (just-one-space)
3511 (setq pos (point))
3512 (end-of-line 1)
3513 (unless (= (point) pos) (just-one-space) (backward-delete-char 1)))
3514 (org-maybe-renumber-ordered-list)
3515 t))
3516
3517 (defun org-insert-todo-heading (arg)
3518 "Insert a new heading with the same level and TODO state as current heading.
3519 If the heading has no TODO state, or if the state is DONE, use the first
3520 state (TODO by default). Also with prefix arg, force first state."
3521 (interactive "P")
3522 (when (not (org-insert-item 'checkbox))
3523 (org-insert-heading)
3524 (save-excursion
3525 (org-back-to-heading)
3526 (if org-noutline-p
3527 (outline-previous-heading)
3528 (outline-previous-visible-heading t))
3529 (looking-at org-todo-line-regexp))
3530 (if (or arg
3531 (not (match-beginning 2))
3532 (equal (match-string 2) org-done-string))
3533 (insert (car org-todo-keywords) " ")
3534 (insert (match-string 2) " "))))
3535
3536 (defun org-promote-subtree ()
3537 "Promote the entire subtree.
3538 See also `org-promote'."
3539 (interactive)
3540 (save-excursion
3541 (org-map-tree 'org-promote)))
3542
3543 (defun org-demote-subtree ()
3544 "Demote the entire subtree. See `org-demote'.
3545 See also `org-promote'."
3546 (interactive)
3547 (save-excursion
3548 (org-map-tree 'org-demote)))
3549
3550 (defun org-do-promote ()
3551 "Promote the current heading higher up the tree.
3552 If the region is active in `transient-mark-mode', promote all headings
3553 in the region."
3554 (interactive)
3555 (save-excursion
3556 (if (org-region-active-p)
3557 (org-map-region 'org-promote (region-beginning) (region-end))
3558 (org-promote)))
3559 (org-fix-position-after-promote))
3560
3561 (defun org-do-demote ()
3562 "Demote the current heading lower down the tree.
3563 If the region is active in `transient-mark-mode', demote all headings
3564 in the region."
3565 (interactive)
3566 (save-excursion
3567 (if (org-region-active-p)
3568 (org-map-region 'org-demote (region-beginning) (region-end))
3569 (org-demote)))
3570 (org-fix-position-after-promote))
3571
3572 (defun org-fix-position-after-promote ()
3573 "Make sure that after pro/demotion cursor position is right."
3574 (and (equal (char-after) ?\ )
3575 (equal (char-before) ?*)
3576 (forward-char 1)))
3577
3578 (defun org-get-legal-level (level change)
3579 "Rectify a level change under the influence of `org-odd-levels-only'
3580 LEVEL is a current level, CHANGE is by how much the level should be
3581 modified. Even if CHANGE is nil, LEVEL may be returned modified because
3582 even level numbers will become the next higher odd number."
3583 (if org-odd-levels-only
3584 (cond ((not change) (1+ (* 2 (/ level 2))))
3585 ((> change 0) (1+ (* 2 (/ (+ level (* 2 change)) 2))))
3586 ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2))))))
3587 (max 1 (+ level change))))
3588
3589 (defun org-promote ()
3590 "Promote the current heading higher up the tree.
3591 If the region is active in `transient-mark-mode', promote all headings
3592 in the region."
3593 (org-back-to-heading t)
3594 (let* ((level (save-match-data (funcall outline-level)))
3595 (up-head (make-string (org-get-legal-level level -1) ?*))
3596 (diff (abs (- level (length up-head)))))
3597 (if (= level 1) (error "Cannot promote to level 0. UNDO to recover"))
3598 (replace-match up-head nil t)
3599 ;; Fixup tag positioning
3600 (and org-auto-align-tags (org-set-tags nil t))
3601 (if org-adapt-indentation
3602 (org-fixup-indentation (if (> diff 1) "^ " "^ ") ""
3603 (if (> diff 1) "^ ? ?\\S-" "^ ?\\S-")))))
3604
3605 (defun org-demote ()
3606 "Demote the current heading lower down the tree.
3607 If the region is active in `transient-mark-mode', demote all headings
3608 in the region."
3609 (org-back-to-heading t)
3610 (let* ((level (save-match-data (funcall outline-level)))
3611 (down-head (make-string (org-get-legal-level level 1) ?*))
3612 (diff (abs (- level (length down-head)))))
3613 (replace-match down-head nil t)
3614 ;; Fixup tag positioning
3615 (and org-auto-align-tags (org-set-tags nil t))
3616 (if org-adapt-indentation
3617 (org-fixup-indentation "^ " (if (> diff 1) " " " ") "^\\S-"))))
3618
3619 (defun org-map-tree (fun)
3620 "Call FUN for every heading underneath the current one."
3621 (org-back-to-heading)
3622 (let ((level (funcall outline-level)))
3623 (save-excursion
3624 (funcall fun)
3625 (while (and (progn
3626 (outline-next-heading)
3627 (> (funcall outline-level) level))
3628 (not (eobp)))
3629 (funcall fun)))))
3630
3631 (defun org-map-region (fun beg end)
3632 "Call FUN for every heading between BEG and END."
3633 (let ((org-ignore-region t))
3634 (save-excursion
3635 (setq end (copy-marker end))
3636 (goto-char beg)
3637 (if (and (re-search-forward (concat "^" outline-regexp) nil t)
3638 (< (point) end))
3639 (funcall fun))
3640 (while (and (progn
3641 (outline-next-heading)
3642 (< (point) end))
3643 (not (eobp)))
3644 (funcall fun)))))
3645
3646 (defun org-fixup-indentation (from to prohibit)
3647 "Change the indentation in the current entry by re-replacing FROM with TO.
3648 However, if the regexp PROHIBIT matches at all, don't do anything.
3649 This is being used to change indentation along with the length of the
3650 heading marker. But if there are any lines which are not indented, nothing
3651 is changed at all."
3652 (save-excursion
3653 (let ((end (save-excursion (outline-next-heading)
3654 (point-marker))))
3655 (unless (save-excursion (re-search-forward prohibit end t))
3656 (while (re-search-forward from end t)
3657 (replace-match to)
3658 (beginning-of-line 2)))
3659 (move-marker end nil))))
3660
3661 ;;; Vertical tree motion, cutting and pasting of subtrees
3662
3663 (defun org-move-subtree-up (&optional arg)
3664 "Move the current subtree up past ARG headlines of the same level."
3665 (interactive "p")
3666 (org-move-subtree-down (- (prefix-numeric-value arg))))
3667
3668 (defun org-move-subtree-down (&optional arg)
3669 "Move the current subtree down past ARG headlines of the same level."
3670 (interactive "p")
3671 (setq arg (prefix-numeric-value arg))
3672 (let ((movfunc (if (> arg 0) 'outline-get-next-sibling
3673 'outline-get-last-sibling))
3674 (ins-point (make-marker))
3675 (cnt (abs arg))
3676 beg end txt folded)
3677 ;; Select the tree
3678 (org-back-to-heading)
3679 (setq beg (point))
3680 (save-match-data
3681 (save-excursion (outline-end-of-heading)
3682 (setq folded (org-invisible-p)))
3683 (outline-end-of-subtree))
3684 (outline-next-heading)
3685 (setq end (point))
3686 ;; Find insertion point, with error handling
3687 (goto-char beg)
3688 (while (> cnt 0)
3689 (or (and (funcall movfunc) (looking-at outline-regexp))
3690 (progn (goto-char beg)
3691 (error "Cannot move past superior level or buffer limit")))
3692 (setq cnt (1- cnt)))
3693 (if (> arg 0)
3694 ;; Moving forward - still need to move over subtree
3695 (progn (outline-end-of-subtree)
3696 (outline-next-heading)
3697 (if (not (or (looking-at (concat "^" outline-regexp))
3698 (bolp)))
3699 (newline))))
3700 (move-marker ins-point (point))
3701 (setq txt (buffer-substring beg end))
3702 (delete-region beg end)
3703 (insert txt)
3704 (goto-char ins-point)
3705 (if folded (hide-subtree))
3706 (move-marker ins-point nil)))
3707
3708 (defvar org-subtree-clip ""
3709 "Clipboard for cut and paste of subtrees.
3710 This is actually only a copy of the kill, because we use the normal kill
3711 ring. We need it to check if the kill was created by `org-copy-subtree'.")
3712
3713 (defvar org-subtree-clip-folded nil
3714 "Was the last copied subtree folded?
3715 This is used to fold the tree back after pasting.")
3716
3717 (defun org-cut-subtree ()
3718 "Cut the current subtree into the clipboard.
3719 This is a short-hand for marking the subtree and then cutting it."
3720 (interactive)
3721 (org-copy-subtree 'cut))
3722
3723 (defun org-copy-subtree (&optional cut)
3724 "Cut the current subtree into the clipboard.
3725 This is a short-hand for marking the subtree and then copying it.
3726 If CUT is non nil, actually cut the subtree."
3727 (interactive)
3728 (let (beg end folded)
3729 (org-back-to-heading)
3730 (setq beg (point))
3731 (save-match-data
3732 (save-excursion (outline-end-of-heading)
3733 (setq folded (org-invisible-p)))
3734 (outline-end-of-subtree))
3735 (if (equal (char-after) ?\n) (forward-char 1))
3736 (setq end (point))
3737 (goto-char beg)
3738 (when (> end beg)
3739 (setq org-subtree-clip-folded folded)
3740 (if cut (kill-region beg end) (copy-region-as-kill beg end))
3741 (setq org-subtree-clip (current-kill 0))
3742 (message "%s: Subtree with %d characters"
3743 (if cut "Cut" "Copied")
3744 (length org-subtree-clip)))))
3745
3746 (defun org-paste-subtree (&optional level tree)
3747 "Paste the clipboard as a subtree, with modification of headline level.
3748 The entire subtree is promoted or demoted in order to match a new headline
3749 level. By default, the new level is derived from the visible headings
3750 before and after the insertion point, and taken to be the inferior headline
3751 level of the two. So if the previous visible heading is level 3 and the
3752 next is level 4 (or vice versa), level 4 will be used for insertion.
3753 This makes sure that the subtree remains an independent subtree and does
3754 not swallow low level entries.
3755
3756 You can also force a different level, either by using a numeric prefix
3757 argument, or by inserting the heading marker by hand. For example, if the
3758 cursor is after \"*****\", then the tree will be shifted to level 5.
3759
3760 If you want to insert the tree as is, just use \\[yank].
3761
3762 If optional TREE is given, use this text instead of the kill ring."
3763 (interactive "P")
3764 (unless (org-kill-is-subtree-p tree)
3765 (error
3766 (substitute-command-keys
3767 "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway")))
3768 (let* ((txt (or tree (and kill-ring (current-kill 0))))
3769 (^re (concat "^\\(" outline-regexp "\\)"))
3770 (re (concat "\\(" outline-regexp "\\)"))
3771 (^re_ (concat "\\(" outline-regexp "\\)[ \t]*"))
3772
3773 (old-level (if (string-match ^re txt)
3774 (- (match-end 0) (match-beginning 0))
3775 -1))
3776 (force-level (cond (level (prefix-numeric-value level))
3777 ((string-match
3778 ^re_ (buffer-substring (point-at-bol) (point)))
3779 (- (match-end 0) (match-beginning 0)))
3780 (t nil)))
3781 (previous-level (save-excursion
3782 (condition-case nil
3783 (progn
3784 (outline-previous-visible-heading 1)
3785 (if (looking-at re)
3786 (- (match-end 0) (match-beginning 0))
3787 1))
3788 (error 1))))
3789 (next-level (save-excursion
3790 (condition-case nil
3791 (progn
3792 (outline-next-visible-heading 1)
3793 (if (looking-at re)
3794 (- (match-end 0) (match-beginning 0))
3795 1))
3796 (error 1))))
3797 (new-level (or force-level (max previous-level next-level)))
3798 (shift (if (or (= old-level -1)
3799 (= new-level -1)
3800 (= old-level new-level))
3801 0
3802 (- new-level old-level)))
3803 (shift1 shift)
3804 (delta (if (> shift 0) -1 1))
3805 (func (if (> shift 0) 'org-demote 'org-promote))
3806 (org-odd-levels-only nil)
3807 beg end)
3808 ;; Remove the forces level indicator
3809 (if force-level
3810 (delete-region (point-at-bol) (point)))
3811 ;; Make sure we start at the beginning of an empty line
3812 (if (not (bolp)) (insert "\n"))
3813 (if (not (looking-at "[ \t]*$"))
3814 (progn (insert "\n") (backward-char 1)))
3815 ;; Paste
3816 (setq beg (point))
3817 (insert txt)
3818 (setq end (point))
3819 (goto-char beg)
3820 ;; Shift if necessary
3821 (if (= shift 0)
3822 (message "Pasted at level %d, without shift" new-level)
3823 (save-restriction
3824 (narrow-to-region beg end)
3825 (while (not (= shift 0))
3826 (org-map-region func (point-min) (point-max))
3827 (setq shift (+ delta shift)))
3828 (goto-char (point-min))
3829 (message "Pasted at level %d, with shift by %d levels"
3830 new-level shift1)))
3831 (if (and kill-ring
3832 (eq org-subtree-clip (current-kill 0))
3833 org-subtree-clip-folded)
3834 ;; The tree was folded before it was killed/copied
3835 (hide-subtree))))
3836
3837 (defun org-kill-is-subtree-p (&optional txt)
3838 "Check if the current kill is an outline subtree, or a set of trees.
3839 Returns nil if kill does not start with a headline, or if the first
3840 headline level is not the largest headline level in the tree.
3841 So this will actually accept several entries of equal levels as well,
3842 which is OK for `org-paste-subtree'.
3843 If optional TXT is given, check this string instead of the current kill."
3844 (let* ((kill (or txt (and kill-ring (current-kill 0)) ""))
3845 (start-level (and kill
3846 (string-match (concat "\\`" outline-regexp) kill)
3847 (- (match-end 0) (match-beginning 0))))
3848 (re (concat "^" outline-regexp))
3849 (start 1))
3850 (if (not start-level)
3851 nil ;; does not even start with a heading
3852 (catch 'exit
3853 (while (setq start (string-match re kill (1+ start)))
3854 (if (< (- (match-end 0) (match-beginning 0)) start-level)
3855 (throw 'exit nil)))
3856 t))))
3857
3858 ;;; Plain list items
3859
3860 (defun org-at-item-p ()
3861 "Is point in a line starting a hand-formatted item?"
3862 (let ((llt org-plain-list-ordered-item-terminator))
3863 (save-excursion
3864 (goto-char (point-at-bol))
3865 (looking-at
3866 (cond
3867 ((eq llt t) "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
3868 ((= llt ?.) "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
3869 ((= llt ?\)) "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
3870 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))))))
3871
3872 (defun org-at-item-checkbox-p ()
3873 "Is point at a line starting a plain-list item with a checklet?"
3874 (and (org-at-item-p)
3875 (save-excursion
3876 (goto-char (match-end 0))
3877 (skip-chars-forward " \t")
3878 (looking-at "\\[[ X]\\]"))))
3879
3880 (defun org-toggle-checkbox ()
3881 "Toggle the checkbox in the current line."
3882 (interactive)
3883 (save-excursion
3884 (if (org-at-item-checkbox-p)
3885 (replace-match (if (equal (match-string 0) "[ ]") "[X]" "[ ]") t t))))
3886
3887 (defun org-get-indentation ()
3888 "Get the indentation of the current line, interpreting tabs."
3889 (save-excursion
3890 (beginning-of-line 1)
3891 (skip-chars-forward " \t")
3892 (current-column)))
3893
3894 (defun org-beginning-of-item ()
3895 "Go to the beginning of the current hand-formatted item.
3896 If the cursor is not in an item, throw an error."
3897 (interactive)
3898 (let ((pos (point))
3899 (limit (save-excursion (org-back-to-heading)
3900 (beginning-of-line 2) (point)))
3901 ind ind1)
3902 (if (org-at-item-p)
3903 (beginning-of-line 1)
3904 (beginning-of-line 1)
3905 (skip-chars-forward " \t")
3906 (setq ind (current-column))
3907 (if (catch 'exit
3908 (while t
3909 (beginning-of-line 0)
3910 (if (< (point) limit) (throw 'exit nil))
3911 (unless (looking-at " \t]*$")
3912 (skip-chars-forward " \t")
3913 (setq ind1 (current-column))
3914 (if (< ind1 ind)
3915 (throw 'exit (org-at-item-p))))))
3916 nil
3917 (goto-char pos)
3918 (error "Not in an item")))))
3919
3920 (defun org-end-of-item ()
3921 "Go to the end of the current hand-formatted item.
3922 If the cursor is not in an item, throw an error."
3923 (interactive)
3924 (let ((pos (point))
3925 (limit (save-excursion (outline-next-heading) (point)))
3926 (ind (save-excursion
3927 (org-beginning-of-item)
3928 (skip-chars-forward " \t")
3929 (current-column)))
3930 ind1)
3931 (if (catch 'exit
3932 (while t
3933 (beginning-of-line 2)
3934 (if (>= (point) limit) (throw 'exit t))
3935 (unless (looking-at "[ \t]*$")
3936 (skip-chars-forward " \t")
3937 (setq ind1 (current-column))
3938 (if (<= ind1 ind) (throw 'exit t)))))
3939 (beginning-of-line 1)
3940 (goto-char pos)
3941 (error "Not in an item"))))
3942
3943 (defun org-next-item ()
3944 "Move to the beginning of the next item in the current plain list.
3945 Error if not at a plain list, or if this is the last item in the list."
3946 (interactive)
3947 (let (beg end ind ind1 (pos (point)) txt)
3948 (org-beginning-of-item)
3949 (setq beg (point))
3950 (setq ind (org-get-indentation))
3951 (org-end-of-item)
3952 (setq end (point))
3953 (setq ind1 (org-get-indentation))
3954 (unless (and (org-at-item-p) (= ind ind1))
3955 (goto-char pos)
3956 (error "On last item"))))
3957
3958 (defun org-previous-item ()
3959 "Move to the beginning of the previous item in the current plain list.
3960 Error if not at a plain list, or if this is the last item in the list."
3961 (interactive)
3962 (let (beg end ind ind1 (pos (point)) txt)
3963 (org-beginning-of-item)
3964 (setq beg (point))
3965 (setq ind (org-get-indentation))
3966 (goto-char beg)
3967 (catch 'exit
3968 (while t
3969 (beginning-of-line 0)
3970 (if (looking-at "[ \t]*$")
3971 nil
3972 (if (<= (setq ind1 (org-get-indentation)) ind)
3973 (throw 'exit t)))))
3974 (condition-case nil
3975 (org-beginning-of-item)
3976 (error (goto-char pos)
3977 (error "On first item")))))
3978
3979 (defun org-move-item-down ()
3980 "Move the plain list item at point down, i.e. swap with following item.
3981 Subitems (items with larger indentation) are considered part of the item,
3982 so this really moves item trees."
3983 (interactive)
3984 (let (beg end ind ind1 (pos (point)) txt)
3985 (org-beginning-of-item)
3986 (setq beg (point))
3987 (setq ind (org-get-indentation))
3988 (org-end-of-item)
3989 (setq end (point))
3990 (setq ind1 (org-get-indentation))
3991 (if (and (org-at-item-p) (= ind ind1))
3992 (progn
3993 (org-end-of-item)
3994 (setq txt (buffer-substring beg end))
3995 (save-excursion
3996 (delete-region beg end))
3997 (setq pos (point))
3998 (insert txt)
3999 (goto-char pos)
4000 (org-maybe-renumber-ordered-list))
4001 (goto-char pos)
4002 (error "Cannot move this item further down"))))
4003
4004 (defun org-move-item-up (arg)
4005 "Move the plain list item at point up, i.e. swap with previous item.
4006 Subitems (items with larger indentation) are considered part of the item,
4007 so this really moves item trees."
4008 (interactive "p")
4009 (let (beg end ind ind1 (pos (point)) txt)
4010 (org-beginning-of-item)
4011 (setq beg (point))
4012 (setq ind (org-get-indentation))
4013 (org-end-of-item)
4014 (setq end (point))
4015 (goto-char beg)
4016 (catch 'exit
4017 (while t
4018 (beginning-of-line 0)
4019 (if (looking-at "[ \t]*$")
4020 nil
4021 (if (<= (setq ind1 (org-get-indentation)) ind)
4022 (throw 'exit t)))))
4023 (condition-case nil
4024 (org-beginning-of-item)
4025 (error (goto-char beg)
4026 (error "Cannot move this item further up")))
4027 (setq ind1 (org-get-indentation))
4028 (if (and (org-at-item-p) (= ind ind1))
4029 (progn
4030 (setq txt (buffer-substring beg end))
4031 (save-excursion
4032 (delete-region beg end))
4033 (setq pos (point))
4034 (insert txt)
4035 (goto-char pos)
4036 (org-maybe-renumber-ordered-list))
4037 (goto-char pos)
4038 (error "Cannot move this item further up"))))
4039
4040 (defun org-maybe-renumber-ordered-list ()
4041 "Renumber the ordered list at point if setup allows it.
4042 This tests the user option `org-auto-renumber-ordered-lists' before
4043 doing the renumbering."
4044 (and org-auto-renumber-ordered-lists
4045 (org-at-item-p)
4046 (match-beginning 3)
4047 (org-renumber-ordered-list 1)))
4048
4049 (defun org-get-string-indentation (s)
4050 "What indentation has S due to SPACE and TAB at the beginning of the string?"
4051 (let ((n -1) (i 0) (w tab-width) c)
4052 (catch 'exit
4053 (while (< (setq n (1+ n)) (length s))
4054 (setq c (aref s n))
4055 (cond ((= c ?\ ) (setq i (1+ i)))
4056 ((= c ?\t) (setq i (* (/ (+ w i) w) w)))
4057 (t (throw 'exit t)))))
4058 i))
4059
4060 (defun org-renumber-ordered-list (arg)
4061 "Renumber an ordered plain list.
4062 Cursor needs to be in the first line of an item, the line that starts
4063 with something like \"1.\" or \"2)\"."
4064 (interactive "p")
4065 (unless (and (org-at-item-p)
4066 (match-beginning 3))
4067 (error "This is not an ordered list"))
4068 (let ((line (org-current-line))
4069 (col (current-column))
4070 (ind (org-get-string-indentation
4071 (buffer-substring (point-at-bol) (match-beginning 3))))
4072 ;; (term (substring (match-string 3) -1))
4073 ind1 (n (1- arg)))
4074 ;; find where this list begins
4075 (catch 'exit
4076 (while t
4077 (catch 'next
4078 (beginning-of-line 0)
4079 (if (looking-at "[ \t]*$") (throw 'next t))
4080 (skip-chars-forward " \t") (setq ind1 (current-column))
4081 (if (or (< ind1 ind)
4082 (and (= ind1 ind)
4083 (not (org-at-item-p))))
4084 (throw 'exit t)))))
4085 ;; Walk forward and replace these numbers
4086 (catch 'exit
4087 (while t
4088 (catch 'next
4089 (beginning-of-line 2)
4090 (if (eobp) (throw 'exit nil))
4091 (if (looking-at "[ \t]*$") (throw 'next nil))
4092 (skip-chars-forward " \t") (setq ind1 (current-column))
4093 (if (> ind1 ind) (throw 'next t))
4094 (if (< ind1 ind) (throw 'exit t))
4095 (if (not (org-at-item-p)) (throw 'exit nil))
4096 (if (not (match-beginning 3))
4097 (error "unordered bullet in ordered list. Press \\[undo] to recover"))
4098 (delete-region (match-beginning 3) (1- (match-end 3)))
4099 (goto-char (match-beginning 3))
4100 (insert (format "%d" (setq n (1+ n)))))))
4101 (goto-line line)
4102 (move-to-column col)))
4103
4104 (defvar org-last-indent-begin-marker (make-marker))
4105 (defvar org-last-indent-end-marker (make-marker))
4106
4107 (defun org-outdent-item (arg)
4108 "Outdent a local list item."
4109 (interactive "p")
4110 (org-indent-item (- arg)))
4111
4112 (defun org-indent-item (arg)
4113 "Indent a local list item."
4114 (interactive "p")
4115 (unless (org-at-item-p)
4116 (error "Not on an item"))
4117 (save-excursion
4118 (let (beg end ind ind1)
4119 (if (memq last-command '(org-shiftmetaright org-shiftmetaleft))
4120 (setq beg org-last-indent-begin-marker
4121 end org-last-indent-end-marker)
4122 (org-beginning-of-item)
4123 (setq beg (move-marker org-last-indent-begin-marker (point)))
4124 (org-end-of-item)
4125 (setq end (move-marker org-last-indent-end-marker (point))))
4126 (goto-char beg)
4127 (skip-chars-forward " \t") (setq ind (current-column))
4128 (if (< (+ arg ind) 0) (error "Cannot outdent beyond margin"))
4129 (while (< (point) end)
4130 (beginning-of-line 1)
4131 (skip-chars-forward " \t") (setq ind1 (current-column))
4132 (delete-region (point-at-bol) (point))
4133 (indent-to-column (+ ind1 arg))
4134 (beginning-of-line 2)))))
4135
4136 ;;; Archiving
4137
4138 (defun org-archive-subtree ()
4139 "Move the current subtree to the archive.
4140 The archive can be a certain top-level heading in the current file, or in
4141 a different file. The tree will be moved to that location, the subtree
4142 heading be marked DONE, and the current time will be added."
4143 (interactive)
4144 ;; Save all relevant TODO keyword-relatex variables
4145 (let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler
4146 (tr-org-todo-keywords org-todo-keywords)
4147 (tr-org-todo-interpretation org-todo-interpretation)
4148 (tr-org-done-string org-done-string)
4149 (tr-org-todo-regexp org-todo-regexp)
4150 (tr-org-todo-line-regexp org-todo-line-regexp)
4151 (this-buffer (current-buffer))
4152 file heading buffer level newfile-p)
4153 (if (string-match "\\(.*\\)::\\(.*\\)" org-archive-location)
4154 (progn
4155 (setq file (format (match-string 1 org-archive-location)
4156 (file-name-nondirectory buffer-file-name))
4157 heading (match-string 2 org-archive-location)))
4158 (error "Invalid `org-archive-location'"))
4159 (if (> (length file) 0)
4160 (setq newfile-p (not (file-exists-p file))
4161 buffer (find-file-noselect file))
4162 (setq buffer (current-buffer)))
4163 (unless buffer
4164 (error "Cannot access file \"%s\"" file))
4165 (if (and (> (length heading) 0)
4166 (string-match "^\\*+" heading))
4167 (setq level (match-end 0))
4168 (setq heading nil level 0))
4169 (save-excursion
4170 ;; We first only copy, in case something goes wrong
4171 ;; we need to protect this-command, to avoid kill-region sets it,
4172 ;; which would lead to duplication of subtrees
4173 (let (this-command) (org-copy-subtree))
4174 (set-buffer buffer)
4175 ;; Enforce org-mode for the archive buffer
4176 (if (not (eq major-mode 'org-mode))
4177 ;; Force the mode for future visits.
4178 (let ((org-insert-mode-line-in-empty-file t))
4179 (call-interactively 'org-mode)))
4180 (when newfile-p
4181 (goto-char (point-max))
4182 (insert (format "\nArchived entries from file %s\n\n"
4183 (buffer-file-name this-buffer))))
4184 ;; Force the TODO keywords of the original buffer
4185 (let ((org-todo-line-regexp tr-org-todo-line-regexp)
4186 (org-todo-keywords tr-org-todo-keywords)
4187 (org-todo-interpretation tr-org-todo-interpretation)
4188 (org-done-string tr-org-done-string)
4189 (org-todo-regexp tr-org-todo-regexp)
4190 (org-todo-line-regexp tr-org-todo-line-regexp))
4191 (goto-char (point-min))
4192 (if heading
4193 (progn
4194 (if (re-search-forward
4195 (concat "\\(^\\|\r\\)"
4196 (regexp-quote heading) "[ \t]*\\($\\|\r\\)")
4197 nil t)
4198 (goto-char (match-end 0))
4199 ;; Heading not found, just insert it at the end
4200 (goto-char (point-max))
4201 (or (bolp) (insert "\n"))
4202 (insert "\n" heading "\n")
4203 (end-of-line 0))
4204 ;; Make the heading visible, and the following as well
4205 (let ((org-show-following-heading t)) (org-show-hierarchy-above))
4206 (if (re-search-forward
4207 (concat "^" (regexp-quote (make-string level ?*)) "[ \t]")
4208 nil t)
4209 (progn (goto-char (match-beginning 0)) (insert "\n")
4210 (beginning-of-line 0))
4211 (goto-char (point-max)) (insert "\n")))
4212 (goto-char (point-max)) (insert "\n"))
4213 ;; Paste
4214 (org-paste-subtree (1+ level))
4215 ;; Mark the entry as done, i.e. set to last work in org-todo-keywords
4216 (if org-archive-mark-done
4217 (org-todo (length org-todo-keywords)))
4218 ;; Move cursor to right after the TODO keyword
4219 (when org-archive-stamp-time
4220 (beginning-of-line 1)
4221 (looking-at org-todo-line-regexp)
4222 (goto-char (or (match-end 2) (match-beginning 3)))
4223 (insert "(" (format-time-string (cdr org-time-stamp-formats)
4224 (org-current-time))
4225 ")"))
4226 ;; Save the buffer, if it is not the same buffer.
4227 (if (not (eq this-buffer buffer)) (save-buffer))))
4228 ;; Here we are back in the original buffer. Everything seems to have
4229 ;; worked. So now cut the tree and finish up.
4230 (let (this-command) (org-cut-subtree))
4231 (if (and (not (eobp)) (looking-at "[ \t]*$")) (kill-line))
4232 (message "Subtree archived %s"
4233 (if (eq this-buffer buffer)
4234 (concat "under heading: " heading)
4235 (concat "in file: " (abbreviate-file-name file))))))
4236
4237 ;;; Completion
4238
4239 (defun org-complete (&optional arg)
4240 "Perform completion on word at point.
4241 At the beginning of a headline, this completes TODO keywords as given in
4242 `org-todo-keywords'.
4243 If the current word is preceded by a backslash, completes the TeX symbols
4244 that are supported for HTML support.
4245 If the current word is preceded by \"#+\", completes special words for
4246 setting file options.
4247 At all other locations, this simply calls `ispell-complete-word'."
4248 (interactive "P")
4249 (catch 'exit
4250 (let* ((end (point))
4251 (beg1 (save-excursion
4252 (if (equal (char-before (point)) ?\ ) (backward-char 1))
4253 (skip-chars-backward "a-zA-Z_@0-9")
4254 (point)))
4255 (beg (save-excursion
4256 (if (equal (char-before (point)) ?\ ) (backward-char 1))
4257 (skip-chars-backward "a-zA-Z0-9_:$")
4258 (point)))
4259 (camel (equal (char-before beg) ?*))
4260 (tag (equal (char-before beg1) ?:))
4261 (texp (equal (char-before beg) ?\\))
4262 (opt (equal (buffer-substring (max (point-at-bol) (- beg 2))
4263 beg)
4264 "#+"))
4265 (completion-ignore-case opt)
4266 (type nil)
4267 (tbl nil)
4268 (table (cond
4269 (opt
4270 (setq type :opt)
4271 (mapcar (lambda (x)
4272 (string-match "^#\\+\\(\\([A-Z_]+:?\\).*\\)" x)
4273 (cons (match-string 2 x) (match-string 1 x)))
4274 (org-split-string (org-get-current-options) "\n")))
4275 (texp
4276 (setq type :tex)
4277 org-html-entities)
4278 ((string-match "\\`\\*+[ \t]*\\'"
4279 (buffer-substring (point-at-bol) beg))
4280 (setq type :todo)
4281 (mapcar 'list org-todo-keywords))
4282 (camel
4283 (setq type :camel)
4284 (save-excursion
4285 (goto-char (point-min))
4286 (while (re-search-forward org-todo-line-regexp nil t)
4287 (push (list
4288 (if org-file-link-context-use-camel-case
4289 (org-make-org-heading-camel (match-string 3) t)
4290 (org-make-org-heading-search-string
4291 (match-string 3) t)))
4292 tbl)))
4293 tbl)
4294 (tag (setq type :tag beg beg1)
4295 (or org-tag-alist (org-get-buffer-tags)))
4296 (t (progn (ispell-complete-word arg) (throw 'exit nil)))))
4297 (pattern (buffer-substring-no-properties beg end))
4298 (completion (try-completion pattern table)))
4299 (cond ((eq completion t)
4300 (if (equal type :opt)
4301 (insert (substring (cdr (assoc (upcase pattern) table))
4302 (length pattern)))))
4303 ((null completion)
4304 (message "Can't find completion for \"%s\"" pattern)
4305 (ding))
4306 ((not (string= pattern completion))
4307 (delete-region beg end)
4308 (if (string-match " +$" completion)
4309 (setq completion (replace-match "" t t completion)))
4310 (insert completion)
4311 (if (get-buffer-window "*Completions*")
4312 (delete-window (get-buffer-window "*Completions*")))
4313 (if (assoc completion table)
4314 (if (eq type :todo) (insert " ")
4315 (if (eq type :tag) (insert ":"))))
4316 (if (and (equal type :opt) (assoc completion table))
4317 (message "%s" (substitute-command-keys
4318 "Press \\[org-complete] again to insert example settings"))))
4319 (t
4320 (message "Making completion list...")
4321 (let ((list (sort (all-completions pattern table) 'string<)))
4322 (with-output-to-temp-buffer "*Completions*"
4323 (condition-case nil
4324 ;; Protection needed for XEmacs and emacs 21
4325 (display-completion-list list pattern)
4326 (error (display-completion-list list)))))
4327 (message "Making completion list...%s" "done"))))))
4328
4329 ;;; Comments, TODO and DEADLINE
4330
4331 (defun org-toggle-comment ()
4332 "Change the COMMENT state of an entry."
4333 (interactive)
4334 (save-excursion
4335 (org-back-to-heading)
4336 (if (looking-at (concat outline-regexp
4337 "\\( +\\<" org-comment-string "\\>\\)"))
4338 (replace-match "" t t nil 1)
4339 (if (looking-at outline-regexp)
4340 (progn
4341 (goto-char (match-end 0))
4342 (insert " " org-comment-string))))))
4343
4344 (defvar org-last-todo-state-is-todo nil
4345 "This is non-nil when the last TODO state change led to a TODO state.
4346 If the last change removed the TODO tag or switched to DONE, then
4347 this is nil.")
4348
4349 (defun org-todo (&optional arg)
4350 "Change the TODO state of an item.
4351 The state of an item is given by a keyword at the start of the heading,
4352 like
4353 *** TODO Write paper
4354 *** DONE Call mom
4355
4356 The different keywords are specified in the variable `org-todo-keywords'.
4357 By default the available states are \"TODO\" and \"DONE\".
4358 So for this example: when the item starts with TODO, it is changed to DONE.
4359 When it starts with DONE, the DONE is removed. And when neither TODO nor
4360 DONE are present, add TODO at the beginning of the heading.
4361
4362 With prefix arg, use completion to determine the new state. With numeric
4363 prefix arg, switch to that state."
4364 (interactive "P")
4365 (save-excursion
4366 (org-back-to-heading)
4367 (if (looking-at outline-regexp) (goto-char (match-end 0)))
4368 (or (looking-at (concat " +" org-todo-regexp " *"))
4369 (looking-at " *"))
4370 (let* ((this (match-string 1))
4371 (completion-ignore-case t)
4372 (member (member this org-todo-keywords))
4373 (tail (cdr member))
4374 (state (cond
4375 ((equal arg '(4))
4376 ;; Read a state with completion
4377 (completing-read "State: " (mapcar (lambda(x) (list x))
4378 org-todo-keywords)
4379 nil t))
4380 ((eq arg 'right)
4381 (if this
4382 (if tail (car tail) nil)
4383 (car org-todo-keywords)))
4384 ((eq arg 'left)
4385 (if (equal member org-todo-keywords)
4386 nil
4387 (if this
4388 (nth (- (length org-todo-keywords) (length tail) 2)
4389 org-todo-keywords)
4390 org-done-string)))
4391 (arg
4392 ;; user requests a specific state
4393 (nth (1- (prefix-numeric-value arg))
4394 org-todo-keywords))
4395 ((null member) (car org-todo-keywords))
4396 ((null tail) nil) ;; -> first entry
4397 ((eq org-todo-interpretation 'sequence)
4398 (car tail))
4399 ((memq org-todo-interpretation '(type priority))
4400 (if (eq this-command last-command)
4401 (car tail)
4402 (if (> (length tail) 0) org-done-string nil)))
4403 (t nil)))
4404 (next (if state (concat " " state " ") " ")))
4405 (replace-match next t t)
4406 (setq org-last-todo-state-is-todo
4407 (not (equal state org-done-string)))
4408 (when org-log-done
4409 (if (equal state org-done-string)
4410 (org-add-planning-info 'closed (current-time) 'scheduled)
4411 (if (not this)
4412 (org-add-planning-info nil nil 'closed))))
4413 ;; Fixup tag positioning
4414 (and org-auto-align-tags (org-set-tags nil t))
4415 (run-hooks 'org-after-todo-state-change-hook)))
4416 ;; Fixup cursor location if close to the keyword
4417 (if (and (outline-on-heading-p)
4418 (not (bolp))
4419 (save-excursion (beginning-of-line 1)
4420 (looking-at org-todo-line-regexp))
4421 (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
4422 (progn
4423 (goto-char (or (match-end 2) (match-end 1)))
4424 (just-one-space))))
4425
4426 (defun org-log-done (&optional undone)
4427 "Add a time stamp logging that a TODO entry has been closed.
4428 When UNDONE is non-nil, remove such a time stamp again."
4429 (interactive)
4430 (let (beg end col)
4431 (save-excursion
4432 (org-back-to-heading t)
4433 (setq beg (point))
4434 (looking-at (concat outline-regexp " *"))
4435 (goto-char (match-end 0))
4436 (setq col (current-column))
4437 (outline-next-heading)
4438 (setq end (point))
4439 (goto-char beg)
4440 (when (re-search-forward (concat
4441 "[\r\n]\\([ \t]*"
4442 (regexp-quote org-closed-string)
4443 " *\\[.*?\\][^\n\r]*[\n\r]?\\)") end t)
4444 (delete-region (match-beginning 1) (match-end 1)))
4445 (unless undone
4446 (org-back-to-heading t)
4447 (skip-chars-forward "^\n\r")
4448 (goto-char (min (1+ (point)) (point-max)))
4449 (when (not (member (char-before) '(?\r ?\n)))
4450 (insert "\n"))
4451 (indent-to col)
4452 (insert org-closed-string " "
4453 (format-time-string
4454 (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")
4455 (org-current-time))
4456 "\n")))))
4457
4458 (defun org-show-todo-tree (arg)
4459 "Make a compact tree which shows all headlines marked with TODO.
4460 The tree will show the lines where the regexp matches, and all higher
4461 headlines above the match.
4462 With \\[universal-argument] prefix, also show the DONE entries.
4463 With a numeric prefix N, construct a sparse tree for the Nth element
4464 of `org-todo-keywords'."
4465 (interactive "P")
4466 (let ((case-fold-search nil)
4467 (kwd-re
4468 (cond ((null arg) org-not-done-regexp)
4469 ((equal arg '(4)) org-todo-regexp)
4470 ((<= (prefix-numeric-value arg) (length org-todo-keywords))
4471 (regexp-quote (nth (1- (prefix-numeric-value arg))
4472 org-todo-keywords)))
4473 (t (error "Invalid prefix argument: %s" arg)))))
4474 (message "%d TODO entries found"
4475 (org-occur (concat "^" outline-regexp " +" kwd-re )))))
4476
4477 (defun org-deadline ()
4478 "Insert the DEADLINE: string to make a deadline.
4479 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
4480 to modify it to the correct date."
4481 (interactive)
4482 (org-add-planning-info 'deadline nil 'closed))
4483
4484 (defun org-schedule ()
4485 "Insert the SCHEDULED: string to schedule a TODO item.
4486 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
4487 to modify it to the correct date."
4488 (interactive)
4489 (org-add-planning-info 'scheduled nil 'closed))
4490
4491 (defun org-add-planning-info (what &optional time &rest remove)
4492 "Insert new timestamp with keyword in the line directly after the headline.
4493 WHAT indicates what kind of time stamp to add. TIME indicated the time to use.
4494 If non is given, the user is prompted for a date.
4495 REMOVE indicates what kind of entries to remove. An old WHAT entry will also
4496 be removed."
4497 (interactive)
4498 (when what (setq time (or time (org-read-date nil 'to-time))))
4499 (when (and org-insert-labeled-timestamps-at-point
4500 (member what '(scheduled deadline)))
4501 (insert
4502 (if (eq what 'scheduled) org-scheduled-string org-deadline-string)
4503 " "
4504 (format-time-string (car org-time-stamp-formats) time))
4505 (setq what nil))
4506 (save-excursion
4507 (let (beg end col list elt (buffer-invisibility-spec nil) ts)
4508 (org-back-to-heading t)
4509 (setq beg (point))
4510 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"))
4511 (goto-char (match-end 1))
4512 (setq col (current-column))
4513 (goto-char (1+ (match-end 0)))
4514 (if (and (not (looking-at outline-regexp))
4515 (looking-at (concat "[^\r\n]*?" org-keyword-time-regexp
4516 "[^\r\n]*")))
4517 (narrow-to-region (match-beginning 0) (match-end 0))
4518 (insert "\n")
4519 (backward-char 1)
4520 (narrow-to-region (point) (point))
4521 (indent-to-column col))
4522 ;; Check if we have to remove something.
4523 (setq list (cons what remove))
4524 (while list
4525 (setq elt (pop list))
4526 (goto-char (point-min))
4527 (when (or (and (eq elt 'scheduled)
4528 (re-search-forward org-scheduled-time-regexp nil t))
4529 (and (eq elt 'deadline)
4530 (re-search-forward org-deadline-time-regexp nil t))
4531 (and (eq elt 'closed)
4532 (re-search-forward org-closed-time-regexp nil t)))
4533 (replace-match "")
4534 (if (looking-at " +") (replace-match ""))))
4535 (goto-char (point-max))
4536 (when what
4537 (insert
4538 (if (not (equal (char-before) ?\ )) " " "")
4539 (cond ((eq what 'scheduled) org-scheduled-string)
4540 ((eq what 'deadline) org-deadline-string)
4541 ((eq what 'closed) org-closed-string))
4542 " ")
4543 (insert
4544 (setq ts
4545 (format-time-string
4546 (if (eq what 'closed)
4547 (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")
4548 (car org-time-stamp-formats))
4549 time))))
4550 (goto-char (point-min))
4551 (widen)
4552 (if (looking-at "[ \t]+\r?\n")
4553 (replace-match ""))
4554 ts)))
4555
4556 (defun org-occur (regexp &optional callback)
4557 "Make a compact tree which shows all matches of REGEXP.
4558 The tree will show the lines where the regexp matches, and all higher
4559 headlines above the match. It will also show the heading after the match,
4560 to make sure editing the matching entry is easy.
4561 If CALLBACK is non-nil, it is a function which is called to confirm
4562 that the match should indeed be shown."
4563 (interactive "sRegexp: ")
4564 (org-remove-occur-highlights nil nil t)
4565 (setq regexp (org-check-occur-regexp regexp))
4566 (let ((cnt 0))
4567 (save-excursion
4568 (goto-char (point-min))
4569 (org-overview)
4570 (while (re-search-forward regexp nil t)
4571 (when (or (not callback)
4572 (save-match-data (funcall callback)))
4573 (setq cnt (1+ cnt))
4574 (org-highlight-new-match (match-beginning 0) (match-end 0))
4575 (org-show-hierarchy-above))))
4576 (org-add-hook 'before-change-functions 'org-remove-occur-highlights
4577 nil 'local)
4578 (run-hooks 'org-occur-hook)
4579 (if (interactive-p)
4580 (message "%d match(es) for regexp %s" cnt regexp))
4581 cnt))
4582
4583 (defun org-show-hierarchy-above ()
4584 "Make sure point and the headings hierarchy above is visible."
4585 (catch 'exit
4586 (if (org-on-heading-p t)
4587 (org-flag-heading nil) ; only show the heading
4588 (and (or (org-invisible-p) (org-invisible-p2))
4589 (org-show-hidden-entry))) ; show entire entry
4590 (save-excursion
4591 (and org-show-following-heading
4592 (outline-next-heading)
4593 (org-flag-heading nil))) ; show the next heading
4594 (when org-show-hierarchy-above
4595 (save-excursion ; show all higher headings
4596 (while (and (condition-case nil
4597 (progn (org-up-heading-all 1) t)
4598 (error nil))
4599 (not (bobp)))
4600 (org-flag-heading nil))))))
4601
4602 ;; Overlay compatibility functions
4603 (defun org-make-overlay (beg end &optional buffer)
4604 (if (featurep 'xemacs)
4605 (make-extent beg end buffer)
4606 (make-overlay beg end buffer)))
4607 (defun org-delete-overlay (ovl)
4608 (if (featurep 'xemacs) (delete-extent ovl) (delete-overlay ovl)))
4609 (defun org-detatch-overlay (ovl)
4610 (if (featurep 'xemacs) (detach-extent ovl) (delete-overlay ovl)))
4611 (defun org-move-overlay (ovl beg end &optional buffer)
4612 (if (featurep 'xemacs)
4613 (set-extent-endpoints ovl beg end buffer)
4614 (move-overlay ovl beg end buffer)))
4615 (defun org-overlay-put (ovl prop value)
4616 (if (featurep 'xemacs)
4617 (set-extent-property ovl prop value)
4618 (overlay-put ovl prop value)))
4619
4620 (defvar org-occur-highlights nil)
4621 (defun org-highlight-new-match (beg end)
4622 "Highlight from BEG to END and mark the highlight is an occur headline."
4623 (let ((ov (org-make-overlay beg end)))
4624 (org-overlay-put ov 'face 'secondary-selection)
4625 (push ov org-occur-highlights)))
4626
4627 (defun org-remove-occur-highlights (&optional beg end noremove)
4628 "Remove the occur highlights from the buffer.
4629 BEG and END are ignored. If NOREMOVE is nil, remove this function
4630 from the `before-change-functions' in the current buffer."
4631 (interactive)
4632 (mapc 'org-delete-overlay org-occur-highlights)
4633 (setq org-occur-highlights nil)
4634 (unless noremove
4635 (remove-hook 'before-change-functions
4636 'org-remove-occur-highlights 'local)))
4637
4638 ;;; Priorities
4639
4640 (defvar org-priority-regexp ".*?\\(\\[#\\([A-Z]\\)\\] ?\\)"
4641 "Regular expression matching the priority indicator.")
4642
4643 (defvar org-remove-priority-next-time nil)
4644
4645 (defun org-priority-up ()
4646 "Increase the priority of the current item."
4647 (interactive)
4648 (org-priority 'up))
4649
4650 (defun org-priority-down ()
4651 "Decrease the priority of the current item."
4652 (interactive)
4653 (org-priority 'down))
4654
4655 (defun org-priority (&optional action)
4656 "Change the priority of an item by ARG.
4657 ACTION can be set, up, or down."
4658 (interactive)
4659 (setq action (or action 'set))
4660 (let (current new news have remove)
4661 (save-excursion
4662 (org-back-to-heading)
4663 (if (looking-at org-priority-regexp)
4664 (setq current (string-to-char (match-string 2))
4665 have t)
4666 (setq current org-default-priority))
4667 (cond
4668 ((eq action 'set)
4669 (message "Priority A-%c, SPC to remove: " org-lowest-priority)
4670 (setq new (read-char-exclusive))
4671 (cond ((equal new ?\ ) (setq remove t))
4672 ((or (< (upcase new) ?A) (> (upcase new) org-lowest-priority))
4673 (error "Priority must be between `%c' and `%c'"
4674 ?A org-lowest-priority))))
4675 ((eq action 'up)
4676 (setq new (1- current)))
4677 ((eq action 'down)
4678 (setq new (1+ current)))
4679 (t (error "Invalid action")))
4680 (setq new (min (max ?A (upcase new)) org-lowest-priority))
4681 (setq news (format "%c" new))
4682 (if have
4683 (if remove
4684 (replace-match "" t t nil 1)
4685 (replace-match news t t nil 2))
4686 (if remove
4687 (error "No priority cookie found in line")
4688 (looking-at org-todo-line-regexp)
4689 (if (match-end 2)
4690 (progn
4691 (goto-char (match-end 2))
4692 (insert " [#" news "]"))
4693 (goto-char (match-beginning 3))
4694 (insert "[#" news "] ")))))
4695 (if remove
4696 (message "Priority removed")
4697 (message "Priority of current item set to %s" news))))
4698
4699
4700 (defun org-get-priority (s)
4701 "Find priority cookie and return priority."
4702 (save-match-data
4703 (if (not (string-match org-priority-regexp s))
4704 (* 1000 (- org-lowest-priority org-default-priority))
4705 (* 1000 (- org-lowest-priority
4706 (string-to-char (match-string 2 s)))))))
4707
4708 ;;; Timestamps
4709
4710 (defvar org-last-changed-timestamp nil)
4711
4712 (defun org-time-stamp (arg)
4713 "Prompt for a date/time and insert a time stamp.
4714 If the user specifies a time like HH:MM, or if this command is called
4715 with a prefix argument, the time stamp will contain date and time.
4716 Otherwise, only the date will be included. All parts of a date not
4717 specified by the user will be filled in from the current date/time.
4718 So if you press just return without typing anything, the time stamp
4719 will represent the current date/time. If there is already a timestamp
4720 at the cursor, it will be modified."
4721 (interactive "P")
4722 (let ((fmt (if arg (cdr org-time-stamp-formats)
4723 (car org-time-stamp-formats)))
4724 (org-time-was-given nil)
4725 time)
4726 (cond
4727 ((and (org-at-timestamp-p)
4728 (eq last-command 'org-time-stamp)
4729 (eq this-command 'org-time-stamp))
4730 (insert "--")
4731 (setq time (let ((this-command this-command))
4732 (org-read-date arg 'totime)))
4733 (if org-time-was-given (setq fmt (cdr org-time-stamp-formats)))
4734 (insert (format-time-string fmt time)))
4735 ((org-at-timestamp-p)
4736 (setq time (let ((this-command this-command))
4737 (org-read-date arg 'totime)))
4738 (and (org-at-timestamp-p) (replace-match
4739 (setq org-last-changed-timestamp
4740 (format-time-string fmt time))
4741 t t))
4742 (message "Timestamp updated"))
4743 (t
4744 (setq time (let ((this-command this-command))
4745 (org-read-date arg 'totime)))
4746 (if org-time-was-given (setq fmt (cdr org-time-stamp-formats)))
4747 (insert (format-time-string fmt time))))))
4748
4749 (defun org-time-stamp-inactive (&optional arg)
4750 "Insert an inactive time stamp.
4751 An inactive time stamp is enclosed in square brackets instead of angle
4752 brackets. It is inactive in the sense that it does not trigger agenda entries,
4753 does not link to the calendar and cannot be changed with the S-cursor keys.
4754 So these are more for recording a certain time/date."
4755 (interactive "P")
4756 (let ((fmt (if arg (cdr org-time-stamp-formats)
4757 (car org-time-stamp-formats)))
4758 (org-time-was-given nil)
4759 time)
4760 (setq time (org-read-date arg 'totime))
4761 (if org-time-was-given (setq fmt (cdr org-time-stamp-formats)))
4762 (setq fmt (concat "[" (substring fmt 1 -1) "]"))
4763 (insert (format-time-string fmt time))))
4764
4765 (defvar org-date-ovl (org-make-overlay 1 1))
4766 (org-overlay-put org-date-ovl 'face 'org-warning)
4767 (org-detatch-overlay org-date-ovl)
4768
4769 (defun org-read-date (&optional with-time to-time)
4770 "Read a date and make things smooth for the user.
4771 The prompt will suggest to enter an ISO date, but you can also enter anything
4772 which will at least partially be understood by `parse-time-string'.
4773 Unrecognized parts of the date will default to the current day, month, year,
4774 hour and minute. For example,
4775 3-2-5 --> 2003-02-05
4776 feb 15 --> currentyear-02-15
4777 sep 12 9 --> 2009-09-12
4778 12:45 --> today 12:45
4779 22 sept 0:34 --> currentyear-09-22 0:34
4780 12 --> currentyear-currentmonth-12
4781 Fri --> nearest Friday (today or later)
4782 etc.
4783 The function understands only English month and weekday abbreviations,
4784 but this can be configured with the variables `parse-time-months' and
4785 `parse-time-weekdays'.
4786
4787 While prompting, a calendar is popped up - you can also select the
4788 date with the mouse (button 1). The calendar shows a period of three
4789 months. To scroll it to other months, use the keys `>' and `<'.
4790 If you don't like the calendar, turn it off with
4791 \(setq org-popup-calendar-for-date-prompt nil)
4792
4793 With optional argument TO-TIME, the date will immediately be converted
4794 to an internal time.
4795 With an optional argument WITH-TIME, the prompt will suggest to also
4796 insert a time. Note that when WITH-TIME is not set, you can still
4797 enter a time, and this function will inform the calling routine about
4798 this change. The calling routine may then choose to change the format
4799 used to insert the time stamp into the buffer to include the time."
4800 (require 'parse-time)
4801 (let* ((org-time-stamp-rounding-minutes
4802 (if (equal with-time '(16)) 0 org-time-stamp-rounding-minutes))
4803 (ct (org-current-time))
4804 (default-time
4805 ;; Default time is either today, or, when entering a range,
4806 ;; the range start.
4807 (if (save-excursion
4808 (re-search-backward
4809 (concat org-ts-regexp "--\\=") ; FIXME: exactly two minuses?
4810 (- (point) 20) t))
4811 (apply
4812 'encode-time
4813 (mapcar (lambda(x) (or x 0))
4814 (parse-time-string (match-string 1))))
4815 ct))
4816 (calendar-move-hook nil)
4817 (view-diary-entries-initially nil)
4818 (view-calendar-holidays-initially nil)
4819 (timestr (format-time-string
4820 (if with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") default-time))
4821 (prompt (format "YYYY-MM-DD [%s]: " timestr))
4822 ans ans1 ans2
4823 second minute hour day month year tl wday wday1)
4824
4825 (if org-popup-calendar-for-date-prompt
4826 (save-excursion
4827 (save-window-excursion
4828 (calendar)
4829 (calendar-forward-day (- (time-to-days default-time)
4830 (calendar-absolute-from-gregorian
4831 (calendar-current-date))))
4832 (org-eval-in-calendar nil)
4833 (let* ((old-map (current-local-map))
4834 (map (copy-keymap calendar-mode-map))
4835 (minibuffer-local-map (copy-keymap minibuffer-local-map)))
4836 (define-key map (kbd "RET") 'org-calendar-select)
4837 (define-key map (if (featurep 'xemacs) [button1] [mouse-1])
4838 'org-calendar-select-mouse)
4839 (define-key map (if (featurep 'xemacs) [button2] [mouse-2])
4840 'org-calendar-select-mouse)
4841 (define-key minibuffer-local-map [(meta shift left)]
4842 (lambda () (interactive)
4843 (org-eval-in-calendar '(calendar-backward-month 1))))
4844 (define-key minibuffer-local-map [(meta shift right)]
4845 (lambda () (interactive)
4846 (org-eval-in-calendar '(calendar-forward-month 1))))
4847 (define-key minibuffer-local-map [(shift up)]
4848 (lambda () (interactive)
4849 (org-eval-in-calendar '(calendar-backward-week 1))))
4850 (define-key minibuffer-local-map [(shift down)]
4851 (lambda () (interactive)
4852 (org-eval-in-calendar '(calendar-forward-week 1))))
4853 (define-key minibuffer-local-map [(shift left)]
4854 (lambda () (interactive)
4855 (org-eval-in-calendar '(calendar-backward-day 1))))
4856 (define-key minibuffer-local-map [(shift right)]
4857 (lambda () (interactive)
4858 (org-eval-in-calendar '(calendar-forward-day 1))))
4859 (define-key minibuffer-local-map ">"
4860 (lambda () (interactive)
4861 (org-eval-in-calendar '(scroll-calendar-left 1))))
4862 (define-key minibuffer-local-map "<"
4863 (lambda () (interactive)
4864 (org-eval-in-calendar '(scroll-calendar-right 1))))
4865 (unwind-protect
4866 (progn
4867 (use-local-map map)
4868 (setq ans (read-string prompt "" nil nil))
4869 (if (not (string-match "\\S-" ans)) (setq ans nil))
4870 (setq ans (or ans1 ans ans2)))
4871 (use-local-map old-map)))))
4872 ;; Naked prompt only
4873 (setq ans (read-string prompt "" nil timestr)))
4874 (org-detatch-overlay org-date-ovl)
4875
4876 (if (string-match
4877 "^ *\\(\\([0-9]+\\)-\\)?\\([0-1]?[0-9]\\)-\\([0-3]?[0-9]\\)\\([^-0-9]\\|$\\)" ans)
4878 (progn
4879 (setq year (if (match-end 2)
4880 (string-to-number (match-string 2 ans))
4881 (string-to-number (format-time-string "%Y")))
4882 month (string-to-number (match-string 3 ans))
4883 day (string-to-number (match-string 4 ans)))
4884 (if (< year 100) (setq year (+ 2000 year)))
4885 (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
4886 t nil ans))))
4887 (setq tl (parse-time-string ans)
4888 year (or (nth 5 tl) (string-to-number (format-time-string "%Y" ct)))
4889 month (or (nth 4 tl) (string-to-number (format-time-string "%m" ct)))
4890 day (or (nth 3 tl) (string-to-number (format-time-string "%d" ct)))
4891 hour (or (nth 2 tl) (string-to-number (format-time-string "%H" ct)))
4892 minute (or (nth 1 tl) (string-to-number (format-time-string "%M" ct)))
4893 second (or (nth 0 tl) 0)
4894 wday (nth 6 tl))
4895 (when (and wday (not (nth 3 tl)))
4896 ;; Weekday was given, but no day, so pick that day in the week
4897 ;; on or after the derived date.
4898 (setq wday1 (nth 6 (decode-time (encode-time 0 0 0 day month year))))
4899 (unless (equal wday wday1)
4900 (setq day (+ day (% (- wday wday1 -7) 7)))))
4901 (if (and (boundp 'org-time-was-given)
4902 (nth 2 tl))
4903 (setq org-time-was-given t))
4904 (if (< year 100) (setq year (+ 2000 year)))
4905 (if to-time
4906 (encode-time second minute hour day month year)
4907 (if (or (nth 1 tl) (nth 2 tl))
4908 (format "%04d-%02d-%02d %02d:%02d" year month day hour minute)
4909 (format "%04d-%02d-%02d" year month day)))))
4910
4911 (defun org-eval-in-calendar (form)
4912 "Eval FORM in the calendar window and return to current window.
4913 Also, store the cursor date in variable ans2."
4914 (let ((sw (selected-window)))
4915 (select-window (get-buffer-window "*Calendar*"))
4916 (eval form)
4917 (when (calendar-cursor-to-date)
4918 (let* ((date (calendar-cursor-to-date))
4919 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
4920 (setq ans2 (format-time-string "%Y-%m-%d" time))))
4921 (org-move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer))
4922 (select-window sw)))
4923
4924 (defun org-calendar-select ()
4925 "Return to `org-read-date' with the date currently selected.
4926 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
4927 (interactive)
4928 (when (calendar-cursor-to-date)
4929 (let* ((date (calendar-cursor-to-date))
4930 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
4931 (setq ans1 (format-time-string "%Y-%m-%d" time)))
4932 (if (active-minibuffer-window) (exit-minibuffer))))
4933
4934 (defun org-calendar-select-mouse (ev)
4935 "Return to `org-read-date' with the date currently selected.
4936 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
4937 (interactive "e")
4938 (mouse-set-point ev)
4939 (when (calendar-cursor-to-date)
4940 (let* ((date (calendar-cursor-to-date))
4941 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
4942 (setq ans1 (format-time-string "%Y-%m-%d" time)))
4943 (if (active-minibuffer-window) (exit-minibuffer))))
4944
4945 (defun org-check-deadlines (ndays)
4946 "Check if there are any deadlines due or past due.
4947 A deadline is considered due if it happens within `org-deadline-warning-days'
4948 days from today's date. If the deadline appears in an entry marked DONE,
4949 it is not shown. The prefix arg NDAYS can be used to test that many
4950 days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are shown."
4951 (interactive "P")
4952 (let* ((org-warn-days
4953 (cond
4954 ((equal ndays '(4)) 100000)
4955 (ndays (prefix-numeric-value ndays))
4956 (t org-deadline-warning-days)))
4957 (case-fold-search nil)
4958 (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>"))
4959 (callback
4960 (lambda ()
4961 (and (let ((d1 (time-to-days (current-time)))
4962 (d2 (time-to-days
4963 (org-time-string-to-time (match-string 1)))))
4964 (< (- d2 d1) org-warn-days))
4965 (not (org-entry-is-done-p))))))
4966 (message "%d deadlines past-due or due within %d days"
4967 (org-occur regexp callback)
4968 org-warn-days)))
4969
4970 (defun org-evaluate-time-range (&optional to-buffer)
4971 "Evaluate a time range by computing the difference between start and end.
4972 Normally the result is just printed in the echo area, but with prefix arg
4973 TO-BUFFER, the result is inserted just after the date stamp into the buffer.
4974 If the time range is actually in a table, the result is inserted into the
4975 next column.
4976 For time difference computation, a year is assumed to be exactly 365
4977 days in order to avoid rounding problems."
4978 (interactive "P")
4979 (save-excursion
4980 (unless (org-at-date-range-p)
4981 (goto-char (point-at-bol))
4982 (re-search-forward org-tr-regexp (point-at-eol) t))
4983 (if (not (org-at-date-range-p))
4984 (error "Not at a time-stamp range, and none found in current line")))
4985 (let* ((ts1 (match-string 1))
4986 (ts2 (match-string 2))
4987 (havetime (or (> (length ts1) 15) (> (length ts2) 15)))
4988 (match-end (match-end 0))
4989 (time1 (org-time-string-to-time ts1))
4990 (time2 (org-time-string-to-time ts2))
4991 (t1 (time-to-seconds time1))
4992 (t2 (time-to-seconds time2))
4993 (diff (abs (- t2 t1)))
4994 (negative (< (- t2 t1) 0))
4995 ;; (ys (floor (* 365 24 60 60)))
4996 (ds (* 24 60 60))
4997 (hs (* 60 60))
4998 (fy "%dy %dd %02d:%02d")
4999 (fy1 "%dy %dd")
5000 (fd "%dd %02d:%02d")
5001 (fd1 "%dd")
5002 (fh "%02d:%02d")
5003 y d h m align)
5004 (if havetime
5005 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
5006 y 0
5007 d (floor (/ diff ds)) diff (mod diff ds)
5008 h (floor (/ diff hs)) diff (mod diff hs)
5009 m (floor (/ diff 60)))
5010 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
5011 y 0
5012 d (floor (+ (/ diff ds) 0.5))
5013 h 0 m 0))
5014 (if (not to-buffer)
5015 (message (org-make-tdiff-string y d h m))
5016 (when (org-at-table-p)
5017 (goto-char match-end)
5018 (setq align t)
5019 (and (looking-at " *|") (goto-char (match-end 0))))
5020 (if (looking-at
5021 "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]")
5022 (replace-match ""))
5023 (if negative (insert " -"))
5024 (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m))
5025 (if (> d 0) (insert " " (format (if havetime fd fd1) d h m))
5026 (insert " " (format fh h m))))
5027 (if align (org-table-align))
5028 (message "Time difference inserted"))))
5029
5030 (defun org-make-tdiff-string (y d h m)
5031 (let ((fmt "")
5032 (l nil))
5033 (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ")
5034 l (push y l)))
5035 (if (> d 0) (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ")
5036 l (push d l)))
5037 (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ")
5038 l (push h l)))
5039 (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ")
5040 l (push m l)))
5041 (apply 'format fmt (nreverse l))))
5042
5043 (defun org-time-string-to-time (s)
5044 (apply 'encode-time (org-parse-time-string s)))
5045
5046 (defun org-parse-time-string (s &optional nodefault)
5047 "Parse the standard Org-mode time string.
5048 This should be a lot faster than the normal `parse-time-string'.
5049 If time is not given, defaults to 0:00. However, with optional NODEFAULT,
5050 hour and minute fields will be nil if not given."
5051 (if (string-match org-ts-regexp1 s)
5052 (list 0
5053 (if (or (match-beginning 8) (not nodefault))
5054 (string-to-number (or (match-string 8 s) "0")))
5055 (if (or (match-beginning 7) (not nodefault))
5056 (string-to-number (or (match-string 7 s) "0")))
5057 (string-to-number (match-string 4 s))
5058 (string-to-number (match-string 3 s))
5059 (string-to-number (match-string 2 s))
5060 nil nil nil)
5061 (make-list 9 0)))
5062
5063 (defun org-timestamp-up (&optional arg)
5064 "Increase the date item at the cursor by one.
5065 If the cursor is on the year, change the year. If it is on the month or
5066 the day, change that.
5067 With prefix ARG, change by that many units."
5068 (interactive "p")
5069 (org-timestamp-change (prefix-numeric-value arg)))
5070
5071 (defun org-timestamp-down (&optional arg)
5072 "Decrease the date item at the cursor by one.
5073 If the cursor is on the year, change the year. If it is on the month or
5074 the day, change that.
5075 With prefix ARG, change by that many units."
5076 (interactive "p")
5077 (org-timestamp-change (- (prefix-numeric-value arg))))
5078
5079 (defun org-timestamp-up-day (&optional arg)
5080 "Increase the date in the time stamp by one day.
5081 With prefix ARG, change that many days."
5082 (interactive "p")
5083 (if (and (not (org-at-timestamp-p))
5084 (org-on-heading-p))
5085 (org-todo 'up)
5086 (org-timestamp-change (prefix-numeric-value arg) 'day)))
5087
5088 (defun org-timestamp-down-day (&optional arg)
5089 "Decrease the date in the time stamp by one day.
5090 With prefix ARG, change that many days."
5091 (interactive "p")
5092 (if (and (not (org-at-timestamp-p))
5093 (org-on-heading-p))
5094 (org-todo 'down)
5095 (org-timestamp-change (- (prefix-numeric-value arg)) 'day)))
5096
5097 (defsubst org-pos-in-match-range (pos n)
5098 (and (match-beginning n)
5099 (<= (match-beginning n) pos)
5100 (>= (match-end n) pos)))
5101
5102 (defun org-at-timestamp-p ()
5103 "Determine if the cursor is in or at a timestamp."
5104 (interactive)
5105 (let* ((tsr org-ts-regexp2)
5106 (pos (point))
5107 (ans (or (looking-at tsr)
5108 (save-excursion
5109 (skip-chars-backward "^<\n\r\t")
5110 (if (> (point) 1) (backward-char 1))
5111 (and (looking-at tsr)
5112 (> (- (match-end 0) pos) -1))))))
5113 (and (boundp 'org-ts-what)
5114 (setq org-ts-what
5115 (cond
5116 ((org-pos-in-match-range pos 2) 'year)
5117 ((org-pos-in-match-range pos 3) 'month)
5118 ((org-pos-in-match-range pos 7) 'hour)
5119 ((org-pos-in-match-range pos 8) 'minute)
5120 ((or (org-pos-in-match-range pos 4)
5121 (org-pos-in-match-range pos 5)) 'day)
5122 (t 'day))))
5123 ans))
5124
5125 (defun org-timestamp-change (n &optional what)
5126 "Change the date in the time stamp at point.
5127 The date will be changed by N times WHAT. WHAT can be `day', `month',
5128 `year', `minute', `second'. If WHAT is not given, the cursor position
5129 in the timestamp determines what will be changed."
5130 (let ((fmt (car org-time-stamp-formats))
5131 org-ts-what
5132 (pos (point))
5133 ts time time0)
5134 (if (not (org-at-timestamp-p))
5135 (error "Not at a timestamp"))
5136 (setq org-ts-what (or what org-ts-what))
5137 (setq fmt (if (<= (abs (- (cdr org-ts-lengths)
5138 (- (match-end 0) (match-beginning 0))))
5139 1)
5140 (cdr org-time-stamp-formats)
5141 (car org-time-stamp-formats)))
5142 (setq ts (match-string 0))
5143 (replace-match "")
5144 (setq time0 (org-parse-time-string ts))
5145 (setq time
5146 (apply 'encode-time
5147 (append
5148 (list (or (car time0) 0))
5149 (list (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0)))
5150 (list (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0)))
5151 (list (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0)))
5152 (list (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0)))
5153 (list (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0)))
5154 (nthcdr 6 time0))))
5155 (if (eq what 'calendar)
5156 (let ((cal-date
5157 (save-excursion
5158 (save-match-data
5159 (set-buffer "*Calendar*")
5160 (calendar-cursor-to-date)))))
5161 (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month
5162 (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day
5163 (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year
5164 (setcar time0 (or (car time0) 0))
5165 (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
5166 (setcar (nthcdr 2 time0) (or (nth 1 time0) 0))
5167 (setq time (apply 'encode-time time0))))
5168 (insert (setq org-last-changed-timestamp (format-time-string fmt time)))
5169 (goto-char pos)
5170 ;; Try to recenter the calendar window, if any
5171 (if (and org-calendar-follow-timestamp-change
5172 (get-buffer-window "*Calendar*" t)
5173 (memq org-ts-what '(day month year)))
5174 (org-recenter-calendar (time-to-days time)))))
5175
5176 (defun org-recenter-calendar (date)
5177 "If the calendar is visible, recenter it to DATE."
5178 (let* ((win (selected-window))
5179 (cwin (get-buffer-window "*Calendar*" t))
5180 (calendar-move-hook nil))
5181 (when cwin
5182 (select-window cwin)
5183 (calendar-goto-date (if (listp date) date
5184 (calendar-gregorian-from-absolute date)))
5185 (select-window win))))
5186
5187 (defun org-goto-calendar (&optional arg)
5188 "Go to the Emacs calendar at the current date.
5189 If there is a time stamp in the current line, go to that date.
5190 A prefix ARG can be used to force the current date."
5191 (interactive "P")
5192 (let ((tsr org-ts-regexp) diff
5193 (calendar-move-hook nil)
5194 (view-calendar-holidays-initially nil)
5195 (view-diary-entries-initially nil))
5196 (if (or (org-at-timestamp-p)
5197 (save-excursion
5198 (beginning-of-line 1)
5199 (looking-at (concat ".*" tsr))))
5200 (let ((d1 (time-to-days (current-time)))
5201 (d2 (time-to-days
5202 (org-time-string-to-time (match-string 1)))))
5203 (setq diff (- d2 d1))))
5204 (calendar)
5205 (calendar-goto-today)
5206 (if (and diff (not arg)) (calendar-forward-day diff))))
5207
5208 (defun org-date-from-calendar ()
5209 "Insert time stamp corresponding to cursor date in *Calendar* buffer.
5210 If there is already a time stamp at the cursor position, update it."
5211 (interactive)
5212 (org-timestamp-change 0 'calendar))
5213
5214 ;;; Agenda, and Diary Integration
5215
5216 ;;; Define the mode
5217
5218 (defvar org-agenda-mode-map (make-sparse-keymap)
5219 "Keymap for `org-agenda-mode'.")
5220
5221 (defvar org-agenda-menu) ; defined later in this file.
5222 (defvar org-agenda-follow-mode nil)
5223 (defvar org-agenda-show-log nil)
5224 (defvar org-agenda-buffer-name "*Org Agenda*")
5225 (defvar org-agenda-redo-command nil)
5226 (defvar org-agenda-mode-hook nil)
5227 (defvar org-agenda-type nil)
5228 (defvar org-agenda-force-single-file nil)
5229
5230 (defun org-agenda-mode ()
5231 "Mode for time-sorted view on action items in Org-mode files.
5232
5233 The following commands are available:
5234
5235 \\{org-agenda-mode-map}"
5236 (interactive)
5237 (kill-all-local-variables)
5238 (setq major-mode 'org-agenda-mode)
5239 (setq mode-name "Org-Agenda")
5240 (use-local-map org-agenda-mode-map)
5241 (easy-menu-add org-agenda-menu)
5242 (if org-startup-truncated (setq truncate-lines t))
5243 (org-add-hook 'post-command-hook 'org-agenda-post-command-hook nil 'local)
5244 (org-add-hook 'pre-command-hook 'org-unhighlight nil 'local)
5245 (unless org-agenda-keep-modes
5246 (setq org-agenda-follow-mode org-agenda-start-with-follow-mode
5247 org-agenda-show-log nil))
5248 (easy-menu-change
5249 '("Agenda") "Agenda Files"
5250 (append
5251 (list
5252 (vector
5253 (if (get 'org-agenda-files 'org-restrict)
5254 "Restricted to single file"
5255 "Edit File List")
5256 '(org-edit-agenda-file-list)
5257 (not (get 'org-agenda-files 'org-restrict)))
5258 "--")
5259 (mapcar 'org-file-menu-entry (org-agenda-files))))
5260 (org-agenda-set-mode-name)
5261 (apply
5262 (if (fboundp 'run-mode-hooks) 'run-mode-hooks 'run-hooks)
5263 (list 'org-agenda-mode-hook)))
5264
5265 (define-key org-agenda-mode-map "\C-i" 'org-agenda-goto)
5266 (define-key org-agenda-mode-map [(tab)] 'org-agenda-goto)
5267 (define-key org-agenda-mode-map "\C-m" 'org-agenda-switch-to)
5268 (define-key org-agenda-mode-map " " 'org-agenda-show)
5269 (define-key org-agenda-mode-map "\C-c\C-t" 'org-agenda-todo)
5270 (define-key org-agenda-mode-map "o" 'delete-other-windows)
5271 (define-key org-agenda-mode-map "L" 'org-agenda-recenter)
5272 (define-key org-agenda-mode-map "t" 'org-agenda-todo)
5273 (define-key org-agenda-mode-map ":" 'org-agenda-set-tags)
5274 (define-key org-agenda-mode-map "." 'org-agenda-goto-today)
5275 (define-key org-agenda-mode-map "d" 'org-agenda-day-view)
5276 (define-key org-agenda-mode-map "w" 'org-agenda-week-view)
5277 (define-key org-agenda-mode-map (org-key 'S-right) 'org-agenda-date-later)
5278 (define-key org-agenda-mode-map (org-key 'S-left) 'org-agenda-date-earlier)
5279 (define-key org-agenda-mode-map [?\C-c ?\C-x (right)] 'org-agenda-date-later)
5280 (define-key org-agenda-mode-map [?\C-c ?\C-x (left)] 'org-agenda-date-earlier)
5281
5282 (define-key org-agenda-mode-map ">" 'org-agenda-date-prompt)
5283 (define-key org-agenda-mode-map "\C-c\C-s" 'org-agenda-schedule)
5284 (define-key org-agenda-mode-map "\C-c\C-d" 'org-agenda-deadline)
5285 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
5286 (while l (define-key org-agenda-mode-map
5287 (int-to-string (pop l)) 'digit-argument)))
5288
5289 (define-key org-agenda-mode-map "f" 'org-agenda-follow-mode)
5290 (define-key org-agenda-mode-map "l" 'org-agenda-log-mode)
5291 (define-key org-agenda-mode-map "D" 'org-agenda-toggle-diary)
5292 (define-key org-agenda-mode-map "g" 'org-agenda-toggle-time-grid)
5293 (define-key org-agenda-mode-map "r" 'org-agenda-redo)
5294 (define-key org-agenda-mode-map "q" 'org-agenda-quit)
5295 (define-key org-agenda-mode-map "x" 'org-agenda-exit)
5296 (define-key org-agenda-mode-map "P" 'org-agenda-show-priority)
5297 (define-key org-agenda-mode-map "T" 'org-agenda-show-tags)
5298 (define-key org-agenda-mode-map "n" 'next-line)
5299 (define-key org-agenda-mode-map "p" 'previous-line)
5300 (define-key org-agenda-mode-map "\C-n" 'org-agenda-next-date-line)
5301 (define-key org-agenda-mode-map "\C-p" 'org-agenda-previous-date-line)
5302 (define-key org-agenda-mode-map "," 'org-agenda-priority)
5303 (define-key org-agenda-mode-map "\C-c," 'org-agenda-priority)
5304 (define-key org-agenda-mode-map "i" 'org-agenda-diary-entry)
5305 (define-key org-agenda-mode-map "c" 'org-agenda-goto-calendar)
5306 (eval-after-load "calendar"
5307 '(define-key calendar-mode-map org-calendar-to-agenda-key
5308 'org-calendar-goto-agenda))
5309 (define-key org-agenda-mode-map "C" 'org-agenda-convert-date)
5310 (define-key org-agenda-mode-map "m" 'org-agenda-phases-of-moon)
5311 (define-key org-agenda-mode-map "M" 'org-agenda-phases-of-moon)
5312 (define-key org-agenda-mode-map "s" 'org-agenda-sunrise-sunset)
5313 (define-key org-agenda-mode-map "S" 'org-agenda-sunrise-sunset)
5314 (define-key org-agenda-mode-map "h" 'org-agenda-holidays)
5315 (define-key org-agenda-mode-map "H" 'org-agenda-holidays)
5316 (define-key org-agenda-mode-map "+" 'org-agenda-priority-up)
5317 (define-key org-agenda-mode-map "-" 'org-agenda-priority-down)
5318 (define-key org-agenda-mode-map (org-key 'S-up) 'org-agenda-priority-up)
5319 (define-key org-agenda-mode-map (org-key 'S-down) 'org-agenda-priority-down)
5320 (define-key org-agenda-mode-map [?\C-c ?\C-x (up)] 'org-agenda-priority-up)
5321 (define-key org-agenda-mode-map [?\C-c ?\C-x (down)] 'org-agenda-priority-down)
5322 (define-key org-agenda-mode-map [(right)] 'org-agenda-later)
5323 (define-key org-agenda-mode-map [(left)] 'org-agenda-earlier)
5324 (define-key org-agenda-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files)
5325 (defvar org-agenda-keymap (copy-keymap org-agenda-mode-map)
5326 "Local keymap for agenda entries from Org-mode.")
5327
5328 (define-key org-agenda-keymap
5329 (if (featurep 'xemacs) [(button2)] [(mouse-2)]) 'org-agenda-goto-mouse)
5330 (define-key org-agenda-keymap
5331 (if (featurep 'xemacs) [(button3)] [(mouse-3)]) 'org-agenda-show-mouse)
5332 (when org-agenda-mouse-1-follows-link
5333 (define-key org-agenda-keymap [follow-link] 'mouse-face))
5334 (easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu"
5335 '("Agenda"
5336 ("Agenda Files")
5337 "--"
5338 ["Show" org-agenda-show t]
5339 ["Go To (other window)" org-agenda-goto t]
5340 ["Go To (one window)" org-agenda-switch-to t]
5341 ["Follow Mode" org-agenda-follow-mode
5342 :style toggle :selected org-agenda-follow-mode :active t]
5343 "--"
5344 ["Cycle TODO" org-agenda-todo t]
5345 ("Tags"
5346 ["Show all Tags" org-agenda-show-tags t]
5347 ["Set Tags" org-agenda-set-tags t])
5348 ("Schedule"
5349 ["Schedule" org-agenda-schedule t]
5350 ["Set Deadline" org-agenda-deadline t]
5351 "--"
5352 ["Reschedule +1 day" org-agenda-date-later (org-agenda-check-type nil 'agenda 'timeline)]
5353 ["Reschedule -1 day" org-agenda-date-earlier (org-agenda-check-type nil 'agenda 'timeline)]
5354 ["Reschedule to ..." org-agenda-date-prompt (org-agenda-check-type nil 'agenda 'timeline)])
5355 ("Priority"
5356 ["Set Priority" org-agenda-priority t]
5357 ["Increase Priority" org-agenda-priority-up t]
5358 ["Decrease Priority" org-agenda-priority-down t]
5359 ["Show Priority" org-agenda-show-priority t])
5360 "--"
5361 ;; ["New agenda command" org-agenda t]
5362 ["Rebuild buffer" org-agenda-redo t]
5363 "--"
5364 ["Goto Today" org-agenda-goto-today (org-agenda-check-type nil 'agenda 'timeline)]
5365 ["Next Dates" org-agenda-later (org-agenda-check-type nil 'agenda)]
5366 ["Previous Dates" org-agenda-earlier (org-agenda-check-type nil 'agenda)]
5367 "--"
5368 ["Day View" org-agenda-day-view :active (org-agenda-check-type nil 'agenda)
5369 :style radio :selected (equal org-agenda-ndays 1)]
5370 ["Week View" org-agenda-week-view :active (org-agenda-check-type nil 'agenda)
5371 :style radio :selected (equal org-agenda-ndays 7)]
5372 "--"
5373 ["Show Logbook entries" org-agenda-log-mode
5374 :style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)]
5375 ["Include Diary" org-agenda-toggle-diary
5376 :style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)]
5377 ["Use Time Grid" org-agenda-toggle-time-grid
5378 :style toggle :selected org-agenda-use-time-grid :active (org-agenda-check-type nil 'agenda)]
5379 "--"
5380 ["New Diary Entry" org-agenda-diary-entry (org-agenda-check-type nil 'agenda 'timeline)]
5381 ("Calendar Commands"
5382 ["Goto Calendar" org-agenda-goto-calendar (org-agenda-check-type nil 'agenda 'timeline)]
5383 ["Phases of the Moon" org-agenda-phases-of-moon (org-agenda-check-type nil 'agenda 'timeline)]
5384 ["Sunrise/Sunset" org-agenda-sunrise-sunset (org-agenda-check-type nil 'agenda 'timeline)]
5385 ["Holidays" org-agenda-holidays (org-agenda-check-type nil 'agenda 'timeline)]
5386 ["Convert" org-agenda-convert-date (org-agenda-check-type nil 'agenda 'timeline)])
5387 ["Create iCalendar file" org-export-icalendar-combine-agenda-files t]
5388 "--"
5389 ["Quit" org-agenda-quit t]
5390 ["Exit and Release Buffers" org-agenda-exit t]
5391 ))
5392
5393 ;;;###autoload
5394 (defun org-agenda (arg)
5395 "Dispatch agenda commands to collect entries to the agenda buffer.
5396 Prompts for a character to select a command. Any prefix arg will be passed
5397 on to the selected command. The default selections are:
5398
5399 a Call `org-agenda' to display the agenda for the current day or week.
5400 t Call `org-todo-list' to display the global todo list.
5401 T Call `org-todo-list' to display the global todo list, select only
5402 entries with a specific TODO keyword (the user gets a prompt).
5403 m Call `org-tags-view' to display headlines with tags matching
5404 a condition (the user is prompted for the condition).
5405 M Like `m', but select only TODO entries, no ordinary headlines.
5406
5407 More commands can be added by configuring the variable
5408 `org-agenda-custom-commands'. In particular, specific tags and TODO keyword
5409 searches can be pre-defined in this way.
5410
5411 If the current buffer is in Org-mode and visiting a file, you can also
5412 first press `1' to indicate that the agenda should be temporarily (until the
5413 next use of \\[org-agenda]) restricted to the current file."
5414 (interactive "P")
5415 (catch 'exit
5416 (let ((restrict-ok (and buffer-file-name (eq major-mode 'org-mode)))
5417 (custom org-agenda-custom-commands)
5418 c entry key type string)
5419 (put 'org-agenda-files 'org-restrict nil)
5420 (save-window-excursion
5421 (delete-other-windows)
5422 (switch-to-buffer-other-window " *Agenda Commands*")
5423 (erase-buffer)
5424 (insert
5425 "Press key for an agenda command:
5426 --------------------------------
5427 a Agenda for current week or day
5428 t List of all TODO entries T Entries with special TODO kwd
5429 m Match a TAGS query M Like m, but only TODO entries
5430 C Configure your own agenda commands")
5431 (while (setq entry (pop custom))
5432 (setq key (car entry) type (nth 1 entry) string (nth 2 entry))
5433 (insert (format "\n%-4s%-14s: %s"
5434 key
5435 (cond
5436 ((eq type 'tags) "Tags query")
5437 ((eq type 'todo) "TODO keyword")
5438 ((eq type 'tags-tree) "Tags tree")
5439 ((eq type 'todo-tree) "TODO kwd tree")
5440 ((eq type 'occur-tree) "Occur tree")
5441 (t "???"))
5442 (org-add-props string nil 'face 'org-warning))))
5443 (goto-char (point-min))
5444 (if (fboundp 'fit-window-to-buffer) (fit-window-to-buffer))
5445 (message "Press key for agenda command%s"
5446 (if restrict-ok ", or [1] to restrict to current file" ""))
5447 (setq c (read-char-exclusive))
5448 (message "")
5449 (when (equal c ?1)
5450 (if restrict-ok
5451 (put 'org-agenda-files 'org-restrict (list buffer-file-name))
5452 (error "Cannot restrict agenda to current buffer"))
5453 (message "Press key for agenda command%s"
5454 (if restrict-ok " (restricted to current file)" ""))
5455 (setq c (read-char-exclusive))
5456 (message "")))
5457 (require 'calendar) ; FIXME: can we avoid this for some commands?
5458 ;; For example the todo list should not need it (but does...)
5459 (cond
5460 ((equal c ?C) (customize-variable 'org-agenda-custom-commands))
5461 ((equal c ?a) (call-interactively 'org-agenda-list))
5462 ((equal c ?t) (call-interactively 'org-todo-list))
5463 ((equal c ?T) (org-call-with-arg 'org-todo-list (or arg '(4))))
5464 ((equal c ?m) (call-interactively 'org-tags-view))
5465 ((equal c ?M) (org-call-with-arg 'org-tags-view (or arg '(4))))
5466 ((setq entry (assoc (char-to-string c) org-agenda-custom-commands))
5467 (setq type (nth 1 entry) string (nth 2 entry))
5468 (cond
5469 ((eq type 'tags)
5470 (org-tags-view current-prefix-arg string))
5471 ((eq type 'tags-todo)
5472 (org-tags-view '(4) string))
5473 ((eq type 'todo)
5474 (org-todo-list string))
5475 ((eq type 'tags-tree)
5476 (org-check-for-org-mode)
5477 (org-tags-sparse-tree current-prefix-arg string))
5478 ((eq type 'todo-tree)
5479 (org-check-for-org-mode)
5480 (org-occur (concat "^" outline-regexp "[ \t]*"
5481 (regexp-quote string) "\\>")))
5482 ((eq type 'occur-tree)
5483 (org-check-for-org-mode)
5484 (org-occur string))
5485 (t (error "Invalid custom agenda command type %s" type))))
5486 (t (error "Invalid key"))))))
5487
5488 (defun org-check-for-org-mode ()
5489 "Make sure current buffer is in org-mode. Error if not."
5490 (or (eq major-mode 'org-mode)
5491 (error "Cannot execute org-mode agenda command on buffer in %s."
5492 major-mode)))
5493
5494 (defun org-fit-agenda-window ()
5495 "Fit the window to the buffer size."
5496 (and org-fit-agenda-window
5497 (fboundp 'fit-window-to-buffer)
5498 (fit-window-to-buffer nil (/ (* (frame-height) 3) 4)
5499 (/ (frame-height) 2))))
5500
5501 (defun org-agenda-files (&optional unrestricted)
5502 "Get the list of agenda files.
5503 Optional UNRESTRICTED means return the full list even if a restriction
5504 is currently in place."
5505 (cond
5506 ((and (not unrestricted) (get 'org-agenda-files 'org-restrict)))
5507 ((stringp org-agenda-files) (org-read-agenda-file-list))
5508 ((listp org-agenda-files) org-agenda-files)
5509 (t (error "Invalid value of `org-agenda-files'"))))
5510
5511 (defvar org-window-configuration)
5512
5513 (defun org-edit-agenda-file-list ()
5514 "Edit the list of agenda files.
5515 Depending on setup, this either uses customize to edit the variable
5516 `org-agenda-files', or it visits the file that is holding the list. In the
5517 latter case, the buffer is set up in a way that saving it automatically kills
5518 the buffer and restores the previous window configuration."
5519 (interactive)
5520 (if (stringp org-agenda-files)
5521 (let ((cw (current-window-configuration)))
5522 (find-file org-agenda-files)
5523 (set (make-local-variable 'org-window-configuration) cw)
5524 (org-add-hook 'after-save-hook
5525 (lambda ()
5526 (set-window-configuration
5527 (prog1 org-window-configuration
5528 (kill-buffer (current-buffer))))
5529 (org-install-agenda-files-menu)
5530 (message "New agenda file list installed"))
5531 nil 'local)
5532 (message (substitute-command-keys
5533 "Edit list and finish with \\[save-buffer]")))
5534 (customize-variable 'org-agenda-files)))
5535
5536 (defun org-store-new-agenda-file-list (list)
5537 "Set new value for the agenda file list and save it correcly."
5538 (if (stringp org-agenda-files)
5539 (let ((f org-agenda-files) b)
5540 (while (setq b (find-buffer-visiting f)) (kill-buffer b))
5541 (with-temp-file f
5542 (insert (mapconcat 'identity list "\n") "\n")))
5543 (let ((org-mode-hook nil) (default-major-mode 'fundamental-mode))
5544 (setq org-agenda-files list)
5545 (customize-save-variable 'org-agenda-files org-agenda-files))))
5546
5547 (defun org-read-agenda-file-list ()
5548 "Read the list of agenda files from a file."
5549 (when (stringp org-agenda-files)
5550 (with-temp-buffer
5551 (insert-file-contents org-agenda-files)
5552 (org-split-string (buffer-string) "[ \t\r\n]*?[\r\n][ \t\r\n]*"))))
5553
5554 (defvar org-agenda-markers nil
5555 "List of all currently active markers created by `org-agenda'.")
5556 (defvar org-agenda-last-marker-time (time-to-seconds (current-time))
5557 "Creation time of the last agenda marker.")
5558
5559 (defun org-agenda-new-marker (&optional pos)
5560 "Return a new agenda marker.
5561 Org-mode keeps a list of these markers and resets them when they are
5562 no longer in use."
5563 (let ((m (copy-marker (or pos (point)))))
5564 (setq org-agenda-last-marker-time (time-to-seconds (current-time)))
5565 (push m org-agenda-markers)
5566 m))
5567
5568 (defun org-agenda-maybe-reset-markers (&optional force)
5569 "Reset markers created by `org-agenda'. But only if they are old enough."
5570 (if (or force
5571 (> (- (time-to-seconds (current-time))
5572 org-agenda-last-marker-time)
5573 5))
5574 (while org-agenda-markers
5575 (move-marker (pop org-agenda-markers) nil))))
5576
5577 (defvar org-agenda-new-buffers nil
5578 "Buffers created to visit agenda files.")
5579
5580 (defun org-get-agenda-file-buffer (file)
5581 "Get a buffer visiting FILE. If the buffer needs to be created, add
5582 it to the list of buffers which might be released later."
5583 (let ((buf (find-buffer-visiting file)))
5584 (if buf
5585 buf ; just return it
5586 ;; Make a new buffer and remember it
5587 (setq buf (find-file-noselect file))
5588 (if buf (push buf org-agenda-new-buffers))
5589 buf)))
5590
5591 (defun org-release-buffers (blist)
5592 "Release all buffers in list, asking the user for confirmation when needed.
5593 When a buffer is unmodified, it is just killed. When modified, it is saved
5594 \(if the user agrees) and then killed."
5595 (let (buf file)
5596 (while (setq buf (pop blist))
5597 (setq file (buffer-file-name buf))
5598 (when (and (buffer-modified-p buf)
5599 file
5600 (y-or-n-p (format "Save file %s? " file)))
5601 (with-current-buffer buf (save-buffer)))
5602 (kill-buffer buf))))
5603
5604 (defvar org-respect-restriction nil) ; Dynamically-scoped param.
5605
5606 (defun org-timeline (&optional include-all keep-modes)
5607 "Show a time-sorted view of the entries in the current org file.
5608 Only entries with a time stamp of today or later will be listed. With
5609 \\[universal-argument] prefix, all unfinished TODO items will also be shown,
5610 under the current date.
5611 If the buffer contains an active region, only check the region for
5612 dates."
5613 (interactive "P")
5614 (require 'calendar)
5615 (org-agenda-maybe-reset-markers 'force)
5616 (org-compile-prefix-format org-timeline-prefix-format)
5617 (let* ((dopast t)
5618 (dotodo include-all)
5619 (doclosed org-agenda-show-log)
5620 (org-agenda-keep-modes keep-modes)
5621 (entry buffer-file-name)
5622 (org-agenda-files (list buffer-file-name))
5623 (date (calendar-current-date))
5624 (win (selected-window))
5625 (pos1 (point))
5626 (beg (if (org-region-active-p) (region-beginning) (point-min)))
5627 (end (if (org-region-active-p) (region-end) (point-max)))
5628 (day-numbers (org-get-all-dates beg end 'no-ranges
5629 t doclosed ; always include today
5630 org-timeline-show-empty-dates))
5631 (today (time-to-days (current-time)))
5632 (org-respect-restriction t)
5633 (past t)
5634 args
5635 s e rtn d emptyp)
5636 (setq org-agenda-redo-command
5637 (list 'progn
5638 (list 'switch-to-buffer-other-window (current-buffer))
5639 (list 'org-timeline (list 'quote include-all) t)))
5640 (if (not dopast)
5641 ;; Remove past dates from the list of dates.
5642 (setq day-numbers (delq nil (mapcar (lambda(x)
5643 (if (>= x today) x nil))
5644 day-numbers))))
5645 (switch-to-buffer-other-window
5646 (get-buffer-create org-agenda-buffer-name))
5647 (setq buffer-read-only nil)
5648 (erase-buffer)
5649 (org-agenda-mode) (setq buffer-read-only nil)
5650 (set (make-local-variable 'org-agenda-type) 'timeline)
5651 (if doclosed (push :closed args))
5652 (push :timestamp args)
5653 (if dotodo (push :todo args))
5654 (while (setq d (pop day-numbers))
5655 (if (and (listp d) (eq (car d) :omitted))
5656 (progn
5657 (setq s (point))
5658 (insert (format "\n[... %d empty days omitted]\n\n" (cdr d)))
5659 (put-text-property s (1- (point)) 'face 'org-level-3))
5660 (if (listp d) (setq d (car d) emptyp t) (setq emptyp nil))
5661 (if (and (>= d today)
5662 dopast
5663 past)
5664 (progn
5665 (setq past nil)
5666 (insert (make-string 79 ?-) "\n")))
5667 (setq date (calendar-gregorian-from-absolute d))
5668 (setq s (point))
5669 (setq rtn (and (not emptyp)
5670 (apply 'org-agenda-get-day-entries
5671 entry date args)))
5672 (if (or rtn (equal d today) org-timeline-show-empty-dates)
5673 (progn
5674 (insert (calendar-day-name date) " "
5675 (number-to-string (extract-calendar-day date)) " "
5676 (calendar-month-name (extract-calendar-month date)) " "
5677 (number-to-string (extract-calendar-year date)) "\n")
5678 (put-text-property s (1- (point)) 'face
5679 'org-level-3)
5680 (if (equal d today)
5681 (put-text-property s (1- (point)) 'org-today t))
5682 (and rtn (insert (org-finalize-agenda-entries rtn) "\n"))
5683 (put-text-property s (1- (point)) 'day d)))))
5684 (goto-char (point-min))
5685 (setq buffer-read-only t)
5686 (goto-char (or (text-property-any (point-min) (point-max) 'org-today t)
5687 (point-min)))
5688 (when (not org-select-timeline-window)
5689 (select-window win)
5690 (goto-char pos1))))
5691
5692 ;;;###autoload
5693 (defun org-agenda-list (&optional include-all start-day ndays keep-modes)
5694 "Produce a weekly view from all files in variable `org-agenda-files'.
5695 The view will be for the current week, but from the overview buffer you
5696 will be able to go to other weeks.
5697 With one \\[universal-argument] prefix argument INCLUDE-ALL, all unfinished TODO items will
5698 also be shown, under the current date.
5699 With two \\[universal-argument] prefix argument INCLUDE-ALL, all TODO entries marked DONE
5700 on the days are also shown. See the variable `org-log-done' for how
5701 to turn on logging.
5702 START-DAY defaults to TODAY, or to the most recent match for the weekday
5703 given in `org-agenda-start-on-weekday'.
5704 NDAYS defaults to `org-agenda-ndays'."
5705 (interactive "P")
5706 (org-agenda-maybe-reset-markers 'force)
5707 (org-compile-prefix-format org-agenda-prefix-format)
5708 (require 'calendar)
5709 (let* ((org-agenda-start-on-weekday
5710 (if (or (equal ndays 1)
5711 (and (null ndays) (equal 1 org-agenda-ndays)))
5712 nil org-agenda-start-on-weekday))
5713 (org-agenda-keep-modes keep-modes)
5714 (thefiles (org-agenda-files))
5715 (files thefiles)
5716 (win (selected-window))
5717 (today (time-to-days (current-time)))
5718 (sd (or start-day today))
5719 (start (if (or (null org-agenda-start-on-weekday)
5720 (< org-agenda-ndays 7))
5721 sd
5722 (let* ((nt (calendar-day-of-week
5723 (calendar-gregorian-from-absolute sd)))
5724 (n1 org-agenda-start-on-weekday)
5725 (d (- nt n1)))
5726 (- sd (+ (if (< d 0) 7 0) d)))))
5727 (day-numbers (list start))
5728 (inhibit-redisplay t)
5729 s e rtn rtnall file date d start-pos end-pos todayp nd)
5730 (setq org-agenda-redo-command
5731 (list 'org-agenda-list (list 'quote include-all) start-day ndays t))
5732 ;; Make the list of days
5733 (setq ndays (or ndays org-agenda-ndays)
5734 nd ndays)
5735 (while (> ndays 1)
5736 (push (1+ (car day-numbers)) day-numbers)
5737 (setq ndays (1- ndays)))
5738 (setq day-numbers (nreverse day-numbers))
5739 (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name)))
5740 (progn
5741 (delete-other-windows)
5742 (switch-to-buffer-other-window
5743 (get-buffer-create org-agenda-buffer-name))))
5744 (setq buffer-read-only nil)
5745 (erase-buffer)
5746 (org-agenda-mode) (setq buffer-read-only nil)
5747 (set (make-local-variable 'org-agenda-type) 'agenda)
5748 (set (make-local-variable 'starting-day) (car day-numbers))
5749 (set (make-local-variable 'include-all-loc) include-all)
5750 (when (and (or include-all org-agenda-include-all-todo)
5751 (member today day-numbers))
5752 (setq files thefiles
5753 rtnall nil)
5754 (while (setq file (pop files))
5755 (catch 'nextfile
5756 (org-check-agenda-file file)
5757 (setq date (calendar-gregorian-from-absolute today)
5758 rtn (org-agenda-get-day-entries
5759 file date :todo))
5760 (setq rtnall (append rtnall rtn))))
5761 (when rtnall
5762 (insert "ALL CURRENTLY OPEN TODO ITEMS:\n")
5763 (add-text-properties (point-min) (1- (point))
5764 (list 'face 'org-level-3))
5765 (insert (org-finalize-agenda-entries rtnall) "\n")))
5766 (while (setq d (pop day-numbers))
5767 (setq date (calendar-gregorian-from-absolute d)
5768 s (point))
5769 (if (or (setq todayp (= d today))
5770 (and (not start-pos) (= d sd)))
5771 (setq start-pos (point))
5772 (if (and start-pos (not end-pos))
5773 (setq end-pos (point))))
5774 (setq files thefiles
5775 rtnall nil)
5776 (while (setq file (pop files))
5777 (catch 'nextfile
5778 (org-check-agenda-file file)
5779 (if org-agenda-show-log
5780 (setq rtn (org-agenda-get-day-entries
5781 file date
5782 :deadline :scheduled :timestamp :closed))
5783 (setq rtn (org-agenda-get-day-entries
5784 file date
5785 :deadline :scheduled :timestamp)))
5786 (setq rtnall (append rtnall rtn))))
5787 (if org-agenda-include-diary
5788 (progn
5789 (require 'diary-lib)
5790 (setq rtn (org-get-entries-from-diary date))
5791 (setq rtnall (append rtnall rtn))))
5792 (if (or rtnall org-agenda-show-all-dates)
5793 (progn
5794 (insert (format "%-9s %2d %s %4d\n"
5795 (calendar-day-name date)
5796 (extract-calendar-day date)
5797 (calendar-month-name (extract-calendar-month date))
5798 (extract-calendar-year date)))
5799 (put-text-property s (1- (point)) 'face
5800 'org-level-3)
5801 (if rtnall (insert
5802 (org-finalize-agenda-entries
5803 (org-agenda-add-time-grid-maybe
5804 rtnall nd todayp))
5805 "\n"))
5806 (put-text-property s (1- (point)) 'day d))))
5807 (goto-char (point-min))
5808 (setq buffer-read-only t)
5809 (org-fit-agenda-window)
5810 (unless (and (pos-visible-in-window-p (point-min))
5811 (pos-visible-in-window-p (point-max)))
5812 (goto-char (1- (point-max)))
5813 (recenter -1)
5814 (if (not (pos-visible-in-window-p (or start-pos 1)))
5815 (progn
5816 (goto-char (or start-pos 1))
5817 (recenter 1))))
5818 (goto-char (or start-pos 1))
5819 (if (not org-select-agenda-window) (select-window win))
5820 (message "")))
5821
5822 (defvar org-select-this-todo-keyword nil)
5823
5824 ;;;###autoload
5825 (defun org-todo-list (arg &optional keep-modes)
5826 "Show all TODO entries from all agenda file in a single list.
5827 The prefix arg can be used to select a specific TODO keyword and limit
5828 the list to these. When using \\[universal-argument], you will be prompted
5829 for a keyword. A numeric prefix directly selects the Nth keyword in
5830 `org-todo-keywords'."
5831 (interactive "P")
5832 (org-agenda-maybe-reset-markers 'force)
5833 (org-compile-prefix-format org-agenda-prefix-format)
5834 (let* ((org-agenda-keep-modes keep-modes)
5835 (today (time-to-days (current-time)))
5836 (date (calendar-gregorian-from-absolute today))
5837 (win (selected-window))
5838 (kwds org-todo-keywords)
5839 (completion-ignore-case t)
5840 (org-select-this-todo-keyword
5841 (if (stringp arg) arg
5842 (and arg (integerp arg) (> arg 0)
5843 (nth (1- arg) org-todo-keywords))))
5844 rtn rtnall files file pos)
5845 (when (equal arg '(4))
5846 (setq org-select-this-todo-keyword
5847 (completing-read "Keyword: " (mapcar 'list org-todo-keywords)
5848 nil t)))
5849 (and (equal 0 arg) (setq org-select-this-todo-keyword nil))
5850 (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name)))
5851 (progn
5852 (delete-other-windows)
5853 (switch-to-buffer-other-window
5854 (get-buffer-create org-agenda-buffer-name))))
5855 (setq buffer-read-only nil)
5856 (erase-buffer)
5857 (org-agenda-mode) (setq buffer-read-only nil)
5858 (set (make-local-variable 'org-agenda-type) 'todo)
5859 (set (make-local-variable 'last-arg) arg)
5860 (set (make-local-variable 'org-todo-keywords) kwds)
5861 (set (make-local-variable 'org-agenda-redo-command)
5862 '(org-todo-list (or current-prefix-arg last-arg) t))
5863 (setq files (org-agenda-files)
5864 rtnall nil)
5865 (while (setq file (pop files))
5866 (catch 'nextfile
5867 (org-check-agenda-file file)
5868 (setq rtn (org-agenda-get-day-entries file date :todo))
5869 (setq rtnall (append rtnall rtn))))
5870 (insert "Global list of TODO items of type: ")
5871 (add-text-properties (point-min) (1- (point))
5872 (list 'face 'org-level-3))
5873 (setq pos (point))
5874 (insert (or org-select-this-todo-keyword "ALL") "\n")
5875 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
5876 (setq pos (point))
5877 (insert
5878 "Available with `N r': (0)ALL "
5879 (let ((n 0))
5880 (mapconcat (lambda (x)
5881 (format "(%d)%s" (setq n (1+ n)) x))
5882 org-todo-keywords " "))
5883 "\n")
5884 (add-text-properties pos (1- (point)) (list 'face 'org-level-3))
5885 (when rtnall
5886 (insert (org-finalize-agenda-entries rtnall) "\n"))
5887 (goto-char (point-min))
5888 (setq buffer-read-only t)
5889 (org-fit-agenda-window)
5890 (if (not org-select-agenda-window) (select-window win))))
5891
5892 (defun org-check-agenda-file (file)
5893 "Make sure FILE exists. If not, ask user what to do."
5894 (when (not (file-exists-p file))
5895 (message "non-existent file %s. [R]emove from list or [A]bort?"
5896 (abbreviate-file-name file))
5897 (let ((r (downcase (read-char-exclusive))))
5898 (cond
5899 ((equal r ?r)
5900 (org-remove-file file)
5901 (throw 'nextfile t))
5902 (t (error "Abort"))))))
5903
5904 (defun org-agenda-check-type (error &rest types)
5905 "Check if agenda buffer is of allowed type.
5906 If ERROR is non-nil, throw an error, otherwise just return nil."
5907 (if (memq org-agenda-type types)
5908 t
5909 (if error
5910 (error "Not allowed in %s-type agenda buffers" org-agenda-type)
5911 nil)))
5912
5913 (defun org-agenda-quit ()
5914 "Exit agenda by removing the window or the buffer."
5915 (interactive)
5916 (let ((buf (current-buffer)))
5917 (if (not (one-window-p)) (delete-window))
5918 (kill-buffer buf)
5919 (org-agenda-maybe-reset-markers 'force)))
5920
5921 (defun org-agenda-exit ()
5922 "Exit agenda by removing the window or the buffer.
5923 Also kill all Org-mode buffers which have been loaded by `org-agenda'.
5924 Org-mode buffers visited directly by the user will not be touched."
5925 (interactive)
5926 (org-release-buffers org-agenda-new-buffers)
5927 (setq org-agenda-new-buffers nil)
5928 (org-agenda-quit))
5929
5930 (defun org-agenda-redo ()
5931 "Rebuild Agenda.
5932 When this is the global TODO list, a prefix argument will be interpreted."
5933 (interactive)
5934 (message "Rebuilding agenda buffer...")
5935 (eval org-agenda-redo-command)
5936 (message "Rebuilding agenda buffer...done"))
5937
5938 (defun org-agenda-goto-today ()
5939 "Go to today."
5940 (interactive)
5941 (org-agenda-check-type t 'timeline 'agenda)
5942 (if (boundp 'starting-day)
5943 (let ((cmd (car org-agenda-redo-command))
5944 (iall (nth 1 org-agenda-redo-command))
5945 (nday (nth 3 org-agenda-redo-command))
5946 (keep (nth 4 org-agenda-redo-command)))
5947 (eval (list cmd iall nil nday keep)))
5948 (goto-char (or (text-property-any (point-min) (point-max) 'org-today t)
5949 (point-min)))))
5950
5951 (defun org-agenda-later (arg)
5952 "Go forward in time by `org-agenda-ndays' days.
5953 With prefix ARG, go forward that many times `org-agenda-ndays'."
5954 (interactive "p")
5955 (org-agenda-check-type t 'agenda)
5956 (org-agenda-list (if (boundp 'include-all-loc) include-all-loc nil)
5957 (+ starting-day (* arg org-agenda-ndays)) nil t))
5958
5959 (defun org-agenda-earlier (arg)
5960 "Go back in time by `org-agenda-ndays' days.
5961 With prefix ARG, go back that many times `org-agenda-ndays'."
5962 (interactive "p")
5963 (org-agenda-check-type t 'agenda)
5964 (org-agenda-list (if (boundp 'include-all-loc) include-all-loc nil)
5965 (- starting-day (* arg org-agenda-ndays)) nil t))
5966
5967 (defun org-agenda-week-view ()
5968 "Switch to weekly view for agenda."
5969 (interactive)
5970 (org-agenda-check-type t 'agenda)
5971 (setq org-agenda-ndays 7)
5972 (org-agenda-list include-all-loc
5973 (or (get-text-property (point) 'day)
5974 starting-day)
5975 nil t)
5976 (org-agenda-set-mode-name)
5977 (message "Switched to week view"))
5978
5979 (defun org-agenda-day-view ()
5980 "Switch to daily view for agenda."
5981 (interactive)
5982 (org-agenda-check-type t 'agenda)
5983 (setq org-agenda-ndays 1)
5984 (org-agenda-list include-all-loc
5985 (or (get-text-property (point) 'day)
5986 starting-day)
5987 nil t)
5988 (org-agenda-set-mode-name)
5989 (message "Switched to day view"))
5990
5991 (defun org-agenda-next-date-line (&optional arg)
5992 "Jump to the next line indicating a date in agenda buffer."
5993 (interactive "p")
5994 (org-agenda-check-type t 'agenda 'timeline)
5995 (beginning-of-line 1)
5996 (if (looking-at "^\\S-") (forward-char 1))
5997 (if (not (re-search-forward "^\\S-" nil t arg))
5998 (progn
5999 (backward-char 1)
6000 (error "No next date after this line in this buffer")))
6001 (goto-char (match-beginning 0)))
6002
6003 (defun org-agenda-previous-date-line (&optional arg)
6004 "Jump to the previous line indicating a date in agenda buffer."
6005 (interactive "p")
6006 (org-agenda-check-type t 'agenda 'timeline)
6007 (beginning-of-line 1)
6008 (if (not (re-search-backward "^\\S-" nil t arg))
6009 (error "No previous date before this line in this buffer")))
6010
6011 ;; Initialize the highlight
6012 (defvar org-hl (org-make-overlay 1 1))
6013 (org-overlay-put org-hl 'face 'highlight)
6014
6015 (defun org-highlight (begin end &optional buffer)
6016 "Highlight a region with overlay."
6017 (funcall (if (featurep 'xemacs) 'set-extent-endpoints 'move-overlay)
6018 org-hl begin end (or buffer (current-buffer))))
6019
6020 (defun org-unhighlight ()
6021 "Detach overlay INDEX."
6022 (funcall (if (featurep 'xemacs) 'detach-extent 'delete-overlay) org-hl))
6023
6024
6025 (defun org-agenda-follow-mode ()
6026 "Toggle follow mode in an agenda buffer."
6027 (interactive)
6028 (setq org-agenda-follow-mode (not org-agenda-follow-mode))
6029 (org-agenda-set-mode-name)
6030 (message "Follow mode is %s"
6031 (if org-agenda-follow-mode "on" "off")))
6032
6033 (defun org-agenda-log-mode ()
6034 "Toggle log mode in an agenda buffer."
6035 (interactive)
6036 (org-agenda-check-type t 'agenda 'timeline)
6037 (setq org-agenda-show-log (not org-agenda-show-log))
6038 (org-agenda-set-mode-name)
6039 (org-agenda-redo)
6040 (message "Log mode is %s"
6041 (if org-agenda-show-log "on" "off")))
6042
6043 (defun org-agenda-toggle-diary ()
6044 "Toggle diary inclusion in an agenda buffer."
6045 (interactive)
6046 (org-agenda-check-type t 'agenda)
6047 (setq org-agenda-include-diary (not org-agenda-include-diary))
6048 (org-agenda-redo)
6049 (org-agenda-set-mode-name)
6050 (message "Diary inclusion turned %s"
6051 (if org-agenda-include-diary "on" "off")))
6052
6053 (defun org-agenda-toggle-time-grid ()
6054 "Toggle time grid in an agenda buffer."
6055 (interactive)
6056 (org-agenda-check-type t 'agenda)
6057 (setq org-agenda-use-time-grid (not org-agenda-use-time-grid))
6058 (org-agenda-redo)
6059 (org-agenda-set-mode-name)
6060 (message "Time-grid turned %s"
6061 (if org-agenda-use-time-grid "on" "off")))
6062
6063 (defun org-agenda-set-mode-name ()
6064 "Set the mode name to indicate all the small mode settings."
6065 (setq mode-name
6066 (concat "Org-Agenda"
6067 (if (equal org-agenda-ndays 1) " Day" "")
6068 (if (equal org-agenda-ndays 7) " Week" "")
6069 (if org-agenda-follow-mode " Follow" "")
6070 (if org-agenda-include-diary " Diary" "")
6071 (if org-agenda-use-time-grid " Grid" "")
6072 (if org-agenda-show-log " Log" "")))
6073 (force-mode-line-update))
6074
6075 (defun org-agenda-post-command-hook ()
6076 (and (eolp) (not (bolp)) (backward-char 1))
6077 (if (and org-agenda-follow-mode
6078 (get-text-property (point) 'org-marker))
6079 (org-agenda-show)))
6080
6081 (defvar org-disable-agenda-to-diary nil) ;Dynamically-scoped param.
6082
6083 (defun org-get-entries-from-diary (date)
6084 "Get the (Emacs Calendar) diary entries for DATE."
6085 (let* ((fancy-diary-buffer "*temporary-fancy-diary-buffer*")
6086 (diary-display-hook '(fancy-diary-display))
6087 (list-diary-entries-hook
6088 (cons 'org-diary-default-entry list-diary-entries-hook))
6089 (diary-file-name-prefix-function nil) ; turn this feature off
6090 (diary-modify-entry-list-string-function 'org-modify-diary-entry-string)
6091 entries
6092 (org-disable-agenda-to-diary t))
6093 (save-excursion
6094 (save-window-excursion
6095 (list-diary-entries date 1))) ;; Keep this name for now, compatibility
6096 (if (not (get-buffer fancy-diary-buffer))
6097 (setq entries nil)
6098 (with-current-buffer fancy-diary-buffer
6099 (setq buffer-read-only nil)
6100 (if (= (point-max) 1)
6101 ;; No entries
6102 (setq entries nil)
6103 ;; Omit the date and other unnecessary stuff
6104 (org-agenda-cleanup-fancy-diary)
6105 ;; Add prefix to each line and extend the text properties
6106 (if (= (point-max) 1)
6107 (setq entries nil)
6108 (setq entries (buffer-substring (point-min) (- (point-max) 1)))))
6109 (set-buffer-modified-p nil)
6110 (kill-buffer fancy-diary-buffer)))
6111 (when entries
6112 (setq entries (org-split-string entries "\n"))
6113 (setq entries
6114 (mapcar
6115 (lambda (x)
6116 (setq x (org-format-agenda-item "" x "Diary" nil 'time))
6117 ;; Extend the text properties to the beginning of the line
6118 (org-add-props x (text-properties-at (1- (length x)) x)))
6119 entries)))))
6120
6121 (defun org-agenda-cleanup-fancy-diary ()
6122 "Remove unwanted stuff in buffer created by `fancy-diary-display'.
6123 This gets rid of the date, the underline under the date, and
6124 the dummy entry installed by `org-mode' to ensure non-empty diary for each
6125 date. It also removes lines that contain only whitespace."
6126 (goto-char (point-min))
6127 (if (looking-at ".*?:[ \t]*")
6128 (progn
6129 (replace-match "")
6130 (re-search-forward "\n=+$" nil t)
6131 (replace-match "")
6132 (while (re-search-backward "^ +\n?" nil t) (replace-match "")))
6133 (re-search-forward "\n=+$" nil t)
6134 (delete-region (point-min) (min (point-max) (1+ (match-end 0)))))
6135 (goto-char (point-min))
6136 (while (re-search-forward "^ +\n" nil t)
6137 (replace-match ""))
6138 (goto-char (point-min))
6139 (if (re-search-forward "^Org-mode dummy\n?" nil t)
6140 (replace-match "")))
6141
6142 ;; Make sure entries from the diary have the right text properties.
6143 (eval-after-load "diary-lib"
6144 '(if (boundp 'diary-modify-entry-list-string-function)
6145 ;; We can rely on the hook, nothing to do
6146 nil
6147 ;; Hook not avaiable, must use advice to make this work
6148 (defadvice add-to-diary-list (before org-mark-diary-entry activate)
6149 "Make the position visible."
6150 (if (and org-disable-agenda-to-diary ;; called from org-agenda
6151 (stringp string)
6152 buffer-file-name)
6153 (setq string (org-modify-diary-entry-string string))))))
6154
6155 (defun org-modify-diary-entry-string (string)
6156 "Add text properties to string, allowing org-mode to act on it."
6157 (org-add-props string nil
6158 'mouse-face 'highlight
6159 'keymap org-agenda-keymap
6160 'help-echo (format "mouse-2 or RET jump to diary file %s"
6161 (abbreviate-file-name buffer-file-name))
6162 'org-agenda-diary-link t
6163 'org-marker (org-agenda-new-marker (point-at-bol))))
6164
6165 (defun org-diary-default-entry ()
6166 "Add a dummy entry to the diary.
6167 Needed to avoid empty dates which mess up holiday display."
6168 ;; Catch the error if dealing with the new add-to-diary-alist
6169 (when org-disable-agenda-to-diary
6170 (condition-case nil
6171 (add-to-diary-list original-date "Org-mode dummy" "")
6172 (error
6173 (add-to-diary-list original-date "Org-mode dummy" "" nil)))))
6174
6175 (defun org-cycle-agenda-files ()
6176 "Cycle through the files in `org-agenda-files'.
6177 If the current buffer visits an agenda file, find the next one in the list.
6178 If the current buffer does not, find the first agenda file."
6179 (interactive)
6180 (let* ((fs (org-agenda-files t))
6181 (files (append fs (list (car fs))))
6182 (tcf (if buffer-file-name (file-truename buffer-file-name)))
6183 file)
6184 (unless files (error "No agenda files"))
6185 (catch 'exit
6186 (while (setq file (pop files))
6187 (if (equal (file-truename file) tcf)
6188 (when (car files)
6189 (find-file (car files))
6190 (throw 'exit t))))
6191 (find-file (car fs)))))
6192
6193 (defun org-agenda-file-to-end ()
6194 "Move/add the current file to the end of the agenda file list.
6195 If the file is not present in the list, it is appended to the list. If it is
6196 present, it is moved there."
6197 (interactive)
6198 (org-agenda-file-to-front 'to-end))
6199
6200 (defun org-agenda-file-to-front (&optional to-end)
6201 "Move/add the current file to the top of the agenda file list.
6202 If the file is not present in the list, it is added to the front. If it is
6203 present, it is moved there. With optional argument TO-END, add/move to the
6204 end of the list."
6205 (interactive "P")
6206 (let ((file-alist (mapcar (lambda (x)
6207 (cons (file-truename x) x))
6208 (org-agenda-files t)))
6209 (ctf (file-truename buffer-file-name))
6210 x had)
6211 (setq x (assoc ctf file-alist) had x)
6212
6213 (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name))))
6214 (if to-end
6215 (setq file-alist (append (delq x file-alist) (list x)))
6216 (setq file-alist (cons x (delq x file-alist))))
6217 (org-store-new-agenda-file-list (mapcar 'cdr file-alist))
6218 (org-install-agenda-files-menu)
6219 (message "File %s to %s of agenda file list"
6220 (if had "moved" "added") (if to-end "end" "front"))))
6221
6222 (defun org-remove-file (&optional file)
6223 "Remove current file from the list of files in variable `org-agenda-files'.
6224 These are the files which are being checked for agenda entries.
6225 Optional argument FILE means, use this file instead of the current."
6226 (interactive)
6227 (let* ((file (or file buffer-file-name))
6228 (true-file (file-truename file))
6229 (afile (abbreviate-file-name file))
6230 (files (delq nil (mapcar
6231 (lambda (x)
6232 (if (equal true-file
6233 (file-truename x))
6234 nil x))
6235 (org-agenda-files t)))))
6236 (if (not (= (length files) (length (org-agenda-files t))))
6237 (progn
6238 (org-store-new-agenda-file-list files)
6239 (org-install-agenda-files-menu)
6240 (message "Removed file: %s" afile))
6241 (message "File was not in list: %s" afile))))
6242
6243 (defun org-file-menu-entry (file)
6244 (vector file (list 'find-file file) t))
6245
6246 (defun org-get-all-dates (beg end &optional no-ranges force-today inactive empty)
6247 "Return a list of all relevant day numbers from BEG to END buffer positions.
6248 If NO-RANGES is non-nil, include only the start and end dates of a range,
6249 not every single day in the range. If FORCE-TODAY is non-nil, make
6250 sure that TODAY is included in the list. If INACTIVE is non-nil, also
6251 inactive time stamps (those in square brackets) are included.
6252 When EMPTY is non-nil, also include days without any entries."
6253 (let ((re (if inactive org-ts-regexp-both org-ts-regexp))
6254 dates dates1 date day day1 day2 ts1 ts2)
6255 (if force-today
6256 (setq dates (list (time-to-days (current-time)))))
6257 (save-excursion
6258 (goto-char beg)
6259 (while (re-search-forward re end t)
6260 (setq day (time-to-days (org-time-string-to-time
6261 (substring (match-string 1) 0 10))))
6262 (or (memq day dates) (push day dates)))
6263 (unless no-ranges
6264 (goto-char beg)
6265 (while (re-search-forward org-tr-regexp end t)
6266 (setq ts1 (substring (match-string 1) 0 10)
6267 ts2 (substring (match-string 2) 0 10)
6268 day1 (time-to-days (org-time-string-to-time ts1))
6269 day2 (time-to-days (org-time-string-to-time ts2)))
6270 (while (< (setq day1 (1+ day1)) day2)
6271 (or (memq day1 dates) (push day1 dates)))))
6272 (setq dates (sort dates '<))
6273 (when empty
6274 (while (setq day (pop dates))
6275 (setq day2 (car dates))
6276 (push day dates1)
6277 (when (and day2 empty)
6278 (if (or (eq empty t)
6279 (and (numberp empty) (<= (- day2 day) empty)))
6280 (while (< (setq day (1+ day)) day2)
6281 (push (list day) dates1))
6282 (push (cons :omitted (- day2 day)) dates1))))
6283 (setq dates (nreverse dates1)))
6284 dates)))
6285
6286 ;;;###autoload
6287 (defun org-diary (&rest args)
6288 "Return diary information from org-files.
6289 This function can be used in a \"sexp\" diary entry in the Emacs calendar.
6290 It accesses org files and extracts information from those files to be
6291 listed in the diary. The function accepts arguments specifying what
6292 items should be listed. The following arguments are allowed:
6293
6294 :timestamp List the headlines of items containing a date stamp or
6295 date range matching the selected date. Deadlines will
6296 also be listed, on the expiration day.
6297
6298 :deadline List any deadlines past due, or due within
6299 `org-deadline-warning-days'. The listing occurs only
6300 in the diary for *today*, not at any other date. If
6301 an entry is marked DONE, it is no longer listed.
6302
6303 :scheduled List all items which are scheduled for the given date.
6304 The diary for *today* also contains items which were
6305 scheduled earlier and are not yet marked DONE.
6306
6307 :todo List all TODO items from the org-file. This may be a
6308 long list - so this is not turned on by default.
6309 Like deadlines, these entries only show up in the
6310 diary for *today*, not at any other date.
6311
6312 The call in the diary file should look like this:
6313
6314 &%%(org-diary) ~/path/to/some/orgfile.org
6315
6316 Use a separate line for each org file to check. Or, if you omit the file name,
6317 all files listed in `org-agenda-files' will be checked automatically:
6318
6319 &%%(org-diary)
6320
6321 If you don't give any arguments (as in the example above), the default
6322 arguments (:deadline :scheduled :timestamp) are used. So the example above may
6323 also be written as
6324
6325 &%%(org-diary :deadline :timestamp :scheduled)
6326
6327 The function expects the lisp variables `entry' and `date' to be provided
6328 by the caller, because this is how the calendar works. Don't use this
6329 function from a program - use `org-agenda-get-day-entries' instead."
6330 (org-agenda-maybe-reset-markers)
6331 (org-compile-prefix-format org-agenda-prefix-format)
6332 (setq args (or args '(:deadline :scheduled :timestamp)))
6333 (let* ((files (if (and entry (stringp entry) (string-match "\\S-" entry))
6334 (list entry)
6335 (org-agenda-files t)))
6336 file rtn results)
6337 ;; If this is called during org-agenda, don't return any entries to
6338 ;; the calendar. Org Agenda will list these entries itself.
6339 (if org-disable-agenda-to-diary (setq files nil))
6340 (while (setq file (pop files))
6341 (setq rtn (apply 'org-agenda-get-day-entries file date args))
6342 (setq results (append results rtn)))
6343 (if results
6344 (concat (org-finalize-agenda-entries results) "\n"))))
6345 (defvar org-category-table nil)
6346 (defun org-get-category-table ()
6347 "Get the table of categories and positions in current buffer."
6348 (let (tbl)
6349 (save-excursion
6350 (goto-char (point-min))
6351 (while (re-search-forward "\\(^\\|\r\\)#\\+CATEGORY:[ \t]*\\(.*\\)" nil t)
6352 (push (cons (point) (org-trim (match-string 2))) tbl)))
6353 tbl))
6354 (defun org-get-category (&optional pos)
6355 "Get the category applying to position POS."
6356 (if (not org-category-table)
6357 (cond
6358 ((null org-category)
6359 (setq org-category
6360 (if buffer-file-name
6361 (file-name-sans-extension
6362 (file-name-nondirectory buffer-file-name))
6363 "???")))
6364 ((symbolp org-category) (symbol-name org-category))
6365 (t org-category))
6366 (let ((tbl org-category-table)
6367 (pos (or pos (point))))
6368 (while (and tbl (> (caar tbl) pos))
6369 (pop tbl))
6370 (or (cdar tbl) (cdr (nth (1- (length org-category-table))
6371 org-category-table))))))
6372
6373 (defun org-agenda-get-day-entries (file date &rest args)
6374 "Does the work for `org-diary' and `org-agenda'.
6375 FILE is the path to a file to be checked for entries. DATE is date like
6376 the one returned by `calendar-current-date'. ARGS are symbols indicating
6377 which kind of entries should be extracted. For details about these, see
6378 the documentation of `org-diary'."
6379 (setq args (or args '(:deadline :scheduled :timestamp)))
6380 (let* ((org-startup-with-deadline-check nil)
6381 (org-startup-folded nil)
6382 (org-startup-align-all-tables nil)
6383 (buffer (if (file-exists-p file)
6384 (org-get-agenda-file-buffer file)
6385 (error "No such file %s" file)))
6386 arg results rtn)
6387 (if (not buffer)
6388 ;; If file does not exist, make sure an error message ends up in diary
6389 (list (format "ORG-AGENDA-ERROR: No such org-file %s" file))
6390 (with-current-buffer buffer
6391 (unless (eq major-mode 'org-mode)
6392 (error "Agenda file %s is not in `org-mode'" file))
6393 (setq org-category-table (org-get-category-table))
6394 (let ((case-fold-search nil))
6395 (save-excursion
6396 (save-restriction
6397 (if org-respect-restriction
6398 (if (org-region-active-p)
6399 ;; Respect a region to restrict search
6400 (narrow-to-region (region-beginning) (region-end)))
6401 ;; If we work for the calendar or many files,
6402 ;; get rid of any restriction
6403 (widen))
6404 ;; The way we repeatedly append to `results' makes it O(n^2) :-(
6405 (while (setq arg (pop args))
6406 (cond
6407 ((and (eq arg :todo)
6408 (equal date (calendar-current-date)))
6409 (setq rtn (org-agenda-get-todos))
6410 (setq results (append results rtn)))
6411 ((eq arg :timestamp)
6412 (setq rtn (org-agenda-get-blocks))
6413 (setq results (append results rtn))
6414 (setq rtn (org-agenda-get-timestamps))
6415 (setq results (append results rtn)))
6416 ((eq arg :scheduled)
6417 (setq rtn (org-agenda-get-scheduled))
6418 (setq results (append results rtn)))
6419 ((eq arg :closed)
6420 (setq rtn (org-agenda-get-closed))
6421 (setq results (append results rtn)))
6422 ((and (eq arg :deadline)
6423 (equal date (calendar-current-date)))
6424 (setq rtn (org-agenda-get-deadlines))
6425 (setq results (append results rtn))))))))
6426 results))))
6427
6428 (defun org-entry-is-done-p ()
6429 "Is the current entry marked DONE?"
6430 (save-excursion
6431 (and (re-search-backward "[\r\n]\\*" nil t)
6432 (looking-at org-nl-done-regexp))))
6433
6434 (defun org-at-date-range-p ()
6435 "Is the cursor inside a date range?"
6436 (interactive)
6437 (save-excursion
6438 (catch 'exit
6439 (let ((pos (point)))
6440 (skip-chars-backward "^<\r\n")
6441 (skip-chars-backward "<")
6442 (and (looking-at org-tr-regexp)
6443 (>= (match-end 0) pos)
6444 (throw 'exit t))
6445 (skip-chars-backward "^<\r\n")
6446 (skip-chars-backward "<")
6447 (and (looking-at org-tr-regexp)
6448 (>= (match-end 0) pos)
6449 (throw 'exit t)))
6450 nil)))
6451
6452 (defun org-agenda-get-todos ()
6453 "Return the TODO information for agenda display."
6454 (let* ((props (list 'face nil
6455 'done-face 'org-done
6456 'org-not-done-regexp org-not-done-regexp
6457 'mouse-face 'highlight
6458 'keymap org-agenda-keymap
6459 'help-echo
6460 (format "mouse-2 or RET jump to org file %s"
6461 (abbreviate-file-name buffer-file-name))))
6462 (regexp (concat "[\n\r]\\*+ *\\("
6463 (if org-select-this-todo-keyword
6464 (concat "\\<\\(" org-select-this-todo-keyword
6465 "\\)\\>")
6466 org-not-done-regexp)
6467 "[^\n\r]*\\)"))
6468 (sched-re (concat ".*\n.*?" org-scheduled-time-regexp))
6469 marker priority category tags
6470 ee txt)
6471 (goto-char (point-min))
6472 (while (re-search-forward regexp nil t)
6473 (when (not (and org-agenda-todo-ignore-scheduled
6474 (save-match-data (looking-at sched-re))))
6475 (goto-char (match-beginning 1))
6476 (setq marker (org-agenda-new-marker (1+ (match-beginning 0)))
6477 category (org-get-category)
6478 tags (org-get-tags-at (point))
6479 txt (org-format-agenda-item "" (match-string 1) category tags)
6480 priority
6481 (+ (org-get-priority txt)
6482 (if org-todo-kwd-priority-p
6483 (- org-todo-kwd-max-priority -2
6484 (length
6485 (member (match-string 2) org-todo-keywords)))
6486 1)))
6487 (org-add-props txt props
6488 'org-marker marker 'org-hd-marker marker
6489 'priority priority 'category category)
6490 (push txt ee)
6491 (if org-agenda-todo-list-sublevels
6492 (goto-char (match-end 1))
6493 (org-end-of-subtree 'invisible))))
6494 (nreverse ee)))
6495
6496 (defconst org-agenda-no-heading-message
6497 "No heading for this item in buffer or region.")
6498
6499 (defun org-agenda-get-timestamps ()
6500 "Return the date stamp information for agenda display."
6501 (let* ((props (list 'face nil
6502 'org-not-done-regexp org-not-done-regexp
6503 'mouse-face 'highlight
6504 'keymap org-agenda-keymap
6505 'help-echo
6506 (format "mouse-2 or RET jump to org file %s"
6507 (abbreviate-file-name buffer-file-name))))
6508 (regexp (regexp-quote
6509 (substring
6510 (format-time-string
6511 (car org-time-stamp-formats)
6512 (apply 'encode-time ; DATE bound by calendar
6513 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
6514 0 11)))
6515 marker hdmarker deadlinep scheduledp donep tmp priority category
6516 ee txt timestr tags)
6517 (goto-char (point-min))
6518 (while (re-search-forward regexp nil t)
6519 (if (not (save-match-data (org-at-date-range-p)))
6520 (progn
6521 (setq marker (org-agenda-new-marker (match-beginning 0))
6522 category (org-get-category (match-beginning 0))
6523 tmp (buffer-substring (max (point-min)
6524 (- (match-beginning 0)
6525 org-ds-keyword-length))
6526 (match-beginning 0))
6527 timestr (buffer-substring (match-beginning 0) (point-at-eol))
6528 deadlinep (string-match org-deadline-regexp tmp)
6529 scheduledp (string-match org-scheduled-regexp tmp)
6530 donep (org-entry-is-done-p))
6531 (if (string-match ">" timestr)
6532 ;; substring should only run to end of time stamp
6533 (setq timestr (substring timestr 0 (match-end 0))))
6534 (save-excursion
6535 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
6536 (progn
6537 (goto-char (match-end 1))
6538 (setq hdmarker (org-agenda-new-marker)
6539 tags (org-get-tags-at))
6540 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
6541 (setq txt (org-format-agenda-item
6542 (format "%s%s"
6543 (if deadlinep "Deadline: " "")
6544 (if scheduledp "Scheduled: " ""))
6545 (match-string 1) category tags timestr)))
6546 (setq txt org-agenda-no-heading-message))
6547 (setq priority (org-get-priority txt))
6548 (org-add-props txt props
6549 'org-marker marker 'org-hd-marker hdmarker)
6550 (if deadlinep
6551 (org-add-props txt nil
6552 'face (if donep 'org-done 'org-warning)
6553 'undone-face 'org-warning 'done-face 'org-done
6554 'category category 'priority (+ 100 priority))
6555 (if scheduledp
6556 (org-add-props txt nil
6557 'face 'org-scheduled-today
6558 'undone-face 'org-scheduled-today 'done-face 'org-done
6559 'category category 'priority (+ 99 priority))
6560 (org-add-props txt nil 'priority priority 'category category)))
6561 (push txt ee))
6562 (outline-next-heading))))
6563 (nreverse ee)))
6564
6565 (defun org-agenda-get-closed ()
6566 "Return the logged TODO entries for agenda display."
6567 (let* ((props (list 'mouse-face 'highlight
6568 'org-not-done-regexp org-not-done-regexp
6569 'keymap org-agenda-keymap
6570 'help-echo
6571 (format "mouse-2 or RET jump to org file %s"
6572 (abbreviate-file-name buffer-file-name))))
6573 (regexp (concat
6574 "\\<" org-closed-string " *\\["
6575 (regexp-quote
6576 (substring
6577 (format-time-string
6578 (car org-time-stamp-formats)
6579 (apply 'encode-time ; DATE bound by calendar
6580 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
6581 1 11))))
6582 marker hdmarker priority category tags
6583 ee txt timestr)
6584 (goto-char (point-min))
6585 (while (re-search-forward regexp nil t)
6586 (if (not (save-match-data (org-at-date-range-p)))
6587 (progn
6588 (setq marker (org-agenda-new-marker (match-beginning 0))
6589 category (org-get-category (match-beginning 0))
6590 timestr (buffer-substring (match-beginning 0) (point-at-eol))
6591 ;; donep (org-entry-is-done-p)
6592 )
6593 (if (string-match "\\]" timestr)
6594 ;; substring should only run to end of time stamp
6595 (setq timestr (substring timestr 0 (match-end 0))))
6596 (save-excursion
6597 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
6598 (progn
6599 (goto-char (match-end 1))
6600 (setq hdmarker (org-agenda-new-marker)
6601 tags (org-get-tags-at))
6602 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
6603 (setq txt (org-format-agenda-item
6604 "Closed: "
6605 (match-string 1) category tags timestr)))
6606 (setq txt org-agenda-no-heading-message))
6607 (setq priority 100000)
6608 (org-add-props txt props
6609 'org-marker marker 'org-hd-marker hdmarker 'face 'org-done
6610 'priority priority 'category category
6611 'undone-face 'org-warning 'done-face 'org-done)
6612 (push txt ee))
6613 (outline-next-heading))))
6614 (nreverse ee)))
6615
6616 (defun org-agenda-get-deadlines ()
6617 "Return the deadline information for agenda display."
6618 (let* ((wdays org-deadline-warning-days)
6619 (props (list 'mouse-face 'highlight
6620 'org-not-done-regexp org-not-done-regexp
6621 'keymap org-agenda-keymap
6622 'help-echo
6623 (format "mouse-2 or RET jump to org file %s"
6624 (abbreviate-file-name buffer-file-name))))
6625 (regexp org-deadline-time-regexp)
6626 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
6627 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
6628 d2 diff pos pos1 category tags
6629 ee txt head face)
6630 (goto-char (point-min))
6631 (while (re-search-forward regexp nil t)
6632 (setq pos (1- (match-beginning 1))
6633 d2 (time-to-days
6634 (org-time-string-to-time (match-string 1)))
6635 diff (- d2 d1))
6636 ;; When to show a deadline in the calendar:
6637 ;; If the expiration is within wdays warning time.
6638 ;; Past-due deadlines are only shown on the current date
6639 (if (and (< diff wdays) todayp (not (= diff 0)))
6640 (save-excursion
6641 (setq category (org-get-category))
6642 (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t)
6643 (progn
6644 (goto-char (match-end 0))
6645 (setq pos1 (match-end 1))
6646 (setq tags (org-get-tags-at pos1))
6647 (setq head (buffer-substring-no-properties
6648 (point)
6649 (progn (skip-chars-forward "^\r\n")
6650 (point))))
6651 (if (string-match org-looking-at-done-regexp head)
6652 (setq txt nil)
6653 (setq txt (org-format-agenda-item
6654 (format "In %3d d.: " diff) head category tags))))
6655 (setq txt org-agenda-no-heading-message))
6656 (when txt
6657 (setq face (cond ((<= diff 0) 'org-warning)
6658 ((<= diff 5) 'org-upcoming-deadline)
6659 (t nil)))
6660 (org-add-props txt props
6661 'org-marker (org-agenda-new-marker pos)
6662 'org-hd-marker (org-agenda-new-marker pos1)
6663 'priority (+ (- 10 diff) (org-get-priority txt))
6664 'category category
6665 'face face 'undone-face face 'done-face 'org-done)
6666 (push txt ee)))))
6667 ee))
6668
6669 (defun org-agenda-get-scheduled ()
6670 "Return the scheduled information for agenda display."
6671 (let* ((props (list 'face 'org-scheduled-previously
6672 'org-not-done-regexp org-not-done-regexp
6673 'undone-face 'org-scheduled-previously
6674 'done-face 'org-done
6675 'mouse-face 'highlight
6676 'keymap org-agenda-keymap
6677 'help-echo
6678 (format "mouse-2 or RET jump to org file %s"
6679 (abbreviate-file-name buffer-file-name))))
6680 (regexp org-scheduled-time-regexp)
6681 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
6682 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
6683 d2 diff pos pos1 category tags
6684 ee txt head)
6685 (goto-char (point-min))
6686 (while (re-search-forward regexp nil t)
6687 (setq pos (1- (match-beginning 1))
6688 d2 (time-to-days
6689 (org-time-string-to-time (match-string 1)))
6690 diff (- d2 d1))
6691 ;; When to show a scheduled item in the calendar:
6692 ;; If it is on or past the date.
6693 (if (and (< diff 0) todayp)
6694 (save-excursion
6695 (setq category (org-get-category))
6696 (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t)
6697 (progn
6698 (goto-char (match-end 0))
6699 (setq pos1 (match-end 1))
6700 (setq tags (org-get-tags-at))
6701 (setq head (buffer-substring-no-properties
6702 (point)
6703 (progn (skip-chars-forward "^\r\n") (point))))
6704 (if (string-match org-looking-at-done-regexp head)
6705 (setq txt nil)
6706 (setq txt (org-format-agenda-item
6707 (format "Sched.%2dx: " (- 1 diff)) head
6708 category tags))))
6709 (setq txt org-agenda-no-heading-message))
6710 (when txt
6711 (org-add-props txt props
6712 'org-marker (org-agenda-new-marker pos)
6713 'org-hd-marker (org-agenda-new-marker pos1)
6714 'priority (+ (- 5 diff) (org-get-priority txt))
6715 'category category)
6716 (push txt ee)))))
6717 ee))
6718
6719 (defun org-agenda-get-blocks ()
6720 "Return the date-range information for agenda display."
6721 (let* ((props (list 'face nil
6722 'org-not-done-regexp org-not-done-regexp
6723 'mouse-face 'highlight
6724 'keymap org-agenda-keymap
6725 'help-echo
6726 (format "mouse-2 or RET jump to org file %s"
6727 (abbreviate-file-name buffer-file-name))))
6728 (regexp org-tr-regexp)
6729 (d0 (calendar-absolute-from-gregorian date))
6730 marker hdmarker ee txt d1 d2 s1 s2 timestr category tags)
6731 (goto-char (point-min))
6732 (while (re-search-forward regexp nil t)
6733 (setq timestr (match-string 0)
6734 s1 (match-string 1)
6735 s2 (match-string 2)
6736 d1 (time-to-days (org-time-string-to-time s1))
6737 d2 (time-to-days (org-time-string-to-time s2)))
6738 (if (and (> (- d0 d1) -1) (> (- d2 d0) -1))
6739 ;; Only allow days between the limits, because the normal
6740 ;; date stamps will catch the limits.
6741 (save-excursion
6742 (setq marker (org-agenda-new-marker (point)))
6743 (setq category (org-get-category))
6744 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
6745 (progn
6746 (setq hdmarker (org-agenda-new-marker (match-end 1)))
6747 (goto-char (match-end 1))
6748 (setq tags (org-get-tags-at))
6749 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
6750 (setq txt (org-format-agenda-item
6751 (format (if (= d1 d2) "" "(%d/%d): ")
6752 (1+ (- d0 d1)) (1+ (- d2 d1)))
6753 (match-string 1) category tags
6754 (if (= d0 d1) timestr))))
6755 (setq txt org-agenda-no-heading-message))
6756 (org-add-props txt props
6757 'org-marker marker 'org-hd-marker hdmarker
6758 'priority (org-get-priority txt) 'category category)
6759 (push txt ee)))
6760 (outline-next-heading))
6761 ;; Sort the entries by expiration date.
6762 (nreverse ee)))
6763
6764 (defconst org-plain-time-of-day-regexp
6765 (concat
6766 "\\(\\<[012]?[0-9]"
6767 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
6768 "\\(--?"
6769 "\\(\\<[012]?[0-9]"
6770 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
6771 "\\)?")
6772 "Regular expression to match a plain time or time range.
6773 Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
6774 groups carry important information:
6775 0 the full match
6776 1 the first time, range or not
6777 8 the second time, if it is a range.")
6778
6779 (defconst org-stamp-time-of-day-regexp
6780 (concat
6781 "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +[a-zA-Z]+ +\\)"
6782 "\\([012][0-9]:[0-5][0-9]\\)>"
6783 "\\(--?"
6784 "<\\1\\([012][0-9]:[0-5][0-9]\\)>\\)?")
6785 "Regular expression to match a timestamp time or time range.
6786 After a match, the following groups carry important information:
6787 0 the full match
6788 1 date plus weekday, for backreferencing to make sure both times on same day
6789 2 the first time, range or not
6790 4 the second time, if it is a range.")
6791
6792 (defvar org-prefix-has-time nil
6793 "A flag, set by `org-compile-prefix-format'.
6794 The flag is set if the currently compiled format contains a `%t'.")
6795 (defvar org-prefix-has-tag nil
6796 "A flag, set by `org-compile-prefix-format'.
6797 The flag is set if the currently compiled format contains a `%T'.")
6798
6799 (defun org-format-agenda-item (extra txt &optional category tags dotime noprefix)
6800 "Format TXT to be inserted into the agenda buffer.
6801 In particular, it adds the prefix and corresponding text properties. EXTRA
6802 must be a string and replaces the `%s' specifier in the prefix format.
6803 CATEGORY (string, symbol or nil) may be used to overrule the default
6804 category taken from local variable or file name. It will replace the `%c'
6805 specifier in the format. DOTIME, when non-nil, indicates that a
6806 time-of-day should be extracted from TXT for sorting of this entry, and for
6807 the `%t' specifier in the format. When DOTIME is a string, this string is
6808 searched for a time before TXT is. NOPREFIX is a flag and indicates that
6809 only the correctly processes TXT should be returned - this is used by
6810 `org-agenda-change-all-lines'. TAG can be the tag of the headline."
6811 (save-match-data
6812 ;; Diary entries sometimes have extra whitespace at the beginning
6813 (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt)))
6814 (let* ((category (or category
6815 org-category
6816 (if buffer-file-name
6817 (file-name-sans-extension
6818 (file-name-nondirectory buffer-file-name))
6819 "")))
6820 (tag (if tags (nth (1- (length tags)) tags) ""))
6821 time ;; needed for the eval of the prefix format
6822 (ts (if dotime (concat (if (stringp dotime) dotime "") txt)))
6823 (time-of-day (and dotime (org-get-time-of-day ts)))
6824 stamp plain s0 s1 s2 rtn)
6825 (when (and dotime time-of-day org-prefix-has-time)
6826 ;; Extract starting and ending time and move them to prefix
6827 (when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts))
6828 (setq plain (string-match org-plain-time-of-day-regexp ts)))
6829 (setq s0 (match-string 0 ts)
6830 s1 (match-string (if plain 1 2) ts)
6831 s2 (match-string (if plain 8 4) ts))
6832
6833 ;; If the times are in TXT (not in DOTIMES), and the prefix will list
6834 ;; them, we might want to remove them there to avoid duplication.
6835 ;; The user can turn this off with a variable.
6836 (if (and org-agenda-remove-times-when-in-prefix (or stamp plain)
6837 (string-match (concat (regexp-quote s0) " *") txt)
6838 (if (eq org-agenda-remove-times-when-in-prefix 'beg)
6839 (= (match-beginning 0) 0)
6840 t))
6841 (setq txt (replace-match "" nil nil txt))))
6842 ;; Normalize the time(s) to 24 hour
6843 (if s1 (setq s1 (org-get-time-of-day s1 'string)))
6844 (if s2 (setq s2 (org-get-time-of-day s2 'string))))
6845
6846 (when (string-match "\\([ \t]+\\)\\(:[a-zA-Z_@0-9:]+:\\)[ \t]*$" txt)
6847 ;; Tags are in the string
6848 (if (or (eq org-agenda-remove-tags-when-in-prefix t)
6849 (and org-agenda-remove-tags-when-in-prefix
6850 org-prefix-has-tag))
6851 (setq txt (replace-match "" t t txt))
6852 (setq txt (replace-match
6853 (concat (make-string (max (- 50 (length txt)) 1) ?\ )
6854 (match-string 2 txt))
6855 t t txt))))
6856
6857 ;; Create the final string
6858 (if noprefix
6859 (setq rtn txt)
6860 ;; Prepare the variables needed in the eval of the compiled format
6861 (setq time (cond (s2 (concat s1 "-" s2))
6862 (s1 (concat s1 "......"))
6863 (t ""))
6864 extra (or extra "")
6865 category (if (symbolp category) (symbol-name category) category))
6866 ;; Evaluate the compiled format
6867 (setq rtn (concat (eval org-prefix-format-compiled) txt)))
6868
6869 ;; And finally add the text properties
6870 (org-add-props rtn nil
6871 'category (downcase category) 'tags tags
6872 'prefix-length (- (length rtn) (length txt))
6873 'time-of-day time-of-day
6874 'dotime dotime))))
6875
6876 (defun org-agenda-add-time-grid-maybe (list ndays todayp)
6877 (catch 'exit
6878 (cond ((not org-agenda-use-time-grid) (throw 'exit list))
6879 ((and todayp (member 'today (car org-agenda-time-grid))))
6880 ((and (= ndays 1) (member 'daily (car org-agenda-time-grid))))
6881 ((member 'weekly (car org-agenda-time-grid)))
6882 (t (throw 'exit list)))
6883 (let* ((have (delq nil (mapcar
6884 (lambda (x) (get-text-property 1 'time-of-day x))
6885 list)))
6886 (string (nth 1 org-agenda-time-grid))
6887 (gridtimes (nth 2 org-agenda-time-grid))
6888 (req (car org-agenda-time-grid))
6889 (remove (member 'remove-match req))
6890 new time)
6891 (if (and (member 'require-timed req) (not have))
6892 ;; don't show empty grid
6893 (throw 'exit list))
6894 (while (setq time (pop gridtimes))
6895 (unless (and remove (member time have))
6896 (setq time (int-to-string time))
6897 (push (org-format-agenda-item
6898 nil string "" nil
6899 (concat (substring time 0 -2) ":" (substring time -2)))
6900 new)
6901 (put-text-property
6902 1 (length (car new)) 'face 'org-time-grid (car new))))
6903 (if (member 'time-up org-agenda-sorting-strategy)
6904 (append new list)
6905 (append list new)))))
6906
6907 (defun org-compile-prefix-format (format)
6908 "Compile the prefix format into a Lisp form that can be evaluated.
6909 The resulting form is returned and stored in the variable
6910 `org-prefix-format-compiled'."
6911 (setq org-prefix-has-time nil org-prefix-has-tag nil)
6912 (let ((start 0) varform vars var (s format)e c f opt)
6913 (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([cts]\\)"
6914 s start)
6915 (setq var (cdr (assoc (match-string 4 s)
6916 '(("c" . category) ("t" . time) ("s" . extra)
6917 ("T" . tag))))
6918 c (or (match-string 3 s) "")
6919 opt (match-beginning 1)
6920 start (1+ (match-beginning 0)))
6921 (if (equal var 'time) (setq org-prefix-has-time t))
6922 (if (equal var 'tag) (setq org-prefix-has-tag t))
6923 (setq f (concat "%" (match-string 2 s) "s"))
6924 (if opt
6925 (setq varform
6926 `(if (equal "" ,var)
6927 ""
6928 (format ,f (if (equal "" ,var) "" (concat ,var ,c)))))
6929 (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c)))))
6930 (setq s (replace-match "%s" t nil s))
6931 (push varform vars))
6932 (setq vars (nreverse vars))
6933 (setq org-prefix-format-compiled `(format ,s ,@vars))))
6934
6935 (defun org-get-time-of-day (s &optional string)
6936 "Check string S for a time of day.
6937 If found, return it as a military time number between 0 and 2400.
6938 If not found, return nil.
6939 The optional STRING argument forces conversion into a 5 character wide string
6940 HH:MM."
6941 (save-match-data
6942 (when
6943 (or
6944 (string-match
6945 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)\\([AaPp][Mm]\\)?\\> *" s)
6946 (string-match
6947 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\([AaPp][Mm]\\)\\> *" s))
6948 (let* ((t0 (+ (* 100
6949 (+ (string-to-number (match-string 1 s))
6950 (if (and (match-beginning 4)
6951 (equal (downcase (match-string 4 s)) "pm"))
6952 12 0)))
6953 (if (match-beginning 3)
6954 (string-to-number (match-string 3 s))
6955 0)))
6956 (t1 (concat " "
6957 (if (< t0 100) "0" "") (if (< t0 10) "0" "")
6958 (int-to-string t0))))
6959 (if string (concat (substring t1 -4 -2) ":" (substring t1 -2)) t0)))))
6960
6961 (defun org-finalize-agenda-entries (list)
6962 "Sort and concatenate the agenda items."
6963 (setq list (mapcar 'org-agenda-highlight-todo list))
6964 (mapconcat 'identity (sort list 'org-entries-lessp) "\n"))
6965
6966 (defun org-agenda-highlight-todo (x)
6967 (let (re pl)
6968 (if (eq x 'line)
6969 (save-excursion
6970 (beginning-of-line 1)
6971 (setq re (get-text-property (point) 'org-not-done-regexp))
6972 (goto-char (+ (point) (get-text-property (point) 'prefix-length)))
6973 (and (looking-at (concat "[ \t]*" re))
6974 (add-text-properties (match-beginning 0) (match-end 0)
6975 '(face org-todo))))
6976 (setq re (get-text-property 0 'org-not-done-regexp x)
6977 pl (get-text-property 0 'prefix-length x))
6978 (and re (equal (string-match re x pl) pl)
6979 (add-text-properties (match-beginning 0) (match-end 0)
6980 '(face org-todo) x))
6981 x)))
6982
6983 (defsubst org-cmp-priority (a b)
6984 "Compare the priorities of string A and B."
6985 (let ((pa (or (get-text-property 1 'priority a) 0))
6986 (pb (or (get-text-property 1 'priority b) 0)))
6987 (cond ((> pa pb) +1)
6988 ((< pa pb) -1)
6989 (t nil))))
6990
6991 (defsubst org-cmp-category (a b)
6992 "Compare the string values of categories of strings A and B."
6993 (let ((ca (or (get-text-property 1 'category a) ""))
6994 (cb (or (get-text-property 1 'category b) "")))
6995 (cond ((string-lessp ca cb) -1)
6996 ((string-lessp cb ca) +1)
6997 (t nil))))
6998
6999 (defsubst org-cmp-time (a b)
7000 "Compare the time-of-day values of strings A and B."
7001 (let* ((def (if org-sort-agenda-notime-is-late 2401 -1))
7002 (ta (or (get-text-property 1 'time-of-day a) def))
7003 (tb (or (get-text-property 1 'time-of-day b) def)))
7004 (cond ((< ta tb) -1)
7005 ((< tb ta) +1)
7006 (t nil))))
7007
7008 (defun org-entries-lessp (a b)
7009 "Predicate for sorting agenda entries."
7010 ;; The following variables will be used when the form is evaluated.
7011 (let* ((time-up (org-cmp-time a b))
7012 (time-down (if time-up (- time-up) nil))
7013 (priority-up (org-cmp-priority a b))
7014 (priority-down (if priority-up (- priority-up) nil))
7015 (category-up (org-cmp-category a b))
7016 (category-down (if category-up (- category-up) nil))
7017 (category-keep (if category-up +1 nil)))
7018 (cdr (assoc
7019 (eval (cons 'or org-agenda-sorting-strategy))
7020 '((-1 . t) (1 . nil) (nil . nil))))))
7021
7022 (defun org-agenda-show-priority ()
7023 "Show the priority of the current item.
7024 This priority is composed of the main priority given with the [#A] cookies,
7025 and by additional input from the age of a schedules or deadline entry."
7026 (interactive)
7027 (let* ((pri (get-text-property (point-at-bol) 'priority)))
7028 (message "Priority is %d" (if pri pri -1000))))
7029
7030 (defun org-agenda-show-tags ()
7031 "Show the tags applicable to the current item."
7032 (interactive)
7033 (let* ((tags (get-text-property (point-at-bol) 'tags)))
7034 (if tags
7035 (message "Tags are :%s:"
7036 (org-no-properties (mapconcat 'identity tags ":")))
7037 (message "No tags associated with this line"))))
7038
7039 (defun org-agenda-goto (&optional highlight)
7040 "Go to the Org-mode file which contains the item at point."
7041 (interactive)
7042 (let* ((marker (or (get-text-property (point) 'org-marker)
7043 (org-agenda-error)))
7044 (buffer (marker-buffer marker))
7045 (pos (marker-position marker)))
7046 (switch-to-buffer-other-window buffer)
7047 (widen)
7048 (goto-char pos)
7049 (when (eq major-mode 'org-mode)
7050 (org-show-hidden-entry)
7051 (save-excursion
7052 (and (outline-next-heading)
7053 (org-flag-heading nil)))) ; show the next heading
7054 (and highlight (org-highlight (point-at-bol) (point-at-eol)))))
7055
7056 (defun org-agenda-switch-to ()
7057 "Go to the Org-mode file which contains the item at point."
7058 (interactive)
7059 (let* ((marker (or (get-text-property (point) 'org-marker)
7060 (org-agenda-error)))
7061 (buffer (marker-buffer marker))
7062 (pos (marker-position marker)))
7063 (switch-to-buffer buffer)
7064 (delete-other-windows)
7065 (widen)
7066 (goto-char pos)
7067 (when (eq major-mode 'org-mode)
7068 (org-show-hidden-entry)
7069 (save-excursion
7070 (and (outline-next-heading)
7071 (org-flag-heading nil)))))) ; show the next heading
7072
7073 (defun org-agenda-goto-mouse (ev)
7074 "Go to the Org-mode file which contains the item at the mouse click."
7075 (interactive "e")
7076 (mouse-set-point ev)
7077 (org-agenda-goto))
7078
7079 (defun org-agenda-show ()
7080 "Display the Org-mode file which contains the item at point."
7081 (interactive)
7082 (let ((win (selected-window)))
7083 (org-agenda-goto t)
7084 (select-window win)))
7085
7086 (defun org-agenda-recenter (arg)
7087 "Display the Org-mode file which contains the item at point and recenter."
7088 (interactive "P")
7089 (let ((win (selected-window)))
7090 (org-agenda-goto t)
7091 (recenter arg)
7092 (select-window win)))
7093
7094 (defun org-agenda-show-mouse (ev)
7095 "Display the Org-mode file which contains the item at the mouse click."
7096 (interactive "e")
7097 (mouse-set-point ev)
7098 (org-agenda-show))
7099
7100 (defun org-agenda-check-no-diary ()
7101 "Check if the entry is a diary link and abort if yes."
7102 (if (get-text-property (point) 'org-agenda-diary-link)
7103 (org-agenda-error)))
7104
7105 (defun org-agenda-error ()
7106 (error "Command not allowed in this line"))
7107
7108 (defvar org-last-heading-marker (make-marker)
7109 "Marker pointing to the headline that last changed its TODO state
7110 by a remote command from the agenda.")
7111
7112 (defun org-agenda-todo (&optional arg)
7113 "Cycle TODO state of line at point, also in Org-mode file.
7114 This changes the line at point, all other lines in the agenda referring to
7115 the same tree node, and the headline of the tree node in the Org-mode file."
7116 (interactive "P")
7117 (org-agenda-check-no-diary)
7118 (let* ((col (current-column))
7119 (marker (or (get-text-property (point) 'org-marker)
7120 (org-agenda-error)))
7121 (buffer (marker-buffer marker))
7122 (pos (marker-position marker))
7123 (hdmarker (get-text-property (point) 'org-hd-marker))
7124 (buffer-read-only nil)
7125 newhead)
7126 (with-current-buffer buffer
7127 (widen)
7128 (goto-char pos)
7129 (org-show-hidden-entry)
7130 (save-excursion
7131 (and (outline-next-heading)
7132 (org-flag-heading nil))) ; show the next heading
7133 (org-todo arg)
7134 (and (bolp) (forward-char 1))
7135 (setq newhead (org-get-heading))
7136 (save-excursion
7137 (org-back-to-heading)
7138 (move-marker org-last-heading-marker (point))))
7139 (beginning-of-line 1)
7140 (save-excursion
7141 (org-agenda-change-all-lines newhead hdmarker 'fixface))
7142 (move-to-column col)))
7143
7144 (defun org-agenda-change-all-lines (newhead hdmarker &optional fixface)
7145 "Change all lines in the agenda buffer which match HDMARKER.
7146 The new content of the line will be NEWHEAD (as modified by
7147 `org-format-agenda-item'). HDMARKER is checked with
7148 `equal' against all `org-hd-marker' text properties in the file.
7149 If FIXFACE is non-nil, the face of each item is modified acording to
7150 the new TODO state."
7151 (let* (props m pl undone-face done-face finish new dotime cat tags)
7152 ; (setq newhead (org-format-agenda-item "x" newhead "x" nil 'noprefix))
7153 (save-excursion
7154 (goto-char (point-max))
7155 (beginning-of-line 1)
7156 (while (not finish)
7157 (setq finish (bobp))
7158 (when (and (setq m (get-text-property (point) 'org-hd-marker))
7159 (equal m hdmarker))
7160 (setq props (text-properties-at (point))
7161 dotime (get-text-property (point) 'dotime)
7162 cat (get-text-property (point) 'category)
7163 tags (get-text-property (point) 'tags)
7164 new (org-format-agenda-item "x" newhead cat tags dotime 'noprefix)
7165 pl (get-text-property (point) 'prefix-length)
7166 undone-face (get-text-property (point) 'undone-face)
7167 done-face (get-text-property (point) 'done-face))
7168 (move-to-column pl)
7169 (if (looking-at ".*")
7170 (progn
7171 (replace-match new t t)
7172 (beginning-of-line 1)
7173 (add-text-properties (point-at-bol) (point-at-eol) props)
7174 (when fixface
7175 (add-text-properties
7176 (point-at-bol) (point-at-eol)
7177 (list 'face
7178 (if org-last-todo-state-is-todo
7179 undone-face done-face)))
7180 (org-agenda-highlight-todo 'line))
7181 (beginning-of-line 1))
7182 (error "Line update did not work")))
7183 (beginning-of-line 0)))))
7184
7185 (defun org-agenda-priority-up ()
7186 "Increase the priority of line at point, also in Org-mode file."
7187 (interactive)
7188 (org-agenda-priority 'up))
7189
7190 (defun org-agenda-priority-down ()
7191 "Decrease the priority of line at point, also in Org-mode file."
7192 (interactive)
7193 (org-agenda-priority 'down))
7194
7195 (defun org-agenda-priority (&optional force-direction)
7196 "Set the priority of line at point, also in Org-mode file.
7197 This changes the line at point, all other lines in the agenda referring to
7198 the same tree node, and the headline of the tree node in the Org-mode file."
7199 (interactive)
7200 (org-agenda-check-no-diary)
7201 (let* ((marker (or (get-text-property (point) 'org-marker)
7202 (org-agenda-error)))
7203 (buffer (marker-buffer marker))
7204 (pos (marker-position marker))
7205 (hdmarker (get-text-property (point) 'org-hd-marker))
7206 (buffer-read-only nil)
7207 newhead)
7208 (with-current-buffer buffer
7209 (widen)
7210 (goto-char pos)
7211 (org-show-hidden-entry)
7212 (save-excursion
7213 (and (outline-next-heading)
7214 (org-flag-heading nil))) ; show the next heading
7215 (funcall 'org-priority force-direction)
7216 (end-of-line 1)
7217 (setq newhead (org-get-heading)))
7218 (org-agenda-change-all-lines newhead hdmarker)
7219 (beginning-of-line 1)))
7220
7221 (defun org-get-tags-at (&optional pos)
7222 "Get a list of all headline tags applicable at POS.
7223 POS defaults to point. If tags are inherited, the list contains
7224 the targets in the same sequence as the headlines appear, i.e.
7225 the tags of the current headline come last."
7226 (interactive)
7227 (let (tags)
7228 (save-excursion
7229 (goto-char (or pos (point)))
7230 (save-match-data
7231 (org-back-to-heading t)
7232 (condition-case nil
7233 (while t
7234 (if (looking-at "[^\r\n]+?:\\([a-zA-Z_@0-9:]+\\):[ \t]*\\([\n\r]\\|\\'\\)")
7235 (setq tags (append (org-split-string
7236 (org-match-string-no-properties 1) ":")
7237 tags)))
7238 (or org-use-tag-inheritance (error ""))
7239 (org-up-heading-all 1))
7240 (error nil))))
7241 (message "%s" tags)
7242 tags))
7243
7244 (defun org-agenda-set-tags ()
7245 "Set tags for the current headline."
7246 (interactive)
7247 (org-agenda-check-no-diary)
7248 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
7249 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
7250 (org-agenda-error)))
7251 (buffer (marker-buffer hdmarker))
7252 (pos (marker-position hdmarker))
7253 (buffer-read-only nil)
7254 newhead)
7255 (with-current-buffer buffer
7256 (widen)
7257 (goto-char pos)
7258 (org-show-hidden-entry)
7259 (save-excursion
7260 (and (outline-next-heading)
7261 (org-flag-heading nil))) ; show the next heading
7262 (call-interactively 'org-set-tags)
7263 (end-of-line 1)
7264 (setq newhead (org-get-heading)))
7265 (org-agenda-change-all-lines newhead hdmarker)
7266 (beginning-of-line 1)))
7267
7268 (defun org-agenda-date-later (arg &optional what)
7269 "Change the date of this item to one day later."
7270 (interactive "p")
7271 (org-agenda-check-type t 'agenda 'timeline)
7272 (org-agenda-check-no-diary)
7273 (let* ((marker (or (get-text-property (point) 'org-marker)
7274 (org-agenda-error)))
7275 (buffer (marker-buffer marker))
7276 (pos (marker-position marker)))
7277 (with-current-buffer buffer
7278 (widen)
7279 (goto-char pos)
7280 (if (not (org-at-timestamp-p))
7281 (error "Cannot find time stamp"))
7282 (org-timestamp-change arg (or what 'day))
7283 (message "Time stamp changed to %s" org-last-changed-timestamp))))
7284
7285 (defun org-agenda-date-earlier (arg &optional what)
7286 "Change the date of this item to one day earlier."
7287 (interactive "p")
7288 (org-agenda-date-later (- arg) what))
7289
7290 (defun org-agenda-date-prompt (arg)
7291 "Change the date of this item. Date is prompted for, with default today.
7292 The prefix ARG is passed to the `org-time-stamp' command and can therefore
7293 be used to request time specification in the time stamp."
7294 (interactive "P")
7295 (org-agenda-check-type t 'agenda 'timeline)
7296 (org-agenda-check-no-diary)
7297 (let* ((marker (or (get-text-property (point) 'org-marker)
7298 (org-agenda-error)))
7299 (buffer (marker-buffer marker))
7300 (pos (marker-position marker)))
7301 (with-current-buffer buffer
7302 (widen)
7303 (goto-char pos)
7304 (if (not (org-at-timestamp-p))
7305 (error "Cannot find time stamp"))
7306 (org-time-stamp arg)
7307 (message "Time stamp changed to %s" org-last-changed-timestamp))))
7308
7309 (defun org-agenda-schedule (arg)
7310 "Schedule the item at point."
7311 (interactive "P")
7312 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
7313 (org-agenda-check-no-diary)
7314 (let* ((marker (or (get-text-property (point) 'org-marker)
7315 (org-agenda-error)))
7316 (buffer (marker-buffer marker))
7317 (pos (marker-position marker))
7318 (org-insert-labeled-timestamps-at-point nil)
7319 ts)
7320 (with-current-buffer buffer
7321 (widen)
7322 (goto-char pos)
7323 (setq ts (org-schedule))
7324 (message "Item scheduled for %s" ts))))
7325
7326 (defun org-agenda-deadline (arg)
7327 "Schedule the item at point."
7328 (interactive "P")
7329 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
7330 (org-agenda-check-no-diary)
7331 (let* ((marker (or (get-text-property (point) 'org-marker)
7332 (org-agenda-error)))
7333 (buffer (marker-buffer marker))
7334 (pos (marker-position marker))
7335 (org-insert-labeled-timestamps-at-point nil)
7336 ts)
7337 (with-current-buffer buffer
7338 (widen)
7339 (goto-char pos)
7340 (setq ts (org-deadline))
7341 (message "Deadline for this item set to %s" ts))))
7342
7343 (defun org-get-heading ()
7344 "Return the heading of the current entry, without the stars."
7345 (save-excursion
7346 (and (memq (char-before) '(?\n ?\r)) (skip-chars-forward "^\n\r"))
7347 (if (and (re-search-backward "[\r\n]\\*" nil t)
7348 (looking-at "[\r\n]\\*+[ \t]+\\([^\r\n]*\\)"))
7349 (match-string 1)
7350 "")))
7351
7352 (defun org-agenda-diary-entry ()
7353 "Make a diary entry, like the `i' command from the calendar.
7354 All the standard commands work: block, weekly etc."
7355 (interactive)
7356 (org-agenda-check-type t 'agenda 'timeline)
7357 (require 'diary-lib)
7358 (let* ((char (progn
7359 (message "Diary entry: [d]ay [w]eekly [m]onthly [y]early [a]nniversary [b]lock [c]yclic")
7360 (read-char-exclusive)))
7361 (cmd (cdr (assoc char
7362 '((?d . insert-diary-entry)
7363 (?w . insert-weekly-diary-entry)
7364 (?m . insert-monthly-diary-entry)
7365 (?y . insert-yearly-diary-entry)
7366 (?a . insert-anniversary-diary-entry)
7367 (?b . insert-block-diary-entry)
7368 (?c . insert-cyclic-diary-entry)))))
7369 (oldf (symbol-function 'calendar-cursor-to-date))
7370 (point (point))
7371 (mark (or (mark t) (point))))
7372 (unless cmd
7373 (error "No command associated with <%c>" char))
7374 (unless (and (get-text-property point 'day)
7375 (or (not (equal ?b char))
7376 (get-text-property mark 'day)))
7377 (error "Don't know which date to use for diary entry"))
7378 ;; We implement this by hacking the `calendar-cursor-to-date' function
7379 ;; and the `calendar-mark-ring' variable. Saves a lot of code.
7380 (let ((calendar-mark-ring
7381 (list (calendar-gregorian-from-absolute
7382 (or (get-text-property mark 'day)
7383 (get-text-property point 'day))))))
7384 (unwind-protect
7385 (progn
7386 (fset 'calendar-cursor-to-date
7387 (lambda (&optional error)
7388 (calendar-gregorian-from-absolute
7389 (get-text-property point 'day))))
7390 (call-interactively cmd))
7391 (fset 'calendar-cursor-to-date oldf)))))
7392
7393
7394 (defun org-agenda-execute-calendar-command (cmd)
7395 "Execute a calendar command from the agenda, with the date associated to
7396 the cursor position."
7397 (org-agenda-check-type t 'agenda 'timeline)
7398 (require 'diary-lib)
7399 (unless (get-text-property (point) 'day)
7400 (error "Don't know which date to use for calendar command"))
7401 (let* ((oldf (symbol-function 'calendar-cursor-to-date))
7402 (point (point))
7403 (date (calendar-gregorian-from-absolute
7404 (get-text-property point 'day)))
7405 (displayed-day (extract-calendar-day date))
7406 (displayed-month (extract-calendar-month date))
7407 (displayed-year (extract-calendar-year date)))
7408 (unwind-protect
7409 (progn
7410 (fset 'calendar-cursor-to-date
7411 (lambda (&optional error)
7412 (calendar-gregorian-from-absolute
7413 (get-text-property point 'day))))
7414 (call-interactively cmd))
7415 (fset 'calendar-cursor-to-date oldf))))
7416
7417 (defun org-agenda-phases-of-moon ()
7418 "Display the phases of the moon for the 3 months around the cursor date."
7419 (interactive)
7420 (org-agenda-execute-calendar-command 'calendar-phases-of-moon))
7421
7422 (defun org-agenda-holidays ()
7423 "Display the holidays for the 3 months around the cursor date."
7424 (interactive)
7425 (org-agenda-execute-calendar-command 'list-calendar-holidays))
7426
7427 (defun org-agenda-sunrise-sunset (arg)
7428 "Display sunrise and sunset for the cursor date.
7429 Latitude and longitude can be specified with the variables
7430 `calendar-latitude' and `calendar-longitude'. When called with prefix
7431 argument, latitude and longitude will be prompted for."
7432 (interactive "P")
7433 (let ((calendar-longitude (if arg nil calendar-longitude))
7434 (calendar-latitude (if arg nil calendar-latitude))
7435 (calendar-location-name
7436 (if arg "the given coordinates" calendar-location-name)))
7437 (org-agenda-execute-calendar-command 'calendar-sunrise-sunset)))
7438
7439 (defun org-agenda-goto-calendar ()
7440 "Open the Emacs calendar with the date at the cursor."
7441 (interactive)
7442 (org-agenda-check-type t 'agenda 'timeline)
7443 (let* ((day (or (get-text-property (point) 'day)
7444 (error "Don't know which date to open in calendar")))
7445 (date (calendar-gregorian-from-absolute day))
7446 (calendar-move-hook nil)
7447 (view-calendar-holidays-initially nil)
7448 (view-diary-entries-initially nil))
7449 (calendar)
7450 (calendar-goto-date date)))
7451
7452 (defun org-calendar-goto-agenda ()
7453 "Compute the Org-mode agenda for the calendar date displayed at the cursor.
7454 This is a command that has to be installed in `calendar-mode-map'."
7455 (interactive)
7456 (org-agenda-list nil (calendar-absolute-from-gregorian
7457 (calendar-cursor-to-date))
7458 nil t))
7459
7460 (defun org-agenda-convert-date ()
7461 (interactive)
7462 (org-agenda-check-type t 'agenda 'timeline)
7463 (let ((day (get-text-property (point) 'day))
7464 date s)
7465 (unless day
7466 (error "Don't know which date to convert"))
7467 (setq date (calendar-gregorian-from-absolute day))
7468 (setq s (concat
7469 "Gregorian: " (calendar-date-string date) "\n"
7470 "ISO: " (calendar-iso-date-string date) "\n"
7471 "Day of Yr: " (calendar-day-of-year-string date) "\n"
7472 "Julian: " (calendar-julian-date-string date) "\n"
7473 "Astron. JD: " (calendar-astro-date-string date)
7474 " (Julian date number at noon UTC)\n"
7475 "Hebrew: " (calendar-hebrew-date-string date) " (until sunset)\n"
7476 "Islamic: " (calendar-islamic-date-string date) " (until sunset)\n"
7477 "French: " (calendar-french-date-string date) "\n"
7478 "Mayan: " (calendar-mayan-date-string date) "\n"
7479 "Coptic: " (calendar-coptic-date-string date) "\n"
7480 "Ethiopic: " (calendar-ethiopic-date-string date) "\n"
7481 "Persian: " (calendar-persian-date-string date) "\n"
7482 "Chinese: " (calendar-chinese-date-string date) "\n"))
7483 (with-output-to-temp-buffer "*Dates*"
7484 (princ s))
7485 (if (fboundp 'fit-window-to-buffer)
7486 (fit-window-to-buffer (get-buffer-window "*Dates*")))))
7487
7488 ;;; Tags
7489
7490 (defun org-scan-tags (action matcher &optional todo-only)
7491 "Scan headline tags with inheritance and produce output ACTION.
7492 ACTION can be `sparse-tree' or `agenda'. MATCHER is a Lisp form to be
7493 evaluated, testing if a given set of tags qualifies a headline for
7494 inclusion. When TODO-ONLY is non-nil, only lines with a TODO keyword
7495 are included in the output."
7496 (let* ((re (concat "[\n\r]" outline-regexp " *\\(\\<\\("
7497 (mapconcat 'regexp-quote
7498 (nreverse (cdr (reverse org-todo-keywords)))
7499 "\\|")
7500 "\\>\\)\\)? *\\(.*?\\)\\(:[A-Za-z_@0-9:]+:\\)?[ \t]*[\n\r]"))
7501 (props (list 'face nil
7502 'done-face 'org-done
7503 'undone-face nil
7504 'mouse-face 'highlight
7505 'keymap org-agenda-keymap
7506 'help-echo
7507 (format "mouse-2 or RET jump to org file %s"
7508 (abbreviate-file-name buffer-file-name))))
7509 lspos
7510 tags tags-list tags-alist (llast 0) rtn level category i txt
7511 todo marker)
7512
7513 (save-excursion
7514 (goto-char (point-min))
7515 (when (eq action 'sparse-tree) (org-overview))
7516 (while (re-search-forward re nil t)
7517 (setq todo (if (match-end 1) (match-string 2))
7518 tags (if (match-end 4) (match-string 4)))
7519 (goto-char (setq lspos (1+ (match-beginning 0))))
7520 (setq level (funcall outline-level)
7521 category (org-get-category))
7522 (setq i llast llast level)
7523 ;; remove tag lists from same and sublevels
7524 (while (>= i level)
7525 (when (setq entry (assoc i tags-alist))
7526 (setq tags-alist (delete entry tags-alist)))
7527 (setq i (1- i)))
7528 ;; add the nex tags
7529 (when tags
7530 (setq tags (mapcar 'downcase (org-split-string tags ":"))
7531 tags-alist
7532 (cons (cons level tags) tags-alist)))
7533 ;; compile tags for current headline
7534 (setq tags-list
7535 (if org-use-tag-inheritance
7536 (apply 'append (mapcar 'cdr tags-alist))
7537 tags))
7538 (when (and (or (not todo-only) todo)
7539 (eval matcher))
7540 ;; list this headline
7541 (if (eq action 'sparse-tree)
7542 (progn
7543 (org-show-hierarchy-above))
7544 (setq txt (org-format-agenda-item
7545 ""
7546 (concat
7547 (if org-tags-match-list-sublevels
7548 (make-string (1- level) ?.) "")
7549 (org-get-heading))
7550 category tags-list))
7551 (goto-char lspos)
7552 (setq marker (org-agenda-new-marker))
7553 (org-add-props txt props
7554 'org-marker marker 'org-hd-marker marker 'category category)
7555 (push txt rtn))
7556 ;; if we are to skip sublevels, jump to end of subtree
7557 (point)
7558 (or org-tags-match-list-sublevels (org-end-of-subtree)))))
7559 (nreverse rtn)))
7560
7561 (defun org-tags-sparse-tree (&optional arg match)
7562 "Create a sparse tree according to tags search string MATCH.
7563 MATCH can contain positive and negative selection of tags, like
7564 \"+WORK+URGENT-WITHBOSS\"."
7565 (interactive "P")
7566 (let ((org-show-following-heading nil)
7567 (org-show-hierarchy-above nil))
7568 (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match)))))
7569
7570 (defun org-make-tags-matcher (match)
7571 "Create the TAGS matcher form for the tags-selecting string MATCH."
7572 (unless match
7573 ;; Get a new match request, with completion
7574 (setq org-last-tags-completion-table
7575 (or (org-get-buffer-tags)
7576 org-last-tags-completion-table))
7577 (setq match (completing-read
7578 "Tags: " 'org-tags-completion-function nil nil nil
7579 'org-tags-history)))
7580 ;; parse the string and create a lisp form
7581 (let ((match0 match) minus tag mm matcher orterms term orlist)
7582 (setq orterms (org-split-string match "|"))
7583 (while (setq term (pop orterms))
7584 (while (string-match "^&?\\([-+:]\\)?\\([A-Za-z_@0-9]+\\)" term)
7585 (setq minus (and (match-end 1)
7586 (equal (match-string 1 term) "-"))
7587 tag (match-string 2 term)
7588 term (substring term (match-end 0))
7589 mm (list 'member (downcase tag) 'tags-list)
7590 mm (if minus (list 'not mm) mm))
7591 (push mm matcher))
7592 (push (if (> (length matcher) 1) (cons 'and matcher) (car matcher))
7593 orlist)
7594 (setq matcher nil))
7595 (setq matcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist)))
7596 ;; Return the string and lisp forms of the matcher
7597 (cons match0 matcher)))
7598
7599 ;;;###autoload
7600 (defun org-tags-view (&optional todo-only match keep-modes)
7601 "Show all headlines for all `org-agenda-files' matching a TAGS criterion.
7602 The prefix arg TODO-ONLY limits the search to TODO entries."
7603 (interactive "P")
7604 (org-agenda-maybe-reset-markers 'force)
7605 (org-compile-prefix-format org-agenda-prefix-format)
7606 (let* ((org-agenda-keep-modes keep-modes)
7607 (org-tags-match-list-sublevels
7608 (if todo-only t org-tags-match-list-sublevels))
7609 (win (selected-window))
7610 (completion-ignore-case t)
7611 rtn rtnall files file pos matcher
7612 buffer)
7613 (setq matcher (org-make-tags-matcher match)
7614 match (car matcher) matcher (cdr matcher))
7615 (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name)))
7616 (progn
7617 (delete-other-windows)
7618 (switch-to-buffer-other-window
7619 (get-buffer-create org-agenda-buffer-name))))
7620 (setq buffer-read-only nil)
7621 (erase-buffer)
7622 (org-agenda-mode) (setq buffer-read-only nil)
7623 (set (make-local-variable 'org-agenda-type) 'tags)
7624 (set (make-local-variable 'org-agenda-redo-command)
7625 (list 'org-tags-view (list 'quote todo-only)
7626 (list 'if 'current-prefix-arg nil match) t))
7627 (setq files (org-agenda-files)
7628 rtnall nil)
7629 (while (setq file (pop files))
7630 (catch 'nextfile
7631 (org-check-agenda-file file)
7632 (setq buffer (if (file-exists-p file)
7633 (org-get-agenda-file-buffer file)
7634 (error "No such file %s" file)))
7635 (if (not buffer)
7636 ;; If file does not exist, merror message to agenda
7637 (setq rtn (list
7638 (format "ORG-AGENDA-ERROR: No such org-file %s" file))
7639 rtnall (append rtnall rtn))
7640 (with-current-buffer buffer
7641 (unless (eq major-mode 'org-mode)
7642 (error "Agenda file %s is not in `org-mode'" file))
7643 (setq org-category-table (org-get-category-table))
7644 (save-excursion
7645 (save-restriction
7646 (if org-respect-restriction
7647 (if (org-region-active-p)
7648 ;; Respect a region to restrict search
7649 (narrow-to-region (region-beginning) (region-end)))
7650 ;; If we work for the calendar or many files,
7651 ;; get rid of any restriction
7652 (widen))
7653 (setq rtn (org-scan-tags 'agenda matcher todo-only))
7654 (setq rtnall (append rtnall rtn))))))))
7655 (insert "Headlines with TAGS match: ")
7656 (add-text-properties (point-min) (1- (point))
7657 (list 'face 'org-level-3))
7658 (setq pos (point))
7659 (insert match "\n")
7660 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
7661 (setq pos (point))
7662 (insert "Press `C-u r' to search again with new search string\n")
7663 (add-text-properties pos (1- (point)) (list 'face 'org-level-3))
7664 (when rtnall
7665 (insert (mapconcat 'identity rtnall "\n")))
7666 (goto-char (point-min))
7667 (setq buffer-read-only t)
7668 (org-fit-agenda-window)
7669 (if (not org-select-agenda-window) (select-window win))))
7670
7671 (defvar org-add-colon-after-tag-completion nil) ;; dynamically skoped param
7672 (defun org-set-tags (&optional arg just-align)
7673 "Set the tags for the current headline.
7674 With prefix ARG, realign all tags in headings in the current buffer."
7675 (interactive "P")
7676 (let* ((re (concat "^" outline-regexp))
7677 (col (current-column))
7678 (current (org-get-tags))
7679 table current-tags inherited-tags ; computed below when needed
7680 tags hd empty invis)
7681 (if arg
7682 (save-excursion
7683 (goto-char (point-min))
7684 (while (re-search-forward re nil t)
7685 (org-set-tags nil t))
7686 (message "All tags realigned to column %d" org-tags-column))
7687 (if just-align
7688 (setq tags current)
7689 (setq table (or org-tag-alist (org-get-buffer-tags))
7690 org-last-tags-completion-table table
7691 current-tags (org-split-string current ":")
7692 inherited-tags (nreverse
7693 (nthcdr (length current-tags)
7694 (nreverse (org-get-tags-at))))
7695 tags
7696 (if (or (eq t org-use-fast-tag-selection)
7697 (and org-use-fast-tag-selection (cdar table)))
7698 (org-fast-tag-selection current-tags inherited-tags table)
7699 (let ((org-add-colon-after-tag-completion t))
7700 (completing-read "Tags: " 'org-tags-completion-function
7701 nil nil current 'org-tags-history))))
7702 (while (string-match "[-+&]+" tags)
7703 (setq tags (replace-match ":" t t tags))))
7704
7705 ;; FIXME: still optimize this by not checking when JUST-ALIGN?
7706 (unless (setq empty (string-match "\\`[\t ]*\\'" tags))
7707 (unless (string-match ":$" tags) (setq tags (concat tags ":")))
7708 (unless (string-match "^:" tags) (setq tags (concat ":" tags))))
7709 (if (equal current "")
7710 (progn
7711 (end-of-line 1)
7712 (or empty (insert-before-markers " ")))
7713 (beginning-of-line 1)
7714 (setq invis (org-invisible-p))
7715 (looking-at (concat "\\(.*\\)\\(" (regexp-quote current) "\\)[ \t]*"))
7716 (setq hd (match-string 1))
7717 (delete-region (match-beginning 0) (match-end 0))
7718 (insert-before-markers (org-trim hd) (if empty "" " ")))
7719 (unless (equal tags "")
7720 (move-to-column (max (current-column)
7721 (if (> org-tags-column 0)
7722 org-tags-column
7723 (- (- org-tags-column) (length tags))))
7724 t)
7725 (insert-before-markers tags)
7726 (if (and (not invis) (org-invisible-p))
7727 (outline-flag-region (point-at-bol) (point) nil)))
7728 (move-to-column col))))
7729
7730 (defun org-tags-completion-function (string predicate &optional flag)
7731 (let (s1 s2 rtn (ctable org-last-tags-completion-table))
7732 (if (string-match "^\\(.*[-+:&|]\\)\\([^-+:&|]*\\)$" string)
7733 (setq s1 (match-string 1 string)
7734 s2 (match-string 2 string))
7735 (setq s1 "" s2 string))
7736 (cond
7737 ((eq flag nil)
7738 ;; try completion
7739 (setq rtn (try-completion s2 ctable))
7740 (if (stringp rtn)
7741 (concat s1 s2 (substring rtn (length s2))
7742 (if (and org-add-colon-after-tag-completion
7743 (assoc rtn ctable))
7744 ":" "")))
7745 )
7746 ((eq flag t)
7747 ;; all-completions
7748 (all-completions s2 ctable)
7749 )
7750 ((eq flag 'lambda)
7751 ;; exact match?
7752 (assoc s2 ctable)))
7753 ))
7754
7755 (defun org-fast-tag-insert (kwd tags face &optional end)
7756 "Insert KDW, and the TAGS, the latter with face FACE. Also inser END."
7757 (insert (format "%-12s" (concat kwd ":"))
7758 (org-add-props (mapconcat 'identity tags " ") nil 'face face)
7759 (or end "")))
7760
7761 (defun org-fast-tag-selection (current inherited table)
7762 "Fast tag selection with single keys.
7763 CURRENT is the current list of tags in the headline, INHERITED is the
7764 list of inherited tags, and TABLE is an alist of tags and corresponding keys.
7765 If the keys are nil, a-z are automatically assigned.
7766 Returns the new tags string, or nil to not change the current settings."
7767 (let* ((maxlen (apply 'max (mapcar (lambda (x)
7768 (string-width (car x))) table)))
7769 (fwidth (+ maxlen 3 1 3))
7770 (ncol (/ (window-width) fwidth))
7771 (i-face 'org-done)
7772 (c-face 'org-tag)
7773 tg cnt e c char ntable tbl rtn)
7774 (save-window-excursion
7775 (delete-other-windows)
7776 (split-window-vertically)
7777 (switch-to-buffer-other-window (get-buffer-create " *Org tags*"))
7778 (erase-buffer)
7779 (org-fast-tag-insert "Inherited" inherited i-face "\n")
7780 (org-fast-tag-insert "Current" current c-face "\n\n")
7781 (setq tbl table char (1- ?a) cnt 0)
7782 (while (setq e (pop tbl))
7783 (setq tg (car e) c (or (cdr e) (setq char (1+ char))))
7784 (setq tg (org-add-props tg nil 'face
7785 (cond
7786 ((member tg current) c-face)
7787 ((member tg inherited) i-face)
7788 (t nil))))
7789 (insert "[" c "] " tg (make-string
7790 (- fwidth 4 (length tg)) ?\ ))
7791 (push (cons tg c) ntable)
7792 (when (= (setq cnt (1+ cnt)) ncol)
7793 (insert "\n")
7794 (setq cnt 0)))
7795 (insert "\n")
7796 (goto-char (point-min))
7797 (if (fboundp 'fit-window-to-buffer) (fit-window-to-buffer))
7798 (setq rtn
7799 (catch 'exit
7800 (while t
7801 (message "[key]:Toggle SPC: clear current RET accept")
7802 (setq c (read-char-exclusive))
7803 (cond
7804 ((= c ?\r) (throw 'exit t))
7805 ((= c ?\C-g) (throw 'exit nil))
7806 ((= c ?\ ) (setq current nil))
7807 (t (setq e (rassoc c ntable) tg (car e))
7808 (if (member tg current)
7809 (setq current (delete tg current))
7810 (setq current (append current (list tg))))))
7811 (goto-char (point-min))
7812 (beginning-of-line 2)
7813 (delete-region (point) (point-at-eol))
7814 (org-fast-tag-insert "Current" current c-face)
7815 (while (re-search-forward "\\[.\\] \\([a-zA-Z0-9_@]+\\)" nil t)
7816 (setq tg (match-string 1))
7817 (add-text-properties (match-beginning 1) (match-end 1)
7818 (list 'face
7819 (cond
7820 ((member tg current) c-face)
7821 ((member tg inherited) i-face)
7822 (t nil)))))
7823 (goto-char (point-min)))))
7824 (if rtn
7825 (mapconcat 'identity current ":")
7826 nil))))
7827
7828 (defun org-get-tags ()
7829 "Get the TAGS string in the current headline."
7830 (unless (org-on-heading-p)
7831 (error "Not on a heading"))
7832 (save-excursion
7833 (beginning-of-line 1)
7834 (if (looking-at ".*[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \t]*\\(\r\\|$\\)")
7835 (org-match-string-no-properties 1)
7836 "")))
7837
7838 (defun org-get-buffer-tags ()
7839 "Get a table of all tags used in the buffer, for completion."
7840 (let (tags)
7841 (save-excursion
7842 (goto-char (point-min))
7843 (while (re-search-forward "[ \t]:\\([A-Za-z_@0-9:]+\\):[ \t\r\n]" nil t)
7844 (mapc (lambda (x) (add-to-list 'tags x))
7845 (org-split-string (org-match-string-no-properties 1) ":"))))
7846 (mapcar 'list tags)))
7847
7848 ;;; Link Stuff
7849
7850 (defvar org-create-file-search-functions nil
7851 "List of functions to construct the right search string for a file link.
7852 These functions are called in turn with point at the location to
7853 which the link should point.
7854
7855 A function in the hook should first test if it would like to
7856 handle this file type, for example by checking the major-mode or
7857 the file extension. If it decides not to handle this file, it
7858 should just return nil to give other functions a chance. If it
7859 does handle the file, it must return the search string to be used
7860 when following the link. The search string will be part of the
7861 file link, given after a double colon, and `org-open-at-point'
7862 will automatically search for it. If special measures must be
7863 taken to make the search successful, another function should be
7864 added to the companion hook `org-execute-file-search-functions',
7865 which see.
7866
7867 A function in this hook may also use `setq' to set the variable
7868 `description' to provide a suggestion for the descriptive text to
7869 be used for this link when it gets inserted into an Org-mode
7870 buffer with \\[org-insert-link].")
7871
7872 (defvar org-execute-file-search-functions nil
7873 "List of functions to execute a file search triggered by a link.
7874
7875 Functions added to this hook must accept a single argument, the
7876 search string that was part of the file link, the part after the
7877 double colon. The function must first check if it would like to
7878 handle this search, for example by checking the major-mode or the
7879 file extension. If it decides not to handle this search, it
7880 should just return nil to give other functions a chance. If it
7881 does handle the search, it must return a non-nil value to keep
7882 other functions from trying.
7883
7884 Each function can access the current prefix argument through the
7885 variable `current-prefix-argument'. Note that a single prefix is
7886 used to force opening a link in Emacs, so it may be good to only
7887 use a numeric or double prefix to guide the search function.
7888
7889 In case this is needed, a function in this hook can also restore
7890 the window configuration before `org-open-at-point' was called using:
7891
7892 (set-window-configuration org-window-config-before-follow-link)")
7893
7894 (defun org-find-file-at-mouse (ev)
7895 "Open file link or URL at mouse."
7896 (interactive "e")
7897 (mouse-set-point ev)
7898 (org-open-at-point 'in-emacs))
7899
7900 (defun org-open-at-mouse (ev)
7901 "Open file link or URL at mouse."
7902 (interactive "e")
7903 (mouse-set-point ev)
7904 (org-open-at-point))
7905
7906 (defvar org-window-config-before-follow-link nil
7907 "The window configuration before following a link.
7908 This is saved in case the need arises to restore it.")
7909
7910 (defun org-open-at-point (&optional in-emacs)
7911 "Open link at or after point.
7912 If there is no link at point, this function will search forward up to
7913 the end of the current subtree.
7914 Normally, files will be opened by an appropriate application. If the
7915 optional argument IN-EMACS is non-nil, Emacs will visit the file."
7916 (interactive "P")
7917 (setq org-window-config-before-follow-link (current-window-configuration))
7918 (org-remove-occur-highlights nil nil t)
7919 (if (org-at-timestamp-p)
7920 (org-agenda-list nil (time-to-days (org-time-string-to-time
7921 (substring (match-string 1) 0 10)))
7922 1)
7923 (let (type path link line search (pos (point)))
7924 (catch 'match
7925 (save-excursion
7926 (skip-chars-forward "^]\n\r")
7927 (when (and (re-search-backward "\\[\\[" nil t)
7928 (looking-at org-bracket-link-regexp)
7929 (<= (match-beginning 0) pos)
7930 (>= (match-end 0) pos))
7931 (setq link (org-link-unescape (org-match-string-no-properties 1)))
7932 (while (string-match " *\n *" link)
7933 (setq link (replace-match " " t t link)))
7934 (if (string-match org-link-re-with-space2 link)
7935 (setq type (match-string 1 link)
7936 path (match-string 2 link))
7937 (setq type "thisfile"
7938 path link))
7939 (throw 'match t)))
7940
7941 (when (get-text-property (point) 'org-linked-text)
7942 (setq type "thisfile"
7943 pos (if (get-text-property (1+ (point)) 'org-linked-text)
7944 (1+ (point)) (point))
7945 path (buffer-substring
7946 (previous-single-property-change pos 'org-linked-text)
7947 (next-single-property-change pos 'org-linked-text)))
7948 (throw 'match t))
7949
7950 (save-excursion
7951 (skip-chars-backward (concat "^[]" org-non-link-chars " "))
7952 (if (equal (char-before) ?<) (backward-char 1))
7953 (when (or (looking-at org-angle-link-re)
7954 (looking-at org-plain-link-re)
7955 (and (or (re-search-forward org-angle-link-re (point-at-eol) t)
7956 (re-search-forward org-plain-link-re (point-at-eol) t))
7957 (<= (match-beginning 0) pos)
7958 (>= (match-end 0) pos)))
7959 (setq type (match-string 1)
7960 path (match-string 2))
7961 (throw 'match t)))
7962 (save-excursion
7963 (skip-chars-backward "^ \t\n\r")
7964 (when (looking-at "\\(:[A-Za-z_@0-9:]+\\):[ \t\r\n]")
7965 (setq type "tags"
7966 path (match-string 1))
7967 (while (string-match ":" path)
7968 (setq path (replace-match "+" t t path)))
7969 (throw 'match t)))
7970 (save-excursion
7971 (skip-chars-backward "a-zA-Z_")
7972 (when (and (memq 'camel org-activate-links)
7973 (looking-at org-camel-regexp))
7974 (setq type "camel" path (match-string 0))
7975 (if (equal (char-before) ?*)
7976 (setq path (concat "*" path))))
7977 (throw 'match t)))
7978 (unless path
7979 (error "No link found"))
7980 ;; Remove any trailing spaces in path
7981 (if (string-match " +\\'" path)
7982 (setq path (replace-match "" t t path)))
7983
7984 (cond
7985
7986 ((member type '("http" "https" "ftp" "mailto" "news"))
7987 (browse-url (concat type ":" path)))
7988
7989 ((string= type "tags")
7990 (org-tags-view in-emacs path))
7991 ((or (string= type "camel")
7992 (string= type "thisfile"))
7993 (org-mark-ring-push)
7994 (org-link-search
7995 path
7996 (cond ((equal in-emacs '(4)) 'occur)
7997 ((equal in-emacs '(16)) 'org-occur)
7998 (t nil))))
7999
8000 ((string= type "file")
8001 (if (string-match "::?\\([0-9]+\\)\\'" path) ;; second : optional
8002 ;; FIXME: It is unsafe to allow a single colon.
8003 (setq line (string-to-number (match-string 1 path))
8004 path (substring path 0 (match-beginning 0)))
8005 (if (string-match "::\\(.+\\)\\'" path)
8006 (setq search (match-string 1 path)
8007 path (substring path 0 (match-beginning 0)))))
8008 (org-open-file path in-emacs line search))
8009
8010 ((string= type "news")
8011 (org-follow-gnus-link path))
8012
8013 ((string= type "bbdb")
8014 (org-follow-bbdb-link path))
8015
8016 ((string= type "info")
8017 (org-follow-info-link path))
8018
8019 ((string= type "gnus")
8020 (let (group article)
8021 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
8022 (error "Error in Gnus link"))
8023 (setq group (match-string 1 path)
8024 article (match-string 3 path))
8025 (org-follow-gnus-link group article)))
8026
8027 ((string= type "vm")
8028 (let (folder article)
8029 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
8030 (error "Error in VM link"))
8031 (setq folder (match-string 1 path)
8032 article (match-string 3 path))
8033 ;; in-emacs is the prefix arg, will be interpreted as read-only
8034 (org-follow-vm-link folder article in-emacs)))
8035
8036 ((string= type "wl")
8037 (let (folder article)
8038 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
8039 (error "Error in Wanderlust link"))
8040 (setq folder (match-string 1 path)
8041 article (match-string 3 path))
8042 (org-follow-wl-link folder article)))
8043
8044 ((string= type "mhe")
8045 (let (folder article)
8046 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
8047 (error "Error in MHE link"))
8048 (setq folder (match-string 1 path)
8049 article (match-string 3 path))
8050 (org-follow-mhe-link folder article)))
8051
8052 ((string= type "rmail")
8053 (let (folder article)
8054 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
8055 (error "Error in RMAIL link"))
8056 (setq folder (match-string 1 path)
8057 article (match-string 3 path))
8058 (org-follow-rmail-link folder article)))
8059
8060 ((string= type "shell")
8061 (let ((cmd path))
8062 (while (string-match "@{" cmd)
8063 (setq cmd (replace-match "<" t t cmd)))
8064 (while (string-match "@}" cmd)
8065 (setq cmd (replace-match ">" t t cmd)))
8066 (if (or (not org-confirm-shell-link-function)
8067 (funcall org-confirm-shell-link-function
8068 (format "Execute \"%s\" in shell? "
8069 (org-add-props cmd nil
8070 'face 'org-warning))))
8071 (progn
8072 (message "Executing %s" cmd)
8073 (shell-command cmd))
8074 (error "Abort"))))
8075
8076 ((string= type "elisp")
8077 (let ((cmd path))
8078 (if (or (not org-confirm-elisp-link-function)
8079 (funcall org-confirm-elisp-link-function
8080 (format "Execute \"%s\" as elisp? "
8081 (org-add-props cmd nil
8082 'face 'org-warning))))
8083 (message "%s => %s" cmd (eval (read cmd)))
8084 (error "Abort"))))
8085
8086 (t
8087 (browse-url-at-point))))))
8088
8089 (defun org-link-search (s &optional type)
8090 "Search for a link search option.
8091 When S is a CamelCaseWord, search for a target, or for a sentence containing
8092 the words. If S is surrounded by forward slashes, it is interpreted as a
8093 regular expression. In org-mode files, this will create an `org-occur'
8094 sparse tree. In ordinary files, `occur' will be used to list matches.
8095 If the current buffer is in `dired-mode', grep will be used to search
8096 in all files."
8097 (let ((case-fold-search t)
8098 (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " "))
8099 (pos (point))
8100 (pre "") (post "")
8101 words re0 re1 re2 re3 re4 re5 re2a reall camel)
8102 (cond
8103 ;; First check if there are any special
8104 ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
8105 ;; Now try the builtin stuff
8106 ((save-excursion
8107 (goto-char (point-min))
8108 (and
8109 (re-search-forward
8110 (concat "<<" (regexp-quote s0) ">>") nil t)
8111 (setq pos (match-beginning 0))))
8112 ;; There is an exact target for this
8113 (goto-char pos))
8114 ((string-match "^/\\(.*\\)/$" s)
8115 ;; A regular expression
8116 (cond
8117 ((eq major-mode 'org-mode)
8118 (org-occur (match-string 1 s)))
8119 ;;((eq major-mode 'dired-mode)
8120 ;; (grep (concat "grep -n -e '" (match-string 1 s) "' *")))
8121 (t (org-do-occur (match-string 1 s)))))
8122 ((or (setq camel (string-match (concat "^" org-camel-regexp "$") s))
8123 t)
8124 ;; A camel or a normal search string
8125 (when (equal (string-to-char s) ?*)
8126 ;; Anchor on headlines, post may include tags.
8127 (setq pre "^\\*+[ \t]*\\(?:\\sw+\\)?[ \t]*"
8128 post "[ \t]*\\(?:[ \t]+:[a-zA-Z_@0-9:+]:[ \t]*\\)?$"
8129 s (substring s 1)))
8130 (remove-text-properties
8131 0 (length s)
8132 '(face nil mouse-face nil keymap nil fontified nil) s)
8133 ;; Make a series of regular expressions to find a match
8134 (setq words
8135 (if camel
8136 (org-camel-to-words s)
8137 (org-split-string s "[ \n\r\t]+"))
8138 re0 (concat "\\(<<" (regexp-quote s0) ">>\\)")
8139 re2 (concat "[ \t\r\n]\\(" (mapconcat 'downcase words "[ \t]+") "\\)[ \t\r\n]")
8140 re2a (concat "[ \t\r\n]\\(" (mapconcat 'downcase words "[ \t\r\n]+") "\\)[ \t\r\n]")
8141 re4 (concat "[^a-zA-Z_]\\(" (mapconcat 'downcase words "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
8142 re1 (concat pre re2 post)
8143 re3 (concat pre re4 post)
8144 re5 (concat pre ".*" re4)
8145 re2 (concat pre re2)
8146 re2a (concat pre re2a)
8147 re4 (concat pre re4)
8148 reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2
8149 "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\("
8150 re5 "\\)"
8151 ))
8152 (cond
8153 ((eq type 'org-occur) (org-occur reall))
8154 ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
8155 (t (goto-char (point-min))
8156 (if (or (org-search-not-link re0 nil t)
8157 (org-search-not-link re1 nil t)
8158 (org-search-not-link re2 nil t)
8159 (org-search-not-link re2a nil t)
8160 (org-search-not-link re3 nil t)
8161 (org-search-not-link re4 nil t)
8162 (org-search-not-link re5 nil t)
8163 )
8164 (goto-char (match-beginning 1))
8165 (goto-char pos)
8166 (error "No match")))))
8167 (t
8168 ;; Normal string-search
8169 (goto-char (point-min))
8170 (if (search-forward s nil t)
8171 (goto-char (match-beginning 0))
8172 (error "No match"))))
8173 (and (eq major-mode 'org-mode) (org-show-hierarchy-above))))
8174
8175 (defun org-search-not-link (&rest args)
8176 "Execute `re-search-forward', but only accept matches that are not a link."
8177 (catch 'exit
8178 (let ((pos (point)) p1)
8179 (while (apply 're-search-forward args)
8180 (setq p1 (point))
8181 (if (not (save-match-data
8182 (and (re-search-backward "\\[\\[" nil t)
8183 (looking-at org-bracket-link-regexp)
8184 (<= (match-beginning 0) p1)
8185 (>= (match-end 0) p1))))
8186 (progn (goto-char (match-end 0))
8187 (throw 'exit (point)))
8188 (goto-char (match-end 0)))))))
8189
8190 (defun org-do-occur (regexp &optional cleanup)
8191 "Call the Emacs command `occur'.
8192 If CLEANUP is non-nil, remove the printout of the regular expression
8193 in the *Occur* buffer. This is useful if the regex is long and not useful
8194 to read."
8195 (occur regexp)
8196 (when cleanup
8197 (let ((cwin (selected-window)) win beg end)
8198 (when (setq win (get-buffer-window "*Occur*"))
8199 (select-window win))
8200 (goto-char (point-min))
8201 (when (re-search-forward "match[a-z]+" nil t)
8202 (setq beg (match-end 0))
8203 (if (re-search-forward "^[ \t]*[0-9]+" nil t)
8204 (setq end (1- (match-beginning 0)))))
8205 (and beg end (let ((buffer-read-only)) (delete-region beg end)))
8206 (goto-char (point-min))
8207 (select-window cwin))))
8208
8209 (defvar org-mark-ring nil
8210 "Mark ring for positions before jumps in Org-mode.")
8211 (defvar org-mark-ring-last-goto nil
8212 "Last position in the mark ring used to go back.")
8213 ;; Fill and close the ring
8214 (setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is reloaded
8215 (loop for i from 1 to org-mark-ring-length do
8216 (push (make-marker) org-mark-ring))
8217 (setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring)
8218 org-mark-ring)
8219
8220 (defun org-mark-ring-push (&optional pos buffer)
8221 "Put the current position or POS into the mark ring and rotate it."
8222 (interactive)
8223 (setq pos (or pos (point)))
8224 (setq org-mark-ring (nthcdr (1- org-mark-ring-length) org-mark-ring))
8225 (move-marker (car org-mark-ring)
8226 (or pos (point))
8227 (or buffer (current-buffer)))
8228 (message
8229 (substitute-command-keys
8230 "Position saved to mark ring, go back with \\[org-mark-ring-goto].")))
8231
8232 (defun org-mark-ring-goto (&optional n)
8233 "Jump to the previous position in the mark ring.
8234 With prefix arg N, jump back that many stored positions. When
8235 called several times in succession, walk through the entire ring.
8236 Org-mode commands jumping to a different position in the current file,
8237 or to another Org-mode file, automatically push the old position
8238 onto the ring."
8239 (interactive "p")
8240 (let (p m)
8241 (if (eq last-command this-command)
8242 (setq p (nthcdr n (or org-mark-ring-last-goto org-mark-ring)))
8243 (setq p org-mark-ring))
8244 (setq org-mark-ring-last-goto p)
8245 (setq m (car p))
8246 (switch-to-buffer (marker-buffer m))
8247 (goto-char m)
8248 (if (or (org-invisible-p) (org-invisible-p2)) (org-show-hierarchy-above))))
8249
8250 (defun org-camel-to-words (s)
8251 "Split \"CamelCaseWords\" to (\"Camel\" \"Case\" \"Words\")."
8252 (let ((case-fold-search nil)
8253 words)
8254 (while (string-match "[a-z][A-Z]" s)
8255 (push (substring s 0 (1+ (match-beginning 0))) words)
8256 (setq s (substring s (1+ (match-beginning 0)))))
8257 (nreverse (cons s words))))
8258
8259 (defun org-remove-angle-brackets (s)
8260 (if (equal (substring s 0 1) "<") (setq s (substring s 1)))
8261 (if (equal (substring s -1) ">") (setq s (substring s 0 -1)))
8262 s)
8263 (defun org-add-angle-brackets (s)
8264 (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s)))
8265 (if (equal (substring s -1) ">") nil (setq s (concat s ">")))
8266 s)
8267
8268 (defun org-follow-bbdb-link (name)
8269 "Follow a BBDB link to NAME."
8270 (require 'bbdb)
8271 (let ((inhibit-redisplay t)
8272 (bbdb-electric-p nil))
8273 (catch 'exit
8274 ;; Exact match on name
8275 (bbdb-name (concat "\\`" name "\\'") nil)
8276 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
8277 ;; Exact match on name
8278 (bbdb-company (concat "\\`" name "\\'") nil)
8279 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
8280 ;; Partial match on name
8281 (bbdb-name name nil)
8282 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
8283 ;; Partial match on company
8284 (bbdb-company name nil)
8285 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
8286 ;; General match including network address and notes
8287 (bbdb name nil)
8288 (when (= 0 (buffer-size (get-buffer "*BBDB*")))
8289 (delete-window (get-buffer-window "*BBDB*"))
8290 (error "No matching BBDB record")))))
8291
8292
8293 (defun org-follow-info-link (name)
8294 "Follow an info file & node link to NAME."
8295 (if (or (string-match "\\(.*\\)::?\\(.*\\)" name)
8296 (string-match "\\(.*\\)" name))
8297 (progn
8298 (require 'info)
8299 (if (match-string 2 name) ; If there isn't a node, choose "Top"
8300 (Info-find-node (match-string 1 name) (match-string 2 name))
8301 (Info-find-node (match-string 1 name) "Top")))
8302 (message (concat "Could not open: " name))))
8303
8304 (defun org-follow-gnus-link (&optional group article)
8305 "Follow a Gnus link to GROUP and ARTICLE."
8306 (require 'gnus)
8307 (funcall (cdr (assq 'gnus org-link-frame-setup)))
8308 (if group (gnus-fetch-group group))
8309 (if article
8310 (or (gnus-summary-goto-article article nil 'force)
8311 (if (fboundp 'gnus-summary-insert-cached-articles)
8312 (progn
8313 (gnus-summary-insert-cached-articles)
8314 (gnus-summary-goto-article article nil 'force))
8315 (message "Message could not be found.")))))
8316
8317 (defun org-follow-vm-link (&optional folder article readonly)
8318 "Follow a VM link to FOLDER and ARTICLE."
8319 (require 'vm)
8320 (setq article (org-add-angle-brackets article))
8321 (if (string-match "^//\\([a-zA-Z]+@\\)?\\([^:]+\\):\\(.*\\)" folder)
8322 ;; ange-ftp or efs or tramp access
8323 (let ((user (or (match-string 1 folder) (user-login-name)))
8324 (host (match-string 2 folder))
8325 (file (match-string 3 folder)))
8326 (cond
8327 ((featurep 'tramp)
8328 ;; use tramp to access the file
8329 (if (featurep 'xemacs)
8330 (setq folder (format "[%s@%s]%s" user host file))
8331 (setq folder (format "/%s@%s:%s" user host file))))
8332 (t
8333 ;; use ange-ftp or efs
8334 (require (if (featurep 'xemacs) 'efs 'ange-ftp))
8335 (setq folder (format "/%s@%s:%s" user host file))))))
8336 (when folder
8337 (funcall (cdr (assq 'vm org-link-frame-setup)) folder readonly)
8338 (sit-for 0.1)
8339 (when article
8340 (vm-select-folder-buffer)
8341 (widen)
8342 (let ((case-fold-search t))
8343 (goto-char (point-min))
8344 (if (not (re-search-forward
8345 (concat "^" "message-id: *" (regexp-quote article))))
8346 (error "Could not find the specified message in this folder"))
8347 (vm-isearch-update)
8348 (vm-isearch-narrow)
8349 (vm-beginning-of-message)
8350 (vm-summarize)))))
8351
8352 (defun org-follow-wl-link (folder article)
8353 "Follow a Wanderlust link to FOLDER and ARTICLE."
8354 (setq article (org-add-angle-brackets article))
8355 (wl-summary-goto-folder-subr folder 'no-sync t nil t)
8356 (if article (wl-summary-jump-to-msg-by-message-id article ">"))
8357 (wl-summary-redisplay))
8358
8359 (defun org-follow-rmail-link (folder article)
8360 "Follow an RMAIL link to FOLDER and ARTICLE."
8361 (setq article (org-add-angle-brackets article))
8362 (let (message-number)
8363 (save-excursion
8364 (save-window-excursion
8365 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
8366 (setq message-number
8367 (save-restriction
8368 (widen)
8369 (goto-char (point-max))
8370 (if (re-search-backward
8371 (concat "^Message-ID:\\s-+" (regexp-quote
8372 (or article "")))
8373 nil t)
8374 (rmail-what-message))))))
8375 (if message-number
8376 (progn
8377 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
8378 (rmail-show-message message-number)
8379 message-number)
8380 (error "Message not found"))))
8381
8382 ;; mh-e integration based on planner-mode
8383 (defun org-mhe-get-message-real-folder ()
8384 "Return the name of the current message real folder, so if you use
8385 sequences, it will now work."
8386 (save-excursion
8387 (let* ((folder
8388 (if (equal major-mode 'mh-folder-mode)
8389 mh-current-folder
8390 ;; Refer to the show buffer
8391 mh-show-folder-buffer))
8392 (end-index
8393 (if (boundp 'mh-index-folder)
8394 (min (length mh-index-folder) (length folder))))
8395 )
8396 ;; a simple test on mh-index-data does not work, because
8397 ;; mh-index-data is always nil in a show buffer.
8398 (if (and (boundp 'mh-index-folder)
8399 (string= mh-index-folder (substring folder 0 end-index)))
8400 (if (equal major-mode 'mh-show-mode)
8401 (save-window-excursion
8402 (when (buffer-live-p (get-buffer folder))
8403 (progn
8404 (pop-to-buffer folder)
8405 (org-mhe-get-message-folder-from-index)
8406 )
8407 ))
8408 (org-mhe-get-message-folder-from-index)
8409 )
8410 folder
8411 )
8412 )))
8413
8414 (defun org-mhe-get-message-folder-from-index ()
8415 "Returns the name of the message folder in a index folder buffer."
8416 (save-excursion
8417 (mh-index-previous-folder)
8418 (re-search-forward "^\\(+.*\\)$" nil t)
8419 (message (match-string 1))))
8420
8421 (defun org-mhe-get-message-folder ()
8422 "Return the name of the current message folder. Be careful if you
8423 use sequences."
8424 (save-excursion
8425 (if (equal major-mode 'mh-folder-mode)
8426 mh-current-folder
8427 ;; Refer to the show buffer
8428 mh-show-folder-buffer)))
8429
8430 (defun org-mhe-get-message-num ()
8431 "Return the number of the current message. Be careful if you
8432 use sequences."
8433 (save-excursion
8434 (if (equal major-mode 'mh-folder-mode)
8435 (mh-get-msg-num nil)
8436 ;; Refer to the show buffer
8437 (mh-show-buffer-message-number))))
8438
8439 (defun org-mhe-get-header (header)
8440 "Return a header of the message in folder mode. This will create a
8441 show buffer for the corresponding message. If you have a more clever
8442 idea..."
8443 (let* ((folder (org-mhe-get-message-folder))
8444 (num (org-mhe-get-message-num))
8445 (buffer (get-buffer-create (concat "show-" folder)))
8446 (header-field))
8447 (with-current-buffer buffer
8448 (mh-display-msg num folder)
8449 (if (equal major-mode 'mh-folder-mode)
8450 (mh-header-display)
8451 (mh-show-header-display))
8452 (set-buffer buffer)
8453 (setq header-field (mh-get-header-field header))
8454 (if (equal major-mode 'mh-folder-mode)
8455 (mh-show)
8456 (mh-show-show))
8457 header-field)))
8458
8459 (defun org-follow-mhe-link (folder article)
8460 "Follow an MHE link to FOLDER and ARTICLE.
8461 If ARTICLE is nil FOLDER is shown. If the configuration variable
8462 `org-mhe-search-all-folders' is t and `mh-searcher' is pick,
8463 ARTICLE is searched in all folders. Indexed searches (swish++,
8464 namazu, and others supported by MH-E) will always search in all
8465 folders."
8466 (require 'mh-e)
8467 (require 'mh-search)
8468 (require 'mh-utils)
8469 (mh-find-path)
8470 (if (not article)
8471 (mh-visit-folder (mh-normalize-folder-name folder))
8472 (setq article (org-add-angle-brackets article))
8473 (mh-search-choose)
8474 (if (equal mh-searcher 'pick)
8475 (progn
8476 (mh-search folder (list "--message-id" article))
8477 (when (and org-mhe-search-all-folders
8478 (not (org-mhe-get-message-real-folder)))
8479 (kill-this-buffer)
8480 (mh-search "+" (list "--message-id" article))))
8481 (mh-search "+" article))
8482 (if (org-mhe-get-message-real-folder)
8483 (mh-show-msg 1)
8484 (kill-this-buffer)
8485 (error "Message not found"))))
8486
8487 ;; BibTeX links
8488
8489 ;; Use the custom search meachnism to construct and use search strings for
8490 ;; file links to BibTeX database entries.
8491
8492 (defun org-create-file-search-in-bibtex ()
8493 "Create the search string and description for a BibTeX database entry."
8494 (when (eq major-mode 'bibtex-mode)
8495 ;; yes, we want to construct this search string.
8496 ;; Make a good description for this entry, using names, year and the title
8497 ;; Put it into the `description' variable which is dynamically scoped.
8498 (let ((bibtex-autokey-names 1)
8499 (bibtex-autokey-names-stretch 1)
8500 (bibtex-autokey-name-case-convert-function 'identity)
8501 (bibtex-autokey-name-separator " & ")
8502 (bibtex-autokey-additional-names " et al.")
8503 (bibtex-autokey-year-length 4)
8504 (bibtex-autokey-name-year-separator " ")
8505 (bibtex-autokey-titlewords 3)
8506 (bibtex-autokey-titleword-separator " ")
8507 (bibtex-autokey-titleword-case-convert-function 'identity)
8508 (bibtex-autokey-titleword-length 'infty)
8509 (bibtex-autokey-year-title-separator ": "))
8510 (setq description (bibtex-generate-autokey)))
8511 ;; Now parse the entry, get the key and return it.
8512 (save-excursion
8513 (bibtex-beginning-of-entry)
8514 (cdr (assoc "=key=" (bibtex-parse-entry))))))
8515
8516 (defun org-execute-file-search-in-bibtex (s)
8517 "Find the link search string S as a key for a database entry."
8518 (when (eq major-mode 'bibtex-mode)
8519 ;; Yes, we want to do the search in this file.
8520 ;; We construct a regexp that searches for "@entrytype{" followed by the key
8521 (goto-char (point-min))
8522 (and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*"
8523 (regexp-quote s) "[ \t\n]*,") nil t)
8524 (goto-char (match-beginning 0)))
8525 (if (and (match-beginning 0) (equal current-prefix-arg '(16)))
8526 ;; Use double prefix to indicate that any web link should be browsed
8527 (let ((b (current-buffer)) (p (point)))
8528 ;; Restore the window configuration because we just use the web link
8529 (set-window-configuration org-window-config-before-follow-link)
8530 (save-excursion (set-buffer b) (goto-char p)
8531 (bibtex-url)))
8532 (recenter 0)) ; Move entry start to beginning of window
8533 ;; return t to indicate that the search is done.
8534 t))
8535
8536 ;; Finally add the functions to the right hooks.
8537 (add-hook 'org-create-file-search-functions 'org-create-file-search-in-bibtex)
8538 (add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-bibtex)
8539
8540 ;; end of Bibtex link setup
8541
8542 (defun org-upgrade-old-links (&optional query-description)
8543 "Transfer old <...> style links to new [[...]] style links.
8544 With arg query-description, ask at each match for a description text to use
8545 for this link."
8546 (interactive (list (y-or-n-p "Would you like to be queried for a description at each link?")))
8547 (save-excursion
8548 (goto-char (point-min))
8549 (let ((re (concat "\\([^[]\\)<\\("
8550 "\\(" (mapconcat 'identity org-link-types "\\|")
8551 "\\):"
8552 "[^" org-non-link-chars "]+\\)>"))
8553 l1 l2 (cnt 0))
8554 (while (re-search-forward re nil t)
8555 (setq cnt (1+ cnt)
8556 l1 (org-match-string-no-properties 2)
8557 l2 (save-match-data (org-link-escape l1)))
8558 (when query-description (setq l1 (read-string "Desc: " l1)))
8559 (if (equal l1 l2)
8560 (replace-match (concat (match-string 1) "[[" l1 "]]") t t)
8561 (replace-match (concat (match-string 1) "[[" l2 "][" l1 "]]") t t)))
8562 (message "%d matches have beed treated" cnt))))
8563
8564 (defun org-open-file (path &optional in-emacs line search)
8565 "Open the file at PATH.
8566 First, this expands any special file name abbreviations. Then the
8567 configuration variable `org-file-apps' is checked if it contains an
8568 entry for this file type, and if yes, the corresponding command is launched.
8569 If no application is found, Emacs simply visits the file.
8570 With optional argument IN-EMACS, Emacs will visit the file.
8571 Optional LINE specifies a line to go to, optional SEARCH a string to
8572 search for. If LINE or SEARCH is given, the file will always be
8573 opened in Emacs.
8574 If the file does not exist, an error is thrown."
8575 (setq in-emacs (or in-emacs line search))
8576 (let* ((file (if (equal path "")
8577 buffer-file-name
8578 (convert-standard-filename (org-expand-file-name path))))
8579 (dirp (file-directory-p file))
8580 (dfile (downcase file))
8581 (old-buffer (current-buffer))
8582 (old-pos (point))
8583 (old-mode major-mode)
8584 ext cmd apps)
8585 (if (and (not (file-exists-p file))
8586 (not org-open-non-existing-files))
8587 (error "No such file: %s" file))
8588 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
8589 (setq ext (match-string 1 dfile))
8590 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
8591 (setq ext (match-string 1 dfile))))
8592 (setq apps (append org-file-apps (org-default-apps)))
8593 (if in-emacs
8594 (setq cmd 'emacs)
8595 (setq cmd (or (and dirp (cdr (assoc 'directory apps)))
8596 (cdr (assoc ext apps))
8597 (cdr (assoc t apps)))))
8598 (when (eq cmd 'mailcap)
8599 (require 'mailcap)
8600 (mailcap-parse-mailcaps)
8601 (let* ((mime-type (mailcap-extension-to-mime (or ext "")))
8602 (command (mailcap-mime-info mime-type)))
8603 (if (stringp command)
8604 (setq cmd command)
8605 (setq cmd 'emacs))))
8606 (cond
8607 ((and (stringp cmd) (not (string-match "^\\s-*$" cmd)))
8608 ;; Normalize use of quote, this can vary.
8609 (if (string-match "['\"]%s['\"]" cmd)
8610 (setq cmd (replace-match "'%s'" t t cmd)))
8611 (setq cmd (format cmd file))
8612 (save-window-excursion
8613 (shell-command (concat cmd " &"))))
8614 ((or (stringp cmd)
8615 (eq cmd 'emacs))
8616 (unless (equal (file-truename file) (file-truename (or buffer-file-name "")))
8617 (funcall (cdr (assq 'file org-link-frame-setup)) file))
8618 (if line (goto-line line)
8619 (if search (org-link-search search))))
8620 ((consp cmd)
8621 (eval cmd))
8622 (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
8623 (and (eq major-mode 'org-mode) (eq old-mode 'org-mode)
8624 (or (not (equal old-buffer (current-buffer)))
8625 (not (equal old-pos (point))))
8626 (org-mark-ring-push old-pos old-buffer))))
8627
8628 (defun org-default-apps ()
8629 "Return the default applications for this operating system."
8630 (cond
8631 ((eq system-type 'darwin)
8632 org-file-apps-defaults-macosx)
8633 ((eq system-type 'windows-nt)
8634 org-file-apps-defaults-windowsnt)
8635 (t org-file-apps-defaults-gnu)))
8636
8637 (defun org-expand-file-name (path)
8638 "Replace special path abbreviations and expand the file name."
8639 (expand-file-name path))
8640
8641
8642 (defvar org-insert-link-history nil
8643 "Minibuffer history for links inserted with `org-insert-link'.")
8644
8645 (defvar org-stored-links nil
8646 "Contains the links stored with `org-store-link'.")
8647
8648 ;;;###autoload
8649 (defun org-store-link (arg)
8650 "\\<org-mode-map>Store an org-link to the current location.
8651 This link can later be inserted into an org-buffer with
8652 \\[org-insert-link].
8653 For some link types, a prefix arg is interpreted:
8654 For links to usenet articles, arg negates `org-usenet-links-prefer-google'.
8655 For file links, arg negates `org-context-in-file-links'."
8656 (interactive "P")
8657 (let (link cpltxt desc description search txt (pos (point)))
8658 (cond
8659
8660 ((eq major-mode 'bbdb-mode)
8661 (setq cpltxt (concat
8662 "bbdb:"
8663 (or (bbdb-record-name (bbdb-current-record))
8664 (bbdb-record-company (bbdb-current-record))))
8665 link (org-make-link cpltxt)))
8666
8667 ((eq major-mode 'Info-mode)
8668 (setq link (org-make-link "info:"
8669 (file-name-nondirectory Info-current-file)
8670 ":" Info-current-node))
8671 (setq cpltxt (concat (file-name-nondirectory Info-current-file)
8672 ":" Info-current-node)))
8673
8674 ((eq major-mode 'calendar-mode)
8675 (let ((cd (calendar-cursor-to-date)))
8676 (setq link
8677 (format-time-string
8678 (car org-time-stamp-formats)
8679 (apply 'encode-time
8680 (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
8681 nil nil nil))))))
8682
8683 ((or (eq major-mode 'vm-summary-mode)
8684 (eq major-mode 'vm-presentation-mode))
8685 (and (eq major-mode 'vm-presentation-mode) (vm-summarize))
8686 (vm-follow-summary-cursor)
8687 (save-excursion
8688 (vm-select-folder-buffer)
8689 (let* ((message (car vm-message-pointer))
8690 (folder buffer-file-name)
8691 (subject (vm-su-subject message))
8692 (author (vm-su-full-name message))
8693 (message-id (vm-su-message-id message)))
8694 (setq message-id (org-remove-angle-brackets message-id))
8695 (setq folder (abbreviate-file-name folder))
8696 (if (string-match (concat "^" (regexp-quote vm-folder-directory))
8697 folder)
8698 (setq folder (replace-match "" t t folder)))
8699 (setq cpltxt (concat author " on: " subject))
8700 (setq link (org-make-link "vm:" folder "#" message-id)))))
8701
8702 ((eq major-mode 'wl-summary-mode)
8703 (let* ((msgnum (wl-summary-message-number))
8704 (message-id (elmo-message-field wl-summary-buffer-elmo-folder
8705 msgnum 'message-id))
8706 (wl-message-entity (elmo-msgdb-overview-get-entity
8707 msgnum (wl-summary-buffer-msgdb)))
8708 (author (wl-summary-line-from)) ; FIXME: correct?
8709 (subject "???")) ; FIXME:
8710 (setq message-id (org-remove-angle-brackets message-id))
8711 (setq cpltxt (concat author " on: " subject))
8712 (setq link (org-make-link "wl:" wl-summary-buffer-folder-name
8713 "#" message-id))))
8714
8715 ((or (equal major-mode 'mh-folder-mode)
8716 (equal major-mode 'mh-show-mode))
8717 (let ((from-header (org-mhe-get-header "From:"))
8718 (to-header (org-mhe-get-header "To:"))
8719 (subject (org-mhe-get-header "Subject:")))
8720 (setq cpltxt (concat from-header " on: " subject))
8721 (setq link (org-make-link "mhe:" (org-mhe-get-message-real-folder) "#"
8722 (org-remove-angle-brackets
8723 (org-mhe-get-header "Message-Id:"))))))
8724
8725 ((eq major-mode 'rmail-mode)
8726 (save-excursion
8727 (save-restriction
8728 (rmail-narrow-to-non-pruned-header)
8729 (let ((folder buffer-file-name)
8730 (message-id (mail-fetch-field "message-id"))
8731 (author (mail-fetch-field "from"))
8732 (subject (mail-fetch-field "subject")))
8733 (setq message-id (org-remove-angle-brackets message-id))
8734 (setq cpltxt (concat author " on: " subject))
8735 (setq link (org-make-link "rmail:" folder "#" message-id))))))
8736
8737 ((eq major-mode 'gnus-group-mode)
8738 (let ((group (cond ((fboundp 'gnus-group-group-name) ; depending on Gnus
8739 (gnus-group-group-name)) ; version
8740 ((fboundp 'gnus-group-name)
8741 (gnus-group-name))
8742 (t "???"))))
8743 (setq cpltxt (concat
8744 (if (org-xor arg org-usenet-links-prefer-google)
8745 "http://groups.google.com/groups?group="
8746 "gnus:")
8747 group)
8748 link (org-make-link cpltxt))))
8749
8750 ((memq major-mode '(gnus-summary-mode gnus-article-mode))
8751 (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary))
8752 (gnus-summary-beginning-of-article)
8753 (let* ((group (car gnus-article-current))
8754 (article (cdr gnus-article-current))
8755 (header (gnus-summary-article-header article))
8756 (author (mail-header-from header))
8757 (message-id (mail-header-id header))
8758 (date (mail-header-date header))
8759 (subject (gnus-summary-subject-string)))
8760 (setq cpltxt (concat author " on: " subject))
8761 (if (org-xor arg org-usenet-links-prefer-google)
8762 (setq link
8763 (concat
8764 cpltxt "\n "
8765 (format "http://groups.google.com/groups?as_umsgid=%s"
8766 (org-fixup-message-id-for-http message-id))))
8767 (setq link (org-make-link "gnus:" group
8768 "#" (number-to-string article))))))
8769
8770 ((eq major-mode 'w3-mode)
8771 (setq cpltxt (url-view-url t)
8772 link (org-make-link cpltxt)))
8773 ((eq major-mode 'w3m-mode)
8774 (setq cpltxt w3m-current-url
8775 link (org-make-link cpltxt)))
8776
8777 ((setq search (run-hook-with-args-until-success
8778 'org-create-file-search-functions))
8779 (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
8780 "::" search))
8781 (setq cpltxt (or description link))) ;; FIXME: is this the best way?
8782
8783 ((eq major-mode 'org-mode)
8784 ;; Just link to current headline
8785 (setq cpltxt (concat "file:"
8786 (abbreviate-file-name buffer-file-name)))
8787 ;; Add a context search string
8788 (when (org-xor org-context-in-file-links arg)
8789 ;; Check if we are on a target
8790 (if (save-excursion
8791 (skip-chars-forward "^>\n\r")
8792 (and (re-search-backward "<<" nil t)
8793 (looking-at "<<\\(.*?\\)>>")
8794 (<= (match-beginning 0) pos)
8795 (>= (match-end 0) pos)))
8796 (setq cpltxt (concat cpltxt "::" (match-string 1)))
8797 (setq txt (cond
8798 ((org-on-heading-p) nil)
8799 ((org-region-active-p)
8800 (buffer-substring (region-beginning) (region-end)))
8801 (t (buffer-substring (point-at-bol) (point-at-eol)))))
8802 (when (or (null txt) (string-match "\\S-" txt))
8803 (setq cpltxt
8804 (concat cpltxt "::"
8805 (if org-file-link-context-use-camel-case
8806 (org-make-org-heading-camel txt)
8807 (org-make-org-heading-search-string txt)))
8808 desc "NONE"))))
8809 (if (string-match "::\\'" cpltxt)
8810 (setq cpltxt (substring cpltxt 0 -2)))
8811 (setq link (org-make-link cpltxt)))
8812
8813 (buffer-file-name
8814 ;; Just link to this file here.
8815 (setq cpltxt (concat "file:"
8816 (abbreviate-file-name buffer-file-name)))
8817 ;; Add a context string
8818 (when (org-xor org-context-in-file-links arg)
8819 (setq txt (if (org-region-active-p)
8820 (buffer-substring (region-beginning) (region-end))
8821 (buffer-substring (point-at-bol) (point-at-eol))))
8822 ;; Only use search option if there is some text.
8823 (when (string-match "\\S-" txt)
8824 (setq cpltxt
8825 (concat cpltxt "::"
8826 (if org-file-link-context-use-camel-case
8827 (org-make-org-heading-camel txt)
8828 (org-make-org-heading-search-string txt)))
8829 desc "NONE")))
8830 (setq link (org-make-link cpltxt)))
8831
8832 ((interactive-p)
8833 (error "Cannot link to a buffer which is not visiting a file"))
8834
8835 (t (setq link nil)))
8836
8837 (if (consp link) (setq cpltxt (car link) link (cdr link)))
8838 (setq link (or link cpltxt)
8839 desc (or desc cpltxt))
8840 (if (equal desc "NONE") (setq desc nil))
8841
8842 (if (and (interactive-p) link)
8843 (progn
8844 (setq org-stored-links
8845 (cons (list cpltxt link desc) org-stored-links))
8846 (message "Stored: %s" (or cpltxt link)))
8847 (org-make-link-string link desc))))
8848
8849 (defun org-make-org-heading-search-string (&optional string heading)
8850 "Make search string for STRING or current headline."
8851 (interactive)
8852 (let ((s (or string (org-get-heading))))
8853 (unless (and string (not heading))
8854 ;; We are using a headline, clean up garbage in there.
8855 (if (string-match org-todo-regexp s)
8856 (setq s (replace-match "" t t s)))
8857 (if (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" s)
8858 (setq s (replace-match "" t t s)))
8859 (setq s (org-trim s))
8860 (if (string-match (concat "^\\(" org-quote-string "\\|"
8861 org-comment-string "\\)") s)
8862 (setq s (replace-match "" t t s)))
8863 (while (string-match org-ts-regexp s)
8864 (setq s (replace-match "" t t s))))
8865 (while (string-match "[^a-zA-Z_0-9 \t]+" s)
8866 (setq s (replace-match " " t t s)))
8867 (or string (setq s (concat "*" s))) ; Add * for headlines
8868 (mapconcat 'identity (org-split-string s "[ \t]+") " ")))
8869
8870 (defun org-make-org-heading-camel (&optional string heading)
8871 "Make a CamelCase string for STRING or the current headline."
8872 (interactive)
8873 (let ((s (or string (org-get-heading))))
8874 (unless (and string (not heading))
8875 ;; We are using a headline, clean up garbage in there.
8876 (if (string-match org-todo-regexp s)
8877 (setq s (replace-match "" t t s)))
8878 (if (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" s)
8879 (setq s (replace-match "" t t s)))
8880 (setq s (org-trim s))
8881 (if (string-match (concat "^\\(" org-quote-string "\\|"
8882 org-comment-string "\\)") s)
8883 (setq s (replace-match "" t t s)))
8884 (while (string-match org-ts-regexp s)
8885 (setq s (replace-match "" t t s))))
8886 (while (string-match "[^a-zA-Z_ \t]+" s)
8887 (setq s (replace-match " " t t s)))
8888 (or string (setq s (concat "*" s))) ; Add * for headlines
8889 (mapconcat 'capitalize (org-split-string s "[ \t]+") "")))
8890
8891 (defun org-make-link (&rest strings)
8892 "Concatenate STRINGS, format resulting string with `org-link-format'."
8893 (format org-link-format (apply 'concat strings)))
8894
8895 (defun org-make-link-string (link &optional description)
8896 "Make a link with brackets, consisting of LINK and DESCRIPTION."
8897 (if (eq org-link-style 'plain)
8898 (if (equal description link)
8899 link
8900 (concat description "\n" link))
8901 (when (stringp description)
8902 ;; Remove brackets from the description, they are fatal.
8903 (while (string-match "\\[\\|\\]" description)
8904 (setq description (replace-match "" t t description))))
8905 (when (equal (org-link-escape link) description)
8906 ;; No description needed, it is identical
8907 (setq description nil))
8908 (when (and (not description)
8909 (not (equal link (org-link-escape link))))
8910 (setq description link))
8911 (concat "[[" (org-link-escape link) "]"
8912 (if description (concat "[" description "]") "")
8913 "]")))
8914
8915 (defconst org-link-escape-chars '(("[" . "%5B") ("]" . "%5D") (" " . "%20"))
8916 "Association list of escapes for some characters problematic in links.")
8917
8918 (defun org-link-escape (text)
8919 "Escape charaters in TEXT that are problematic for links."
8920 (when text
8921 (let ((re (mapconcat (lambda (x) (regexp-quote (car x)))
8922 org-link-escape-chars "\\|")))
8923 (while (string-match re text)
8924 (setq text
8925 (replace-match
8926 (cdr (assoc (match-string 0 text) org-link-escape-chars))
8927 t t text)))
8928 text)))
8929
8930 (defun org-link-unescape (text)
8931 "Reverse the action of `org-link-escape'."
8932 (when text
8933 (let ((re (mapconcat (lambda (x) (regexp-quote (cdr x)))
8934 org-link-escape-chars "\\|")))
8935 (while (string-match re text)
8936 (setq text
8937 (replace-match
8938 (car (rassoc (match-string 0 text) org-link-escape-chars))
8939 t t text)))
8940 text)))
8941
8942 (defun org-xor (a b)
8943 "Exclusive or."
8944 (if a (not b) b))
8945
8946 (defun org-get-header (header)
8947 "Find a header field in the current buffer."
8948 (save-excursion
8949 (goto-char (point-min))
8950 (let ((case-fold-search t) s)
8951 (cond
8952 ((eq header 'from)
8953 (if (re-search-forward "^From:\\s-+\\(.*\\)" nil t)
8954 (setq s (match-string 1)))
8955 (while (string-match "\"" s)
8956 (setq s (replace-match "" t t s)))
8957 (if (string-match "[<(].*" s)
8958 (setq s (replace-match "" t t s))))
8959 ((eq header 'message-id)
8960 (if (re-search-forward "^message-id:\\s-+\\(.*\\)" nil t)
8961 (setq s (match-string 1))))
8962 ((eq header 'subject)
8963 (if (re-search-forward "^subject:\\s-+\\(.*\\)" nil t)
8964 (setq s (match-string 1)))))
8965 (if (string-match "\\`[ \t\]+" s) (setq s (replace-match "" t t s)))
8966 (if (string-match "[ \t\]+\\'" s) (setq s (replace-match "" t t s)))
8967 s)))
8968
8969
8970 (defun org-fixup-message-id-for-http (s)
8971 "Replace special characters in a message id, so it can be used in an http query."
8972 (while (string-match "<" s)
8973 (setq s (replace-match "%3C" t t s)))
8974 (while (string-match ">" s)
8975 (setq s (replace-match "%3E" t t s)))
8976 (while (string-match "@" s)
8977 (setq s (replace-match "%40" t t s)))
8978 s)
8979
8980 (defun org-insert-link (&optional complete-file)
8981 "Insert a link. At the prompt, enter the link.
8982
8983 Completion can be used to select a link previously stored with
8984 `org-store-link'. When the empty string is entered (i.e. if you just
8985 press RET at the prompt), the link defaults to the most recently
8986 stored link. As SPC triggers completion in the minibuffer, you need to
8987 use M-SPC or C-q SPC to force the insertion of a space character.
8988
8989 You will also be prompted for a description, and if one is given, it will
8990 be displayed in the buffer instead of the link.
8991
8992 If there is already a link at point, this command will allow you to edit link
8993 and description parts.
8994
8995 With a \\[universal-argument] prefix, prompts for a file to link to. The file name can be
8996 selected using completion. The path to the file will be relative to
8997 the current directory if the file is in the current directory or a
8998 subdirectory. Otherwise, the link will be the absolute path as
8999 completed in the minibuffer (i.e. normally ~/path/to/file).
9000
9001 With two \\[universal-argument] prefixes, enforce an absolute path even if the file
9002 is in the current directory or below."
9003 (interactive "P")
9004 (let (link desc entry remove file (pos (point)))
9005 (cond
9006 ((save-excursion
9007 (skip-chars-forward "^]\n\r")
9008 (and (re-search-backward "\\[\\[" nil t)
9009 (looking-at org-bracket-link-regexp)
9010 (<= (match-beginning 0) pos)
9011 (>= (match-end 0) pos)))
9012 ;; We do have a link at point, and we are going to edit it.
9013 (setq remove (list (match-beginning 0) (match-end 0)))
9014 (setq desc (if (match-end 3) (org-match-string-no-properties 3)))
9015 (setq link (read-string "Link: "
9016 (org-link-unescape
9017 (org-match-string-no-properties 1)))))
9018 (complete-file
9019 ;; Completing read for file names.
9020 (setq file (read-file-name "File: "))
9021 (let ((pwd (file-name-as-directory (expand-file-name ".")))
9022 (pwd1 (file-name-as-directory (abbreviate-file-name
9023 (expand-file-name ".")))))
9024 (cond
9025 ((equal complete-file '(16))
9026 (setq link (org-make-link
9027 "file:"
9028 (abbreviate-file-name (expand-file-name file)))))
9029 ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
9030 (setq link (org-make-link "file:" (match-string 1 file))))
9031 ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
9032 (expand-file-name file))
9033 (setq link (org-make-link
9034 "file:" (match-string 1 (expand-file-name file)))))
9035 (t (setq link (org-make-link "file:" file))))))
9036 (t
9037 ;; Read link, with completion for stored links.
9038 (setq link (org-completing-read
9039 "Link: " org-stored-links nil nil nil
9040 org-insert-link-history
9041 (or (car (car org-stored-links)))))
9042 (setq entry (assoc link org-stored-links))
9043 (if (not org-keep-stored-link-after-insertion)
9044 (setq org-stored-links (delq (assoc link org-stored-links)
9045 org-stored-links)))
9046 (setq link (if entry (nth 1 entry) link)
9047 desc (or desc (nth 2 entry)))))
9048
9049 (if (string-match org-plain-link-re link)
9050 ;; URL-like link, normalize the use of angular brackets.
9051 (setq link (org-make-link (org-remove-angle-brackets link))))
9052
9053 ;; Check if we are linking to the current file with a search option
9054 ;; If yes, simplify the link by using only the search option.
9055 (when (string-match "\\<file:\\(.+?\\)::\\([^>]+\\)" link)
9056 (let* ((path (match-string 1 link))
9057 (case-fold-search nil)
9058 (search (match-string 2 link)))
9059 (save-match-data
9060 (if (equal (file-truename buffer-file-name) (file-truename path))
9061 ;; We are linking to this same file, with a search option
9062 (setq link search)))))
9063
9064 ;; Check if we can/should use a relative path. If yes, simplify the link
9065 (when (string-match "\\<file:\\(.*\\)" link)
9066 (let* ((path (match-string 1 link))
9067 (case-fold-search nil))
9068 (cond
9069 ((eq org-link-file-path-type 'absolute)
9070 (setq path (abbreviate-file-name (expand-file-name path))))
9071 ((eq org-link-file-path-type 'noabbrev)
9072 (setq path (expand-file-name path)))
9073 ((eq org-link-file-path-type 'relative)
9074 (setq path (file-relative-name path)))
9075 (t
9076 (save-match-data
9077 (if (string-match (concat "^" (regexp-quote
9078 (file-name-as-directory
9079 (expand-file-name "."))))
9080 (expand-file-name path))
9081 ;; We are linking a file with relative path name.
9082 (setq path (substring (expand-file-name path)
9083 (match-end 0)))))))
9084 (setq link (concat "file:" path))))
9085
9086 (setq desc (read-string "Description: " desc))
9087 (unless (string-match "\\S-" desc) (setq desc nil))
9088 (if remove (apply 'delete-region remove))
9089 (insert (org-make-link-string link desc))))
9090
9091 (defun org-completing-read (&rest args)
9092 (let ((minibuffer-local-completion-map
9093 (copy-keymap minibuffer-local-completion-map)))
9094 (define-key minibuffer-local-completion-map " " 'self-insert-command)
9095 (apply 'completing-read args)))
9096
9097 ;;; Hooks for remember.el
9098
9099 (defvar org-finish-function nil)
9100
9101 ;;;###autoload
9102 (defun org-remember-annotation ()
9103 "Return a link to the current location as an annotation for remember.el.
9104 If you are using Org-mode files as target for data storage with
9105 remember.el, then the annotations should include a link compatible with the
9106 conventions in Org-mode. This function returns such a link."
9107 (org-store-link nil))
9108
9109 (defconst org-remember-help
9110 "Select a destination location for the note.
9111 UP/DOWN=headline TAB=cycle visibility [Q]uit RET/<left>/<right>=Store
9112 RET at beg-of-buf -> Append to file as level 2 headline
9113 RET on headline -> Store as sublevel entry to current headline
9114 <left>/<right> -> before/after current headline, same headings level")
9115
9116 ;;;###autoload
9117 (defun org-remember-apply-template ()
9118 "Initialize *remember* buffer with template, invoke `org-mode'.
9119 This function should be placed into `remember-mode-hook' and in fact requires
9120 to be run from that hook to fucntion properly."
9121 (if org-remember-templates
9122
9123 (let* ((entry (if (= (length org-remember-templates) 1)
9124 (cdar org-remember-templates)
9125 (message "Select template: %s"
9126 (mapconcat
9127 (lambda (x) (char-to-string (car x)))
9128 org-remember-templates " "))
9129 (cdr (assoc (read-char-exclusive) org-remember-templates))))
9130 (tpl (car entry))
9131 (file (if (consp (cdr entry)) (nth 1 entry)))
9132 (v-t (format-time-string (car org-time-stamp-formats) (org-current-time)))
9133 (v-T (format-time-string (cdr org-time-stamp-formats) (org-current-time)))
9134 (v-u (concat "[" (substring v-t 1 -1) "]"))
9135 (v-U (concat "[" (substring v-T 1 -1) "]"))
9136 (v-a annotation) ; defined in `remember-mode'
9137 (v-i initial) ; defined in `remember-mode'
9138 (v-n user-full-name)
9139 )
9140 (unless tpl (setq tpl "") (message "No template") (ding))
9141 (insert tpl) (goto-char (point-min))
9142 (while (re-search-forward "%\\([tTuTai]\\)" nil t)
9143 (when (and initial (equal (match-string 0) "%i"))
9144 (save-match-data
9145 (let* ((lead (buffer-substring
9146 (point-at-bol) (match-beginning 0))))
9147 (setq v-i (mapconcat 'identity
9148 (org-split-string initial "\n")
9149 (concat "\n" lead))))))
9150 (replace-match
9151 (or (eval (intern (concat "v-" (match-string 1)))) "")
9152 t t))
9153 (let ((org-startup-folded nil)
9154 (org-startup-with-deadline-check nil))
9155 (org-mode))
9156 (if (and file (string-match "\\S-" file) (not (file-directory-p file)))
9157 (set (make-local-variable 'org-default-notes-file) file))
9158 (goto-char (point-min))
9159 (if (re-search-forward "%\\?" nil t) (replace-match "")))
9160 (let ((org-startup-folded nil)
9161 (org-startup-with-deadline-check nil))
9162 (org-mode)))
9163 (set (make-local-variable 'org-finish-function) 'remember-buffer))
9164
9165 ;;;###autoload
9166 (defun org-remember-handler ()
9167 "Store stuff from remember.el into an org file.
9168 First prompts for an org file. If the user just presses return, the value
9169 of `org-default-notes-file' is used.
9170 Then the command offers the headings tree of the selected file in order to
9171 file the text at a specific location.
9172 You can either immediately press RET to get the note appended to the
9173 file, or you can use vertical cursor motion and visibility cycling (TAB) to
9174 find a better place. Then press RET or <left> or <right> in insert the note.
9175
9176 Key Cursor position Note gets inserted
9177 -----------------------------------------------------------------------------
9178 RET buffer-start as level 2 heading at end of file
9179 RET on headline as sublevel of the heading at cursor
9180 RET no heading at cursor position, level taken from context.
9181 Or use prefix arg to specify level manually.
9182 <left> on headline as same level, before current heading
9183 <right> on headline as same level, after current heading
9184
9185 So the fastest way to store the note is to press RET RET to append it to
9186 the default file. This way your current train of thought is not
9187 interrupted, in accordance with the principles of remember.el. But with
9188 little extra effort, you can push it directly to the correct location.
9189
9190 Before being stored away, the function ensures that the text has a
9191 headline, i.e. a first line that starts with a \"*\". If not, a headline
9192 is constructed from the current date and some additional data.
9193
9194 If the variable `org-adapt-indentation' is non-nil, the entire text is
9195 also indented so that it starts in the same column as the headline
9196 \(i.e. after the stars).
9197
9198 See also the variable `org-reverse-note-order'."
9199 (catch 'quit
9200 (let* ((txt (buffer-substring (point-min) (point-max)))
9201 (fastp current-prefix-arg)
9202 (file (if fastp org-default-notes-file (org-get-org-file)))
9203 (visiting (find-buffer-visiting file))
9204 (org-startup-with-deadline-check nil)
9205 (org-startup-folded nil)
9206 (org-startup-align-all-tables nil)
9207 spos level indent reversed)
9208 ;; Modify text so that it becomes a nice subtree which can be inserted
9209 ;; into an org tree.
9210 (let* ((lines (split-string txt "\n"))
9211 first)
9212 ;; remove empty lines at the beginning
9213 (while (and lines (string-match "^[ \t]*\n" (car lines)))
9214 (setq lines (cdr lines)))
9215 (setq first (car lines) lines (cdr lines))
9216 (if (string-match "^\\*+" first)
9217 ;; Is already a headline
9218 (setq indent nil)
9219 ;; We need to add a headline: Use time and first buffer line
9220 (setq lines (cons first lines)
9221 first (concat "* " (current-time-string)
9222 " (" (remember-buffer-desc) ")")
9223 indent " "))
9224 (if (and org-adapt-indentation indent)
9225 (setq lines (mapcar (lambda (x) (concat indent x)) lines)))
9226 (setq txt (concat first "\n"
9227 (mapconcat 'identity lines "\n"))))
9228 ;; Find the file
9229 (if (not visiting)
9230 (find-file-noselect file))
9231 (with-current-buffer (get-file-buffer file)
9232 (save-excursion (and (goto-char (point-min))
9233 (not (re-search-forward "^\\* " nil t))
9234 (insert "\n* Notes\n")))
9235 (setq reversed (org-notes-order-reversed-p))
9236 (save-excursion
9237 (save-restriction
9238 (widen)
9239 ;; Ask the User for a location
9240 (setq spos (if fastp 1 (org-get-location
9241 (current-buffer)
9242 org-remember-help)))
9243 (if (not spos) (throw 'quit nil)) ; return nil to show we did
9244 ; not handle this note
9245 (goto-char spos)
9246 (cond ((bobp)
9247 ;; Put it at the start or end, as level 2
9248 (save-restriction
9249 (widen)
9250 (goto-char (if reversed (point-min) (point-max)))
9251 (if (not (bolp)) (newline))
9252 (org-paste-subtree 2 txt)))
9253 ((and (org-on-heading-p nil) (not current-prefix-arg))
9254 ;; Put it below this entry, at the beg/end of the subtree
9255 (org-back-to-heading)
9256 (setq level (funcall outline-level))
9257 (if reversed
9258 (outline-end-of-heading)
9259 (outline-end-of-subtree))
9260 (if (not (bolp)) (newline))
9261 (beginning-of-line 1)
9262 (org-paste-subtree (1+ level) txt))
9263 (t
9264 ;; Put it right there, with automatic level determined by
9265 ;; org-paste-subtree or from prefix arg
9266 (org-paste-subtree current-prefix-arg txt)))
9267 (when remember-save-after-remembering
9268 (save-buffer)
9269 (if (not visiting) (kill-buffer (current-buffer)))))))))
9270 t) ;; return t to indicate that we took care of this note.
9271
9272 (defun org-get-org-file ()
9273 "Read a filename, with default directory `org-directory'."
9274 (let ((default (or org-default-notes-file remember-data-file)))
9275 (read-file-name (format "File name [%s]: " default)
9276 (file-name-as-directory org-directory)
9277 default)))
9278
9279 (defun org-notes-order-reversed-p ()
9280 "Check if the current file should receive notes in reversed order."
9281 (cond
9282 ((not org-reverse-note-order) nil)
9283 ((eq t org-reverse-note-order) t)
9284 ((not (listp org-reverse-note-order)) nil)
9285 (t (catch 'exit
9286 (let ((all org-reverse-note-order)
9287 entry)
9288 (while (setq entry (pop all))
9289 (if (string-match (car entry) buffer-file-name)
9290 (throw 'exit (cdr entry))))
9291 nil)))))
9292
9293 ;;; Tables
9294
9295 ;; Watch out: Here we are talking about two different kind of tables.
9296 ;; Most of the code is for the tables created with the Org-mode table editor.
9297 ;; Sometimes, we talk about tables created and edited with the table.el
9298 ;; Emacs package. We call the former org-type tables, and the latter
9299 ;; table.el-type tables.
9300
9301
9302 (defun org-before-change-function (beg end)
9303 "Every change indicates that a table might need an update."
9304 (setq org-table-may-need-update t))
9305
9306 (defconst org-table-line-regexp "^[ \t]*|"
9307 "Detects an org-type table line.")
9308 (defconst org-table-dataline-regexp "^[ \t]*|[^-]"
9309 "Detects an org-type table line.")
9310 (defconst org-table-auto-recalculate-regexp "^[ \t]*| *# *\\(|\\|$\\)"
9311 "Detects a table line marked for automatic recalculation.")
9312 (defconst org-table-recalculate-regexp "^[ \t]*| *[#*] *\\(|\\|$\\)"
9313 "Detects a table line marked for automatic recalculation.")
9314 (defconst org-table-calculate-mark-regexp "^[ \t]*| *[!$^_#*] *\\(|\\|$\\)"
9315 "Detects a table line marked for automatic recalculation.")
9316 (defconst org-table-hline-regexp "^[ \t]*|-"
9317 "Detects an org-type table hline.")
9318 (defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]"
9319 "Detects a table-type table hline.")
9320 (defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)"
9321 "Detects an org-type or table-type table.")
9322 (defconst org-table-border-regexp "^[ \t]*[^| \t]"
9323 "Searching from within a table (any type) this finds the first line
9324 outside the table.")
9325 (defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]"
9326 "Searching from within a table (any type) this finds the first line
9327 outside the table.")
9328
9329 (defun org-table-create-with-table.el ()
9330 "Use the table.el package to insert a new table.
9331 If there is already a table at point, convert between Org-mode tables
9332 and table.el tables."
9333 (interactive)
9334 (require 'table)
9335 (cond
9336 ((org-at-table.el-p)
9337 (if (y-or-n-p "Convert table to Org-mode table? ")
9338 (org-table-convert)))
9339 ((org-at-table-p)
9340 (if (y-or-n-p "Convert table to table.el table? ")
9341 (org-table-convert)))
9342 (t (call-interactively 'table-insert))))
9343
9344 (defun org-table-create-or-convert-from-region (arg)
9345 "Convert region to table, or create an empty table.
9346 If there is an active region, convert it to a table. If there is no such
9347 region, create an empty table."
9348 (interactive "P")
9349 (if (org-region-active-p)
9350 (org-table-convert-region (region-beginning) (region-end) arg)
9351 (org-table-create arg)))
9352
9353 (defun org-table-create (&optional size)
9354 "Query for a size and insert a table skeleton.
9355 SIZE is a string Columns x Rows like for example \"3x2\"."
9356 (interactive "P")
9357 (unless size
9358 (setq size (read-string
9359 (concat "Table size Columns x Rows [e.g. "
9360 org-table-default-size "]: ")
9361 "" nil org-table-default-size)))
9362
9363 (let* ((pos (point))
9364 (indent (make-string (current-column) ?\ ))
9365 (split (org-split-string size " *x *"))
9366 (rows (string-to-number (nth 1 split)))
9367 (columns (string-to-number (car split)))
9368 (line (concat (apply 'concat indent "|" (make-list columns " |"))
9369 "\n")))
9370 (if (string-match "^[ \t]*$" (buffer-substring-no-properties
9371 (point-at-bol) (point)))
9372 (beginning-of-line 1)
9373 (newline))
9374 ;; (mapcar (lambda (x) (insert line)) (make-list rows t))
9375 (dotimes (i rows) (insert line))
9376 (goto-char pos)
9377 (if (> rows 1)
9378 ;; Insert a hline after the first row.
9379 (progn
9380 (end-of-line 1)
9381 (insert "\n|-")
9382 (goto-char pos)))
9383 (org-table-align)))
9384
9385 (defun org-table-convert-region (beg0 end0 &optional nspace)
9386 "Convert region to a table.
9387 The region goes from BEG0 to END0, but these borders will be moved
9388 slightly, to make sure a beginning of line in the first line is included.
9389 When NSPACE is non-nil, it indicates the minimum number of spaces that
9390 separate columns (default: just one space)."
9391 (interactive "rP")
9392 (let* ((beg (min beg0 end0))
9393 (end (max beg0 end0))
9394 (tabsep t)
9395 re)
9396 (goto-char beg)
9397 (beginning-of-line 1)
9398 (setq beg (move-marker (make-marker) (point)))
9399 (goto-char end)
9400 (if (bolp) (backward-char 1) (end-of-line 1))
9401 (setq end (move-marker (make-marker) (point)))
9402 ;; Lets see if this is tab-separated material. If every nonempty line
9403 ;; contains a tab, we will assume that it is tab-separated material
9404 (if nspace
9405 (setq tabsep nil)
9406 (goto-char beg)
9407 (and (re-search-forward "^[^\n\t]+$" end t) (setq tabsep nil)))
9408 (if nspace (setq tabsep nil))
9409 (if tabsep
9410 (setq re "^\\|\t")
9411 (setq re (format "^ *\\| *\t *\\| \\{%d,\\}"
9412 (max 1 (prefix-numeric-value nspace)))))
9413 (goto-char beg)
9414 (while (re-search-forward re end t)
9415 (replace-match "|" t t))
9416 (goto-char beg)
9417 (insert " ")
9418 (org-table-align)))
9419
9420 (defun org-table-import (file arg)
9421 "Import FILE as a table.
9422 The file is assumed to be tab-separated. Such files can be produced by most
9423 spreadsheet and database applications. If no tabs (at least one per line)
9424 are found, lines will be split on whitespace into fields."
9425 (interactive "f\nP")
9426 (or (bolp) (newline))
9427 (let ((beg (point))
9428 (pm (point-max)))
9429 (insert-file-contents file)
9430 (org-table-convert-region beg (+ (point) (- (point-max) pm)) arg)))
9431
9432 (defun org-table-export ()
9433 "Export table as a tab-separated file.
9434 Such a file can be imported into a spreadsheet program like Excel."
9435 (interactive)
9436 (let* ((beg (org-table-begin))
9437 (end (org-table-end))
9438 (table (buffer-substring beg end))
9439 (file (read-file-name "Export table to: "))
9440 buf)
9441 (unless (or (not (file-exists-p file))
9442 (y-or-n-p (format "Overwrite file %s? " file)))
9443 (error "Abort"))
9444 (with-current-buffer (find-file-noselect file)
9445 (setq buf (current-buffer))
9446 (erase-buffer)
9447 (fundamental-mode)
9448 (insert table)
9449 (goto-char (point-min))
9450 (while (re-search-forward "^[ \t]*|[ \t]*" nil t)
9451 (replace-match "" t t)
9452 (end-of-line 1))
9453 (goto-char (point-min))
9454 (while (re-search-forward "[ \t]*|[ \t]*$" nil t)
9455 (replace-match "" t t)
9456 (goto-char (min (1+ (point)) (point-max))))
9457 (goto-char (point-min))
9458 (while (re-search-forward "^-[-+]*$" nil t)
9459 (replace-match "")
9460 (if (looking-at "\n")
9461 (delete-char 1)))
9462 (goto-char (point-min))
9463 (while (re-search-forward "[ \t]*|[ \t]*" nil t)
9464 (replace-match "\t" t t))
9465 (save-buffer))
9466 (kill-buffer buf)))
9467
9468 (defvar org-table-aligned-begin-marker (make-marker)
9469 "Marker at the beginning of the table last aligned.
9470 Used to check if cursor still is in that table, to minimize realignment.")
9471 (defvar org-table-aligned-end-marker (make-marker)
9472 "Marker at the end of the table last aligned.
9473 Used to check if cursor still is in that table, to minimize realignment.")
9474 (defvar org-table-last-alignment nil
9475 "List of flags for flushright alignment, from the last re-alignment.
9476 This is being used to correctly align a single field after TAB or RET.")
9477 (defvar org-table-last-column-widths nil
9478 "List of max width of fields in each column.
9479 This is being used to correctly align a single field after TAB or RET.")
9480
9481 (defvar org-last-recalc-line nil)
9482 (defconst org-narrow-column-arrow "=>"
9483 "Used as display property in narrowed table columns.")
9484
9485 (defun org-table-align ()
9486 "Align the table at point by aligning all vertical bars."
9487 (interactive)
9488 (let* (
9489 ;; Limits of table
9490 (beg (org-table-begin))
9491 (end (org-table-end))
9492 ;; Current cursor position
9493 (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
9494 (colpos (org-table-current-column))
9495 (winstart (window-start))
9496 text lines (new "") lengths l typenums ty fields maxfields i
9497 column
9498 (indent "") cnt frac
9499 rfmt hfmt
9500 (spaces '(1 . 1))
9501 (sp1 (car spaces))
9502 (sp2 (cdr spaces))
9503 (rfmt1 (concat
9504 (make-string sp2 ?\ ) "%%%s%ds" (make-string sp1 ?\ ) "|"))
9505 (hfmt1 (concat
9506 (make-string sp2 ?-) "%s" (make-string sp1 ?-) "+"))
9507 emptystrings xx links narrow fmax fmin f1 len c e)
9508 (untabify beg end)
9509 (remove-text-properties beg end '(org-cwidth t display t))
9510 ;; Check if we have links
9511 (goto-char beg)
9512 (setq links (re-search-forward org-bracket-link-regexp end t))
9513 ;; Make sure the link properties are right FIXME: Can this be optimized????
9514 (when links (goto-char beg) (while (org-activate-bracket-links end)))
9515 ;; Check if we are narrowing any columns
9516 (goto-char beg)
9517 (setq narrow (and org-format-transports-properties-p
9518 (re-search-forward "<[0-9]+>" end t)))
9519 ;; Get the rows
9520 (setq lines (org-split-string
9521 (buffer-substring beg end) "\n"))
9522 ;; Store the indentation of the first line
9523 (if (string-match "^ *" (car lines))
9524 (setq indent (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
9525 ;; Mark the hlines by setting the corresponding element to nil
9526 ;; At the same time, we remove trailing space.
9527 (setq lines (mapcar (lambda (l)
9528 (if (string-match "^ *|-" l)
9529 nil
9530 (if (string-match "[ \t]+$" l)
9531 (substring l 0 (match-beginning 0))
9532 l)))
9533 lines))
9534 ;; Get the data fields by splitting the lines.
9535 (setq fields (mapcar
9536 (lambda (l)
9537 (org-split-string l " *| *"))
9538 (delq nil (copy-sequence lines))))
9539 ;; How many fields in the longest line?
9540 (condition-case nil
9541 (setq maxfields (apply 'max (mapcar 'length fields)))
9542 (error
9543 (kill-region beg end)
9544 (org-table-create org-table-default-size)
9545 (error "Empty table - created default table")))
9546 ;; A list of empty string to fill any short rows on output
9547 (setq emptystrings (make-list maxfields ""))
9548 ;; Check for special formatting.
9549 (setq i -1)
9550 (while (< (setq i (1+ i)) maxfields) ;; Loop over all columns
9551 (setq column (mapcar (lambda (x) (or (nth i x) "")) fields))
9552 ;; Check if there is an explicit width specified
9553 (when (and org-table-limit-column-width narrow)
9554 (setq c column fmax nil)
9555 (while c
9556 (setq e (pop c))
9557 (if (and (stringp e) (string-match "^<\\([0-9]+\\)>$" e))
9558 (setq fmax (string-to-number (match-string 1 e)) c nil)))
9559 ;; Find fields that are wider than fmax, and shorten them
9560 (when fmax
9561 (loop for xx in column do
9562 (when (and (stringp xx)
9563 (> (org-string-width xx) fmax))
9564 (org-add-props xx nil
9565 'help-echo
9566 (concat "Clipped table field, use C-c ` to edit. Full value is:\n" (org-no-properties (copy-sequence xx))))
9567 (setq f1 (min fmax (or (string-match org-bracket-link-regexp xx) fmax)))
9568 (unless (> f1 1)
9569 (error "Cannot narrow field starting with wide link \"%s\""
9570 (match-string 0 xx)))
9571 (add-text-properties f1 (length xx) (list 'org-cwidth t) xx)
9572 (add-text-properties (- f1 2) f1
9573 (list 'display org-narrow-column-arrow)
9574 xx)))))
9575 ;; Get the maximum width for each column
9576 (push (apply 'max 1 (mapcar 'org-string-width column)) lengths)
9577 ;; Get the fraction of numbers, to decide about alignment of the column
9578 (setq cnt 0 frac 0.0)
9579 (loop for x in column do
9580 (if (equal x "")
9581 nil
9582 (setq frac ( / (+ (* frac cnt)
9583 (if (string-match org-table-number-regexp x) 1 0))
9584 (setq cnt (1+ cnt))))))
9585 (push (>= frac org-table-number-fraction) typenums))
9586 (setq lengths (nreverse lengths) typenums (nreverse typenums))
9587
9588 ;; Store the alignment of this table, for later editing of single fields
9589 (setq org-table-last-alignment typenums
9590 org-table-last-column-widths lengths)
9591
9592 ;; With invisible characters, `format' does not get the field width right
9593 ;; So we need to make these fields wide by hand.
9594 (when links
9595 (loop for i from 0 upto (1- maxfields) do
9596 (setq len (nth i lengths))
9597 (loop for j from 0 upto (1- (length fields)) do
9598 (setq c (nthcdr i (car (nthcdr j fields))))
9599 (if (and (stringp (car c))
9600 (string-match org-bracket-link-regexp (car c))
9601 (< (org-string-width (car c)) len))
9602 (setcar c (concat (car c) (make-string (- len (org-string-width (car c))) ?\ )))))))
9603
9604 ;; Compute the formats needed for output of the table
9605 (setq rfmt (concat indent "|") hfmt (concat indent "|"))
9606 (while (setq l (pop lengths))
9607 (setq ty (if (pop typenums) "" "-")) ; number types flushright
9608 (setq rfmt (concat rfmt (format rfmt1 ty l))
9609 hfmt (concat hfmt (format hfmt1 (make-string l ?-)))))
9610 (setq rfmt (concat rfmt "\n")
9611 hfmt (concat (substring hfmt 0 -1) "|\n"))
9612
9613 (setq new (mapconcat
9614 (lambda (l)
9615 (if l (apply 'format rfmt
9616 (append (pop fields) emptystrings))
9617 hfmt))
9618 lines ""))
9619 ;; Replace the old one
9620 (delete-region beg end)
9621 (move-marker end nil)
9622 (move-marker org-table-aligned-begin-marker (point))
9623 (insert new)
9624 (move-marker org-table-aligned-end-marker (point))
9625 (when (and orgtbl-mode (not (eq major-mode 'org-mode)))
9626 (goto-char org-table-aligned-begin-marker)
9627 (while (org-hide-wide-columns org-table-aligned-end-marker)))
9628 ;; Try to move to the old location (approximately)
9629 (goto-line linepos)
9630 (set-window-start (selected-window) winstart 'noforce)
9631 (org-table-goto-column colpos)
9632 (setq org-table-may-need-update nil)
9633 ))
9634
9635 (defun org-string-width (s)
9636 "Compute width of string, ignoring invisible characters.
9637 This ignores character with invisibility property `org-link', and also
9638 characters with property `org-cwidth', because these will become invisible
9639 upon the next fontification round."
9640 (let (b)
9641 (when (or (eq t buffer-invisibility-spec)
9642 (assq 'org-link buffer-invisibility-spec))
9643 (while (setq b (text-property-any 0 (length s)
9644 'invisible 'org-link s))
9645 (setq s (concat (substring s 0 b)
9646 (substring s (or (next-single-property-change
9647 b 'invisible s) (length s)))))))
9648 (while (setq b (text-property-any 0 (length s) 'org-cwidth t s))
9649 (setq s (concat (substring s 0 b)
9650 (substring s (or (next-single-property-change
9651 b 'org-cwidth s) (length s))))))
9652 (string-width s)))
9653
9654 (defun org-table-begin (&optional table-type)
9655 "Find the beginning of the table and return its position.
9656 With argument TABLE-TYPE, go to the beginning of a table.el-type table."
9657 (save-excursion
9658 (if (not (re-search-backward
9659 (if table-type org-table-any-border-regexp
9660 org-table-border-regexp)
9661 nil t))
9662 (progn (goto-char (point-min)) (point))
9663 (goto-char (match-beginning 0))
9664 (beginning-of-line 2)
9665 (point))))
9666
9667 (defun org-table-end (&optional table-type)
9668 "Find the end of the table and return its position.
9669 With argument TABLE-TYPE, go to the end of a table.el-type table."
9670 (save-excursion
9671 (if (not (re-search-forward
9672 (if table-type org-table-any-border-regexp
9673 org-table-border-regexp)
9674 nil t))
9675 (goto-char (point-max))
9676 (goto-char (match-beginning 0)))
9677 (point-marker)))
9678
9679 (defun org-table-justify-field-maybe (&optional new)
9680 "Justify the current field, text to left, number to right.
9681 Optional argument NEW may specify text to replace the current field content."
9682 (cond
9683 ((and (not new) org-table-may-need-update)) ; Realignment will happen anyway
9684 ((org-at-table-hline-p))
9685 ((and (not new)
9686 (or (not (equal (marker-buffer org-table-aligned-begin-marker)
9687 (current-buffer)))
9688 (< (point) org-table-aligned-begin-marker)
9689 (>= (point) org-table-aligned-end-marker)))
9690 ;; This is not the same table, force a full re-align
9691 (setq org-table-may-need-update t))
9692 (t ;; realign the current field, based on previous full realign
9693 (let* ((pos (point)) s
9694 (col (org-table-current-column))
9695 (num (if (> col 0) (nth (1- col) org-table-last-alignment)))
9696 l f n o e)
9697 (when (> col 0)
9698 (skip-chars-backward "^|\n")
9699 (if (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)")
9700 (progn
9701 (setq s (match-string 1)
9702 o (match-string 0)
9703 l (max 1 (- (match-end 0) (match-beginning 0) 3))
9704 e (not (= (match-beginning 2) (match-end 2))))
9705 (setq f (format (if num " %%%ds %s" " %%-%ds %s")
9706 l (if e "|" (setq org-table-may-need-update t) ""))
9707 n (format f s))
9708 (if new
9709 (if (<= (length new) l) ;; FIXME: length -> str-width?
9710 (setq n (format f new))
9711 (setq n (concat new "|") org-table-may-need-update t)))
9712 (or (equal n o)
9713 (let (org-table-may-need-update)
9714 (replace-match n))))
9715 (setq org-table-may-need-update t))
9716 (goto-char pos))))))
9717
9718 (defun org-table-next-field ()
9719 "Go to the next field in the current table, creating new lines as needed.
9720 Before doing so, re-align the table if necessary."
9721 (interactive)
9722 (org-table-maybe-eval-formula)
9723 (org-table-maybe-recalculate-line)
9724 (if (and org-table-automatic-realign
9725 org-table-may-need-update)
9726 (org-table-align))
9727 (let ((end (org-table-end)))
9728 (if (org-at-table-hline-p)
9729 (end-of-line 1))
9730 (condition-case nil
9731 (progn
9732 (re-search-forward "|" end)
9733 (if (looking-at "[ \t]*$")
9734 (re-search-forward "|" end))
9735 (if (and (looking-at "-")
9736 org-table-tab-jumps-over-hlines
9737 (re-search-forward "^[ \t]*|\\([^-]\\)" end t))
9738 (goto-char (match-beginning 1)))
9739 (if (looking-at "-")
9740 (progn
9741 (beginning-of-line 0)
9742 (org-table-insert-row 'below))
9743 (if (looking-at " ") (forward-char 1))))
9744 (error
9745 (org-table-insert-row 'below)))))
9746
9747 (defun org-table-previous-field ()
9748 "Go to the previous field in the table.
9749 Before doing so, re-align the table if necessary."
9750 (interactive)
9751 (org-table-justify-field-maybe)
9752 (org-table-maybe-recalculate-line)
9753 (if (and org-table-automatic-realign
9754 org-table-may-need-update)
9755 (org-table-align))
9756 (if (org-at-table-hline-p)
9757 (end-of-line 1))
9758 (re-search-backward "|" (org-table-begin))
9759 (re-search-backward "|" (org-table-begin))
9760 (while (looking-at "|\\(-\\|[ \t]*$\\)")
9761 (re-search-backward "|" (org-table-begin)))
9762 (if (looking-at "| ?")
9763 (goto-char (match-end 0))))
9764
9765 (defun org-table-next-row ()
9766 "Go to the next row (same column) in the current table.
9767 Before doing so, re-align the table if necessary."
9768 (interactive)
9769 (org-table-maybe-eval-formula)
9770 (org-table-maybe-recalculate-line)
9771 (if (or (looking-at "[ \t]*$")
9772 (save-excursion (skip-chars-backward " \t") (bolp)))
9773 (newline)
9774 (if (and org-table-automatic-realign
9775 org-table-may-need-update)
9776 (org-table-align))
9777 (let ((col (org-table-current-column)))
9778 (beginning-of-line 2)
9779 (if (or (not (org-at-table-p))
9780 (org-at-table-hline-p))
9781 (progn
9782 (beginning-of-line 0)
9783 (org-table-insert-row 'below)))
9784 (org-table-goto-column col)
9785 (skip-chars-backward "^|\n\r")
9786 (if (looking-at " ") (forward-char 1)))))
9787
9788 (defun org-table-copy-down (n)
9789 "Copy a field down in the current column.
9790 If the field at the cursor is empty, copy into it the content of the nearest
9791 non-empty field above. With argument N, use the Nth non-empty field.
9792 If the current field is not empty, it is copied down to the next row, and
9793 the cursor is moved with it. Therefore, repeating this command causes the
9794 column to be filled row-by-row.
9795 If the variable `org-table-copy-increment' is non-nil and the field is an
9796 integer, it will be incremented while copying."
9797 (interactive "p")
9798 (let* ((colpos (org-table-current-column))
9799 (field (org-table-get-field))
9800 (non-empty (string-match "[^ \t]" field))
9801 (beg (org-table-begin))
9802 txt)
9803 (org-table-check-inside-data-field)
9804 (if non-empty
9805 (progn
9806 (setq txt (org-trim field))
9807 (org-table-next-row)
9808 (org-table-blank-field))
9809 (save-excursion
9810 (setq txt
9811 (catch 'exit
9812 (while (progn (beginning-of-line 1)
9813 (re-search-backward org-table-dataline-regexp
9814 beg t))
9815 (org-table-goto-column colpos t)
9816 (if (and (looking-at
9817 "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|")
9818 (= (setq n (1- n)) 0))
9819 (throw 'exit (match-string 1))))))))
9820 (if txt
9821 (progn
9822 (if (and org-table-copy-increment
9823 (string-match "^[0-9]+$" txt))
9824 (setq txt (format "%d" (+ (string-to-number txt) 1))))
9825 (insert txt)
9826 (org-table-maybe-recalculate-line)
9827 (org-table-align))
9828 (error "No non-empty field found"))))
9829
9830 (defun org-table-check-inside-data-field ()
9831 "Is point inside a table data field?
9832 I.e. not on a hline or before the first or after the last column?
9833 This actually throws an error, so it aborts the current command."
9834 (if (or (not (org-at-table-p))
9835 (= (org-table-current-column) 0)
9836 (org-at-table-hline-p)
9837 (looking-at "[ \t]*$"))
9838 (error "Not in table data field")))
9839
9840 (defvar org-table-clip nil
9841 "Clipboard for table regions.")
9842
9843 (defun org-table-blank-field ()
9844 "Blank the current table field or active region."
9845 (interactive)
9846 (org-table-check-inside-data-field)
9847 (if (and (interactive-p) (org-region-active-p))
9848 (let (org-table-clip)
9849 (org-table-cut-region (region-beginning) (region-end)))
9850 (skip-chars-backward "^|")
9851 (backward-char 1)
9852 (if (looking-at "|[^|\n]+")
9853 (let* ((pos (match-beginning 0))
9854 (match (match-string 0))
9855 (len (org-string-width match)))
9856 (replace-match (concat "|" (make-string (1- len) ?\ )))
9857 (goto-char (+ 2 pos))
9858 (substring match 1)))))
9859
9860 (defun org-table-get-field (&optional n replace)
9861 "Return the value of the field in column N of current row.
9862 N defaults to current field.
9863 If REPLACE is a string, replace field with this value. The return value
9864 is always the old value."
9865 (and n (org-table-goto-column n))
9866 (skip-chars-backward "^|\n")
9867 (backward-char 1)
9868 (if (looking-at "|[^|\r\n]*")
9869 (let* ((pos (match-beginning 0))
9870 (val (buffer-substring (1+ pos) (match-end 0))))
9871 (if replace
9872 (replace-match (concat "|" replace)))
9873 (goto-char (min (point-at-eol) (+ 2 pos)))
9874 val)
9875 (forward-char 1) ""))
9876
9877 (defun org-table-current-column ()
9878 "Find out which column we are in.
9879 When called interactively, column is also displayed in echo area."
9880 (interactive)
9881 (if (interactive-p) (org-table-check-inside-data-field))
9882 (save-excursion
9883 (let ((cnt 0) (pos (point)))
9884 (beginning-of-line 1)
9885 (while (search-forward "|" pos t)
9886 (setq cnt (1+ cnt)))
9887 (if (interactive-p) (message "This is table column %d" cnt))
9888 cnt)))
9889
9890 (defun org-table-goto-column (n &optional on-delim force)
9891 "Move the cursor to the Nth column in the current table line.
9892 With optional argument ON-DELIM, stop with point before the left delimiter
9893 of the field.
9894 If there are less than N fields, just go to after the last delimiter.
9895 However, when FORCE is non-nil, create new columns if necessary."
9896 (interactive "p")
9897 (let ((pos (point-at-eol)))
9898 (beginning-of-line 1)
9899 (when (> n 0)
9900 (while (and (> (setq n (1- n)) -1)
9901 (or (search-forward "|" pos t)
9902 (and force
9903 (progn (end-of-line 1)
9904 (skip-chars-backward "^|")
9905 (insert " | "))))))
9906 ; (backward-char 2) t)))))
9907 (when (and force (not (looking-at ".*|")))
9908 (save-excursion (end-of-line 1) (insert " | ")))
9909 (if on-delim
9910 (backward-char 1)
9911 (if (looking-at " ") (forward-char 1))))))
9912
9913 (defun org-at-table-p (&optional table-type)
9914 "Return t if the cursor is inside an org-type table.
9915 If TABLE-TYPE is non-nil, also check for table.el-type tables."
9916 (if org-enable-table-editor
9917 (save-excursion
9918 (beginning-of-line 1)
9919 (looking-at (if table-type org-table-any-line-regexp
9920 org-table-line-regexp)))
9921 nil))
9922
9923 (defun org-at-table.el-p ()
9924 "Return t if and only if we are at a table.el table."
9925 (and (org-at-table-p 'any)
9926 (save-excursion
9927 (goto-char (org-table-begin 'any))
9928 (looking-at org-table1-hline-regexp))))
9929
9930 (defun org-table-recognize-table.el ()
9931 "If there is a table.el table nearby, recognize it and move into it."
9932 (if org-table-tab-recognizes-table.el
9933 (if (org-at-table.el-p)
9934 (progn
9935 (beginning-of-line 1)
9936 (if (looking-at org-table-dataline-regexp)
9937 nil
9938 (if (looking-at org-table1-hline-regexp)
9939 (progn
9940 (beginning-of-line 2)
9941 (if (looking-at org-table-any-border-regexp)
9942 (beginning-of-line -1)))))
9943 (if (re-search-forward "|" (org-table-end t) t)
9944 (progn
9945 (require 'table)
9946 (if (table--at-cell-p (point))
9947 t
9948 (message "recognizing table.el table...")
9949 (table-recognize-table)
9950 (message "recognizing table.el table...done")))
9951 (error "This should not happen..."))
9952 t)
9953 nil)
9954 nil))
9955
9956 (defun org-at-table-hline-p ()
9957 "Return t if the cursor is inside a hline in a table."
9958 (if org-enable-table-editor
9959 (save-excursion
9960 (beginning-of-line 1)
9961 (looking-at org-table-hline-regexp))
9962 nil))
9963
9964 (defun org-table-insert-column ()
9965 "Insert a new column into the table."
9966 (interactive)
9967 (if (not (org-at-table-p))
9968 (error "Not at a table"))
9969 (org-table-find-dataline)
9970 (let* ((col (max 1 (org-table-current-column)))
9971 (beg (org-table-begin))
9972 (end (org-table-end))
9973 ;; Current cursor position
9974 (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
9975 (colpos col))
9976 (goto-char beg)
9977 (while (< (point) end)
9978 (if (org-at-table-hline-p)
9979 nil
9980 (org-table-goto-column col t)
9981 (insert "| "))
9982 (beginning-of-line 2))
9983 (move-marker end nil)
9984 (goto-line linepos)
9985 (org-table-goto-column colpos)
9986 (org-table-align)
9987 (org-table-modify-formulas 'insert col)))
9988
9989 (defun org-table-find-dataline ()
9990 "Find a dataline in the current table, which is needed for column commands."
9991 (if (and (org-at-table-p)
9992 (not (org-at-table-hline-p)))
9993 t
9994 (let ((col (current-column))
9995 (end (org-table-end)))
9996 (move-to-column col)
9997 (while (and (< (point) end)
9998 (or (not (= (current-column) col))
9999 (org-at-table-hline-p)))
10000 (beginning-of-line 2)
10001 (move-to-column col))
10002 (if (and (org-at-table-p)
10003 (not (org-at-table-hline-p)))
10004 t
10005 (error
10006 "Please position cursor in a data line for column operations")))))
10007
10008 (defun org-table-delete-column ()
10009 "Delete a column from the table."
10010 (interactive)
10011 (if (not (org-at-table-p))
10012 (error "Not at a table"))
10013 (org-table-find-dataline)
10014 (org-table-check-inside-data-field)
10015 (let* ((col (org-table-current-column))
10016 (beg (org-table-begin))
10017 (end (org-table-end))
10018 ;; Current cursor position
10019 (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
10020 (colpos col))
10021 (goto-char beg)
10022 (while (< (point) end)
10023 (if (org-at-table-hline-p)
10024 nil
10025 (org-table-goto-column col t)
10026 (and (looking-at "|[^|\n]+|")
10027 (replace-match "|")))
10028 (beginning-of-line 2))
10029 (move-marker end nil)
10030 (goto-line linepos)
10031 (org-table-goto-column colpos)
10032 (org-table-align)
10033 (org-table-modify-formulas 'remove col)))
10034
10035 (defun org-table-move-column-right ()
10036 "Move column to the right."
10037 (interactive)
10038 (org-table-move-column nil))
10039 (defun org-table-move-column-left ()
10040 "Move column to the left."
10041 (interactive)
10042 (org-table-move-column 'left))
10043
10044 (defun org-table-move-column (&optional left)
10045 "Move the current column to the right. With arg LEFT, move to the left."
10046 (interactive "P")
10047 (if (not (org-at-table-p))
10048 (error "Not at a table"))
10049 (org-table-find-dataline)
10050 (org-table-check-inside-data-field)
10051 (let* ((col (org-table-current-column))
10052 (col1 (if left (1- col) col))
10053 (beg (org-table-begin))
10054 (end (org-table-end))
10055 ;; Current cursor position
10056 (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
10057 (colpos (if left (1- col) (1+ col))))
10058 (if (and left (= col 1))
10059 (error "Cannot move column further left"))
10060 (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$"))
10061 (error "Cannot move column further right"))
10062 (goto-char beg)
10063 (while (< (point) end)
10064 (if (org-at-table-hline-p)
10065 nil
10066 (org-table-goto-column col1 t)
10067 (and (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|")
10068 (replace-match "|\\2|\\1|")))
10069 (beginning-of-line 2))
10070 (move-marker end nil)
10071 (goto-line linepos)
10072 (org-table-goto-column colpos)
10073 (org-table-align)
10074 (org-table-modify-formulas 'swap col (if left (1- col) (1+ col)))))
10075
10076 (defun org-table-move-row-down ()
10077 "Move table row down."
10078 (interactive)
10079 (org-table-move-row nil))
10080 (defun org-table-move-row-up ()
10081 "Move table row up."
10082 (interactive)
10083 (org-table-move-row 'up))
10084
10085 (defun org-table-move-row (&optional up)
10086 "Move the current table line down. With arg UP, move it up."
10087 (interactive "P")
10088 (let ((col (current-column))
10089 (pos (point))
10090 (tonew (if up 0 2))
10091 txt)
10092 (beginning-of-line tonew)
10093 (if (not (org-at-table-p))
10094 (progn
10095 (goto-char pos)
10096 (error "Cannot move row further")))
10097 (goto-char pos)
10098 (beginning-of-line 1)
10099 (setq pos (point))
10100 (setq txt (buffer-substring (point) (1+ (point-at-eol))))
10101 (delete-region (point) (1+ (point-at-eol)))
10102 (beginning-of-line tonew)
10103 (insert txt)
10104 (beginning-of-line 0)
10105 (move-to-column col)))
10106
10107 (defun org-table-insert-row (&optional arg)
10108 "Insert a new row above the current line into the table.
10109 With prefix ARG, insert below the current line."
10110 (interactive "P")
10111 (if (not (org-at-table-p))
10112 (error "Not at a table"))
10113 (let* ((line (buffer-substring (point-at-bol) (point-at-eol)))
10114 (new (org-table-clean-line line)))
10115 ;; Fix the first field if necessary
10116 (if (string-match "^[ \t]*| *[#$] *|" line)
10117 (setq new (replace-match (match-string 0 line) t t new)))
10118 (beginning-of-line (if arg 2 1))
10119 (let (org-table-may-need-update) (insert-before-markers new "\n"))
10120 (beginning-of-line 0)
10121 (re-search-forward "| ?" (point-at-eol) t)
10122 (and org-table-may-need-update (org-table-align))))
10123
10124 (defun org-table-insert-hline (&optional arg)
10125 "Insert a horizontal-line below the current line into the table.
10126 With prefix ARG, insert above the current line."
10127 (interactive "P")
10128 (if (not (org-at-table-p))
10129 (error "Not at a table"))
10130 (let ((line (org-table-clean-line
10131 (buffer-substring (point-at-bol) (point-at-eol))))
10132 (col (current-column)))
10133 (while (string-match "|\\( +\\)|" line)
10134 (setq line (replace-match
10135 (concat "+" (make-string (- (match-end 1) (match-beginning 1))
10136 ?-) "|") t t line)))
10137 (and (string-match "\\+" line) (setq line (replace-match "|" t t line)))
10138 (beginning-of-line (if arg 1 2))
10139 (insert line "\n")
10140 (beginning-of-line (if arg 1 -1))
10141 (move-to-column col)))
10142
10143 (defun org-table-clean-line (s)
10144 "Convert a table line S into a string with only \"|\" and space.
10145 In particular, this does handle wide and invisible characters."
10146 (if (string-match "^[ \t]*|-" s)
10147 ;; It's a hline, just map the characters
10148 (setq s (mapconcat (lambda (x) (if (member x '(?| ?+)) "|" " ")) s ""))
10149 (while (string-match "|\\([ \t]*?[^ \t\r\n|][^\r\n|]*\\)|" s)
10150 (setq s (replace-match
10151 (concat "|" (make-string (org-string-width (match-string 1 s))
10152 ?\ ) "|")
10153 t t s)))
10154 s))
10155
10156 (defun org-table-kill-row ()
10157 "Delete the current row or horizontal line from the table."
10158 (interactive)
10159 (if (not (org-at-table-p))
10160 (error "Not at a table"))
10161 (let ((col (current-column)))
10162 (kill-region (point-at-bol) (min (1+ (point-at-eol)) (point-max)))
10163 (if (not (org-at-table-p)) (beginning-of-line 0))
10164 (move-to-column col)))
10165
10166 (defun org-table-sort-lines (beg end numericp)
10167 "Sort table lines in region.
10168 Point and mark define the first and last line to include. Both point and
10169 mark should be in the column that is used for sorting. For example, to
10170 sort according to column 3, put the mark in the first line to sort, in
10171 table column 3. Put point into the last line to be included in the sorting,
10172 also in table column 3. The command will prompt for the sorting method
10173 \(n for numerical, a for alphanumeric)."
10174 (interactive "r\nsSorting method: [n]=numeric [a]=alpha: ")
10175 (setq numericp (string-match "[nN]" numericp))
10176 (org-table-align) ;; Just to be safe
10177 (let* (bcol ecol cmp column lns)
10178 (goto-char beg)
10179 (org-table-check-inside-data-field)
10180 (setq column (org-table-current-column)
10181 beg (move-marker (make-marker) (point-at-bol)))
10182 (goto-char end)
10183 (org-table-check-inside-data-field)
10184 (setq end (move-marker (make-marker) (1+ (point-at-eol))))
10185 (untabify beg end)
10186 (goto-char beg)
10187 (org-table-goto-column column)
10188 (skip-chars-backward "^|")
10189 (setq bcol (current-column))
10190 (org-table-goto-column (1+ column))
10191 (skip-chars-backward "^|")
10192 (setq ecol (1- (current-column)))
10193 (setq cmp (if numericp
10194 (lambda (a b) (< (car a) (car b)))
10195 (lambda (a b) (string< (car a) (car b)))))
10196 (setq lns (mapcar (lambda(x) (cons (org-trim (substring x bcol ecol)) x))
10197 (org-split-string (buffer-substring beg end) "\n")))
10198 (if numericp
10199 (setq lns (mapcar (lambda(x)
10200 (cons (string-to-number (car x)) (cdr x)))
10201 lns)))
10202 (delete-region beg end)
10203 (move-marker beg nil)
10204 (move-marker end nil)
10205 (insert (mapconcat 'cdr (setq lns (sort lns cmp)) "\n") "\n")
10206 (message "%d lines sorted %s based on column %d"
10207 (length lns)
10208 (if numericp "numerically" "alphabetically") column)))
10209
10210 (defun org-table-cut-region (beg end)
10211 "Copy region in table to the clipboard and blank all relevant fields."
10212 (interactive "r")
10213 (org-table-copy-region beg end 'cut))
10214
10215 (defun org-table-copy-region (beg end &optional cut)
10216 "Copy rectangular region in table to clipboard.
10217 A special clipboard is used which can only be accessed
10218 with `org-table-paste-rectangle'."
10219 (interactive "rP")
10220 (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2
10221 region cols
10222 (rpl (if cut " " nil)))
10223 (goto-char beg)
10224 (org-table-check-inside-data-field)
10225 (setq l01 (count-lines (point-min) (point))
10226 c01 (org-table-current-column))
10227 (goto-char end)
10228 (org-table-check-inside-data-field)
10229 (setq l02 (count-lines (point-min) (point))
10230 c02 (org-table-current-column))
10231 (setq l1 (min l01 l02) l2 (max l01 l02)
10232 c1 (min c01 c02) c2 (max c01 c02))
10233 (catch 'exit
10234 (while t
10235 (catch 'nextline
10236 (if (> l1 l2) (throw 'exit t))
10237 (goto-line l1)
10238 (if (org-at-table-hline-p) (throw 'nextline (setq l1 (1+ l1))))
10239 (setq cols nil ic1 c1 ic2 c2)
10240 (while (< ic1 (1+ ic2))
10241 (push (org-table-get-field ic1 rpl) cols)
10242 (setq ic1 (1+ ic1)))
10243 (push (nreverse cols) region)
10244 (setq l1 (1+ l1)))))
10245 (setq org-table-clip (nreverse region))
10246 (if cut (org-table-align))
10247 org-table-clip))
10248
10249 (defun org-table-paste-rectangle ()
10250 "Paste a rectangular region into a table.
10251 The upper right corner ends up in the current field. All involved fields
10252 will be overwritten. If the rectangle does not fit into the present table,
10253 the table is enlarged as needed. The process ignores horizontal separator
10254 lines."
10255 (interactive)
10256 (unless (and org-table-clip (listp org-table-clip))
10257 (error "First cut/copy a region to paste!"))
10258 (org-table-check-inside-data-field)
10259 (let* ((clip org-table-clip)
10260 (line (count-lines (point-min) (point)))
10261 (col (org-table-current-column))
10262 (org-enable-table-editor t)
10263 (org-table-automatic-realign nil)
10264 c cols field)
10265 (while (setq cols (pop clip))
10266 (while (org-at-table-hline-p) (beginning-of-line 2))
10267 (if (not (org-at-table-p))
10268 (progn (end-of-line 0) (org-table-next-field)))
10269 (setq c col)
10270 (while (setq field (pop cols))
10271 (org-table-goto-column c nil 'force)
10272 (org-table-get-field nil field)
10273 (setq c (1+ c)))
10274 (beginning-of-line 2))
10275 (goto-line line)
10276 (org-table-goto-column col)
10277 (org-table-align)))
10278
10279 (defun org-table-convert ()
10280 "Convert from `org-mode' table to table.el and back.
10281 Obviously, this only works within limits. When an Org-mode table is
10282 converted to table.el, all horizontal separator lines get lost, because
10283 table.el uses these as cell boundaries and has no notion of horizontal lines.
10284 A table.el table can be converted to an Org-mode table only if it does not
10285 do row or column spanning. Multiline cells will become multiple cells.
10286 Beware, Org-mode does not test if the table can be successfully converted - it
10287 blindly applies a recipe that works for simple tables."
10288 (interactive)
10289 (require 'table)
10290 (if (org-at-table.el-p)
10291 ;; convert to Org-mode table
10292 (let ((beg (move-marker (make-marker) (org-table-begin t)))
10293 (end (move-marker (make-marker) (org-table-end t))))
10294 (table-unrecognize-region beg end)
10295 (goto-char beg)
10296 (while (re-search-forward "^\\([ \t]*\\)\\+-.*\n" end t)
10297 (replace-match ""))
10298 (goto-char beg))
10299 (if (org-at-table-p)
10300 ;; convert to table.el table
10301 (let ((beg (move-marker (make-marker) (org-table-begin)))
10302 (end (move-marker (make-marker) (org-table-end))))
10303 ;; first, get rid of all horizontal lines
10304 (goto-char beg)
10305 (while (re-search-forward "^\\([ \t]*\\)|-.*\n" end t)
10306 (replace-match ""))
10307 ;; insert a hline before first
10308 (goto-char beg)
10309 (org-table-insert-hline 'above)
10310 (beginning-of-line -1)
10311 ;; insert a hline after each line
10312 (while (progn (beginning-of-line 3) (< (point) end))
10313 (org-table-insert-hline))
10314 (goto-char beg)
10315 (setq end (move-marker end (org-table-end)))
10316 ;; replace "+" at beginning and ending of hlines
10317 (while (re-search-forward "^\\([ \t]*\\)|-" end t)
10318 (replace-match "\\1+-"))
10319 (goto-char beg)
10320 (while (re-search-forward "-|[ \t]*$" end t)
10321 (replace-match "-+"))
10322 (goto-char beg)))))
10323
10324 (defun org-table-wrap-region (arg)
10325 "Wrap several fields in a column like a paragraph.
10326 This is useful if you'd like to spread the contents of a field over several
10327 lines, in order to keep the table compact.
10328
10329 If there is an active region, and both point and mark are in the same column,
10330 the text in the column is wrapped to minimum width for the given number of
10331 lines. Generally, this makes the table more compact. A prefix ARG may be
10332 used to change the number of desired lines. For example, `C-2 \\[org-table-wrap]'
10333 formats the selected text to two lines. If the region was longer than two
10334 lines, the remaining lines remain empty. A negative prefix argument reduces
10335 the current number of lines by that amount. The wrapped text is pasted back
10336 into the table. If you formatted it to more lines than it was before, fields
10337 further down in the table get overwritten - so you might need to make space in
10338 the table first.
10339
10340 If there is no region, the current field is split at the cursor position and
10341 the text fragment to the right of the cursor is prepended to the field one
10342 line down.
10343
10344 If there is no region, but you specify a prefix ARG, the current field gets
10345 blank, and the content is appended to the field above."
10346 (interactive "P")
10347 (org-table-check-inside-data-field)
10348 (if (org-region-active-p)
10349 ;; There is a region: fill as a paragraph
10350 (let ((beg (region-beginning))
10351 nlines)
10352 (org-table-cut-region (region-beginning) (region-end))
10353 (if (> (length (car org-table-clip)) 1)
10354 (error "Region must be limited to single column"))
10355 (setq nlines (if arg
10356 (if (< arg 1)
10357 (+ (length org-table-clip) arg)
10358 arg)
10359 (length org-table-clip)))
10360 (setq org-table-clip
10361 (mapcar 'list (org-wrap (mapconcat 'car org-table-clip " ")
10362 nil nlines)))
10363 (goto-char beg)
10364 (org-table-paste-rectangle))
10365 ;; No region, split the current field at point
10366 (if arg
10367 ;; combine with field above
10368 (let ((s (org-table-blank-field))
10369 (col (org-table-current-column)))
10370 (beginning-of-line 0)
10371 (while (org-at-table-hline-p) (beginning-of-line 0))
10372 (org-table-goto-column col)
10373 (skip-chars-forward "^|")
10374 (skip-chars-backward " ")
10375 (insert " " (org-trim s))
10376 (org-table-align))
10377 ;; split field
10378 (when (looking-at "\\([^|]+\\)+|")
10379 (let ((s (match-string 1)))
10380 (replace-match " |")
10381 (goto-char (match-beginning 0))
10382 (org-table-next-row)
10383 (insert (org-trim s) " ")
10384 (org-table-align))))))
10385
10386 (defvar org-field-marker nil)
10387
10388 (defun org-table-edit-field (arg)
10389 "Edit table field in a different window.
10390 This is mainly useful for fields that contain hidden parts.
10391 When called with a \\[universal-argument] prefix, just make the full field visible so that
10392 it can be edited in place."
10393 (interactive "P")
10394 (if arg
10395 (let ((b (save-excursion (skip-chars-backward "^|") (point)))
10396 (e (save-excursion (skip-chars-forward "^|\r\n") (point))))
10397 (remove-text-properties b e '(org-cwidth t invisible t
10398 display t intangible t))
10399 (if (and (boundp 'font-lock-mode) font-lock-mode)
10400 (font-lock-fontify-block)))
10401 (let ((pos (move-marker (make-marker) (point)))
10402 (field (org-table-get-field))
10403 (cw (current-window-configuration))
10404 p)
10405 (switch-to-buffer-other-window "*Org tmp*")
10406 (erase-buffer)
10407 (insert "#\n# Edit field and finish with C-c C-c\n#\n")
10408 (org-mode)
10409 (goto-char (setq p (point-max)))
10410 (insert (org-trim field))
10411 (remove-text-properties p (point-max)
10412 '(invisible t org-cwidth t display t
10413 intangible t))
10414 (goto-char p)
10415 (set (make-local-variable 'org-finish-function)
10416 'org-table-finish-edit-field)
10417 (set (make-local-variable 'org-window-configuration) cw)
10418 (set (make-local-variable 'org-field-marker) pos)
10419 (message "Edit and finish with C-c C-c"))))
10420
10421 (defun org-table-finish-edit-field ()
10422 "Finish editing a table data field.
10423 Remove all newline characters, insert the result into the table, realign
10424 the table and kill the editing buffer."
10425 (let ((pos org-field-marker)
10426 (cw org-window-configuration)
10427 (cb (current-buffer))
10428 text)
10429 (goto-char (point-min))
10430 (while (re-search-forward "^#.*\n?" nil t) (replace-match ""))
10431 (while (re-search-forward "\\([ \t]*\n[ \t]*\\)+" nil t)
10432 (replace-match " "))
10433 (setq text (org-trim (buffer-string)))
10434 (set-window-configuration cw)
10435 (kill-buffer cb)
10436 (select-window (get-buffer-window (marker-buffer pos)))
10437 (goto-char pos)
10438 (move-marker pos nil)
10439 (org-table-check-inside-data-field)
10440 (org-table-get-field nil text)
10441 (org-table-align)
10442 (message "New field value inserted")))
10443
10444 (defun org-trim (s)
10445 "Remove whitespace at beginning and end of string."
10446 (if (string-match "^[ \t]+" s) (setq s (replace-match "" t t s)))
10447 (if (string-match "[ \t]+$" s) (setq s (replace-match "" t t s)))
10448 s)
10449
10450 (defun org-wrap (string &optional width lines)
10451 "Wrap string to either a number of lines, or a width in characters.
10452 If WIDTH is non-nil, the string is wrapped to that width, however many lines
10453 that costs. If there is a word longer than WIDTH, the text is actually
10454 wrapped to the length of that word.
10455 IF WIDTH is nil and LINES is non-nil, the string is forced into at most that
10456 many lines, whatever width that takes.
10457 The return value is a list of lines, without newlines at the end."
10458 (let* ((words (org-split-string string "[ \t\n]+"))
10459 (maxword (apply 'max (mapcar 'org-string-width words)))
10460 w ll)
10461 (cond (width
10462 (org-do-wrap words (max maxword width)))
10463 (lines
10464 (setq w maxword)
10465 (setq ll (org-do-wrap words maxword))
10466 (if (<= (length ll) lines)
10467 ll
10468 (setq ll words)
10469 (while (> (length ll) lines)
10470 (setq w (1+ w))
10471 (setq ll (org-do-wrap words w)))
10472 ll))
10473 (t (error "Cannot wrap this")))))
10474
10475
10476 (defun org-do-wrap (words width)
10477 "Create lines of maximum width WIDTH (in characters) from word list WORDS."
10478 (let (lines line)
10479 (while words
10480 (setq line (pop words))
10481 (while (and words (< (+ (length line) (length (car words))) width))
10482 (setq line (concat line " " (pop words))))
10483 (setq lines (push line lines)))
10484 (nreverse lines)))
10485
10486 (defun org-split-string (string &optional separators)
10487 "Splits STRING into substrings at SEPARATORS.
10488 No empty strings are returned if there are matches at the beginning
10489 and end of string."
10490 (let ((rexp (or separators "[ \f\t\n\r\v]+"))
10491 (start 0)
10492 notfirst
10493 (list nil))
10494 (while (and (string-match rexp string
10495 (if (and notfirst
10496 (= start (match-beginning 0))
10497 (< start (length string)))
10498 (1+ start) start))
10499 (< (match-beginning 0) (length string)))
10500 (setq notfirst t)
10501 (or (eq (match-beginning 0) 0)
10502 (and (eq (match-beginning 0) (match-end 0))
10503 (eq (match-beginning 0) start))
10504 (setq list
10505 (cons (substring string start (match-beginning 0))
10506 list)))
10507 (setq start (match-end 0)))
10508 (or (eq start (length string))
10509 (setq list
10510 (cons (substring string start)
10511 list)))
10512 (nreverse list)))
10513
10514 (defun org-table-map-tables (function)
10515 "Apply FUNCTION to the start of all tables in the buffer."
10516 (save-excursion
10517 (save-restriction
10518 (widen)
10519 (goto-char (point-min))
10520 (while (re-search-forward org-table-any-line-regexp nil t)
10521 (message "Mapping tables: %d%%" (/ (* 100.0 (point)) (buffer-size)))
10522 (beginning-of-line 1)
10523 (if (looking-at org-table-line-regexp)
10524 (save-excursion (funcall function)))
10525 (re-search-forward org-table-any-border-regexp nil 1))))
10526 (message "Mapping tables: done"))
10527
10528 (defun org-table-sum (&optional beg end nlast)
10529 "Sum numbers in region of current table column.
10530 The result will be displayed in the echo area, and will be available
10531 as kill to be inserted with \\[yank].
10532
10533 If there is an active region, it is interpreted as a rectangle and all
10534 numbers in that rectangle will be summed. If there is no active
10535 region and point is located in a table column, sum all numbers in that
10536 column.
10537
10538 If at least one number looks like a time HH:MM or HH:MM:SS, all other
10539 numbers are assumed to be times as well (in decimal hours) and the
10540 numbers are added as such.
10541
10542 If NLAST is a number, only the NLAST fields will actually be summed."
10543 (interactive)
10544 (save-excursion
10545 (let (col (timecnt 0) diff h m s org-table-clip)
10546 (cond
10547 ((and beg end)) ; beg and end given explicitly
10548 ((org-region-active-p)
10549 (setq beg (region-beginning) end (region-end)))
10550 (t
10551 (setq col (org-table-current-column))
10552 (goto-char (org-table-begin))
10553 (unless (re-search-forward "^[ \t]*|[^-]" nil t)
10554 (error "No table data"))
10555 (org-table-goto-column col)
10556 ;not needed? (skip-chars-backward "^|")
10557 (setq beg (point))
10558 (goto-char (org-table-end))
10559 (unless (re-search-backward "^[ \t]*|[^-]" nil t)
10560 (error "No table data"))
10561 (org-table-goto-column col)
10562 ;not needed? (skip-chars-forward "^|")
10563 (setq end (point))))
10564 (let* ((items (apply 'append (org-table-copy-region beg end)))
10565 (items1 (cond ((not nlast) items)
10566 ((>= nlast (length items)) items)
10567 (t (setq items (reverse items))
10568 (setcdr (nthcdr (1- nlast) items) nil)
10569 (nreverse items))))
10570 (numbers (delq nil (mapcar 'org-table-get-number-for-summing
10571 items1)))
10572 (res (apply '+ numbers))
10573 (sres (if (= timecnt 0)
10574 (format "%g" res)
10575 (setq diff (* 3600 res)
10576 h (floor (/ diff 3600)) diff (mod diff 3600)
10577 m (floor (/ diff 60)) diff (mod diff 60)
10578 s diff)
10579 (format "%d:%02d:%02d" h m s))))
10580 (kill-new sres)
10581 (if (interactive-p)
10582 (message "%s"
10583 (substitute-command-keys
10584 (format "Sum of %d items: %-20s (\\[yank] will insert result into buffer)"
10585 (length numbers) sres))))
10586 sres))))
10587
10588 (defun org-table-get-number-for-summing (s)
10589 (let (n)
10590 (if (string-match "^ *|? *" s)
10591 (setq s (replace-match "" nil nil s)))
10592 (if (string-match " *|? *$" s)
10593 (setq s (replace-match "" nil nil s)))
10594 (setq n (string-to-number s))
10595 (cond
10596 ((and (string-match "0" s)
10597 (string-match "\\`[-+ \t0.edED]+\\'" s)) 0)
10598 ((string-match "\\`[ \t]+\\'" s) nil)
10599 ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?\\'" s)
10600 (let ((h (string-to-number (or (match-string 1 s) "0")))
10601 (m (string-to-number (or (match-string 2 s) "0")))
10602 (s (string-to-number (or (match-string 4 s) "0"))))
10603 (if (boundp 'timecnt) (setq timecnt (1+ timecnt)))
10604 (* 1.0 (+ h (/ m 60.0) (/ s 3600.0)))))
10605 ((equal n 0) nil)
10606 (t n))))
10607
10608 (defun org-table-get-vertical-vector (desc &optional tbeg col)
10609 "Get a calc vector from a column, accorting to descriptor DESC.
10610 Optional arguments TBEG and COL can give the beginning of the table and
10611 the current column, to avoid unnecessary parsing."
10612 (save-excursion
10613 (or tbeg (setq tbeg (org-table-begin)))
10614 (or col (setq col (org-table-current-column)))
10615 (let (beg end nn n n1 n2 l (thisline (org-current-line)) hline-list)
10616 (cond
10617 ((string-match "\\(I+\\)\\(-\\(I+\\)\\)?" desc)
10618 (setq n1 (- (match-end 1) (match-beginning 1)))
10619 (if (match-beginning 3)
10620 (setq n2 (- (match-end 2) (match-beginning 3))))
10621 (setq n (if n2 (max n1 n2) n1))
10622 (setq n1 (if n2 (min n1 n2)))
10623 (setq nn n)
10624 (while (and (> nn 0)
10625 (re-search-backward org-table-hline-regexp tbeg t))
10626 (push (org-current-line) hline-list)
10627 (setq nn (1- nn)))
10628 (setq hline-list (nreverse hline-list))
10629 (goto-line (nth (1- n) hline-list))
10630 (when (re-search-forward org-table-dataline-regexp)
10631 (org-table-goto-column col)
10632 (setq beg (point)))
10633 (goto-line (if n1 (nth (1- n1) hline-list) thisline))
10634 (when (re-search-backward org-table-dataline-regexp)
10635 (org-table-goto-column col)
10636 (setq end (point)))
10637 (setq l (apply 'append (org-table-copy-region beg end)))
10638 (concat "[" (mapconcat (lambda (x) (setq x (org-trim x))
10639 (if (equal x "") "0" x))
10640 l ",") "]"))
10641 ((string-match "\\([0-9]+\\)-\\([0-9]+\\)" desc)
10642 (setq n1 (string-to-number (match-string 1 desc))
10643 n2 (string-to-number (match-string 2 desc)))
10644 (beginning-of-line 1)
10645 (save-excursion
10646 (when (re-search-backward org-table-dataline-regexp tbeg t n1)
10647 (org-table-goto-column col)
10648 (setq beg (point))))
10649 (when (re-search-backward org-table-dataline-regexp tbeg t n2)
10650 (org-table-goto-column col)
10651 (setq end (point)))
10652 (setq l (apply 'append (org-table-copy-region beg end)))
10653 (concat "[" (mapconcat
10654 (lambda (x) (setq x (org-trim x))
10655 (if (equal x "") "0" x))
10656 l ",") "]"))
10657 ((string-match "\\([0-9]+\\)" desc)
10658 (beginning-of-line 1)
10659 (when (re-search-backward org-table-dataline-regexp tbeg t
10660 (string-to-number (match-string 0 desc)))
10661 (org-table-goto-column col)
10662 (org-trim (org-table-get-field))))))))
10663
10664 (defvar org-table-formula-history nil)
10665
10666 (defvar org-table-column-names nil
10667 "Alist with column names, derived from the `!' line.")
10668 (defvar org-table-column-name-regexp nil
10669 "Regular expression matching the current column names.")
10670 (defvar org-table-local-parameters nil
10671 "Alist with parameter names, derived from the `$' line.")
10672 (defvar org-table-named-field-locations nil
10673 "Alist with locations of named fields.")
10674
10675 (defun org-table-get-formula (&optional equation named)
10676 "Read a formula from the minibuffer, offer stored formula as default."
10677 (let* ((name (car (rassoc (list (org-current-line)
10678 (org-table-current-column))
10679 org-table-named-field-locations)))
10680 (scol (if named
10681 (if name name
10682 (error "Not in a named field"))
10683 (int-to-string (org-table-current-column))))
10684 (dummy (and name (not named)
10685 (not (y-or-n-p "Replace named-field formula with column equation? " ))
10686 (error "Abort")))
10687 (org-table-may-need-update nil)
10688 (stored-list (org-table-get-stored-formulas))
10689 (stored (cdr (assoc scol stored-list)))
10690 (eq (cond
10691 ((and stored equation (string-match "^ *=? *$" equation))
10692 stored)
10693 ((stringp equation)
10694 equation)
10695 (t (read-string
10696 (format "%s formula $%s=" (if named "Field" "Column") scol)
10697 (or stored "") 'org-table-formula-history
10698 ;stored
10699 ))))
10700 mustsave)
10701 (when (not (string-match "\\S-" eq))
10702 ;; remove formula
10703 (setq stored-list (delq (assoc scol stored-list) stored-list))
10704 (org-table-store-formulas stored-list)
10705 (error "Formula removed"))
10706 (if (string-match "^ *=?" eq) (setq eq (replace-match "" t t eq)))
10707 (if (string-match " *$" eq) (setq eq (replace-match "" t t eq)))
10708 (if (and name (not named))
10709 ;; We set the column equation, delete the named one.
10710 (setq stored-list (delq (assoc name stored-list) stored-list)
10711 mustsave t))
10712 (if stored
10713 (setcdr (assoc scol stored-list) eq)
10714 (setq stored-list (cons (cons scol eq) stored-list)))
10715 (if (or mustsave (not (equal stored eq)))
10716 (org-table-store-formulas stored-list))
10717 eq))
10718
10719 (defun org-table-store-formulas (alist)
10720 "Store the list of formulas below the current table."
10721 (setq alist (sort alist (lambda (a b) (string< (car a) (car b)))))
10722 (save-excursion
10723 (goto-char (org-table-end))
10724 (if (looking-at "\\([ \t]*\n\\)*#\\+TBLFM:.*\n?")
10725 (delete-region (point) (match-end 0)))
10726 (insert "#+TBLFM: "
10727 (mapconcat (lambda (x)
10728 (concat "$" (car x) "=" (cdr x)))
10729 alist "::")
10730 "\n")))
10731
10732 (defun org-table-get-stored-formulas ()
10733 "Return an alist with the stored formulas directly after current table."
10734 (interactive)
10735 (let (scol eq eq-alist strings string seen)
10736 (save-excursion
10737 (goto-char (org-table-end))
10738 (when (looking-at "\\([ \t]*\n\\)*#\\+TBLFM: *\\(.*\\)")
10739 (setq strings (org-split-string (match-string 2) " *:: *"))
10740 (while (setq string (pop strings))
10741 (when (string-match "\\$\\([a-zA-Z0-9]+\\) *= *\\(.*[^ \t]\\)" string)
10742 (setq scol (match-string 1 string)
10743 eq (match-string 2 string)
10744 eq-alist (cons (cons scol eq) eq-alist))
10745 (if (member scol seen)
10746 (error "Double definition `$%s=' in TBLFM line, please fix by hand" scol)
10747 (push scol seen))))))
10748 (nreverse eq-alist)))
10749
10750 (defun org-table-modify-formulas (action &rest columns)
10751 "Modify the formulas stored below the current table.
10752 ACTION can be `remove', `insert', `swap'. For `swap', two column numbers are
10753 expected, for the other actions only a single column number is needed."
10754 (let ((list (org-table-get-stored-formulas))
10755 (nmax (length (org-split-string
10756 (buffer-substring (point-at-bol) (point-at-eol))
10757 "|")))
10758 col col1 col2 scol si sc1 sc2)
10759 (cond
10760 ((null list)) ; No action needed if there are no stored formulas
10761 ((eq action 'remove)
10762 (setq col (car columns)
10763 scol (int-to-string col))
10764 (org-table-replace-in-formulas list scol "INVALID")
10765 (if (assoc scol list) (setq list (delq (assoc scol list) list)))
10766 (loop for i from (1+ col) upto nmax by 1 do
10767 (setq si (int-to-string i))
10768 (org-table-replace-in-formulas list si (int-to-string (1- i)))
10769 (if (assoc si list) (setcar (assoc si list)
10770 (int-to-string (1- i))))))
10771 ((eq action 'insert)
10772 (setq col (car columns))
10773 (loop for i from nmax downto col by 1 do
10774 (setq si (int-to-string i))
10775 (org-table-replace-in-formulas list si (int-to-string (1+ i)))
10776 (if (assoc si list) (setcar (assoc si list)
10777 (int-to-string (1+ i))))))
10778 ((eq action 'swap)
10779 (setq col1 (car columns) col2 (nth 1 columns)
10780 sc1 (int-to-string col1) sc2 (int-to-string col2))
10781 ;; Hopefully, ZqZtZ will never be a name in a table
10782 (org-table-replace-in-formulas list sc1 "ZqZtZ")
10783 (org-table-replace-in-formulas list sc2 sc1)
10784 (org-table-replace-in-formulas list "ZqZtZ" sc2)
10785 (if (assoc sc1 list) (setcar (assoc sc1 list) "ZqZtZ"))
10786 (if (assoc sc2 list) (setcar (assoc sc2 list) sc1))
10787 (if (assoc "ZqZtZ" list) (setcar (assoc "ZqZtZ" list) sc2)))
10788 (t (error "Invalid action in `org-table-modify-formulas'")))
10789 (if list (org-table-store-formulas list))))
10790
10791 (defun org-table-replace-in-formulas (list s1 s2)
10792 (let (elt re s)
10793 (setq s1 (concat "$" (if (integerp s1) (int-to-string s1) s1))
10794 s2 (concat "$" (if (integerp s2) (int-to-string s2) s2))
10795 re (concat (regexp-quote s1) "\\>"))
10796 (while (setq elt (pop list))
10797 (setq s (cdr elt))
10798 (while (string-match re s)
10799 (setq s (replace-match s2 t t s)))
10800 (setcdr elt s))))
10801
10802 (defun org-table-get-specials ()
10803 "Get the column names and local parameters for this table."
10804 (save-excursion
10805 (let ((beg (org-table-begin)) (end (org-table-end))
10806 names name fields fields1 field cnt c v line col)
10807 (setq org-table-column-names nil
10808 org-table-local-parameters nil
10809 org-table-named-field-locations nil)
10810 (goto-char beg)
10811 (when (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t)
10812 (setq names (org-split-string (match-string 1) " *| *")
10813 cnt 1)
10814 (while (setq name (pop names))
10815 (setq cnt (1+ cnt))
10816 (if (string-match "^[a-zA-Z][a-zA-Z0-9]*$" name)
10817 (push (cons name (int-to-string cnt)) org-table-column-names))))
10818 (setq org-table-column-names (nreverse org-table-column-names))
10819 (setq org-table-column-name-regexp
10820 (concat "\\$\\(" (mapconcat 'car org-table-column-names "\\|") "\\)\\>"))
10821 (goto-char beg)
10822 (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t)
10823 (setq fields (org-split-string (match-string 1) " *| *"))
10824 (while (setq field (pop fields))
10825 (if (string-match "^\\([a-zA-Z][a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field)
10826 (push (cons (match-string 1 field) (match-string 2 field))
10827 org-table-local-parameters))))
10828 (goto-char beg)
10829 (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t)
10830 (setq c (match-string 1)
10831 fields (org-split-string (match-string 2) " *| *"))
10832 (save-excursion
10833 (beginning-of-line (if (equal c "_") 2 0))
10834 (setq line (org-current-line) col 1)
10835 (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)")
10836 (setq fields1 (org-split-string (match-string 1) " *| *"))))
10837 (while (and fields1 (setq field (pop fields)))
10838 (setq v (pop fields1) col (1+ col))
10839 (when (and (stringp field) (stringp v)
10840 (string-match "^[a-zA-Z][a-zA-Z0-9]*$" field))
10841 (push (cons field v) org-table-local-parameters)
10842 (push (list field line col) org-table-named-field-locations)))))))
10843
10844 (defun org-this-word ()
10845 ;; Get the current word
10846 (save-excursion
10847 (let ((beg (progn (skip-chars-backward "^ \t\n") (point)))
10848 (end (progn (skip-chars-forward "^ \t\n") (point))))
10849 (buffer-substring-no-properties beg end))))
10850
10851 (defun org-table-maybe-eval-formula ()
10852 "Check if the current field starts with \"=\" or \":=\".
10853 If yes, store the formula and apply it."
10854 ;; We already know we are in a table. Get field will only return a formula
10855 ;; when appropriate. It might return a separator line, but no problem.
10856 (when org-table-formula-evaluate-inline
10857 (let* ((field (org-trim (or (org-table-get-field) "")))
10858 named eq)
10859 (when (string-match "^:?=\\(.*\\)" field)
10860 (setq named (equal (string-to-char field) ?:)
10861 eq (match-string 1 field))
10862 (if (fboundp 'calc-eval)
10863 (org-table-eval-formula (if named '(4) nil) eq))))))
10864
10865 (defvar org-recalc-commands nil
10866 "List of commands triggering the recalculation of a line.
10867 Will be filled automatically during use.")
10868
10869 (defvar org-recalc-marks
10870 '((" " . "Unmarked: no special line, no automatic recalculation")
10871 ("#" . "Automatically recalculate this line upon TAB, RET, and C-c C-c in the line")
10872 ("*" . "Recalculate only when entire table is recalculated with `C-u C-c *'")
10873 ("!" . "Column name definition line. Reference in formula as $name.")
10874 ("$" . "Parameter definition line name=value. Reference in formula as $name.")
10875 ("_" . "Names for values in row below this one.")
10876 ("^" . "Names for values in row above this one.")))
10877
10878 (defun org-table-rotate-recalc-marks (&optional newchar)
10879 "Rotate the recalculation mark in the first column.
10880 If in any row, the first field is not consistent with a mark,
10881 insert a new column for the markers.
10882 When there is an active region, change all the lines in the region,
10883 after prompting for the marking character.
10884 After each change, a message will be displayed indicating the meaning
10885 of the new mark."
10886 (interactive)
10887 (unless (org-at-table-p) (error "Not at a table"))
10888 (let* ((marks (append (mapcar 'car org-recalc-marks) '(" ")))
10889 (beg (org-table-begin))
10890 (end (org-table-end))
10891 (l (org-current-line))
10892 (l1 (if (org-region-active-p) (org-current-line (region-beginning))))
10893 (l2 (if (org-region-active-p) (org-current-line (region-end))))
10894 (have-col
10895 (save-excursion
10896 (goto-char beg)
10897 (not (re-search-forward "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" end t))))
10898 (col (org-table-current-column))
10899 (forcenew (car (assoc newchar org-recalc-marks)))
10900 epos new)
10901 (when l1
10902 (message "Change region to what mark? Type # * ! $ or SPC: ")
10903 (setq newchar (char-to-string (read-char-exclusive))
10904 forcenew (car (assoc newchar org-recalc-marks))))
10905 (if (and newchar (not forcenew))
10906 (error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'"
10907 newchar))
10908 (if l1 (goto-line l1))
10909 (save-excursion
10910 (beginning-of-line 1)
10911 (unless (looking-at org-table-dataline-regexp)
10912 (error "Not at a table data line")))
10913 (unless have-col
10914 (org-table-goto-column 1)
10915 (org-table-insert-column)
10916 (org-table-goto-column (1+ col)))
10917 (setq epos (point-at-eol))
10918 (save-excursion
10919 (beginning-of-line 1)
10920 (org-table-get-field
10921 1 (if (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|")
10922 (concat " "
10923 (setq new (or forcenew
10924 (cadr (member (match-string 1) marks))))
10925 " ")
10926 " # ")))
10927 (if (and l1 l2)
10928 (progn
10929 (goto-line l1)
10930 (while (progn (beginning-of-line 2) (not (= (org-current-line) l2)))
10931 (and (looking-at org-table-dataline-regexp)
10932 (org-table-get-field 1 (concat " " new " "))))
10933 (goto-line l1)))
10934 (if (not (= epos (point-at-eol))) (org-table-align))
10935 (goto-line l)
10936 (and (interactive-p) (message (cdr (assoc new org-recalc-marks))))))
10937
10938 (defun org-table-maybe-recalculate-line ()
10939 "Recompute the current line if marked for it, and if we haven't just done it."
10940 (interactive)
10941 (and org-table-allow-automatic-line-recalculation
10942 (not (and (memq last-command org-recalc-commands)
10943 (equal org-last-recalc-line (org-current-line))))
10944 (save-excursion (beginning-of-line 1)
10945 (looking-at org-table-auto-recalculate-regexp))
10946 (fboundp 'calc-eval)
10947 (org-table-recalculate) t))
10948
10949 (defvar org-table-formula-debug nil
10950 "Non-nil means, debug table formulas.
10951 When nil, simply write \"#ERROR\" in corrupted fields.")
10952
10953 (defvar modes)
10954 (defsubst org-set-calc-mode (var &optional value)
10955 (if (stringp var)
10956 (setq var (assoc var '(("D" calc-angle-mode deg)
10957 ("R" calc-angle-mode rad)
10958 ("F" calc-prefer-frac t)
10959 ("S" calc-symbolic-mode t)))
10960 value (nth 2 var) var (nth 1 var)))
10961 (if (memq var modes)
10962 (setcar (cdr (memq var modes)) value)
10963 (cons var (cons value modes)))
10964 modes)
10965
10966 (defun org-table-eval-formula (&optional arg equation
10967 suppress-align suppress-const
10968 suppress-store)
10969 "Replace the table field value at the cursor by the result of a calculation.
10970
10971 This function makes use of Dave Gillespie's Calc package, in my view the
10972 most exciting program ever written for GNU Emacs. So you need to have Calc
10973 installed in order to use this function.
10974
10975 In a table, this command replaces the value in the current field with the
10976 result of a formula. It also installs the formula as the \"current\" column
10977 formula, by storing it in a special line below the table. When called
10978 with a `C-u' prefix, the current field must ba a named field, and the
10979 formula is installed as valid in only this specific field.
10980
10981 When called, the command first prompts for a formula, which is read in
10982 the minibuffer. Previously entered formulas are available through the
10983 history list, and the last used formula is offered as a default.
10984 These stored formulas are adapted correctly when moving, inserting, or
10985 deleting columns with the corresponding commands.
10986
10987 The formula can be any algebraic expression understood by the Calc package.
10988 For details, see the Org-mode manual.
10989
10990 This function can also be called from Lisp programs and offers
10991 additional arguments: EQUATION can be the formula to apply. If this
10992 argument is given, the user will not be prompted. SUPPRESS-ALIGN is
10993 used to speed-up recursive calls by by-passing unnecessary aligns.
10994 SUPPRESS-CONST suppresses the interpretation of constants in the
10995 formula, assuming that this has been done already outside the function.
10996 SUPPRESS-STORE means the formula should not be stored, either because
10997 it is already stored, or because it is a modified equation that should
10998 not overwrite the stored one."
10999 (interactive "P")
11000 (require 'calc)
11001 (org-table-check-inside-data-field)
11002 (org-table-get-specials)
11003 (let* (fields
11004 (ndown (if (integerp arg) arg 1))
11005 (org-table-automatic-realign nil)
11006 (case-fold-search nil)
11007 (down (> ndown 1))
11008 (formula (if (and equation suppress-store)
11009 equation
11010 (org-table-get-formula equation (equal arg '(4)))))
11011 (n0 (org-table-current-column))
11012 (modes (copy-sequence org-calc-default-modes))
11013 n form fmt x ev orig c lispp)
11014 ;; Parse the format string. Since we have a lot of modes, this is
11015 ;; a lot of work. However, I think calc still uses most of the time.
11016 (if (string-match ";" formula)
11017 (let ((tmp (org-split-string formula ";")))
11018 (setq formula (car tmp)
11019 fmt (concat (cdr (assoc "%" org-table-local-parameters))
11020 (nth 1 tmp)))
11021 (while (string-match "[pnfse]\\(-?[0-9]+\\)" fmt)
11022 (setq c (string-to-char (match-string 1 fmt))
11023 n (string-to-number (or (match-string 1 fmt) "")))
11024 (if (= c ?p) (setq modes (org-set-calc-mode 'calc-internal-prec n))
11025 (setq modes (org-set-calc-mode
11026 'calc-float-format
11027 (list (cdr (assoc c '((?n . float) (?f . fix)
11028 (?s . sci) (?e . eng))))
11029 n))))
11030 (setq fmt (replace-match "" t t fmt)))
11031 (while (string-match "[DRFS]" fmt)
11032 (setq modes (org-set-calc-mode (match-string 0 fmt)))
11033 (setq fmt (replace-match "" t t fmt)))
11034 (unless (string-match "\\S-" fmt)
11035 (setq fmt nil))))
11036 (if (and (not suppress-const) org-table-formula-use-constants)
11037 (setq formula (org-table-formula-substitute-names formula)))
11038 (setq orig (or (get-text-property 1 :orig-formula formula) "?"))
11039 (while (> ndown 0)
11040 (setq fields (org-split-string
11041 (buffer-substring
11042 (point-at-bol) (point-at-eol)) " *| *"))
11043 (if org-table-formula-numbers-only
11044 (setq fields (mapcar
11045 (lambda (x) (number-to-string (string-to-number x)))
11046 fields)))
11047 (setq ndown (1- ndown))
11048 (setq form (copy-sequence formula)
11049 lispp (equal (substring form 0 2) "'("))
11050 ;; Insert the references to fields in same row
11051 (while (string-match "\\$\\([0-9]+\\)?" form)
11052 (setq n (if (match-beginning 1)
11053 (string-to-number (match-string 1 form))
11054 n0)
11055 x (nth (1- n) fields))
11056 (unless x (error "Invalid field specifier \"%s\""
11057 (match-string 0 form)))
11058 (if (equal x "") (setq x "0"))
11059 (setq form (replace-match
11060 (if lispp x (concat "(" x ")"))
11061 t t form)))
11062 ;; Insert ranges in current column
11063 (while (string-match "\\&[-I0-9]+" form)
11064 (setq form (replace-match
11065 (save-match-data
11066 (org-table-get-vertical-vector (match-string 0 form)
11067 nil n0))
11068 t t form)))
11069 (if lispp
11070 (setq ev (eval (eval (read form)))
11071 ev (if (numberp ev) (number-to-string ev) ev))
11072 (setq ev (calc-eval (cons form modes)
11073 (if org-table-formula-numbers-only 'num))))
11074
11075 (when org-table-formula-debug
11076 (with-output-to-temp-buffer "*Help*"
11077 (princ (format "Substitution history of formula
11078 Orig: %s
11079 $xyz-> %s
11080 $1-> %s\n" orig formula form))
11081 (if (listp ev)
11082 (princ (format " %s^\nError: %s"
11083 (make-string (car ev) ?\-) (nth 1 ev)))
11084 (princ (format "Result: %s\nFormat: %s\nFinal: %s"
11085 ev (or fmt "NONE")
11086 (if fmt (format fmt (string-to-number ev)) ev)))))
11087 (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*"))
11088 (unless (and (interactive-p) (not ndown))
11089 (unless (let (inhibit-redisplay)
11090 (y-or-n-p "Debugging Formula. Continue to next? "))
11091 (org-table-align)
11092 (error "Abort"))
11093 (delete-window (get-buffer-window "*Help*"))
11094 (message "")))
11095 (if (listp ev) (setq fmt nil ev "#ERROR"))
11096 (org-table-justify-field-maybe
11097 (if fmt (format fmt (string-to-number ev)) ev))
11098 (if (and down (> ndown 0) (looking-at ".*\n[ \t]*|[^-]"))
11099 (call-interactively 'org-return)
11100 (setq ndown 0)))
11101 (and down (org-table-maybe-recalculate-line))
11102 (or suppress-align (and org-table-may-need-update
11103 (org-table-align)))))
11104
11105 (defun org-table-recalculate (&optional all noalign)
11106 "Recalculate the current table line by applying all stored formulas.
11107 With prefix arg ALL, do this for all lines in the table."
11108 (interactive "P")
11109 (or (memq this-command org-recalc-commands)
11110 (setq org-recalc-commands (cons this-command org-recalc-commands)))
11111 (unless (org-at-table-p) (error "Not at a table"))
11112 (org-table-get-specials)
11113 (let* ((eqlist (sort (org-table-get-stored-formulas)
11114 (lambda (a b) (string< (car a) (car b)))))
11115 (inhibit-redisplay t)
11116 (line-re org-table-dataline-regexp)
11117 (thisline (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
11118 (thiscol (org-table-current-column))
11119 beg end entry eqlnum eqlname eql (cnt 0) eq a name)
11120 ;; Insert constants in all formulas
11121 (setq eqlist
11122 (mapcar (lambda (x)
11123 (setcdr x (org-table-formula-substitute-names (cdr x)))
11124 x)
11125 eqlist))
11126 ;; Split the equation list
11127 (while (setq eq (pop eqlist))
11128 (if (<= (string-to-char (car eq)) ?9)
11129 (push eq eqlnum)
11130 (push eq eqlname)))
11131 (setq eqlnum (nreverse eqlnum) eqlname (nreverse eqlname))
11132 (if all
11133 (progn
11134 (setq end (move-marker (make-marker) (1+ (org-table-end))))
11135 (goto-char (setq beg (org-table-begin)))
11136 (if (re-search-forward org-table-calculate-mark-regexp end t)
11137 ;; This is a table with marked lines, only compute selected lines
11138 (setq line-re org-table-recalculate-regexp)
11139 ;; Move forward to the first non-header line
11140 (if (and (re-search-forward org-table-dataline-regexp end t)
11141 (re-search-forward org-table-hline-regexp end t)
11142 (re-search-forward org-table-dataline-regexp end t))
11143 (setq beg (match-beginning 0))
11144 nil))) ;; just leave beg where it is
11145 (setq beg (point-at-bol)
11146 end (move-marker (make-marker) (1+ (point-at-eol)))))
11147 (goto-char beg)
11148 (and all (message "Re-applying formulas to full table..."))
11149 (while (re-search-forward line-re end t)
11150 (unless (string-match "^ *[_^!$] *$" (org-table-get-field 1))
11151 ;; Unprotected line, recalculate
11152 (and all (message "Re-applying formulas to full table...(line %d)"
11153 (setq cnt (1+ cnt))))
11154 (setq org-last-recalc-line (org-current-line))
11155 (setq eql eqlnum)
11156 (while (setq entry (pop eql))
11157 (goto-line org-last-recalc-line)
11158 (org-table-goto-column (string-to-number (car entry)) nil 'force)
11159 (org-table-eval-formula nil (cdr entry) 'noalign 'nocst 'nostore))))
11160 (goto-line thisline)
11161 (org-table-goto-column thiscol)
11162 (or noalign (and org-table-may-need-update (org-table-align))
11163 (and all (message "Re-applying formulas to %d lines...done" cnt)))
11164 ;; Now do the names fields
11165 (while (setq eq (pop eqlname))
11166 (setq name (car eq)
11167 a (assoc name org-table-named-field-locations))
11168 (when a
11169 (message "Re-applying formula to named field: %s" name)
11170 (goto-line (nth 1 a))
11171 (org-table-goto-column (nth 2 a))
11172 (org-table-eval-formula nil (cdr eq) 'noalign 'nocst 'nostore)))
11173 ;; back to initial position
11174 (goto-line thisline)
11175 (org-table-goto-column thiscol)
11176 (or noalign (and org-table-may-need-update (org-table-align))
11177 (and all (message "Re-applying formulas...done")))))
11178
11179 (defun org-table-formula-substitute-names (f)
11180 "Replace $const with values in string F."
11181 (let ((start 0) a n1 n2 nn1 nn2 s (f1 f))
11182 ;; First, check for column names
11183 (while (setq start (string-match org-table-column-name-regexp f start))
11184 (setq start (1+ start))
11185 (setq a (assoc (match-string 1 f) org-table-column-names))
11186 (setq f (replace-match (concat "$" (cdr a)) t t f)))
11187 ;; Expand ranges to vectors
11188 (while (string-match "\\$\\([0-9]+\\)\\.\\.\\.?\\$\\([0-9]+\\)" f)
11189 (setq n1 (string-to-number (match-string 1 f))
11190 n2 (string-to-number (match-string 2 f))
11191 nn1 (1+ (min n1 n2)) nn2 (max n1 n2)
11192 s (concat "[($" (number-to-string (1- nn1)) ")"))
11193 (loop for i from nn1 upto nn2 do
11194 (setq s (concat s ",($" (int-to-string i) ")")))
11195 (setq s (concat s "]"))
11196 (if (< n2 n1) (setq s (concat "rev(" s ")")))
11197 (setq f (replace-match s t t f)))
11198 ;; Parameters and constants
11199 (setq start 0)
11200 (while (setq start (string-match "\\$\\([a-zA-Z][a-zA-Z0-9]*\\)" f start))
11201 (setq start (1+ start))
11202 (if (setq a (save-match-data
11203 (org-table-get-constant (match-string 1 f))))
11204 (setq f (replace-match (concat "(" a ")") t t f))))
11205 (if org-table-formula-debug
11206 (put-text-property 0 (length f) :orig-formula f1 f))
11207 f))
11208
11209 (defun org-table-get-constant (const)
11210 "Find the value for a parameter or constant in a formula.
11211 Parameters get priority."
11212 (or (cdr (assoc const org-table-local-parameters))
11213 (cdr (assoc const org-table-formula-constants))
11214 (and (fboundp 'constants-get) (constants-get const))
11215 "#UNDEFINED_NAME"))
11216
11217 (defvar org-edit-formulas-map (make-sparse-keymap))
11218 (define-key org-edit-formulas-map "\C-c\C-c" 'org-finish-edit-formulas)
11219 (define-key org-edit-formulas-map "\C-c\C-q" 'org-abort-edit-formulas)
11220 (define-key org-edit-formulas-map "\C-c?" 'org-show-variable)
11221
11222 (defvar org-pos)
11223
11224 (defun org-table-edit-formulas ()
11225 "Edit the formulas of the current table in a separate buffer."
11226 (interactive)
11227 (unless (org-at-table-p)
11228 (error "Not at a table"))
11229 (org-table-get-specials)
11230 (let ((eql (org-table-get-stored-formulas))
11231 (pos (move-marker (make-marker) (point)))
11232 (wc (current-window-configuration))
11233 entry loc s)
11234 (switch-to-buffer-other-window "*Edit Formulas*")
11235 (erase-buffer)
11236 (fundamental-mode)
11237 (set (make-local-variable 'org-pos) pos)
11238 (set (make-local-variable 'org-window-configuration) wc)
11239 (use-local-map org-edit-formulas-map)
11240 (setq s "# Edit formulas and finish with `C-c C-c'.
11241 # Use `C-u C-c C-c' to also appy them immediately to the entire table.
11242 # Use `C-c ?' to get information about $name at point.
11243 # To cancel editing, press `C-c C-q'.\n")
11244 (put-text-property 0 (length s) 'face 'font-lock-comment-face s)
11245 (insert s)
11246 (while (setq entry (pop eql))
11247 (when (setq loc (assoc (car entry) org-table-named-field-locations))
11248 (setq s (format "# Named formula, referring to column %d in line %d\n"
11249 (nth 2 loc) (nth 1 loc)))
11250 (put-text-property 0 (length s) 'face 'font-lock-comment-face s)
11251 (insert s))
11252 (setq s (concat "$" (car entry) "=" (cdr entry) "\n"))
11253 (remove-text-properties 0 (length s) '(face nil) s)
11254 (insert s))
11255 (goto-char (point-min))
11256 (message "Edit formulas and finish with `C-c C-c'.")))
11257
11258 (defun org-show-variable ()
11259 "Show the location/value of the $ expression at point."
11260 (interactive)
11261 (let (var (pos org-pos) (win (selected-window)) e)
11262 (save-excursion
11263 (or (looking-at "\\$") (skip-chars-backward "$a-zA-Z0-9"))
11264 (if (looking-at "\\$\\([a-zA-Z0-9]+\\)")
11265 (setq var (match-string 1))
11266 (error "No variable at point")))
11267 (cond
11268 ((setq e (assoc var org-table-named-field-locations))
11269 (switch-to-buffer-other-window (marker-buffer pos))
11270 (goto-line (nth 1 e))
11271 (org-table-goto-column (nth 2 e))
11272 (select-window win)
11273 (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e)))
11274 ((setq e (assoc var org-table-column-names))
11275 (switch-to-buffer-other-window (marker-buffer pos))
11276 (goto-char pos)
11277 (goto-char (org-table-begin))
11278 (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|")
11279 (org-table-end) t)
11280 (progn
11281 (goto-char (match-beginning 1))
11282 (message "Named column (column %s)" (cdr e)))
11283 (error "Column name not found"))
11284 (select-window win))
11285 ((string-match "^[0-9]$" var)
11286 ;; column number
11287 (switch-to-buffer-other-window (marker-buffer pos))
11288 (goto-char pos)
11289 (goto-char (org-table-begin))
11290 (recenter 1)
11291 (if (re-search-forward org-table-dataline-regexp
11292 (org-table-end) t)
11293 (progn
11294 (goto-char (match-beginning 0))
11295 (org-table-goto-column (string-to-number var))
11296 (message "Column %s" var))
11297 (error "Column name not found"))
11298 (select-window win))
11299 ((setq e (assoc var org-table-local-parameters))
11300 (switch-to-buffer-other-window (marker-buffer pos))
11301 (goto-char pos)
11302 (goto-char (org-table-begin))
11303 (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") nil t)
11304 (progn
11305 (goto-char (match-beginning 1))
11306 (message "Local parameter."))
11307 (error "Parameter not found"))
11308 (select-window win))
11309 (t
11310 (cond
11311 ((setq e (assoc var org-table-formula-constants))
11312 (message "Constant: $%s=%s in `org-table-formula-constants'." var (cdr e)))
11313 ((setq e (and (fboundp 'constants-get) (constants-get var)))
11314 (message "Constant: $%s=%s, retrieved from `constants.el'." var e))
11315 (t (error "Undefined name $%s" var)))))))
11316
11317 (defun org-finish-edit-formulas (&optional arg)
11318 "Parse the buffer for formula definitions and install them.
11319 With prefix ARG, apply the new formulas to the table."
11320 (interactive "P")
11321 (let ((pos org-pos) eql)
11322 (goto-char (point-min))
11323 (while (re-search-forward "^\\$\\([a-zA-Z0-9]+\\) *= *\\(.*?\\) *$" nil t)
11324 (push (cons (match-string 1) (match-string 2)) eql))
11325 (set-window-configuration org-window-configuration)
11326 (select-window (get-buffer-window (marker-buffer pos)))
11327 (goto-char pos)
11328 (unless (org-at-table-p)
11329 (error "Lost table position - cannot install formulae"))
11330 (org-table-store-formulas eql)
11331 (move-marker pos nil)
11332 (kill-buffer "*Edit Formulas*")
11333 (if arg
11334 (org-table-recalculate 'all)
11335 (message "New formulas installed - press C-u C-c C-c to apply."))))
11336
11337 (defun org-abort-edit-formulas ()
11338 "Abort editing formulas, without installing the changes."
11339 (interactive)
11340 (let ((pos org-pos))
11341 (set-window-configuration org-window-configuration)
11342 (select-window (get-buffer-window (marker-buffer pos)))
11343 (goto-char pos)
11344 (message "Formula editing aborted without installing changes")))
11345
11346 ;;; The orgtbl minor mode
11347
11348 ;; Define a minor mode which can be used in other modes in order to
11349 ;; integrate the org-mode table editor.
11350
11351 ;; This is really a hack, because the org-mode table editor uses several
11352 ;; keys which normally belong to the major mode, for example the TAB and
11353 ;; RET keys. Here is how it works: The minor mode defines all the keys
11354 ;; necessary to operate the table editor, but wraps the commands into a
11355 ;; function which tests if the cursor is currently inside a table. If that
11356 ;; is the case, the table editor command is executed. However, when any of
11357 ;; those keys is used outside a table, the function uses `key-binding' to
11358 ;; look up if the key has an associated command in another currently active
11359 ;; keymap (minor modes, major mode, global), and executes that command.
11360 ;; There might be problems if any of the keys used by the table editor is
11361 ;; otherwise used as a prefix key.
11362
11363 ;; Another challenge is that the key binding for TAB can be tab or \C-i,
11364 ;; likewise the binding for RET can be return or \C-m. Orgtbl-mode
11365 ;; addresses this by checking explicitly for both bindings.
11366
11367 ;; The optimized version (see variable `orgtbl-optimized') takes over
11368 ;; all keys which are bound to `self-insert-command' in the *global map*.
11369 ;; Some modes bind other commands to simple characters, for example
11370 ;; AUCTeX binds the double quote to `Tex-insert-quote'. With orgtbl-mode
11371 ;; active, this binding is ignored inside tables and replaced with a
11372 ;; modified self-insert.
11373
11374 (defvar orgtbl-mode nil
11375 "Variable controlling `orgtbl-mode', a minor mode enabling the `org-mode'
11376 table editor in arbitrary modes.")
11377 (make-variable-buffer-local 'orgtbl-mode)
11378
11379 (defvar orgtbl-mode-map (make-keymap)
11380 "Keymap for `orgtbl-mode'.")
11381
11382 ;;;###autoload
11383 (defun turn-on-orgtbl ()
11384 "Unconditionally turn on `orgtbl-mode'."
11385 (orgtbl-mode 1))
11386
11387 ;;;###autoload
11388 (defun orgtbl-mode (&optional arg)
11389 "The `org-mode' table editor as a minor mode for use in other modes."
11390 (interactive)
11391 (if (eq major-mode 'org-mode)
11392 ;; Exit without error, in case some hook functions calls this
11393 ;; by accident in org-mode.
11394 (message "Orgtbl-mode is not useful in org-mode, command ignored")
11395 (setq orgtbl-mode
11396 (if arg (> (prefix-numeric-value arg) 0) (not orgtbl-mode)))
11397 (if orgtbl-mode
11398 (progn
11399 (and (orgtbl-setup) (defun orgtbl-setup () nil))
11400 ;; Make sure we are first in minor-mode-map-alist
11401 (let ((c (assq 'orgtbl-mode minor-mode-map-alist)))
11402 (and c (setq minor-mode-map-alist
11403 (cons c (delq c minor-mode-map-alist)))))
11404 (set (make-local-variable (quote org-table-may-need-update)) t)
11405 (org-add-hook 'before-change-functions 'org-before-change-function
11406 nil 'local)
11407 (set (make-local-variable 'org-old-auto-fill-inhibit-regexp)
11408 auto-fill-inhibit-regexp)
11409 (set (make-local-variable 'auto-fill-inhibit-regexp)
11410 (if auto-fill-inhibit-regexp
11411 (concat "\\([ \t]*|\\|" auto-fill-inhibit-regexp)
11412 "[ \t]*|"))
11413 (org-add-to-invisibility-spec '(org-cwidth))
11414 (easy-menu-add orgtbl-mode-menu)
11415 (run-hooks 'orgtbl-mode-hook))
11416 (setq auto-fill-inhibit-regexp org-old-auto-fill-inhibit-regexp)
11417 (org-cleanup-narrow-column-properties)
11418 (org-remove-from-invisibility-spec '(org-cwidth))
11419 (remove-hook 'before-change-functions 'org-before-change-function t)
11420 (easy-menu-remove orgtbl-mode-menu)
11421 (force-mode-line-update 'all))))
11422
11423 (defun org-cleanup-narrow-column-properties ()
11424 "Remove all properties related to narrow-column invisibility."
11425 (let ((s 1))
11426 (while (setq s (text-property-any s (point-max)
11427 'display org-narrow-column-arrow))
11428 (remove-text-properties s (1+ s) '(display t)))
11429 (setq s 1)
11430 (while (setq s (text-property-any s (point-max) 'org-cwidth 1))
11431 (remove-text-properties s (1+ s) '(org-cwidth t)))
11432 (setq s 1)
11433 (while (setq s (text-property-any s (point-max) 'invisible 'org-cwidth))
11434 (remove-text-properties s (1+ s) '(invisible t)))))
11435
11436 ;; Install it as a minor mode.
11437 (put 'orgtbl-mode :included t)
11438 (put 'orgtbl-mode :menu-tag "Org Table Mode")
11439 (add-minor-mode 'orgtbl-mode " OrgTbl" orgtbl-mode-map)
11440
11441 (defun orgtbl-make-binding (fun n &rest keys)
11442 "Create a function for binding in the table minor mode.
11443 FUN is the command to call inside a table. N is used to create a unique
11444 command name. KEYS are keys that should be checked in for a command
11445 to execute outside of tables."
11446 (eval
11447 (list 'defun
11448 (intern (concat "orgtbl-hijacker-command-" (int-to-string n)))
11449 '(arg)
11450 (concat "In tables, run `" (symbol-name fun) "'.\n"
11451 "Outside of tables, run the binding of `"
11452 (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
11453 "'.")
11454 '(interactive "p")
11455 (list 'if
11456 '(org-at-table-p)
11457 (list 'call-interactively (list 'quote fun))
11458 (list 'let '(orgtbl-mode)
11459 (list 'call-interactively
11460 (append '(or)
11461 (mapcar (lambda (k)
11462 (list 'key-binding k))
11463 keys)
11464 '('orgtbl-error))))))))
11465
11466 (defun orgtbl-error ()
11467 "Error when there is no default binding for a table key."
11468 (interactive)
11469 (error "This key is has no function outside tables"))
11470
11471 (defun orgtbl-setup ()
11472 "Setup orgtbl keymaps."
11473 (let ((nfunc 0)
11474 (bindings
11475 (list
11476 '([(meta shift left)] org-table-delete-column)
11477 '([(meta left)] org-table-move-column-left)
11478 '([(meta right)] org-table-move-column-right)
11479 '([(meta shift right)] org-table-insert-column)
11480 '([(meta shift up)] org-table-kill-row)
11481 '([(meta shift down)] org-table-insert-row)
11482 '([(meta up)] org-table-move-row-up)
11483 '([(meta down)] org-table-move-row-down)
11484 '("\C-c\C-w" org-table-cut-region)
11485 '("\C-c\M-w" org-table-copy-region)
11486 '("\C-c\C-y" org-table-paste-rectangle)
11487 '("\C-c-" org-table-insert-hline)
11488 ; '([(shift tab)] org-table-previous-field)
11489 '("\C-m" org-table-next-row)
11490 (list (org-key 'S-return) 'org-table-copy-down)
11491 '([(meta return)] org-table-wrap-region)
11492 '("\C-c\C-q" org-table-wrap-region)
11493 '("\C-c?" org-table-current-column)
11494 '("\C-c " org-table-blank-field)
11495 '("\C-c+" org-table-sum)
11496 '("\C-c=" org-table-eval-formula)
11497 '("\C-c'" org-table-edit-formulas)
11498 '("\C-c`" org-table-edit-field)
11499 '("\C-c*" org-table-recalculate)
11500 '("\C-c|" org-table-create-or-convert-from-region)
11501 '("\C-c^" org-table-sort-lines)
11502 '([(control ?#)] org-table-rotate-recalc-marks)))
11503 elt key fun cmd)
11504 (while (setq elt (pop bindings))
11505 (setq nfunc (1+ nfunc))
11506 (setq key (car elt)
11507 fun (nth 1 elt)
11508 cmd (orgtbl-make-binding fun nfunc key))
11509 (define-key orgtbl-mode-map key cmd))
11510 ;; Special treatment needed for TAB and RET
11511 (define-key orgtbl-mode-map [(return)]
11512 (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m"))
11513 (define-key orgtbl-mode-map "\C-m"
11514 (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)]))
11515 (define-key orgtbl-mode-map [(tab)]
11516 (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i"))
11517 (define-key orgtbl-mode-map "\C-i"
11518 (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)])))
11519 (define-key orgtbl-mode-map "\C-i"
11520 (orgtbl-make-binding 'orgtbl-tab 104 [(shift tab)]))
11521 (define-key orgtbl-mode-map "\C-c\C-c"
11522 (orgtbl-make-binding 'org-ctrl-c-ctrl-c 105 "\C-c\C-c"))
11523 (when orgtbl-optimized
11524 ;; If the user wants maximum table support, we need to hijack
11525 ;; some standard editing functions
11526 (org-remap orgtbl-mode-map
11527 'self-insert-command 'orgtbl-self-insert-command
11528 'delete-char 'org-delete-char
11529 'delete-backward-char 'org-delete-backward-char)
11530 (define-key orgtbl-mode-map "|" 'org-force-self-insert))
11531 (easy-menu-define orgtbl-mode-menu orgtbl-mode-map "OrgTbl menu"
11532 '("OrgTbl"
11533 ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p) :keys "C-c C-c"]
11534 ["Next Field" org-cycle :active (org-at-table-p) :keys "TAB"]
11535 ["Previous Field" org-shifttab :active (org-at-table-p) :keys "S-TAB"]
11536 ["Next Row" org-return :active (org-at-table-p) :keys "RET"]
11537 "--"
11538 ["Blank Field" org-table-blank-field :active (org-at-table-p) :keys "C-c SPC"]
11539 ["Edit Field" org-table-edit-field :active (org-at-table-p) :keys "C-c ` "]
11540 ["Copy Field from Above"
11541 org-table-copy-down :active (org-at-table-p) :keys "S-RET"]
11542 "--"
11543 ("Column"
11544 ["Move Column Left" org-metaleft :active (org-at-table-p) :keys "M-<left>"]
11545 ["Move Column Right" org-metaright :active (org-at-table-p) :keys "M-<right>"]
11546 ["Delete Column" org-shiftmetaleft :active (org-at-table-p) :keys "M-S-<left>"]
11547 ["Insert Column" org-shiftmetaright :active (org-at-table-p) :keys "M-S-<right>"]
11548 "--"
11549 ["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])
11550 ("Row"
11551 ["Move Row Up" org-metaup :active (org-at-table-p) :keys "M-<up>"]
11552 ["Move Row Down" org-metadown :active (org-at-table-p) :keys "M-<down>"]
11553 ["Delete Row" org-shiftmetaup :active (org-at-table-p) :keys "M-S-<up>"]
11554 ["Insert Row" org-shiftmetadown :active (org-at-table-p) :keys "M-S-<down>"]
11555 ["Sort lines in region" org-table-sort-lines (org-at-table-p) :keys "C-c ^"]
11556 "--"
11557 ["Insert Hline" org-table-insert-hline :active (org-at-table-p) :keys "C-c -"])
11558 ("Rectangle"
11559 ["Copy Rectangle" org-copy-special :active (org-at-table-p)]
11560 ["Cut Rectangle" org-cut-special :active (org-at-table-p)]
11561 ["Paste Rectangle" org-paste-special :active (org-at-table-p)]
11562 ["Fill Rectangle" org-table-wrap-region :active (org-at-table-p)])
11563 "--"
11564 ["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="]
11565 ["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
11566 ["Edit Formulas" org-table-edit-formulas :active (org-at-table-p) :keys "C-c '"]
11567 ["Recalculate line" org-table-recalculate :active (org-at-table-p) :keys "C-c *"]
11568 ["Recalculate all" (org-table-recalculate '(4)) :active (org-at-table-p) :keys "C-u C-c *"]
11569 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks :active (org-at-table-p) :keys "C-c #"]
11570 ["Sum Column/Rectangle" org-table-sum
11571 :active (or (org-at-table-p) (org-region-active-p)) :keys "C-c +"]
11572 ["Which Column?" org-table-current-column :active (org-at-table-p) :keys "C-c ?"]
11573 ["Debug Formulas"
11574 (setq org-table-formula-debug (not org-table-formula-debug))
11575 :style toggle :selected org-table-formula-debug]
11576 ))
11577 t)
11578
11579 (defun orgtbl-tab (arg)
11580 "Justification and field motion for `orgtbl-mode'."
11581 (interactive "P")
11582 (if arg (org-table-edit-field t)
11583 (org-table-justify-field-maybe)
11584 (org-table-next-field)))
11585
11586 (defun orgtbl-ret ()
11587 "Justification and field motion for `orgtbl-mode'."
11588 (interactive)
11589 (org-table-justify-field-maybe)
11590 (org-table-next-row))
11591
11592 (defun orgtbl-self-insert-command (N)
11593 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
11594 If the cursor is in a table looking at whitespace, the whitespace is
11595 overwritten, and the table is not marked as requiring realignment."
11596 (interactive "p")
11597 (if (and (org-at-table-p)
11598 (or
11599 (and org-table-auto-blank-field
11600 (member last-command
11601 '(orgtbl-hijacker-command-100
11602 orgtbl-hijacker-command-101
11603 orgtbl-hijacker-command-102
11604 orgtbl-hijacker-command-103
11605 orgtbl-hijacker-command-104
11606 orgtbl-hijacker-command-105))
11607 (org-table-blank-field))
11608 t)
11609 (eq N 1)
11610 (looking-at "[^|\n]* +|"))
11611 (let (org-table-may-need-update)
11612 (goto-char (1- (match-end 0)))
11613 (delete-backward-char 1)
11614 (goto-char (match-beginning 0))
11615 (self-insert-command N))
11616 (setq org-table-may-need-update t)
11617 (let (orgtbl-mode)
11618 (call-interactively (key-binding (vector last-input-event))))))
11619
11620 (defun org-force-self-insert (N)
11621 "Needed to enforce self-insert under remapping."
11622 (interactive "p")
11623 (self-insert-command N))
11624
11625 ;;; Exporting
11626
11627 (defconst org-level-max 20)
11628
11629 (defvar org-export-html-preamble nil
11630 "Preamble, to be inserted just after <body>. Set by publishing functions.")
11631 (defvar org-export-html-postamble nil
11632 "Preamble, to be inserted just before </body>. Set by publishing functions.")
11633 (defvar org-export-html-auto-preamble t
11634 "Should default preamble be inserted? Set by publishing functions.")
11635 (defvar org-export-html-auto-postamble t
11636 "Should default postamble be inserted? Set by publishing functions.")
11637
11638 (defconst org-export-plist-vars
11639 '((:language . org-export-default-language)
11640 (:headline-levels . org-export-headline-levels)
11641 (:section-numbers . org-export-with-section-numbers)
11642 (:table-of-contents . org-export-with-toc)
11643 (:emphasize . org-export-with-emphasize)
11644 (:sub-superscript . org-export-with-sub-superscripts)
11645 (:TeX-macros . org-export-with-TeX-macros)
11646 (:fixed-width . org-export-with-fixed-width)
11647 (:timestamps . org-export-with-timestamps)
11648 (:tables . org-export-with-tables)
11649 (:table-auto-headline . org-export-highlight-first-table-line)
11650 (:style . org-export-html-style)
11651 (:convert-org-links . org-export-html-link-org-files-as-html)
11652 (:inline-images . org-export-html-inline-images)
11653 (:expand-quoted-html . org-export-html-expand)
11654 (:timestamp . org-export-html-with-timestamp)
11655 (:publishing-directory . org-export-publishing-directory)
11656 (:preamble . org-export-html-preamble)
11657 (:postamble . org-export-html-postamble)
11658 (:auto-preamble . org-export-html-auto-preamble)
11659 (:auto-postamble . org-export-html-auto-postamble)
11660 (:author . user-full-name)
11661 (:email . user-mail-address)))
11662
11663 (defun org-default-export-plist ()
11664 "Return the property list with default settings for the export variables."
11665 (let ((l org-export-plist-vars) rtn e)
11666 (while (setq e (pop l))
11667 (setq rtn (cons (car e) (cons (symbol-value (cdr e)) rtn))))
11668 rtn))
11669
11670 (defun org-infile-export-plist ()
11671 "Return the property list with file-local settings for export."
11672 (save-excursion
11673 (goto-char 0)
11674 (let ((re (org-make-options-regexp
11675 '("TITLE" "AUTHOR" "EMAIL" "TEXT" "OPTIONS" "LANGUAGE")))
11676 (text nil)
11677 p key val text options)
11678 (while (re-search-forward re nil t)
11679 (setq key (org-match-string-no-properties 1)
11680 val (org-match-string-no-properties 2))
11681 (cond
11682 ((string-equal key "TITLE") (setq p (plist-put p :title val)))
11683 ((string-equal key "AUTHOR")(setq p (plist-put p :author val)))
11684 ((string-equal key "EMAIL") (setq p (plist-put p :email val)))
11685 ((string-equal key "LANGUAGE") (setq p (plist-put p :language val)))
11686 ((string-equal key "TEXT")
11687 (setq text (if text (concat text "\n" val) val)))
11688 ((string-equal key "OPTIONS") (setq options val))))
11689 (setq p (plist-put p :text text))
11690 (when options
11691 (let ((op '(("H" . :headline-levels)
11692 ("num" . :section-numbers)
11693 ("toc" . :table-of-contents)
11694 ("\\n" . :preserve-breaks)
11695 ("@" . :expand-quoted-html)
11696 (":" . :fixed-width)
11697 ("|" . :tables)
11698 ("^" . :sub-superscript)
11699 ("*" . :emphasize)
11700 ("TeX" . :TeX-macros)))
11701 o)
11702 (while (setq o (pop op))
11703 (if (string-match (concat (regexp-quote (car o))
11704 ":\\([^ \t\n\r;,.]*\\)")
11705 options)
11706 (setq p (plist-put p (cdr o)
11707 (car (read-from-string
11708 (match-string 1 options)))))))))
11709 p)))
11710
11711 (defun org-combine-plists (&rest plists)
11712 "Create a single property list from all plists in PLISTS.
11713 The process starts by copying the last list, and then setting properties
11714 from the other lists. Settings in the first list are the most significant
11715 ones and overrule settings in the other lists."
11716 (let ((rtn (copy-sequence (pop plists)))
11717 p v ls)
11718 (while plists
11719 (setq ls (pop plists))
11720 (while ls
11721 (setq p (pop ls) v (pop ls))
11722 (setq rtn (plist-put rtn p v))))
11723 rtn))
11724
11725 (defun org-export-directory (type plist)
11726 (let* ((val (plist-get plist :publishing-directory))
11727 (dir (if (listp val)
11728 (or (cdr (assoc type val)) ".")
11729 val)))
11730 dir))
11731
11732 (defun org-export-find-first-heading-line (list)
11733 "Remove all lines from LIST which are before the first headline."
11734 (let ((orig-list list)
11735 (re (concat "^" outline-regexp)))
11736 (while (and list
11737 (not (string-match re (car list))))
11738 (pop list))
11739 (or list orig-list)))
11740
11741 (defun org-skip-comments (lines)
11742 "Skip lines starting with \"#\" and subtrees starting with COMMENT."
11743 (let ((re1 (concat "^\\(\\*+\\)[ \t]+" org-comment-string))
11744 (re2 "^\\(\\*+\\)[ \t\n\r]")
11745 rtn line level)
11746 (while (setq line (pop lines))
11747 (cond
11748 ((and (string-match re1 line)
11749 (setq level (- (match-end 1) (match-beginning 1))))
11750 ;; Beginning of a COMMENT subtree. Skip it.
11751 (while (and (setq line (pop lines))
11752 (or (not (string-match re2 line))
11753 (> (- (match-end 1) (match-beginning 1)) level))))
11754 (setq lines (cons line lines)))
11755 ((string-match "^#" line)
11756 ;; an ordinary comment line
11757 )
11758 ((and org-export-table-remove-special-lines
11759 (string-match "^[ \t]*| *[!_^] *|" line))
11760 ;; a special table line that should be removed
11761 )
11762 (t (setq rtn (cons line rtn)))))
11763 (nreverse rtn)))
11764
11765 ;; ASCII
11766
11767 (defconst org-html-entities
11768 '(("nbsp")
11769 ("iexcl")
11770 ("cent")
11771 ("pound")
11772 ("curren")
11773 ("yen")
11774 ("brvbar")
11775 ("sect")
11776 ("uml")
11777 ("copy")
11778 ("ordf")
11779 ("laquo")
11780 ("not")
11781 ("shy")
11782 ("reg")
11783 ("macr")
11784 ("deg")
11785 ("plusmn")
11786 ("sup2")
11787 ("sup3")
11788 ("acute")
11789 ("micro")
11790 ("para")
11791 ("middot")
11792 ("odot"."o")
11793 ("star"."*")
11794 ("cedil")
11795 ("sup1")
11796 ("ordm")
11797 ("raquo")
11798 ("frac14")
11799 ("frac12")
11800 ("frac34")
11801 ("iquest")
11802 ("Agrave")
11803 ("Aacute")
11804 ("Acirc")
11805 ("Atilde")
11806 ("Auml")
11807 ("Aring") ("AA"."&Aring;")
11808 ("AElig")
11809 ("Ccedil")
11810 ("Egrave")
11811 ("Eacute")
11812 ("Ecirc")
11813 ("Euml")
11814 ("Igrave")
11815 ("Iacute")
11816 ("Icirc")
11817 ("Iuml")
11818 ("ETH")
11819 ("Ntilde")
11820 ("Ograve")
11821 ("Oacute")
11822 ("Ocirc")
11823 ("Otilde")
11824 ("Ouml")
11825 ("times")
11826 ("Oslash")
11827 ("Ugrave")
11828 ("Uacute")
11829 ("Ucirc")
11830 ("Uuml")
11831 ("Yacute")
11832 ("THORN")
11833 ("szlig")
11834 ("agrave")
11835 ("aacute")
11836 ("acirc")
11837 ("atilde")
11838 ("auml")
11839 ("aring")
11840 ("aelig")
11841 ("ccedil")
11842 ("egrave")
11843 ("eacute")
11844 ("ecirc")
11845 ("euml")
11846 ("igrave")
11847 ("iacute")
11848 ("icirc")
11849 ("iuml")
11850 ("eth")
11851 ("ntilde")
11852 ("ograve")
11853 ("oacute")
11854 ("ocirc")
11855 ("otilde")
11856 ("ouml")
11857 ("divide")
11858 ("oslash")
11859 ("ugrave")
11860 ("uacute")
11861 ("ucirc")
11862 ("uuml")
11863 ("yacute")
11864 ("thorn")
11865 ("yuml")
11866 ("fnof")
11867 ("Alpha")
11868 ("Beta")
11869 ("Gamma")
11870 ("Delta")
11871 ("Epsilon")
11872 ("Zeta")
11873 ("Eta")
11874 ("Theta")
11875 ("Iota")
11876 ("Kappa")
11877 ("Lambda")
11878 ("Mu")
11879 ("Nu")
11880 ("Xi")
11881 ("Omicron")
11882 ("Pi")
11883 ("Rho")
11884 ("Sigma")
11885 ("Tau")
11886 ("Upsilon")
11887 ("Phi")
11888 ("Chi")
11889 ("Psi")
11890 ("Omega")
11891 ("alpha")
11892 ("beta")
11893 ("gamma")
11894 ("delta")
11895 ("epsilon")
11896 ("varepsilon"."&epsilon;")
11897 ("zeta")
11898 ("eta")
11899 ("theta")
11900 ("iota")
11901 ("kappa")
11902 ("lambda")
11903 ("mu")
11904 ("nu")
11905 ("xi")
11906 ("omicron")
11907 ("pi")
11908 ("rho")
11909 ("sigmaf") ("varsigma"."&sigmaf;")
11910 ("sigma")
11911 ("tau")
11912 ("upsilon")
11913 ("phi")
11914 ("chi")
11915 ("psi")
11916 ("omega")
11917 ("thetasym") ("vartheta"."&thetasym;")
11918 ("upsih")
11919 ("piv")
11920 ("bull") ("bullet"."&bull;")
11921 ("hellip") ("dots"."&hellip;")
11922 ("prime")
11923 ("Prime")
11924 ("oline")
11925 ("frasl")
11926 ("weierp")
11927 ("image")
11928 ("real")
11929 ("trade")
11930 ("alefsym")
11931 ("larr") ("leftarrow"."&larr;") ("gets"."&larr;")
11932 ("uarr") ("uparrow"."&uarr;")
11933 ("rarr") ("to"."&rarr;") ("rightarrow"."&rarr;")
11934 ("darr")("downarrow"."&darr;")
11935 ("harr") ("leftrightarrow"."&harr;")
11936 ("crarr") ("hookleftarrow"."&crarr;") ; has round hook, not quite CR
11937 ("lArr") ("Leftarrow"."&lArr;")
11938 ("uArr") ("Uparrow"."&uArr;")
11939 ("rArr") ("Rightarrow"."&rArr;")
11940 ("dArr") ("Downarrow"."&dArr;")
11941 ("hArr") ("Leftrightarrow"."&hArr;")
11942 ("forall")
11943 ("part") ("partial"."&part;")
11944 ("exist") ("exists"."&exist;")
11945 ("empty") ("emptyset"."&empty;")
11946 ("nabla")
11947 ("isin") ("in"."&isin;")
11948 ("notin")
11949 ("ni")
11950 ("prod")
11951 ("sum")
11952 ("minus")
11953 ("lowast") ("ast"."&lowast;")
11954 ("radic")
11955 ("prop") ("proptp"."&prop;")
11956 ("infin") ("infty"."&infin;")
11957 ("ang") ("angle"."&ang;")
11958 ("and") ("vee"."&and;")
11959 ("or") ("wedge"."&or;")
11960 ("cap")
11961 ("cup")
11962 ("int")
11963 ("there4")
11964 ("sim")
11965 ("cong") ("simeq"."&cong;")
11966 ("asymp")("approx"."&asymp;")
11967 ("ne") ("neq"."&ne;")
11968 ("equiv")
11969 ("le")
11970 ("ge")
11971 ("sub") ("subset"."&sub;")
11972 ("sup") ("supset"."&sup;")
11973 ("nsub")
11974 ("sube")
11975 ("supe")
11976 ("oplus")
11977 ("otimes")
11978 ("perp")
11979 ("sdot") ("cdot"."&sdot;")
11980 ("lceil")
11981 ("rceil")
11982 ("lfloor")
11983 ("rfloor")
11984 ("lang")
11985 ("rang")
11986 ("loz") ("Diamond"."&loz;")
11987 ("spades") ("spadesuit"."&spades;")
11988 ("clubs") ("clubsuit"."&clubs;")
11989 ("hearts") ("diamondsuit"."&hearts;")
11990 ("diams") ("diamondsuit"."&diams;")
11991 ("quot")
11992 ("amp")
11993 ("lt")
11994 ("gt")
11995 ("OElig")
11996 ("oelig")
11997 ("Scaron")
11998 ("scaron")
11999 ("Yuml")
12000 ("circ")
12001 ("tilde")
12002 ("ensp")
12003 ("emsp")
12004 ("thinsp")
12005 ("zwnj")
12006 ("zwj")
12007 ("lrm")
12008 ("rlm")
12009 ("ndash")
12010 ("mdash")
12011 ("lsquo")
12012 ("rsquo")
12013 ("sbquo")
12014 ("ldquo")
12015 ("rdquo")
12016 ("bdquo")
12017 ("dagger")
12018 ("Dagger")
12019 ("permil")
12020 ("lsaquo")
12021 ("rsaquo")
12022 ("euro")
12023
12024 ("arccos"."arccos")
12025 ("arcsin"."arcsin")
12026 ("arctan"."arctan")
12027 ("arg"."arg")
12028 ("cos"."cos")
12029 ("cosh"."cosh")
12030 ("cot"."cot")
12031 ("coth"."coth")
12032 ("csc"."csc")
12033 ("deg"."deg")
12034 ("det"."det")
12035 ("dim"."dim")
12036 ("exp"."exp")
12037 ("gcd"."gcd")
12038 ("hom"."hom")
12039 ("inf"."inf")
12040 ("ker"."ker")
12041 ("lg"."lg")
12042 ("lim"."lim")
12043 ("liminf"."liminf")
12044 ("limsup"."limsup")
12045 ("ln"."ln")
12046 ("log"."log")
12047 ("max"."max")
12048 ("min"."min")
12049 ("Pr"."Pr")
12050 ("sec"."sec")
12051 ("sin"."sin")
12052 ("sinh"."sinh")
12053 ("sup"."sup")
12054 ("tan"."tan")
12055 ("tanh"."tanh")
12056 )
12057 "Entities for TeX->HTML translation.
12058 Entries can be like (\"ent\"), in which case \"\\ent\" will be translated to
12059 \"&ent;\". An entry can also be a dotted pair like (\"ent\".\"&other;\").
12060 In that case, \"\\ent\" will be translated to \"&other;\".
12061 The list contains HTML entities for Latin-1, Greek and other symbols.
12062 It is supplemented by a number of commonly used TeX macros with appropriate
12063 translations. There is currently no way for users to extend this.")
12064
12065 (defun org-cleaned-string-for-export (string)
12066 "Cleanup a buffer substring so that links can be created safely."
12067 (interactive)
12068 (let* ((cb (current-buffer))
12069 (re-radio (and org-target-link-regexp
12070 (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)")))
12071 (re-plain-link (concat "\\([^[<]\\)" org-plain-link-re))
12072 (re-angle-link (concat "\\([^[]\\)" org-angle-link-re))
12073 rtn)
12074 (save-excursion
12075 (set-buffer (get-buffer-create " org-mode-tmp"))
12076 (erase-buffer)
12077 (insert string)
12078 (org-mode)
12079 ;; Find targets in comments and move them out of comments,
12080 ;; but mark them as targets that should be invisible
12081 (goto-char (point-min))
12082 (while (re-search-forward "^#.*?\\(<<<?[^>\r\n]+>>>?\\).*" nil t)
12083 (replace-match "\\1(INVISIBLE)"))
12084 ;; Find matches for radio targets and turn them into internal links
12085 (goto-char (point-min))
12086 (when re-radio
12087 (while (re-search-forward re-radio nil t)
12088 (replace-match "\\1[[\\2]]")))
12089 ;; Find all links that contain a newline and put them into a single line
12090 (goto-char (point-min))
12091 (while (re-search-forward "\\(\\(\\[\\|\\]\\)\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\(\\[\\|\\]\\)\\)" nil t)
12092 (replace-match "\\1 \\3")
12093 (goto-char (match-beginning 0)))
12094 ;; Normalize links: Convert angle and plain links into bracket links
12095 (goto-char (point-min))
12096 (while (re-search-forward re-plain-link nil t)
12097 (replace-match
12098 (concat
12099 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
12100 t t))
12101 (goto-char (point-min))
12102 (while (re-search-forward re-angle-link nil t)
12103 (replace-match
12104 (concat
12105 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
12106 t t))
12107
12108 ;; Remove comments
12109 (goto-char (point-min))
12110 (while (re-search-forward "^#.*\n?" nil t)
12111 (replace-match ""))
12112 (setq rtn (buffer-string)))
12113 (kill-buffer " org-mode-tmp")
12114 rtn))
12115
12116 (defun org-solidify-link-text (s &optional alist)
12117 "Take link text and make a safe target out of it."
12118 (save-match-data
12119 (let* ((rtn
12120 (mapconcat
12121 'identity
12122 (org-split-string s "[ \t\r\n]+") "--"))
12123 (a (assoc rtn alist)))
12124 (or (cdr a) rtn))))
12125
12126 (defun org-convert-to-odd-levels ()
12127 "Convert an org-mode file with all levels allowed to one with odd levels.
12128 This will leave level 1 alone, convert level 2 to level 3, level 3 to
12129 level 5 etc."
12130 (interactive)
12131 (when (yes-or-no-p "Are you sure you want to globally change levels to odd? ")
12132 (let ((org-odd-levels-only nil) n)
12133 (save-excursion
12134 (goto-char (point-min))
12135 (while (re-search-forward "^\\*\\*+" nil t)
12136 (setq n (1- (length (match-string 0))))
12137 (while (>= (setq n (1- n)) 0)
12138 (org-demote))
12139 (end-of-line 1))))))
12140
12141
12142 (defun org-convert-to-oddeven-levels ()
12143 "Convert an org-mode file with only odd levels to one with odd and even levels.
12144 This promotes level 3 to level 2, level 5 to level 3 etc. If the file contains a
12145 section with an even level, conversion would destroy the structure of the file. An error
12146 is signaled in this case."
12147 (interactive)
12148 (goto-char (point-min))
12149 ;; First check if there are no even levels
12150 (when (re-search-forward "^\\(\\*\\*\\)+[^*]" nil t)
12151 (org-show-hierarchy-above)
12152 (error "Not all levels are odd in this file. Conversion not possible."))
12153 (when (yes-or-no-p "Are you sure you want to globally change levels to odd-even? ")
12154 (let ((org-odd-levels-only nil) n)
12155 (save-excursion
12156 (goto-char (point-min))
12157 (while (re-search-forward "^\\*\\*+" nil t)
12158 (setq n (/ (length (match-string 0)) 2))
12159 (while (>= (setq n (1- n)) 0)
12160 (org-promote))
12161 (end-of-line 1))))))
12162
12163 (defun org-tr-level (n)
12164 "Make N odd if required."
12165 (if org-odd-levels-only (1+ (/ n 2)) n))
12166
12167 (defvar org-last-level nil) ; dynamically scoped variable
12168 (defvar org-ascii-current-indentation nil) ; For communication
12169 ;; FIXME: change indentation???/
12170
12171
12172 (defun org-export-as-ascii (arg)
12173 "Export the outline as a pretty ASCII file.
12174 If there is an active region, export only the region.
12175 The prefix ARG specifies how many levels of the outline should become
12176 underlined headlines. The default is 3."
12177 (interactive "P")
12178 (setq-default org-todo-line-regexp org-todo-line-regexp)
12179 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
12180 (org-infile-export-plist)))
12181 (region
12182 (buffer-substring
12183 (if (org-region-active-p) (region-beginning) (point-min))
12184 (if (org-region-active-p) (region-end) (point-max))))
12185 (lines (org-export-find-first-heading-line
12186 (org-skip-comments
12187 (org-split-string
12188 (org-cleaned-string-for-export region)
12189 "[\r\n]"))))
12190 (org-ascii-current-indentation "")
12191 (org-startup-with-deadline-check nil)
12192 (level 0) line txt
12193 (umax nil)
12194 (case-fold-search nil)
12195 (filename (concat (file-name-as-directory
12196 (org-export-directory :ascii opt-plist))
12197 (file-name-sans-extension
12198 (file-name-nondirectory buffer-file-name))
12199 ".txt"))
12200 (buffer (find-file-noselect filename))
12201 (levels-open (make-vector org-level-max nil))
12202 (odd org-odd-levels-only)
12203 (date (format-time-string "%Y/%m/%d" (current-time)))
12204 (time (format-time-string "%X" (org-current-time)))
12205 (author (plist-get opt-plist :author))
12206 (title (or (plist-get opt-plist :title)
12207 (file-name-sans-extension
12208 (file-name-nondirectory buffer-file-name))))
12209 (options nil)
12210 (email (plist-get opt-plist :email))
12211 (language (plist-get opt-plist :language))
12212 (text nil)
12213 (todo nil)
12214 (lang-words nil))
12215
12216 (setq org-last-level 1)
12217 (org-init-section-numbers)
12218
12219 (find-file-noselect filename)
12220
12221 (setq lang-words (or (assoc language org-export-language-setup)
12222 (assoc "en" org-export-language-setup)))
12223 (if org-export-ascii-show-new-buffer
12224 (switch-to-buffer-other-window buffer)
12225 (set-buffer buffer))
12226 (erase-buffer)
12227 (fundamental-mode)
12228 ;; create local variables for all options, to make sure all called
12229 ;; functions get the correct information
12230 (mapcar (lambda (x)
12231 (set (make-local-variable (cdr x))
12232 (plist-get opt-plist (car x))))
12233 org-export-plist-vars)
12234 (set (make-local-variable 'org-odd-levels-only) odd)
12235 (setq umax (if arg (prefix-numeric-value arg)
12236 org-export-headline-levels))
12237
12238 ;; File header
12239 (if title (org-insert-centered title ?=))
12240 (insert "\n")
12241 (if (or author email)
12242 (insert (concat (nth 1 lang-words) ": " (or author "")
12243 (if email (concat " <" email ">") "")
12244 "\n")))
12245 (if (and date time)
12246 (insert (concat (nth 2 lang-words) ": " date " " time "\n")))
12247 (if text (insert (concat (org-html-expand-for-ascii text) "\n\n")))
12248
12249 (insert "\n\n")
12250
12251 (if org-export-with-toc
12252 (progn
12253 (insert (nth 3 lang-words) "\n"
12254 (make-string (length (nth 3 lang-words)) ?=) "\n")
12255 (mapcar '(lambda (line)
12256 (if (string-match org-todo-line-regexp
12257 line)
12258 ;; This is a headline
12259 (progn
12260 (setq level (- (match-end 1) (match-beginning 1))
12261 level (org-tr-level level)
12262 txt (match-string 3 line)
12263 todo
12264 (or (and org-export-mark-todo-in-toc
12265 (match-beginning 2)
12266 (not (equal (match-string 2 line)
12267 org-done-string)))
12268 ; TODO, not DONE
12269 (and org-export-mark-todo-in-toc
12270 (= level umax)
12271 (org-search-todo-below
12272 line lines level))))
12273 (setq txt (org-html-expand-for-ascii txt))
12274
12275 (if org-export-with-section-numbers
12276 (setq txt (concat (org-section-number level)
12277 " " txt)))
12278 (if (<= level umax)
12279 (progn
12280 (insert
12281 (make-string (* (1- level) 4) ?\ )
12282 (format (if todo "%s (*)\n" "%s\n") txt))
12283 (setq org-last-level level))
12284 ))))
12285 lines)))
12286
12287 (org-init-section-numbers)
12288 (while (setq line (pop lines))
12289 ;; Remove the quoted HTML tags.
12290 (setq line (org-html-expand-for-ascii line))
12291 ;; Remove targets
12292 (while (string-match "<<<?[^<>]*>>>?[ \t]*\n?" line)
12293 (setq line (replace-match "" t t line)))
12294 ;; Replace internal links
12295 (while (string-match org-bracket-link-regexp line)
12296 (setq line (replace-match
12297 (if (match-end 3) "[\\3]" "[\\1]")
12298 t nil line)))
12299 (cond
12300 ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line)
12301 ;; a Headline
12302 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
12303 txt (match-string 2 line))
12304 (org-ascii-level-start level txt umax lines))
12305 (t
12306 ;; FIXME: do we need to do something about the indention when items are
12307 ;; converted to lists?
12308 (insert org-ascii-current-indentation line "\n"))))
12309 (normal-mode)
12310 (save-buffer)
12311 ;; remove display and invisible chars
12312 (let (beg end s)
12313 (goto-char (point-min))
12314 (while (setq beg (next-single-property-change (point) 'display))
12315 (setq end (next-single-property-change beg 'display))
12316 (delete-region beg end)
12317 (goto-char beg)
12318 (insert "=>"))
12319 (goto-char (point-min))
12320 (while (setq beg (next-single-property-change (point) 'org-cwidth))
12321 (setq end (next-single-property-change beg 'org-cwidth))
12322 (delete-region beg end)
12323 (goto-char beg)))
12324 (goto-char (point-min))))
12325
12326 (defun org-search-todo-below (line lines level)
12327 "Search the subtree below LINE for any TODO entries."
12328 (let ((rest (cdr (memq line lines)))
12329 (re org-todo-line-regexp)
12330 line lv todo)
12331 (catch 'exit
12332 (while (setq line (pop rest))
12333 (if (string-match re line)
12334 (progn
12335 (setq lv (- (match-end 1) (match-beginning 1))
12336 todo (and (match-beginning 2)
12337 (not (equal (match-string 2 line)
12338 org-done-string))))
12339 ; TODO, not DONE
12340 (if (<= lv level) (throw 'exit nil))
12341 (if todo (throw 'exit t))))))))
12342
12343 ;; FIXME: Try to handle <b> and <i> as faces via text properties.
12344 ;; We could also implement *bold*,/italic/ and _underline_ for ASCII export
12345 (defun org-html-expand-for-ascii (line)
12346 "Handle quoted HTML for ASCII export."
12347 (if org-export-html-expand
12348 (while (string-match "@<[^<>\n]*>" line)
12349 ;; We just remove the tags for now.
12350 (setq line (replace-match "" nil nil line))))
12351 line)
12352
12353 (defun org-insert-centered (s &optional underline)
12354 "Insert the string S centered and underline it with character UNDERLINE."
12355 (let ((ind (max (/ (- 80 (string-width s)) 2) 0)))
12356 (insert (make-string ind ?\ ) s "\n")
12357 (if underline
12358 (insert (make-string ind ?\ )
12359 (make-string (string-width s) underline)
12360 "\n"))))
12361
12362 (defun org-ascii-level-start (level title umax &optional lines)
12363 "Insert a new level in ASCII export."
12364 (let (char (n (- level umax 1)) (ind 0))
12365 (if (> level umax)
12366 (progn
12367 (insert (make-string (* 2 n) ?\ )
12368 (char-to-string (nth (% n (length org-export-ascii-bullets))
12369 org-export-ascii-bullets))
12370 " " title "\n")
12371 ;; find the indentation of the next non-empty line
12372 (catch 'stop
12373 (while lines
12374 (if (string-match "^\\*" (car lines)) (throw 'stop nil))
12375 (if (string-match "^\\([ \t]*\\)\\S-" (car lines))
12376 (throw 'stop (setq ind (match-end 1))))
12377 (pop lines)))
12378 (setq org-ascii-current-indentation
12379 (make-string (max (- (* 2 (1+ n)) ind) 0) ?\ )))
12380 (if (or (not (equal (char-before) ?\n))
12381 (not (equal (char-before (1- (point))) ?\n)))
12382 (insert "\n"))
12383 (setq char (nth (- umax level) (reverse org-export-ascii-underline)))
12384 (if org-export-with-section-numbers
12385 (setq title (concat (org-section-number level) " " title)))
12386 (insert title "\n" (make-string (string-width title) char) "\n")
12387 (setq org-ascii-current-indentation ""))))
12388
12389 (defun org-export-visible (type arg)
12390 "Create a copy of the visible part of the current buffer, and export it.
12391 The copy is created in a temporary buffer and removed after use.
12392 TYPE is the final key (as a string) of the `C-c C-x' key sequence that will
12393 run the export command - in interactive use, the command prompts for this
12394 key. As a special case, if the you type SPC at the prompt, the temporary
12395 org-mode file will not be removed but presented to you so that you can
12396 continue to use it. The prefix arg ARG is passed through to the exporting
12397 command."
12398 (interactive
12399 (list (progn
12400 (message "Export visible: [a]SCII [h]tml [b]rowse HTML [x]OXO [ ]keep buffer")
12401 (char-to-string (read-char-exclusive)))
12402 current-prefix-arg))
12403 (if (not (member type '("a" "\C-a" "b" "\C-b" "h" "x" " ")))
12404 (error "Invalid export key"))
12405 (let* ((binding (key-binding (concat "\C-c\C-x" type)))
12406 (keepp (equal type " "))
12407 (file buffer-file-name)
12408 (buffer (get-buffer-create "*Org Export Visible*"))
12409 s e)
12410 (with-current-buffer buffer (erase-buffer))
12411 (save-excursion
12412 (setq s (goto-char (point-min)))
12413 (while (not (= (point) (point-max)))
12414 (goto-char (org-find-invisible))
12415 (append-to-buffer buffer s (point))
12416 (setq s (goto-char (org-find-visible))))
12417 (goto-char (point-min))
12418 (unless keepp
12419 ;; Copy all comment lines to the end, to make sure #+ settings are
12420 ;; still available for the second export step. Kind of a hack, but
12421 ;; does do the trick.
12422 (if (looking-at "#[^\r\n]*")
12423 (append-to-buffer buffer (match-beginning 0) (1+ (match-end 0))))
12424 (while (re-search-forward "[\n\r]#[^\n\r]*" nil t)
12425 (append-to-buffer buffer (1+ (match-beginning 0))
12426 (min (point-max) (1+ (match-end 0))))))
12427 (set-buffer buffer)
12428 (let ((buffer-file-name file)
12429 (org-inhibit-startup t))
12430 (org-mode)
12431 (show-all)
12432 (unless keepp (funcall binding arg))))
12433 (if (not keepp)
12434 (kill-buffer buffer)
12435 (switch-to-buffer-other-window buffer)
12436 (goto-char (point-min)))))
12437
12438 (defun org-find-visible ()
12439 (if (featurep 'noutline)
12440 (let ((s (point)))
12441 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
12442 (get-char-property s 'invisible)))
12443 s)
12444 (skip-chars-forward "^\n")
12445 (point)))
12446 (defun org-find-invisible ()
12447 (if (featurep 'noutline)
12448 (let ((s (point)))
12449 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
12450 (not (get-char-property s 'invisible))))
12451 s)
12452 (skip-chars-forward "^\r")
12453 (point)))
12454
12455 ;; HTML
12456
12457 (defun org-get-current-options ()
12458 "Return a string with current options as keyword options.
12459 Does include HTML export options as well as TODO and CATEGORY stuff."
12460 (format
12461 "#+TITLE: %s
12462 #+AUTHOR: %s
12463 #+EMAIL: %s
12464 #+LANGUAGE: %s
12465 #+TEXT: Some descriptive text to be emitted. Several lines OK.
12466 #+OPTIONS: H:%d num:%s toc:%s \\n:%s @:%s ::%s |:%s ^:%s *:%s TeX:%s
12467 #+CATEGORY: %s
12468 #+SEQ_TODO: %s
12469 #+TYP_TODO: %s
12470 #+STARTUP: %s %s %s %s %s %s
12471 #+TAGS: %s
12472 #+ARCHIVE: %s
12473 "
12474 (buffer-name) (user-full-name) user-mail-address org-export-default-language
12475 org-export-headline-levels
12476 org-export-with-section-numbers
12477 org-export-with-toc
12478 org-export-preserve-breaks
12479 org-export-html-expand
12480 org-export-with-fixed-width
12481 org-export-with-tables
12482 org-export-with-sub-superscripts
12483 org-export-with-emphasize
12484 org-export-with-TeX-macros
12485 (file-name-nondirectory buffer-file-name)
12486 (if (equal org-todo-interpretation 'sequence)
12487 (mapconcat 'identity org-todo-keywords " ")
12488 "TODO FEEDBACK VERIFY DONE")
12489 (if (equal org-todo-interpretation 'type)
12490 (mapconcat 'identity org-todo-keywords " ")
12491 "Me Jason Marie DONE")
12492 (cdr (assoc org-startup-folded
12493 '((nil . "showall") (t . "overview") (content . "content"))))
12494 (if org-startup-with-deadline-check "dlcheck" "nodlcheck")
12495 (if org-odd-levels-only "odd" "oddeven")
12496 (if org-hide-leading-stars "hidestars" "showstars")
12497 (if org-startup-align-all-tables "align" "noalign")
12498 (if org-log-done "logging" "nologging")
12499 (if org-tag-alist (mapconcat 'car org-tag-alist " ") "")
12500 org-archive-location
12501 ))
12502
12503 (defun org-insert-export-options-template ()
12504 "Insert into the buffer a template with information for exporting."
12505 (interactive)
12506 (if (not (bolp)) (newline))
12507 (let ((s (org-get-current-options)))
12508 (and (string-match "#\\+CATEGORY" s)
12509 (setq s (substring s 0 (match-beginning 0))))
12510 (insert s)))
12511
12512 (defun org-toggle-fixed-width-section (arg)
12513 "Toggle the fixed-width export.
12514 If there is no active region, the QUOTE keyword at the current headline is
12515 inserted or removed. When present, it causes the text between this headline
12516 and the next to be exported as fixed-width text, and unmodified.
12517 If there is an active region, this command adds or removes a colon as the
12518 first character of this line. If the first character of a line is a colon,
12519 this line is also exported in fixed-width font."
12520 (interactive "P")
12521 (let* ((cc 0)
12522 (regionp (org-region-active-p))
12523 (beg (if regionp (region-beginning) (point)))
12524 (end (if regionp (region-end)))
12525 (nlines (or arg (if (and beg end) (count-lines beg end) 1)))
12526 (re "[ \t]*\\(:\\)")
12527 off)
12528 (if regionp
12529 (save-excursion
12530 (goto-char beg)
12531 (setq cc (current-column))
12532 (beginning-of-line 1)
12533 (setq off (looking-at re))
12534 (while (> nlines 0)
12535 (setq nlines (1- nlines))
12536 (beginning-of-line 1)
12537 (cond
12538 (arg
12539 (move-to-column cc t)
12540 (insert ":\n")
12541 (forward-line -1))
12542 ((and off (looking-at re))
12543 (replace-match "" t t nil 1))
12544 ((not off) (move-to-column cc t) (insert ":")))
12545 (forward-line 1)))
12546 (save-excursion
12547 (org-back-to-heading)
12548 (if (looking-at (concat outline-regexp
12549 "\\( +\\<" org-quote-string "\\>\\)"))
12550 (replace-match "" t t nil 1)
12551 (if (looking-at outline-regexp)
12552 (progn
12553 (goto-char (match-end 0))
12554 (insert " " org-quote-string))))))))
12555
12556 (defun org-export-as-html-and-open (arg)
12557 "Export the outline as HTML and immediately open it with a browser.
12558 If there is an active region, export only the region.
12559 The prefix ARG specifies how many levels of the outline should become
12560 headlines. The default is 3. Lower levels will become bulleted lists."
12561 (interactive "P")
12562 (org-export-as-html arg 'hidden)
12563 (org-open-file buffer-file-name))
12564
12565 (defun org-export-as-html-batch ()
12566 "Call `org-export-as-html', may be used in batch processing as
12567 emacs --batch
12568 --load=$HOME/lib/emacs/org.el
12569 --eval \"(setq org-export-headline-levels 2)\"
12570 --visit=MyFile --funcall org-export-as-html-batch"
12571 (org-export-as-html org-export-headline-levels 'hidden))
12572
12573 (defun org-export-as-html (arg &optional hidden ext-plist)
12574 "Export the outline as a pretty HTML file.
12575 If there is an active region, export only the region.
12576 The prefix ARG specifies how many levels of the outline should become
12577 headlines. The default is 3. Lower levels will become bulleted lists.
12578 When HIDDEN is non-nil, don't display the HTML buffer.
12579 EXT-PLIST is a property list with external parameters overriding
12580 org-mode's default settings, but still inferior to file-local settings."
12581 (interactive "P")
12582 (setq-default org-todo-line-regexp org-todo-line-regexp)
12583 (setq-default org-deadline-line-regexp org-deadline-line-regexp)
12584 (setq-default org-done-string org-done-string)
12585 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
12586 ext-plist
12587 (org-infile-export-plist)))
12588
12589 (style (plist-get opt-plist :style))
12590 (odd org-odd-levels-only)
12591 (region-p (org-region-active-p))
12592 (region
12593 (buffer-substring
12594 (if region-p (region-beginning) (point-min))
12595 (if region-p (region-end) (point-max))))
12596 (all_lines
12597 (org-skip-comments (org-split-string
12598 (org-cleaned-string-for-export region)
12599 "[\r\n]")))
12600 (lines (org-export-find-first-heading-line all_lines))
12601 (level 0) (line "") (origline "") txt todo
12602 (umax nil)
12603 (filename (concat (file-name-as-directory
12604 (org-export-directory :html opt-plist))
12605 (file-name-sans-extension
12606 (file-name-nondirectory buffer-file-name))
12607 ".html"))
12608 (buffer (find-file-noselect filename))
12609 (levels-open (make-vector org-level-max nil))
12610 (date (format-time-string "%Y/%m/%d" (current-time)))
12611 (time (format-time-string "%X" (org-current-time)))
12612 (author (plist-get opt-plist :author))
12613 (title (or (plist-get opt-plist :title)
12614 (file-name-sans-extension
12615 (file-name-nondirectory buffer-file-name))))
12616 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
12617 (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
12618 (inquote nil)
12619 (infixed nil)
12620 (in-local-list nil)
12621 (local-list-num nil)
12622 (local-list-indent nil)
12623 (llt org-plain-list-ordered-item-terminator)
12624 (email (plist-get opt-plist :email))
12625 (language (plist-get opt-plist :language))
12626 (text (plist-get opt-plist :text))
12627 (lang-words nil)
12628 (target-alist nil) tg
12629 (head-count 0) cnt
12630 (start 0)
12631 ;; FIXME: The following returns always nil under XEmacs
12632 (coding-system (and (fboundp 'coding-system-get)
12633 (boundp 'buffer-file-coding-system)
12634 buffer-file-coding-system))
12635 (coding-system-for-write (or coding-system coding-system-for-write))
12636 (save-buffer-coding-system (or coding-system save-buffer-coding-system))
12637 (charset (and coding-system
12638 (coding-system-get coding-system 'mime-charset)))
12639 table-open type
12640 table-buffer table-orig-buffer
12641 ind start-is-num starter
12642 rpl path desc descp desc1 desc2 link
12643 )
12644 (message "Exporting...")
12645
12646 (setq org-last-level 1)
12647 (org-init-section-numbers)
12648
12649 ;; Get the language-dependent settings
12650 (setq lang-words (or (assoc language org-export-language-setup)
12651 (assoc "en" org-export-language-setup)))
12652
12653 ;; Switch to the output buffer
12654 (if (or hidden (not org-export-html-show-new-buffer))
12655 (set-buffer buffer)
12656 (switch-to-buffer-other-window buffer))
12657 (erase-buffer)
12658 (fundamental-mode)
12659 (let ((case-fold-search nil)
12660 (org-odd-levels-only odd))
12661 ;; create local variables for all options, to make sure all called
12662 ;; functions get the correct information
12663 (mapcar (lambda (x)
12664 (set (make-local-variable (cdr x))
12665 (plist-get opt-plist (car x))))
12666 org-export-plist-vars)
12667 (setq umax (if arg (prefix-numeric-value arg)
12668 org-export-headline-levels))
12669
12670 ;; File header
12671 (insert (format
12672 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
12673 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
12674 <html xmlns=\"http://www.w3.org/1999/xhtml\"
12675 lang=\"%s\" xml:lang=\"%s\">
12676 <head>
12677 <title>%s</title>
12678 <meta http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"/>
12679 <meta name=\"generator\" content=\"Org-mode\"/>
12680 <meta name=\"generated\" content=\"%s %s\"/>
12681 <meta name=\"author\" content=\"%s\"/>
12682 %s
12683 </head><body>
12684 "
12685 language language (org-html-expand title) (or charset "iso-8859-1")
12686 date time author style))
12687
12688
12689 (insert (or (plist-get opt-plist :preamble) ""))
12690
12691 (when (plist-get opt-plist :auto-preamble)
12692 (if title (insert (concat "<h1 class=\"title\">"
12693 (org-html-expand title) "</h1>\n")))
12694
12695 (if text (insert "<p>\n" (org-html-expand text) "</p>")))
12696
12697 (if org-export-with-toc
12698 (progn
12699 (insert (format "<h2>%s</h2>\n" (nth 3 lang-words)))
12700 (insert "<ul>\n<li>")
12701 (setq lines
12702 (mapcar '(lambda (line)
12703 (if (string-match org-todo-line-regexp line)
12704 ;; This is a headline
12705 (progn
12706 (setq level (- (match-end 1) (match-beginning 1))
12707 level (org-tr-level level)
12708 txt (save-match-data
12709 (org-html-expand
12710 (org-html-cleanup-toc-line
12711 (match-string 3 line))))
12712 todo
12713 (or (and org-export-mark-todo-in-toc
12714 (match-beginning 2)
12715 (not (equal (match-string 2 line)
12716 org-done-string)))
12717 ; TODO, not DONE
12718 (and org-export-mark-todo-in-toc
12719 (= level umax)
12720 (org-search-todo-below
12721 line lines level))))
12722 (if org-export-with-section-numbers
12723 (setq txt (concat (org-section-number level)
12724 " " txt)))
12725 (if (<= level umax)
12726 (progn
12727 (setq head-count (+ head-count 1))
12728 (if (> level org-last-level)
12729 (progn
12730 (setq cnt (- level org-last-level))
12731 (while (>= (setq cnt (1- cnt)) 0)
12732 (insert "\n<ul>\n<li>"))
12733 (insert "\n")))
12734 (if (< level org-last-level)
12735 (progn
12736 (setq cnt (- org-last-level level))
12737 (while (>= (setq cnt (1- cnt)) 0)
12738 (insert "</li>\n</ul>"))
12739 (insert "\n")))
12740 ;; Check for targets
12741 (while (string-match org-target-regexp line)
12742 (setq tg (match-string 1 line)
12743 line (replace-match
12744 (concat "@<span class=\"target\">" tg "@</span> ")
12745 t t line))
12746 (push (cons (org-solidify-link-text tg)
12747 (format "sec-%d" head-count))
12748 target-alist))
12749 (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
12750 (setq txt (replace-match "" t t txt)))
12751 (insert
12752 (format
12753 (if todo
12754 "</li>\n<li><a href=\"#sec-%d\"><span class=\"todo\">%s</span></a>"
12755 "</li>\n<li><a href=\"#sec-%d\">%s</a>")
12756 head-count txt))
12757
12758 (setq org-last-level level))
12759 )))
12760 line)
12761 lines))
12762 (while (> org-last-level 0)
12763 (setq org-last-level (1- org-last-level))
12764 (insert "</li>\n</ul>\n"))
12765 ))
12766 (setq head-count 0)
12767 (org-init-section-numbers)
12768
12769 (while (setq line (pop lines) origline line)
12770 (catch 'nextline
12771
12772 ;; end of quote section?
12773 (when (and inquote (string-match "^\\*+" line))
12774 (insert "</pre>\n")
12775 (setq inquote nil))
12776 ;; inside a quote section?
12777 (when inquote
12778 (insert (org-html-protect line) "\n")
12779 (throw 'nextline nil))
12780
12781 ;; verbatim lines
12782 (when (and org-export-with-fixed-width
12783 (string-match "^[ \t]*:\\(.*\\)" line))
12784 (when (not infixed)
12785 (setq infixed t)
12786 (insert "<pre>\n"))
12787 (insert (org-html-protect (match-string 1 line)) "\n")
12788 (when (and lines
12789 (not (string-match "^[ \t]*\\(:.*\\)"
12790 (car lines))))
12791 (setq infixed nil)
12792 (insert "</pre>\n"))
12793 (throw 'nextline nil))
12794
12795
12796 ;; make targets to anchors
12797 (while (string-match "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line)
12798 (cond
12799 ((match-end 2)
12800 (setq line (replace-match
12801 (concat "@<a name=\""
12802 (org-solidify-link-text (match-string 1 line))
12803 "\">\\nbsp@</a>")
12804 t t line)))
12805 ((and org-export-with-toc (equal (string-to-char line) ?*))
12806 (setq line (replace-match
12807 (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
12808 ; (concat "@<i>" (match-string 1 line) "@</i> ")
12809 t t line)))
12810 (t
12811 (setq line (replace-match
12812 (concat "@<a name=\""
12813 (org-solidify-link-text (match-string 1 line))
12814 "\" class=\"target\">" (match-string 1 line) "@</a> ")
12815 t t line)))))
12816
12817 (setq line (org-html-handle-time-stamps line))
12818
12819 ;; replace "&" by "&amp;", "<" and ">" by "&lt;" and "&gt;"
12820 ;; handle @<..> HTML tags (replace "@&gt;..&lt;" by "<..>")
12821 ;; Also handle sub_superscripts and checkboxes
12822 ;; FIXME: is there no better place for checkboxes
12823 (setq line (org-html-expand line))
12824
12825 ;; Format the links
12826 (setq start 0)
12827 (while (string-match org-bracket-link-analytic-regexp line start)
12828 (setq start (match-beginning 0))
12829 (setq type (if (match-end 2) (match-string 2 line) "internal"))
12830 (setq path (match-string 3 line))
12831 (setq desc1 (if (match-end 5) (match-string 5 line))
12832 desc2 (if (match-end 2) (concat type ":" path) path)
12833 descp (and desc1 (not (equal desc1 desc2)))
12834 desc (or desc1 desc2))
12835 ;; FIXME: do we need to unescape here somewhere?
12836 (cond
12837 ((equal type "internal")
12838 (setq rpl
12839 (concat
12840 "<a href=\"#"
12841 (org-solidify-link-text path target-alist)
12842 "\">" desc "</a>")))
12843 ((member type '("http" "https" "ftp" "mailto" "news"))
12844 ;; standard URL
12845 (setq link (concat type ":" path))
12846 (setq rpl (concat "<a href=\"" link "\">" desc "</a>")))
12847 ((string= type "file")
12848 ;; FILE link
12849 (let* ((filename path)
12850 (abs-p (file-name-absolute-p filename))
12851 thefile file-is-image-p search)
12852 (save-match-data
12853 (if (string-match "::\\(.*\\)" filename)
12854 (setq search (match-string 1 filename)
12855 filename (replace-match "" t nil filename)))
12856 (setq file-is-image-p
12857 (string-match (org-image-file-name-regexp) filename))
12858 (setq thefile (if abs-p (expand-file-name filename) filename))
12859 (when (and org-export-html-link-org-files-as-html
12860 (string-match "\\.org$" thefile))
12861 (setq thefile (concat (substring thefile 0
12862 (match-beginning 0))
12863 ".html"))
12864 (if (and search
12865 ;; make sure this is can be used as target search
12866 (not (string-match "^[0-9]*$" search))
12867 (not (string-match "^\\*" search))
12868 (not (string-match "^/.*/$" search)))
12869 (setq thefile (concat thefile "#"
12870 (org-solidify-link-text
12871 (org-link-unescape search)))))
12872 (when (string-match "^file:" desc)
12873 (setq desc (replace-match "" t t desc))
12874 (if (string-match "\\.org$" desc)
12875 (setq desc (replace-match "" t t desc))))))
12876 (setq rpl (if (and file-is-image-p
12877 (or (eq t org-export-html-inline-images)
12878 (and org-export-html-inline-images
12879 (not descp))))
12880 (concat "<img src=\"" thefile "\"/>")
12881 (concat "<a href=\"" thefile "\">" desc "</a>")))))
12882 ((member type '("bbdb" "vm" "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
12883 (setq rpl (concat "<i>&lt;" type ":"
12884 (save-match-data (org-link-unescape path))
12885 "&gt;</i>"))))
12886 (setq line (replace-match rpl t t line)
12887 start (+ start (length rpl))))
12888 ;; TODO items
12889 (if (and (string-match org-todo-line-regexp line)
12890 (match-beginning 2))
12891 (if (equal (match-string 2 line) org-done-string)
12892 (setq line (replace-match
12893 "<span class=\"done\">\\2</span>"
12894 t nil line 2))
12895 (setq line (replace-match "<span class=\"todo\">\\2</span>"
12896 t nil line 2))))
12897
12898 (cond
12899 ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line)
12900 ;; This is a headline
12901 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
12902 txt (match-string 2 line))
12903 (if (string-match quote-re0 txt)
12904 (setq txt (replace-match "" t t txt)))
12905 (if (<= level umax) (setq head-count (+ head-count 1)))
12906 (when in-local-list
12907 ;; Close any local lists before inserting a new header line
12908 (while local-list-num
12909 (org-close-li)
12910 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
12911 (pop local-list-num))
12912 (setq local-list-indent nil
12913 in-local-list nil))
12914 (org-html-level-start level txt umax
12915 (and org-export-with-toc (<= level umax))
12916 head-count)
12917 ;; QUOTES
12918 (when (string-match quote-re line)
12919 (insert "<pre>")
12920 (setq inquote t)))
12921
12922 ((and org-export-with-tables
12923 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
12924 (if (not table-open)
12925 ;; New table starts
12926 (setq table-open t table-buffer nil table-orig-buffer nil))
12927 ;; Accumulate lines
12928 (setq table-buffer (cons line table-buffer)
12929 table-orig-buffer (cons origline table-orig-buffer))
12930 (when (or (not lines)
12931 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
12932 (car lines))))
12933 (setq table-open nil
12934 table-buffer (nreverse table-buffer)
12935 table-orig-buffer (nreverse table-orig-buffer))
12936 (org-close-par-maybe)
12937 (insert (org-format-table-html table-buffer table-orig-buffer))))
12938 (t
12939 ;; Normal lines
12940 (when (string-match
12941 (cond
12942 ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*]\\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
12943 ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*]\\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
12944 ((= llt ?\)) "^\\( \t]*\\)\\(\\([-+*]\\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
12945 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
12946 line)
12947 (setq ind (org-get-string-indentation line)
12948 start-is-num (match-beginning 4)
12949 starter (if (match-beginning 2)
12950 (substring (match-string 2 line) 0 -1))
12951 line (substring line (match-beginning 5)))
12952 (unless (string-match "[^ \t]" line)
12953 ;; empty line. Pretend indentation is large.
12954 (setq ind (1+ (or (car local-list-indent) 1))))
12955 (while (and in-local-list
12956 (or (and (= ind (car local-list-indent))
12957 (not starter))
12958 (< ind (car local-list-indent))))
12959 (org-close-li)
12960 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
12961 (pop local-list-num) (pop local-list-indent)
12962 (setq in-local-list local-list-indent))
12963 (cond
12964 ((and starter
12965 (or (not in-local-list)
12966 (> ind (car local-list-indent))))
12967 ;; Start new (level of ) list
12968 (org-close-par-maybe)
12969 (insert (if start-is-num "<ol>\n<li>\n" "<ul>\n<li>\n"))
12970 (push start-is-num local-list-num)
12971 (push ind local-list-indent)
12972 (setq in-local-list t))
12973 (starter
12974 ;; continue current list
12975 (org-close-li)
12976 (insert "<li>\n")))
12977 (if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
12978 (setq line
12979 (replace-match
12980 (if (equal (match-string 1 line) "X")
12981 "<b>[X]</b>"
12982 "<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
12983 t t line))))
12984
12985 ;; Empty lines start a new paragraph. If hand-formatted lists
12986 ;; are not fully interpreted, lines starting with "-", "+", "*"
12987 ;; also start a new paragraph.
12988 (if (string-match "^ [-+*]-\\|^[ \t]*$" line) (org-open-par))
12989
12990 ;; Check if the line break needs to be conserved
12991 ;; FIXME: document \\ at end of line.
12992 (cond
12993 ((string-match "\\\\\\\\[ \t]*$" line)
12994 (setq line (replace-match "<br/>" t t line)))
12995 (org-export-preserve-breaks
12996 (setq line (concat line "<br/>"))))
12997
12998 (insert line "\n")))))
12999
13000 ;; Properly close all local lists and other lists
13001 (when inquote (insert "</pre>\n"))
13002 (when in-local-list
13003 ;; Close any local lists before inserting a new header line
13004 (while local-list-num
13005 (org-close-li)
13006 (insert (if (car local-list-num) "</ol>\n" "</ul>\n"))
13007 (pop local-list-num))
13008 (setq local-list-indent nil
13009 in-local-list nil))
13010 (org-html-level-start 1 nil umax
13011 (and org-export-with-toc (<= level umax))
13012 head-count)
13013
13014 (when (plist-get opt-plist :auto-postamble)
13015 (when author
13016 (insert "<p class=\"author\"> "
13017 (nth 1 lang-words) ": " author "\n")
13018 (when email
13019 (insert "<a href=\"mailto:" email "\">&lt;"
13020 email "&gt;</a>\n"))
13021 (insert "</p>\n"))
13022 (when (and date time)
13023 (insert "<p class=\"date\"> "
13024 (nth 2 lang-words) ": "
13025 date " " time "</p>\n")))
13026
13027 (if org-export-html-with-timestamp
13028 (insert org-export-html-html-helper-timestamp))
13029 (insert (or (plist-get opt-plist :postamble) ""))
13030 (insert "</body>\n</html>\n")
13031 (normal-mode)
13032 ;; remove empty paragraphs and lists
13033 (goto-char (point-min))
13034 (while (re-search-forward "<p>[ \r\n\t]*</p>" nil t)
13035 (replace-match ""))
13036 (goto-char (point-min))
13037 (while (re-search-forward "<li>[ \r\n\t]*</li>\n?" nil t)
13038 (replace-match ""))
13039 (save-buffer)
13040 (goto-char (point-min)))))
13041
13042 (defun org-format-table-html (lines olines)
13043 "Find out which HTML converter to use and return the HTML code."
13044 (if (string-match "^[ \t]*|" (car lines))
13045 ;; A normal org table
13046 (org-format-org-table-html lines)
13047 ;; Table made by table.el - test for spanning
13048 (let* ((hlines (delq nil (mapcar
13049 (lambda (x)
13050 (if (string-match "^[ \t]*\\+-" x) x
13051 nil))
13052 lines)))
13053 (first (car hlines))
13054 (ll (and (string-match "\\S-+" first)
13055 (match-string 0 first)))
13056 (re (concat "^[ \t]*" (regexp-quote ll)))
13057 (spanning (delq nil (mapcar (lambda (x) (not (string-match re x)))
13058 hlines))))
13059 (if (and (not spanning)
13060 (not org-export-prefer-native-exporter-for-tables))
13061 ;; We can use my own converter with HTML conversions
13062 (org-format-table-table-html lines)
13063 ;; Need to use the code generator in table.el, with the original text.
13064 (org-format-table-table-html-using-table-generate-source olines)))))
13065
13066 (defun org-format-org-table-html (lines)
13067 "Format a table into HTML."
13068 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
13069 (setq lines (nreverse lines))
13070 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
13071 (setq lines (nreverse lines))
13072 (when org-export-table-remove-special-lines
13073 ;; Check if the table has a marking column. If yes remove the
13074 ;; column and the special lines
13075 (let* ((special
13076 (not
13077 (memq nil
13078 (mapcar
13079 (lambda (x)
13080 (or (string-match "^[ \t]*|-" x)
13081 (string-match "^[ \t]*| *\\([#!$*_^ ]\\) *|" x)))
13082 lines)))))
13083 (if special
13084 (setq lines
13085 (delq nil
13086 (mapcar
13087 (lambda (x)
13088 (if (string-match "^[ \t]*| *[!_^] *|" x)
13089 nil ; ignore this line
13090 (and (or (string-match "^[ \t]*|-+\\+" x)
13091 (string-match "^[ \t]*|[^|]*|" x))
13092 (replace-match "|" t t x))))
13093 lines))))))
13094
13095 (let ((head (and org-export-highlight-first-table-line
13096 (delq nil (mapcar
13097 (lambda (x) (string-match "^[ \t]*|-" x))
13098 (cdr lines)))))
13099 line fields html)
13100 (setq html (concat org-export-html-table-tag "\n"))
13101 (while (setq line (pop lines))
13102 (catch 'next-line
13103 (if (string-match "^[ \t]*|-" line)
13104 (progn
13105 (setq head nil) ;; head ends here, first time around
13106 ;; ignore this line
13107 (throw 'next-line t)))
13108 ;; Break the line into fields
13109 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
13110 (setq html (concat
13111 html
13112 "<tr>"
13113 (mapconcat (lambda (x)
13114 (if head
13115 (concat "<th>" x "</th>")
13116 (concat "<td>" x "</td>")))
13117 fields "")
13118 "</tr>\n"))))
13119 (setq html (concat html "</table>\n"))
13120 html))
13121
13122 (defun org-fake-empty-table-line (line)
13123 "Replace everything except \"|\" with spaces."
13124 (let ((i (length line))
13125 (newstr (copy-sequence line)))
13126 (while (> i 0)
13127 (setq i (1- i))
13128 (if (not (eq (aref newstr i) ?|))
13129 (aset newstr i ?\ )))
13130 newstr))
13131
13132 (defun org-format-table-table-html (lines)
13133 "Format a table generated by table.el into HTML.
13134 This conversion does *not* use `table-generate-source' from table.el.
13135 This has the advantage that Org-mode's HTML conversions can be used.
13136 But it has the disadvantage, that no cell- or row-spanning is allowed."
13137 (let (line field-buffer
13138 (head org-export-highlight-first-table-line)
13139 fields html empty)
13140 (setq html (concat org-export-html-table-tag "\n"))
13141 (while (setq line (pop lines))
13142 (setq empty "&nbsp")
13143 (catch 'next-line
13144 (if (string-match "^[ \t]*\\+-" line)
13145 (progn
13146 (if field-buffer
13147 (progn
13148 (setq html (concat
13149 html
13150 "<tr>"
13151 (mapconcat
13152 (lambda (x)
13153 (if (equal x "") (setq x empty))
13154 (if head
13155 (concat "<th>" x "</th>\n")
13156 (concat "<td>" x "</td>\n")))
13157 field-buffer "\n")
13158 "</tr>\n"))
13159 (setq head nil)
13160 (setq field-buffer nil)))
13161 ;; Ignore this line
13162 (throw 'next-line t)))
13163 ;; Break the line into fields and store the fields
13164 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
13165 (if field-buffer
13166 (setq field-buffer (mapcar
13167 (lambda (x)
13168 (concat x "<br/>" (pop fields)))
13169 field-buffer))
13170 (setq field-buffer fields))))
13171 (setq html (concat html "</table>\n"))
13172 html))
13173
13174 (defun org-format-table-table-html-using-table-generate-source (lines)
13175 "Format a table into html, using `table-generate-source' from table.el.
13176 This has the advantage that cell- or row-spanning is allowed.
13177 But it has the disadvantage, that Org-mode's HTML conversions cannot be used."
13178 (require 'table)
13179 (with-current-buffer (get-buffer-create " org-tmp1 ")
13180 (erase-buffer)
13181 (insert (mapconcat 'identity lines "\n"))
13182 (goto-char (point-min))
13183 (if (not (re-search-forward "|[^+]" nil t))
13184 (error "Error processing table"))
13185 (table-recognize-table)
13186 (with-current-buffer (get-buffer-create " org-tmp2 ") (erase-buffer))
13187 (table-generate-source 'html " org-tmp2 ")
13188 (set-buffer " org-tmp2 ")
13189 (buffer-substring (point-min) (point-max))))
13190
13191 (defun org-html-handle-time-stamps (s)
13192 "Format time stamps in string S, or remove them."
13193 (let (r b)
13194 (while (string-match org-maybe-keyword-time-regexp s)
13195 (or b (setq b (substring s 0 (match-beginning 0))))
13196 (if (not org-export-with-timestamps)
13197 (setq r (concat r (substring s 0 (match-beginning 0)))
13198 s (substring s (match-end 0)))
13199 (setq r (concat
13200 r (substring s 0 (match-beginning 0))
13201 (if (match-end 1)
13202 (format "@<span class=\"timestamp-kwd\">%s @</span>"
13203 (match-string 1 s)))
13204 (format " @<span class=\"timestamp\">%s@</span>"
13205 (substring (match-string 3 s) 1 -1)))
13206 s (substring s (match-end 0)))))
13207 ;; Line break of line started and ended with time stamp stuff
13208 (if (not r)
13209 s
13210 (setq r (concat r s))
13211 (unless (string-match "\\S-" (concat b s))
13212 (setq r (concat r "@<br/>")))
13213 r)))
13214
13215 (defun org-html-protect (s)
13216 ;; convert & to &amp;, < to &lt; and > to &gt;
13217 (let ((start 0))
13218 (while (string-match "&" s start)
13219 (setq s (replace-match "&amp;" t t s)
13220 start (1+ (match-beginning 0))))
13221 (while (string-match "<" s)
13222 (setq s (replace-match "&lt;" t t s)))
13223 (while (string-match ">" s)
13224 (setq s (replace-match "&gt;" t t s))))
13225 s)
13226
13227 (defun org-html-cleanup-toc-line (s)
13228 "Remove tags and time staps from lines going into the toc."
13229 (if (string-match " +:[a-zA-Z0-9_@:]+: *$" s)
13230 (setq s (replace-match "" t t s)))
13231 (while (string-match org-maybe-keyword-time-regexp s)
13232 (setq s (replace-match "" t t s)))
13233 s)
13234
13235 (defun org-html-expand (string)
13236 "Prepare STRING for HTML export. Applies all active conversions.
13237 If there are links in the string, don't modify these."
13238 (let* (m s l res)
13239 (while (setq m (string-match org-bracket-link-regexp string))
13240 (setq s (substring string 0 m)
13241 l (match-string 0 string)
13242 string (substring string (match-end 0)))
13243 (push (org-html-do-expand s) res)
13244 (push l res))
13245 (push (org-html-do-expand string) res)
13246 (apply 'concat (nreverse res))))
13247
13248 (defun org-html-do-expand (s)
13249 "Apply all active conversions to translate special ASCII to HTML."
13250 (setq s (org-html-protect s))
13251 (if org-export-html-expand
13252 (while (string-match "@&lt;\\([^&]*\\)&gt;" s)
13253 (setq s (replace-match "<\\1>" t nil s))))
13254 (if org-export-with-emphasize
13255 (setq s (org-export-html-convert-emphasize s)))
13256 (if org-export-with-sub-superscripts
13257 (setq s (org-export-html-convert-sub-super s)))
13258 (if org-export-with-TeX-macros
13259 (let ((start 0) wd ass)
13260 (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)" s start))
13261 (setq wd (match-string 1 s))
13262 (if (setq ass (assoc wd org-html-entities))
13263 (setq s (replace-match (or (cdr ass)
13264 (concat "&" (car ass) ";"))
13265 t t s))
13266 (setq start (+ start (length wd)))))))
13267 s)
13268
13269 (defun org-create-multibrace-regexp (left right n)
13270 "Create a regular expression which will match a balanced sexp.
13271 Opening delimiter is LEFT, and closing delimiter is RIGHT, both given
13272 as single character strings.
13273 The regexp returned will match the entire expression including the
13274 delimiters. It will also define a single group which contains the
13275 match except for the outermost delimiters. The maximum depth of
13276 stacked delimiters is N. Escaping delimiters is not possible."
13277 (let* ((nothing (concat "[^" "\\" left "\\" right "]*?"))
13278 (or "\\|")
13279 (re nothing)
13280 (next (concat "\\(?:" nothing left nothing right "\\)+" nothing)))
13281 (while (> n 1)
13282 (setq n (1- n)
13283 re (concat re or next)
13284 next (concat "\\(?:" nothing left next right "\\)+" nothing)))
13285 (concat left "\\(" re "\\)" right)))
13286
13287 (defvar org-match-substring-regexp
13288 (concat
13289 "\\([^\\]\\)\\([_^]\\)\\("
13290 "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
13291 "\\|"
13292 "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
13293 "\\|"
13294 "\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
13295 "The regular expression matching a sub- or superscript.")
13296
13297 (defun org-export-html-convert-sub-super (string)
13298 "Convert sub- and superscripts in STRING to HTML."
13299 (let (key c)
13300 (while (string-match org-match-substring-regexp string)
13301 (setq key (if (string= (match-string 2 string) "_") "sub" "sup"))
13302 (setq c (or (match-string 8 string)
13303 (match-string 6 string)
13304 (match-string 5 string)))
13305 (setq string (replace-match
13306 (concat (match-string 1 string)
13307 "<" key ">" c "</" key ">")
13308 t t string)))
13309 (while (string-match "\\\\\\([_^]\\)" string)
13310 (setq string (replace-match (match-string 1 string) t t string))))
13311 string)
13312
13313 (defun org-export-html-convert-emphasize (string)
13314 (while (string-match org-italic-re string)
13315 (setq string (replace-match "\\1<i>\\3</i>\\4" t nil string)))
13316 (while (string-match org-bold-re string)
13317 (setq string (replace-match "\\1<b>\\3</b>\\4" t nil string)))
13318 (while (string-match org-underline-re string)
13319 (setq string (replace-match "\\1<u>\\3</u>\\4" t nil string)))
13320 string)
13321
13322 (defvar org-par-open nil)
13323 (defun org-open-par ()
13324 "Insert <p>, but first close previous paragraph if any."
13325 (org-close-par-maybe)
13326 (insert "\n<p>")
13327 (setq org-par-open t))
13328 (defun org-close-par-maybe ()
13329 "Close paragraph if there is one open."
13330 (when org-par-open
13331 (insert "</p>")
13332 (setq org-par-open nil)))
13333 (defun org-close-li ()
13334 "Close <li> if necessary."
13335 (org-close-par-maybe)
13336 (insert "</li>\n"))
13337 ; (when (save-excursion
13338 ; (re-search-backward "</?\\(ul\\|ol\\|li\\|[hH][0-9]\\)>" nil t))
13339 ; (if (member (match-string 0) '("</ul>" "</ol>" "<li>"))
13340 ; (insert "</li>"))))
13341
13342 (defun org-html-level-start (level title umax with-toc head-count)
13343 "Insert a new level in HTML export.
13344 When TITLE is nil, just close all open levels."
13345 (org-close-par-maybe)
13346 (let ((l (1+ (max level umax))))
13347 (while (<= l org-level-max)
13348 (if (aref levels-open (1- l))
13349 (progn
13350 (org-html-level-close l)
13351 (aset levels-open (1- l) nil)))
13352 (setq l (1+ l)))
13353 (when title
13354 ;; If title is nil, this means this function is called to close
13355 ;; all levels, so the rest is done only if title is given
13356 (if (> level umax)
13357 (progn
13358 (if (aref levels-open (1- level))
13359 (progn
13360 (org-close-li)
13361 (insert "<li>" title "<br/>\n"))
13362 (aset levels-open (1- level) t)
13363 (org-close-par-maybe)
13364 (insert "<ul>\n<li>" title "<br/>\n")))
13365 (if org-export-with-section-numbers
13366 (setq title (concat (org-section-number level) " " title)))
13367 (setq level (+ level 1))
13368 (when (string-match "\\(:[a-zA-Z0-9_@:]+:\\)[ \t]*$" title)
13369 (setq title (replace-match
13370 (if org-export-with-tags
13371 (save-match-data
13372 (concat
13373 "&nbsp;&nbsp;&nbsp;<span class=\"tag\">"
13374 (mapconcat 'identity (org-split-string
13375 (match-string 1 title) ":")
13376 "&nbsp;")
13377 "</span>"))
13378 "")
13379 t t title)))
13380 (if with-toc
13381 (insert (format "\n<h%d><a name=\"sec-%d\">%s</a></h%d>\n"
13382 level head-count title level))
13383 (insert (format "\n<h%d>%s</h%d>\n" level title level)))
13384 (org-open-par)))))
13385
13386 (defun org-html-level-close (&rest args)
13387 "Terminate one level in HTML export."
13388 (org-close-li)
13389 (insert "</ul>"))
13390
13391 ;; Variable holding the vector with section numbers
13392 (defvar org-section-numbers (make-vector org-level-max 0))
13393
13394 (defun org-init-section-numbers ()
13395 "Initialize the vector for the section numbers."
13396 (let* ((level -1)
13397 (numbers (nreverse (org-split-string "" "\\.")))
13398 (depth (1- (length org-section-numbers)))
13399 (i depth) number-string)
13400 (while (>= i 0)
13401 (if (> i level)
13402 (aset org-section-numbers i 0)
13403 (setq number-string (or (car numbers) "0"))
13404 (if (string-match "\\`[A-Z]\\'" number-string)
13405 (aset org-section-numbers i
13406 (- (string-to-char number-string) ?A -1))
13407 (aset org-section-numbers i (string-to-number number-string)))
13408 (pop numbers))
13409 (setq i (1- i)))))
13410
13411 (defun org-section-number (&optional level)
13412 "Return a string with the current section number.
13413 When LEVEL is non-nil, increase section numbers on that level."
13414 (let* ((depth (1- (length org-section-numbers))) idx n (string ""))
13415 (when level
13416 (when (> level -1)
13417 (aset org-section-numbers
13418 level (1+ (aref org-section-numbers level))))
13419 (setq idx (1+ level))
13420 (while (<= idx depth)
13421 (if (not (= idx 1))
13422 (aset org-section-numbers idx 0))
13423 (setq idx (1+ idx))))
13424 (setq idx 0)
13425 (while (<= idx depth)
13426 (setq n (aref org-section-numbers idx))
13427 (setq string (concat string (if (not (string= string "")) "." "")
13428 (int-to-string n)))
13429 (setq idx (1+ idx)))
13430 (save-match-data
13431 (if (string-match "\\`\\([@0]\\.\\)+" string)
13432 (setq string (replace-match "" t nil string)))
13433 (if (string-match "\\(\\.0\\)+\\'" string)
13434 (setq string (replace-match "" t nil string))))
13435 string))
13436
13437
13438 (defun org-export-icalendar-this-file ()
13439 "Export current file as an iCalendar file.
13440 The iCalendar file will be located in the same directory as the Org-mode
13441 file, but with extension `.ics'."
13442 (interactive)
13443 (org-export-icalendar nil buffer-file-name))
13444
13445 (defun org-export-as-xml (arg)
13446 "Export current buffer as XOXO XML buffer."
13447 (interactive "P")
13448 (cond ((eq org-export-xml-type 'xoxo)
13449 (org-export-as-xoxo (current-buffer)))))
13450
13451 (defun org-export-as-xoxo-insert-into (buffer &rest output)
13452 (with-current-buffer buffer
13453 (apply 'insert output)))
13454
13455 (defun org-export-as-xoxo (&optional buffer)
13456 "Export the org buffer as XOXO.
13457 The XOXO buffer is named *xoxo-<source buffer name>*"
13458 (interactive (list (current-buffer)))
13459 ;; A quickie abstraction
13460
13461 ;; Output everything as XOXO
13462 (with-current-buffer (get-buffer buffer)
13463 (goto-char (point-min)) ;; CD: beginning-of-buffer is not allowed.
13464 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
13465 (org-infile-export-plist)))
13466 (filename (concat (file-name-as-directory
13467 (org-export-directory :xoxo opt-plist))
13468 (file-name-sans-extension
13469 (file-name-nondirectory buffer-file-name))
13470 ".html"))
13471 (out (find-file-noselect filename))
13472 (last-level 1)
13473 (hanging-li nil))
13474 ;; Check the output buffer is empty.
13475 (with-current-buffer out (erase-buffer))
13476 ;; Kick off the output
13477 (org-export-as-xoxo-insert-into out "<ol class='xoxo'>\n")
13478 (while (re-search-forward "^\\(\\*+\\) \\(.+\\)" (point-max) 't)
13479 (let* ((hd (match-string-no-properties 1))
13480 (level (length hd))
13481 (text (concat
13482 (match-string-no-properties 2)
13483 (save-excursion
13484 (goto-char (match-end 0))
13485 (let ((str ""))
13486 (catch 'loop
13487 (while 't
13488 (forward-line)
13489 (if (looking-at "^[ \t]\\(.*\\)")
13490 (setq str (concat str (match-string-no-properties 1)))
13491 (throw 'loop str)))))))))
13492
13493 ;; Handle level rendering
13494 (cond
13495 ((> level last-level)
13496 (org-export-as-xoxo-insert-into out "\n<ol>\n"))
13497
13498 ((< level last-level)
13499 (dotimes (- (- last-level level) 1)
13500 (if hanging-li
13501 (org-export-as-xoxo-insert-into out "</li>\n"))
13502 (org-export-as-xoxo-insert-into out "</ol>\n"))
13503 (when hanging-li
13504 (org-export-as-xoxo-insert-into out "</li>\n")
13505 (setq hanging-li nil)))
13506
13507 ((equal level last-level)
13508 (if hanging-li
13509 (org-export-as-xoxo-insert-into out "</li>\n")))
13510 )
13511
13512 (setq last-level level)
13513
13514 ;; And output the new li
13515 (setq hanging-li 't)
13516 (if (equal ?+ (elt text 0))
13517 (org-export-as-xoxo-insert-into out "<li class='" (substring text 1) "'>")
13518 (org-export-as-xoxo-insert-into out "<li>" text))))
13519
13520 ;; Finally finish off the ol
13521 (dotimes (- last-level 1)
13522 (if hanging-li
13523 (org-export-as-xoxo-insert-into out "</li>\n"))
13524 (org-export-as-xoxo-insert-into out "</ol>\n"))
13525
13526 ;; Finish the buffer off and clean it up.
13527 (switch-to-buffer-other-window out)
13528 (indent-region (point-min) (point-max) nil)
13529 (save-buffer)
13530 (goto-char (point-min))
13531 )))
13532
13533 ;;;###autoload
13534 (defun org-export-icalendar-all-agenda-files ()
13535 "Export all files in `org-agenda-files' to iCalendar .ics files.
13536 Each iCalendar file will be located in the same directory as the Org-mode
13537 file, but with extension `.ics'."
13538 (interactive)
13539 (apply 'org-export-icalendar nil (org-agenda-files t)))
13540
13541 ;;;###autoload
13542 (defun org-export-icalendar-combine-agenda-files ()
13543 "Export all files in `org-agenda-files' to a single combined iCalendar file.
13544 The file is stored under the name `org-combined-agenda-icalendar-file'."
13545 (interactive)
13546 (apply 'org-export-icalendar t (org-agenda-files t)))
13547
13548 (defun org-export-icalendar (combine &rest files)
13549 "Create iCalendar files for all elements of FILES.
13550 If COMBINE is non-nil, combine all calendar entries into a single large
13551 file and store it under the name `org-combined-agenda-icalendar-file'."
13552 (save-excursion
13553 (let* ((dir (org-export-directory
13554 :ical (list :publishing-directory
13555 org-export-publishing-directory)))
13556 file ical-file ical-buffer category started org-agenda-new-buffers)
13557
13558 (when combine
13559 (setq ical-file
13560 (if (file-name-absolute-p org-combined-agenda-icalendar-file)
13561 org-combined-agenda-icalendar-file
13562 (expand-file-name org-combined-agenda-icalendar-file dir))
13563 ical-buffer (org-get-agenda-file-buffer ical-file))
13564 (set-buffer ical-buffer) (erase-buffer))
13565 (while (setq file (pop files))
13566 (catch 'nextfile
13567 (org-check-agenda-file file)
13568 (set-buffer (org-get-agenda-file-buffer file))
13569 (unless combine
13570 (setq ical-file (concat (file-name-as-directory dir)
13571 (file-name-sans-extension
13572 (file-name-nondirectory buffer-file-name))
13573 ".ics"))
13574 (setq ical-buffer (org-get-agenda-file-buffer ical-file))
13575 (with-current-buffer ical-buffer (erase-buffer)))
13576 (setq category (or org-category
13577 (file-name-sans-extension
13578 (file-name-nondirectory buffer-file-name))))
13579 (if (symbolp category) (setq category (symbol-name category)))
13580 (let ((standard-output ical-buffer))
13581 (if combine
13582 (and (not started) (setq started t)
13583 (org-start-icalendar-file org-icalendar-combined-name))
13584 (org-start-icalendar-file category))
13585 (org-print-icalendar-entries combine category)
13586 (when (or (and combine (not files)) (not combine))
13587 (org-finish-icalendar-file)
13588 (set-buffer ical-buffer)
13589 (save-buffer)
13590 (run-hooks 'org-after-save-iCalendar-file-hook)))))
13591 (org-release-buffers org-agenda-new-buffers))))
13592
13593 (defvar org-after-save-iCalendar-file-hook nil
13594 "Hook run after an iCalendar file has been saved.
13595 The iCalendar buffer is still current when this hook is run.
13596 A good way to use this is to tell a desktop calenndar application to re-read
13597 the iCalendar file.")
13598
13599 (defun org-print-icalendar-entries (&optional combine category)
13600 "Print iCalendar entries for the current Org-mode file to `standard-output'.
13601 When COMBINE is non nil, add the category to each line."
13602 (let ((re2 (concat "--?-?\\(" org-ts-regexp "\\)"))
13603 (dts (org-ical-ts-to-string
13604 (format-time-string (cdr org-time-stamp-formats) (current-time))
13605 "DTSTART"))
13606 hd ts ts2 state (inc t) pos scheduledp deadlinep tmp pri)
13607 (save-excursion
13608 (goto-char (point-min))
13609 (while (re-search-forward org-ts-regexp nil t)
13610 (setq pos (match-beginning 0)
13611 ts (match-string 0)
13612 inc t
13613 hd (org-get-heading))
13614 (if (looking-at re2)
13615 (progn
13616 (goto-char (match-end 0))
13617 (setq ts2 (match-string 1) inc nil))
13618 (setq ts2 ts
13619 tmp (buffer-substring (max (point-min)
13620 (- pos org-ds-keyword-length))
13621 pos)
13622 deadlinep (string-match org-deadline-regexp tmp)
13623 scheduledp (string-match org-scheduled-regexp tmp)
13624 ;; donep (org-entry-is-done-p)
13625 ))
13626 (if (or (string-match org-tr-regexp hd)
13627 (string-match org-ts-regexp hd))
13628 (setq hd (replace-match "" t t hd)))
13629 (if combine
13630 (setq hd (concat hd " (category " category ")")))
13631 (if deadlinep (setq hd (concat "DL: " hd " This is a deadline")))
13632 (if scheduledp (setq hd (concat "S: " hd " Scheduled for this date")))
13633 (princ (format "BEGIN:VEVENT
13634 %s
13635 %s
13636 SUMMARY:%s
13637 END:VEVENT\n"
13638 (org-ical-ts-to-string ts "DTSTART")
13639 (org-ical-ts-to-string ts2 "DTEND" inc)
13640 hd)))
13641 (when org-icalendar-include-todo
13642 (goto-char (point-min))
13643 (while (re-search-forward org-todo-line-regexp nil t)
13644 (setq state (match-string 1))
13645 (unless (equal state org-done-string)
13646 (setq hd (match-string 3))
13647 (if (string-match org-priority-regexp hd)
13648 (setq pri (string-to-char (match-string 2 hd))
13649 hd (concat (substring hd 0 (match-beginning 1))
13650 (substring hd (- (match-end 1)))))
13651 (setq pri org-default-priority))
13652 (setq pri (floor (1+ (* 8. (/ (float (- org-lowest-priority pri))
13653 (- org-lowest-priority ?A))))))
13654
13655 (princ (format "BEGIN:VTODO
13656 %s
13657 SUMMARY:%s
13658 SEQUENCE:1
13659 PRIORITY:%d
13660 END:VTODO\n"
13661 dts hd pri))))))))
13662
13663 (defun org-start-icalendar-file (name)
13664 "Start an iCalendar file by inserting the header."
13665 (let ((user user-full-name)
13666 (name (or name "unknown"))
13667 (timezone (cadr (current-time-zone))))
13668 (princ
13669 (format "BEGIN:VCALENDAR
13670 VERSION:2.0
13671 X-WR-CALNAME:%s
13672 PRODID:-//%s//Emacs with Org-mode//EN
13673 X-WR-TIMEZONE:%s
13674 CALSCALE:GREGORIAN\n" name user timezone))))
13675
13676 (defun org-finish-icalendar-file ()
13677 "Finish an iCalendar file by inserting the END statement."
13678 (princ "END:VCALENDAR\n"))
13679
13680 (defun org-ical-ts-to-string (s keyword &optional inc)
13681 "Take a time string S and convert it to iCalendar format.
13682 KEYWORD is added in front, to make a complete line like DTSTART....
13683 When INC is non-nil, increase the hour by two (if time string contains
13684 a time), or the day by one (if it does not contain a time)."
13685 (let ((t1 (org-parse-time-string s 'nodefault))
13686 t2 fmt have-time time)
13687 (if (and (car t1) (nth 1 t1) (nth 2 t1))
13688 (setq t2 t1 have-time t)
13689 (setq t2 (org-parse-time-string s)))
13690 (let ((s (car t2)) (mi (nth 1 t2)) (h (nth 2 t2))
13691 (d (nth 3 t2)) (m (nth 4 t2)) (y (nth 5 t2)))
13692 (when inc
13693 (if have-time (setq h (+ 2 h)) (setq d (1+ d))))
13694 (setq time (encode-time s mi h d m y)))
13695 (setq fmt (if have-time ":%Y%m%dT%H%M%S" ";VALUE=DATE:%Y%m%d"))
13696 (concat keyword (format-time-string fmt time))))
13697
13698
13699 ;;; Key bindings
13700
13701 ;; - Bindings in Org-mode map are currently
13702 ;; 0123456789abcdefghijklmnopqrstuvwxyz!?@#$%^&-+*/=()_{}[]:;"|,.<>~`'\t the alphabet
13703 ;; abcd fgh j lmnopqrstuvwxyz!? #$ ^ -+*/= [] ; |,.<>~ '\t necessary bindings
13704 ;; e (?) useful from outline-mode
13705 ;; i k @ expendable from outline-mode
13706 ;; 0123456789 % & ()_{} " ` free
13707
13708 ;; Make `C-c C-x' a prefix key
13709 (define-key org-mode-map "\C-c\C-x" (make-sparse-keymap))
13710 (define-key org-mode-map "\C-c\C-e" (make-sparse-keymap))
13711
13712 ;; TAB key with modifiers
13713 (define-key org-mode-map "\C-i" 'org-cycle)
13714 (define-key org-mode-map [(tab)] 'org-cycle)
13715 (define-key org-mode-map [(meta tab)] 'org-complete)
13716 (define-key org-mode-map "\M-\C-i" 'org-complete) ; for tty emacs
13717 ;; The following line is necessary under Suse GNU/Linux
13718 (unless (featurep 'xemacs)
13719 (define-key org-mode-map [S-iso-lefttab] 'org-shifttab))
13720 (define-key org-mode-map [(shift tab)] 'org-shifttab)
13721
13722 (define-key org-mode-map (org-key 'S-return) 'org-table-copy-down)
13723 (define-key org-mode-map "\C-c\C-xc" 'org-table-copy-down) ; tty
13724 (define-key org-mode-map [(meta shift return)] 'org-insert-todo-heading)
13725 (define-key org-mode-map "\C-c\C-xM" 'org-insert-todo-heading) ; tty
13726 (define-key org-mode-map [(meta return)] 'org-meta-return)
13727 (define-key org-mode-map "\C-c\C-xm" 'org-meta-return) ; tty emacs
13728 (define-key org-mode-map [?\e (return)] 'org-meta-return) ; tty emacs
13729
13730 ;; Cursor keys with modifiers
13731 (define-key org-mode-map [(meta left)] 'org-metaleft)
13732 (define-key org-mode-map [?\e (left)] 'org-metaleft) ; for tty emacs
13733 (define-key org-mode-map "\C-c\C-xl" 'org-metaleft) ; for tty emacs
13734 (define-key org-mode-map [(meta right)] 'org-metaright)
13735 (define-key org-mode-map [?\e (right)] 'org-metaright) ; for tty emacs
13736 (define-key org-mode-map "\C-c\C-xr" 'org-metaright) ; for tty emacs
13737 (define-key org-mode-map [(meta up)] 'org-metaup)
13738 (define-key org-mode-map [?\e (up)] 'org-metaup) ; for tty emacs
13739 (define-key org-mode-map "\C-c\C-xu" 'org-metaup) ; for tty emacs
13740 (define-key org-mode-map [(meta down)] 'org-metadown)
13741 (define-key org-mode-map [?\e (down)] 'org-metadown) ; for tty emacs
13742 (define-key org-mode-map "\C-c\C-xd" 'org-metadown) ; for tty emacs
13743
13744 (define-key org-mode-map [(meta shift left)] 'org-shiftmetaleft)
13745 (define-key org-mode-map "\C-c\C-xL" 'org-shiftmetaleft) ; tty
13746 (define-key org-mode-map [(meta shift right)] 'org-shiftmetaright)
13747 (define-key org-mode-map "\C-c\C-xR" 'org-shiftmetaright) ; tty
13748 (define-key org-mode-map [(meta shift up)] 'org-shiftmetaup)
13749 (define-key org-mode-map "\C-c\C-xU" 'org-shiftmetaup) ; tty
13750 (define-key org-mode-map [(meta shift down)] 'org-shiftmetadown)
13751 (define-key org-mode-map "\C-c\C-xD" 'org-shiftmetadown) ; tty
13752 (define-key org-mode-map (org-key 'S-up) 'org-shiftup)
13753 (define-key org-mode-map [?\C-c ?\C-x (up)] 'org-shiftup)
13754 (define-key org-mode-map (org-key 'S-down) 'org-shiftdown)
13755 (define-key org-mode-map [?\C-c ?\C-x (down)] 'org-shiftdown)
13756 (define-key org-mode-map (org-key 'S-left) 'org-shiftleft)
13757 (define-key org-mode-map [?\C-c ?\C-x (left)] 'org-shiftleft)
13758 (define-key org-mode-map (org-key 'S-right) 'org-shiftright)
13759 (define-key org-mode-map [?\C-c ?\C-x (right)] 'org-shiftright)
13760
13761 ;; All the other keys
13762
13763 (define-key org-mode-map "\C-c\C-a" 'show-all) ; in case allout messed up.
13764 (define-key org-mode-map "\C-c$" 'org-archive-subtree)
13765 (define-key org-mode-map "\C-c\C-j" 'org-goto)
13766 (define-key org-mode-map "\C-c\C-t" 'org-todo)
13767 (define-key org-mode-map "\C-c\C-s" 'org-schedule)
13768 (define-key org-mode-map "\C-c\C-d" 'org-deadline)
13769 (define-key org-mode-map "\C-c;" 'org-toggle-comment)
13770 (define-key org-mode-map "\C-c\C-v" 'org-show-todo-tree)
13771 (define-key org-mode-map "\C-c\C-w" 'org-check-deadlines)
13772 (define-key org-mode-map "\C-c/" 'org-occur) ; Minor-mode reserved
13773 (define-key org-mode-map "\C-c\\" 'org-tags-sparse-tree) ; Minor-mode res.
13774 (define-key org-mode-map "\C-c\C-m" 'org-insert-heading)
13775 (define-key org-mode-map "\M-\C-m" 'org-insert-heading)
13776 (define-key org-mode-map "\C-c\C-l" 'org-insert-link)
13777 (define-key org-mode-map "\C-c\C-o" 'org-open-at-point)
13778 (define-key org-mode-map "\C-c%" 'org-mark-ring-push)
13779 (define-key org-mode-map "\C-c&" 'org-mark-ring-goto)
13780 (define-key org-mode-map "\C-c\C-z" 'org-time-stamp) ; Alternative binding
13781 (define-key org-mode-map "\C-c." 'org-time-stamp) ; Minor-mode reserved
13782 (define-key org-mode-map "\C-c!" 'org-time-stamp-inactive) ; Minor-mode r.
13783 (define-key org-mode-map "\C-c," 'org-priority) ; Minor-mode reserved
13784 (define-key org-mode-map "\C-c\C-y" 'org-evaluate-time-range)
13785 (define-key org-mode-map "\C-c>" 'org-goto-calendar)
13786 (define-key org-mode-map "\C-c<" 'org-date-from-calendar)
13787 (define-key org-mode-map [(control ?,)] 'org-cycle-agenda-files)
13788 (define-key org-mode-map "\C-c[" 'org-agenda-file-to-front)
13789 (define-key org-mode-map "\C-c]" 'org-remove-file)
13790 (define-key org-mode-map "\C-c\C-r" 'org-timeline)
13791 (define-key org-mode-map "\C-c-" 'org-table-insert-hline)
13792 (define-key org-mode-map "\C-c^" 'org-table-sort-lines)
13793 (define-key org-mode-map "\C-c\C-c" 'org-ctrl-c-ctrl-c)
13794 (define-key org-mode-map "\C-m" 'org-return)
13795 (define-key org-mode-map "\C-c?" 'org-table-current-column)
13796 (define-key org-mode-map "\C-c " 'org-table-blank-field)
13797 (define-key org-mode-map "\C-c+" 'org-table-sum)
13798 (define-key org-mode-map "\C-c=" 'org-table-eval-formula)
13799 (define-key org-mode-map "\C-c'" 'org-table-edit-formulas)
13800 (define-key org-mode-map "\C-c`" 'org-table-edit-field)
13801 (define-key org-mode-map "\C-c|" 'org-table-create-or-convert-from-region)
13802 (define-key org-mode-map "\C-c*" 'org-table-recalculate)
13803 (define-key org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks)
13804 (define-key org-mode-map "\C-c~" 'org-table-create-with-table.el)
13805 (define-key org-mode-map "\C-c\C-q" 'org-table-wrap-region)
13806 (define-key org-mode-map "\C-c\C-xa" 'org-export-as-ascii)
13807 (define-key org-mode-map "\C-c\C-x\C-a" 'org-export-as-ascii)
13808 (define-key org-mode-map "\C-c\C-xv" 'org-export-visible)
13809 (define-key org-mode-map "\C-c\C-x\C-v" 'org-export-visible)
13810 ;; OPML support is only an option for the future
13811 ;(define-key org-mode-map "\C-c\C-xo" 'org-export-as-opml)
13812 ;(define-key org-mode-map "\C-c\C-x\C-o" 'org-export-as-opml)
13813 (define-key org-mode-map "\C-c\C-xi" 'org-export-icalendar-this-file)
13814 (define-key org-mode-map "\C-c\C-x\C-i" 'org-export-icalendar-all-agenda-files)
13815 (define-key org-mode-map "\C-c\C-xc" 'org-export-icalendar-combine-agenda-files)
13816 (define-key org-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files)
13817 (define-key org-mode-map "\C-c\C-xt" 'org-insert-export-options-template)
13818 (define-key org-mode-map "\C-c:" 'org-toggle-fixed-width-section)
13819 (define-key org-mode-map "\C-c\C-xh" 'org-export-as-html)
13820 (define-key org-mode-map "\C-c\C-xx" 'org-export-as-xml)
13821 (define-key org-mode-map "\C-c\C-x\C-x" 'org-export-as-xml)
13822 (define-key org-mode-map "\C-c\C-xb" 'org-export-as-html-and-open)
13823 (define-key org-mode-map "\C-c\C-x\C-b" 'org-export-as-html-and-open)
13824
13825 (define-key org-mode-map "\C-c\C-x\C-k" 'org-cut-special)
13826 (define-key org-mode-map "\C-c\C-x\C-w" 'org-cut-special)
13827 (define-key org-mode-map "\C-c\C-x\M-w" 'org-copy-special)
13828 (define-key org-mode-map "\C-c\C-x\C-y" 'org-paste-special)
13829
13830 (define-key org-mode-map "\C-c\C-ef" 'org-publish-current-file)
13831 (define-key org-mode-map "\C-c\C-ep" 'org-publish-current-project)
13832 (define-key org-mode-map "\C-c\C-ec" 'org-publish)
13833 (define-key org-mode-map "\C-c\C-ea" 'org-publish-all)
13834 (define-key org-mode-map "\C-c\C-e\C-f" 'org-publish-current-file)
13835 (define-key org-mode-map "\C-c\C-e\C-p" 'org-publish-current-project)
13836 (define-key org-mode-map "\C-c\C-e\C-c" 'org-publish)
13837 (define-key org-mode-map "\C-c\C-e\C-a" 'org-publish-all)
13838
13839 (when (featurep 'xemacs)
13840 (define-key org-mode-map 'button3 'popup-mode-menu))
13841
13842 (defsubst org-table-p () (org-at-table-p))
13843
13844 (defun org-self-insert-command (N)
13845 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
13846 If the cursor is in a table looking at whitespace, the whitespace is
13847 overwritten, and the table is not marked as requiring realignment."
13848 (interactive "p")
13849 (if (and (org-table-p)
13850 (progn
13851 ;; check if we blank the field, and if that triggers align
13852 (and org-table-auto-blank-field
13853 (member last-command
13854 '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c))
13855 (if (or (equal (char-after) ?\ ) (looking-at "[^|\n]* |"))
13856 ;; got extra space, this field does not determine column width
13857 (let (org-table-may-need-update) (org-table-blank-field))
13858 ;; no extra space, this field may determine column width
13859 (org-table-blank-field)))
13860 t)
13861 (eq N 1)
13862 (looking-at "[^|\n]* |"))
13863 (let (org-table-may-need-update)
13864 (goto-char (1- (match-end 0)))
13865 (delete-backward-char 1)
13866 (goto-char (match-beginning 0))
13867 (self-insert-command N))
13868 (setq org-table-may-need-update t)
13869 (self-insert-command N)))
13870
13871 (defun org-delete-backward-char (N)
13872 "Like `delete-backward-char', insert whitespace at field end in tables.
13873 When deleting backwards, in tables this function will insert whitespace in
13874 front of the next \"|\" separator, to keep the table aligned. The table will
13875 still be marked for re-alignment if the field did fill the entire column,
13876 because, in this case the deletion might narrow the column."
13877 (interactive "p")
13878 (if (and (org-table-p)
13879 (eq N 1)
13880 (string-match "|" (buffer-substring (point-at-bol) (point)))
13881 (looking-at ".*?|"))
13882 (let ((pos (point))
13883 (noalign (looking-at "[^|\n\r]* |"))
13884 (c org-table-may-need-update))
13885 (backward-delete-char N)
13886 (skip-chars-forward "^|")
13887 (insert " ")
13888 (goto-char (1- pos))
13889 ;; noalign: if there were two spaces at the end, this field
13890 ;; does not determine the width of the column.
13891 (if noalign (setq org-table-may-need-update c)))
13892 (backward-delete-char N)))
13893
13894 (defun org-delete-char (N)
13895 "Like `delete-char', but insert whitespace at field end in tables.
13896 When deleting characters, in tables this function will insert whitespace in
13897 front of the next \"|\" separator, to keep the table aligned. The table will
13898 still be marked for re-alignment if the field did fill the entire column,
13899 because, in this case the deletion might narrow the column."
13900 (interactive "p")
13901 (if (and (org-table-p)
13902 (not (bolp))
13903 (not (= (char-after) ?|))
13904 (eq N 1))
13905 (if (looking-at ".*?|")
13906 (let ((pos (point))
13907 (noalign (looking-at "[^|\n\r]* |"))
13908 (c org-table-may-need-update))
13909 (replace-match (concat
13910 (substring (match-string 0) 1 -1)
13911 " |"))
13912 (goto-char pos)
13913 ;; noalign: if there were two spaces at the end, this field
13914 ;; does not determine the width of the column.
13915 (if noalign (setq org-table-may-need-update c)))
13916 (delete-char N))
13917 (delete-char N)))
13918
13919 ;; How to do this: Measure non-white length of current string
13920 ;; If equal to column width, we should realign.
13921
13922 (defun org-remap (map &rest commands)
13923 "In MAP, remap the functions given in COMMANDS.
13924 COMMANDS is a list of alternating OLDDEF NEWDEF command names."
13925 (let (new old)
13926 (while commands
13927 (setq old (pop commands) new (pop commands))
13928 (if (fboundp 'command-remapping)
13929 (define-key map (vector 'remap old) new)
13930 (substitute-key-definition old new map global-map)))))
13931
13932 (when (eq org-enable-table-editor 'optimized)
13933 ;; If the user wants maximum table support, we need to hijack
13934 ;; some standard editing functions
13935 (org-remap org-mode-map
13936 'self-insert-command 'org-self-insert-command
13937 'delete-char 'org-delete-char
13938 'delete-backward-char 'org-delete-backward-char)
13939 (define-key org-mode-map "|" 'org-force-self-insert))
13940
13941 (defun org-shiftcursor-error ()
13942 "Throw an error because Shift-Cursor command was applied in wrong context."
13943 (error "This command is active in special context like tables, headlines or timestamps"))
13944
13945 (defun org-shifttab ()
13946 "Global visibility cycling or move to previous table field.
13947 Calls `org-cycle' with argument t, or `org-table-previous-field', depending
13948 on context.
13949 See the individual commands for more information."
13950 (interactive)
13951 (cond
13952 ((org-at-table-p) (call-interactively 'org-table-previous-field))
13953 (t (call-interactively 'org-global-cycle))))
13954
13955 (defun org-shiftmetaleft ()
13956 "Promote subtree or delete table column.
13957 Calls `org-promote-subtree' or `org-table-delete-column', depending on context.
13958 See the individual commands for more information."
13959 (interactive)
13960 (cond
13961 ((org-at-table-p) (call-interactively 'org-table-delete-column))
13962 ((org-on-heading-p) (call-interactively 'org-promote-subtree))
13963 ((org-at-item-p) (call-interactively 'org-outdent-item))
13964 (t (org-shiftcursor-error))))
13965
13966 (defun org-shiftmetaright ()
13967 "Demote subtree or insert table column.
13968 Calls `org-demote-subtree' or `org-table-insert-column', depending on context.
13969 See the individual commands for more information."
13970 (interactive)
13971 (cond
13972 ((org-at-table-p) (call-interactively 'org-table-insert-column))
13973 ((org-on-heading-p) (call-interactively 'org-demote-subtree))
13974 ((org-at-item-p) (call-interactively 'org-indent-item))
13975 (t (org-shiftcursor-error))))
13976
13977 (defun org-shiftmetaup (&optional arg)
13978 "Move subtree up or kill table row.
13979 Calls `org-move-subtree-up' or `org-table-kill-row' or
13980 `org-move-item-up' depending on context. See the individual commands
13981 for more information."
13982 (interactive "P")
13983 (cond
13984 ((org-at-table-p) (call-interactively 'org-table-kill-row))
13985 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
13986 ((org-at-item-p) (call-interactively 'org-move-item-up))
13987 (t (org-shiftcursor-error))))
13988 (defun org-shiftmetadown (&optional arg)
13989 "Move subtree down or insert table row.
13990 Calls `org-move-subtree-down' or `org-table-insert-row' or
13991 `org-move-item-down', depending on context. See the individual
13992 commands for more information."
13993 (interactive "P")
13994 (cond
13995 ((org-at-table-p) (call-interactively 'org-table-insert-row))
13996 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
13997 ((org-at-item-p) (call-interactively 'org-move-item-down))
13998 (t (org-shiftcursor-error))))
13999
14000 (defun org-metaleft (&optional arg)
14001 "Promote heading or move table column to left.
14002 Calls `org-do-promote' or `org-table-move-column', depending on context.
14003 With no specific context, calls the Emacs default `backward-word'.
14004 See the individual commands for more information."
14005 (interactive "P")
14006 (cond
14007 ((org-at-table-p) (org-call-with-arg 'org-table-move-column 'left))
14008 ((or (org-on-heading-p) (org-region-active-p))
14009 (call-interactively 'org-do-promote))
14010 (t (call-interactively 'backward-word))))
14011
14012 (defun org-metaright (&optional arg)
14013 "Demote subtree or move table column to right.
14014 Calls `org-do-demote' or `org-table-move-column', depending on context.
14015 With no specific context, calls the Emacs default `forward-word'.
14016 See the individual commands for more information."
14017 (interactive "P")
14018 (cond
14019 ((org-at-table-p) (call-interactively 'org-table-move-column))
14020 ((or (org-on-heading-p) (org-region-active-p))
14021 (call-interactively 'org-do-demote))
14022 (t (call-interactively 'forward-word))))
14023
14024 (defun org-metaup (&optional arg)
14025 "Move subtree up or move table row up.
14026 Calls `org-move-subtree-up' or `org-table-move-row' or
14027 `org-move-item-up', depending on context. See the individual commands
14028 for more information."
14029 (interactive "P")
14030 (cond
14031 ((org-at-table-p) (org-call-with-arg 'org-table-move-row 'up))
14032 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
14033 ((org-at-item-p) (call-interactively 'org-move-item-up))
14034 (t (org-shiftcursor-error))))
14035
14036 (defun org-metadown (&optional arg)
14037 "Move subtree down or move table row down.
14038 Calls `org-move-subtree-down' or `org-table-move-row' or
14039 `org-move-item-down', depending on context. See the individual
14040 commands for more information."
14041 (interactive "P")
14042 (cond
14043 ((org-at-table-p) (call-interactively 'org-table-move-row))
14044 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
14045 ((org-at-item-p) (call-interactively 'org-move-item-down))
14046 (t (org-shiftcursor-error))))
14047
14048 (defun org-shiftup (&optional arg)
14049 "Increase item in timestamp or increase priority of current headline.
14050 Calls `org-timestamp-up' or `org-priority-up', depending on context.
14051 See the individual commands for more information."
14052 (interactive "P")
14053 (cond
14054 ((org-at-timestamp-p) (call-interactively 'org-timestamp-up))
14055 ((org-on-heading-p) (call-interactively 'org-priority-up))
14056 ((org-at-item-p) (call-interactively 'org-previous-item))
14057 (t (call-interactively 'org-beginning-of-item) (beginning-of-line 1))))
14058
14059 (defun org-shiftdown (&optional arg)
14060 "Decrease item in timestamp or decrease priority of current headline.
14061 Calls `org-timestamp-down' or `org-priority-down', depending on context.
14062 See the individual commands for more information."
14063 (interactive "P")
14064 (cond
14065 ((org-at-timestamp-p) (call-interactively 'org-timestamp-down))
14066 ((org-on-heading-p) (call-interactively 'org-priority-down))
14067 (t (call-interactively 'org-next-item))))
14068
14069 (defun org-shiftright ()
14070 "Next TODO keyword or timestamp one day later, depending on context."
14071 (interactive)
14072 (cond
14073 ((org-at-timestamp-p) (call-interactively 'org-timestamp-up-day))
14074 ((org-on-heading-p) (org-call-with-arg 'org-todo 'right))
14075 (t (org-shiftcursor-error))))
14076
14077 (defun org-shiftleft ()
14078 "Previous TODO keyword or timestamp one day earlier, depending on context."
14079 (interactive)
14080 (cond
14081 ((org-at-timestamp-p) (call-interactively 'org-timestamp-down-day))
14082 ((org-on-heading-p) (org-call-with-arg 'org-todo 'left))
14083 (t (org-shiftcursor-error))))
14084
14085 (defun org-copy-special ()
14086 "Copy region in table or copy current subtree.
14087 Calls `org-table-copy' or `org-copy-subtree', depending on context.
14088 See the individual commands for more information."
14089 (interactive)
14090 (call-interactively
14091 (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree)))
14092
14093 (defun org-cut-special ()
14094 "Cut region in table or cut current subtree.
14095 Calls `org-table-copy' or `org-cut-subtree', depending on context.
14096 See the individual commands for more information."
14097 (interactive)
14098 (call-interactively
14099 (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree)))
14100
14101 (defun org-paste-special (arg)
14102 "Paste rectangular region into table, or past subtree relative to level.
14103 Calls `org-table-paste-rectangle' or `org-paste-subtree', depending on context.
14104 See the individual commands for more information."
14105 (interactive "P")
14106 (if (org-at-table-p)
14107 (org-table-paste-rectangle)
14108 (org-paste-subtree arg)))
14109
14110 (defun org-ctrl-c-ctrl-c (&optional arg)
14111 "Set tags in headline, or update according to changed information at point.
14112
14113 This command does many different things, depending on context:
14114
14115 - If the cursor is in a headline, prompt for tags and insert them
14116 into the current line, aligned to `org-tags-column'. When called
14117 with prefix arg, realign all tags in the current buffer.
14118
14119 - If the cursor is in one of the special #+KEYWORD lines, this
14120 triggers scanning the buffer for these lines and updating the
14121 information.
14122
14123 - If the cursor is inside a table, realign the table. This command
14124 works even if the automatic table editor has been turned off.
14125
14126 - If the cursor is on a #+TBLFM line, re-apply the formulas to
14127 the entire table.
14128
14129 - If the cursor is inside a table created by the table.el package,
14130 activate that table.
14131
14132 - If the current buffer is a remember buffer, close note and file it.
14133 with a prefix argument, file it without further interaction to the default
14134 location.
14135
14136 - If the cursor is on a <<<target>>>, update radio targets and corresponding
14137 links in this buffer.
14138
14139 - If the cursor is on a numbered item in a plain list, renumber the
14140 ordered list."
14141 (interactive "P")
14142 (let ((org-enable-table-editor t))
14143 (cond
14144 ((and (local-variable-p 'org-finish-function (current-buffer))
14145 (fboundp org-finish-function))
14146 (funcall org-finish-function))
14147 ((org-on-target-p) (call-interactively 'org-update-radio-target-regexp))
14148 ((org-on-heading-p) (call-interactively 'org-set-tags))
14149 ((org-at-table.el-p)
14150 (require 'table)
14151 (beginning-of-line 1)
14152 (re-search-forward "|" (save-excursion (end-of-line 2) (point)))
14153 (call-interactively 'table-recognize-table))
14154 ((org-at-table-p)
14155 (org-table-maybe-eval-formula)
14156 (if arg
14157 (call-interactively 'org-table-recalculate)
14158 (org-table-maybe-recalculate-line))
14159 (call-interactively 'org-table-align))
14160 ((org-at-item-checkbox-p)
14161 (call-interactively 'org-toggle-checkbox))
14162 ((org-at-item-p)
14163 (call-interactively 'org-renumber-ordered-list))
14164 ((save-excursion (beginning-of-line 1) (looking-at "#\\+\\([A-Z]+\\)"))
14165 (cond
14166 ((equal (match-string 1) "TBLFM")
14167 ;; Recalculate the table before this line
14168 (save-excursion
14169 (beginning-of-line 1)
14170 (skip-chars-backward " \r\n\t")
14171 (if (org-at-table-p)
14172 (org-call-with-arg 'org-table-recalculate t))))
14173 (t
14174 (call-interactively 'org-mode-restart))))
14175 (t (error "C-c C-c can do nothing useful at this location.")))))
14176
14177 (defun org-mode-restart ()
14178 "Restart Org-mode, to scan again for special lines.
14179 Also updates the keyword regular expressions."
14180 (interactive)
14181 (let ((org-inhibit-startup t)) (org-mode))
14182 (message "Org-mode restarted to refresh keyword and special line setup"))
14183
14184 (defun org-return ()
14185 "Goto next table row or insert a newline.
14186 Calls `org-table-next-row' or `newline', depending on context.
14187 See the individual commands for more information."
14188 (interactive)
14189 (cond
14190 ((org-at-table-p)
14191 (org-table-justify-field-maybe)
14192 (call-interactively 'org-table-next-row))
14193 (t (newline))))
14194
14195 (defun org-meta-return (&optional arg)
14196 "Insert a new heading or wrap a region in a table.
14197 Calls `org-insert-heading' or `org-table-wrap-region', depending on context.
14198 See the individual commands for more information."
14199 (interactive "P")
14200 (cond
14201 ((org-at-table-p)
14202 (call-interactively 'org-table-wrap-region))
14203 (t (call-interactively 'org-insert-heading))))
14204
14205 ;;; Menu entries
14206
14207 ;; Define the Org-mode menus
14208 (easy-menu-define org-tbl-menu org-mode-map "Tbl menu"
14209 '("Tbl"
14210 ["Align" org-ctrl-c-ctrl-c (org-at-table-p)]
14211 ["Next Field" org-cycle (org-at-table-p)]
14212 ["Previous Field" org-shifttab (org-at-table-p)]
14213 ["Next Row" org-return (org-at-table-p)]
14214 "--"
14215 ["Blank Field" org-table-blank-field (org-at-table-p)]
14216 ["Edit Field" org-table-edit-field (org-at-table-p)]
14217 ["Copy Field from Above" org-table-copy-down (org-at-table-p)]
14218 "--"
14219 ("Column"
14220 ["Move Column Left" org-metaleft (org-at-table-p)]
14221 ["Move Column Right" org-metaright (org-at-table-p)]
14222 ["Delete Column" org-shiftmetaleft (org-at-table-p)]
14223 ["Insert Column" org-shiftmetaright (org-at-table-p)]
14224 "--"
14225 ["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])
14226 ("Row"
14227 ["Move Row Up" org-metaup (org-at-table-p)]
14228 ["Move Row Down" org-metadown (org-at-table-p)]
14229 ["Delete Row" org-shiftmetaup (org-at-table-p)]
14230 ["Insert Row" org-shiftmetadown (org-at-table-p)]
14231 ["Sort lines in region" org-table-sort-lines (org-at-table-p)]
14232 "--"
14233 ["Insert Hline" org-table-insert-hline (org-at-table-p)])
14234 ("Rectangle"
14235 ["Copy Rectangle" org-copy-special (org-at-table-p)]
14236 ["Cut Rectangle" org-cut-special (org-at-table-p)]
14237 ["Paste Rectangle" org-paste-special (org-at-table-p)]
14238 ["Fill Rectangle" org-table-wrap-region (org-at-table-p)])
14239 "--"
14240 ("Calculate"
14241 ["Set Column Formula" org-table-eval-formula (org-at-table-p)]
14242 ["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
14243 ["Edit Formulas" org-table-edit-formulas (org-at-table-p)]
14244 "--"
14245 ["Recalculate line" org-table-recalculate (org-at-table-p)]
14246 ["Recalculate all" (lambda () (interactive) (org-table-recalculate '(4))) :active (org-at-table-p) :keys "C-u C-c *"]
14247 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks (org-at-table-p)]
14248 "--"
14249 ["Sum Column/Rectangle" org-table-sum
14250 (or (org-at-table-p) (org-region-active-p))]
14251 ["Which Column?" org-table-current-column (org-at-table-p)])
14252 ["Debug Formulas"
14253 (setq org-table-formula-debug (not org-table-formula-debug))
14254 :style toggle :selected org-table-formula-debug]
14255 "--"
14256 ["Create" org-table-create (and (not (org-at-table-p))
14257 org-enable-table-editor)]
14258 ["Convert Region" org-table-convert-region (not (org-at-table-p 'any))]
14259 ["Import from File" org-table-import (not (org-at-table-p))]
14260 ["Export to File" org-table-export (org-at-table-p)]
14261 "--"
14262 ["Create/Convert from/to table.el" org-table-create-with-table.el t]))
14263
14264 (easy-menu-define org-org-menu org-mode-map "Org menu"
14265 '("Org"
14266 ["Cycle Visibility" org-cycle (or (bobp) (outline-on-heading-p))]
14267 ["Cycle Global Visibility" org-shifttab (not (org-at-table-p))]
14268 ["Sparse Tree" org-occur t]
14269 ["Show All" show-all t]
14270 "--"
14271 ["New Heading" org-insert-heading t]
14272 ("Navigate Headings"
14273 ["Up" outline-up-heading t]
14274 ["Next" outline-next-visible-heading t]
14275 ["Previous" outline-previous-visible-heading t]
14276 ["Next Same Level" outline-forward-same-level t]
14277 ["Previous Same Level" outline-backward-same-level t]
14278 "--"
14279 ["Jump" org-goto t])
14280 ("Edit Structure"
14281 ["Move Subtree Up" org-shiftmetaup (not (org-at-table-p))]
14282 ["Move Subtree Down" org-shiftmetadown (not (org-at-table-p))]
14283 "--"
14284 ["Copy Subtree" org-copy-special (not (org-at-table-p))]
14285 ["Cut Subtree" org-cut-special (not (org-at-table-p))]
14286 ["Paste Subtree" org-paste-special (not (org-at-table-p))]
14287 "--"
14288 ["Promote Heading" org-metaleft (not (org-at-table-p))]
14289 ["Promote Subtree" org-shiftmetaleft (not (org-at-table-p))]
14290 ["Demote Heading" org-metaright (not (org-at-table-p))]
14291 ["Demote Subtree" org-shiftmetaright (not (org-at-table-p))]
14292 "--"
14293 ["Archive Subtree" org-archive-subtree t]
14294 "--"
14295 ["Convert to odd levels" org-convert-to-odd-levels t]
14296 ["Convert to odd/even levels" org-convert-to-oddeven-levels t])
14297 "--"
14298 ("TODO Lists"
14299 ["TODO/DONE/-" org-todo t]
14300 ["Show TODO Tree" org-show-todo-tree t]
14301 ["Global TODO list" org-todo-list t]
14302 "--"
14303 ["Set Priority" org-priority t]
14304 ["Priority Up" org-shiftup t]
14305 ["Priority Down" org-shiftdown t])
14306 ("Dates and Scheduling"
14307 ["Timestamp" org-time-stamp t]
14308 ["Timestamp (inactive)" org-time-stamp-inactive t]
14309 ("Change Date"
14310 ["1 Day Later" org-timestamp-up-day t]
14311 ["1 Day Earlier" org-timestamp-down-day t]
14312 ["1 ... Later" org-shiftup t]
14313 ["1 ... Earlier" org-shiftdown t])
14314 ["Compute Time Range" org-evaluate-time-range t]
14315 ["Schedule Item" org-schedule t]
14316 ["Deadline" org-deadline t]
14317 "--"
14318 ["Goto Calendar" org-goto-calendar t]
14319 ["Date from Calendar" org-date-from-calendar t])
14320 "--"
14321 ["Agenda Command" org-agenda t]
14322 ("File List for Agenda")
14323 ("Special views current file"
14324 ["TODO Tree" org-show-todo-tree t]
14325 ["Check Deadlines" org-check-deadlines t]
14326 ["Timeline" org-timeline t]
14327 ["Tags Tree" org-tags-sparse-tree t])
14328 "--"
14329 ("Hyperlinks"
14330 ["Store Link (Global)" org-store-link t]
14331 ["Insert Link" org-insert-link t]
14332 ["Follow Link" org-open-at-point t]
14333 "--"
14334 ["Descriptive Links"
14335 (progn (org-add-to-invisibility-spec '(org-link)) (org-restart-font-lock))
14336 :style radio :selected (member '(org-link) buffer-invisibility-spec)]
14337 ["Literal Links"
14338 (progn
14339 (org-remove-from-invisibility-spec '(org-link)) (org-restart-font-lock))
14340 :style radio :selected (not (member '(org-link) buffer-invisibility-spec))]
14341 "--"
14342 ["Upgrade all <link> to [[link][desc]]" org-upgrade-old-links
14343 (save-excursion (goto-char (point-min))
14344 (re-search-forward "<[a-z]+:" nil t))])
14345 "--"
14346 ("Export"
14347 ["ASCII" org-export-as-ascii t]
14348 ["Export visible part..." org-export-visible t]
14349 ["HTML" org-export-as-html t]
14350 ["HTML and Open" org-export-as-html-and-open t]
14351 ["XOXO" org-export-as-xml t]
14352 "--"
14353 ["iCalendar this file" org-export-icalendar-this-file t]
14354 ["iCalendar all agenda files" org-export-icalendar-all-agenda-files
14355 :active t :keys "C-c C-x C-i"]
14356 ["iCalendar combined" org-export-icalendar-combine-agenda-files t]
14357 "--"
14358 ["Option Template" org-insert-export-options-template t]
14359 ["Toggle Fixed Width" org-toggle-fixed-width-section t])
14360 ("Publish"
14361 ["Current File" org-publish-current-file t]
14362 ["Current Project" org-publish-current-project t]
14363 ["Project..." org-publish t]
14364 ["All Projects" org-publish-all t])
14365 "--"
14366 ("Documentation"
14367 ["Show Version" org-version t]
14368 ["Info Documentation" org-info t])
14369 ("Customize"
14370 ["Browse Org Group" org-customize t]
14371 "--"
14372 ["Expand This Menu" org-create-customize-menu
14373 (fboundp 'customize-menu-create)])
14374 "--"
14375 ["Refresh setup" org-mode-restart t]
14376 ))
14377
14378 (defun org-info (&optional node)
14379 "Read documentation for Org-mode in the info system.
14380 With optional NODE, go directly to that node."
14381 (interactive)
14382 (require 'info)
14383 (Info-goto-node (format "(org)%s" (or node ""))))
14384
14385 (defun org-install-agenda-files-menu ()
14386 (let ((bl (buffer-list)))
14387 (save-excursion
14388 (while bl
14389 (set-buffer (pop bl))
14390 (if (eq major-mode 'org-mode) (setq bl nil)))
14391 (when (eq major-mode 'org-mode)
14392 (easy-menu-change
14393 '("Org") "File List for Agenda"
14394 (append
14395 (list
14396 ["Edit File List" (org-edit-agenda-file-list) t]
14397 ["Add/Move Current File to Front of List" org-agenda-file-to-front t]
14398 ["Remove Current File from List" org-remove-file t]
14399 ["Cycle through agenda files" org-cycle-agenda-files t]
14400 "--")
14401 (mapcar 'org-file-menu-entry (org-agenda-files t))))))))
14402
14403 ;;; Documentation
14404
14405 (defun org-customize ()
14406 "Call the customize function with org as argument."
14407 (interactive)
14408 (customize-browse 'org))
14409
14410 (defun org-create-customize-menu ()
14411 "Create a full customization menu for Org-mode, insert it into the menu."
14412 (interactive)
14413 (if (fboundp 'customize-menu-create)
14414 (progn
14415 (easy-menu-change
14416 '("Org") "Customize"
14417 `(["Browse Org group" org-customize t]
14418 "--"
14419 ,(customize-menu-create 'org)
14420 ["Set" Custom-set t]
14421 ["Save" Custom-save t]
14422 ["Reset to Current" Custom-reset-current t]
14423 ["Reset to Saved" Custom-reset-saved t]
14424 ["Reset to Standard Settings" Custom-reset-standard t]))
14425 (message "\"Org\"-menu now contains full customization menu"))
14426 (error "Cannot expand menu (outdated version of cus-edit.el)")))
14427
14428 ;;; Miscellaneous stuff
14429
14430 (defun org-context ()
14431 "Return a list of contexts of the current cursor position.
14432 If several contexts apply, all are returned.
14433 Each context entry is a list with a symbol naming the context, and
14434 two positions indicating start and end of the context. Possible
14435 contexts are:
14436
14437 :headline anywhere in a headline
14438 :headline-stars on the leading stars in a headline
14439 :todo-keyword on a TODO keyword (including DONE) in a headline
14440 :tags on the TAGS in a headline
14441 :priority on the priority cookie in a headline
14442 :item on the first line of a plain list item
14443 :checkbox on the checkbox in a plain list item
14444 :table in an org-mode table
14445 :table-special on a special filed in a table
14446 :table-table in a table.el table
14447 :link on a hyperline
14448 :keyword on a keyword: SCHEDULED, DEADLINE, CLOSE,COMMENT, QUOTE.
14449 :target on a <<target>>
14450 :radio-target on a <<<radio-target>>>
14451
14452 This function expects the position to be visible because it uses font-lock
14453 faces as a help to recognize the following contexts: :table-special, :link,
14454 and :keyword."
14455 (let* ((f (get-text-property (point) 'face))
14456 (faces (if (listp f) f (list f)))
14457 (p (point)) clist)
14458 ;; First the large context
14459 (cond
14460 ((org-on-heading-p)
14461 (push (list :headline (point-at-bol) (point-at-eol)) clist)
14462 (when (progn
14463 (beginning-of-line 1)
14464 (looking-at org-todo-line-tags-regexp))
14465 (push (org-point-in-group p 1 :headline-stars) clist)
14466 (push (org-point-in-group p 2 :todo-keyword) clist)
14467 (push (org-point-in-group p 4 :tags) clist))
14468 (goto-char p)
14469 (skip-chars-backward "^[\n\r \t") (or (eobp) (backward-char 1))
14470 (if (looking-at "\\[#[A-Z]\\]")
14471 (push (org-point-in-group p 0 :priority) clist)))
14472
14473 ((org-at-item-p)
14474 (push (list :item (point-at-bol)
14475 (save-excursion (org-end-of-item) (point)))
14476 clist)
14477 (and (org-at-item-checkbox-p)
14478 (push (org-point-in-group p 0 :checkbox) clist)))
14479
14480 ((org-at-table-p)
14481 (push (list :table (org-table-begin) (org-table-end)) clist)
14482 (if (memq 'org-formula faces)
14483 (push (list :table-special
14484 (previous-single-property-change p 'face)
14485 (next-single-property-change p 'face)) clist)))
14486 ((org-at-table-p 'any)
14487 (push (list :table-table) clist)))
14488 (goto-char p)
14489
14490 ;; Now the small context
14491 (cond
14492 ((org-at-timestamp-p)
14493 (push (org-point-in-group p 0 :timestamp) clist))
14494 ((memq 'org-link faces)
14495 (push (list :link
14496 (previous-single-property-change p 'face)
14497 (next-single-property-change p 'face)) clist))
14498 ((memq 'org-special-keyword faces)
14499 (push (list :keyword
14500 (previous-single-property-change p 'face)
14501 (next-single-property-change p 'face)) clist))
14502 ((org-on-target-p)
14503 (push (org-point-in-group p 0 :target) clist)
14504 (goto-char (1- (match-beginning 0)))
14505 (if (looking-at org-radio-target-regexp)
14506 (push (org-point-in-group p 0 :radio-target) clist))
14507 (goto-char p)))
14508
14509 (setq clist (nreverse (delq nil clist)))
14510 clist))
14511
14512 (defun org-point-in-group (point group &optional context)
14513 "Check if POINT is in match-group GROUP.
14514 If CONTEXT is non-nil, return a list with CONTEXT and the boundaries of the
14515 match. If the match group does ot exist or point is not inside it,
14516 return nil."
14517 (and (match-beginning group)
14518 (>= point (match-beginning group))
14519 (<= point (match-end group))
14520 (if context
14521 (list context (match-beginning group) (match-end group))
14522 t)))
14523
14524 (defun org-move-line-down (arg)
14525 "Move the current line down. With prefix argument, move it past ARG lines."
14526 (interactive "p")
14527 (let ((col (current-column))
14528 beg end pos)
14529 (beginning-of-line 1) (setq beg (point))
14530 (beginning-of-line 2) (setq end (point))
14531 (beginning-of-line (+ 1 arg))
14532 (setq pos (move-marker (make-marker) (point)))
14533 (insert (delete-and-extract-region beg end))
14534 (goto-char pos)
14535 (move-to-column col)))
14536
14537 (defun org-move-line-up (arg)
14538 "Move the current line up. With prefix argument, move it past ARG lines."
14539 (interactive "p")
14540 (let ((col (current-column))
14541 beg end pos)
14542 (beginning-of-line 1) (setq beg (point))
14543 (beginning-of-line 2) (setq end (point))
14544 (beginning-of-line (- arg))
14545 (setq pos (move-marker (make-marker) (point)))
14546 (insert (delete-and-extract-region beg end))
14547 (goto-char pos)
14548 (move-to-column col)))
14549
14550 ;; Paragraph filling stuff.
14551 ;; We want this to be just right, so use the full arsenal.
14552 ;; FIXME: This very likely does not work correctly for XEmacs, because the
14553 ;; filladapt package works slightly differently.
14554
14555 (defun org-set-autofill-regexps ()
14556 (interactive)
14557 ;; In the paragraph separator we include headlines, because filling
14558 ;; text in a line directly attached to a headline would otherwise
14559 ;; fill the headline as well.
14560 (set (make-local-variable 'paragraph-separate) "\f\\|\\*\\|[ ]*$\\|[ \t]*[:|]")
14561 ;; The paragraph starter includes hand-formatted lists.
14562 (set (make-local-variable 'paragraph-start)
14563 "\f\\|[ ]*$\\|\\([*\f]+\\)\\|[ \t]*\\([-+*]\\|[0-9]+[.)][ \t]+\\)\\|[ \t]*[:|]")
14564 ;; Inhibit auto-fill for headers, tables and fixed-width lines.
14565 ;; But only if the user has not turned off tables or fixed-width regions
14566 (set (make-local-variable 'auto-fill-inhibit-regexp)
14567 (concat "\\*\\|#"
14568 (if (or org-enable-table-editor org-enable-fixed-width-editor)
14569 (concat
14570 "\\|[ \t]*["
14571 (if org-enable-table-editor "|" "")
14572 (if org-enable-fixed-width-editor ":" "")
14573 "]"))))
14574 ;; We use our own fill-paragraph function, to make sure that tables
14575 ;; and fixed-width regions are not wrapped. That function will pass
14576 ;; through to `fill-paragraph' when appropriate.
14577 (set (make-local-variable 'fill-paragraph-function) 'org-fill-paragraph)
14578 ;; Adaptive filling: To get full control, first make sure that
14579 ;; `adaptive-fill-regexp' never matches. Then install our own matcher.
14580 (set (make-local-variable 'adaptive-fill-regexp) "\000")
14581 (set (make-local-variable 'adaptive-fill-function)
14582 'org-adaptive-fill-function))
14583
14584 (defun org-fill-paragraph (&optional justify)
14585 "Re-align a table, pass through to fill-paragraph if no table."
14586 (let ((table-p (org-at-table-p))
14587 (table.el-p (org-at-table.el-p)))
14588 (cond ((equal (char-after (point-at-bol)) ?*) t) ; skip headlines
14589 (table.el-p t) ; skip table.el tables
14590 (table-p (org-table-align) t) ; align org-mode tables
14591 (t nil)))) ; call paragraph-fill
14592
14593 ;; For reference, this is the default value of adaptive-fill-regexp
14594 ;; "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*"
14595
14596 (defun org-adaptive-fill-function ()
14597 "Return a fill prefix for org-mode files.
14598 In particular, this makes sure hanging paragraphs for hand-formatted lists
14599 work correctly."
14600 (if (looking-at " *\\([-*+] \\|[0-9]+[.)] \\)?")
14601 (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
14602
14603 ;; Functions needed for Emacs/XEmacs region compatibility
14604
14605 (defun org-add-hook (hook function &optional append local)
14606 "Add-hook, compatible with both Emacsen."
14607 (if (and local (featurep 'xemacs))
14608 (add-local-hook hook function append)
14609 (add-hook hook function append local)))
14610
14611 (defun org-region-active-p ()
14612 "Is `transient-mark-mode' on and the region active?
14613 Works on both Emacs and XEmacs."
14614 (if org-ignore-region
14615 nil
14616 (if (featurep 'xemacs)
14617 (and zmacs-regions (region-active-p))
14618 (and transient-mark-mode mark-active))))
14619
14620 (defun org-add-to-invisibility-spec (arg)
14621 "Add elements to `buffer-invisibility-spec'.
14622 See documentation for `buffer-invisibility-spec' for the kind of elements
14623 that can be added."
14624 (cond
14625 ((fboundp 'add-to-invisibility-spec)
14626 (add-to-invisibility-spec arg))
14627 ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t))
14628 (setq buffer-invisibility-spec (list arg)))
14629 (t
14630 (setq buffer-invisibility-spec
14631 (cons arg buffer-invisibility-spec)))))
14632
14633 (defun org-remove-from-invisibility-spec (arg)
14634 "Remove elements from `buffer-invisibility-spec'."
14635 (if (fboundp 'remove-from-invisibility-spec)
14636 (remove-from-invisibility-spec arg)
14637 (if (consp buffer-invisibility-spec)
14638 (setq buffer-invisibility-spec
14639 (delete arg buffer-invisibility-spec)))))
14640
14641 (defun org-in-invisibility-spec-p (arg)
14642 "Is ARG a member of `buffer-invisibility-spec'?"
14643 (if (consp buffer-invisibility-spec)
14644 (member arg buffer-invisibility-spec)
14645 nil))
14646
14647 (defun org-image-file-name-regexp ()
14648 "Return regexp matching the file names of images."
14649 (if (fboundp 'image-file-name-regexp)
14650 (image-file-name-regexp)
14651 (let ((image-file-name-extensions
14652 '("png" "jpeg" "jpg" "gif" "tiff" "tif"
14653 "xbm" "xpm" "pbm" "pgm" "ppm")))
14654 (concat "\\."
14655 (regexp-opt (nconc (mapcar 'upcase
14656 image-file-name-extensions)
14657 image-file-name-extensions)
14658 t)
14659 "\\'"))))
14660
14661 ;; Functions needed for compatibility with old outline.el.
14662
14663 ;; Programming for the old outline.el (that uses selective display
14664 ;; instead of `invisible' text properties) is a nightmare, mostly
14665 ;; because regular expressions can no longer be anchored at
14666 ;; beginning/end of line. Therefore a number of function need special
14667 ;; treatment when the old outline.el is being used.
14668
14669 ;; The following functions capture almost the entire compatibility code
14670 ;; between the different versions of outline-mode. The only other
14671 ;; places where this is important are the font-lock-keywords, and in
14672 ;; `org-export-visible'. Search for `org-noutline-p' to find them.
14673
14674 ;; C-a should go to the beginning of a *visible* line, also in the
14675 ;; new outline.el. I guess this should be patched into Emacs?
14676 (defun org-beginning-of-line ()
14677 "Go to the beginning of the current line. If that is invisible, continue
14678 to a visible line beginning. This makes the function of C-a more intuitive."
14679 (interactive)
14680 (beginning-of-line 1)
14681 (if (bobp)
14682 nil
14683 (backward-char 1)
14684 (if (org-invisible-p)
14685 (while (and (not (bobp)) (org-invisible-p))
14686 (backward-char 1)
14687 (beginning-of-line 1))
14688 (forward-char 1))))
14689
14690 (when org-noutline-p
14691 (define-key org-mode-map "\C-a" 'org-beginning-of-line))
14692 ;; FIXME: should I use substitute-key-definition to reach other bindings
14693 ;; of beginning-of-line?
14694
14695 (defun org-invisible-p ()
14696 "Check if point is at a character currently not visible."
14697 (if org-noutline-p
14698 ;; Early versions of noutline don't have `outline-invisible-p'.
14699 (if (fboundp 'outline-invisible-p)
14700 (outline-invisible-p)
14701 (get-char-property (point) 'invisible))
14702 (save-excursion
14703 (skip-chars-backward "^\r\n")
14704 (equal (char-before) ?\r))))
14705
14706 (defun org-invisible-p2 ()
14707 "Check if point is at a character currently not visible."
14708 (save-excursion
14709 (if org-noutline-p
14710 (progn
14711 (if (and (eolp) (not (bobp))) (backward-char 1))
14712 ;; Early versions of noutline don't have `outline-invisible-p'.
14713 (if (fboundp 'outline-invisible-p)
14714 (outline-invisible-p)
14715 (get-char-property (point) 'invisible)))
14716 (skip-chars-backward "^\r\n")
14717 (equal (char-before) ?\r))))
14718
14719 (defun org-back-to-heading (&optional invisible-ok)
14720 "Move to previous heading line, or beg of this line if it's a heading.
14721 Only visible heading lines are considered, unless INVISIBLE-OK is non-nil."
14722 (if org-noutline-p
14723 (outline-back-to-heading invisible-ok)
14724 (if (and (or (bobp) (memq (char-before) '(?\n ?\r)))
14725 (looking-at outline-regexp))
14726 t
14727 (if (re-search-backward (concat (if invisible-ok "\\([\r\n]\\|^\\)" "^")
14728 outline-regexp)
14729 nil t)
14730 (if invisible-ok
14731 (progn (goto-char (or (match-end 1) (match-beginning 0)))
14732 (looking-at outline-regexp)))
14733 (error "Before first heading")))))
14734
14735 (defun org-on-heading-p (&optional invisible-ok)
14736 "Return t if point is on a (visible) heading line.
14737 If INVISIBLE-OK is non-nil, an invisible heading line is ok too."
14738 (if org-noutline-p
14739 (outline-on-heading-p 'invisible-ok)
14740 (save-excursion
14741 (skip-chars-backward "^\n\r")
14742 (and (looking-at outline-regexp)
14743 (or invisible-ok
14744 (bobp)
14745 (equal (char-before) ?\n))))))
14746
14747 (defun org-on-target-p ()
14748 (let ((pos (point)))
14749 (save-excursion
14750 (skip-chars-forward "<")
14751 (and (re-search-backward "<<" nil t)
14752 (or (looking-at org-radio-target-regexp)
14753 (looking-at org-target-regexp))
14754 (<= (match-beginning 0) pos)
14755 (>= (1+ (match-end 0)) pos)))))
14756
14757 (defun org-up-heading-all (arg)
14758 "Move to the heading line of which the present line is a subheading.
14759 This function considers both visible and invisible heading lines.
14760 With argument, move up ARG levels."
14761 (if org-noutline-p
14762 (if (fboundp 'outline-up-heading-all)
14763 (outline-up-heading-all arg) ; emacs 21 version of outline.el
14764 (outline-up-heading arg t)) ; emacs 22 version of outline.el
14765 (org-back-to-heading t)
14766 (looking-at outline-regexp)
14767 (if (<= (- (match-end 0) (match-beginning 0)) arg)
14768 (error "Cannot move up %d levels" arg)
14769 (re-search-backward
14770 (concat "[\n\r]" (regexp-quote
14771 (make-string (- (match-end 0) (match-beginning 0) arg)
14772 ?*))
14773 "[^*]"))
14774 (forward-char 1))))
14775
14776 (defun org-show-hidden-entry ()
14777 "Show an entry where even the heading is hidden."
14778 (save-excursion
14779 (if (not org-noutline-p)
14780 (progn
14781 (org-back-to-heading t)
14782 (org-flag-heading nil)))
14783 (org-show-entry)))
14784
14785 (defun org-check-occur-regexp (regexp)
14786 "If REGEXP starts with \"^\", modify it to check for \\r as well.
14787 Of course, only for the old outline mode."
14788 (if org-noutline-p
14789 regexp
14790 (if (string-match "^\\^" regexp)
14791 (concat "[\n\r]" (substring regexp 1))
14792 regexp)))
14793
14794 (defun org-flag-heading (flag &optional entry)
14795 "Flag the current heading. FLAG non-nil means make invisible.
14796 When ENTRY is non-nil, show the entire entry."
14797 (save-excursion
14798 (org-back-to-heading t)
14799 (if (not org-noutline-p)
14800 ;; Make the current headline visible
14801 (outline-flag-region (max 1 (1- (point))) (point) (if flag ?\r ?\n)))
14802 ;; Check if we should show the entire entry
14803 (if entry
14804 (progn
14805 (org-show-entry)
14806 (save-excursion
14807 (and (outline-next-heading)
14808 (org-flag-heading nil))))
14809 (outline-flag-region (max 1 (1- (point)))
14810 (save-excursion (outline-end-of-heading) (point))
14811 (if org-noutline-p
14812 flag
14813 (if flag ?\r ?\n))))))
14814
14815 (defun org-end-of-subtree (&optional invisible-OK)
14816 ;; This is an exact copy of the original function, but it uses
14817 ;; `org-back-to-heading', to make it work also in invisible
14818 ;; trees. And is uses an invisible-OK argument.
14819 ;; Under Emacs this is not needed, but the old outline.el needs this fix.
14820 (org-back-to-heading invisible-OK)
14821 (let ((first t)
14822 (level (funcall outline-level)))
14823 (while (and (not (eobp))
14824 (or first (> (funcall outline-level) level)))
14825 (setq first nil)
14826 (outline-next-heading))
14827 (if (memq (preceding-char) '(?\n ?\^M))
14828 (progn
14829 ;; Go to end of line before heading
14830 (forward-char -1)
14831 (if (memq (preceding-char) '(?\n ?\^M))
14832 ;; leave blank line before heading
14833 (forward-char -1))))))
14834
14835 (defun org-show-subtree ()
14836 "Show everything after this heading at deeper levels."
14837 (outline-flag-region
14838 (point)
14839 (save-excursion
14840 (outline-end-of-subtree) (outline-next-heading) (point))
14841 (if org-noutline-p nil ?\n)))
14842
14843 (defun org-show-entry ()
14844 "Show the body directly following this heading.
14845 Show the heading too, if it is currently invisible."
14846 (interactive)
14847 (save-excursion
14848 (org-back-to-heading t)
14849 (outline-flag-region
14850 (max 1 (1- (point)))
14851 (save-excursion
14852 (re-search-forward (concat "[\r\n]\\(" outline-regexp "\\)") nil 'move)
14853 (or (match-beginning 1) (point-max)))
14854 (if org-noutline-p nil ?\n))))
14855
14856 (defun org-make-options-regexp (kwds)
14857 "Make a regular expression for keyword lines."
14858 (concat
14859 (if org-noutline-p "^" "[\n\r]")
14860 "#?[ \t]*\\+\\("
14861 (mapconcat 'regexp-quote kwds "\\|")
14862 "\\):[ \t]*"
14863 (if org-noutline-p "\\(.+\\)" "\\([^\n\r]+\\)")))
14864
14865 ;; Make `bookmark-jump' show the jump location if it was hidden.
14866 (eval-after-load "bookmark"
14867 '(if (boundp 'bookmark-after-jump-hook)
14868 ;; We can use the hook
14869 (add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide)
14870 ;; Hook not available, use advice
14871 (defadvice bookmark-jump (after org-make-visible activate)
14872 "Make the position visible."
14873 (org-bookmark-jump-unhide))))
14874
14875 (defun org-bookmark-jump-unhide ()
14876 "Unhide the current position, to show the bookmark location."
14877 (and (eq major-mode 'org-mode)
14878 (or (org-invisible-p)
14879 (save-excursion (goto-char (max (point-min) (1- (point))))
14880 (org-invisible-p)))
14881 (org-show-hierarchy-above)))
14882
14883 ;;; Finish up
14884
14885 (provide 'org)
14886
14887 (run-hooks 'org-load-hook)
14888
14889
14890 ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
14891 ;;; org.el ends here
14892