Release 4.34
[org-mode.git] / org.el
blob93c73d4fe48436df585a7c80275c121326186b8b
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.34
9 ;;
10 ;; This file is part of GNU Emacs.
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28 ;;; Commentary:
30 ;; Org-mode is a mode for keeping notes, maintaining ToDo lists, and doing
31 ;; project planning with a fast and effective plain-text system.
33 ;; Org-mode develops organizational tasks around NOTES files that contain
34 ;; information about projects as plain text. Org-mode is implemented on
35 ;; top of outline-mode, which makes it possible to keep the content of
36 ;; large files well structured. Visibility cycling and structure editing
37 ;; help to work with the tree. Tables are easily created with a built-in
38 ;; table editor. Org-mode supports ToDo items, deadlines, time stamps,
39 ;; and scheduling. It dynamically compiles entries into an agenda that
40 ;; utilizes and smoothly integrates much of the Emacs calendar and diary.
41 ;; Plain text URL-like links connect to websites, emails, Usenet
42 ;; messages, BBDB entries, and any files related to the projects. For
43 ;; printing and sharing of notes, an Org-mode file can be exported as a
44 ;; structured ASCII file, as HTML, or (todo and agenda items only) as an
45 ;; iCalendar file. It can also serve as a publishing tool for a set of
46 ;; linked webpages.
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.
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)
60 ;; Furthermore you need to activate font-lock-mode in org-mode buffers.
61 ;; either of the following two lins will do the trick:
63 ;; (global-font-lock-mode 1) ; for all buffers
64 ;; (add-hook 'org-mode-hook 'turn-on-font-lock) ; org-mode buffers only
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:
70 ;; (require 'org-install)
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:
78 ;; MY PROJECTS -*- mode: org; -*-
80 ;; which will select Org-mode for this buffer no matter what the file's
81 ;; name is.
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.
91 ;; Recent changes
92 ;; --------------
93 ;; Version 4.34
94 ;; - Bug fixes.
96 ;; Version 4.33
97 ;; - New commands to move through plain lists: S-up and S-down.
98 ;; - Bug fixes and documentation update.
100 ;; Version 4.32
101 ;; - Fast (single-key-per-tag) interface for setting TAGS.
102 ;; - The list of legal tags can be configured globally and locally.
103 ;; - Elisp and Info links (thanks to Todd Neal).
104 ;; - `org-export-publishing-directory' can be an alist, with different
105 ;; directories for different export types.
106 ;; - All context-sensitive commands use `call-interactively' to dispatch.
107 ;; - `org-confirm-shell-links' renamed to `org-confirm-shell-link-function'.
108 ;; - Bug fixes.
110 ;; Version 4.31
111 ;; - Bug fixes.
113 ;; Version 4.30
114 ;; - Modified installation: Autoloads have been collected in org-install.el.
115 ;; - Logging (org-log-done) is now a #+STARTUP option.
116 ;; - Checkboxes in plain list items, following up on Frank Ruell's idea.
117 ;; - File links inserted with C-c C-l will use relative paths if the linked
118 ;; file is in the current directory or a subdirectory of it.
119 ;; - New variable `org-link-file-path-type' to specify preference for
120 ;; relative and absolute paths.
121 ;; - New CSS classes for tags, timestamps, timestamp keywords.
122 ;; - Bug and typo fixes.
124 ;; Version 4.29
125 ;; - Inlining images in HTML export now depends on wheather the link
126 ;; contains a description or not.
127 ;; - TODO items can be scheduled from the global TODO list using C-c C-s.
128 ;; - TODO items already scheduled can be made to disappear from the global
129 ;; todo list, see `org-agenda-todo-ignore-scheduled'.
130 ;; - In Tables, formulas may also be Lisp forms.
131 ;; - Exporting the visible part of an outline with `C-c C-x v' works now
132 ;; for all available exporters.
133 ;; - Bug fixes, lots of them :-(
135 ;; Version 4.28
136 ;; - Bug fixes.
138 ;; Version 4.27
139 ;; - HTML exporter generalized to receive external options.
140 ;; As part of the process, author, email and date have been moved to the
141 ;; end of the HTML file.
142 ;; - Support for customizable file search in file links.
143 ;; - BibTeX database links as first application of the above.
144 ;; - New option `org-agenda-todo-list-sublevels' to turn off listing TODO
145 ;; entries that are sublevels of another TODO entry.
148 ;;; Code:
150 (eval-when-compile
151 (require 'cl)
152 (require 'calendar))
153 (require 'outline)
154 (require 'time-date)
155 (require 'easymenu)
157 ;;; Customization variables
159 (defvar org-version "4.34"
160 "The version number of the file org.el.")
161 (defun org-version ()
162 (interactive)
163 (message "Org-mode version %s" org-version))
165 ;; The following constant is for compatibility with different versions
166 ;; of outline.el.
167 (defconst org-noutline-p (featurep 'noutline)
168 "Are we using the new outline mode?")
169 (defconst org-xemacs-p (featurep 'xemacs)) ; not used by org.el itself
170 (defconst org-format-transports-properties-p
171 (let ((x "a"))
172 (add-text-properties 0 1 '(test t) x)
173 (get-text-property 0 'test (format "%s" x)))
174 "Does format transport text properties?")
176 (defgroup org nil
177 "Outline-based notes management and organizer."
178 :tag "Org"
179 :group 'outlines
180 :group 'hypermedia
181 :group 'calendar)
183 (defgroup org-startup nil
184 "Options concerning startup of Org-mode."
185 :tag "Org Startup"
186 :group 'org)
188 (defcustom org-startup-folded t
189 "Non-nil means, entering Org-mode will switch to OVERVIEW.
190 This can also be configured on a per-file basis by adding one of
191 the following lines anywhere in the buffer:
193 #+STARTUP: fold
194 #+STARTUP: nofold
195 #+STARTUP: content"
196 :group 'org-startup
197 :type '(choice
198 (const :tag "nofold: show all" nil)
199 (const :tag "fold: overview" t)
200 (const :tag "content: all headlines" content)))
202 (defcustom org-startup-truncated t
203 "Non-nil means, entering Org-mode will set `truncate-lines'.
204 This is useful since some lines containing links can be very long and
205 uninteresting. Also tables look terrible when wrapped."
206 :group 'org-startup
207 :type 'boolean)
209 (defcustom org-startup-align-all-tables nil
210 "Non-nil means, align all tables when visiting a file.
211 This is useful when the column width in tables is forced with <N> cookies
212 in table fields. Such tables will look correct only after the first re-align.
213 This can also be configured on a per-file basis by adding one of
214 the following lines anywhere in the buffer:
215 #+STARTUP: align
216 #+STARTUP: noalign"
217 :group 'org-startup
218 :type 'boolean)
220 (defcustom org-startup-with-deadline-check nil
221 "Non-nil means, entering Org-mode will run the deadline check.
222 This means, if you start editing an org file, you will get an
223 immediate reminder of any due deadlines.
224 This can also be configured on a per-file basis by adding one of
225 the following lines anywhere in the buffer:
226 #+STARTUP: dlcheck
227 #+STARTUP: nodlcheck"
228 :group 'org-startup
229 :type 'boolean)
231 (defcustom org-insert-mode-line-in-empty-file nil
232 "Non-nil means insert the first line setting Org-mode in empty files.
233 When the function `org-mode' is called interactively in an empty file, this
234 normally means that the file name does not automatically trigger Org-mode.
235 To ensure that the file will always be in Org-mode in the future, a
236 line enforcing Org-mode will be inserted into the buffer, if this option
237 has been set."
238 :group 'org-startup
239 :type 'boolean)
241 (defcustom org-CUA-compatible nil
242 "Non-nil means use alternative key bindings for S-<cursor movement>.
243 Org-mode used S-<cursor movement> for changing timestamps and priorities.
244 S-<cursor movement> is also used for example by `CUA-mode' to select text.
245 If you want to use Org-mode together with `CUA-mode', Org-mode needs to use
246 alternative bindings. Setting this variable to t will replace the following
247 keys both in Org-mode and in the Org-agenda buffer.
249 S-RET -> C-S-RET
250 S-up -> M-p
251 S-down -> M-n
252 S-left -> M--
253 S-right -> M-+
255 If you do not like the alternative keys, take a look at the variable
256 `org-disputed-keys'.
258 This option is only relevant at load-time of Org-mode. Changing it requires
259 a restart of Emacs to become effective."
260 :group 'org-startup
261 :type 'boolean)
263 (defvar org-disputed-keys
264 '((S-up [(shift up)] [(meta ?p)])
265 (S-down [(shift down)] [(meta ?n)])
266 (S-left [(shift left)] [(meta ?-)])
267 (S-right [(shift right)] [(meta ?+)])
268 (S-return [(shift return)] [(control shift return)]))
269 "Keys for which Org-mode and other modes compete.
270 This is an alist, cars are symbols for lookup, 1st element is the default key,
271 second element will be used when `org-CUA-compatible' is t.")
273 (defun org-key (key)
274 "Select a key according to `org-CUA-compatible'."
275 (nth (if org-CUA-compatible 2 1)
276 (or (assq key org-disputed-keys)
277 (error "Invalid Key %s in `org-key'" key))))
279 (defcustom org-ellipsis nil
280 "The ellipsis to use in the Org-mode outline.
281 When nil, just use the standard three dots. When a string, use that instead,
282 and just in Org-mode (which will then use its own display table).
283 Changing this requires executing `M-x org-mode' in a buffer to become
284 effective."
285 :group 'org-startup
286 :type '(choice (const :tag "Default" nil)
287 (string :tag "String" :value "...#")))
289 (defvar org-display-table nil
290 "The display table for org-mode, in case `org-ellipsis' is non-nil.")
292 (defgroup org-keywords nil
293 "Keywords in Org-mode."
294 :tag "Org Keywords"
295 :group 'org)
297 (defcustom org-deadline-string "DEADLINE:"
298 "String to mark deadline entries.
299 A deadline is this string, followed by a time stamp. Should be a word,
300 terminated by a colon. You can insert a schedule keyword and
301 a timestamp with \\[org-deadline].
302 Changes become only effective after restarting Emacs."
303 :group 'org-keywords
304 :type 'string)
306 (defcustom org-scheduled-string "SCHEDULED:"
307 "String to mark scheduled TODO entries.
308 A schedule 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-schedule].
311 Changes become only effective after restarting Emacs."
312 :group 'org-keywords
313 :type 'string)
315 (defcustom org-closed-string "CLOSED:"
316 "String used as the prefix for timestamps logging closing a TODO entry."
317 :group 'org-keywords
318 :type 'string)
320 (defcustom org-comment-string "COMMENT"
321 "Entries starting with this keyword will never be exported.
322 An entry can be toggled between COMMENT and normal with
323 \\[org-toggle-comment].
324 Changes become only effective after restarting Emacs."
325 :group 'org-keywords
326 :type 'string)
328 (defcustom org-quote-string "QUOTE"
329 "Entries starting with this keyword will be exported in fixed-width font.
330 Quoting applies only to the text in the entry following the headline, and does
331 not extend beyond the next headline, even if that is lower level.
332 An entry can be toggled between QUOTE and normal with
333 \\[org-toggle-fixed-width-section]."
334 :group 'org-keywords
335 :type 'string)
337 (defgroup org-structure nil
338 "Options concerning the general structure of Org-mode files."
339 :tag "Org Structure"
340 :group 'org)
342 (defgroup org-cycle nil
343 "Options concerning visibility cycling in Org-mode."
344 :tag "Org Cycle"
345 :group 'org-structure)
347 (defcustom org-cycle-global-at-bob t
348 "Cycle globally if cursor is at beginning of buffer and not at a headline.
349 This makes it possible to do global cycling without having to use S-TAB or
350 C-u TAB. For this special case to work, the first line of the buffer
351 must not be a headline - it may be empty ot some other text. When used in
352 this way, `org-cycle-hook' is disables temporarily, to make sure the
353 cursor stays at the beginning of the buffer.
354 When this option is nil, don't do anything special at the beginning
355 of the buffer."
356 :group 'org-cycle
357 :type 'boolean)
359 (defcustom org-cycle-emulate-tab t
360 "Where should `org-cycle' emulate TAB.
361 nil Never
362 white Only in completely white lines
363 t Everywhere except in headlines"
364 :group 'org-cycle
365 :type '(choice (const :tag "Never" nil)
366 (const :tag "Only in completely white lines" white)
367 (const :tag "Everywhere except in headlines" t)
370 (defcustom org-cycle-hook '(org-optimize-window-after-visibility-change)
371 "Hook that is run after `org-cycle' has changed the buffer visibility.
372 The function(s) in this hook must accept a single argument which indicates
373 the new state that was set by the most recent `org-cycle' command. The
374 argument is a symbol. After a global state change, it can have the values
375 `overview', `content', or `all'. After a local state change, it can have
376 the values `folded', `children', or `subtree'."
377 :group 'org-cycle
378 :type 'hook)
380 (defgroup org-edit-structure nil
381 "Options concerning structure editing in Org-mode."
382 :tag "Org Edit Structure"
383 :group 'org-structure)
385 (defcustom org-odd-levels-only nil
386 "Non-nil means, skip even levels and only use odd levels for the outline.
387 This has the effect that two stars are being added/taken away in
388 promotion/demotion commands. It also influences how levels are
389 handled by the exporters.
390 Changing it requires restart of `font-lock-mode' to become effective
391 for fontification also in regions already fontified.
392 You may also set this on a per-file basis by adding one of the following
393 lines to the buffer:
395 #+STARTUP: odd
396 #+STARTUP: oddeven"
397 :group 'org-edit-structure
398 :group 'org-font-lock
399 :type 'boolean)
401 (defcustom org-adapt-indentation t
402 "Non-nil means, adapt indentation when promoting and demoting.
403 When this is set and the *entire* text in an entry is indented, the
404 indentation is increased by one space in a demotion command, and
405 decreased by one in a promotion command. If any line in the entry
406 body starts at column 0, indentation is not changed at all."
407 :group 'org-edit-structure
408 :type 'boolean)
410 (defcustom org-insert-heading-hook nil
411 "Hook being run after inserting a new heading."
412 :group 'org-edit-structure
413 :type 'boolean)
415 (defcustom org-enable-fixed-width-editor t
416 "Non-nil means, lines starting with \":\" are treated as fixed-width.
417 This currently only means, they are never auto-wrapped.
418 When nil, such lines will be treated like ordinary lines.
419 See also the QUOTE keyword."
420 :group 'org-edit-structure
421 :type 'boolean)
423 (defgroup org-sparse-trees nil
424 "Options concerning sparse trees in Org-mode."
425 :tag "Org Sparse Trees"
426 :group 'org-structure)
428 (defcustom org-highlight-sparse-tree-matches t
429 "Non-nil means, highlight all matches that define a sparse tree.
430 The highlights will automatically disappear the next time the buffer is
431 changed by an edit command."
432 :group 'org-sparse-trees
433 :type 'boolean)
435 (defcustom org-show-hierarchy-above t
436 "Non-nil means, show full hierarchy when showing a spot in the tree.
437 Turning this off makes sparse trees more compact, but also less clear."
438 :group 'org-sparse-trees
439 :type 'boolean)
441 (defcustom org-show-following-heading t
442 "Non-nil means, show heading following match in `org-occur'.
443 When doing an `org-occur' it is useful to show the headline which
444 follows the match, even if they do not match the regexp. This makes it
445 easier to edit directly inside the sparse tree. However, if you use
446 `org-occur' mainly as an overview, the following headlines are
447 unnecessary clutter."
448 :group 'org-sparse-trees
449 :type 'boolean)
451 (defcustom org-occur-hook '(org-first-headline-recenter)
452 "Hook that is run after `org-occur' has constructed a sparse tree.
453 This can be used to recenter the window to show as much of the structure
454 as possible."
455 :group 'org-sparse-trees
456 :type 'hook)
458 (defgroup org-plain-lists nil
459 "Options concerning plain lists in Org-mode."
460 :tag "Org Plain lists"
461 :group 'org-structure)
463 (defcustom org-cycle-include-plain-lists nil
464 "Non-nil means, include plain lists into visibility cycling.
465 This means that during cycling, plain list items will *temporarily* be
466 interpreted as outline headlines with a level given by 1000+i where i is the
467 indentation of the bullet. In all other operations, plain list items are
468 not seen as headlines. For example, you cannot assign a TODO keyword to
469 such an item."
470 :group 'org-plain-lists
471 :type 'boolean)
474 (defcustom org-plain-list-ordered-item-terminator t
475 "The character that makes a line with leading number an ordered list item.
476 Valid values are ?. and ?\). To get both terminators, use t. While
477 ?. may look nicer, it creates the danger that a line with leading
478 number may be incorrectly interpreted as an item. ?\) therefore is
479 the safe choice."
480 :group 'org-plain-lists
481 :type '(choice (const :tag "dot like in \"2.\"" ?.)
482 (const :tag "paren like in \"2)\"" ?\))
483 (const :tab "both" t)))
485 (defcustom org-auto-renumber-ordered-lists t
486 "Non-nil means, automatically renumber ordered plain lists.
487 Renumbering happens when the sequence have been changed with
488 \\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands,
489 use \\[org-ctrl-c-ctrl-c] to trigger renumbering."
490 :group 'org-plain-lists
491 :type 'boolean)
493 (defgroup org-archive nil
494 "Options concerning archiving in Org-mode."
495 :tag "Org Archive"
496 :group 'org-structure)
498 (defcustom org-archive-location "%s_archive::"
499 "The location where subtrees should be archived.
500 This string consists of two parts, separated by a double-colon.
502 The first part is a file name - when omitted, archiving happens in the same
503 file. %s will be replaced by the current file name (without directory part).
504 Archiving to a different file is useful to keep archived entries from
505 contributing to the Org-mode Agenda.
507 The part after the double colon is a headline. The archived entries will be
508 filed under that headline. When omitted, the subtrees are simply filed away
509 at the end of the file, as top-level entries.
511 Here are a few examples:
512 \"%s_archive::\"
513 If the current file is Projects.org, archive in file
514 Projects.org_archive, as top-level trees. This is the default.
516 \"::* Archived Tasks\"
517 Archive in the current file, under the top-level headline
518 \"* Archived Tasks\".
520 \"~/org/archive.org::\"
521 Archive in file ~/org/archive.org (absolute path), as top-level trees.
523 \"basement::** Finished Tasks\"
524 Archive in file ./basement (relative path), as level 3 trees
525 below the level 2 heading \"** Finished Tasks\".
527 You may set this option on a per-file basis by adding to the buffer a
528 line like
530 #+ARCHIVE: basement::** Finished Tasks"
531 :group 'org-archive
532 :type 'string)
534 (defcustom org-archive-mark-done t
535 "Non-nil means, mark archived entries as DONE."
536 :group 'org-archive
537 :type 'boolean)
539 (defcustom org-archive-stamp-time t
540 "Non-nil means, add a time stamp to archived entries.
541 The time stamp will be added directly after the TODO state keyword in the
542 first line, so it is probably best to use this in combinations with
543 `org-archive-mark-done'."
544 :group 'org-archive
545 :type 'boolean)
547 (defgroup org-table nil
548 "Options concerning tables in Org-mode."
549 :tag "Org Table"
550 :group 'org)
552 (defcustom org-enable-table-editor 'optimized
553 "Non-nil means, lines starting with \"|\" are handled by the table editor.
554 When nil, such lines will be treated like ordinary lines.
556 When equal to the symbol `optimized', the table editor will be optimized to
557 do the following:
558 - Use automatic overwrite mode in front of whitespace in table fields.
559 This make the structure of the table stay in tact as long as the edited
560 field does not exceed the column width.
561 - Minimize the number of realigns. Normally, the table is aligned each time
562 TAB or RET are pressed to move to another field. With optimization this
563 happens only if changes to a field might have changed the column width.
564 Optimization requires replacing the functions `self-insert-command',
565 `delete-char', and `backward-delete-char' in Org-mode buffers, with a
566 slight (in fact: unnoticeable) speed impact for normal typing. Org-mode is
567 very good at guessing when a re-align will be necessary, but you can always
568 force one with \\[org-ctrl-c-ctrl-c].
570 If you would like to use the optimized version in Org-mode, but the
571 un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'.
573 This variable can be used to turn on and off the table editor during a session,
574 but in order to toggle optimization, a restart is required.
576 See also the variable `org-table-auto-blank-field'."
577 :group 'org-table
578 :type '(choice
579 (const :tag "off" nil)
580 (const :tag "on" t)
581 (const :tag "on, optimized" optimized)))
583 (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized)
584 "Non-nil means, use the optimized table editor version for `orgtbl-mode'.
585 In the optimized version, the table editor takes over all simple keys that
586 normally just insert a character. In tables, the characters are inserted
587 in a way to minimize disturbing the table structure (i.e. in overwrite mode
588 for empty fields). Outside tables, the correct binding of the keys is
589 restored.
591 The default for this option is t if the optimized version is also used in
592 Org-mode. See the variable `org-enable-table-editor' for details. Changing
593 this variable requires a restart of Emacs to become effective."
594 :group 'org-table
595 :type 'boolean)
597 (defgroup org-table-settings nil
598 "Settings for tables in Org-mode."
599 :tag "Org Table Settings"
600 :group 'org-table)
602 (defcustom org-table-default-size "5x2"
603 "The default size for newly created tables, Columns x Rows."
604 :group 'org-table-settings
605 :type 'string)
607 (defcustom org-table-number-regexp "^[<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*$"
608 "Regular expression for recognizing numbers in table columns.
609 If a table column contains mostly numbers, it will be aligned to the
610 right. If not, it will be aligned to the left.
612 The default value of this option is a regular expression which allows
613 anything which looks remotely like a number as used in scientific
614 context. For example, all of the following will be considered a
615 number:
616 12 12.2 2.4e-08 2x10^12 4.034+-0.02 2.7(10) >3.5
618 Other options offered by the customize interface are more restrictive."
619 :group 'org-table-settings
620 :type '(choice
621 (const :tag "Positive Integers"
622 "^[0-9]+$")
623 (const :tag "Integers"
624 "^[-+]?[0-9]+$")
625 (const :tag "Floating Point Numbers"
626 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.[0-9]*\\)$")
627 (const :tag "Floating Point Number or Integer"
628 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.?[0-9]*\\)$")
629 (const :tag "Exponential, Floating point, Integer"
630 "^[-+]?[0-9.]+\\([eEdD][-+0-9]+\\)?$")
631 (const :tag "Very General Number-Like"
632 "^[<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*$")
633 (string :tag "Regexp:")))
635 (defcustom org-table-number-fraction 0.5
636 "Fraction of numbers in a column required to make the column align right.
637 In a column all non-white fields are considered. If at least this
638 fraction of fields is matched by `org-table-number-fraction',
639 alignment to the right border applies."
640 :group 'org-table-settings
641 :type 'number)
643 (defgroup org-table-editing nil
644 "Bahavior of tables during editing in Org-mode."
645 :tag "Org Table Editing"
646 :group 'org-table)
648 (defcustom org-table-automatic-realign t
649 "Non-nil means, automatically re-align table when pressing TAB or RETURN.
650 When nil, aligning is only done with \\[org-table-align], or after column
651 removal/insertion."
652 :group 'org-table-editing
653 :type 'boolean)
655 (defcustom org-table-limit-column-width t ;kw
656 "Non-nil means, allow to limit the width of table columns with <N> fields."
657 :group 'org-table-editing
658 :type 'boolean)
660 (defcustom org-table-auto-blank-field t
661 "Non-nil means, automatically blank table field when starting to type into it.
662 This only happens when typing immediately after a field motion
663 command (TAB, S-TAB or RET).
664 Only relevant when `org-enable-table-editor' is equal to `optimized'."
665 :group 'org-table-editing
666 :type 'boolean)
668 (defcustom org-table-tab-jumps-over-hlines t
669 "Non-nil means, tab in the last column of a table with jump over a hline.
670 If a horizontal separator line is following the current line,
671 `org-table-next-field' can either create a new row before that line, or jump
672 over the line. When this option is nil, a new line will be created before
673 this line."
674 :group 'org-table-editing
675 :type 'boolean)
677 (defcustom org-table-tab-recognizes-table.el t
678 "Non-nil means, TAB will automatically notice a table.el table.
679 When it sees such a table, it moves point into it and - if necessary -
680 calls `table-recognize-table'."
681 :group 'org-table-editing
682 :type 'boolean)
684 (defgroup org-table-calculation nil
685 "Options concerning tables in Org-mode."
686 :tag "Org Table Calculation"
687 :group 'org-table)
689 (defcustom org-table-copy-increment t
690 "Non-nil means, increment when copying current field with \\[org-table-copy-down]."
691 :group 'org-table-calculation
692 :type 'boolean)
694 (defcustom org-calc-default-modes
695 '(calc-internal-prec 12
696 calc-float-format (float 5)
697 calc-angle-mode deg
698 calc-prefer-frac nil
699 calc-symbolic-mode nil
700 calc-date-format (YYYY "-" MM "-" DD " " Www (" " HH ":" mm))
701 calc-display-working-message t
703 "List with Calc mode settings for use in calc-eval for table formulas.
704 The list must contain alternating symbols (Calc modes variables and values).
705 Don't remove any of the default settings, just change the values. Org-mode
706 relies on the variables to be present in the list."
707 :group 'org-table-calculation
708 :type 'plist)
710 (defcustom org-table-formula-evaluate-inline t
711 "Non-nil means, TAB and RET evaluate a formula in current table field.
712 If the current field starts with an equal sign, it is assumed to be a formula
713 which should be evaluated as described in the manual and in the documentation
714 string of the command `org-table-eval-formula'. This feature requires the
715 Emacs calc package.
716 When this variable is nil, formula calculation is only available through
717 the command \\[org-table-eval-formula]."
718 :group 'org-table-calculation
719 :type 'boolean)
722 (defcustom org-table-formula-use-constants t
723 "Non-nil means, interpret constants in formulas in tables.
724 A constant looks like `$c' or `$Grav' and will be replaced before evaluation
725 by the value given in `org-table-formula-constants', or by a value obtained
726 from the `constants.el' package."
727 :group 'org-table-calculation
728 :type 'boolean)
730 (defcustom org-table-formula-constants nil
731 "Alist with constant names and values, for use in table formulas.
732 The car of each element is a name of a constant, without the `$' before it.
733 The cdr is the value as a string. For example, if you'd like to use the
734 speed of light in a formula, you would configure
736 (setq org-table-formula-constants '((\"c\" . \"299792458.\")))
738 and then use it in an equation like `$1*$c'."
739 :group 'org-table-calculation
740 :type '(repeat
741 (cons (string :tag "name")
742 (string :tag "value"))))
744 (defcustom org-table-formula-numbers-only nil
745 "Non-nil means, calculate only with numbers in table formulas.
746 Then all input fields will be converted to a number, and the result
747 must also be a number. When nil, calc's full potential is available
748 in table calculations, including symbolics etc."
749 :group 'org-table-calculation
750 :type 'boolean)
752 (defcustom org-table-allow-automatic-line-recalculation t
753 "Non-nil means, lines marked with |#| or |*| will be recomputed automatically.
754 Automatically means, when TAB or RET or C-c C-c are pressed in the line."
755 :group 'org-table-calculation
756 :type 'boolean)
758 (defgroup org-link nil
759 "Options concerning links in Org-mode."
760 :tag "Org Link"
761 :group 'org)
763 (defcustom org-descriptive-links t
764 "Non-nil means, hide link part and only show description of bracket links.
765 Bracket links are like [[link][descritpion]]. This variable sets the initial
766 state in new org-mode buffers. The setting can then be toggled on a
767 per-buffer basis from the Org->Hyperlinks menu."
768 :group 'org-link
769 :type 'boolean)
771 (defcustom org-link-style 'bracket
772 "The style of links to be inserted with \\[org-insert-link].
773 Possible values are:
774 bracket [[link][description]]. This is recommended
775 plain Description \\n link. The old way, no longer recommended."
776 :group 'org-link
777 :type '(choice
778 (const :tag "Bracket (recommended)" bracket)
779 (const :tag "Plain (no longer recommended)" plain)))
781 (defcustom org-link-format "%s"
782 "Default format for external, URL-like linkes in the buffer.
783 This is a format string for printf, %s will be replaced by the link text.
784 The recommended value is just \"%s\", since links will be protected by
785 enclosing them in double brackets. If you prefer plain links (see variable
786 `org-link-style'), \"<%s>\" is useful. Some people also recommend an
787 additional URL: prefix, so the format would be \"<URL:%s>\"."
788 :group 'org-link
789 :type '(choice
790 (const :tag "\"%s\" (e.g. http://www.there.com)" "%s")
791 (const :tag "\"<%s>\" (e.g. <http://www.there.com>)" "<%s>")
792 (const :tag "\"<URL:%s>\" (e.g. <URL:http://www.there.com>)" "<URL:%s>")
793 (string :tag "Other" :value "<%s>")))
795 (defcustom org-link-file-path-type 'adaptive
796 "How the path name in file links should be stored.
797 Valid values are:
799 relative relative to the current directory, i.e. the directory of the file
800 into which the link is being inserted.
801 absolute absolute path, if possible with ~ for home directory.
802 noabbrev absolute path, no abbreviation of home directory.
803 adaptive Use relative path for files in the current directory and sub-
804 directories of it. For other files, use an absolute path."
805 :group 'org-link
806 :type '(choice
807 (const relative)
808 (const absolute)
809 (const noabbrev)
810 (const adaptive)))
812 (defcustom org-activate-links '(bracket angle plain radio tag date)
813 "Types of links that should be activated in Org-mode files.
814 This is a list of symbols, each leading to the activation of a certain link
815 type. In principle, it does not hurt to turn on most link types - there may
816 be a small gain when turning off unused link types. The types are:
818 bracket The recommended [[link][description]] or [[link]] links with hiding.
819 angular Links in angular brackes that may contain whitespace like
820 <bbdb:Carsten Dominik>.
821 plain Plain links in normal text, no whitespace, like http://google.com.
822 radio Text that is matched by a radio target, see manual for details.
823 tag Tag settings in a headline (link to tag search).
824 date Time stamps (link to calendar).
825 camel CamelCase words defining text searches.
827 Changing this variable requires a restart of Emacs to become effective."
828 :group 'org-link
829 :type '(set (const :tag "Double bracket links (new style)" bracket)
830 (const :tag "Angular bracket links (old style)" angular)
831 (const :tag "plain text links" plain)
832 (const :tag "Radio target matches" radio)
833 (const :tag "Tags" tag)
834 (const :tag "Timestamps" date)
835 (const :tag "CamelCase words" camel)))
837 (defgroup org-link-store nil
838 "Options concerning storing links in Org-mode"
839 :tag "Org Store Link"
840 :group 'org-link)
842 (defcustom org-context-in-file-links t
843 "Non-nil means, file links from `org-store-link' contain context.
844 A search string will be added to the file name with :: as separator and
845 used to find the context when the link is activated by the command
846 `org-open-at-point'.
847 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
848 negates this setting for the duration of the command."
849 :group 'org-link-store
850 :type 'boolean)
852 (defcustom org-file-link-context-use-camel-case nil
853 "Non-nil means, use CamelCase to store a search context in a file link.
854 When nil, the search string simply consists of the words of the string.
855 CamelCase is deprecated, and support for it may be dropped in the future."
856 :group 'org-link-store
857 :type 'boolean)
859 (defcustom org-keep-stored-link-after-insertion nil
860 "Non-nil means, keep link in list for entire session.
862 The command `org-store-link' adds a link pointing to the current
863 location to an internal list. These links accumulate during a session.
864 The command `org-insert-link' can be used to insert links into any
865 Org-mode file (offering completion for all stored links). When this
866 option is nil, every link which has been inserted once using \\[org-insert-link]
867 will be removed from the list, to make completing the unused links
868 more efficient."
869 :group 'org-link-store
870 :type 'boolean)
872 (defcustom org-usenet-links-prefer-google nil
873 "Non-nil means, `org-store-link' will create web links to Google groups.
874 When nil, Gnus will be used for such links.
875 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
876 negates this setting for the duration of the command."
877 :group 'org-link-store
878 :type 'boolean)
880 (defgroup org-link-follow nil
881 "Options concerning following links in Org-mode"
882 :tag "Org Follow Link"
883 :group 'org-link)
885 (defcustom org-tab-follows-link nil
886 "Non-nil means, on links TAB will follow the link.
887 Needs to be set before org.el is loaded."
888 :group 'org-link-follow
889 :type 'boolean)
891 (defcustom org-return-follows-link nil
892 "Non-nil means, on links RET will follow the link.
893 Needs to be set before org.el is loaded."
894 :group 'org-link-follow
895 :type 'boolean)
897 (defcustom org-mouse-1-follows-link t
898 "Non-nil means, mouse-1 on a link will follow the link.
899 A longer mouse click will still set point. Does not wortk on XEmacs.
900 Needs to be set before org.el is loaded."
901 :group 'org-link-follow
902 :type 'boolean)
904 (defcustom org-mark-ring-length 4
905 "Number of different positions to be recorded in the ring
906 Changing this requires a restart of Emacs to work correctly."
907 :group 'org-link-follow
908 :type 'interger)
910 (defcustom org-link-frame-setup
911 '((vm . vm-visit-folder-other-frame)
912 (gnus . gnus-other-frame)
913 (file . find-file-other-window))
914 "Setup the frame configuration for following links.
915 When following a link with Emacs, it may often be useful to display
916 this link in another window or frame. This variable can be used to
917 set this up for the different types of links.
918 For VM, use any of
919 `vm-visit-folder'
920 `vm-visit-folder-other-frame'
921 For Gnus, use any of
922 `gnus'
923 `gnus-other-frame'
924 For FILE, use any of
925 `find-file'
926 `find-file-other-window'
927 `find-file-other-frame'
928 For the calendar, use the variable `calendar-setup'.
929 For BBDB, it is currently only possible to display the matches in
930 another window."
931 :group 'org-link-follow
932 :type '(list
933 (cons (const vm)
934 (choice
935 (const vm-visit-folder)
936 (const vm-visit-folder-other-window)
937 (const vm-visit-folder-other-frame)))
938 (cons (const gnus)
939 (choice
940 (const gnus)
941 (const gnus-other-frame)))
942 (cons (const file)
943 (choice
944 (const find-file)
945 (const find-file-other-window)
946 (const find-file-other-frame)))))
948 (defcustom org-open-non-existing-files nil
949 "Non-nil means, `org-open-file' will open non-existing file.
950 When nil, an error will be generated."
951 :group 'org-link-follow
952 :type 'boolean)
954 (defcustom org-confirm-shell-link-function 'yes-or-no-p
955 "Non-nil means, ask for confirmation before executing shell links.
956 Shell links can be dangerous, just thing about a link
958 [[shell:rm -rf ~/*][Google Search]]
960 This link would show up in your Org-mode document as \"Google Search\"
961 but really it would remove your entire home directory.
962 Therefore I *definitely* advise against setting this variable to nil.
963 Just change it to `y-or-n-p' of you want to confirm with a single key press
964 rather than having to type \"yes\"."
965 :group 'org-link-follow
966 :type '(choice
967 (const :tag "with yes-or-no (safer)" yes-or-no-p)
968 (const :tag "with y-or-n (faster)" y-or-n-p)
969 (const :tag "no confirmation (dangerous)" nil)))
971 (defcustom org-confirm-elisp-link-function 'yes-or-no-p
972 "Non-nil means, ask for confirmation before executing elisp links.
973 Elisp links can be dangerous, just thing about a link
975 [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]]
977 This link would show up in your Org-mode document as \"Google Search\"
978 but really it would remove your entire home directory.
979 Therefore I *definitely* advise against setting this variable to nil.
980 Just change it to `y-or-n-p' of you want to confirm with a single key press
981 rather than having to type \"yes\"."
982 :group 'org-link-follow
983 :type '(choice
984 (const :tag "with yes-or-no (safer)" yes-or-no-p)
985 (const :tag "with y-or-n (faster)" y-or-n-p)
986 (const :tag "no confirmation (dangerous)" nil)))
988 (defconst org-file-apps-defaults-gnu
989 '((t . mailcap))
990 "Default file applications on a UNIX or GNU/Linux system.
991 See `org-file-apps'.")
993 (defconst org-file-apps-defaults-macosx
994 '((t . "open %s")
995 ("ps" . "gv %s")
996 ("ps.gz" . "gv %s")
997 ("eps" . "gv %s")
998 ("eps.gz" . "gv %s")
999 ("dvi" . "xdvi %s")
1000 ("fig" . "xfig %s"))
1001 "Default file applications on a MacOS X system.
1002 The system \"open\" is known as a default, but we use X11 applications
1003 for some files for which the OS does not have a good default.
1004 See `org-file-apps'.")
1006 (defconst org-file-apps-defaults-windowsnt
1007 (list (cons t
1008 (list (if (featurep 'xemacs)
1009 'mswindows-shell-execute
1010 'w32-shell-execute)
1011 "open" 'file)))
1012 "Default file applications on a Windows NT system.
1013 The system \"open\" is used for most files.
1014 See `org-file-apps'.")
1016 (defcustom org-file-apps
1018 ("txt" . emacs)
1019 ("tex" . emacs)
1020 ("ltx" . emacs)
1021 ("org" . emacs)
1022 ("el" . emacs)
1023 ("bib" . emacs)
1025 "External applications for opening `file:path' items in a document.
1026 Org-mode uses system defaults for different file types, but
1027 you can use this variable to set the application for a given file
1028 extension. The entries in this list are cons cells where the car identifies
1029 files and the cdr the corresponding command. Possible values for the
1030 file identifier are
1031 \"ext\" A string identifying an extension
1032 `directory' Matches a directory
1033 t Default for all remaining files
1035 Possible values for the command are:
1036 `emacs' The file will be visited by the current Emacs process.
1037 `default' Use the default application for this file type.
1038 string A command to be executed by a shell; %s will be replaced
1039 by the path to the file.
1040 sexp A Lisp form which will be evaluated. The file path will
1041 be available in the Lisp variable `file'.
1042 For more examples, see the system specific constants
1043 `org-file-apps-defaults-macosx'
1044 `org-file-apps-defaults-windowsnt'
1045 `org-file-apps-defaults-gnu'."
1046 :group 'org-link-follow
1047 :type '(repeat
1048 (cons (choice :value ""
1049 (string :tag "Extension")
1050 (const :tag "Default for unrecognized files" t)
1051 (const :tag "Links to a directory" directory))
1052 (choice :value ""
1053 (const :tag "Visit with Emacs" emacs)
1054 (const :tag "Use system default" default)
1055 (string :tag "Command")
1056 (sexp :tag "Lisp form")))))
1058 (defcustom org-mhe-search-all-folders nil
1059 "Non-nil means, that the search for the mh-message will be extended to
1060 all folders if the message cannot be found in the folder given in the link.
1061 Searching all folders is very effective with one of the search engines
1062 supported by MH-E, but will be slow with pick."
1063 :group 'org-link-follow
1064 :type 'boolean)
1066 (defgroup org-remember nil
1067 "Options concerning interaction with remember.el."
1068 :tag "Org Remember"
1069 :group 'org)
1071 (defcustom org-directory "~/org"
1072 "Directory with org files.
1073 This directory will be used as default to prompt for org files.
1074 Used by the hooks for remember.el."
1075 :group 'org-remember
1076 :type 'directory)
1078 (defcustom org-default-notes-file "~/.notes"
1079 "Default target for storing notes.
1080 Used by the hooks for remember.el. This can be a string, or nil to mean
1081 the value of `remember-data-file'."
1082 :group 'org-remember
1083 :type '(choice
1084 (const :tag "Default from remember-data-file" nil)
1085 file))
1087 (defcustom org-remember-templates nil
1088 "Templates for the creation of remember buffers.
1089 When nil, just let remember make the buffer.
1090 When not nil, this is a list of 3-element lists. In each entry, the first
1091 element is a character, a unique key to select this template.
1092 The second element is the template. The third element is optional and can
1093 specify a destination file for remember items created with this template.
1094 The default file is given by `org-default-notes-file'.
1096 The template specifies the structure of the remember buffer. It should have
1097 a first line starting with a star, to act as the org-mode headline.
1098 Furthermore, the following %-escapes will be replaced with content:
1099 %t time stamp, date only
1100 %T time stamp with date and time
1101 %u inactive time stamp, date only
1102 %U inactive time stamp with date and time
1103 %n user name
1104 %a annotation, normally the link created with org-store-link
1105 %i initial content, the region when remember is called with C-u.
1106 If %i is indented, the entire inserted text will be indented as well.
1107 %? This will be removed, and the cursor placed at this position."
1108 :group 'org-remember
1109 :type '(repeat :tag "enabled"
1110 (list :value (?a "\n" nil)
1111 (character :tag "Selection Key")
1112 (string :tag "Template")
1113 (file :tag "Destination file (optional)"))))
1115 (defcustom org-reverse-note-order nil
1116 "Non-nil means, store new notes at the beginning of a file or entry.
1117 When nil, new notes will be filed to the end of a file or entry."
1118 :group 'org-remember
1119 :type '(choice
1120 (const :tag "Reverse always" t)
1121 (const :tag "Reverse never" nil)
1122 (repeat :tag "By file name regexp"
1123 (cons regexp boolean))))
1125 (defgroup org-todo nil
1126 "Options concerning TODO items in Org-mode."
1127 :tag "Org TODO"
1128 :group 'org)
1130 (defcustom org-todo-keywords '("TODO" "DONE")
1131 "List of TODO entry keywords.
1132 \\<org-mode-map>By default, this is '(\"TODO\" \"DONE\"). The last entry in the list is
1133 considered to mean that the entry is \"done\". All the other mean that
1134 action is required, and will make the entry show up in todo lists, diaries
1135 etc.
1136 The command \\[org-todo] cycles an entry through these states, and an
1137 additional state where no keyword is present. For details about this
1138 cycling, see also the variable `org-todo-interpretation'
1139 Changes become only effective after restarting Emacs."
1140 :group 'org-todo
1141 :group 'org-keywords
1142 :type '(repeat (string :tag "Keyword")))
1144 (defcustom org-todo-interpretation 'sequence
1145 "Controls how TODO keywords are interpreted.
1146 This variable is only relevant if `org-todo-keywords' contains more than two
1147 states. \\<org-mode-map>Possible values are `sequence' and `type'.
1149 When `sequence', \\[org-todo] will always switch to the next state in the
1150 `org-todo-keywords' list. When `type', \\[org-todo] only cycles from state
1151 to state when executed several times in direct succession. Otherwise, it
1152 switches directly to DONE from any state.
1153 See the manual for more information."
1154 :group 'org-todo
1155 :group 'org-keywords
1156 :type '(choice (const sequence)
1157 (const type)))
1159 (defcustom org-after-todo-state-change-hook nil
1160 "Hook which is run after the state of a TODO item was changed.
1161 The new state (a string with a TODO keyword, or nil) is available in the
1162 Lisp variable `state'."
1163 :group 'org-todo
1164 :type 'hook)
1166 (defcustom org-log-done nil
1167 "When set, insert a (non-active) time stamp when TODO entry is marked DONE.
1168 When the state of an entry is changed from nothing to TODO, remove a previous
1169 closing date.
1170 This can also be configured on a per-file basis by adding one of
1171 the following lines anywhere in the buffer:
1173 #+STARTUP: logging
1174 #+STARTUP: nologging"
1175 :group 'org-todo
1176 :type 'boolean)
1178 (defgroup org-priorities nil
1179 "Priorities in Org-mode."
1180 :tag "Org Priorities"
1181 :group 'org-todo)
1183 (defcustom org-default-priority ?B
1184 "The default priority of TODO items.
1185 This is the priority an item get if no explicit priority is given."
1186 :group 'org-priorities
1187 :type 'character)
1189 (defcustom org-lowest-priority ?C
1190 "The lowest priority of TODO items. A character like ?A, ?B etc."
1191 :group 'org-priorities
1192 :type 'character)
1194 (defgroup org-time nil
1195 "Options concerning time stamps and deadlines in Org-mode."
1196 :tag "Org Time"
1197 :group 'org)
1199 (defcustom org-insert-labeled-timestamps-at-point nil
1200 "Non-nil means, SCHEDULED and DEADLINE timestamps are inserted at point.
1201 When nil, these labeled time stamps are forces into the second line of an
1202 entry, just after the headline. When scheduling from the global TODO list,
1203 the time stamp will always be forced into the second line."
1204 :group 'org-time
1205 :type 'boolean)
1207 (defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
1208 "Formats for `format-time-string' which are used for time stamps.
1209 It is not recommended to change this constant.")
1211 (defcustom org-time-stamp-rounding-minutes 0
1212 "Number of minutes to round time stamps to upon insertion.
1213 When zero, insert the time unmodified. Useful rounding numbers
1214 should be factors of 60, so for example 5, 10, 15.
1215 When this is not zero, you can still force an exact time-stamp by using
1216 a double prefix argument to a time-stamp command like `C-c .' or `C-c !'."
1217 :group 'org-time
1218 :type 'integer)
1220 (defcustom org-deadline-warning-days 30
1221 "No. of days before expiration during which a deadline becomes active.
1222 This variable governs the display in the org file."
1223 :group 'org-time
1224 :type 'number)
1226 (defcustom org-popup-calendar-for-date-prompt t
1227 "Non-nil means, pop up a calendar when prompting for a date.
1228 In the calendar, the date can be selected with mouse-1. However, the
1229 minibuffer will also be active, and you can simply enter the date as well.
1230 When nil, only the minibuffer will be available."
1231 :group 'org-time
1232 :type 'boolean)
1234 (defcustom org-calendar-follow-timestamp-change t
1235 "Non-nil means, make the calendar window follow timestamp changes.
1236 When a timestamp is modified and the calendar window is visible, it will be
1237 moved to the new date."
1238 :group 'org-time
1239 :type 'boolean)
1241 (defgroup org-tags nil
1242 "Options concerning tags in Org-mode."
1243 :tag "Org Tags"
1244 :group 'org)
1246 (defcustom org-tag-alist nil
1247 "List of tags allowed in Org-mode files.
1248 When this list is nil, Org-mode will base TAG input on what is already in the
1249 buffer.
1250 The value of this variable is an alist, the car may be (and should) be a
1251 character that is used to select that tag through the fast-tag-selection
1252 interface. See the manual for details."
1253 :group 'org-tags
1254 :type '(repeat
1255 (cons (character) (string :tag "Tag"))))
1257 (defcustom org-use-fast-tag-selection 'auto
1258 "Non-nil means, use fast tag selection scheme.
1259 This is a special interface to select and deselect tags with single keys.
1260 When nil, fast selection is never used.
1261 When the symbol `auto', fast selection is used if and only if selection
1262 characters for tags have been configured, either through the variable
1263 `org-tag-alist' or through a #+TAGS line in the buffer.
1264 When t, fast selection is always used and selection keys are assigned
1265 automatically if necessary."
1266 :group 'org-tags
1267 :type '(choice
1268 (const :tag "Always" t)
1269 (const :tag "Never" nil)
1270 (const :tag "When selection characters are configured" 'auto)))
1272 (defcustom org-tags-column 48
1273 "The column to which tags should be indented in a headline.
1274 If this number is positive, it specifies the column. If it is negative,
1275 it means that the tags should be flushright to that column. For example,
1276 -79 works well for a normal 80 character screen."
1277 :group 'org-tags
1278 :type 'integer)
1280 (defcustom org-auto-align-tags t
1281 "Non-nil means, realign tags after pro/demotion of TODO state change.
1282 These operations change the length of a headline and therefore shift
1283 the tags around. With this options turned on, after each such operation
1284 the tags are again aligned to `org-tags-column'."
1285 :group 'org-tags
1286 :type 'boolean)
1288 (defcustom org-use-tag-inheritance t
1289 "Non-nil means, tags in levels apply also for sublevels.
1290 When nil, only the tags directly given in a specific line apply there.
1291 If you turn off this option, you very likely want to turn on the
1292 companion option `org-tags-match-list-sublevels'."
1293 :group 'org-tags
1294 :type 'boolean)
1296 (defcustom org-tags-match-list-sublevels nil
1297 "Non-nil means list also sublevels of headlines matching tag search.
1298 Because of tag inheritance (see variable `org-use-tag-inheritance'),
1299 the sublevels of a headline matching a tag search often also match
1300 the same search. Listing all of them can create very long lists.
1301 Setting this variable to nil causes subtrees of a match to be skipped.
1302 This option is off by default, because inheritance in on. If you turn
1303 inheritance off, you very likely want to turn this option on.
1305 As a special case, if the tag search is restricted to TODO items, the
1306 value of this variable is ignored and sublevels are always checked, to
1307 make sure all corresponding TODO items find their way into the list."
1308 :group 'org-tags
1309 :type 'boolean)
1311 (defvar org-tags-history nil
1312 "History of minibuffer reads for tags.")
1313 (defvar org-last-tags-completion-table nil
1314 "The last used completion table for tags.")
1316 (defgroup org-agenda nil
1317 "Options concerning agenda display Org-mode."
1318 :tag "Org Agenda"
1319 :group 'org)
1321 (defvar org-category nil
1322 "Variable used by org files to set a category for agenda display.
1323 Such files should use a file variable to set it, for example
1325 -*- mode: org; org-category: \"ELisp\"
1327 or contain a special line
1329 #+CATEGORY: ELisp
1331 If the file does not specify a category, then file's base name
1332 is used instead.")
1333 (make-variable-buffer-local 'org-category)
1335 (defcustom org-agenda-files nil
1336 "The files to be used for agenda display.
1337 Entries may be added to this list with \\[org-agenda-file-to-front] and removed with
1338 \\[org-remove-file]. You can also use customize to edit the list.
1340 If the value of the variable is not a list but a single file name, then
1341 the list of agenda files is actually stored and maintained in that file, one
1342 agenda file per line."
1343 :group 'org-agenda
1344 :type '(choice
1345 (repeat :tag "List of files" file)
1346 (file :tag "Store list in a file\n" :value "~/.agenda_files")))
1348 (defcustom org-agenda-custom-commands '(("w" todo "WAITING"))
1349 "Custom commands for the agenda.
1350 These commands will be offered on the splash screen displayed by the
1351 agenda dispatcher \\[org-agenda]. Each entry is a list of 3 items:
1353 key The key (a single char as a string) to be associated with the command.
1354 type The command type, any of the following symbols:
1355 todo Entries with a specific TODO keyword, in all agenda files.
1356 tags Tags match in all agenda files.
1357 tags-todo Tags match in all agenda files, TODO entries only.
1358 todo-tree Sparse tree of specific TODO keyword in *current* file.
1359 tags-tree Sparse tree with all tags matches in *current* file.
1360 occur-tree Occur sparse tree for current file.
1361 match What to search for:
1362 - a single keyword for TODO keyword searches
1363 - a tags match expression for tags searches
1364 - a regular expression for occur searches"
1365 :group 'org-agenda
1366 :type '(repeat
1367 (list (string :tag "Key")
1368 (choice :tag "Type"
1369 (const :tag "Tags search in all agenda files" tags)
1370 (const :tag "Tags search of TODO entries, all agenda files" tags-todo)
1371 (const :tag "TODO keyword search in all agenda files" todo)
1372 (const :tag "Tags sparse tree in current buffer" tags-tree)
1373 (const :tag "TODO keyword tree in current buffer" todo-tree)
1374 (const :tag "Occur tree in current buffer" occur-tree))
1375 (string :tag "Match"))))
1377 ;; FIXME: Need a toggle for this variable, maybe a mode in the agenda buffer?
1378 (defcustom org-agenda-todo-list-sublevels t
1379 "Non-nil means, check also the sublevels of a TODO entry for TODO entries.
1380 When nil, the sublevels of a TODO entry are not checked, resulting in
1381 potentially much shorter TODO lists."
1382 :group 'org-agenda
1383 :group 'org-todo
1384 :type 'boolean)
1386 (defcustom org-agenda-todo-ignore-scheduled nil
1387 "Non-nil means, don't show scheduled entries in the global todo list.
1388 The idea behind this is that by scheduling it, you have already taken care
1389 of this item."
1390 :group 'org-agenda
1391 :group 'org-todo
1392 :type 'boolean)
1394 (defcustom org-agenda-include-all-todo nil
1395 "Non-nil means, the agenda will always contain all TODO entries.
1396 When nil, date-less entries will only be shown if `org-agenda' is called
1397 with a prefix argument.
1398 When non-nil, the TODO entries will be listed at the top of the agenda, before
1399 the entries for specific days."
1400 :group 'org-agenda
1401 :type 'boolean)
1403 (defcustom org-agenda-include-diary nil
1404 "If non-nil, include in the agenda entries from the Emacs Calendar's diary."
1405 :group 'org-agenda
1406 :type 'boolean)
1408 (defcustom org-calendar-to-agenda-key [?c]
1409 "The key to be installed in `calendar-mode-map' for switching to the agenda.
1410 The command `org-calendar-goto-agenda' will be bound to this key. The
1411 default is the character `c' because then `c' can be used to switch back and
1412 forth between agenda and calendar."
1413 :group 'org-agenda
1414 :type 'sexp)
1416 (defgroup org-agenda-setup nil
1417 "Options concerning setting up the Agenda window in Org Mode."
1418 :tag "Org Agenda Window Setup"
1419 :group 'org-agenda)
1421 (defcustom org-agenda-mouse-1-follows-link nil
1422 "Non-nil means, mouse-1 on a link will follow the link in the agenda.
1423 A longer mouse click will still set point. Does not wortk on XEmacs.
1424 Needs to be set before org.el is loaded."
1425 :group 'org-agenda-setup
1426 :type 'boolean)
1428 (defcustom org-agenda-start-with-follow-mode nil
1429 "The initial value of follwo-mode in a newly created agenda window."
1430 :group 'org-agenda-setup
1431 :type 'boolean)
1433 (defcustom org-select-timeline-window t
1434 "Non-nil means, after creating a timeline, move cursor into Timeline window.
1435 When nil, cursor will remain in the current window."
1436 :group 'org-agenda-setup
1437 :type 'boolean)
1439 (defcustom org-select-agenda-window t
1440 "Non-nil means, after creating an agenda, move cursor into Agenda window.
1441 When nil, cursor will remain in the current window."
1442 :group 'org-agenda-setup
1443 :type 'boolean)
1445 (defcustom org-fit-agenda-window t
1446 "Non-nil means, change window size of agenda to fit content."
1447 :group 'org-agenda-setup
1448 :type 'boolean)
1450 (defgroup org-agenda-display nil
1451 "Options concerning what to display initially in Agenda."
1452 :tag "Org Agenda Display"
1453 :group 'org-agenda)
1455 (defcustom org-agenda-show-all-dates t
1456 "Non-nil means, `org-agenda' shows every day in the selected range.
1457 When nil, only the days which actually have entries are shown."
1458 :group 'org-agenda-display
1459 :type 'boolean)
1461 (defcustom org-agenda-start-on-weekday 1
1462 "Non-nil means, start the overview always on the specified weekday.
1463 0 denotes Sunday, 1 denotes Monday etc.
1464 When nil, always start on the current day."
1465 :group 'org-agenda-display
1466 :type '(choice (const :tag "Today" nil)
1467 (number :tag "Weekday No.")))
1469 (defcustom org-agenda-ndays 7
1470 "Number of days to include in overview display.
1471 Should be 1 or 7."
1472 :group 'org-agenda-display
1473 :type 'number)
1475 (defcustom org-agenda-use-time-grid t
1476 "Non-nil means, show a time grid in the agenda schedule.
1477 A time grid is a set of lines for specific times (like every two hours between
1478 8:00 and 20:00). The items scheduled for a day at specific times are
1479 sorted in between these lines.
1480 For details about when the grid will be shown, and what it will look like, see
1481 the variable `org-agenda-time-grid'."
1482 :group 'org-agenda-display
1483 :type 'boolean)
1485 (defcustom org-agenda-time-grid
1486 '((daily today require-timed)
1487 "----------------"
1488 (800 1000 1200 1400 1600 1800 2000))
1490 "The settings for time grid for agenda display.
1491 This is a list of three items. The first item is again a list. It contains
1492 symbols specifying conditions when the grid should be displayed:
1494 daily if the agenda shows a single day
1495 weekly if the agenda shows an entire week
1496 today show grid on current date, independent of daily/weekly display
1497 require-timed show grid only if at least on item has a time specification
1499 The second item is a string which will be places behing the grid time.
1501 The third item is a list of integers, indicating the times that should have
1502 a grid line."
1503 :group 'org-agenda-display
1504 :type
1505 '(list
1506 (set :greedy t :tag "Grid Display Options"
1507 (const :tag "Show grid in single day agenda display" daily)
1508 (const :tag "Show grid in weekly agenda display" weekly)
1509 (const :tag "Always show grid for today" today)
1510 (const :tag "Show grid only if any timed entries are present"
1511 require-timed)
1512 (const :tag "Skip grid times already present in an entry"
1513 remove-match))
1514 (string :tag "Grid String")
1515 (repeat :tag "Grid Times" (integer :tag "Time"))))
1517 (defcustom org-agenda-sorting-strategy '(time-up category-keep priority-down)
1518 "Sorting structure for the agenda items of a single day.
1519 This is a list of symbols which will be used in sequence to determine
1520 if an entry should be listed before another entry. The following
1521 symbols are recognized:
1523 time-up Put entries with time-of-day indications first, early first
1524 time-down Put entries with time-of-day indications first, late first
1525 category-keep Keep the default order of categories, corresponding to the
1526 sequence in `org-agenda-files'.
1527 category-up Sort alphabetically by category, A-Z.
1528 category-down Sort alphabetically by category, Z-A.
1529 priority-up Sort numerically by priority, high priority last.
1530 priority-down Sort numerically by priority, high priority first.
1532 The different possibilities will be tried in sequence, and testing stops
1533 if one comparison returns a \"not-equal\". For example, the default
1534 '(time-up category-keep priority-down)
1535 means: Pull out all entries having a specified time of day and sort them,
1536 in order to make a time schedule for the current day the first thing in the
1537 agenda listing for the day. Of the entries without a time indication, keep
1538 the grouped in categories, don't sort the categories, but keep them in
1539 the sequence given in `org-agenda-files'. Within each category sort by
1540 priority.
1542 Leaving out `category-keep' would mean that items will be sorted across
1543 categories by priority."
1544 :group 'org-agenda-display
1545 :type '(repeat
1546 (choice
1547 (const time-up)
1548 (const time-down)
1549 (const category-keep)
1550 (const category-up)
1551 (const category-down)
1552 (const priority-up)
1553 (const priority-down))))
1555 (defcustom org-sort-agenda-notime-is-late t
1556 "Non-nil means, items without time are considered late.
1557 This is only relevant for sorting. When t, items which have no explicit
1558 time like 15:30 will be considered as 24:01, i.e. later than any items which
1559 do have a time. When nil, the default time is before 0:00. You can use this
1560 option to decide if the schedule for today should come before or after timeless
1561 agenda entries."
1562 :group 'org-agenda-display
1563 :type 'boolean)
1566 (defgroup org-agenda-prefix nil
1567 "Options concerning the entry prefix in the Org-mode agenda display."
1568 :tag "Org Agenda Prefix"
1569 :group 'org-agenda)
1571 (defcustom org-agenda-prefix-format " %-12:c%?-12t% s"
1572 "Format specification for the prefix of items in the agenda buffer.
1573 This format works similar to a printf format, with the following meaning:
1575 %c the category of the item, \"Diary\" for entries from the diary, or
1576 as given by the CATEGORY keyword or derived from the file name.
1577 %T the first tag of the item.
1578 %t the time-of-day specification if one applies to the entry, in the
1579 format HH:MM
1580 %s Scheduling/Deadline information, a short string
1582 All specifiers work basically like the standard `%s' of printf, but may
1583 contain two additional characters: A question mark just after the `%' and
1584 a whitespace/punctuation character just before the final letter.
1586 If the first character after `%' is a question mark, the entire field
1587 will only be included if the corresponding value applies to the
1588 current entry. This is useful for fields which should have fixed
1589 width when present, but zero width when absent. For example,
1590 \"%?-12t\" will result in a 12 character time field if a time of the
1591 day is specified, but will completely disappear in entries which do
1592 not contain a time.
1594 If there is punctuation or whitespace character just before the final
1595 format letter, this character will be appended to the field value if
1596 the value is not empty. For example, the format \"%-12:c\" leads to
1597 \"Diary: \" if the category is \"Diary\". If the category were be
1598 empty, no additional colon would be interted.
1600 The default value of this option is \" %-12:c%?-12t% s\", meaning:
1601 - Indent the line with two space characters
1602 - Give the category in a 12 chars wide field, padded with whitespace on
1603 the right (because of `-'). Append a colon if there is a category
1604 (because of `:').
1605 - If there is a time-of-day, put it into a 12 chars wide field. If no
1606 time, don't put in an empty field, just skip it (because of '?').
1607 - Finally, put the scheduling information and append a whitespace.
1609 As another example, if you don't want the time-of-day of entries in
1610 the prefix, you could use:
1612 (setq org-agenda-prefix-format \" %-11:c% s\")
1614 See also the variables `org-agenda-remove-times-when-in-prefix' and
1615 `org-agenda-remove-tags-when-in-prefix'."
1616 :type 'string
1617 :group 'org-agenda-prefix)
1619 (defcustom org-timeline-prefix-format " % s"
1620 "Like `org-agenda-prefix-format', but for the timeline of a single file."
1621 :type 'string
1622 :group 'org-agenda-prefix)
1624 (defvar org-prefix-format-compiled nil
1625 "The compiled version of the most recently used prefix format.
1626 Depending on which command was used last, this may be the compiled version
1627 of `org-agenda-prefix-format' or `org-timeline-prefix-format'.")
1629 ;; FIXME: There seem to be situations where this does not work.
1630 (defcustom org-agenda-remove-times-when-in-prefix t
1631 "Non-nil means, remove duplicate time specifications in agenda items.
1632 When the format `org-agenda-prefix-format' contains a `%t' specifier, a
1633 time-of-day specification in a headline or diary entry is extracted and
1634 placed into the prefix. If this option is non-nil, the original specification
1635 \(a timestamp or -range, or just a plain time(range) specification like
1636 11:30-4pm) will be removed for agenda display. This makes the agenda less
1637 cluttered.
1638 The option can be t or nil. It may also be the symbol `beg', indicating
1639 that the time should only be removed what it is located at the beginning of
1640 the headline/diary entry."
1641 :group 'org-agenda-prefix
1642 :type '(choice
1643 (const :tag "Always" t)
1644 (const :tag "Never" nil)
1645 (const :tag "When at beginning of entry" beg)))
1647 (defcustom org-agenda-remove-tags-when-in-prefix nil
1648 "Non-nil means, remove the tags from the headline copy in the agenda.
1649 When this is the symbol `prefix', only remove tags when
1650 `org-agenda-prefix-format' contains a `%T' specifier."
1651 :group 'org-agenda-prefix
1652 :type '(choice
1653 (const :tag "Always" t)
1654 (const :tag "Never" nil)
1655 (const :tag "When prefix format contains %T" prefix)))
1657 (defgroup org-export nil
1658 "Options for exporting org-listings."
1659 :tag "Org Export"
1660 :group 'org)
1662 (defgroup org-export-general nil
1663 "General options for exporting Org-mode files."
1664 :tag "Org Export General"
1665 :group 'org-export)
1667 (defcustom org-export-publishing-directory "."
1668 "Path to the location where exported files should be located.
1669 This path may be relative to the directory where the Org-mode file lives.
1670 The default is to put them into the same directory as the Org-mode file.
1671 The variable may also be an alist with export types `:html', `:ascii',
1672 `:ical', or `:xoxo' and the corresponding directories. If a direcoty path
1673 is relative, it is interpreted relative to the directory where the exported
1674 Org-mode files lives."
1675 :group 'org-export-general
1676 :type '(choice
1677 (directory)
1678 (repeat
1679 (cons
1680 (choice :tag "Type"
1681 (const :html) (const :ascii) (const :ical) (const :xoxo))
1682 (directory)))))
1684 (defcustom org-export-language-setup
1685 '(("en" "Author" "Date" "Table of Contents")
1686 ("da" "Ophavsmand" "Dato" "Indhold")
1687 ("de" "Autor" "Datum" "Inhaltsverzeichnis")
1688 ("es" "Autor" "Fecha" "\xccndice")
1689 ("fr" "Auteur" "Date" "Table des Mati\xe8res")
1690 ("it" "Autore" "Data" "Indice")
1691 ("nl" "Auteur" "Datum" "Inhoudsopgave")
1692 ("nn" "Forfattar" "Dato" "Innhold") ;; nn = Norsk (nynorsk)
1693 ("sv" "F\xf6rfattarens" "Datum" "Inneh\xe5ll"))
1694 "Terms used in export text, translated to different languages.
1695 Use the variable `org-export-default-language' to set the language,
1696 or use the +OPTION lines for a per-file setting."
1697 :group 'org-export-general
1698 :type '(repeat
1699 (list
1700 (string :tag "HTML language tag")
1701 (string :tag "Author")
1702 (string :tag "Date")
1703 (string :tag "Table of Contents"))))
1705 (defcustom org-export-default-language "en"
1706 "The default language of HTML export, as a string.
1707 This should have an association in `org-export-language-setup'."
1708 :group 'org-export-general
1709 :type 'string)
1711 (defcustom org-export-headline-levels 3
1712 "The last level which is still exported as a headline.
1713 Inferior levels will produce itemize lists when exported.
1714 Note that a numeric prefix argument to an exporter function overrides
1715 this setting.
1717 This option can also be set with the +OPTIONS line, e.g. \"H:2\"."
1718 :group 'org-export-general
1719 :type 'number)
1721 (defcustom org-export-with-section-numbers t
1722 "Non-nil means, add section numbers to headlines when exporting.
1724 This option can also be set with the +OPTIONS line, e.g. \"num:t\"."
1725 :group 'org-export-general
1726 :type 'boolean)
1728 (defcustom org-export-with-toc t
1729 "Non-nil means, create a table of contents in exported files.
1730 The TOC contains headlines with levels up to`org-export-headline-levels'.
1732 Headlines which contain any TODO items will be marked with \"(*)\" in
1733 ASCII export, and with red color in HTML output.
1735 In HTML output, the TOC will be clickable.
1737 This option can also be set with the +OPTIONS line, e.g. \"toc:nil\"."
1738 :group 'org-export-general
1739 :type 'boolean)
1741 (defcustom org-export-mark-todo-in-toc nil
1742 "Non-nil means, mark TOC lines that contain any open TODO items."
1743 :group 'org-export-general
1744 :type 'boolean)
1746 (defcustom org-export-preserve-breaks nil
1747 "Non-nil means, preserve all line breaks when exporting.
1748 Normally, in HTML output paragraphs will be reformatted. In ASCII
1749 export, line breaks will always be preserved, regardless of this variable.
1751 This option can also be set with the +OPTIONS line, e.g. \"\\n:t\"."
1752 :group 'org-export-general
1753 :type 'boolean)
1755 (defcustom org-export-with-timestamps t
1756 "Nil means, do not export time stamps and associated keywords."
1757 :group 'org-export
1758 :type 'boolean)
1760 (defcustom org-export-with-tags t
1761 "Nil means, do not export tags, just remove them from headlines."
1762 :group 'org-export-general
1763 :type 'boolean)
1765 (defcustom org-export-with-timestamps t
1766 "Nil means, do not export timestamps and associated keywords."
1767 :group 'org-export-general
1768 :type 'boolean)
1770 (defgroup org-export-translation nil
1771 "Options for translating special ascii sequences for the export backends."
1772 :tag "Org Export Translation"
1773 :group 'org-export)
1775 (defcustom org-export-with-emphasize t
1776 "Non-nil means, interpret *word*, /word/, and _word_ as emphasized text.
1777 If the export target supports emphasizing text, the word will be
1778 typeset in bold, italic, or underlined, respectively. Works only for
1779 single words, but you can say: I *really* *mean* *this*.
1780 Not all export backends support this.
1782 This option can also be set with the +OPTIONS line, e.g. \"*:nil\"."
1783 :group 'org-export-translation
1784 :type 'boolean)
1786 (defcustom org-export-with-sub-superscripts t
1787 "Non-nil means, interpret \"_\" and \"^\" for export.
1788 When this option is turned on, you can use TeX-like syntax for sub- and
1789 superscripts. Several characters after \"_\" or \"^\" will be
1790 considered as a single item - so grouping with {} is normally not
1791 needed. For example, the following things will be parsed as single
1792 sub- or superscripts.
1794 10^24 or 10^tau several digits will be considered 1 item.
1795 10^-12 or 10^-tau a leading sign with digits or a word
1796 x^2-y^3 will be read as x^2 - y^3, because items are
1797 terminated by almost any nonword/nondigit char.
1798 x_{i^2} or x^(2-i) braces or parenthesis do grouping.
1800 Still, ambiguity is possible - so when in doubt use {} to enclose the
1801 sub/superscript.
1802 Not all export backends support this, but HTML does.
1804 This option can also be set with the +OPTIONS line, e.g. \"^:nil\"."
1805 :group 'org-export-translation
1806 :type 'boolean)
1808 (defcustom org-export-with-TeX-macros t
1809 "Non-nil means, interpret simple TeX-like macros when exporting.
1810 For example, HTML export converts \\alpha to &alpha; and \\AA to &Aring;.
1811 No only real TeX macros will work here, but the standard HTML entities
1812 for math can be used as macro names as well. For a list of supported
1813 names in HTML export, see the constant `org-html-entities'.
1814 Not all export backends support this.
1816 This option can also be set with the +OPTIONS line, e.g. \"TeX:nil\"."
1817 :group 'org-export-translation
1818 :type 'boolean)
1820 (defcustom org-export-with-fixed-width t
1821 "Non-nil means, lines starting with \":\" will be in fixed width font.
1822 This can be used to have pre-formatted text, fragments of code etc. For
1823 example:
1824 : ;; Some Lisp examples
1825 : (while (defc cnt)
1826 : (ding))
1827 will be looking just like this in also HTML. See also the QUOTE keyword.
1828 Not all export backends support this.
1830 This option can also be set with the +OPTIONS line, e.g. \"::nil\"."
1831 :group 'org-export-translation
1832 :type 'boolean)
1834 (defcustom org-match-sexp-depth 3
1835 "Number of stacked braces for sub/superscript matching.
1836 This has to be set before loading org.el to be effective."
1837 :group 'org-export-translation
1838 :type 'integer)
1840 (defgroup org-export-tables nil
1841 "Options for exporting tables in Org-mode."
1842 :tag "Org Export Tables"
1843 :group 'org-export)
1845 (defcustom org-export-with-tables t
1846 "If non-nil, lines starting with \"|\" define a table.
1847 For example:
1849 | Name | Address | Birthday |
1850 |-------------+----------+-----------|
1851 | Arthur Dent | England | 29.2.2100 |
1853 Not all export backends support this.
1855 This option can also be set with the +OPTIONS line, e.g. \"|:nil\"."
1856 :group 'org-export-tables
1857 :type 'boolean)
1859 (defcustom org-export-highlight-first-table-line t
1860 "Non-nil means, highlight the first table line.
1861 In HTML export, this means use <th> instead of <td>.
1862 In tables created with table.el, this applies to the first table line.
1863 In Org-mode tables, all lines before the first horizontal separator
1864 line will be formatted with <th> tags."
1865 :group 'org-export-tables
1866 :type 'boolean)
1868 (defcustom org-export-table-remove-special-lines t
1869 "Remove special lines and marking characters in calculating tables.
1870 This removes the special marking character column from tables that are set
1871 up for spreadsheet calculations. It also removes the entire lines
1872 marked with `!', `_', or `^'. The lines with `$' are kept, because
1873 the values of constants may be useful to have."
1874 :group 'org-export-tables
1875 :type 'boolean)
1877 (defcustom org-export-prefer-native-exporter-for-tables nil
1878 "Non-nil means, always export tables created with table.el natively.
1879 Natively means, use the HTML code generator in table.el.
1880 When nil, Org-mode's own HTML generator is used when possible (i.e. if
1881 the table does not use row- or column-spanning). This has the
1882 advantage, that the automatic HTML conversions for math symbols and
1883 sub/superscripts can be applied. Org-mode's HTML generator is also
1884 much faster."
1885 :group 'org-export-tables
1886 :type 'boolean)
1888 (defgroup org-export-ascii nil
1889 "Options specific for ASCII export of Org-mode files."
1890 :tag "Org Export ASCII"
1891 :group 'org-export)
1893 (defcustom org-export-ascii-show-new-buffer t
1894 "Non-nil means, popup buffer containing the exported ASCII text.
1895 Otherwise the buffer will just be saved to a file and stay hidden."
1896 :group 'org-export-ascii
1897 :type 'boolean)
1899 (defgroup org-export-xml nil
1900 "Options specific for XML export of Org-mode files."
1901 :tag "Org Export XML"
1902 :group 'org-export)
1904 ;; FIXME: I am told XOXO is not XML, it is semantic-only HTML.
1905 (defcustom org-export-xml-type 'xoxo
1906 "The kind of XML to be produced by the XML exporter.
1907 Allowed values are:
1908 xoxo The XOXO exporter."
1909 :group 'org-export-xml
1910 :type '(choice
1911 (const :tag "XOXO" xoxo)))
1913 (defgroup org-export-html nil
1914 "Options specific for HTML export of Org-mode files."
1915 :tag "Org Export HTML"
1916 :group 'org-export)
1918 (defcustom org-export-html-style
1919 "<style type=\"text/css\">
1920 html {
1921 font-family: Times, serif;
1922 font-size: 12pt;
1924 .title { text-align: center; }
1925 .todo { color: red; }
1926 .done { color: green; }
1927 .timestamp { color: grey }
1928 .timestamp-kwd { color: CadetBlue }
1929 .tag { background-color:lightblue; font-weight:normal }
1930 .target { background-color: lavender; }
1931 pre {
1932 border: 1pt solid #AEBDCC;
1933 background-color: #F3F5F7;
1934 padding: 5pt;
1935 font-family: courier, monospace;
1937 table { border-collapse: collapse; }
1938 td, th {
1939 vertical-align: top;
1940 border: 1pt solid #ADB9CC;
1942 </style>"
1943 "The default style specification for exported HTML files.
1944 Since there are different ways of setting style information, this variable
1945 needs to contain the full HTML structure to provide a style, including the
1946 surrounding HTML tags. The style specifications should include definitions
1947 for new classes todo, done, title, and deadline. For example, legal values
1948 would be:
1950 <style type=\"text/css\">
1951 p { font-weight: normal; color: gray; }
1952 h1 { color: black; }
1953 .title { text-align: center; }
1954 .todo, .deadline { color: red; }
1955 .done { color: green; }
1956 </style>
1958 or, if you want to keep the style in a file,
1960 <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\">
1962 As the value of this option simply gets inserted into the HTML <head> header,
1963 you can \"misuse\" it to add arbitrary text to the header."
1964 :group 'org-export-html
1965 :type 'string)
1967 (defcustom org-export-html-link-org-files-as-html t
1968 "Non-nil means, make file links to `file.org' point to `file.html'.
1969 When org-mode is exporting an org-mode file to HTML, links to
1970 non-html files are directly put into a href tag in HTML.
1971 However, links to other Org-mode files (recognized by the
1972 extension `.org.) should become links to the corresponding html
1973 file, assuming that the linked org-mode file will also be
1974 converted to HTML.
1975 When nil, the links still point to the plain `.org' file."
1976 :group 'org-export-html
1977 :type 'boolean)
1979 (defcustom org-export-html-inline-images 'maybe
1980 "Non-nil means, inline images into exported HTML pages.
1981 This is done using an <img> tag. When nil, an anchor with href is used to
1982 link to the image. If this option is `maybe', then images in links with
1983 an empty description will be inlined, while images with a description will
1984 be linked only."
1985 :group 'org-export-html
1986 :type '(choice (const :tag "Never" nil)
1987 (const :tag "Always" t)
1988 (const :tag "When there is no description" maybe)))
1990 (defcustom org-export-html-expand t
1991 "Non-nil means, for HTML export, treat @<...> as HTML tag.
1992 When nil, these tags will be exported as plain text and therefore
1993 not be interpreted by a browser.
1995 This option can also be set with the +OPTIONS line, e.g. \"@:nil\"."
1996 :group 'org-export-html
1997 :type 'boolean)
1999 (defcustom org-export-html-table-tag
2000 "<table border=1 cellspacing=0 cellpadding=6>"
2001 "The HTML tag used to start a table.
2002 This must be a <table> tag, but you may change the options like
2003 borders and spacing."
2004 :group 'org-export-html
2005 :type 'string)
2007 (defcustom org-export-html-with-timestamp nil
2008 "If non-nil, write `org-export-html-html-helper-timestamp'
2009 into the exported HTML text. Otherwise, the buffer will just be saved
2010 to a file."
2011 :group 'org-export-html
2012 :type 'boolean)
2014 (defcustom org-export-html-html-helper-timestamp
2015 "<br><br><hr><p><!-- hhmts start --> <!-- hhmts end -->\n"
2016 "The HTML tag used as timestamp delimiter for HTML-helper-mode."
2017 :group 'org-export-html
2018 :type 'string)
2020 (defcustom org-export-html-show-new-buffer nil
2021 "Non-nil means, popup buffer containing the exported html text.
2022 Otherwise, the buffer will just be saved to a file and stay hidden."
2023 :group 'org-export-html
2024 :type 'boolean)
2026 (defgroup org-export-icalendar nil
2027 "Options specific for iCalendar export of Org-mode files."
2028 :tag "Org Export iCalendar"
2029 :group 'org-export)
2031 (defcustom org-combined-agenda-icalendar-file "~/org.ics"
2032 "The file name for the iCalendar file covering all agenda files.
2033 This file is created with the command \\[org-export-icalendar-all-agenda-files].
2034 The file name should be absolute."
2035 :group 'org-export-icalendar
2036 :type 'file)
2038 (defcustom org-icalendar-include-todo nil
2039 "Non-nil means, export to iCalendar files should also cover TODO items."
2040 :group 'org-export-icalendar
2041 :type 'boolean)
2043 (defcustom org-icalendar-combined-name "OrgMode"
2044 "Calendar name for the combined iCalendar representing all agenda files."
2045 :group 'org-export-icalendar
2046 :type 'string)
2048 (defgroup org-font-lock nil
2049 "Font-lock settings for highlighting in Org-mode."
2050 :tag "Org Font Lock"
2051 :group 'org)
2053 (defcustom org-level-color-stars-only nil
2054 "Non-nil means fontify only the stars in each headline.
2055 When nil, the entire headline is fontified.
2056 Changing it requires restart of `font-lock-mode' to become effective
2057 also in regions already fontified."
2058 :group 'org-font-lock
2059 :type 'boolean)
2061 (defcustom org-hide-leading-stars nil
2062 "Non-nil means, hide the first N-1 stars in a headline.
2063 This works by using the face `org-hide' for these stars. This
2064 face is white for a light background, and black for a dark
2065 background. You may have to customize the face `org-hide' to
2066 make this work.
2067 Changing it requires restart of `font-lock-mode' to become effective
2068 also in regions already fontified.
2069 You may also set this on a per-file basis by adding one of the following
2070 lines to the buffer:
2072 #+STARTUP: hidestars
2073 #+STARTUP: showstars"
2074 :group 'org-font-lock
2075 :type 'boolean)
2077 (defcustom org-fontify-done-headline nil
2078 "Non-nil means, change the face of a headline if it is marked DONE.
2079 Normally, only the TODO/DONE keyword indicates the state of a headline.
2080 When this is non-nil, the headline after the keyword is set to the
2081 `org-headline-done' as an additional indication."
2082 :group 'org-font-lock
2083 :type 'boolean)
2085 (defcustom org-fontify-emphasized-text t
2086 "Non-nil means fontify *bold*, /italic/ and _underlined_ text.
2087 Changing this variable requires a restart of Emacs to take effect."
2088 :group 'org-font-lock
2089 :type 'boolean)
2091 (defgroup org-faces nil
2092 "Faces in Org-mode."
2093 :tag "Org Faces"
2094 :group 'org-font-lock)
2096 (defun org-compatible-face (specs)
2097 "Make a compatible face specification.
2098 XEmacs and Emacs 21 do not know about the `min-colors' attribute.
2099 For them we convert a (min-colors 8) entry to a `tty' entry and move it
2100 to the top of the list. The `min-colors' attribute will be removed from
2101 any other entries, and any resulting duplicates will be removed entirely."
2102 (if (or (featurep 'xemacs) (< emacs-major-version 22))
2103 (let (r e a)
2104 (while (setq e (pop specs))
2105 (cond
2106 ((memq (car e) '(t default)) (push e r))
2107 ((setq a (member '(min-colors 8) (car e)))
2108 (nconc r (list (cons (cons '(type tty) (delq (car a) (car e)))
2109 (cdr e)))))
2110 ((setq a (assq 'min-colors (car e)))
2111 (setq e (cons (delq a (car e)) (cdr e)))
2112 (or (assoc (car e) r) (push e r)))
2113 (t (or (assoc (car e) r) (push e r)))))
2114 (nreverse r))
2115 specs))
2117 (defface org-hide
2118 '((((background light)) (:foreground "white"))
2119 (((background dark)) (:foreground "black")))
2120 "Face used to hide leading stars in headlines.
2121 The forground color of this face should be equal to the background
2122 color of the frame."
2123 :group 'org-faces)
2125 (defface org-level-1 ;; font-lock-function-name-face
2126 (org-compatible-face
2127 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
2128 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
2129 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
2130 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
2131 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
2132 (t (:bold t))))
2133 "Face used for level 1 headlines."
2134 :group 'org-faces)
2136 (defface org-level-2 ;; font-lock-variable-name-face
2137 (org-compatible-face
2138 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
2139 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
2140 (((class color) (min-colors 8) (background light)) (:foreground "yellow"))
2141 (((class color) (min-colors 8) (background dark)) (:foreground "yellow" :bold t))
2142 (t (:bold t))))
2143 "Face used for level 2 headlines."
2144 :group 'org-faces)
2146 (defface org-level-3 ;; font-lock-keyword-face
2147 (org-compatible-face
2148 '((((class color) (min-colors 88) (background light)) (:foreground "Purple"))
2149 (((class color) (min-colors 88) (background dark)) (:foreground "Cyan1"))
2150 (((class color) (min-colors 16) (background light)) (:foreground "Purple"))
2151 (((class color) (min-colors 16) (background dark)) (:foreground "Cyan"))
2152 (((class color) (min-colors 8) (background light)) (:foreground "purple" :bold t))
2153 (((class color) (min-colors 8) (background dark)) (:foreground "cyan" :bold t))
2154 (t (:bold t))))
2155 "Face used for level 3 headlines."
2156 :group 'org-faces)
2158 (defface org-level-4 ;; font-lock-comment-face
2159 (org-compatible-face
2160 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2161 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2162 (((class color) (min-colors 16) (background light)) (:foreground "red"))
2163 (((class color) (min-colors 16) (background dark)) (:foreground "red1"))
2164 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
2165 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2166 (t (:bold t))))
2167 "Face used for level 4 headlines."
2168 :group 'org-faces)
2170 (defface org-level-5 ;; font-lock-type-face
2171 (org-compatible-face
2172 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
2173 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
2174 (((class color) (min-colors 8)) (:foreground "green"))))
2175 "Face used for level 5 headlines."
2176 :group 'org-faces)
2178 (defface org-level-6 ;; font-lock-constant-face
2179 (org-compatible-face
2180 '((((class color) (min-colors 16) (background light)) (:foreground "CadetBlue"))
2181 (((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine"))
2182 (((class color) (min-colors 8)) (:foreground "magenta"))))
2183 "Face used for level 6 headlines."
2184 :group 'org-faces)
2186 (defface org-level-7 ;; font-lock-builtin-face
2187 (org-compatible-face
2188 '((((class color) (min-colors 16) (background light)) (:foreground "Orchid"))
2189 (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue"))
2190 (((class color) (min-colors 8)) (:foreground "blue"))))
2191 "Face used for level 7 headlines."
2192 :group 'org-faces)
2194 (defface org-level-8 ;; font-lock-string-face
2195 (org-compatible-face
2196 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
2197 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
2198 (((class color) (min-colors 8)) (:foreground "green"))))
2199 "Face used for level 8 headlines."
2200 :group 'org-faces)
2202 (defface org-special-keyword ;; font-lock-string-face
2203 (org-compatible-face
2204 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
2205 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
2206 (t (:italic t))))
2207 "Face used for special keywords."
2208 :group 'org-faces)
2210 (defface org-warning ;; font-lock-warning-face
2211 (org-compatible-face
2212 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
2213 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
2214 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
2215 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2216 (t (:bold t))))
2217 "Face for deadlines and TODO keywords."
2218 :group 'org-faces)
2220 (defface org-headline-done ;; font-lock-string-face
2221 (org-compatible-face
2222 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
2223 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
2224 (((class color) (min-colors 8) (background light)) (:bold nil))))
2225 "Face used to indicate that a headline is DONE.
2226 This face is only used if `org-fontify-done-headline' is set."
2227 :group 'org-faces)
2229 (defface org-link
2230 '((((class color) (background light)) (:foreground "Purple" :underline t))
2231 (((class color) (background dark)) (:foreground "Cyan" :underline t))
2232 (t (:underline t)))
2233 "Face for links."
2234 :group 'org-faces)
2236 (defface org-date
2237 '((((class color) (background light)) (:foreground "Purple" :underline t))
2238 (((class color) (background dark)) (:foreground "Cyan" :underline t))
2239 (t (:underline t)))
2240 "Face for links."
2241 :group 'org-faces)
2243 (defface org-tag
2244 '((t (:bold t)))
2245 "Face for tags."
2246 :group 'org-faces)
2248 (defface org-todo ;; font-lock-warning-face
2249 (org-compatible-face
2250 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
2251 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
2252 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
2253 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2254 (t (:inverse-video t :bold t))))
2255 "Face for TODO keywords."
2256 :group 'org-faces)
2258 (defface org-done ;; font-lock-type-face
2259 (org-compatible-face
2260 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
2261 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
2262 (((class color) (min-colors 8)) (:foreground "green"))
2263 (t (:bold t))))
2264 "Face used for DONE."
2265 :group 'org-faces)
2267 (defface org-table ;; font-lock-function-name-face
2268 (org-compatible-face
2269 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
2270 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
2271 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
2272 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
2273 (((class color) (min-colors 8) (background light)) (:foreground "blue"))
2274 (((class color) (min-colors 8) (background dark)))))
2275 "Face used for tables."
2276 :group 'org-faces)
2278 (defface org-formula
2279 (org-compatible-face
2280 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2281 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2282 (((class color) (min-colors 8) (background light)) (:foreground "red"))
2283 (((class color) (min-colors 8) (background dark)) (:foreground "red"))
2284 (t (:bold t :italic t))))
2285 "Face for formulas."
2286 :group 'org-faces)
2288 (defface org-scheduled-today
2289 (org-compatible-face
2290 '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen"))
2291 (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen"))
2292 (((class color) (min-colors 8)) (:foreground "green"))
2293 (t (:bold t :italic t))))
2294 "Face for items scheduled for a certain day."
2295 :group 'org-faces)
2297 (defface org-scheduled-previously
2298 (org-compatible-face
2299 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
2300 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
2301 (((class color) (min-colors 8) (background light)) (:foreground "red"))
2302 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
2303 (t (:bold t))))
2304 "Face for items scheduled previously, and not yet done."
2305 :group 'org-faces)
2307 (defface org-time-grid ;; font-lock-variable-name-face
2308 (org-compatible-face
2309 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
2310 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
2311 (((class color) (min-colors 8)) (:foreground "yellow" :weight light))))
2312 "Face used for time grids."
2313 :group 'org-faces)
2315 (defconst org-level-faces
2316 '(org-level-1 org-level-2 org-level-3 org-level-4
2317 org-level-5 org-level-6 org-level-7 org-level-8
2319 (defconst org-n-levels (length org-level-faces))
2321 (defconst org-bold-re
2322 (if (featurep 'xemacs)
2323 "\\([ ]\\|^\\)\\(\\*\\(\\w[a-zA-Z0-9-_ ]*?\\w\\)\\*\\)\\([ ,.]\\|$\\)"
2324 "\\([ ]\\|^\\)\\(\\*\\(\\w[[:word:] -_]*?\\w\\)\\*\\)\\([ ,.]\\|$\\)")
2325 "Regular expression for bold emphasis.")
2326 (defconst org-italic-re
2327 (if (featurep 'xemacs)
2328 "\\([ ]\\|^\\)\\(/\\(\\w[a-zA-Z0-9-_ ]*?\\w\\)/\\)\\([ ,.]\\|$\\)"
2329 "\\([ ]\\|^\\)\\(/\\(\\w[[:word:] -_]*?\\w\\)/\\)\\([ ,.]\\|$\\)")
2330 "Regular expression for italic emphasis.")
2331 (defconst org-underline-re
2332 (if (featurep 'xemacs)
2333 "\\([ ]\\|^\\)\\(_\\(\\w[a-zA-Z0-9-_ ]*?\\w\\)_\\)\\([ ,.]\\|$\\)"
2334 "\\([ ]\\|^\\)\\(_\\(\\w[[:word:] -_]*?\\w\\)_\\)\\([ ,.]\\|$\\)")
2335 "Regular expression for underline emphasis.")
2337 ;; Variables for pre-computed regular expressions, all buffer local
2338 (defvar org-done-string nil
2339 "The last string in `org-todo-keywords', indicating an item is DONE.")
2340 (make-variable-buffer-local 'org-done-string)
2341 (defvar org-todo-regexp nil
2342 "Matches any of the TODO state keywords.")
2343 (make-variable-buffer-local 'org-todo-regexp)
2344 (defvar org-not-done-regexp nil
2345 "Matches any of the TODO state keywords except the last one.")
2346 (make-variable-buffer-local 'org-not-done-regexp)
2347 (defvar org-todo-line-regexp nil
2348 "Matches a headline and puts TODO state into group 2 if present.")
2349 (make-variable-buffer-local 'org-todo-line-regexp)
2350 (defvar org-nl-done-regexp nil
2351 "Matches newline followed by a headline with the DONE keyword.")
2352 (make-variable-buffer-local 'org-nl-done-regexp)
2353 (defvar org-looking-at-done-regexp nil
2354 "Matches the DONE keyword a point.")
2355 (make-variable-buffer-local 'org-looking-at-done-regexp)
2356 (defvar org-todo-kwd-priority-p nil
2357 "Do TODO items have priorities?")
2358 (make-variable-buffer-local 'org-todo-kwd-priority-p)
2359 (defvar org-todo-kwd-max-priority nil
2360 "Maximum priority of TODO items.")
2361 (make-variable-buffer-local 'org-todo-kwd-max-priority)
2362 (defvar org-ds-keyword-length 12
2363 "Maximum length of the Deadline and SCHEDULED keywords.")
2364 (make-variable-buffer-local 'org-ds-keyword-length)
2365 (defvar org-deadline-regexp nil
2366 "Matches the DEADLINE keyword.")
2367 (make-variable-buffer-local 'org-deadline-regexp)
2368 (defvar org-deadline-time-regexp nil
2369 "Matches the DEADLINE keyword together with a time stamp.")
2370 (make-variable-buffer-local 'org-deadline-time-regexp)
2371 (defvar org-deadline-line-regexp nil
2372 "Matches the DEADLINE keyword and the rest of the line.")
2373 (make-variable-buffer-local 'org-deadline-line-regexp)
2374 (defvar org-scheduled-regexp nil
2375 "Matches the SCHEDULED keyword.")
2376 (make-variable-buffer-local 'org-scheduled-regexp)
2377 (defvar org-scheduled-time-regexp nil
2378 "Matches the SCHEDULED keyword together with a time stamp.")
2379 (make-variable-buffer-local 'org-scheduled-time-regexp)
2380 (defvar org-closed-time-regexp nil
2381 "Matches the CLOSED keyword together with a time stamp.")
2382 (make-variable-buffer-local 'org-closed-time-regexp)
2384 (defvar org-keyword-time-regexp nil
2385 "Matches any of the 3 keywords, together with the time stamp.")
2386 (make-variable-buffer-local 'org-keyword-time-regexp)
2387 (defvar org-maybe-keyword-time-regexp nil
2388 "Matches a timestamp, possibly preceeded by a keyword.")
2389 (make-variable-buffer-local 'org-keyword-time-regexp)
2391 (defconst org-rm-props '(invisible t face t keymap t intangible t mouse-face t
2392 mouse-map t)
2393 "Properties to remove when a string without properties is wanted.")
2395 (defsubst org-match-string-no-properties (num &optional string)
2396 (if (featurep 'xemacs)
2397 (let ((s (match-string num string)))
2398 (remove-text-properties 0 (length s) org-rm-props s)
2400 (match-string-no-properties num string)))
2402 (defsubst org-no-properties (s)
2403 (remove-text-properties 0 (length s) org-rm-props s)
2406 (defun org-set-regexps-and-options ()
2407 "Precompute regular expressions for current buffer."
2408 (when (eq major-mode 'org-mode)
2409 (let ((re (org-make-options-regexp
2410 '("CATEGORY" "SEQ_TODO" "PRI_TODO" "TYP_TODO"
2411 "STARTUP" "ARCHIVE" "TAGS")))
2412 (splitre "[ \t]+")
2413 kwds int key value cat arch tags)
2414 (save-excursion
2415 (save-restriction
2416 (widen)
2417 (goto-char (point-min))
2418 (while (re-search-forward re nil t)
2419 (setq key (match-string 1) value (org-match-string-no-properties 2))
2420 (cond
2421 ((equal key "CATEGORY")
2422 (if (string-match "[ \t]+$" value)
2423 (setq value (replace-match "" t t value)))
2424 (setq cat (intern value)))
2425 ((equal key "SEQ_TODO")
2426 (setq int 'sequence
2427 kwds (append kwds (org-split-string value splitre))))
2428 ((equal key "PRI_TODO")
2429 (setq int 'priority
2430 kwds (append kwds (org-split-string value splitre))))
2431 ((equal key "TYP_TODO")
2432 (setq int 'type
2433 kwds (append kwds (org-split-string value splitre))))
2434 ((equal key "TAGS")
2435 (setq tags (append tags (org-split-string value splitre))))
2436 ((equal key "STARTUP")
2437 (let ((opts (org-split-string value splitre))
2438 (set '(("fold" org-startup-folded t)
2439 ("overview" org-startup-folded t)
2440 ("nofold" org-startup-folded nil)
2441 ("showall" org-startup-folded nil)
2442 ("content" org-startup-folded content)
2443 ("hidestars" org-hide-leading-stars t)
2444 ("showstars" org-hide-leading-stars nil)
2445 ("odd" org-odd-levels-only t)
2446 ("oddeven" org-odd-levels-only nil)
2447 ("align" org-startup-align-all-tables t)
2448 ("noalign" org-startup-align-all-tables nil)
2449 ("logging" org-log-done t)
2450 ("nologging" org-log-done nil)
2451 ("dlcheck" org-startup-with-deadline-check t)
2452 ("nodlcheck" org-startup-with-deadline-check nil)))
2453 l var val)
2454 (while (setq l (assoc (pop opts) set))
2455 (setq var (nth 1 l) val (nth 2 l))
2456 (set (make-local-variable var) val))))
2457 ((equal key "ARCHIVE")
2458 (string-match " *$" value)
2459 (setq arch (replace-match "" t t value))
2460 (remove-text-properties 0 (length arch)
2461 '(face t fontified t) arch)))
2463 (and cat (set (make-local-variable 'org-category) cat))
2464 (and kwds (set (make-local-variable 'org-todo-keywords) kwds))
2465 (and arch (set (make-local-variable 'org-archive-location) arch))
2466 (and int (set (make-local-variable 'org-todo-interpretation) int))
2467 (when tags
2468 (let (e tg c tgs)
2469 (while (setq e (pop tags))
2470 (if (string-match "^\\([0-9a-zA-Z_@]+\\)(\\(.\\))$" e)
2471 (push (cons (match-string 1 e)
2472 (string-to-char (match-string 2 e)))
2473 tgs)
2474 (push (list e) tgs)))
2475 (set (make-local-variable 'org-tag-alist) nil)
2476 (while (setq e (pop tgs))
2477 (or (assoc (car e) org-tag-alist)
2478 (push e org-tag-alist))))))
2480 ;; Compute the regular expressions and other local variables
2481 (setq org-todo-kwd-priority-p (equal org-todo-interpretation 'priority)
2482 org-todo-kwd-max-priority (1- (length org-todo-keywords))
2483 org-ds-keyword-length (+ 2 (max (length org-deadline-string)
2484 (length org-scheduled-string)))
2485 org-done-string
2486 (nth (1- (length org-todo-keywords)) org-todo-keywords)
2487 org-todo-regexp
2488 (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords
2489 "\\|") "\\)\\>")
2490 org-not-done-regexp
2491 (concat "\\<\\("
2492 (mapconcat 'regexp-quote
2493 (nreverse (cdr (reverse org-todo-keywords)))
2494 "\\|")
2495 "\\)\\>")
2496 org-todo-line-regexp
2497 (concat "^\\(\\*+\\)[ \t]*\\("
2498 (mapconcat 'regexp-quote org-todo-keywords "\\|")
2499 "\\)? *\\(.*\\)")
2500 org-nl-done-regexp
2501 (concat "[\r\n]\\*+[ \t]+" org-done-string "\\>")
2502 org-looking-at-done-regexp (concat "^" org-done-string "\\>")
2503 org-deadline-regexp (concat "\\<" org-deadline-string)
2504 org-deadline-time-regexp
2505 (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
2506 org-deadline-line-regexp
2507 (concat "\\<\\(" org-deadline-string "\\).*")
2508 org-scheduled-regexp
2509 (concat "\\<" org-scheduled-string)
2510 org-scheduled-time-regexp
2511 (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
2512 org-closed-time-regexp
2513 (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
2514 org-keyword-time-regexp
2515 (concat "\\<\\(" org-scheduled-string
2516 "\\|" org-deadline-string
2517 "\\|" org-closed-string "\\)"
2518 " *[[<]\\([^]>]+\\)[]>]")
2519 org-maybe-keyword-time-regexp
2520 (concat "\\(\\<\\(" org-scheduled-string
2521 "\\|" org-deadline-string
2522 "\\|" org-closed-string "\\)\\)?"
2523 " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^]\r\n>]*?[]>]\\)"))
2525 (org-set-font-lock-defaults)))
2527 ;; Tell the compiler about dynamically scoped variables,
2528 ;; and variables from other packages
2529 (defvar calc-embedded-close-formula) ; defined by the calc package
2530 (defvar calc-embedded-open-formula) ; defined by the calc package
2531 (defvar font-lock-unfontify-region-function) ; defined by font-lock.el
2532 (defvar zmacs-regions) ; XEmacs regions
2533 (defvar original-date) ; dynamically scoped in calendar
2534 (defvar org-old-auto-fill-inhibit-regexp) ; local variable used by `orgtbl-mode'
2535 (defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized
2536 (defvar org-html-entities) ; defined later in this file
2537 (defvar org-goto-start-pos) ; dynamically scoped parameter
2538 (defvar org-time-was-given) ; dynamically scoped parameter
2539 (defvar org-ts-what) ; dynamically scoped parameter
2540 (defvar mark-active) ; Emacs only, not available in XEmacs.
2541 (defvar timecnt) ; dynamically scoped parameter
2542 (defvar levels-open) ; dynamically scoped parameter
2543 (defvar entry) ; dynamically scoped parameter
2544 (defvar date) ; dynamically scoped parameter
2545 (defvar description) ; dynamically scoped parameter
2546 (defvar ans1) ; dynamically scoped parameter
2547 (defvar ans2) ; dynamically scoped parameter
2548 (defvar starting-day) ; local variable
2549 (defvar include-all-loc) ; local variable
2550 (defvar vm-message-pointer) ; from vm
2551 (defvar vm-folder-directory) ; from vm
2552 (defvar wl-summary-buffer-elmo-folder) ; from wanderlust
2553 (defvar wl-summary-buffer-folder-name) ; from wanderlust
2554 (defvar gnus-group-name) ; from gnus
2555 (defvar gnus-article-current) ; from gnus
2556 (defvar w3m-current-url) ; from w3m
2557 (defvar mh-progs) ; from MH-E
2558 (defvar mh-current-folder) ; from MH-E
2559 (defvar mh-show-folder-buffer) ; from MH-E
2560 (defvar mh-index-folder) ; from MH-E
2561 (defvar mh-searcher) ; from MH-E
2562 (defvar org-selected-point) ; dynamically scoped parameter
2563 (defvar calendar-mode-map) ; from calendar.el
2564 (defvar last-arg) ; local variable
2565 (defvar remember-save-after-remembering) ; from remember.el
2566 (defvar remember-data-file) ; from remember.el
2567 (defvar annotation) ; from remember.el, dynamically scoped in `remember-mode'
2568 (defvar initial) ; from remember.el, dynamically scoped in `remember-mode'
2569 (defvar orgtbl-mode) ; defined later in this file
2570 (defvar Info-current-file) ; from info.el
2571 (defvar Info-current-node) ; from info.el
2573 ;;; Define the mode
2575 (defvar org-mode-map
2576 (if (and (not (keymapp outline-mode-map)) (featurep 'allout))
2577 (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.")
2578 (copy-keymap outline-mode-map))
2579 "Keymap for Org-mode.")
2581 (defvar org-struct-menu) ; defined later in this file
2582 (defvar org-org-menu) ; defined later in this file
2583 (defvar org-tbl-menu) ; defined later in this file
2585 ;; We use a before-change function to check if a table might need
2586 ;; an update.
2587 (defvar org-table-may-need-update t
2588 "Indicates that a table might need an update.
2589 This variable is set by `org-before-change-function'.
2590 `org-table-align' sets it back to nil.")
2591 (defvar org-mode-hook nil)
2592 (defvar org-inhibit-startup nil) ; Dynamically-scoped param.
2593 (defvar org-agenda-keep-modes nil) ; Dynamically-scoped param.
2596 ;;;###autoload
2597 (define-derived-mode org-mode outline-mode "Org"
2598 "Outline-based notes management and organizer, alias
2599 \"Carsten's outline-mode for keeping track of everything.\"
2601 Org-mode develops organizational tasks around a NOTES file which
2602 contains information about projects as plain text. Org-mode is
2603 implemented on top of outline-mode, which is ideal to keep the content
2604 of large files well structured. It supports ToDo items, deadlines and
2605 time stamps, which magically appear in the diary listing of the Emacs
2606 calendar. Tables are easily created with a built-in table editor.
2607 Plain text URL-like links connect to websites, emails (VM), Usenet
2608 messages (Gnus), BBDB entries, and any files related to the project.
2609 For printing and sharing of notes, an Org-mode file (or a part of it)
2610 can be exported as a structured ASCII or HTML file.
2612 The following commands are available:
2614 \\{org-mode-map}"
2616 ;; Get rid of Outline menus, they are not needed
2617 ;; Need to do this here because define-derived-mode sets up
2618 ;; the keymap so late.
2619 (if (featurep 'xemacs)
2620 (if org-noutline-p
2621 (progn
2622 (easy-menu-remove outline-mode-menu-heading)
2623 (easy-menu-remove outline-mode-menu-show)
2624 (easy-menu-remove outline-mode-menu-hide))
2625 (delete-menu-item '("Headings"))
2626 (delete-menu-item '("Show"))
2627 (delete-menu-item '("Hide"))
2628 (set-menubar-dirty-flag))
2629 (define-key org-mode-map [menu-bar headings] 'undefined)
2630 (define-key org-mode-map [menu-bar hide] 'undefined)
2631 (define-key org-mode-map [menu-bar show] 'undefined))
2633 (easy-menu-add org-org-menu)
2634 (easy-menu-add org-tbl-menu)
2635 (org-install-agenda-files-menu)
2636 (if org-descriptive-links (org-add-to-invisibility-spec '(org-link)))
2637 (org-add-to-invisibility-spec '(org-cwidth))
2638 (when (featurep 'xemacs)
2639 (set (make-local-variable 'line-move-ignore-invisible) t))
2640 (setq outline-regexp "\\*+")
2641 ;;(setq outline-regexp "\\(?:\\*+\\|[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\) \\)")
2642 (setq outline-level 'org-outline-level)
2643 (when (and org-ellipsis (stringp org-ellipsis))
2644 (unless org-display-table
2645 (setq org-display-table (make-display-table)))
2646 (set-display-table-slot org-display-table
2647 4 (string-to-vector org-ellipsis))
2648 (setq buffer-display-table org-display-table))
2649 (org-set-regexps-and-options)
2650 (if org-startup-truncated (setq truncate-lines t))
2651 (set (make-local-variable 'font-lock-unfontify-region-function)
2652 'org-unfontify-region)
2653 ;; Activate before-change-function
2654 (set (make-local-variable 'org-table-may-need-update) t)
2655 (org-add-hook 'before-change-functions 'org-before-change-function nil
2656 'local)
2657 ;; Paragraphs and auto-filling
2658 (org-set-autofill-regexps)
2659 (org-update-radio-target-regexp)
2660 ;; Settings for Calc embedded mode
2661 (set (make-local-variable 'calc-embedded-open-formula) "|\\|\n")
2662 (set (make-local-variable 'calc-embedded-close-formula) "|\\|\n")
2663 (if (and org-insert-mode-line-in-empty-file
2664 (interactive-p)
2665 (= (point-min) (point-max)))
2666 (insert " -*- mode: org -*-\n\n"))
2668 (unless org-inhibit-startup
2669 (if org-startup-align-all-tables
2670 (org-table-map-tables 'org-table-align))
2671 (if org-startup-with-deadline-check
2672 (call-interactively 'org-check-deadlines)
2673 (cond
2674 ((eq org-startup-folded t)
2675 (org-cycle '(4)))
2676 ((eq org-startup-folded 'content)
2677 (let ((this-command 'org-cycle) (last-command 'org-cycle))
2678 (org-cycle '(4)) (org-cycle '(4))))))))
2680 (defsubst org-call-with-arg (command arg)
2681 "Call COMMAND interactively, but pretend prefix are was ARG."
2682 (let ((current-prefix-arg arg)) (call-interactively command)))
2684 (defsubst org-current-line (&optional pos)
2685 (+ (if (bolp) 1 0) (count-lines (point-min) (or pos (point)))))
2687 (defun org-current-time ()
2688 "Current time, possibly rounded to `org-time-stamp-rounding-minutes'."
2689 (if (> org-time-stamp-rounding-minutes 0)
2690 (let ((r org-time-stamp-rounding-minutes)
2691 (time (decode-time)))
2692 (apply 'encode-time
2693 (append (list 0 (* r (floor (+ .5 (/ (float (nth 1 time)) r)))))
2694 (nthcdr 2 time))))
2695 (current-time)))
2697 (defun org-add-props (string plist &rest props)
2698 "Add text properties to entire string, from beginning to end.
2699 PLIST may be a list of properties, PROPS are individual properties and values
2700 that will be added to PLIST. Returns the string that was modified."
2701 (add-text-properties
2702 0 (length string) (if props (append plist props) plist) string)
2703 string)
2704 (put 'org-add-props 'lisp-indent-function 2)
2707 ;;; Font-Lock stuff
2709 (defvar org-mouse-map (make-sparse-keymap))
2710 (define-key org-mouse-map
2711 (if (featurep 'xemacs) [button2] [mouse-2]) 'org-open-at-mouse)
2712 (define-key org-mouse-map
2713 (if (featurep 'xemacs) [button3] [mouse-3]) 'org-find-file-at-mouse)
2714 (when org-mouse-1-follows-link
2715 (define-key org-mouse-map [follow-link] 'mouse-face))
2716 (when org-tab-follows-link
2717 (define-key org-mouse-map [(tab)] 'org-open-at-point)
2718 (define-key org-mouse-map "\C-i" 'org-open-at-point))
2719 (when org-return-follows-link
2720 (define-key org-mouse-map [(return)] 'org-open-at-point)
2721 (define-key org-mouse-map "\C-m" 'org-open-at-point))
2723 (require 'font-lock)
2725 (defconst org-non-link-chars "]\t\n\r<>")
2726 (defconst org-link-types '("https?" "ftp" "mailto" "file" "news" "bbdb" "vm"
2727 "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
2728 (defconst org-link-re-with-space
2729 (concat
2730 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
2731 "\\([^" org-non-link-chars " ]"
2732 "[^" org-non-link-chars "]*"
2733 "[^" org-non-link-chars " ]\\)>?")
2734 "Matches a link with spaces, optional angular brackets around it.")
2736 (defconst org-link-re-with-space2
2737 (concat
2738 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
2739 "\\([^" org-non-link-chars " ]"
2740 "[^]\t\n\r]*"
2741 "[^" org-non-link-chars " ]\\)>?")
2742 "Matches a link with spaces, optional angular brackets around it.")
2744 (defconst org-angle-link-re
2745 (concat
2746 "<\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
2747 "\\([^" org-non-link-chars " ]"
2748 "[^" org-non-link-chars "]*"
2749 "\\)>")
2750 "Matches link with angular brackets, spaces are allowed.")
2751 (defconst org-plain-link-re
2752 (concat
2753 "\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
2754 "\\([^]\t\n\r<>,;() ]+\\)")
2755 "Matches plain link, without spaces.")
2757 (defconst org-bracket-link-regexp
2758 "\\[\\[\\([^]]+\\)\\]\\(\\[\\([^]]+\\)\\]\\)?\\]"
2759 "Matches a link in double brackets.")
2761 (defconst org-bracket-link-analytic-regexp
2762 (concat
2763 "\\[\\["
2764 "\\(\\(" (mapconcat 'identity org-link-types "\\|") "\\):\\)?"
2765 "\\([^]]+\\)"
2766 "\\]"
2767 "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
2768 "\\]"))
2769 ; 1: http:
2770 ; 2: http
2771 ; 3: path
2772 ; 4: [desc]
2773 ; 5: desc
2776 (defconst org-ts-lengths
2777 (cons (length (format-time-string (car org-time-stamp-formats)))
2778 (length (format-time-string (cdr org-time-stamp-formats))))
2779 "This holds the lengths of the two different time formats.")
2780 (defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^\r\n>]*?\\)>"
2781 "Regular expression for fast time stamp matching.")
2782 (defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^\r\n>]*?\\)[]>]"
2783 "Regular expression for fast time stamp matching.")
2784 (defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\([^0-9>\r\n]*\\)\\(\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
2785 "Regular expression matching time strings for analysis.")
2786 (defconst org-ts-regexp2 (concat "<" org-ts-regexp1 ">")
2787 "Regular expression matching time stamps, with groups.")
2788 (defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp)
2789 "Regular expression matching a time stamp range.")
2790 (defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?"
2791 org-ts-regexp "\\)?")
2792 "Regular expression matching a time stamp or time stamp range.")
2794 (defun org-activate-plain-links (limit)
2795 "Run through the buffer and add overlays to links."
2796 (if (re-search-forward org-plain-link-re limit t)
2797 (progn
2798 (add-text-properties (match-beginning 0) (match-end 0)
2799 (list 'mouse-face 'highlight
2800 'keymap org-mouse-map
2802 t)))
2804 (defun org-activate-angle-links (limit)
2805 "Run through the buffer and add overlays to links."
2806 (if (re-search-forward org-angle-link-re limit t)
2807 (progn
2808 (add-text-properties (match-beginning 0) (match-end 0)
2809 (list 'mouse-face 'highlight
2810 'keymap org-mouse-map
2812 t)))
2814 (defun org-activate-bracket-links (limit)
2815 "Run through the buffer and add overlays to bracketed links."
2816 (if (re-search-forward org-bracket-link-regexp limit t)
2817 (let* ((help (concat "LINK: "
2818 (org-match-string-no-properties 1)))
2819 ;; FIXME: above we should remove the escapes.
2820 (ip (list 'invisible 'org-link 'intangible t 'rear-nonsticky t
2821 'keymap org-mouse-map 'mouse-face 'highlight
2822 'help-echo help))
2823 (vp (list 'rear-nonsticky t
2824 'keymap org-mouse-map 'mouse-face 'highlight
2825 'help-echo help)))
2826 ;; We need to remove the invisible property here. Table narrowing
2827 ;; may have made some of this invisible.
2828 (remove-text-properties (match-beginning 0) (match-end 0)
2829 '(invisible nil))
2830 (if (match-end 3)
2831 (progn
2832 (add-text-properties (match-beginning 0) (match-beginning 3) ip)
2833 (add-text-properties (match-beginning 3) (match-end 3) vp)
2834 (add-text-properties (match-end 3) (match-end 0) ip))
2835 (add-text-properties (match-beginning 0) (match-beginning 1) ip)
2836 (add-text-properties (match-beginning 1) (match-end 1) vp)
2837 (add-text-properties (match-end 1) (match-end 0) ip))
2838 t)))
2840 (defun org-activate-dates (limit)
2841 "Run through the buffer and add overlays to dates."
2842 (if (re-search-forward org-tsr-regexp limit t)
2843 (progn
2844 (add-text-properties (match-beginning 0) (match-end 0)
2845 (list 'mouse-face 'highlight
2846 'keymap org-mouse-map))
2847 t)))
2849 (defvar org-target-link-regexp nil
2850 "Regular expression matching radio targets in plain text.")
2851 (defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>"
2852 "Regular expression matching a link target.")
2853 (defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>"
2854 "Regular expression matching a link target.")
2856 (defun org-activate-target-links (limit)
2857 "Run through the buffer and add overlays to target matches."
2858 (when org-target-link-regexp
2859 (let ((case-fold-search t))
2860 (if (re-search-forward org-target-link-regexp limit t)
2861 (progn
2862 (add-text-properties (match-beginning 0) (match-end 0)
2863 (list 'mouse-face 'highlight
2864 'keymap org-mouse-map
2865 'help-echo "Radio target link"
2866 'org-linked-text t))
2867 t)))))
2869 (defun org-update-radio-target-regexp ()
2870 "Find all radio targets in this file and update the regular expression."
2871 (interactive)
2872 (when (memq 'radio org-activate-links)
2873 (setq org-target-link-regexp
2874 (org-make-target-link-regexp (org-all-targets 'radio)))
2875 (org-restart-font-lock)))
2877 (defun org-hide-wide-columns (limit)
2878 (let (s e)
2879 (setq s (text-property-any (point) (or limit (point-max))
2880 'org-cwidth t))
2881 (when s
2882 (setq e (next-single-property-change s 'org-cwidth))
2883 (add-text-properties s e '(invisible org-cwidth intangible t))
2884 (goto-char e)
2885 t)))
2887 (defun org-restart-font-lock ()
2888 "Restart font-lock-mode, to force refontification."
2889 (when (and (boundp 'font-lock-mode) font-lock-mode)
2890 (font-lock-mode -1)
2891 (font-lock-mode 1)))
2893 (defun org-all-targets (&optional radio)
2894 "Return a list of all targets in this file.
2895 With optional argument RADIO, only find radio targets."
2896 (let ((re (if radio org-radio-target-regexp org-target-regexp))
2897 rtn)
2898 (save-excursion
2899 (goto-char (point-min))
2900 (while (re-search-forward re nil t)
2901 (add-to-list 'rtn (downcase (org-match-string-no-properties 1))))
2902 rtn)))
2904 (defun org-make-target-link-regexp (targets)
2905 "Make regular expression matching all strings in TARGETS.
2906 The regular expression finds the targets also if there is a line break
2907 between words."
2908 (and targets
2909 (concat
2910 "\\<\\("
2911 (mapconcat
2912 (lambda (x)
2913 (while (string-match " +" x)
2914 (setq x (replace-match "\\s-+" t t x)))
2916 targets
2917 "\\|")
2918 "\\)\\>")))
2920 (defvar org-camel-regexp "\\*?\\<[A-Z]+[a-z]+[A-Z][a-zA-Z]*\\>"
2921 "Matches CamelCase words, possibly with a star before it.")
2923 (defun org-activate-camels (limit)
2924 "Run through the buffer and add overlays to dates."
2925 (if (re-search-forward org-camel-regexp limit t)
2926 (progn
2927 (add-text-properties (match-beginning 0) (match-end 0)
2928 (list 'mouse-face 'highlight
2929 'keymap org-mouse-map))
2930 t)))
2932 (defun org-activate-tags (limit)
2933 (if (re-search-forward "[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \r\n]" limit t)
2934 (progn
2935 (add-text-properties (match-beginning 1) (match-end 1)
2936 (list 'mouse-face 'highlight
2937 'keymap org-mouse-map))
2938 t)))
2940 (defun org-font-lock-level ()
2941 (save-excursion
2942 (org-back-to-heading t)
2943 (- (match-end 0) (match-beginning 0))))
2945 (defun org-outline-level ()
2946 (save-excursion
2947 (looking-at outline-regexp)
2948 (if (match-beginning 1)
2949 (+ (org-get-string-indentation (match-string 1)) 1000)
2950 (- (match-end 0) (match-beginning 0)))))
2952 (defvar org-font-lock-keywords nil)
2954 (defun org-set-font-lock-defaults ()
2955 (let* ((em org-fontify-emphasized-text)
2956 (lk org-activate-links)
2957 (org-font-lock-extra-keywords
2958 ;; Headlines
2959 (list
2960 '("^\\(\\**\\)\\(\\*\\)\\(.*\\)" (1 (org-get-level-face 1))
2961 (2 (org-get-level-face 2)) (3 (org-get-level-face 3)))
2962 '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)"
2963 (1 'org-table))
2964 ;; Links
2965 (if (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
2966 (if (memq 'plain lk) '(org-activate-plain-links (0 'org-link t)))
2967 (if (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
2968 (if (memq 'radio lk) '(org-activate-target-links (0 'org-link t)))
2969 (if (memq 'date lk) '(org-activate-dates (0 'org-date t)))
2970 (if (memq 'camel lk) '(org-activate-camels (0 'org-link t)))
2971 (if (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
2972 (if org-table-limit-column-width
2973 '(org-hide-wide-columns (0 nil append)))
2974 ;; TODO lines
2975 (list (concat "^\\*+[ \t]*" org-not-done-regexp)
2976 '(1 'org-todo t))
2977 ;; Priorities
2978 (list (concat "\\[#[A-Z]\\]") '(0 'org-special-keyword t))
2979 ;; Special keywords
2980 (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t))
2981 (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword t))
2982 (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t))
2983 ;; Emphasis
2984 (if em (list org-bold-re 2 ''bold 'prepend))
2985 (if em (list org-italic-re 2 ''italic 'prepend))
2986 (if em (list org-underline-re 2 ''underline 'prepend))
2987 ;; Checkboxes, similar to Frank Ruell's org-checklet.el
2988 '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)"
2989 2 'bold prepend)
2990 ;; COMMENT
2991 (list (concat "^\\*+[ \t]*\\<\\(" org-comment-string
2992 "\\|" org-quote-string "\\)\\>")
2993 '(1 'org-special-keyword t))
2994 '("^#.*" (0 'font-lock-comment-face t))
2995 ;; DONE
2996 (if org-fontify-done-headline
2997 (list (concat "^[*]+ +\\<\\(" org-done-string "\\)\\(.*\\)\\>")
2998 '(1 'org-done t) '(2 'org-headline-done t))
2999 (list (concat "^[*]+ +\\<\\(" org-done-string "\\)\\>")
3000 '(1 'org-done t)))
3001 ;; Table stuff
3002 '("^[ \t]*\\(:.*\\)" (1 'org-table t))
3003 '("| *\\(:?=[^|\n]*\\)" (1 'org-formula t))
3004 '("^[ \t]*| *\\([#!$*_^]\\) *|" (1 'org-formula t))
3005 (if org-format-transports-properties-p
3006 '("| *\\(<[0-9]+>\\) *" (1 'org-formula t)))
3008 (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords))
3009 ;; Now set the full font-lock-keywords
3010 (set (make-local-variable 'org-font-lock-keywords)
3011 org-font-lock-extra-keywords)
3012 (set (make-local-variable 'font-lock-defaults)
3013 '(org-font-lock-keywords t nil nil backward-paragraph))
3014 (kill-local-variable 'font-lock-keywords) nil))
3016 (defvar org-m nil)
3017 (defvar org-l nil)
3018 (defvar org-f nil)
3019 (defun org-get-level-face (n)
3020 "Get the right face for match N in font-lock matching of healdines."
3021 (setq org-l (- (match-end 2) (match-beginning 1)))
3022 (if org-odd-levels-only (setq org-l (1+ (/ org-l 2))))
3023 ; (setq org-f (nth (1- (% org-l org-n-levels)) org-level-faces))
3024 (setq org-f (nth (% (1- org-l) org-n-levels) org-level-faces))
3025 (cond
3026 ((eq n 1) (if org-hide-leading-stars 'org-hide org-f))
3027 ((eq n 2) org-f)
3028 (t (if org-level-color-stars-only nil org-f))))
3030 (defun org-unfontify-region (beg end &optional maybe_loudly)
3031 "Remove fontification and activation overlays from links."
3032 (font-lock-default-unfontify-region beg end)
3033 (let* ((buffer-undo-list t)
3034 (inhibit-read-only t) (inhibit-point-motion-hooks t)
3035 (inhibit-modification-hooks t)
3036 deactivate-mark buffer-file-name buffer-file-truename)
3037 (remove-text-properties beg end
3038 '(mouse-face nil keymap nil org-linked-text nil
3039 invisible nil intangible nil))))
3040 ;;; Visibility cycling
3042 (defvar org-cycle-global-status nil)
3043 (make-variable-buffer-local 'org-cycle-global-status)
3044 (defvar org-cycle-subtree-status nil)
3045 (make-variable-buffer-local 'org-cycle-subtree-status)
3047 ;;;###autoload
3048 (defun org-cycle (&optional arg)
3049 "Visibility cycling for Org-mode.
3051 - When this function is called with a prefix argument, rotate the entire
3052 buffer through 3 states (global cycling)
3053 1. OVERVIEW: Show only top-level headlines.
3054 2. CONTENTS: Show all headlines of all levels, but no body text.
3055 3. SHOW ALL: Show everything.
3057 - When point is at the beginning of a headline, rotate the subtree started
3058 by this line through 3 different states (local cycling)
3059 1. FOLDED: Only the main headline is shown.
3060 2. CHILDREN: The main headline and the direct children are shown.
3061 From this state, you can move to one of the children
3062 and zoom in further.
3063 3. SUBTREE: Show the entire subtree, including body text.
3065 - When there is a numeric prefix, go up to a heading with level ARG, do
3066 a `show-subtree' and return to the previous cursor position. If ARG
3067 is negative, go up that many levels.
3069 - When point is not at the beginning of a headline, execute
3070 `indent-relative', like TAB normally does. See the option
3071 `org-cycle-emulate-tab' for details.
3073 - Special case: if point is the the beginning of the buffer and there is
3074 no headline in line 1, this function will act as if called with prefix arg."
3075 (interactive "P")
3077 (let* ((outline-regexp
3078 (if org-cycle-include-plain-lists
3079 "\\*+\\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) "
3080 outline-regexp))
3081 (bob-special (and org-cycle-global-at-bob (bobp)
3082 (not (looking-at outline-regexp))))
3083 (org-cycle-hook (if bob-special nil org-cycle-hook)))
3085 (if (or bob-special (equal arg '(4)))
3086 ;; special case: use global cycling
3087 (setq arg t))
3089 (cond
3091 ((org-at-table-p 'any)
3092 ;; Enter the table or move to the next field in the table
3093 (or (org-table-recognize-table.el)
3094 (progn
3095 (if arg (org-table-edit-field t)
3096 (org-table-justify-field-maybe)
3097 (call-interactively 'org-table-next-field)))))
3099 ((eq arg t) ;; Global cycling
3101 (cond
3102 ((and (eq last-command this-command)
3103 (eq org-cycle-global-status 'overview))
3104 ;; We just created the overview - now do table of contents
3105 ;; This can be slow in very large buffers, so indicate action
3106 (message "CONTENTS...")
3107 (org-content)
3108 (message "CONTENTS...done")
3109 (setq org-cycle-global-status 'contents)
3110 (run-hook-with-args 'org-cycle-hook 'contents))
3112 ((and (eq last-command this-command)
3113 (eq org-cycle-global-status 'contents))
3114 ;; We just showed the table of contents - now show everything
3115 (show-all)
3116 (message "SHOW ALL")
3117 (setq org-cycle-global-status 'all)
3118 (run-hook-with-args 'org-cycle-hook 'all))
3121 ;; Default action: go to overview
3122 (org-overview)
3123 (message "OVERVIEW")
3124 (setq org-cycle-global-status 'overview)
3125 (run-hook-with-args 'org-cycle-hook 'overview))))
3127 ((integerp arg)
3128 ;; Show-subtree, ARG levels up from here.
3129 (save-excursion
3130 (org-back-to-heading)
3131 (outline-up-heading (if (< arg 0) (- arg)
3132 (- (funcall outline-level) arg)))
3133 (org-show-subtree)))
3135 ((save-excursion (beginning-of-line 1) (looking-at outline-regexp))
3136 ;; At a heading: rotate between three different views
3137 (org-back-to-heading)
3138 (let ((goal-column 0) eoh eol eos)
3139 ;; First, some boundaries
3140 (save-excursion
3141 (org-back-to-heading)
3142 (save-excursion
3143 (beginning-of-line 2)
3144 (while (and (not (eobp)) ;; this is like `next-line'
3145 (get-char-property (1- (point)) 'invisible))
3146 (beginning-of-line 2)) (setq eol (point)))
3147 (outline-end-of-heading) (setq eoh (point))
3148 (org-end-of-subtree t) (setq eos (point))
3149 (outline-next-heading))
3150 ;; Find out what to do next and set `this-command'
3151 (cond
3152 ((and (= eos eoh)
3153 ;; Nothing is hidden behind this heading
3154 (message "EMPTY ENTRY")
3155 (setq org-cycle-subtree-status nil)))
3156 ((>= eol eos)
3157 ;; Entire subtree is hidden in one line: open it
3158 (org-show-entry)
3159 (show-children)
3160 (message "CHILDREN")
3161 (setq org-cycle-subtree-status 'children)
3162 (run-hook-with-args 'org-cycle-hook 'children))
3163 ((and (eq last-command this-command)
3164 (eq org-cycle-subtree-status 'children))
3165 ;; We just showed the children, now show everything.
3166 (org-show-subtree)
3167 (message "SUBTREE")
3168 (setq org-cycle-subtree-status 'subtree)
3169 (run-hook-with-args 'org-cycle-hook 'subtree))
3171 ;; Default action: hide the subtree.
3172 (hide-subtree)
3173 (message "FOLDED")
3174 (setq org-cycle-subtree-status 'folded)
3175 (run-hook-with-args 'org-cycle-hook 'folded)))))
3177 ;; TAB emulation
3178 (buffer-read-only (org-back-to-heading))
3179 ((if (and (eq org-cycle-emulate-tab 'white)
3180 (save-excursion (beginning-of-line 1) (looking-at "[ \t]+$")))
3182 (eq org-cycle-emulate-tab t))
3183 (if (and (looking-at "[ \n\r\t]")
3184 (string-match "^[ \t]*$" (buffer-substring
3185 (point-at-bol) (point))))
3186 (progn
3187 (beginning-of-line 1)
3188 (and (looking-at "[ \t]+") (replace-match ""))))
3189 (indent-relative))
3191 (t (save-excursion
3192 (org-back-to-heading)
3193 (org-cycle))))))
3195 ;;;###autoload
3196 (defun org-global-cycle ()
3197 "Cycle the global visibility. For details see `org-cycle'."
3198 (interactive)
3199 (org-cycle '(4)))
3201 (defun org-overview ()
3202 "Switch to overview mode, shoing only top-level headlines.
3203 Really, this shows all headlines with level equal or greater than the level
3204 of the first headline in the buffer. This is important, because if the
3205 first headline is not level one, then (hide-sublevels 1) gives confusing
3206 results."
3207 (interactive)
3208 (hide-sublevels (save-excursion
3209 (goto-char (point-min))
3210 (if (re-search-forward (concat "^" outline-regexp) nil t)
3211 (progn
3212 (goto-char (match-beginning 0))
3213 (funcall outline-level))
3214 1))))
3216 ;; FIXME: allow an argument to give a limiting level for this.
3217 (defun org-content ()
3218 "Show all headlines in the buffer, like a table of contents"
3219 (interactive)
3220 (save-excursion
3221 ;; Visit all headings and show their offspring
3222 (goto-char (point-max))
3223 (catch 'exit
3224 (while (and (progn (condition-case nil
3225 (outline-previous-visible-heading 1)
3226 (error (goto-char (point-min))))
3228 (looking-at outline-regexp))
3229 (show-branches)
3230 (if (bobp) (throw 'exit nil))))))
3233 (defun org-optimize-window-after-visibility-change (state)
3234 "Adjust the window after a change in outline visibility.
3235 This function is the default value of the hook `org-cycle-hook'."
3236 (when (get-buffer-window (current-buffer))
3237 (cond
3238 ((eq state 'overview) (org-first-headline-recenter 1))
3239 ((eq state 'content) nil)
3240 ((eq state 'all) nil)
3241 ((eq state 'folded) nil)
3242 ((eq state 'children) (or (org-subtree-end-visible-p) (recenter 1)))
3243 ((eq state 'subtree) (or (org-subtree-end-visible-p) (recenter 1))))))
3245 (defun org-subtree-end-visible-p ()
3246 "Is the end of the current subtree visible?"
3247 (pos-visible-in-window-p
3248 (save-excursion (org-end-of-subtree t) (point))))
3250 (defun org-first-headline-recenter (&optional N)
3251 "Move cursor to the first headline and recenter the headline.
3252 Optional argument N means, put the headline into the Nth line of the window."
3253 (goto-char (point-min))
3254 (when (re-search-forward (concat "^" outline-regexp) nil t)
3255 (beginning-of-line)
3256 (recenter (prefix-numeric-value N))))
3258 (defvar org-goto-window-configuration nil)
3259 (defvar org-goto-marker nil)
3260 (defvar org-goto-map (make-sparse-keymap))
3261 (let ((cmds '(isearch-forward isearch-backward)) cmd)
3262 (while (setq cmd (pop cmds))
3263 (substitute-key-definition cmd cmd org-goto-map global-map)))
3264 (define-key org-goto-map "\C-m" 'org-goto-ret)
3265 (define-key org-goto-map [(left)] 'org-goto-left)
3266 (define-key org-goto-map [(right)] 'org-goto-right)
3267 (define-key org-goto-map [(?q)] 'org-goto-quit)
3268 (define-key org-goto-map [(control ?g)] 'org-goto-quit)
3269 (define-key org-goto-map "\C-i" 'org-cycle)
3270 (define-key org-goto-map [(tab)] 'org-cycle)
3271 (define-key org-goto-map [(down)] 'outline-next-visible-heading)
3272 (define-key org-goto-map [(up)] 'outline-previous-visible-heading)
3273 (define-key org-goto-map "n" 'outline-next-visible-heading)
3274 (define-key org-goto-map "p" 'outline-previous-visible-heading)
3275 (define-key org-goto-map "f" 'outline-forward-same-level)
3276 (define-key org-goto-map "b" 'outline-backward-same-level)
3277 (define-key org-goto-map "u" 'outline-up-heading)
3278 (define-key org-goto-map "\C-c\C-n" 'outline-next-visible-heading)
3279 (define-key org-goto-map "\C-c\C-p" 'outline-previous-visible-heading)
3280 (define-key org-goto-map "\C-c\C-f" 'outline-forward-same-level)
3281 (define-key org-goto-map "\C-c\C-b" 'outline-backward-same-level)
3282 (define-key org-goto-map "\C-c\C-u" 'outline-up-heading)
3283 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
3284 (while l (define-key org-goto-map (int-to-string (pop l)) 'digit-argument)))
3286 (defconst org-goto-help
3287 "Select a location to jump to, press RET
3288 \[Up]/[Down]=next/prev headline TAB=cycle visibility RET=select [Q]uit")
3290 (defun org-goto ()
3291 "Go to a different location of the document, keeping current visibility.
3293 When you want to go to a different location in a document, the fastest way
3294 is often to fold the entire buffer and then dive into the tree. This
3295 method has the disadvantage, that the previous location will be folded,
3296 which may not be what you want.
3298 This command works around this by showing a copy of the current buffer in
3299 overview mode. You can dive into the tree in that copy, to find the
3300 location you want to reach. When pressing RET, the command returns to the
3301 original buffer in which the visibility is still unchanged. It then jumps
3302 to the new location, making it and the headline hierarchy above it visible."
3303 (interactive)
3304 (let* ((org-goto-start-pos (point))
3305 (selected-point
3306 (org-get-location (current-buffer) org-goto-help)))
3307 (if selected-point
3308 (progn
3309 (org-mark-ring-push org-goto-start-pos)
3310 (goto-char selected-point)
3311 (if (or (org-invisible-p) (org-invisible-p2))
3312 (org-show-hierarchy-above)))
3313 (error "Quit"))))
3315 (defun org-get-location (buf help)
3316 "Let the user select a location in the Org-mode buffer BUF.
3317 This function uses a recursive edit. It returns the selected position
3318 or nil."
3319 (let (org-selected-point)
3320 (save-excursion
3321 (save-window-excursion
3322 (delete-other-windows)
3323 (switch-to-buffer (get-buffer-create "*org-goto*"))
3324 (with-output-to-temp-buffer "*Help*"
3325 (princ help))
3326 (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*"))
3327 (setq buffer-read-only nil)
3328 (erase-buffer)
3329 (insert-buffer-substring buf)
3330 (let ((org-startup-truncated t)
3331 (org-startup-folded t)
3332 (org-startup-align-all-tables nil)
3333 (org-startup-with-deadline-check nil))
3334 (org-mode))
3335 (setq buffer-read-only t)
3336 (if (boundp 'org-goto-start-pos)
3337 (goto-char org-goto-start-pos)
3338 (goto-char (point-min)))
3339 (org-beginning-of-line)
3340 (message "Select location and press RET")
3341 ;; now we make sure that during selection, ony very few keys work
3342 ;; and that it is impossible to switch to another window.
3343 (let ((gm (current-global-map))
3344 (overriding-local-map org-goto-map))
3345 (unwind-protect
3346 (progn
3347 (use-global-map org-goto-map)
3348 (recursive-edit))
3349 (use-global-map gm)))))
3350 (kill-buffer "*org-goto*")
3351 org-selected-point))
3353 (defun org-goto-ret (&optional arg)
3354 "Finish `org-goto' by going to the new location."
3355 (interactive "P")
3356 (setq org-selected-point (point)
3357 current-prefix-arg arg)
3358 (throw 'exit nil))
3360 (defun org-goto-left ()
3361 "Finish `org-goto' by going to the new location."
3362 (interactive)
3363 (if (org-on-heading-p)
3364 (progn
3365 (beginning-of-line 1)
3366 (setq org-selected-point (point)
3367 current-prefix-arg (- (match-end 0) (match-beginning 0)))
3368 (throw 'exit nil))
3369 (error "Not on a heading")))
3371 (defun org-goto-right ()
3372 "Finish `org-goto' by going to the new location."
3373 (interactive)
3374 (if (org-on-heading-p)
3375 (progn
3376 (outline-end-of-subtree)
3377 (or (eobp) (forward-char 1))
3378 (setq org-selected-point (point)
3379 current-prefix-arg (- (match-end 0) (match-beginning 0)))
3380 (throw 'exit nil))
3381 (error "Not on a heading")))
3383 (defun org-goto-quit ()
3384 "Finish `org-goto' without cursor motion."
3385 (interactive)
3386 (setq org-selected-point nil)
3387 (throw 'exit nil))
3389 ;;; Promotion, Demotion, Inserting new headlines
3391 (defvar org-ignore-region nil
3392 "To temporarily disable the active region.")
3394 (defun org-insert-heading (&optional force-heading)
3395 "Insert a new heading or item with same depth at point.
3396 If point is in a plain list and FORCE-HEADING is nil, create a new list item.
3397 If point is at the beginning of a headline, insert a sibling before the
3398 current headline. If point is in the middle of a headline, split the headline
3399 at that position and make the rest of the headline part of the sibling below
3400 the current headline."
3401 (interactive "P")
3402 (if (= (buffer-size) 0)
3403 (insert "\n* ")
3404 (when (or force-heading (not (org-insert-item)))
3405 (let* ((head (save-excursion
3406 (condition-case nil
3407 (progn
3408 (org-back-to-heading)
3409 (match-string 0))
3410 (error "*"))))
3411 pos)
3412 (cond
3413 ((and (org-on-heading-p) (bolp)
3414 (save-excursion (backward-char 1) (not (org-invisible-p))))
3415 (open-line 1))
3416 ((bolp) nil)
3417 (t (newline)))
3418 (insert head) (just-one-space)
3419 (setq pos (point))
3420 (end-of-line 1)
3421 (unless (= (point) pos) (just-one-space) (backward-delete-char 1))
3422 (run-hooks 'org-insert-heading-hook)))))
3424 (defun org-insert-item (&optional checkbox)
3425 "Insert a new item at the current level.
3426 Return t when things worked, nil when we are not in an item."
3427 (when (save-excursion
3428 (condition-case nil
3429 (progn
3430 (org-beginning-of-item)
3431 (org-at-item-p)
3433 (error nil)))
3434 (let* ((bul (match-string 0))
3435 (end (match-end 0))
3436 (eow (save-excursion (beginning-of-line 1) (looking-at "[ \t]*")
3437 (match-end 0)))
3438 (eowcol (save-excursion (goto-char eow) (current-column)))
3439 pos)
3440 (cond
3441 ((and (org-at-item-p) (<= (point) eow))
3442 ;; before the bullet
3443 (beginning-of-line 1)
3444 (open-line 1))
3445 ((<= (point) eow)
3446 (beginning-of-line 1))
3447 (t (newline)))
3448 (insert bul (if checkbox "[ ]" ""))
3449 (just-one-space)
3450 (setq pos (point))
3451 (end-of-line 1)
3452 (unless (= (point) pos) (just-one-space) (backward-delete-char 1)))
3453 (org-maybe-renumber-ordered-list)
3456 (defun org-insert-todo-heading (arg)
3457 "Insert a new heading with the same level and TODO state as current heading.
3458 If the heading has no TODO state, or if the state is DONE, use the first
3459 state (TODO by default). Also with prefix arg, force first state."
3460 (interactive "P")
3461 (when (not (org-insert-item 'checkbox))
3462 (org-insert-heading)
3463 (save-excursion
3464 (org-back-to-heading)
3465 (if org-noutline-p
3466 (outline-previous-heading)
3467 (outline-previous-visible-heading t))
3468 (looking-at org-todo-line-regexp))
3469 (if (or arg
3470 (not (match-beginning 2))
3471 (equal (match-string 2) org-done-string))
3472 (insert (car org-todo-keywords) " ")
3473 (insert (match-string 2) " "))))
3475 (defun org-promote-subtree ()
3476 "Promote the entire subtree.
3477 See also `org-promote'."
3478 (interactive)
3479 (save-excursion
3480 (org-map-tree 'org-promote)))
3482 (defun org-demote-subtree ()
3483 "Demote the entire subtree. See `org-demote'.
3484 See also `org-promote'."
3485 (interactive)
3486 (save-excursion
3487 (org-map-tree 'org-demote)))
3489 (defun org-do-promote ()
3490 "Promote the current heading higher up the tree.
3491 If the region is active in `transient-mark-mode', promote all headings
3492 in the region."
3493 (interactive)
3494 (save-excursion
3495 (if (org-region-active-p)
3496 (org-map-region 'org-promote (region-beginning) (region-end))
3497 (org-promote)))
3498 (org-fix-position-after-promote))
3500 (defun org-do-demote ()
3501 "Demote the current heading lower down the tree.
3502 If the region is active in `transient-mark-mode', demote all headings
3503 in the region."
3504 (interactive)
3505 (save-excursion
3506 (if (org-region-active-p)
3507 (org-map-region 'org-demote (region-beginning) (region-end))
3508 (org-demote)))
3509 (org-fix-position-after-promote))
3511 (defun org-fix-position-after-promote ()
3512 "Make sure that after pro/demotion cursor position is right."
3513 (and (equal (char-after) ?\ )
3514 (equal (char-before) ?*)
3515 (forward-char 1)))
3517 (defun org-get-legal-level (level change)
3518 "Rectify a level change under the influence of `org-odd-levels-only'
3519 LEVEL is a current level, CHANGE is by how much the level should be
3520 modified. Even if CHANGE is nil, LEVEL may be returned modified because
3521 even level numbers will become the next higher odd number."
3522 (if org-odd-levels-only
3523 (cond ((not change) (1+ (* 2 (/ level 2))))
3524 ((> change 0) (1+ (* 2 (/ (+ level (* 2 change)) 2))))
3525 ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2))))))
3526 (max 1 (+ level change))))
3528 (defun org-promote ()
3529 "Promote the current heading higher up the tree.
3530 If the region is active in `transient-mark-mode', promote all headings
3531 in the region."
3532 (org-back-to-heading t)
3533 (let* ((level (save-match-data (funcall outline-level)))
3534 (up-head (make-string (org-get-legal-level level -1) ?*))
3535 (diff (abs (- level (length up-head)))))
3536 (if (= level 1) (error "Cannot promote to level 0. UNDO to recover"))
3537 (replace-match up-head nil t)
3538 ;; Fixup tag positioning
3539 (and org-auto-align-tags (org-set-tags nil t))
3540 (if org-adapt-indentation
3541 (org-fixup-indentation (if (> diff 1) "^ " "^ ") ""
3542 (if (> diff 1) "^ ? ?\\S-" "^ ?\\S-")))))
3544 (defun org-demote ()
3545 "Demote the current heading lower down the tree.
3546 If the region is active in `transient-mark-mode', demote all headings
3547 in the region."
3548 (org-back-to-heading t)
3549 (let* ((level (save-match-data (funcall outline-level)))
3550 (down-head (make-string (org-get-legal-level level 1) ?*))
3551 (diff (abs (- level (length down-head)))))
3552 (replace-match down-head nil t)
3553 ;; Fixup tag positioning
3554 (and org-auto-align-tags (org-set-tags nil t))
3555 (if org-adapt-indentation
3556 (org-fixup-indentation "^ " (if (> diff 1) " " " ") "^\\S-"))))
3558 (defun org-map-tree (fun)
3559 "Call FUN for every heading underneath the current one."
3560 (org-back-to-heading)
3561 (let ((level (funcall outline-level)))
3562 (save-excursion
3563 (funcall fun)
3564 (while (and (progn
3565 (outline-next-heading)
3566 (> (funcall outline-level) level))
3567 (not (eobp)))
3568 (funcall fun)))))
3570 (defun org-map-region (fun beg end)
3571 "Call FUN for every heading between BEG and END."
3572 (let ((org-ignore-region t))
3573 (save-excursion
3574 (setq end (copy-marker end))
3575 (goto-char beg)
3576 (if (and (re-search-forward (concat "^" outline-regexp) nil t)
3577 (< (point) end))
3578 (funcall fun))
3579 (while (and (progn
3580 (outline-next-heading)
3581 (< (point) end))
3582 (not (eobp)))
3583 (funcall fun)))))
3585 (defun org-fixup-indentation (from to prohibit)
3586 "Change the indentation in the current entry by re-replacing FROM with TO.
3587 However, if the regexp PROHIBIT matches at all, don't do anything.
3588 This is being used to change indentation along with the length of the
3589 heading marker. But if there are any lines which are not indented, nothing
3590 is changed at all."
3591 (save-excursion
3592 (let ((end (save-excursion (outline-next-heading)
3593 (point-marker))))
3594 (unless (save-excursion (re-search-forward prohibit end t))
3595 (while (re-search-forward from end t)
3596 (replace-match to)
3597 (beginning-of-line 2)))
3598 (move-marker end nil))))
3600 ;;; Vertical tree motion, cutting and pasting of subtrees
3602 (defun org-move-subtree-up (&optional arg)
3603 "Move the current subtree up past ARG headlines of the same level."
3604 (interactive "p")
3605 (org-move-subtree-down (- (prefix-numeric-value arg))))
3607 (defun org-move-subtree-down (&optional arg)
3608 "Move the current subtree down past ARG headlines of the same level."
3609 (interactive "p")
3610 (setq arg (prefix-numeric-value arg))
3611 (let ((movfunc (if (> arg 0) 'outline-get-next-sibling
3612 'outline-get-last-sibling))
3613 (ins-point (make-marker))
3614 (cnt (abs arg))
3615 beg end txt folded)
3616 ;; Select the tree
3617 (org-back-to-heading)
3618 (setq beg (point))
3619 (save-match-data
3620 (save-excursion (outline-end-of-heading)
3621 (setq folded (org-invisible-p)))
3622 (outline-end-of-subtree))
3623 (outline-next-heading)
3624 (setq end (point))
3625 ;; Find insertion point, with error handling
3626 (goto-char beg)
3627 (while (> cnt 0)
3628 (or (and (funcall movfunc) (looking-at outline-regexp))
3629 (progn (goto-char beg)
3630 (error "Cannot move past superior level or buffer limit")))
3631 (setq cnt (1- cnt)))
3632 (if (> arg 0)
3633 ;; Moving forward - still need to move over subtree
3634 (progn (outline-end-of-subtree)
3635 (outline-next-heading)
3636 (if (not (or (looking-at (concat "^" outline-regexp))
3637 (bolp)))
3638 (newline))))
3639 (move-marker ins-point (point))
3640 (setq txt (buffer-substring beg end))
3641 (delete-region beg end)
3642 (insert txt)
3643 (goto-char ins-point)
3644 (if folded (hide-subtree))
3645 (move-marker ins-point nil)))
3647 (defvar org-subtree-clip ""
3648 "Clipboard for cut and paste of subtrees.
3649 This is actually only a copy of the kill, because we use the normal kill
3650 ring. We need it to check if the kill was created by `org-copy-subtree'.")
3652 (defvar org-subtree-clip-folded nil
3653 "Was the last copied subtree folded?
3654 This is used to fold the tree back after pasting.")
3656 (defun org-cut-subtree ()
3657 "Cut the current subtree into the clipboard.
3658 This is a short-hand for marking the subtree and then cutting it."
3659 (interactive)
3660 (org-copy-subtree 'cut))
3662 (defun org-copy-subtree (&optional cut)
3663 "Cut the current subtree into the clipboard.
3664 This is a short-hand for marking the subtree and then copying it.
3665 If CUT is non nil, actually cut the subtree."
3666 (interactive)
3667 (let (beg end folded)
3668 (org-back-to-heading)
3669 (setq beg (point))
3670 (save-match-data
3671 (save-excursion (outline-end-of-heading)
3672 (setq folded (org-invisible-p)))
3673 (outline-end-of-subtree))
3674 (if (equal (char-after) ?\n) (forward-char 1))
3675 (setq end (point))
3676 (goto-char beg)
3677 (when (> end beg)
3678 (setq org-subtree-clip-folded folded)
3679 (if cut (kill-region beg end) (copy-region-as-kill beg end))
3680 (setq org-subtree-clip (current-kill 0))
3681 (message "%s: Subtree with %d characters"
3682 (if cut "Cut" "Copied")
3683 (length org-subtree-clip)))))
3685 (defun org-paste-subtree (&optional level tree)
3686 "Paste the clipboard as a subtree, with modification of headline level.
3687 The entire subtree is promoted or demoted in order to match a new headline
3688 level. By default, the new level is derived from the visible headings
3689 before and after the insertion point, and taken to be the inferior headline
3690 level of the two. So if the previous visible heading is level 3 and the
3691 next is level 4 (or vice versa), level 4 will be used for insertion.
3692 This makes sure that the subtree remains an independent subtree and does
3693 not swallow low level entries.
3695 You can also force a different level, either by using a numeric prefix
3696 argument, or by inserting the heading marker by hand. For example, if the
3697 cursor is after \"*****\", then the tree will be shifted to level 5.
3699 If you want to insert the tree as is, just use \\[yank].
3701 If optional TREE is given, use this text instead of the kill ring."
3702 (interactive "P")
3703 (unless (org-kill-is-subtree-p tree)
3704 (error
3705 (substitute-command-keys
3706 "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway")))
3707 (let* ((txt (or tree (and kill-ring (current-kill 0))))
3708 (^re (concat "^\\(" outline-regexp "\\)"))
3709 (re (concat "\\(" outline-regexp "\\)"))
3710 (^re_ (concat "\\(" outline-regexp "\\)[ \t]*"))
3712 (old-level (if (string-match ^re txt)
3713 (- (match-end 0) (match-beginning 0))
3714 -1))
3715 (force-level (cond (level (prefix-numeric-value level))
3716 ((string-match
3717 ^re_ (buffer-substring (point-at-bol) (point)))
3718 (- (match-end 0) (match-beginning 0)))
3719 (t nil)))
3720 (previous-level (save-excursion
3721 (condition-case nil
3722 (progn
3723 (outline-previous-visible-heading 1)
3724 (if (looking-at re)
3725 (- (match-end 0) (match-beginning 0))
3727 (error 1))))
3728 (next-level (save-excursion
3729 (condition-case nil
3730 (progn
3731 (outline-next-visible-heading 1)
3732 (if (looking-at re)
3733 (- (match-end 0) (match-beginning 0))
3735 (error 1))))
3736 (new-level (or force-level (max previous-level next-level)))
3737 (shift (if (or (= old-level -1)
3738 (= new-level -1)
3739 (= old-level new-level))
3741 (- new-level old-level)))
3742 (shift1 shift)
3743 (delta (if (> shift 0) -1 1))
3744 (func (if (> shift 0) 'org-demote 'org-promote))
3745 (org-odd-levels-only nil)
3746 beg end)
3747 ;; Remove the forces level indicator
3748 (if force-level
3749 (delete-region (point-at-bol) (point)))
3750 ;; Make sure we start at the beginning of an empty line
3751 (if (not (bolp)) (insert "\n"))
3752 (if (not (looking-at "[ \t]*$"))
3753 (progn (insert "\n") (backward-char 1)))
3754 ;; Paste
3755 (setq beg (point))
3756 (insert txt)
3757 (setq end (point))
3758 (goto-char beg)
3759 ;; Shift if necessary
3760 (if (= shift 0)
3761 (message "Pasted at level %d, without shift" new-level)
3762 (save-restriction
3763 (narrow-to-region beg end)
3764 (while (not (= shift 0))
3765 (org-map-region func (point-min) (point-max))
3766 (setq shift (+ delta shift)))
3767 (goto-char (point-min))
3768 (message "Pasted at level %d, with shift by %d levels"
3769 new-level shift1)))
3770 (if (and kill-ring
3771 (eq org-subtree-clip (current-kill 0))
3772 org-subtree-clip-folded)
3773 ;; The tree was folded before it was killed/copied
3774 (hide-subtree))))
3776 (defun org-kill-is-subtree-p (&optional txt)
3777 "Check if the current kill is an outline subtree, or a set of trees.
3778 Returns nil if kill does not start with a headline, or if the first
3779 headline level is not the largest headline level in the tree.
3780 So this will actually accept several entries of equal levels as well,
3781 which is OK for `org-paste-subtree'.
3782 If optional TXT is given, check this string instead of the current kill."
3783 (let* ((kill (or txt (and kill-ring (current-kill 0)) ""))
3784 (start-level (and kill
3785 (string-match (concat "\\`" outline-regexp) kill)
3786 (- (match-end 0) (match-beginning 0))))
3787 (re (concat "^" outline-regexp))
3788 (start 1))
3789 (if (not start-level)
3790 nil ;; does not even start with a heading
3791 (catch 'exit
3792 (while (setq start (string-match re kill (1+ start)))
3793 (if (< (- (match-end 0) (match-beginning 0)) start-level)
3794 (throw 'exit nil)))
3795 t))))
3797 ;;; Plain list items
3799 (defun org-at-item-p ()
3800 "Is point in a line starting a hand-formatted item?"
3801 (let ((llt org-plain-list-ordered-item-terminator))
3802 (save-excursion
3803 (goto-char (point-at-bol))
3804 (looking-at
3805 (cond
3806 ((eq llt t) "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
3807 ((= llt ?.) "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
3808 ((= llt ?\)) "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
3809 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))))))
3811 (defun org-at-item-checkbox-p ()
3812 "Is point at a line starting a plain-list item with a checklet?"
3813 (and (org-at-item-p)
3814 (save-excursion
3815 (goto-char (match-end 0))
3816 (skip-chars-forward " \t")
3817 (looking-at "\\[[ X]\\]"))))
3819 (defun org-toggle-checkbox ()
3820 "Toggle the checkbox in the current line."
3821 (interactive)
3822 (save-excursion
3823 (if (org-at-item-checkbox-p)
3824 (replace-match (if (equal (match-string 0) "[ ]") "[X]" "[ ]") t t))))
3826 (defun org-get-indentation ()
3827 "Get the indentation of the current line, interpreting tabs."
3828 (save-excursion
3829 (beginning-of-line 1)
3830 (skip-chars-forward " \t")
3831 (current-column)))
3833 (defun org-beginning-of-item ()
3834 "Go to the beginning of the current hand-formatted item.
3835 If the cursor is not in an item, throw an error."
3836 (interactive)
3837 (let ((pos (point))
3838 (limit (save-excursion (org-back-to-heading)
3839 (beginning-of-line 2) (point)))
3840 ind ind1)
3841 (if (org-at-item-p)
3842 (beginning-of-line 1)
3843 (beginning-of-line 1)
3844 (skip-chars-forward " \t")
3845 (setq ind (current-column))
3846 (if (catch 'exit
3847 (while t
3848 (beginning-of-line 0)
3849 (if (< (point) limit) (throw 'exit nil))
3850 (unless (looking-at " \t]*$")
3851 (skip-chars-forward " \t")
3852 (setq ind1 (current-column))
3853 (if (< ind1 ind)
3854 (throw 'exit (org-at-item-p))))))
3856 (goto-char pos)
3857 (error "Not in an item")))))
3859 (defun org-end-of-item ()
3860 "Go to the end of the current hand-formatted item.
3861 If the cursor is not in an item, throw an error."
3862 (interactive)
3863 (let ((pos (point))
3864 (limit (save-excursion (outline-next-heading) (point)))
3865 (ind (save-excursion
3866 (org-beginning-of-item)
3867 (skip-chars-forward " \t")
3868 (current-column)))
3869 ind1)
3870 (if (catch 'exit
3871 (while t
3872 (beginning-of-line 2)
3873 (if (>= (point) limit) (throw 'exit t))
3874 (unless (looking-at "[ \t]*$")
3875 (skip-chars-forward " \t")
3876 (setq ind1 (current-column))
3877 (if (<= ind1 ind) (throw 'exit t)))))
3878 (beginning-of-line 1)
3879 (goto-char pos)
3880 (error "Not in an item"))))
3882 (defun org-next-item ()
3883 "Move to the beginning of the next item in the current plain list.
3884 Error if not at a plain list, or if this is the last item in the list."
3885 (interactive)
3886 (let (beg end ind ind1 (pos (point)) txt)
3887 (org-beginning-of-item)
3888 (setq beg (point))
3889 (setq ind (org-get-indentation))
3890 (org-end-of-item)
3891 (setq end (point))
3892 (setq ind1 (org-get-indentation))
3893 (unless (and (org-at-item-p) (= ind ind1))
3894 (goto-char pos)
3895 (error "On last item"))))
3897 (defun org-previous-item ()
3898 "Move to the beginning of the previous item in the current plain list.
3899 Error if not at a plain list, or if this is the last item in the list."
3900 (interactive)
3901 (let (beg end ind ind1 (pos (point)) txt)
3902 (org-beginning-of-item)
3903 (setq beg (point))
3904 (setq ind (org-get-indentation))
3905 (goto-char beg)
3906 (catch 'exit
3907 (while t
3908 (beginning-of-line 0)
3909 (if (looking-at "[ \t]*$")
3911 (if (<= (setq ind1 (org-get-indentation)) ind)
3912 (throw 'exit t)))))
3913 (condition-case nil
3914 (org-beginning-of-item)
3915 (error (goto-char pos)
3916 (error "On first item")))))
3918 (defun org-move-item-down ()
3919 "Move the plain list item at point down, i.e. swap with following item.
3920 Subitems (items with larger indentation) are considered part of the item,
3921 so this really moves item trees."
3922 (interactive)
3923 (let (beg end ind ind1 (pos (point)) txt)
3924 (org-beginning-of-item)
3925 (setq beg (point))
3926 (setq ind (org-get-indentation))
3927 (org-end-of-item)
3928 (setq end (point))
3929 (setq ind1 (org-get-indentation))
3930 (if (and (org-at-item-p) (= ind ind1))
3931 (progn
3932 (org-end-of-item)
3933 (setq txt (buffer-substring beg end))
3934 (save-excursion
3935 (delete-region beg end))
3936 (setq pos (point))
3937 (insert txt)
3938 (goto-char pos)
3939 (org-maybe-renumber-ordered-list))
3940 (goto-char pos)
3941 (error "Cannot move this item further down"))))
3943 (defun org-move-item-up (arg)
3944 "Move the plain list item at point up, i.e. swap with previous item.
3945 Subitems (items with larger indentation) are considered part of the item,
3946 so this really moves item trees."
3947 (interactive "p")
3948 (let (beg end ind ind1 (pos (point)) txt)
3949 (org-beginning-of-item)
3950 (setq beg (point))
3951 (setq ind (org-get-indentation))
3952 (org-end-of-item)
3953 (setq end (point))
3954 (goto-char beg)
3955 (catch 'exit
3956 (while t
3957 (beginning-of-line 0)
3958 (if (looking-at "[ \t]*$")
3960 (if (<= (setq ind1 (org-get-indentation)) ind)
3961 (throw 'exit t)))))
3962 (condition-case nil
3963 (org-beginning-of-item)
3964 (error (goto-char beg)
3965 (error "Cannot move this item further up")))
3966 (setq ind1 (org-get-indentation))
3967 (if (and (org-at-item-p) (= ind ind1))
3968 (progn
3969 (setq txt (buffer-substring beg end))
3970 (save-excursion
3971 (delete-region beg end))
3972 (setq pos (point))
3973 (insert txt)
3974 (goto-char pos)
3975 (org-maybe-renumber-ordered-list))
3976 (goto-char pos)
3977 (error "Cannot move this item further up"))))
3979 (defun org-maybe-renumber-ordered-list ()
3980 "Renumber the ordered list at point if setup allows it.
3981 This tests the user option `org-auto-renumber-ordered-lists' before
3982 doing the renumbering."
3983 (and org-auto-renumber-ordered-lists
3984 (org-at-item-p)
3985 (match-beginning 3)
3986 (org-renumber-ordered-list 1)))
3988 (defun org-get-string-indentation (s)
3989 "What indentation has S due to SPACE and TAB at the beginning of the string?"
3990 (let ((n -1) (i 0) (w tab-width) c)
3991 (catch 'exit
3992 (while (< (setq n (1+ n)) (length s))
3993 (setq c (aref s n))
3994 (cond ((= c ?\ ) (setq i (1+ i)))
3995 ((= c ?\t) (setq i (* (/ (+ w i) w) w)))
3996 (t (throw 'exit t)))))
3999 (defun org-renumber-ordered-list (arg)
4000 "Renumber an ordered plain list.
4001 Cursor needs to be in the first line of an item, the line that starts
4002 with something like \"1.\" or \"2)\"."
4003 (interactive "p")
4004 (unless (and (org-at-item-p)
4005 (match-beginning 3))
4006 (error "This is not an ordered list"))
4007 (let ((line (org-current-line))
4008 (col (current-column))
4009 (ind (org-get-string-indentation
4010 (buffer-substring (point-at-bol) (match-beginning 3))))
4011 ;; (term (substring (match-string 3) -1))
4012 ind1 (n (1- arg)))
4013 ;; find where this list begins
4014 (catch 'exit
4015 (while t
4016 (catch 'next
4017 (beginning-of-line 0)
4018 (if (looking-at "[ \t]*$") (throw 'next t))
4019 (skip-chars-forward " \t") (setq ind1 (current-column))
4020 (if (or (< ind1 ind)
4021 (and (= ind1 ind)
4022 (not (org-at-item-p))))
4023 (throw 'exit t)))))
4024 ;; Walk forward and replace these numbers
4025 (catch 'exit
4026 (while t
4027 (catch 'next
4028 (beginning-of-line 2)
4029 (if (eobp) (throw 'exit nil))
4030 (if (looking-at "[ \t]*$") (throw 'next nil))
4031 (skip-chars-forward " \t") (setq ind1 (current-column))
4032 (if (> ind1 ind) (throw 'next t))
4033 (if (< ind1 ind) (throw 'exit t))
4034 (if (not (org-at-item-p)) (throw 'exit nil))
4035 (if (not (match-beginning 3))
4036 (error "unordered bullet in ordered list. Press \\[undo] to recover"))
4037 (delete-region (match-beginning 3) (1- (match-end 3)))
4038 (goto-char (match-beginning 3))
4039 (insert (format "%d" (setq n (1+ n)))))))
4040 (goto-line line)
4041 (move-to-column col)))
4043 (defvar org-last-indent-begin-marker (make-marker))
4044 (defvar org-last-indent-end-marker (make-marker))
4046 (defun org-outdent-item (arg)
4047 "Outdent a local list item."
4048 (interactive "p")
4049 (org-indent-item (- arg)))
4051 (defun org-indent-item (arg)
4052 "Indent a local list item."
4053 (interactive "p")
4054 (unless (org-at-item-p)
4055 (error "Not on an item"))
4056 (save-excursion
4057 (let (beg end ind ind1)
4058 (if (memq last-command '(org-shiftmetaright org-shiftmetaleft))
4059 (setq beg org-last-indent-begin-marker
4060 end org-last-indent-end-marker)
4061 (org-beginning-of-item)
4062 (setq beg (move-marker org-last-indent-begin-marker (point)))
4063 (org-end-of-item)
4064 (setq end (move-marker org-last-indent-end-marker (point))))
4065 (goto-char beg)
4066 (skip-chars-forward " \t") (setq ind (current-column))
4067 (if (< (+ arg ind) 0) (error "Cannot outdent beyond margin"))
4068 (while (< (point) end)
4069 (beginning-of-line 1)
4070 (skip-chars-forward " \t") (setq ind1 (current-column))
4071 (delete-region (point-at-bol) (point))
4072 (indent-to-column (+ ind1 arg))
4073 (beginning-of-line 2)))))
4075 ;;; Archiving
4077 (defun org-archive-subtree ()
4078 "Move the current subtree to the archive.
4079 The archive can be a certain top-level heading in the current file, or in
4080 a different file. The tree will be moved to that location, the subtree
4081 heading be marked DONE, and the current time will be added."
4082 (interactive)
4083 ;; Save all relevant TODO keyword-relatex variables
4084 (let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler
4085 (tr-org-todo-keywords org-todo-keywords)
4086 (tr-org-todo-interpretation org-todo-interpretation)
4087 (tr-org-done-string org-done-string)
4088 (tr-org-todo-regexp org-todo-regexp)
4089 (tr-org-todo-line-regexp org-todo-line-regexp)
4090 (this-buffer (current-buffer))
4091 file heading buffer level newfile-p)
4092 (if (string-match "\\(.*\\)::\\(.*\\)" org-archive-location)
4093 (progn
4094 (setq file (format (match-string 1 org-archive-location)
4095 (file-name-nondirectory buffer-file-name))
4096 heading (match-string 2 org-archive-location)))
4097 (error "Invalid `org-archive-location'"))
4098 (if (> (length file) 0)
4099 (setq newfile-p (not (file-exists-p file))
4100 buffer (find-file-noselect file))
4101 (setq buffer (current-buffer)))
4102 (unless buffer
4103 (error "Cannot access file \"%s\"" file))
4104 (if (and (> (length heading) 0)
4105 (string-match "^\\*+" heading))
4106 (setq level (match-end 0))
4107 (setq heading nil level 0))
4108 (save-excursion
4109 ;; We first only copy, in case something goes wrong
4110 ;; we need to protect this-command, to avoid kill-region sets it,
4111 ;; which would lead to duplication of subtrees
4112 (let (this-command) (org-copy-subtree))
4113 (set-buffer buffer)
4114 ;; Enforce org-mode for the archive buffer
4115 (if (not (eq major-mode 'org-mode))
4116 ;; Force the mode for future visits.
4117 (let ((org-insert-mode-line-in-empty-file t))
4118 (call-interactively 'org-mode)))
4119 (when newfile-p
4120 (goto-char (point-max))
4121 (insert (format "\nArchived entries from file %s\n\n"
4122 (buffer-file-name this-buffer))))
4123 ;; Force the TODO keywords of the original buffer
4124 (let ((org-todo-line-regexp tr-org-todo-line-regexp)
4125 (org-todo-keywords tr-org-todo-keywords)
4126 (org-todo-interpretation tr-org-todo-interpretation)
4127 (org-done-string tr-org-done-string)
4128 (org-todo-regexp tr-org-todo-regexp)
4129 (org-todo-line-regexp tr-org-todo-line-regexp))
4130 (goto-char (point-min))
4131 (if heading
4132 (progn
4133 (if (re-search-forward
4134 (concat "\\(^\\|\r\\)"
4135 (regexp-quote heading) "[ \t]*\\($\\|\r\\)")
4136 nil t)
4137 (goto-char (match-end 0))
4138 ;; Heading not found, just insert it at the end
4139 (goto-char (point-max))
4140 (or (bolp) (insert "\n"))
4141 (insert "\n" heading "\n")
4142 (end-of-line 0))
4143 ;; Make the heading visible, and the following as well
4144 (let ((org-show-following-heading t)) (org-show-hierarchy-above))
4145 (if (re-search-forward
4146 (concat "^" (regexp-quote (make-string level ?*)) "[ \t]")
4147 nil t)
4148 (progn (goto-char (match-beginning 0)) (insert "\n")
4149 (beginning-of-line 0))
4150 (goto-char (point-max)) (insert "\n")))
4151 (goto-char (point-max)) (insert "\n"))
4152 ;; Paste
4153 (org-paste-subtree (1+ level))
4154 ;; Mark the entry as done, i.e. set to last work in org-todo-keywords
4155 (if org-archive-mark-done
4156 (org-todo (length org-todo-keywords)))
4157 ;; Move cursor to right after the TODO keyword
4158 (when org-archive-stamp-time
4159 (beginning-of-line 1)
4160 (looking-at org-todo-line-regexp)
4161 (goto-char (or (match-end 2) (match-beginning 3)))
4162 (insert "(" (format-time-string (cdr org-time-stamp-formats)
4163 (org-current-time))
4164 ")"))
4165 ;; Save the buffer, if it is not the same buffer.
4166 (if (not (eq this-buffer buffer)) (save-buffer))))
4167 ;; Here we are back in the original buffer. Everything seems to have
4168 ;; worked. So now cut the tree and finish up.
4169 (let (this-command) (org-cut-subtree))
4170 (if (and (not (eobp)) (looking-at "[ \t]*$")) (kill-line))
4171 (message "Subtree archived %s"
4172 (if (eq this-buffer buffer)
4173 (concat "under heading: " heading)
4174 (concat "in file: " (abbreviate-file-name file))))))
4176 ;;; Completion
4178 (defun org-complete (&optional arg)
4179 "Perform completion on word at point.
4180 At the beginning of a headline, this completes TODO keywords as given in
4181 `org-todo-keywords'.
4182 If the current word is preceded by a backslash, completes the TeX symbols
4183 that are supported for HTML support.
4184 If the current word is preceded by \"#+\", completes special words for
4185 setting file options.
4186 At all other locations, this simply calls `ispell-complete-word'."
4187 (interactive "P")
4188 (catch 'exit
4189 (let* ((end (point))
4190 (beg1 (save-excursion
4191 (if (equal (char-before (point)) ?\ ) (backward-char 1))
4192 (skip-chars-backward "a-zA-Z_@0-9")
4193 (point)))
4194 (beg (save-excursion
4195 (if (equal (char-before (point)) ?\ ) (backward-char 1))
4196 (skip-chars-backward "a-zA-Z0-9_:$")
4197 (point)))
4198 (camel (equal (char-before beg) ?*))
4199 (tag (equal (char-before beg1) ?:))
4200 (texp (equal (char-before beg) ?\\))
4201 (opt (equal (buffer-substring (max (point-at-bol) (- beg 2))
4202 beg)
4203 "#+"))
4204 (completion-ignore-case opt)
4205 (type nil)
4206 (tbl nil)
4207 (table (cond
4208 (opt
4209 (setq type :opt)
4210 (mapcar (lambda (x)
4211 (string-match "^#\\+\\(\\([A-Z_]+:?\\).*\\)" x)
4212 (cons (match-string 2 x) (match-string 1 x)))
4213 (org-split-string (org-get-current-options) "\n")))
4214 (texp
4215 (setq type :tex)
4216 org-html-entities)
4217 ((string-match "\\`\\*+[ \t]*\\'"
4218 (buffer-substring (point-at-bol) beg))
4219 (setq type :todo)
4220 (mapcar 'list org-todo-keywords))
4221 (camel
4222 (setq type :camel)
4223 (save-excursion
4224 (goto-char (point-min))
4225 (while (re-search-forward org-todo-line-regexp nil t)
4226 (push (list
4227 (if org-file-link-context-use-camel-case
4228 (org-make-org-heading-camel (match-string 3) t)
4229 (org-make-org-heading-search-string
4230 (match-string 3) t)))
4231 tbl)))
4232 tbl)
4233 (tag (setq type :tag beg beg1)
4234 (or org-tag-alist (org-get-buffer-tags)))
4235 (t (progn (ispell-complete-word arg) (throw 'exit nil)))))
4236 (pattern (buffer-substring-no-properties beg end))
4237 (completion (try-completion pattern table)))
4238 (cond ((eq completion t)
4239 (if (equal type :opt)
4240 (insert (substring (cdr (assoc (upcase pattern) table))
4241 (length pattern)))))
4242 ((null completion)
4243 (message "Can't find completion for \"%s\"" pattern)
4244 (ding))
4245 ((not (string= pattern completion))
4246 (delete-region beg end)
4247 (if (string-match " +$" completion)
4248 (setq completion (replace-match "" t t completion)))
4249 (insert completion)
4250 (if (get-buffer-window "*Completions*")
4251 (delete-window (get-buffer-window "*Completions*")))
4252 (if (assoc completion table)
4253 (if (eq type :todo) (insert " ")
4254 (if (eq type :tag) (insert ":"))))
4255 (if (and (equal type :opt) (assoc completion table))
4256 (message "%s" (substitute-command-keys
4257 "Press \\[org-complete] again to insert example settings"))))
4259 (message "Making completion list...")
4260 (let ((list (sort (all-completions pattern table) 'string<)))
4261 (with-output-to-temp-buffer "*Completions*"
4262 (condition-case nil
4263 ;; Protection needed for XEmacs and emacs 21
4264 (display-completion-list list pattern)
4265 (error (display-completion-list list)))))
4266 (message "Making completion list...%s" "done"))))))
4268 ;;; Comments, TODO and DEADLINE
4270 (defun org-toggle-comment ()
4271 "Change the COMMENT state of an entry."
4272 (interactive)
4273 (save-excursion
4274 (org-back-to-heading)
4275 (if (looking-at (concat outline-regexp
4276 "\\( +\\<" org-comment-string "\\>\\)"))
4277 (replace-match "" t t nil 1)
4278 (if (looking-at outline-regexp)
4279 (progn
4280 (goto-char (match-end 0))
4281 (insert " " org-comment-string))))))
4283 (defvar org-last-todo-state-is-todo nil
4284 "This is non-nil when the last TODO state change led to a TODO state.
4285 If the last change removed the TODO tag or switched to DONE, then
4286 this is nil.")
4288 (defun org-todo (&optional arg)
4289 "Change the TODO state of an item.
4290 The state of an item is given by a keyword at the start of the heading,
4291 like
4292 *** TODO Write paper
4293 *** DONE Call mom
4295 The different keywords are specified in the variable `org-todo-keywords'.
4296 By default the available states are \"TODO\" and \"DONE\".
4297 So for this example: when the item starts with TODO, it is changed to DONE.
4298 When it starts with DONE, the DONE is removed. And when neither TODO nor
4299 DONE are present, add TODO at the beginning of the heading.
4301 With prefix arg, use completion to determine the new state. With numeric
4302 prefix arg, switch to that state."
4303 (interactive "P")
4304 (save-excursion
4305 (org-back-to-heading)
4306 (if (looking-at outline-regexp) (goto-char (match-end 0)))
4307 (or (looking-at (concat " +" org-todo-regexp " *"))
4308 (looking-at " *"))
4309 (let* ((this (match-string 1))
4310 (completion-ignore-case t)
4311 (member (member this org-todo-keywords))
4312 (tail (cdr member))
4313 (state (cond
4314 ((equal arg '(4))
4315 ;; Read a state with completion
4316 (completing-read "State: " (mapcar (lambda(x) (list x))
4317 org-todo-keywords)
4318 nil t))
4319 ((eq arg 'right)
4320 (if this
4321 (if tail (car tail) nil)
4322 (car org-todo-keywords)))
4323 ((eq arg 'left)
4324 (if (equal member org-todo-keywords)
4326 (if this
4327 (nth (- (length org-todo-keywords) (length tail) 2)
4328 org-todo-keywords)
4329 org-done-string)))
4330 (arg
4331 ;; user requests a specific state
4332 (nth (1- (prefix-numeric-value arg))
4333 org-todo-keywords))
4334 ((null member) (car org-todo-keywords))
4335 ((null tail) nil) ;; -> first entry
4336 ((eq org-todo-interpretation 'sequence)
4337 (car tail))
4338 ((memq org-todo-interpretation '(type priority))
4339 (if (eq this-command last-command)
4340 (car tail)
4341 (if (> (length tail) 0) org-done-string nil)))
4342 (t nil)))
4343 (next (if state (concat " " state " ") " ")))
4344 (replace-match next t t)
4345 (setq org-last-todo-state-is-todo
4346 (not (equal state org-done-string)))
4347 (when org-log-done
4348 (if (equal state org-done-string)
4349 (org-add-planning-info 'closed (current-time) 'scheduled)
4350 (if (not this)
4351 (org-add-planning-info nil nil 'closed))))
4352 ;; Fixup tag positioning
4353 (and org-auto-align-tags (org-set-tags nil t))
4354 (run-hooks 'org-after-todo-state-change-hook)))
4355 ;; Fixup cursor location if close to the keyword
4356 (if (and (outline-on-heading-p)
4357 (not (bolp))
4358 (save-excursion (beginning-of-line 1)
4359 (looking-at org-todo-line-regexp))
4360 (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
4361 (progn
4362 (goto-char (or (match-end 2) (match-end 1)))
4363 (just-one-space))))
4365 (defun org-log-done (&optional undone)
4366 "Add a time stamp logging that a TODO entry has been closed.
4367 When UNDONE is non-nil, remove such a time stamp again."
4368 (interactive)
4369 (let (beg end col)
4370 (save-excursion
4371 (org-back-to-heading t)
4372 (setq beg (point))
4373 (looking-at (concat outline-regexp " *"))
4374 (goto-char (match-end 0))
4375 (setq col (current-column))
4376 (outline-next-heading)
4377 (setq end (point))
4378 (goto-char beg)
4379 (when (re-search-forward (concat
4380 "[\r\n]\\([ \t]*"
4381 (regexp-quote org-closed-string)
4382 " *\\[.*?\\][^\n\r]*[\n\r]?\\)") end t)
4383 (delete-region (match-beginning 1) (match-end 1)))
4384 (unless undone
4385 (org-back-to-heading t)
4386 (skip-chars-forward "^\n\r")
4387 (goto-char (min (1+ (point)) (point-max)))
4388 (when (not (member (char-before) '(?\r ?\n)))
4389 (insert "\n"))
4390 (indent-to col)
4391 (insert org-closed-string " "
4392 (format-time-string
4393 (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")
4394 (org-current-time))
4395 "\n")))))
4397 (defun org-show-todo-tree (arg)
4398 "Make a compact tree which shows all headlines marked with TODO.
4399 The tree will show the lines where the regexp matches, and all higher
4400 headlines above the match.
4401 With \\[universal-argument] prefix, also show the DONE entries.
4402 With a numeric prefix N, construct a sparse tree for the Nth element
4403 of `org-todo-keywords'."
4404 (interactive "P")
4405 (let ((case-fold-search nil)
4406 (kwd-re
4407 (cond ((null arg) org-not-done-regexp)
4408 ((equal arg '(4)) org-todo-regexp)
4409 ((<= (prefix-numeric-value arg) (length org-todo-keywords))
4410 (regexp-quote (nth (1- (prefix-numeric-value arg))
4411 org-todo-keywords)))
4412 (t (error "Invalid prefix argument: %s" arg)))))
4413 (message "%d TODO entries found"
4414 (org-occur (concat "^" outline-regexp " +" kwd-re )))))
4416 (defun org-deadline ()
4417 "Insert the DEADLINE: string to make a deadline.
4418 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
4419 to modify it to the correct date."
4420 (interactive)
4421 (org-add-planning-info 'deadline nil 'closed))
4423 (defun org-schedule ()
4424 "Insert the SCHEDULED: string to schedule a TODO item.
4425 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
4426 to modify it to the correct date."
4427 (interactive)
4428 (org-add-planning-info 'scheduled nil 'closed))
4430 (defun org-add-planning-info (what &optional time &rest remove)
4431 "Insert new timestamp with keyword in the line directly after the headline.
4432 WHAT indicates what kind of time stamp to add. TIME indicated the time to use.
4433 If non is given, the user is prompted for a date.
4434 REMOVE indicates what kind of entries to remove. An old WHAT entry will also
4435 be removed."
4436 (interactive)
4437 (when what (setq time (or time (org-read-date nil 'to-time))))
4438 (when (and org-insert-labeled-timestamps-at-point
4439 (member what '(scheduled deadline)))
4440 (insert
4441 (if (eq what 'scheduled) org-scheduled-string org-deadline-string)
4443 (format-time-string (car org-time-stamp-formats) time))
4444 (setq what nil))
4445 (save-excursion
4446 (let (beg end col list elt (buffer-invisibility-spec nil) ts)
4447 (org-back-to-heading t)
4448 (setq beg (point))
4449 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"))
4450 (goto-char (match-end 1))
4451 (setq col (current-column))
4452 (goto-char (1+ (match-end 0)))
4453 (if (and (not (looking-at outline-regexp))
4454 (looking-at (concat "[^\r\n]*?" org-keyword-time-regexp
4455 "[^\r\n]*")))
4456 (narrow-to-region (match-beginning 0) (match-end 0))
4457 (insert "\n")
4458 (backward-char 1)
4459 (narrow-to-region (point) (point))
4460 (indent-to-column col))
4461 ;; Check if we have to remove something.
4462 (setq list (cons what remove))
4463 (while list
4464 (setq elt (pop list))
4465 (goto-char (point-min))
4466 (when (or (and (eq elt 'scheduled)
4467 (re-search-forward org-scheduled-time-regexp nil t))
4468 (and (eq elt 'deadline)
4469 (re-search-forward org-deadline-time-regexp nil t))
4470 (and (eq elt 'closed)
4471 (re-search-forward org-closed-time-regexp nil t)))
4472 (replace-match "")
4473 (if (looking-at " +") (replace-match ""))))
4474 (goto-char (point-max))
4475 (when what
4476 (insert
4477 (if (not (equal (char-before) ?\ )) " " "")
4478 (cond ((eq what 'scheduled) org-scheduled-string)
4479 ((eq what 'deadline) org-deadline-string)
4480 ((eq what 'closed) org-closed-string))
4481 " ")
4482 (insert
4483 (setq ts
4484 (format-time-string
4485 (if (eq what 'closed)
4486 (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")
4487 (car org-time-stamp-formats))
4488 time))))
4489 (goto-char (point-min))
4490 (widen)
4491 (if (looking-at "[ \t]+\r?\n")
4492 (replace-match ""))
4493 ts)))
4495 (defun org-occur (regexp &optional callback)
4496 "Make a compact tree which shows all matches of REGEXP.
4497 The tree will show the lines where the regexp matches, and all higher
4498 headlines above the match. It will also show the heading after the match,
4499 to make sure editing the matching entry is easy.
4500 If CALLBACK is non-nil, it is a function which is called to confirm
4501 that the match should indeed be shown."
4502 (interactive "sRegexp: ")
4503 (org-remove-occur-highlights nil nil t)
4504 (setq regexp (org-check-occur-regexp regexp))
4505 (let ((cnt 0))
4506 (save-excursion
4507 (goto-char (point-min))
4508 (org-overview)
4509 (while (re-search-forward regexp nil t)
4510 (when (or (not callback)
4511 (save-match-data (funcall callback)))
4512 (setq cnt (1+ cnt))
4513 (org-highlight-new-match (match-beginning 0) (match-end 0))
4514 (org-show-hierarchy-above))))
4515 (org-add-hook 'before-change-functions 'org-remove-occur-highlights
4516 nil 'local)
4517 (run-hooks 'org-occur-hook)
4518 (if (interactive-p)
4519 (message "%d match(es) for regexp %s" cnt regexp))
4520 cnt))
4522 (defun org-show-hierarchy-above ()
4523 "Make sure point and the headings hierarchy above is visible."
4524 (catch 'exit
4525 (if (org-on-heading-p t)
4526 (org-flag-heading nil) ; only show the heading
4527 (and (or (org-invisible-p) (org-invisible-p2))
4528 (org-show-hidden-entry))) ; show entire entry
4529 (save-excursion
4530 (and org-show-following-heading
4531 (outline-next-heading)
4532 (org-flag-heading nil))) ; show the next heading
4533 (when org-show-hierarchy-above
4534 (save-excursion ; show all higher headings
4535 (while (and (condition-case nil
4536 (progn (org-up-heading-all 1) t)
4537 (error nil))
4538 (not (bobp)))
4539 (org-flag-heading nil))))))
4541 ;; Overlay compatibility functions
4542 (defun org-make-overlay (beg end &optional buffer)
4543 (if (featurep 'xemacs)
4544 (make-extent beg end buffer)
4545 (make-overlay beg end buffer)))
4546 (defun org-delete-overlay (ovl)
4547 (if (featurep 'xemacs) (delete-extent ovl) (delete-overlay ovl)))
4548 (defun org-detatch-overlay (ovl)
4549 (if (featurep 'xemacs) (detach-extent ovl) (delete-overlay ovl)))
4550 (defun org-move-overlay (ovl beg end &optional buffer)
4551 (if (featurep 'xemacs)
4552 (set-extent-endpoints ovl beg end buffer)
4553 (move-overlay ovl beg end buffer)))
4554 (defun org-overlay-put (ovl prop value)
4555 (if (featurep 'xemacs)
4556 (set-extent-property ovl prop value)
4557 (overlay-put ovl prop value)))
4559 (defvar org-occur-highlights nil)
4560 (defun org-highlight-new-match (beg end)
4561 "Highlight from BEG to END and mark the highlight is an occur headline."
4562 (let ((ov (org-make-overlay beg end)))
4563 (org-overlay-put ov 'face 'secondary-selection)
4564 (push ov org-occur-highlights)))
4566 (defun org-remove-occur-highlights (&optional beg end noremove)
4567 "Remove the occur highlights from the buffer.
4568 BEG and END are ignored. If NOREMOVE is nil, remove this function
4569 from the `before-change-functions' in the current buffer."
4570 (interactive)
4571 (mapc 'org-delete-overlay org-occur-highlights)
4572 (setq org-occur-highlights nil)
4573 (unless noremove
4574 (remove-hook 'before-change-functions
4575 'org-remove-occur-highlights 'local)))
4577 ;;; Priorities
4579 (defvar org-priority-regexp ".*?\\(\\[#\\([A-Z]\\)\\] ?\\)"
4580 "Regular expression matching the priority indicator.")
4582 (defvar org-remove-priority-next-time nil)
4584 (defun org-priority-up ()
4585 "Increase the priority of the current item."
4586 (interactive)
4587 (org-priority 'up))
4589 (defun org-priority-down ()
4590 "Decrease the priority of the current item."
4591 (interactive)
4592 (org-priority 'down))
4594 (defun org-priority (&optional action)
4595 "Change the priority of an item by ARG.
4596 ACTION can be set, up, or down."
4597 (interactive)
4598 (setq action (or action 'set))
4599 (let (current new news have remove)
4600 (save-excursion
4601 (org-back-to-heading)
4602 (if (looking-at org-priority-regexp)
4603 (setq current (string-to-char (match-string 2))
4604 have t)
4605 (setq current org-default-priority))
4606 (cond
4607 ((eq action 'set)
4608 (message "Priority A-%c, SPC to remove: " org-lowest-priority)
4609 (setq new (read-char-exclusive))
4610 (cond ((equal new ?\ ) (setq remove t))
4611 ((or (< (upcase new) ?A) (> (upcase new) org-lowest-priority))
4612 (error "Priority must be between `%c' and `%c'"
4613 ?A org-lowest-priority))))
4614 ((eq action 'up)
4615 (setq new (1- current)))
4616 ((eq action 'down)
4617 (setq new (1+ current)))
4618 (t (error "Invalid action")))
4619 (setq new (min (max ?A (upcase new)) org-lowest-priority))
4620 (setq news (format "%c" new))
4621 (if have
4622 (if remove
4623 (replace-match "" t t nil 1)
4624 (replace-match news t t nil 2))
4625 (if remove
4626 (error "No priority cookie found in line")
4627 (looking-at org-todo-line-regexp)
4628 (if (match-end 2)
4629 (progn
4630 (goto-char (match-end 2))
4631 (insert " [#" news "]"))
4632 (goto-char (match-beginning 3))
4633 (insert "[#" news "] ")))))
4634 (if remove
4635 (message "Priority removed")
4636 (message "Priority of current item set to %s" news))))
4639 (defun org-get-priority (s)
4640 "Find priority cookie and return priority."
4641 (save-match-data
4642 (if (not (string-match org-priority-regexp s))
4643 (* 1000 (- org-lowest-priority org-default-priority))
4644 (* 1000 (- org-lowest-priority
4645 (string-to-char (match-string 2 s)))))))
4647 ;;; Timestamps
4649 (defvar org-last-changed-timestamp nil)
4651 (defun org-time-stamp (arg)
4652 "Prompt for a date/time and insert a time stamp.
4653 If the user specifies a time like HH:MM, or if this command is called
4654 with a prefix argument, the time stamp will contain date and time.
4655 Otherwise, only the date will be included. All parts of a date not
4656 specified by the user will be filled in from the current date/time.
4657 So if you press just return without typing anything, the time stamp
4658 will represent the current date/time. If there is already a timestamp
4659 at the cursor, it will be modified."
4660 (interactive "P")
4661 (let ((fmt (if arg (cdr org-time-stamp-formats)
4662 (car org-time-stamp-formats)))
4663 (org-time-was-given nil)
4664 time)
4665 (cond
4666 ((and (org-at-timestamp-p)
4667 (eq last-command 'org-time-stamp)
4668 (eq this-command 'org-time-stamp))
4669 (insert "--")
4670 (setq time (let ((this-command this-command))
4671 (org-read-date arg 'totime)))
4672 (if org-time-was-given (setq fmt (cdr org-time-stamp-formats)))
4673 (insert (format-time-string fmt time)))
4674 ((org-at-timestamp-p)
4675 (setq time (let ((this-command this-command))
4676 (org-read-date arg 'totime)))
4677 (and (org-at-timestamp-p) (replace-match
4678 (setq org-last-changed-timestamp
4679 (format-time-string fmt time))
4680 t t))
4681 (message "Timestamp updated"))
4683 (setq time (let ((this-command this-command))
4684 (org-read-date arg 'totime)))
4685 (if org-time-was-given (setq fmt (cdr org-time-stamp-formats)))
4686 (insert (format-time-string fmt time))))))
4688 (defun org-time-stamp-inactive (&optional arg)
4689 "Insert an inactive time stamp.
4690 An inactive time stamp is enclosed in square brackets instead of angle
4691 brackets. It is inactive in the sense that it does not trigger agenda entries,
4692 does not link to the calendar and cannot be changed with the S-cursor keys.
4693 So these are more for recording a certain time/date."
4694 (interactive "P")
4695 (let ((fmt (if arg (cdr org-time-stamp-formats)
4696 (car org-time-stamp-formats)))
4697 (org-time-was-given nil)
4698 time)
4699 (setq time (org-read-date arg 'totime))
4700 (if org-time-was-given (setq fmt (cdr org-time-stamp-formats)))
4701 (setq fmt (concat "[" (substring fmt 1 -1) "]"))
4702 (insert (format-time-string fmt time))))
4704 (defvar org-date-ovl (org-make-overlay 1 1))
4705 (org-overlay-put org-date-ovl 'face 'org-warning)
4706 (org-detatch-overlay org-date-ovl)
4708 (defun org-read-date (&optional with-time to-time)
4709 "Read a date and make things smooth for the user.
4710 The prompt will suggest to enter an ISO date, but you can also enter anything
4711 which will at least partially be understood by `parse-time-string'.
4712 Unrecognized parts of the date will default to the current day, month, year,
4713 hour and minute. For example,
4714 3-2-5 --> 2003-02-05
4715 feb 15 --> currentyear-02-15
4716 sep 12 9 --> 2009-09-12
4717 12:45 --> today 12:45
4718 22 sept 0:34 --> currentyear-09-22 0:34
4719 12 --> currentyear-currentmonth-12
4720 Fri --> nearest Friday (today or later)
4721 etc.
4722 The function understands only English month and weekday abbreviations,
4723 but this can be configured with the variables `parse-time-months' and
4724 `parse-time-weekdays'.
4726 While prompting, a calendar is popped up - you can also select the
4727 date with the mouse (button 1). The calendar shows a period of three
4728 months. To scroll it to other months, use the keys `>' and `<'.
4729 If you don't like the calendar, turn it off with
4730 \(setq org-popup-calendar-for-date-prompt nil)
4732 With optional argument TO-TIME, the date will immediately be converted
4733 to an internal time.
4734 With an optional argument WITH-TIME, the prompt will suggest to also
4735 insert a time. Note that when WITH-TIME is not set, you can still
4736 enter a time, and this function will inform the calling routine about
4737 this change. The calling routine may then choose to change the format
4738 used to insert the time stamp into the buffer to include the time."
4739 (require 'parse-time)
4740 (let* ((org-time-stamp-rounding-minutes
4741 (if (equal with-time '(16)) 0 org-time-stamp-rounding-minutes))
4742 (ct (org-current-time))
4743 (default-time
4744 ;; Default time is either today, or, when entering a range,
4745 ;; the range start.
4746 (if (save-excursion
4747 (re-search-backward
4748 (concat org-ts-regexp "--\\=") ; FIXME: exactly two minuses?
4749 (- (point) 20) t))
4750 (apply
4751 'encode-time
4752 (mapcar (lambda(x) (or x 0))
4753 (parse-time-string (match-string 1))))
4754 ct))
4755 (calendar-move-hook nil)
4756 (view-diary-entries-initially nil)
4757 (view-calendar-holidays-initially nil)
4758 (timestr (format-time-string
4759 (if with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") default-time))
4760 (prompt (format "YYYY-MM-DD [%s]: " timestr))
4761 ans ans1 ans2
4762 second minute hour day month year tl wday wday1)
4764 (if org-popup-calendar-for-date-prompt
4765 (save-excursion
4766 (save-window-excursion
4767 (calendar)
4768 (calendar-forward-day (- (time-to-days default-time)
4769 (calendar-absolute-from-gregorian
4770 (calendar-current-date))))
4771 (org-eval-in-calendar nil)
4772 (let* ((old-map (current-local-map))
4773 (map (copy-keymap calendar-mode-map))
4774 (minibuffer-local-map (copy-keymap minibuffer-local-map)))
4775 (define-key map (kbd "RET") 'org-calendar-select)
4776 (define-key map (if (featurep 'xemacs) [button1] [mouse-1])
4777 'org-calendar-select-mouse)
4778 (define-key map (if (featurep 'xemacs) [button2] [mouse-2])
4779 'org-calendar-select-mouse)
4780 (define-key minibuffer-local-map [(meta shift left)]
4781 (lambda () (interactive)
4782 (org-eval-in-calendar '(calendar-backward-month 1))))
4783 (define-key minibuffer-local-map [(meta shift right)]
4784 (lambda () (interactive)
4785 (org-eval-in-calendar '(calendar-forward-month 1))))
4786 (define-key minibuffer-local-map [(shift up)]
4787 (lambda () (interactive)
4788 (org-eval-in-calendar '(calendar-backward-week 1))))
4789 (define-key minibuffer-local-map [(shift down)]
4790 (lambda () (interactive)
4791 (org-eval-in-calendar '(calendar-forward-week 1))))
4792 (define-key minibuffer-local-map [(shift left)]
4793 (lambda () (interactive)
4794 (org-eval-in-calendar '(calendar-backward-day 1))))
4795 (define-key minibuffer-local-map [(shift right)]
4796 (lambda () (interactive)
4797 (org-eval-in-calendar '(calendar-forward-day 1))))
4798 (define-key minibuffer-local-map ">"
4799 (lambda () (interactive)
4800 (org-eval-in-calendar '(scroll-calendar-left 1))))
4801 (define-key minibuffer-local-map "<"
4802 (lambda () (interactive)
4803 (org-eval-in-calendar '(scroll-calendar-right 1))))
4804 (unwind-protect
4805 (progn
4806 (use-local-map map)
4807 (setq ans (read-string prompt "" nil nil))
4808 (if (not (string-match "\\S-" ans)) (setq ans nil))
4809 (setq ans (or ans1 ans ans2)))
4810 (use-local-map old-map)))))
4811 ;; Naked prompt only
4812 (setq ans (read-string prompt "" nil timestr)))
4813 (org-detatch-overlay org-date-ovl)
4815 (if (string-match
4816 "^ *\\(\\([0-9]+\\)-\\)?\\([0-1]?[0-9]\\)-\\([0-3]?[0-9]\\)\\([^-0-9]\\|$\\)" ans)
4817 (progn
4818 (setq year (if (match-end 2)
4819 (string-to-number (match-string 2 ans))
4820 (string-to-number (format-time-string "%Y")))
4821 month (string-to-number (match-string 3 ans))
4822 day (string-to-number (match-string 4 ans)))
4823 (if (< year 100) (setq year (+ 2000 year)))
4824 (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
4825 t nil ans))))
4826 (setq tl (parse-time-string ans)
4827 year (or (nth 5 tl) (string-to-number (format-time-string "%Y" ct)))
4828 month (or (nth 4 tl) (string-to-number (format-time-string "%m" ct)))
4829 day (or (nth 3 tl) (string-to-number (format-time-string "%d" ct)))
4830 hour (or (nth 2 tl) (string-to-number (format-time-string "%H" ct)))
4831 minute (or (nth 1 tl) (string-to-number (format-time-string "%M" ct)))
4832 second (or (nth 0 tl) 0)
4833 wday (nth 6 tl))
4834 (when (and wday (not (nth 3 tl)))
4835 ;; Weekday was given, but no day, so pick that day in the week
4836 ;; on or after the derived date.
4837 (setq wday1 (nth 6 (decode-time (encode-time 0 0 0 day month year))))
4838 (unless (equal wday wday1)
4839 (setq day (+ day (% (- wday wday1 -7) 7)))))
4840 (if (and (boundp 'org-time-was-given)
4841 (nth 2 tl))
4842 (setq org-time-was-given t))
4843 (if (< year 100) (setq year (+ 2000 year)))
4844 (if to-time
4845 (encode-time second minute hour day month year)
4846 (if (or (nth 1 tl) (nth 2 tl))
4847 (format "%04d-%02d-%02d %02d:%02d" year month day hour minute)
4848 (format "%04d-%02d-%02d" year month day)))))
4850 (defun org-eval-in-calendar (form)
4851 "Eval FORM in the calendar window and return to current window.
4852 Also, store the cursor date in variable ans2."
4853 (let ((sw (selected-window)))
4854 (select-window (get-buffer-window "*Calendar*"))
4855 (eval form)
4856 (when (calendar-cursor-to-date)
4857 (let* ((date (calendar-cursor-to-date))
4858 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
4859 (setq ans2 (format-time-string "%Y-%m-%d" time))))
4860 (org-move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer))
4861 (select-window sw)))
4863 (defun org-calendar-select ()
4864 "Return to `org-read-date' with the date currently selected.
4865 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
4866 (interactive)
4867 (when (calendar-cursor-to-date)
4868 (let* ((date (calendar-cursor-to-date))
4869 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
4870 (setq ans1 (format-time-string "%Y-%m-%d" time)))
4871 (if (active-minibuffer-window) (exit-minibuffer))))
4873 (defun org-calendar-select-mouse (ev)
4874 "Return to `org-read-date' with the date currently selected.
4875 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
4876 (interactive "e")
4877 (mouse-set-point ev)
4878 (when (calendar-cursor-to-date)
4879 (let* ((date (calendar-cursor-to-date))
4880 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
4881 (setq ans1 (format-time-string "%Y-%m-%d" time)))
4882 (if (active-minibuffer-window) (exit-minibuffer))))
4884 (defun org-check-deadlines (ndays)
4885 "Check if there are any deadlines due or past due.
4886 A deadline is considered due if it happens within `org-deadline-warning-days'
4887 days from today's date. If the deadline appears in an entry marked DONE,
4888 it is not shown. The prefix arg NDAYS can be used to test that many
4889 days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are shown."
4890 (interactive "P")
4891 (let* ((org-warn-days
4892 (cond
4893 ((equal ndays '(4)) 100000)
4894 (ndays (prefix-numeric-value ndays))
4895 (t org-deadline-warning-days)))
4896 (case-fold-search nil)
4897 (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>"))
4898 (callback
4899 (lambda ()
4900 (and (let ((d1 (time-to-days (current-time)))
4901 (d2 (time-to-days
4902 (org-time-string-to-time (match-string 1)))))
4903 (< (- d2 d1) org-warn-days))
4904 (not (org-entry-is-done-p))))))
4905 (message "%d deadlines past-due or due within %d days"
4906 (org-occur regexp callback)
4907 org-warn-days)))
4909 (defun org-evaluate-time-range (&optional to-buffer)
4910 "Evaluate a time range by computing the difference between start and end.
4911 Normally the result is just printed in the echo area, but with prefix arg
4912 TO-BUFFER, the result is inserted just after the date stamp into the buffer.
4913 If the time range is actually in a table, the result is inserted into the
4914 next column.
4915 For time difference computation, a year is assumed to be exactly 365
4916 days in order to avoid rounding problems."
4917 (interactive "P")
4918 (save-excursion
4919 (unless (org-at-date-range-p)
4920 (goto-char (point-at-bol))
4921 (re-search-forward org-tr-regexp (point-at-eol) t))
4922 (if (not (org-at-date-range-p))
4923 (error "Not at a time-stamp range, and none found in current line")))
4924 (let* ((ts1 (match-string 1))
4925 (ts2 (match-string 2))
4926 (havetime (or (> (length ts1) 15) (> (length ts2) 15)))
4927 (match-end (match-end 0))
4928 (time1 (org-time-string-to-time ts1))
4929 (time2 (org-time-string-to-time ts2))
4930 (t1 (time-to-seconds time1))
4931 (t2 (time-to-seconds time2))
4932 (diff (abs (- t2 t1)))
4933 (negative (< (- t2 t1) 0))
4934 ;; (ys (floor (* 365 24 60 60)))
4935 (ds (* 24 60 60))
4936 (hs (* 60 60))
4937 (fy "%dy %dd %02d:%02d")
4938 (fy1 "%dy %dd")
4939 (fd "%dd %02d:%02d")
4940 (fd1 "%dd")
4941 (fh "%02d:%02d")
4942 y d h m align)
4943 (if havetime
4944 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
4946 d (floor (/ diff ds)) diff (mod diff ds)
4947 h (floor (/ diff hs)) diff (mod diff hs)
4948 m (floor (/ diff 60)))
4949 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
4951 d (floor (+ (/ diff ds) 0.5))
4952 h 0 m 0))
4953 (if (not to-buffer)
4954 (message (org-make-tdiff-string y d h m))
4955 (when (org-at-table-p)
4956 (goto-char match-end)
4957 (setq align t)
4958 (and (looking-at " *|") (goto-char (match-end 0))))
4959 (if (looking-at
4960 "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]")
4961 (replace-match ""))
4962 (if negative (insert " -"))
4963 (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m))
4964 (if (> d 0) (insert " " (format (if havetime fd fd1) d h m))
4965 (insert " " (format fh h m))))
4966 (if align (org-table-align))
4967 (message "Time difference inserted"))))
4969 (defun org-make-tdiff-string (y d h m)
4970 (let ((fmt "")
4971 (l nil))
4972 (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ")
4973 l (push y l)))
4974 (if (> d 0) (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ")
4975 l (push d l)))
4976 (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ")
4977 l (push h l)))
4978 (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ")
4979 l (push m l)))
4980 (apply 'format fmt (nreverse l))))
4982 (defun org-time-string-to-time (s)
4983 (apply 'encode-time (org-parse-time-string s)))
4985 (defun org-parse-time-string (s &optional nodefault)
4986 "Parse the standard Org-mode time string.
4987 This should be a lot faster than the normal `parse-time-string'.
4988 If time is not given, defaults to 0:00. However, with optional NODEFAULT,
4989 hour and minute fields will be nil if not given."
4990 (if (string-match org-ts-regexp1 s)
4991 (list 0
4992 (if (or (match-beginning 8) (not nodefault))
4993 (string-to-number (or (match-string 8 s) "0")))
4994 (if (or (match-beginning 7) (not nodefault))
4995 (string-to-number (or (match-string 7 s) "0")))
4996 (string-to-number (match-string 4 s))
4997 (string-to-number (match-string 3 s))
4998 (string-to-number (match-string 2 s))
4999 nil nil nil)
5000 (make-list 9 0)))
5002 (defun org-timestamp-up (&optional arg)
5003 "Increase the date item at the cursor by one.
5004 If the cursor is on the year, change the year. If it is on the month or
5005 the day, change that.
5006 With prefix ARG, change by that many units."
5007 (interactive "p")
5008 (org-timestamp-change (prefix-numeric-value arg)))
5010 (defun org-timestamp-down (&optional arg)
5011 "Decrease the date item at the cursor by one.
5012 If the cursor is on the year, change the year. If it is on the month or
5013 the day, change that.
5014 With prefix ARG, change by that many units."
5015 (interactive "p")
5016 (org-timestamp-change (- (prefix-numeric-value arg))))
5018 (defun org-timestamp-up-day (&optional arg)
5019 "Increase the date in the time stamp by one day.
5020 With prefix ARG, change that many days."
5021 (interactive "p")
5022 (if (and (not (org-at-timestamp-p))
5023 (org-on-heading-p))
5024 (org-todo 'up)
5025 (org-timestamp-change (prefix-numeric-value arg) 'day)))
5027 (defun org-timestamp-down-day (&optional arg)
5028 "Decrease the date in the time stamp by one day.
5029 With prefix ARG, change that many days."
5030 (interactive "p")
5031 (if (and (not (org-at-timestamp-p))
5032 (org-on-heading-p))
5033 (org-todo 'down)
5034 (org-timestamp-change (- (prefix-numeric-value arg)) 'day)))
5036 (defsubst org-pos-in-match-range (pos n)
5037 (and (match-beginning n)
5038 (<= (match-beginning n) pos)
5039 (>= (match-end n) pos)))
5041 (defun org-at-timestamp-p ()
5042 "Determine if the cursor is in or at a timestamp."
5043 (interactive)
5044 (let* ((tsr org-ts-regexp2)
5045 (pos (point))
5046 (ans (or (looking-at tsr)
5047 (save-excursion
5048 (skip-chars-backward "^<\n\r\t")
5049 (if (> (point) 1) (backward-char 1))
5050 (and (looking-at tsr)
5051 (> (- (match-end 0) pos) -1))))))
5052 (and (boundp 'org-ts-what)
5053 (setq org-ts-what
5054 (cond
5055 ((org-pos-in-match-range pos 2) 'year)
5056 ((org-pos-in-match-range pos 3) 'month)
5057 ((org-pos-in-match-range pos 7) 'hour)
5058 ((org-pos-in-match-range pos 8) 'minute)
5059 ((or (org-pos-in-match-range pos 4)
5060 (org-pos-in-match-range pos 5)) 'day)
5061 (t 'day))))
5062 ans))
5064 (defun org-timestamp-change (n &optional what)
5065 "Change the date in the time stamp at point.
5066 The date will be changed by N times WHAT. WHAT can be `day', `month',
5067 `year', `minute', `second'. If WHAT is not given, the cursor position
5068 in the timestamp determines what will be changed."
5069 (let ((fmt (car org-time-stamp-formats))
5070 org-ts-what
5071 (pos (point))
5072 ts time time0)
5073 (if (not (org-at-timestamp-p))
5074 (error "Not at a timestamp"))
5075 (setq org-ts-what (or what org-ts-what))
5076 (setq fmt (if (<= (abs (- (cdr org-ts-lengths)
5077 (- (match-end 0) (match-beginning 0))))
5079 (cdr org-time-stamp-formats)
5080 (car org-time-stamp-formats)))
5081 (setq ts (match-string 0))
5082 (replace-match "")
5083 (setq time0 (org-parse-time-string ts))
5084 (setq time
5085 (apply 'encode-time
5086 (append
5087 (list (or (car time0) 0))
5088 (list (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0)))
5089 (list (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0)))
5090 (list (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0)))
5091 (list (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0)))
5092 (list (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0)))
5093 (nthcdr 6 time0))))
5094 (if (eq what 'calendar)
5095 (let ((cal-date
5096 (save-excursion
5097 (save-match-data
5098 (set-buffer "*Calendar*")
5099 (calendar-cursor-to-date)))))
5100 (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month
5101 (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day
5102 (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year
5103 (setcar time0 (or (car time0) 0))
5104 (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
5105 (setcar (nthcdr 2 time0) (or (nth 1 time0) 0))
5106 (setq time (apply 'encode-time time0))))
5107 (insert (setq org-last-changed-timestamp (format-time-string fmt time)))
5108 (goto-char pos)
5109 ;; Try to recenter the calendar window, if any
5110 (if (and org-calendar-follow-timestamp-change
5111 (get-buffer-window "*Calendar*" t)
5112 (memq org-ts-what '(day month year)))
5113 (org-recenter-calendar (time-to-days time)))))
5115 (defun org-recenter-calendar (date)
5116 "If the calendar is visible, recenter it to DATE."
5117 (let* ((win (selected-window))
5118 (cwin (get-buffer-window "*Calendar*" t))
5119 (calendar-move-hook nil))
5120 (when cwin
5121 (select-window cwin)
5122 (calendar-goto-date (if (listp date) date
5123 (calendar-gregorian-from-absolute date)))
5124 (select-window win))))
5126 (defun org-goto-calendar (&optional arg)
5127 "Go to the Emacs calendar at the current date.
5128 If there is a time stamp in the current line, go to that date.
5129 A prefix ARG can be used to force the current date."
5130 (interactive "P")
5131 (let ((tsr org-ts-regexp) diff
5132 (calendar-move-hook nil)
5133 (view-calendar-holidays-initially nil)
5134 (view-diary-entries-initially nil))
5135 (if (or (org-at-timestamp-p)
5136 (save-excursion
5137 (beginning-of-line 1)
5138 (looking-at (concat ".*" tsr))))
5139 (let ((d1 (time-to-days (current-time)))
5140 (d2 (time-to-days
5141 (org-time-string-to-time (match-string 1)))))
5142 (setq diff (- d2 d1))))
5143 (calendar)
5144 (calendar-goto-today)
5145 (if (and diff (not arg)) (calendar-forward-day diff))))
5147 (defun org-date-from-calendar ()
5148 "Insert time stamp corresponding to cursor date in *Calendar* buffer.
5149 If there is already a time stamp at the cursor position, update it."
5150 (interactive)
5151 (org-timestamp-change 0 'calendar))
5153 ;;; Agenda, and Diary Integration
5155 ;;; Define the mode
5157 (defvar org-agenda-mode-map (make-sparse-keymap)
5158 "Keymap for `org-agenda-mode'.")
5160 (defvar org-agenda-menu) ; defined later in this file.
5161 (defvar org-agenda-follow-mode nil)
5162 (defvar org-agenda-show-log nil)
5163 (defvar org-agenda-buffer-name "*Org Agenda*")
5164 (defvar org-agenda-redo-command nil)
5165 (defvar org-agenda-mode-hook nil)
5166 (defvar org-agenda-type nil)
5167 (defvar org-agenda-force-single-file nil)
5169 (defun org-agenda-mode ()
5170 "Mode for time-sorted view on action items in Org-mode files.
5172 The following commands are available:
5174 \\{org-agenda-mode-map}"
5175 (interactive)
5176 (kill-all-local-variables)
5177 (setq major-mode 'org-agenda-mode)
5178 (setq mode-name "Org-Agenda")
5179 (use-local-map org-agenda-mode-map)
5180 (easy-menu-add org-agenda-menu)
5181 (if org-startup-truncated (setq truncate-lines t))
5182 (org-add-hook 'post-command-hook 'org-agenda-post-command-hook nil 'local)
5183 (org-add-hook 'pre-command-hook 'org-unhighlight nil 'local)
5184 (unless org-agenda-keep-modes
5185 (setq org-agenda-follow-mode org-agenda-start-with-follow-mode
5186 org-agenda-show-log nil))
5187 (easy-menu-change
5188 '("Agenda") "Agenda Files"
5189 (append
5190 (list
5191 (vector
5192 (if (get 'org-agenda-files 'org-restrict)
5193 "Restricted to single file"
5194 "Edit File List")
5195 '(org-edit-agenda-file-list)
5196 (not (get 'org-agenda-files 'org-restrict)))
5197 "--")
5198 (mapcar 'org-file-menu-entry (org-agenda-files))))
5199 (org-agenda-set-mode-name)
5200 (apply
5201 (if (fboundp 'run-mode-hooks) 'run-mode-hooks 'run-hooks)
5202 (list 'org-agenda-mode-hook)))
5204 (define-key org-agenda-mode-map "\C-i" 'org-agenda-goto)
5205 (define-key org-agenda-mode-map [(tab)] 'org-agenda-goto)
5206 (define-key org-agenda-mode-map "\C-m" 'org-agenda-switch-to)
5207 (define-key org-agenda-mode-map " " 'org-agenda-show)
5208 (define-key org-agenda-mode-map "\C-c\C-t" 'org-agenda-todo)
5209 (define-key org-agenda-mode-map "o" 'delete-other-windows)
5210 (define-key org-agenda-mode-map "L" 'org-agenda-recenter)
5211 (define-key org-agenda-mode-map "t" 'org-agenda-todo)
5212 (define-key org-agenda-mode-map ":" 'org-agenda-set-tags)
5213 (define-key org-agenda-mode-map "." 'org-agenda-goto-today)
5214 (define-key org-agenda-mode-map "d" 'org-agenda-day-view)
5215 (define-key org-agenda-mode-map "w" 'org-agenda-week-view)
5216 (define-key org-agenda-mode-map (org-key 'S-right) 'org-agenda-date-later)
5217 (define-key org-agenda-mode-map (org-key 'S-left) 'org-agenda-date-earlier)
5218 (define-key org-agenda-mode-map [?\C-c ?\C-x (right)] 'org-agenda-date-later)
5219 (define-key org-agenda-mode-map [?\C-c ?\C-x (left)] 'org-agenda-date-earlier)
5221 (define-key org-agenda-mode-map ">" 'org-agenda-date-prompt)
5222 (define-key org-agenda-mode-map "\C-c\C-s" 'org-agenda-schedule)
5223 (define-key org-agenda-mode-map "\C-c\C-d" 'org-agenda-deadline)
5224 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
5225 (while l (define-key org-agenda-mode-map
5226 (int-to-string (pop l)) 'digit-argument)))
5228 (define-key org-agenda-mode-map "f" 'org-agenda-follow-mode)
5229 (define-key org-agenda-mode-map "l" 'org-agenda-log-mode)
5230 (define-key org-agenda-mode-map "D" 'org-agenda-toggle-diary)
5231 (define-key org-agenda-mode-map "g" 'org-agenda-toggle-time-grid)
5232 (define-key org-agenda-mode-map "r" 'org-agenda-redo)
5233 (define-key org-agenda-mode-map "q" 'org-agenda-quit)
5234 (define-key org-agenda-mode-map "x" 'org-agenda-exit)
5235 (define-key org-agenda-mode-map "P" 'org-agenda-show-priority)
5236 (define-key org-agenda-mode-map "T" 'org-agenda-show-tags)
5237 (define-key org-agenda-mode-map "n" 'next-line)
5238 (define-key org-agenda-mode-map "p" 'previous-line)
5239 (define-key org-agenda-mode-map "\C-n" 'org-agenda-next-date-line)
5240 (define-key org-agenda-mode-map "\C-p" 'org-agenda-previous-date-line)
5241 (define-key org-agenda-mode-map "," 'org-agenda-priority)
5242 (define-key org-agenda-mode-map "\C-c," 'org-agenda-priority)
5243 (define-key org-agenda-mode-map "i" 'org-agenda-diary-entry)
5244 (define-key org-agenda-mode-map "c" 'org-agenda-goto-calendar)
5245 (eval-after-load "calendar"
5246 '(define-key calendar-mode-map org-calendar-to-agenda-key
5247 'org-calendar-goto-agenda))
5248 (define-key org-agenda-mode-map "C" 'org-agenda-convert-date)
5249 (define-key org-agenda-mode-map "m" 'org-agenda-phases-of-moon)
5250 (define-key org-agenda-mode-map "M" 'org-agenda-phases-of-moon)
5251 (define-key org-agenda-mode-map "s" 'org-agenda-sunrise-sunset)
5252 (define-key org-agenda-mode-map "S" 'org-agenda-sunrise-sunset)
5253 (define-key org-agenda-mode-map "h" 'org-agenda-holidays)
5254 (define-key org-agenda-mode-map "H" 'org-agenda-holidays)
5255 (define-key org-agenda-mode-map "+" 'org-agenda-priority-up)
5256 (define-key org-agenda-mode-map "-" 'org-agenda-priority-down)
5257 (define-key org-agenda-mode-map (org-key 'S-up) 'org-agenda-priority-up)
5258 (define-key org-agenda-mode-map (org-key 'S-down) 'org-agenda-priority-down)
5259 (define-key org-agenda-mode-map [?\C-c ?\C-x (up)] 'org-agenda-priority-up)
5260 (define-key org-agenda-mode-map [?\C-c ?\C-x (down)] 'org-agenda-priority-down)
5261 (define-key org-agenda-mode-map [(right)] 'org-agenda-later)
5262 (define-key org-agenda-mode-map [(left)] 'org-agenda-earlier)
5263 (define-key org-agenda-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files)
5264 (defvar org-agenda-keymap (copy-keymap org-agenda-mode-map)
5265 "Local keymap for agenda entries from Org-mode.")
5267 (define-key org-agenda-keymap
5268 (if (featurep 'xemacs) [(button2)] [(mouse-2)]) 'org-agenda-goto-mouse)
5269 (define-key org-agenda-keymap
5270 (if (featurep 'xemacs) [(button3)] [(mouse-3)]) 'org-agenda-show-mouse)
5271 (when org-agenda-mouse-1-follows-link
5272 (define-key org-agenda-keymap [follow-link] 'mouse-face))
5273 (easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu"
5274 '("Agenda"
5275 ("Agenda Files")
5276 "--"
5277 ["Show" org-agenda-show t]
5278 ["Go To (other window)" org-agenda-goto t]
5279 ["Go To (one window)" org-agenda-switch-to t]
5280 ["Follow Mode" org-agenda-follow-mode
5281 :style toggle :selected org-agenda-follow-mode :active t]
5282 "--"
5283 ["Cycle TODO" org-agenda-todo t]
5284 ("Tags"
5285 ["Show all Tags" org-agenda-show-tags t]
5286 ["Set Tags" org-agenda-set-tags t])
5287 ("Schedule"
5288 ["Schedule" org-agenda-schedule t]
5289 ["Set Deadline" org-agenda-deadline t]
5290 "--"
5291 ["Reschedule +1 day" org-agenda-date-later (org-agenda-check-type nil 'agenda 'timeline)]
5292 ["Reschedule -1 day" org-agenda-date-earlier (org-agenda-check-type nil 'agenda 'timeline)]
5293 ["Reschedule to ..." org-agenda-date-prompt (org-agenda-check-type nil 'agenda 'timeline)])
5294 ("Priority"
5295 ["Set Priority" org-agenda-priority t]
5296 ["Increase Priority" org-agenda-priority-up t]
5297 ["Decrease Priority" org-agenda-priority-down t]
5298 ["Show Priority" org-agenda-show-priority t])
5299 "--"
5300 ;; ["New agenda command" org-agenda t]
5301 ["Rebuild buffer" org-agenda-redo t]
5302 "--"
5303 ["Goto Today" org-agenda-goto-today (org-agenda-check-type nil 'agenda 'timeline)]
5304 ["Next Dates" org-agenda-later (org-agenda-check-type nil 'agenda)]
5305 ["Previous Dates" org-agenda-earlier (org-agenda-check-type nil 'agenda)]
5306 "--"
5307 ["Day View" org-agenda-day-view :active (org-agenda-check-type nil 'agenda)
5308 :style radio :selected (equal org-agenda-ndays 1)]
5309 ["Week View" org-agenda-week-view :active (org-agenda-check-type nil 'agenda)
5310 :style radio :selected (equal org-agenda-ndays 7)]
5311 "--"
5312 ["Show Logbook entries" org-agenda-log-mode
5313 :style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)]
5314 ["Include Diary" org-agenda-toggle-diary
5315 :style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)]
5316 ["Use Time Grid" org-agenda-toggle-time-grid
5317 :style toggle :selected org-agenda-use-time-grid :active (org-agenda-check-type nil 'agenda)]
5318 "--"
5319 ["New Diary Entry" org-agenda-diary-entry (org-agenda-check-type nil 'agenda 'timeline)]
5320 ("Calendar Commands"
5321 ["Goto Calendar" org-agenda-goto-calendar (org-agenda-check-type nil 'agenda 'timeline)]
5322 ["Phases of the Moon" org-agenda-phases-of-moon (org-agenda-check-type nil 'agenda 'timeline)]
5323 ["Sunrise/Sunset" org-agenda-sunrise-sunset (org-agenda-check-type nil 'agenda 'timeline)]
5324 ["Holidays" org-agenda-holidays (org-agenda-check-type nil 'agenda 'timeline)]
5325 ["Convert" org-agenda-convert-date (org-agenda-check-type nil 'agenda 'timeline)])
5326 ["Create iCalendar file" org-export-icalendar-combine-agenda-files t]
5327 "--"
5328 ["Quit" org-agenda-quit t]
5329 ["Exit and Release Buffers" org-agenda-exit t]
5332 ;;;###autoload
5333 (defun org-agenda (arg)
5334 "Dispatch agenda commands to collect entries to the agenda buffer.
5335 Prompts for a character to select a command. Any prefix arg will be passed
5336 on to the selected command. The default selections are:
5338 a Call `org-agenda' to display the agenda for the current day or week.
5339 t Call `org-todo-list' to display the global todo list.
5340 T Call `org-todo-list' to display the global todo list, select only
5341 entries with a specific TODO keyword (the user gets a prompt).
5342 m Call `org-tags-view' to display headlines with tags matching
5343 a condition (the user is prompted for the condition).
5344 M Like `m', but select only TODO entries, no ordinary headlines.
5346 More commands can be added by configuring the variable
5347 `org-agenda-custom-commands'. In particular, specific tags and TODO keyword
5348 searches can be pre-defined in this way.
5350 If the current buffer is in Org-mode and visiting a file, you can also
5351 first press `1' to indicate that the agenda should be temporarily (until the
5352 next use of \\[org-agenda]) restricted to the current file."
5353 (interactive "P")
5354 (catch 'exit
5355 (let ((restrict-ok (and buffer-file-name (eq major-mode 'org-mode)))
5356 (custom org-agenda-custom-commands)
5357 c entry key type string)
5358 (put 'org-agenda-files 'org-restrict nil)
5359 (save-window-excursion
5360 (delete-other-windows)
5361 (switch-to-buffer-other-window " *Agenda Commands*")
5362 (erase-buffer)
5363 (insert
5364 "Press key for an agenda command:
5365 --------------------------------
5366 a Agenda for current week or day
5367 t List of all TODO entries T Entries with special TODO kwd
5368 m Match a TAGS query M Like m, but only TODO entries
5369 C Configure your own agenda commands")
5370 (while (setq entry (pop custom))
5371 (setq key (car entry) type (nth 1 entry) string (nth 2 entry))
5372 (insert (format "\n%-4s%-14s: %s"
5374 (cond
5375 ((eq type 'tags) "Tags query")
5376 ((eq type 'todo) "TODO keyword")
5377 ((eq type 'tags-tree) "Tags tree")
5378 ((eq type 'todo-tree) "TODO kwd tree")
5379 ((eq type 'occur-tree) "Occur tree")
5380 (t "???"))
5381 (org-add-props string nil 'face 'org-warning))))
5382 (goto-char (point-min))
5383 (if (fboundp 'fit-window-to-buffer) (fit-window-to-buffer))
5384 (message "Press key for agenda command%s"
5385 (if restrict-ok ", or [1] to restrict to current file" ""))
5386 (setq c (read-char-exclusive))
5387 (message "")
5388 (when (equal c ?1)
5389 (if restrict-ok
5390 (put 'org-agenda-files 'org-restrict (list buffer-file-name))
5391 (error "Cannot restrict agenda to current buffer"))
5392 (message "Press key for agenda command%s"
5393 (if restrict-ok " (restricted to current file)" ""))
5394 (setq c (read-char-exclusive))
5395 (message "")))
5396 (require 'calendar) ; FIXME: can we avoid this for some commands?
5397 ;; For example the todo list should not need it (but does...)
5398 (cond
5399 ((equal c ?C) (customize-variable 'org-agenda-custom-commands))
5400 ((equal c ?a) (call-interactively 'org-agenda-list))
5401 ((equal c ?t) (call-interactively 'org-todo-list))
5402 ((equal c ?T) (org-call-with-arg 'org-todo-list (or arg '(4))))
5403 ((equal c ?m) (call-interactively 'org-tags-view))
5404 ((equal c ?M) (org-call-with-arg 'org-tags-view (or arg '(4))))
5405 ((setq entry (assoc (char-to-string c) org-agenda-custom-commands))
5406 (setq type (nth 1 entry) string (nth 2 entry))
5407 (cond
5408 ((eq type 'tags)
5409 (org-tags-view current-prefix-arg string))
5410 ((eq type 'tags-todo)
5411 (org-tags-view '(4) string))
5412 ((eq type 'todo)
5413 (org-todo-list string))
5414 ((eq type 'tags-tree)
5415 (org-check-for-org-mode)
5416 (org-tags-sparse-tree current-prefix-arg string))
5417 ((eq type 'todo-tree)
5418 (org-check-for-org-mode)
5419 (org-occur (concat "^" outline-regexp "[ \t]*"
5420 (regexp-quote string) "\\>")))
5421 ((eq type 'occur-tree)
5422 (org-check-for-org-mode)
5423 (org-occur string))
5424 (t (error "Invalid custom agenda command type %s" type))))
5425 (t (error "Invalid key"))))))
5427 (defun org-check-for-org-mode ()
5428 "Make sure current buffer is in org-mode. Error if not."
5429 (or (eq major-mode 'org-mode)
5430 (error "Cannot execute org-mode agenda command on buffer in %s."
5431 major-mode)))
5433 (defun org-fit-agenda-window ()
5434 "Fit the window to the buffer size."
5435 (and org-fit-agenda-window
5436 (fboundp 'fit-window-to-buffer)
5437 (fit-window-to-buffer nil (/ (* (frame-height) 3) 4)
5438 (/ (frame-height) 2))))
5440 (defun org-agenda-files (&optional unrestricted)
5441 "Get the list of agenda files.
5442 Optional UNRESTRICTED means return the full list even if a restriction
5443 is currently in place."
5444 (cond
5445 ((and (not unrestricted) (get 'org-agenda-files 'org-restrict)))
5446 ((stringp org-agenda-files) (org-read-agenda-file-list))
5447 ((listp org-agenda-files) org-agenda-files)
5448 (t (error "Invalid value of `org-agenda-files'"))))
5450 (defvar org-window-configuration)
5452 (defun org-edit-agenda-file-list ()
5453 "Edit the list of agenda files.
5454 Depending on setup, this either uses customize to edit the variable
5455 `org-agenda-files', or it visits the file that is holding the list. In the
5456 latter case, the buffer is set up in a way that saving it automatically kills
5457 the buffer and restores the previous window configuration."
5458 (interactive)
5459 (if (stringp org-agenda-files)
5460 (let ((cw (current-window-configuration)))
5461 (find-file org-agenda-files)
5462 (set (make-local-variable 'org-window-configuration) cw)
5463 (org-add-hook 'after-save-hook
5464 (lambda ()
5465 (set-window-configuration
5466 (prog1 org-window-configuration
5467 (kill-buffer (current-buffer))))
5468 (org-install-agenda-files-menu)
5469 (message "New agenda file list installed"))
5470 nil 'local)
5471 (message (substitute-command-keys
5472 "Edit list and finish with \\[save-buffer]")))
5473 (customize-variable 'org-agenda-files)))
5475 (defun org-store-new-agenda-file-list (list)
5476 "Set new value for the agenda file list and save it correcly."
5477 (if (stringp org-agenda-files)
5478 (let ((f org-agenda-files) b)
5479 (while (setq b (find-buffer-visiting f)) (kill-buffer b))
5480 (with-temp-file f
5481 (insert (mapconcat 'identity list "\n") "\n")))
5482 (let ((org-mode-hook nil) (default-major-mode 'fundamental-mode))
5483 (setq org-agenda-files list)
5484 (customize-save-variable 'org-agenda-files org-agenda-files))))
5486 (defun org-read-agenda-file-list ()
5487 "Read the list of agenda files from a file."
5488 (when (stringp org-agenda-files)
5489 (with-temp-buffer
5490 (insert-file-contents org-agenda-files)
5491 (org-split-string (buffer-string) "[ \t\r\n]*?[\r\n][ \t\r\n]*"))))
5493 (defvar org-agenda-markers nil
5494 "List of all currently active markers created by `org-agenda'.")
5495 (defvar org-agenda-last-marker-time (time-to-seconds (current-time))
5496 "Creation time of the last agenda marker.")
5498 (defun org-agenda-new-marker (&optional pos)
5499 "Return a new agenda marker.
5500 Org-mode keeps a list of these markers and resets them when they are
5501 no longer in use."
5502 (let ((m (copy-marker (or pos (point)))))
5503 (setq org-agenda-last-marker-time (time-to-seconds (current-time)))
5504 (push m org-agenda-markers)
5507 (defun org-agenda-maybe-reset-markers (&optional force)
5508 "Reset markers created by `org-agenda'. But only if they are old enough."
5509 (if (or force
5510 (> (- (time-to-seconds (current-time))
5511 org-agenda-last-marker-time)
5513 (while org-agenda-markers
5514 (move-marker (pop org-agenda-markers) nil))))
5516 (defvar org-agenda-new-buffers nil
5517 "Buffers created to visit agenda files.")
5519 (defun org-get-agenda-file-buffer (file)
5520 "Get a buffer visiting FILE. If the buffer needs to be created, add
5521 it to the list of buffers which might be released later."
5522 (let ((buf (find-buffer-visiting file)))
5523 (if buf
5524 buf ; just return it
5525 ;; Make a new buffer and remember it
5526 (setq buf (find-file-noselect file))
5527 (if buf (push buf org-agenda-new-buffers))
5528 buf)))
5530 (defun org-release-buffers (blist)
5531 "Release all buffers in list, asking the user for confirmation when needed.
5532 When a buffer is unmodified, it is just killed. When modified, it is saved
5533 \(if the user agrees) and then killed."
5534 (let (buf file)
5535 (while (setq buf (pop blist))
5536 (setq file (buffer-file-name buf))
5537 (when (and (buffer-modified-p buf)
5538 file
5539 (y-or-n-p (format "Save file %s? " file)))
5540 (with-current-buffer buf (save-buffer)))
5541 (kill-buffer buf))))
5543 (defvar org-respect-restriction nil) ; Dynamically-scoped param.
5545 (defun org-timeline (&optional include-all keep-modes)
5546 "Show a time-sorted view of the entries in the current org file.
5547 Only entries with a time stamp of today or later will be listed. With
5548 \\[universal-argument] prefix, all unfinished TODO items will also be shown,
5549 under the current date.
5550 If the buffer contains an active region, only check the region for
5551 dates."
5552 (interactive "P")
5553 (require 'calendar)
5554 (org-agenda-maybe-reset-markers 'force)
5555 (org-compile-prefix-format org-timeline-prefix-format)
5556 (let* ((dopast t)
5557 (dotodo include-all)
5558 (doclosed org-agenda-show-log)
5559 (org-agenda-keep-modes keep-modes)
5560 (entry buffer-file-name)
5561 (org-agenda-files (list buffer-file-name))
5562 (date (calendar-current-date))
5563 (win (selected-window))
5564 (pos1 (point))
5565 (beg (if (org-region-active-p) (region-beginning) (point-min)))
5566 (end (if (org-region-active-p) (region-end) (point-max)))
5567 (day-numbers (org-get-all-dates beg end 'no-ranges
5568 t doclosed)) ; always include today
5569 (today (time-to-days (current-time)))
5570 (org-respect-restriction t)
5571 (past t)
5572 args
5573 s e rtn d)
5574 (setq org-agenda-redo-command
5575 (list 'progn
5576 (list 'switch-to-buffer-other-window (current-buffer))
5577 (list 'org-timeline (list 'quote include-all) t)))
5578 (if (not dopast)
5579 ;; Remove past dates from the list of dates.
5580 (setq day-numbers (delq nil (mapcar (lambda(x)
5581 (if (>= x today) x nil))
5582 day-numbers))))
5583 (switch-to-buffer-other-window
5584 (get-buffer-create org-agenda-buffer-name))
5585 (setq buffer-read-only nil)
5586 (erase-buffer)
5587 (org-agenda-mode) (setq buffer-read-only nil)
5588 (set (make-local-variable 'org-agenda-type) 'timeline)
5589 (if doclosed (push :closed args))
5590 (push :timestamp args)
5591 (if dotodo (push :todo args))
5592 (while (setq d (pop day-numbers))
5593 (if (and (>= d today)
5594 dopast
5595 past)
5596 (progn
5597 (setq past nil)
5598 (insert (make-string 79 ?-) "\n")))
5599 (setq date (calendar-gregorian-from-absolute d))
5600 (setq s (point))
5601 (setq rtn (apply 'org-agenda-get-day-entries
5602 entry date args))
5603 (if (or rtn (equal d today))
5604 (progn
5605 (insert (calendar-day-name date) " "
5606 (number-to-string (extract-calendar-day date)) " "
5607 (calendar-month-name (extract-calendar-month date)) " "
5608 (number-to-string (extract-calendar-year date)) "\n")
5609 (put-text-property s (1- (point)) 'face
5610 'org-level-3)
5611 (if (equal d today)
5612 (put-text-property s (1- (point)) 'org-today t))
5613 (insert (org-finalize-agenda-entries rtn) "\n")
5614 (put-text-property s (1- (point)) 'day d))))
5615 (goto-char (point-min))
5616 (setq buffer-read-only t)
5617 (goto-char (or (text-property-any (point-min) (point-max) 'org-today t)
5618 (point-min)))
5619 (when (not org-select-timeline-window)
5620 (select-window win)
5621 (goto-char pos1))))
5623 ;;;###autoload
5624 (defun org-agenda-list (&optional include-all start-day ndays keep-modes)
5625 "Produce a weekly view from all files in variable `org-agenda-files'.
5626 The view will be for the current week, but from the overview buffer you
5627 will be able to go to other weeks.
5628 With one \\[universal-argument] prefix argument INCLUDE-ALL, all unfinished TODO items will
5629 also be shown, under the current date.
5630 With two \\[universal-argument] prefix argument INCLUDE-ALL, all TODO entries marked DONE
5631 on the days are also shown. See the variable `org-log-done' for how
5632 to turn on logging.
5633 START-DAY defaults to TODAY, or to the most recent match for the weekday
5634 given in `org-agenda-start-on-weekday'.
5635 NDAYS defaults to `org-agenda-ndays'."
5636 (interactive "P")
5637 (org-agenda-maybe-reset-markers 'force)
5638 (org-compile-prefix-format org-agenda-prefix-format)
5639 (require 'calendar)
5640 (let* ((org-agenda-start-on-weekday
5641 (if (or (equal ndays 1)
5642 (and (null ndays) (equal 1 org-agenda-ndays)))
5643 nil org-agenda-start-on-weekday))
5644 (org-agenda-keep-modes keep-modes)
5645 (thefiles (org-agenda-files))
5646 (files thefiles)
5647 (win (selected-window))
5648 (today (time-to-days (current-time)))
5649 (sd (or start-day today))
5650 (start (if (or (null org-agenda-start-on-weekday)
5651 (< org-agenda-ndays 7))
5653 (let* ((nt (calendar-day-of-week
5654 (calendar-gregorian-from-absolute sd)))
5655 (n1 org-agenda-start-on-weekday)
5656 (d (- nt n1)))
5657 (- sd (+ (if (< d 0) 7 0) d)))))
5658 (day-numbers (list start))
5659 (inhibit-redisplay t)
5660 s e rtn rtnall file date d start-pos end-pos todayp nd)
5661 (setq org-agenda-redo-command
5662 (list 'org-agenda-list (list 'quote include-all) start-day ndays t))
5663 ;; Make the list of days
5664 (setq ndays (or ndays org-agenda-ndays)
5665 nd ndays)
5666 (while (> ndays 1)
5667 (push (1+ (car day-numbers)) day-numbers)
5668 (setq ndays (1- ndays)))
5669 (setq day-numbers (nreverse day-numbers))
5670 (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name)))
5671 (progn
5672 (delete-other-windows)
5673 (switch-to-buffer-other-window
5674 (get-buffer-create org-agenda-buffer-name))))
5675 (setq buffer-read-only nil)
5676 (erase-buffer)
5677 (org-agenda-mode) (setq buffer-read-only nil)
5678 (set (make-local-variable 'org-agenda-type) 'agenda)
5679 (set (make-local-variable 'starting-day) (car day-numbers))
5680 (set (make-local-variable 'include-all-loc) include-all)
5681 (when (and (or include-all org-agenda-include-all-todo)
5682 (member today day-numbers))
5683 (setq files thefiles
5684 rtnall nil)
5685 (while (setq file (pop files))
5686 (catch 'nextfile
5687 (org-check-agenda-file file)
5688 (setq date (calendar-gregorian-from-absolute today)
5689 rtn (org-agenda-get-day-entries
5690 file date :todo))
5691 (setq rtnall (append rtnall rtn))))
5692 (when rtnall
5693 (insert "ALL CURRENTLY OPEN TODO ITEMS:\n")
5694 (add-text-properties (point-min) (1- (point))
5695 (list 'face 'org-level-3))
5696 (insert (org-finalize-agenda-entries rtnall) "\n")))
5697 (while (setq d (pop day-numbers))
5698 (setq date (calendar-gregorian-from-absolute d)
5699 s (point))
5700 (if (or (setq todayp (= d today))
5701 (and (not start-pos) (= d sd)))
5702 (setq start-pos (point))
5703 (if (and start-pos (not end-pos))
5704 (setq end-pos (point))))
5705 (setq files thefiles
5706 rtnall nil)
5707 (while (setq file (pop files))
5708 (catch 'nextfile
5709 (org-check-agenda-file file)
5710 (if org-agenda-show-log
5711 (setq rtn (org-agenda-get-day-entries
5712 file date
5713 :deadline :scheduled :timestamp :closed))
5714 (setq rtn (org-agenda-get-day-entries
5715 file date
5716 :deadline :scheduled :timestamp)))
5717 (setq rtnall (append rtnall rtn))))
5718 (if org-agenda-include-diary
5719 (progn
5720 (require 'diary-lib)
5721 (setq rtn (org-get-entries-from-diary date))
5722 (setq rtnall (append rtnall rtn))))
5723 (if (or rtnall org-agenda-show-all-dates)
5724 (progn
5725 (insert (format "%-9s %2d %s %4d\n"
5726 (calendar-day-name date)
5727 (extract-calendar-day date)
5728 (calendar-month-name (extract-calendar-month date))
5729 (extract-calendar-year date)))
5730 (put-text-property s (1- (point)) 'face
5731 'org-level-3)
5732 (if rtnall (insert
5733 (org-finalize-agenda-entries
5734 (org-agenda-add-time-grid-maybe
5735 rtnall nd todayp))
5736 "\n"))
5737 (put-text-property s (1- (point)) 'day d))))
5738 (goto-char (point-min))
5739 (setq buffer-read-only t)
5740 (org-fit-agenda-window)
5741 (unless (and (pos-visible-in-window-p (point-min))
5742 (pos-visible-in-window-p (point-max)))
5743 (goto-char (1- (point-max)))
5744 (recenter -1)
5745 (if (not (pos-visible-in-window-p (or start-pos 1)))
5746 (progn
5747 (goto-char (or start-pos 1))
5748 (recenter 1))))
5749 (goto-char (or start-pos 1))
5750 (if (not org-select-agenda-window) (select-window win))
5751 (message "")))
5753 (defvar org-select-this-todo-keyword nil)
5755 ;;;###autoload
5756 (defun org-todo-list (arg &optional keep-modes)
5757 "Show all TODO entries from all agenda file in a single list.
5758 The prefix arg can be used to select a specific TODO keyword and limit
5759 the list to these. When using \\[universal-argument], you will be prompted
5760 for a keyword. A numeric prefix directly selects the Nth keyword in
5761 `org-todo-keywords'."
5762 (interactive "P")
5763 (org-agenda-maybe-reset-markers 'force)
5764 (org-compile-prefix-format org-agenda-prefix-format)
5765 (let* ((org-agenda-keep-modes keep-modes)
5766 (today (time-to-days (current-time)))
5767 (date (calendar-gregorian-from-absolute today))
5768 (win (selected-window))
5769 (kwds org-todo-keywords)
5770 (completion-ignore-case t)
5771 (org-select-this-todo-keyword
5772 (if (stringp arg) arg
5773 (and arg (integerp arg) (> arg 0)
5774 (nth (1- arg) org-todo-keywords))))
5775 rtn rtnall files file pos)
5776 (when (equal arg '(4))
5777 (setq org-select-this-todo-keyword
5778 (completing-read "Keyword: " (mapcar 'list org-todo-keywords)
5779 nil t)))
5780 (and (equal 0 arg) (setq org-select-this-todo-keyword nil))
5781 (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name)))
5782 (progn
5783 (delete-other-windows)
5784 (switch-to-buffer-other-window
5785 (get-buffer-create org-agenda-buffer-name))))
5786 (setq buffer-read-only nil)
5787 (erase-buffer)
5788 (org-agenda-mode) (setq buffer-read-only nil)
5789 (set (make-local-variable 'org-agenda-type) 'todo)
5790 (set (make-local-variable 'last-arg) arg)
5791 (set (make-local-variable 'org-todo-keywords) kwds)
5792 (set (make-local-variable 'org-agenda-redo-command)
5793 '(org-todo-list (or current-prefix-arg last-arg) t))
5794 (setq files (org-agenda-files)
5795 rtnall nil)
5796 (while (setq file (pop files))
5797 (catch 'nextfile
5798 (org-check-agenda-file file)
5799 (setq rtn (org-agenda-get-day-entries file date :todo))
5800 (setq rtnall (append rtnall rtn))))
5801 (insert "Global list of TODO items of type: ")
5802 (add-text-properties (point-min) (1- (point))
5803 (list 'face 'org-level-3))
5804 (setq pos (point))
5805 (insert (or org-select-this-todo-keyword "ALL") "\n")
5806 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
5807 (setq pos (point))
5808 (insert
5809 "Available with `N r': (0)ALL "
5810 (let ((n 0))
5811 (mapconcat (lambda (x)
5812 (format "(%d)%s" (setq n (1+ n)) x))
5813 org-todo-keywords " "))
5814 "\n")
5815 (add-text-properties pos (1- (point)) (list 'face 'org-level-3))
5816 (when rtnall
5817 (insert (org-finalize-agenda-entries rtnall) "\n"))
5818 (goto-char (point-min))
5819 (setq buffer-read-only t)
5820 (org-fit-agenda-window)
5821 (if (not org-select-agenda-window) (select-window win))))
5823 (defun org-check-agenda-file (file)
5824 "Make sure FILE exists. If not, ask user what to do."
5825 (when (not (file-exists-p file))
5826 (message "non-existent file %s. [R]emove from list or [A]bort?"
5827 (abbreviate-file-name file))
5828 (let ((r (downcase (read-char-exclusive))))
5829 (cond
5830 ((equal r ?r)
5831 (org-remove-file file)
5832 (throw 'nextfile t))
5833 (t (error "Abort"))))))
5835 (defun org-agenda-check-type (error &rest types)
5836 "Check if agenda buffer is of allowed type.
5837 If ERROR is non-nil, throw an error, otherwise just return nil."
5838 (if (memq org-agenda-type types)
5840 (if error
5841 (error "Not allowed in %s-type agenda buffers" org-agenda-type)
5842 nil)))
5844 (defun org-agenda-quit ()
5845 "Exit agenda by removing the window or the buffer."
5846 (interactive)
5847 (let ((buf (current-buffer)))
5848 (if (not (one-window-p)) (delete-window))
5849 (kill-buffer buf)
5850 (org-agenda-maybe-reset-markers 'force)))
5852 (defun org-agenda-exit ()
5853 "Exit agenda by removing the window or the buffer.
5854 Also kill all Org-mode buffers which have been loaded by `org-agenda'.
5855 Org-mode buffers visited directly by the user will not be touched."
5856 (interactive)
5857 (org-release-buffers org-agenda-new-buffers)
5858 (setq org-agenda-new-buffers nil)
5859 (org-agenda-quit))
5861 (defun org-agenda-redo ()
5862 "Rebuild Agenda.
5863 When this is the global TODO list, a prefix argument will be interpreted."
5864 (interactive)
5865 (message "Rebuilding agenda buffer...")
5866 (eval org-agenda-redo-command)
5867 (message "Rebuilding agenda buffer...done"))
5869 (defun org-agenda-goto-today ()
5870 "Go to today."
5871 (interactive)
5872 (org-agenda-check-type t 'timeline 'agenda)
5873 (if (boundp 'starting-day)
5874 (let ((cmd (car org-agenda-redo-command))
5875 (iall (nth 1 org-agenda-redo-command))
5876 (nday (nth 3 org-agenda-redo-command))
5877 (keep (nth 4 org-agenda-redo-command)))
5878 (eval (list cmd iall nil nday keep)))
5879 (goto-char (or (text-property-any (point-min) (point-max) 'org-today t)
5880 (point-min)))))
5882 (defun org-agenda-later (arg)
5883 "Go forward in time by `org-agenda-ndays' days.
5884 With prefix ARG, go forward that many times `org-agenda-ndays'."
5885 (interactive "p")
5886 (org-agenda-check-type t 'agenda)
5887 (org-agenda-list (if (boundp 'include-all-loc) include-all-loc nil)
5888 (+ starting-day (* arg org-agenda-ndays)) nil t))
5890 (defun org-agenda-earlier (arg)
5891 "Go back in time by `org-agenda-ndays' days.
5892 With prefix ARG, go back that many times `org-agenda-ndays'."
5893 (interactive "p")
5894 (org-agenda-check-type t 'agenda)
5895 (org-agenda-list (if (boundp 'include-all-loc) include-all-loc nil)
5896 (- starting-day (* arg org-agenda-ndays)) nil t))
5898 (defun org-agenda-week-view ()
5899 "Switch to weekly view for agenda."
5900 (interactive)
5901 (org-agenda-check-type t 'agenda)
5902 (setq org-agenda-ndays 7)
5903 (org-agenda-list include-all-loc
5904 (or (get-text-property (point) 'day)
5905 starting-day)
5906 nil t)
5907 (org-agenda-set-mode-name)
5908 (message "Switched to week view"))
5910 (defun org-agenda-day-view ()
5911 "Switch to daily view for agenda."
5912 (interactive)
5913 (org-agenda-check-type t 'agenda)
5914 (setq org-agenda-ndays 1)
5915 (org-agenda-list include-all-loc
5916 (or (get-text-property (point) 'day)
5917 starting-day)
5918 nil t)
5919 (org-agenda-set-mode-name)
5920 (message "Switched to day view"))
5922 (defun org-agenda-next-date-line (&optional arg)
5923 "Jump to the next line indicating a date in agenda buffer."
5924 (interactive "p")
5925 (org-agenda-check-type t 'agenda 'timeline)
5926 (beginning-of-line 1)
5927 (if (looking-at "^\\S-") (forward-char 1))
5928 (if (not (re-search-forward "^\\S-" nil t arg))
5929 (progn
5930 (backward-char 1)
5931 (error "No next date after this line in this buffer")))
5932 (goto-char (match-beginning 0)))
5934 (defun org-agenda-previous-date-line (&optional arg)
5935 "Jump to the previous line indicating a date in agenda buffer."
5936 (interactive "p")
5937 (org-agenda-check-type t 'agenda 'timeline)
5938 (beginning-of-line 1)
5939 (if (not (re-search-backward "^\\S-" nil t arg))
5940 (error "No previous date before this line in this buffer")))
5942 ;; Initialize the highlight
5943 (defvar org-hl (org-make-overlay 1 1))
5944 (org-overlay-put org-hl 'face 'highlight)
5946 (defun org-highlight (begin end &optional buffer)
5947 "Highlight a region with overlay."
5948 (funcall (if (featurep 'xemacs) 'set-extent-endpoints 'move-overlay)
5949 org-hl begin end (or buffer (current-buffer))))
5951 (defun org-unhighlight ()
5952 "Detach overlay INDEX."
5953 (funcall (if (featurep 'xemacs) 'detach-extent 'delete-overlay) org-hl))
5956 (defun org-agenda-follow-mode ()
5957 "Toggle follow mode in an agenda buffer."
5958 (interactive)
5959 (setq org-agenda-follow-mode (not org-agenda-follow-mode))
5960 (org-agenda-set-mode-name)
5961 (message "Follow mode is %s"
5962 (if org-agenda-follow-mode "on" "off")))
5964 (defun org-agenda-log-mode ()
5965 "Toggle log mode in an agenda buffer."
5966 (interactive)
5967 (org-agenda-check-type t 'agenda 'timeline)
5968 (setq org-agenda-show-log (not org-agenda-show-log))
5969 (org-agenda-set-mode-name)
5970 (org-agenda-redo)
5971 (message "Log mode is %s"
5972 (if org-agenda-show-log "on" "off")))
5974 (defun org-agenda-toggle-diary ()
5975 "Toggle diary inclusion in an agenda buffer."
5976 (interactive)
5977 (org-agenda-check-type t 'agenda)
5978 (setq org-agenda-include-diary (not org-agenda-include-diary))
5979 (org-agenda-redo)
5980 (org-agenda-set-mode-name)
5981 (message "Diary inclusion turned %s"
5982 (if org-agenda-include-diary "on" "off")))
5984 (defun org-agenda-toggle-time-grid ()
5985 "Toggle time grid in an agenda buffer."
5986 (interactive)
5987 (org-agenda-check-type t 'agenda)
5988 (setq org-agenda-use-time-grid (not org-agenda-use-time-grid))
5989 (org-agenda-redo)
5990 (org-agenda-set-mode-name)
5991 (message "Time-grid turned %s"
5992 (if org-agenda-use-time-grid "on" "off")))
5994 (defun org-agenda-set-mode-name ()
5995 "Set the mode name to indicate all the small mode settings."
5996 (setq mode-name
5997 (concat "Org-Agenda"
5998 (if (equal org-agenda-ndays 1) " Day" "")
5999 (if (equal org-agenda-ndays 7) " Week" "")
6000 (if org-agenda-follow-mode " Follow" "")
6001 (if org-agenda-include-diary " Diary" "")
6002 (if org-agenda-use-time-grid " Grid" "")
6003 (if org-agenda-show-log " Log" "")))
6004 (force-mode-line-update))
6006 (defun org-agenda-post-command-hook ()
6007 (and (eolp) (not (bolp)) (backward-char 1))
6008 (if (and org-agenda-follow-mode
6009 (get-text-property (point) 'org-marker))
6010 (org-agenda-show)))
6012 (defvar org-disable-agenda-to-diary nil) ;Dynamically-scoped param.
6014 (defun org-get-entries-from-diary (date)
6015 "Get the (Emacs Calendar) diary entries for DATE."
6016 (let* ((fancy-diary-buffer "*temporary-fancy-diary-buffer*")
6017 (diary-display-hook '(fancy-diary-display))
6018 (list-diary-entries-hook
6019 (cons 'org-diary-default-entry list-diary-entries-hook))
6020 (diary-file-name-prefix-function nil) ; turn this feature off
6021 (diary-modify-entry-list-string-function 'org-modify-diary-entry-string)
6022 entries
6023 (org-disable-agenda-to-diary t))
6024 (save-excursion
6025 (save-window-excursion
6026 (list-diary-entries date 1))) ;; Keep this name for now, compatibility
6027 (if (not (get-buffer fancy-diary-buffer))
6028 (setq entries nil)
6029 (with-current-buffer fancy-diary-buffer
6030 (setq buffer-read-only nil)
6031 (if (= (point-max) 1)
6032 ;; No entries
6033 (setq entries nil)
6034 ;; Omit the date and other unnecessary stuff
6035 (org-agenda-cleanup-fancy-diary)
6036 ;; Add prefix to each line and extend the text properties
6037 (if (= (point-max) 1)
6038 (setq entries nil)
6039 (setq entries (buffer-substring (point-min) (- (point-max) 1)))))
6040 (set-buffer-modified-p nil)
6041 (kill-buffer fancy-diary-buffer)))
6042 (when entries
6043 (setq entries (org-split-string entries "\n"))
6044 (setq entries
6045 (mapcar
6046 (lambda (x)
6047 (setq x (org-format-agenda-item "" x "Diary" nil 'time))
6048 ;; Extend the text properties to the beginning of the line
6049 (org-add-props x (text-properties-at (1- (length x)) x)))
6050 entries)))))
6052 (defun org-agenda-cleanup-fancy-diary ()
6053 "Remove unwanted stuff in buffer created by `fancy-diary-display'.
6054 This gets rid of the date, the underline under the date, and
6055 the dummy entry installed by `org-mode' to ensure non-empty diary for each
6056 date. It also removes lines that contain only whitespace."
6057 (goto-char (point-min))
6058 (if (looking-at ".*?:[ \t]*")
6059 (progn
6060 (replace-match "")
6061 (re-search-forward "\n=+$" nil t)
6062 (replace-match "")
6063 (while (re-search-backward "^ +\n?" nil t) (replace-match "")))
6064 (re-search-forward "\n=+$" nil t)
6065 (delete-region (point-min) (min (point-max) (1+ (match-end 0)))))
6066 (goto-char (point-min))
6067 (while (re-search-forward "^ +\n" nil t)
6068 (replace-match ""))
6069 (goto-char (point-min))
6070 (if (re-search-forward "^Org-mode dummy\n?" nil t)
6071 (replace-match "")))
6073 ;; Make sure entries from the diary have the right text properties.
6074 (eval-after-load "diary-lib"
6075 '(if (boundp 'diary-modify-entry-list-string-function)
6076 ;; We can rely on the hook, nothing to do
6078 ;; Hook not avaiable, must use advice to make this work
6079 (defadvice add-to-diary-list (before org-mark-diary-entry activate)
6080 "Make the position visible."
6081 (if (and org-disable-agenda-to-diary ;; called from org-agenda
6082 (stringp string)
6083 buffer-file-name)
6084 (setq string (org-modify-diary-entry-string string))))))
6086 (defun org-modify-diary-entry-string (string)
6087 "Add text properties to string, allowing org-mode to act on it."
6088 (org-add-props string nil
6089 'mouse-face 'highlight
6090 'keymap org-agenda-keymap
6091 'help-echo (format "mouse-2 or RET jump to diary file %s"
6092 (abbreviate-file-name buffer-file-name))
6093 'org-agenda-diary-link t
6094 'org-marker (org-agenda-new-marker (point-at-bol))))
6096 (defun org-diary-default-entry ()
6097 "Add a dummy entry to the diary.
6098 Needed to avoid empty dates which mess up holiday display."
6099 ;; Catch the error if dealing with the new add-to-diary-alist
6100 (when org-disable-agenda-to-diary
6101 (condition-case nil
6102 (add-to-diary-list original-date "Org-mode dummy" "")
6103 (error
6104 (add-to-diary-list original-date "Org-mode dummy" "" nil)))))
6106 (defun org-cycle-agenda-files ()
6107 "Cycle through the files in `org-agenda-files'.
6108 If the current buffer visits an agenda file, find the next one in the list.
6109 If the current buffer does not, find the first agenda file."
6110 (interactive)
6111 (let* ((fs (org-agenda-files t))
6112 (files (append fs (list (car fs))))
6113 (tcf (if buffer-file-name (file-truename buffer-file-name)))
6114 file)
6115 (unless files (error "No agenda files"))
6116 (catch 'exit
6117 (while (setq file (pop files))
6118 (if (equal (file-truename file) tcf)
6119 (when (car files)
6120 (find-file (car files))
6121 (throw 'exit t))))
6122 (find-file (car fs)))))
6124 (defun org-agenda-file-to-end ()
6125 "Move/add the current file to the end of the agenda file list.
6126 If the file is not present in the list, it is appended to the list. If it is
6127 present, it is moved there."
6128 (interactive)
6129 (org-agenda-file-to-front 'to-end))
6131 (defun org-agenda-file-to-front (&optional to-end)
6132 "Move/add the current file to the top of the agenda file list.
6133 If the file is not present in the list, it is added to the front. If it is
6134 present, it is moved there. With optional argument TO-END, add/move to the
6135 end of the list."
6136 (interactive "P")
6137 (let ((file-alist (mapcar (lambda (x)
6138 (cons (file-truename x) x))
6139 (org-agenda-files t)))
6140 (ctf (file-truename buffer-file-name))
6141 x had)
6142 (setq x (assoc ctf file-alist) had x)
6144 (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name))))
6145 (if to-end
6146 (setq file-alist (append (delq x file-alist) (list x)))
6147 (setq file-alist (cons x (delq x file-alist))))
6148 (org-store-new-agenda-file-list (mapcar 'cdr file-alist))
6149 (org-install-agenda-files-menu)
6150 (message "File %s to %s of agenda file list"
6151 (if had "moved" "added") (if to-end "end" "front"))))
6153 (defun org-remove-file (&optional file)
6154 "Remove current file from the list of files in variable `org-agenda-files'.
6155 These are the files which are being checked for agenda entries.
6156 Optional argument FILE means, use this file instead of the current."
6157 (interactive)
6158 (let* ((file (or file buffer-file-name))
6159 (true-file (file-truename file))
6160 (afile (abbreviate-file-name file))
6161 (files (delq nil (mapcar
6162 (lambda (x)
6163 (if (equal true-file
6164 (file-truename x))
6165 nil x))
6166 (org-agenda-files t)))))
6167 (if (not (= (length files) (length (org-agenda-files t))))
6168 (progn
6169 (org-store-new-agenda-file-list files)
6170 (org-install-agenda-files-menu)
6171 (message "Removed file: %s" afile))
6172 (message "File was not in list: %s" afile))))
6174 (defun org-file-menu-entry (file)
6175 (vector file (list 'find-file file) t))
6177 (defun org-get-all-dates (beg end &optional no-ranges force-today inactive)
6178 "Return a list of all relevant day numbers from BEG to END buffer positions.
6179 If NO-RANGES is non-nil, include only the start and end dates of a range,
6180 not every single day in the range. If FORCE-TODAY is non-nil, make
6181 sure that TODAY is included in the list. If INACTIVE is non-nil, also
6182 inactive time stamps (those in square brackets) are included."
6183 (let ((re (if inactive org-ts-regexp-both org-ts-regexp))
6184 dates date day day1 day2 ts1 ts2)
6185 (if force-today
6186 (setq dates (list (time-to-days (current-time)))))
6187 (save-excursion
6188 (goto-char beg)
6189 (while (re-search-forward re end t)
6190 (setq day (time-to-days (org-time-string-to-time
6191 (substring (match-string 1) 0 10))))
6192 (or (memq day dates) (push day dates)))
6193 (unless no-ranges
6194 (goto-char beg)
6195 (while (re-search-forward org-tr-regexp end t)
6196 (setq ts1 (substring (match-string 1) 0 10)
6197 ts2 (substring (match-string 2) 0 10)
6198 day1 (time-to-days (org-time-string-to-time ts1))
6199 day2 (time-to-days (org-time-string-to-time ts2)))
6200 (while (< (setq day1 (1+ day1)) day2)
6201 (or (memq day1 dates) (push day1 dates)))))
6202 (sort dates '<))))
6204 ;;;###autoload
6205 (defun org-diary (&rest args)
6206 "Return diary information from org-files.
6207 This function can be used in a \"sexp\" diary entry in the Emacs calendar.
6208 It accesses org files and extracts information from those files to be
6209 listed in the diary. The function accepts arguments specifying what
6210 items should be listed. The following arguments are allowed:
6212 :timestamp List the headlines of items containing a date stamp or
6213 date range matching the selected date. Deadlines will
6214 also be listed, on the expiration day.
6216 :deadline List any deadlines past due, or due within
6217 `org-deadline-warning-days'. The listing occurs only
6218 in the diary for *today*, not at any other date. If
6219 an entry is marked DONE, it is no longer listed.
6221 :scheduled List all items which are scheduled for the given date.
6222 The diary for *today* also contains items which were
6223 scheduled earlier and are not yet marked DONE.
6225 :todo List all TODO items from the org-file. This may be a
6226 long list - so this is not turned on by default.
6227 Like deadlines, these entries only show up in the
6228 diary for *today*, not at any other date.
6230 The call in the diary file should look like this:
6232 &%%(org-diary) ~/path/to/some/orgfile.org
6234 Use a separate line for each org file to check. Or, if you omit the file name,
6235 all files listed in `org-agenda-files' will be checked automatically:
6237 &%%(org-diary)
6239 If you don't give any arguments (as in the example above), the default
6240 arguments (:deadline :scheduled :timestamp) are used. So the example above may
6241 also be written as
6243 &%%(org-diary :deadline :timestamp :scheduled)
6245 The function expects the lisp variables `entry' and `date' to be provided
6246 by the caller, because this is how the calendar works. Don't use this
6247 function from a program - use `org-agenda-get-day-entries' instead."
6248 (org-agenda-maybe-reset-markers)
6249 (org-compile-prefix-format org-agenda-prefix-format)
6250 (setq args (or args '(:deadline :scheduled :timestamp)))
6251 (let* ((files (if (and entry (stringp entry) (string-match "\\S-" entry))
6252 (list entry)
6253 (org-agenda-files t)))
6254 file rtn results)
6255 ;; If this is called during org-agenda, don't return any entries to
6256 ;; the calendar. Org Agenda will list these entries itself.
6257 (if org-disable-agenda-to-diary (setq files nil))
6258 (while (setq file (pop files))
6259 (setq rtn (apply 'org-agenda-get-day-entries file date args))
6260 (setq results (append results rtn)))
6261 (if results
6262 (concat (org-finalize-agenda-entries results) "\n"))))
6263 (defvar org-category-table nil)
6264 (defun org-get-category-table ()
6265 "Get the table of categories and positions in current buffer."
6266 (let (tbl)
6267 (save-excursion
6268 (goto-char (point-min))
6269 (while (re-search-forward "\\(^\\|\r\\)#\\+CATEGORY:[ \t]*\\(.*\\)" nil t)
6270 (push (cons (point) (org-trim (match-string 2))) tbl)))
6271 tbl))
6272 (defun org-get-category (&optional pos)
6273 "Get the category applying to position POS."
6274 (if (not org-category-table)
6275 (cond
6276 ((null org-category)
6277 (setq org-category
6278 (if buffer-file-name
6279 (file-name-sans-extension
6280 (file-name-nondirectory buffer-file-name))
6281 "???")))
6282 ((symbolp org-category) (symbol-name org-category))
6283 (t org-category))
6284 (let ((tbl org-category-table)
6285 (pos (or pos (point))))
6286 (while (and tbl (> (caar tbl) pos))
6287 (pop tbl))
6288 (or (cdar tbl) (cdr (nth (1- (length org-category-table))
6289 org-category-table))))))
6291 (defun org-agenda-get-day-entries (file date &rest args)
6292 "Does the work for `org-diary' and `org-agenda'.
6293 FILE is the path to a file to be checked for entries. DATE is date like
6294 the one returned by `calendar-current-date'. ARGS are symbols indicating
6295 which kind of entries should be extracted. For details about these, see
6296 the documentation of `org-diary'."
6297 (setq args (or args '(:deadline :scheduled :timestamp)))
6298 (let* ((org-startup-with-deadline-check nil)
6299 (org-startup-folded nil)
6300 (org-startup-align-all-tables nil)
6301 (buffer (if (file-exists-p file)
6302 (org-get-agenda-file-buffer file)
6303 (error "No such file %s" file)))
6304 arg results rtn)
6305 (if (not buffer)
6306 ;; If file does not exist, make sure an error message ends up in diary
6307 (list (format "ORG-AGENDA-ERROR: No such org-file %s" file))
6308 (with-current-buffer buffer
6309 (unless (eq major-mode 'org-mode)
6310 (error "Agenda file %s is not in `org-mode'" file))
6311 (setq org-category-table (org-get-category-table))
6312 (let ((case-fold-search nil))
6313 (save-excursion
6314 (save-restriction
6315 (if org-respect-restriction
6316 (if (org-region-active-p)
6317 ;; Respect a region to restrict search
6318 (narrow-to-region (region-beginning) (region-end)))
6319 ;; If we work for the calendar or many files,
6320 ;; get rid of any restriction
6321 (widen))
6322 ;; The way we repeatedly append to `results' makes it O(n^2) :-(
6323 (while (setq arg (pop args))
6324 (cond
6325 ((and (eq arg :todo)
6326 (equal date (calendar-current-date)))
6327 (setq rtn (org-agenda-get-todos))
6328 (setq results (append results rtn)))
6329 ((eq arg :timestamp)
6330 (setq rtn (org-agenda-get-blocks))
6331 (setq results (append results rtn))
6332 (setq rtn (org-agenda-get-timestamps))
6333 (setq results (append results rtn)))
6334 ((eq arg :scheduled)
6335 (setq rtn (org-agenda-get-scheduled))
6336 (setq results (append results rtn)))
6337 ((eq arg :closed)
6338 (setq rtn (org-agenda-get-closed))
6339 (setq results (append results rtn)))
6340 ((and (eq arg :deadline)
6341 (equal date (calendar-current-date)))
6342 (setq rtn (org-agenda-get-deadlines))
6343 (setq results (append results rtn))))))))
6344 results))))
6346 (defun org-entry-is-done-p ()
6347 "Is the current entry marked DONE?"
6348 (save-excursion
6349 (and (re-search-backward "[\r\n]\\*" nil t)
6350 (looking-at org-nl-done-regexp))))
6352 (defun org-at-date-range-p ()
6353 "Is the cursor inside a date range?"
6354 (interactive)
6355 (save-excursion
6356 (catch 'exit
6357 (let ((pos (point)))
6358 (skip-chars-backward "^<\r\n")
6359 (skip-chars-backward "<")
6360 (and (looking-at org-tr-regexp)
6361 (>= (match-end 0) pos)
6362 (throw 'exit t))
6363 (skip-chars-backward "^<\r\n")
6364 (skip-chars-backward "<")
6365 (and (looking-at org-tr-regexp)
6366 (>= (match-end 0) pos)
6367 (throw 'exit t)))
6368 nil)))
6370 (defun org-agenda-get-todos ()
6371 "Return the TODO information for agenda display."
6372 (let* ((props (list 'face nil
6373 'done-face 'org-done
6374 'org-not-done-regexp org-not-done-regexp
6375 'mouse-face 'highlight
6376 'keymap org-agenda-keymap
6377 'help-echo
6378 (format "mouse-2 or RET jump to org file %s"
6379 (abbreviate-file-name buffer-file-name))))
6380 (regexp (concat "[\n\r]\\*+ *\\("
6381 (if org-select-this-todo-keyword
6382 (concat "\\<\\(" org-select-this-todo-keyword
6383 "\\)\\>")
6384 org-not-done-regexp)
6385 "[^\n\r]*\\)"))
6386 (sched-re (concat ".*\n.*?" org-scheduled-time-regexp))
6387 marker priority category tags
6388 ee txt)
6389 (goto-char (point-min))
6390 (while (re-search-forward regexp nil t)
6391 (when (not (and org-agenda-todo-ignore-scheduled
6392 (save-match-data (looking-at sched-re))))
6393 (goto-char (match-beginning 1))
6394 (setq marker (org-agenda-new-marker (1+ (match-beginning 0)))
6395 category (org-get-category)
6396 tags (org-get-tags-at (point))
6397 txt (org-format-agenda-item "" (match-string 1) category tags)
6398 priority
6399 (+ (org-get-priority txt)
6400 (if org-todo-kwd-priority-p
6401 (- org-todo-kwd-max-priority -2
6402 (length
6403 (member (match-string 2) org-todo-keywords)))
6404 1)))
6405 (org-add-props txt props
6406 'org-marker marker 'org-hd-marker marker
6407 'priority priority 'category category)
6408 (push txt ee)
6409 (if org-agenda-todo-list-sublevels
6410 (goto-char (match-end 1))
6411 (org-end-of-subtree 'invisible))))
6412 (nreverse ee)))
6414 (defconst org-agenda-no-heading-message
6415 "No heading for this item in buffer or region.")
6417 (defun org-agenda-get-timestamps ()
6418 "Return the date stamp information for agenda display."
6419 (let* ((props (list 'face nil
6420 'org-not-done-regexp org-not-done-regexp
6421 'mouse-face 'highlight
6422 'keymap org-agenda-keymap
6423 'help-echo
6424 (format "mouse-2 or RET jump to org file %s"
6425 (abbreviate-file-name buffer-file-name))))
6426 (regexp (regexp-quote
6427 (substring
6428 (format-time-string
6429 (car org-time-stamp-formats)
6430 (apply 'encode-time ; DATE bound by calendar
6431 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
6432 0 11)))
6433 marker hdmarker deadlinep scheduledp donep tmp priority category
6434 ee txt timestr tags)
6435 (goto-char (point-min))
6436 (while (re-search-forward regexp nil t)
6437 (if (not (save-match-data (org-at-date-range-p)))
6438 (progn
6439 (setq marker (org-agenda-new-marker (match-beginning 0))
6440 category (org-get-category (match-beginning 0))
6441 tmp (buffer-substring (max (point-min)
6442 (- (match-beginning 0)
6443 org-ds-keyword-length))
6444 (match-beginning 0))
6445 timestr (buffer-substring (match-beginning 0) (point-at-eol))
6446 deadlinep (string-match org-deadline-regexp tmp)
6447 scheduledp (string-match org-scheduled-regexp tmp)
6448 donep (org-entry-is-done-p))
6449 (if (string-match ">" timestr)
6450 ;; substring should only run to end of time stamp
6451 (setq timestr (substring timestr 0 (match-end 0))))
6452 (save-excursion
6453 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
6454 (progn
6455 (goto-char (match-end 1))
6456 (setq hdmarker (org-agenda-new-marker)
6457 tags (org-get-tags-at))
6458 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
6459 (setq txt (org-format-agenda-item
6460 (format "%s%s"
6461 (if deadlinep "Deadline: " "")
6462 (if scheduledp "Scheduled: " ""))
6463 (match-string 1) category tags timestr)))
6464 (setq txt org-agenda-no-heading-message))
6465 (setq priority (org-get-priority txt))
6466 (org-add-props txt props
6467 'org-marker marker 'org-hd-marker hdmarker)
6468 (if deadlinep
6469 (org-add-props txt nil
6470 'face (if donep 'org-done 'org-warning)
6471 'undone-face 'org-warning 'done-face 'org-done
6472 'category category 'priority (+ 100 priority))
6473 (if scheduledp
6474 (org-add-props txt nil
6475 'face 'org-scheduled-today
6476 'undone-face 'org-scheduled-today 'done-face 'org-done
6477 'category category 'priority (+ 99 priority))
6478 (org-add-props txt nil 'priority priority 'category category)))
6479 (push txt ee))
6480 (outline-next-heading))))
6481 (nreverse ee)))
6483 (defun org-agenda-get-closed ()
6484 "Return the logged TODO entries for agenda display."
6485 (let* ((props (list 'mouse-face 'highlight
6486 'org-not-done-regexp org-not-done-regexp
6487 'keymap org-agenda-keymap
6488 'help-echo
6489 (format "mouse-2 or RET jump to org file %s"
6490 (abbreviate-file-name buffer-file-name))))
6491 (regexp (concat
6492 "\\<" org-closed-string " *\\["
6493 (regexp-quote
6494 (substring
6495 (format-time-string
6496 (car org-time-stamp-formats)
6497 (apply 'encode-time ; DATE bound by calendar
6498 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
6499 1 11))))
6500 marker hdmarker priority category tags
6501 ee txt timestr)
6502 (goto-char (point-min))
6503 (while (re-search-forward regexp nil t)
6504 (if (not (save-match-data (org-at-date-range-p)))
6505 (progn
6506 (setq marker (org-agenda-new-marker (match-beginning 0))
6507 category (org-get-category (match-beginning 0))
6508 timestr (buffer-substring (match-beginning 0) (point-at-eol))
6509 ;; donep (org-entry-is-done-p)
6511 (if (string-match "\\]" timestr)
6512 ;; substring should only run to end of time stamp
6513 (setq timestr (substring timestr 0 (match-end 0))))
6514 (save-excursion
6515 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
6516 (progn
6517 (goto-char (match-end 1))
6518 (setq hdmarker (org-agenda-new-marker)
6519 tags (org-get-tags-at))
6520 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
6521 (setq txt (org-format-agenda-item
6522 "Closed: "
6523 (match-string 1) category tags timestr)))
6524 (setq txt org-agenda-no-heading-message))
6525 (setq priority 100000)
6526 (org-add-props txt props
6527 'org-marker marker 'org-hd-marker hdmarker 'face 'org-done
6528 'priority priority 'category category
6529 'undone-face 'org-warning 'done-face 'org-done)
6530 (push txt ee))
6531 (outline-next-heading))))
6532 (nreverse ee)))
6534 (defun org-agenda-get-deadlines ()
6535 "Return the deadline information for agenda display."
6536 (let* ((wdays org-deadline-warning-days)
6537 (props (list 'mouse-face 'highlight
6538 'org-not-done-regexp org-not-done-regexp
6539 'keymap org-agenda-keymap
6540 'help-echo
6541 (format "mouse-2 or RET jump to org file %s"
6542 (abbreviate-file-name buffer-file-name))))
6543 (regexp org-deadline-time-regexp)
6544 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
6545 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
6546 d2 diff pos pos1 category tags
6547 ee txt head)
6548 (goto-char (point-min))
6549 (while (re-search-forward regexp nil t)
6550 (setq pos (1- (match-beginning 1))
6551 d2 (time-to-days
6552 (org-time-string-to-time (match-string 1)))
6553 diff (- d2 d1))
6554 ;; When to show a deadline in the calendar:
6555 ;; If the expiration is within wdays warning time.
6556 ;; Past-due deadlines are only shown on the current date
6557 (if (and (< diff wdays) todayp (not (= diff 0)))
6558 (save-excursion
6559 (setq category (org-get-category))
6560 (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t)
6561 (progn
6562 (goto-char (match-end 0))
6563 (setq pos1 (match-end 1))
6564 (setq tags (org-get-tags-at pos1))
6565 (setq head (buffer-substring-no-properties
6566 (point)
6567 (progn (skip-chars-forward "^\r\n")
6568 (point))))
6569 (if (string-match org-looking-at-done-regexp head)
6570 (setq txt nil)
6571 (setq txt (org-format-agenda-item
6572 (format "In %3d d.: " diff) head category tags))))
6573 (setq txt org-agenda-no-heading-message))
6574 (when txt
6575 (org-add-props txt props
6576 'org-marker (org-agenda-new-marker pos)
6577 'org-hd-marker (org-agenda-new-marker pos1)
6578 'priority (+ (- 10 diff) (org-get-priority txt))
6579 'category category
6580 'face (cond ((<= diff 0) 'org-warning)
6581 ((<= diff 5) 'org-scheduled-previously)
6582 (t nil))
6583 'undone-face (cond
6584 ((<= diff 0) 'org-warning)
6585 ((<= diff 5) 'org-scheduled-previously)
6586 (t nil))
6587 'done-face 'org-done)
6588 (push txt ee)))))
6589 ee))
6591 (defun org-agenda-get-scheduled ()
6592 "Return the scheduled information for agenda display."
6593 (let* ((props (list 'face 'org-scheduled-previously
6594 'org-not-done-regexp org-not-done-regexp
6595 'undone-face 'org-scheduled-previously
6596 'done-face 'org-done
6597 'mouse-face 'highlight
6598 'keymap org-agenda-keymap
6599 'help-echo
6600 (format "mouse-2 or RET jump to org file %s"
6601 (abbreviate-file-name buffer-file-name))))
6602 (regexp org-scheduled-time-regexp)
6603 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
6604 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
6605 d2 diff pos pos1 category tags
6606 ee txt head)
6607 (goto-char (point-min))
6608 (while (re-search-forward regexp nil t)
6609 (setq pos (1- (match-beginning 1))
6610 d2 (time-to-days
6611 (org-time-string-to-time (match-string 1)))
6612 diff (- d2 d1))
6613 ;; When to show a scheduled item in the calendar:
6614 ;; If it is on or past the date.
6615 (if (and (< diff 0) todayp)
6616 (save-excursion
6617 (setq category (org-get-category))
6618 (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t)
6619 (progn
6620 (goto-char (match-end 0))
6621 (setq pos1 (match-end 1))
6622 (setq tags (org-get-tags-at))
6623 (setq head (buffer-substring-no-properties
6624 (point)
6625 (progn (skip-chars-forward "^\r\n") (point))))
6626 (if (string-match org-looking-at-done-regexp head)
6627 (setq txt nil)
6628 (setq txt (org-format-agenda-item
6629 (format "Sched.%2dx: " (- 1 diff)) head
6630 category tags))))
6631 (setq txt org-agenda-no-heading-message))
6632 (when txt
6633 (org-add-props txt props
6634 'org-marker (org-agenda-new-marker pos)
6635 'org-hd-marker (org-agenda-new-marker pos1)
6636 'priority (+ (- 5 diff) (org-get-priority txt))
6637 'category category)
6638 (push txt ee)))))
6639 ee))
6641 (defun org-agenda-get-blocks ()
6642 "Return the date-range information for agenda display."
6643 (let* ((props (list 'face nil
6644 'org-not-done-regexp org-not-done-regexp
6645 'mouse-face 'highlight
6646 'keymap org-agenda-keymap
6647 'help-echo
6648 (format "mouse-2 or RET jump to org file %s"
6649 (abbreviate-file-name buffer-file-name))))
6650 (regexp org-tr-regexp)
6651 (d0 (calendar-absolute-from-gregorian date))
6652 marker hdmarker ee txt d1 d2 s1 s2 timestr category tags)
6653 (goto-char (point-min))
6654 (while (re-search-forward regexp nil t)
6655 (setq timestr (match-string 0)
6656 s1 (match-string 1)
6657 s2 (match-string 2)
6658 d1 (time-to-days (org-time-string-to-time s1))
6659 d2 (time-to-days (org-time-string-to-time s2)))
6660 (if (and (> (- d0 d1) -1) (> (- d2 d0) -1))
6661 ;; Only allow days between the limits, because the normal
6662 ;; date stamps will catch the limits.
6663 (save-excursion
6664 (setq marker (org-agenda-new-marker (point)))
6665 (setq category (org-get-category))
6666 (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t)
6667 (progn
6668 (setq hdmarker (org-agenda-new-marker (match-end 1)))
6669 (goto-char (match-end 1))
6670 (setq tags (org-get-tags-at))
6671 (looking-at "\\*+[ \t]*\\([^\r\n]+\\)")
6672 (setq txt (org-format-agenda-item
6673 (format (if (= d1 d2) "" "(%d/%d): ")
6674 (1+ (- d0 d1)) (1+ (- d2 d1)))
6675 (match-string 1) category tags
6676 (if (= d0 d1) timestr))))
6677 (setq txt org-agenda-no-heading-message))
6678 (org-add-props txt props
6679 'org-marker marker 'org-hd-marker hdmarker
6680 'priority (org-get-priority txt) 'category category)
6681 (push txt ee)))
6682 (outline-next-heading))
6683 ;; Sort the entries by expiration date.
6684 (nreverse ee)))
6686 (defconst org-plain-time-of-day-regexp
6687 (concat
6688 "\\(\\<[012]?[0-9]"
6689 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
6690 "\\(--?"
6691 "\\(\\<[012]?[0-9]"
6692 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
6693 "\\)?")
6694 "Regular expression to match a plain time or time range.
6695 Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
6696 groups carry important information:
6697 0 the full match
6698 1 the first time, range or not
6699 8 the second time, if it is a range.")
6701 (defconst org-stamp-time-of-day-regexp
6702 (concat
6703 "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +[a-zA-Z]+ +\\)"
6704 "\\([012][0-9]:[0-5][0-9]\\)>"
6705 "\\(--?"
6706 "<\\1\\([012][0-9]:[0-5][0-9]\\)>\\)?")
6707 "Regular expression to match a timestamp time or time range.
6708 After a match, the following groups carry important information:
6709 0 the full match
6710 1 date plus weekday, for backreferencing to make sure both times on same day
6711 2 the first time, range or not
6712 4 the second time, if it is a range.")
6714 (defvar org-prefix-has-time nil
6715 "A flag, set by `org-compile-prefix-format'.
6716 The flag is set if the currently compiled format contains a `%t'.")
6717 (defvar org-prefix-has-tag nil
6718 "A flag, set by `org-compile-prefix-format'.
6719 The flag is set if the currently compiled format contains a `%T'.")
6721 (defun org-format-agenda-item (extra txt &optional category tags dotime noprefix)
6722 "Format TXT to be inserted into the agenda buffer.
6723 In particular, it adds the prefix and corresponding text properties. EXTRA
6724 must be a string and replaces the `%s' specifier in the prefix format.
6725 CATEGORY (string, symbol or nil) may be used to overrule the default
6726 category taken from local variable or file name. It will replace the `%c'
6727 specifier in the format. DOTIME, when non-nil, indicates that a
6728 time-of-day should be extracted from TXT for sorting of this entry, and for
6729 the `%t' specifier in the format. When DOTIME is a string, this string is
6730 searched for a time before TXT is. NOPREFIX is a flag and indicates that
6731 only the correctly processes TXT should be returned - this is used by
6732 `org-agenda-change-all-lines'. TAG can be the tag of the headline."
6733 (save-match-data
6734 ;; Diary entries sometimes have extra whitespace at the beginning
6735 (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt)))
6736 (let* ((category (or category
6737 org-category
6738 (if buffer-file-name
6739 (file-name-sans-extension
6740 (file-name-nondirectory buffer-file-name))
6741 "")))
6742 (tag (if tags (nth (1- (length tags)) tags) ""))
6743 time ;; needed for the eval of the prefix format
6744 (ts (if dotime (concat (if (stringp dotime) dotime "") txt)))
6745 (time-of-day (and dotime (org-get-time-of-day ts)))
6746 stamp plain s0 s1 s2 rtn)
6747 (when (and dotime time-of-day org-prefix-has-time)
6748 ;; Extract starting and ending time and move them to prefix
6749 (when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts))
6750 (setq plain (string-match org-plain-time-of-day-regexp ts)))
6751 (setq s0 (match-string 0 ts)
6752 s1 (match-string (if plain 1 2) ts)
6753 s2 (match-string (if plain 8 4) ts))
6755 ;; If the times are in TXT (not in DOTIMES), and the prefix will list
6756 ;; them, we might want to remove them there to avoid duplication.
6757 ;; The user can turn this off with a variable.
6758 (if (and org-agenda-remove-times-when-in-prefix (or stamp plain)
6759 (string-match (concat (regexp-quote s0) " *") txt)
6760 (if (eq org-agenda-remove-times-when-in-prefix 'beg)
6761 (= (match-beginning 0) 0)
6763 (setq txt (replace-match "" nil nil txt))))
6764 ;; Normalize the time(s) to 24 hour
6765 (if s1 (setq s1 (org-get-time-of-day s1 'string)))
6766 (if s2 (setq s2 (org-get-time-of-day s2 'string))))
6768 (when (string-match "\\([ \t]+\\)\\(:[a-zA-Z_@0-9:]+:\\)[ \t]*$" txt)
6769 ;; Tags are in the string
6770 (if (or (eq org-agenda-remove-tags-when-in-prefix t)
6771 (and org-agenda-remove-tags-when-in-prefix
6772 org-prefix-has-tag))
6773 (setq txt (replace-match "" t t txt))
6774 (setq txt (replace-match
6775 (concat (make-string (max (- 50 (length txt)) 1) ?\ )
6776 (match-string 2 txt))
6777 t t txt))))
6779 ;; Create the final string
6780 (if noprefix
6781 (setq rtn txt)
6782 ;; Prepare the variables needed in the eval of the compiled format
6783 (setq time (cond (s2 (concat s1 "-" s2))
6784 (s1 (concat s1 "......"))
6785 (t ""))
6786 extra (or extra "")
6787 category (if (symbolp category) (symbol-name category) category))
6788 ;; Evaluate the compiled format
6789 (setq rtn (concat (eval org-prefix-format-compiled) txt)))
6791 ;; And finally add the text properties
6792 (org-add-props rtn nil
6793 'category (downcase category) 'tags tags
6794 'prefix-length (- (length rtn) (length txt))
6795 'time-of-day time-of-day
6796 'dotime dotime))))
6798 (defun org-agenda-add-time-grid-maybe (list ndays todayp)
6799 (catch 'exit
6800 (cond ((not org-agenda-use-time-grid) (throw 'exit list))
6801 ((and todayp (member 'today (car org-agenda-time-grid))))
6802 ((and (= ndays 1) (member 'daily (car org-agenda-time-grid))))
6803 ((member 'weekly (car org-agenda-time-grid)))
6804 (t (throw 'exit list)))
6805 (let* ((have (delq nil (mapcar
6806 (lambda (x) (get-text-property 1 'time-of-day x))
6807 list)))
6808 (string (nth 1 org-agenda-time-grid))
6809 (gridtimes (nth 2 org-agenda-time-grid))
6810 (req (car org-agenda-time-grid))
6811 (remove (member 'remove-match req))
6812 new time)
6813 (if (and (member 'require-timed req) (not have))
6814 ;; don't show empty grid
6815 (throw 'exit list))
6816 (while (setq time (pop gridtimes))
6817 (unless (and remove (member time have))
6818 (setq time (int-to-string time))
6819 (push (org-format-agenda-item
6820 nil string "" nil
6821 (concat (substring time 0 -2) ":" (substring time -2)))
6822 new)
6823 (put-text-property
6824 1 (length (car new)) 'face 'org-time-grid (car new))))
6825 (if (member 'time-up org-agenda-sorting-strategy)
6826 (append new list)
6827 (append list new)))))
6829 (defun org-compile-prefix-format (format)
6830 "Compile the prefix format into a Lisp form that can be evaluated.
6831 The resulting form is returned and stored in the variable
6832 `org-prefix-format-compiled'."
6833 (setq org-prefix-has-time nil org-prefix-has-tag nil)
6834 (let ((start 0) varform vars var (s format)e c f opt)
6835 (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([cts]\\)"
6836 s start)
6837 (setq var (cdr (assoc (match-string 4 s)
6838 '(("c" . category) ("t" . time) ("s" . extra)
6839 ("T" . tag))))
6840 c (or (match-string 3 s) "")
6841 opt (match-beginning 1)
6842 start (1+ (match-beginning 0)))
6843 (if (equal var 'time) (setq org-prefix-has-time t))
6844 (if (equal var 'tag) (setq org-prefix-has-tag t))
6845 (setq f (concat "%" (match-string 2 s) "s"))
6846 (if opt
6847 (setq varform
6848 `(if (equal "" ,var)
6850 (format ,f (if (equal "" ,var) "" (concat ,var ,c)))))
6851 (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c)))))
6852 (setq s (replace-match "%s" t nil s))
6853 (push varform vars))
6854 (setq vars (nreverse vars))
6855 (setq org-prefix-format-compiled `(format ,s ,@vars))))
6857 (defun org-get-time-of-day (s &optional string)
6858 "Check string S for a time of day.
6859 If found, return it as a military time number between 0 and 2400.
6860 If not found, return nil.
6861 The optional STRING argument forces conversion into a 5 character wide string
6862 HH:MM."
6863 (save-match-data
6864 (when
6866 (string-match
6867 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)\\([AaPp][Mm]\\)?\\> *" s)
6868 (string-match
6869 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\([AaPp][Mm]\\)\\> *" s))
6870 (let* ((t0 (+ (* 100
6871 (+ (string-to-number (match-string 1 s))
6872 (if (and (match-beginning 4)
6873 (equal (downcase (match-string 4 s)) "pm"))
6874 12 0)))
6875 (if (match-beginning 3)
6876 (string-to-number (match-string 3 s))
6877 0)))
6878 (t1 (concat " "
6879 (if (< t0 100) "0" "") (if (< t0 10) "0" "")
6880 (int-to-string t0))))
6881 (if string (concat (substring t1 -4 -2) ":" (substring t1 -2)) t0)))))
6883 (defun org-finalize-agenda-entries (list)
6884 "Sort and concatenate the agenda items."
6885 (setq list (mapcar 'org-agenda-highlight-todo list))
6886 (mapconcat 'identity (sort list 'org-entries-lessp) "\n"))
6888 (defun org-agenda-highlight-todo (x)
6889 (let (re)
6890 (if (eq x 'line)
6891 (save-excursion
6892 (beginning-of-line 1)
6893 (setq re (get-text-property (point) 'org-not-done-regexp))
6894 (goto-char (+ (point) (get-text-property (point) 'prefix-length)))
6895 (and (looking-at (concat "[ \t]*" re))
6896 (add-text-properties (match-beginning 0) (match-end 0)
6897 '(face org-todo))))
6898 (setq re (get-text-property 0 'org-not-done-regexp x))
6899 (and re (string-match re x)
6900 (add-text-properties (match-beginning 0) (match-end 0)
6901 '(face org-todo) x))
6902 x)))
6904 (defsubst org-cmp-priority (a b)
6905 "Compare the priorities of string A and B."
6906 (let ((pa (or (get-text-property 1 'priority a) 0))
6907 (pb (or (get-text-property 1 'priority b) 0)))
6908 (cond ((> pa pb) +1)
6909 ((< pa pb) -1)
6910 (t nil))))
6912 (defsubst org-cmp-category (a b)
6913 "Compare the string values of categories of strings A and B."
6914 (let ((ca (or (get-text-property 1 'category a) ""))
6915 (cb (or (get-text-property 1 'category b) "")))
6916 (cond ((string-lessp ca cb) -1)
6917 ((string-lessp cb ca) +1)
6918 (t nil))))
6920 (defsubst org-cmp-time (a b)
6921 "Compare the time-of-day values of strings A and B."
6922 (let* ((def (if org-sort-agenda-notime-is-late 2401 -1))
6923 (ta (or (get-text-property 1 'time-of-day a) def))
6924 (tb (or (get-text-property 1 'time-of-day b) def)))
6925 (cond ((< ta tb) -1)
6926 ((< tb ta) +1)
6927 (t nil))))
6929 (defun org-entries-lessp (a b)
6930 "Predicate for sorting agenda entries."
6931 ;; The following variables will be used when the form is evaluated.
6932 (let* ((time-up (org-cmp-time a b))
6933 (time-down (if time-up (- time-up) nil))
6934 (priority-up (org-cmp-priority a b))
6935 (priority-down (if priority-up (- priority-up) nil))
6936 (category-up (org-cmp-category a b))
6937 (category-down (if category-up (- category-up) nil))
6938 (category-keep (if category-up +1 nil)))
6939 (cdr (assoc
6940 (eval (cons 'or org-agenda-sorting-strategy))
6941 '((-1 . t) (1 . nil) (nil . nil))))))
6943 (defun org-agenda-show-priority ()
6944 "Show the priority of the current item.
6945 This priority is composed of the main priority given with the [#A] cookies,
6946 and by additional input from the age of a schedules or deadline entry."
6947 (interactive)
6948 (let* ((pri (get-text-property (point-at-bol) 'priority)))
6949 (message "Priority is %d" (if pri pri -1000))))
6951 (defun org-agenda-show-tags ()
6952 "Show the tags applicable to the current item."
6953 (interactive)
6954 (let* ((tags (get-text-property (point-at-bol) 'tags)))
6955 (if tags
6956 (message "Tags are :%s:"
6957 (org-no-properties (mapconcat 'identity tags ":")))
6958 (message "No tags associated with this line"))))
6960 (defun org-agenda-goto (&optional highlight)
6961 "Go to the Org-mode file which contains the item at point."
6962 (interactive)
6963 (let* ((marker (or (get-text-property (point) 'org-marker)
6964 (org-agenda-error)))
6965 (buffer (marker-buffer marker))
6966 (pos (marker-position marker)))
6967 (switch-to-buffer-other-window buffer)
6968 (widen)
6969 (goto-char pos)
6970 (when (eq major-mode 'org-mode)
6971 (org-show-hidden-entry)
6972 (save-excursion
6973 (and (outline-next-heading)
6974 (org-flag-heading nil)))) ; show the next heading
6975 (and highlight (org-highlight (point-at-bol) (point-at-eol)))))
6977 (defun org-agenda-switch-to ()
6978 "Go to the Org-mode file which contains the item at point."
6979 (interactive)
6980 (let* ((marker (or (get-text-property (point) 'org-marker)
6981 (org-agenda-error)))
6982 (buffer (marker-buffer marker))
6983 (pos (marker-position marker)))
6984 (switch-to-buffer buffer)
6985 (delete-other-windows)
6986 (widen)
6987 (goto-char pos)
6988 (when (eq major-mode 'org-mode)
6989 (org-show-hidden-entry)
6990 (save-excursion
6991 (and (outline-next-heading)
6992 (org-flag-heading nil)))))) ; show the next heading
6994 (defun org-agenda-goto-mouse (ev)
6995 "Go to the Org-mode file which contains the item at the mouse click."
6996 (interactive "e")
6997 (mouse-set-point ev)
6998 (org-agenda-goto))
7000 (defun org-agenda-show ()
7001 "Display the Org-mode file which contains the item at point."
7002 (interactive)
7003 (let ((win (selected-window)))
7004 (org-agenda-goto t)
7005 (select-window win)))
7007 (defun org-agenda-recenter (arg)
7008 "Display the Org-mode file which contains the item at point and recenter."
7009 (interactive "P")
7010 (let ((win (selected-window)))
7011 (org-agenda-goto t)
7012 (recenter arg)
7013 (select-window win)))
7015 (defun org-agenda-show-mouse (ev)
7016 "Display the Org-mode file which contains the item at the mouse click."
7017 (interactive "e")
7018 (mouse-set-point ev)
7019 (org-agenda-show))
7021 (defun org-agenda-check-no-diary ()
7022 "Check if the entry is a diary link and abort if yes."
7023 (if (get-text-property (point) 'org-agenda-diary-link)
7024 (org-agenda-error)))
7026 (defun org-agenda-error ()
7027 (error "Command not allowed in this line"))
7029 (defvar org-last-heading-marker (make-marker)
7030 "Marker pointing to the headline that last changed its TODO state
7031 by a remote command from the agenda.")
7033 (defun org-agenda-todo (&optional arg)
7034 "Cycle TODO state of line at point, also in Org-mode file.
7035 This changes the line at point, all other lines in the agenda referring to
7036 the same tree node, and the headline of the tree node in the Org-mode file."
7037 (interactive "P")
7038 (org-agenda-check-no-diary)
7039 (let* ((col (current-column))
7040 (marker (or (get-text-property (point) 'org-marker)
7041 (org-agenda-error)))
7042 (buffer (marker-buffer marker))
7043 (pos (marker-position marker))
7044 (hdmarker (get-text-property (point) 'org-hd-marker))
7045 (buffer-read-only nil)
7046 newhead)
7047 (with-current-buffer buffer
7048 (widen)
7049 (goto-char pos)
7050 (org-show-hidden-entry)
7051 (save-excursion
7052 (and (outline-next-heading)
7053 (org-flag-heading nil))) ; show the next heading
7054 (org-todo arg)
7055 (and (bolp) (forward-char 1))
7056 (setq newhead (org-get-heading))
7057 (save-excursion
7058 (org-back-to-heading)
7059 (move-marker org-last-heading-marker (point))))
7060 (beginning-of-line 1)
7061 (save-excursion
7062 (org-agenda-change-all-lines newhead hdmarker 'fixface))
7063 (move-to-column col)))
7065 (defun org-agenda-change-all-lines (newhead hdmarker &optional fixface)
7066 "Change all lines in the agenda buffer which match HDMARKER.
7067 The new content of the line will be NEWHEAD (as modified by
7068 `org-format-agenda-item'). HDMARKER is checked with
7069 `equal' against all `org-hd-marker' text properties in the file.
7070 If FIXFACE is non-nil, the face of each item is modified acording to
7071 the new TODO state."
7072 (let* (props m pl undone-face done-face finish new dotime cat tags)
7073 ; (setq newhead (org-format-agenda-item "x" newhead "x" nil 'noprefix))
7074 (save-excursion
7075 (goto-char (point-max))
7076 (beginning-of-line 1)
7077 (while (not finish)
7078 (setq finish (bobp))
7079 (when (and (setq m (get-text-property (point) 'org-hd-marker))
7080 (equal m hdmarker))
7081 (setq props (text-properties-at (point))
7082 dotime (get-text-property (point) 'dotime)
7083 cat (get-text-property (point) 'category)
7084 tags (get-text-property (point) 'tags)
7085 new (org-format-agenda-item "x" newhead cat tags dotime 'noprefix)
7086 pl (get-text-property (point) 'prefix-length)
7087 undone-face (get-text-property (point) 'undone-face)
7088 done-face (get-text-property (point) 'done-face))
7089 (move-to-column pl)
7090 (if (looking-at ".*")
7091 (progn
7092 (replace-match new t t)
7093 (beginning-of-line 1)
7094 (add-text-properties (point-at-bol) (point-at-eol) props)
7095 (when fixface
7096 (add-text-properties
7097 (point-at-bol) (point-at-eol)
7098 (list 'face
7099 (if org-last-todo-state-is-todo
7100 undone-face done-face)))
7101 (org-agenda-highlight-todo 'line))
7102 (beginning-of-line 1))
7103 (error "Line update did not work")))
7104 (beginning-of-line 0)))))
7106 (defun org-agenda-priority-up ()
7107 "Increase the priority of line at point, also in Org-mode file."
7108 (interactive)
7109 (org-agenda-priority 'up))
7111 (defun org-agenda-priority-down ()
7112 "Decrease the priority of line at point, also in Org-mode file."
7113 (interactive)
7114 (org-agenda-priority 'down))
7116 (defun org-agenda-priority (&optional force-direction)
7117 "Set the priority of line at point, also in Org-mode file.
7118 This changes the line at point, all other lines in the agenda referring to
7119 the same tree node, and the headline of the tree node in the Org-mode file."
7120 (interactive)
7121 (org-agenda-check-no-diary)
7122 (let* ((marker (or (get-text-property (point) 'org-marker)
7123 (org-agenda-error)))
7124 (buffer (marker-buffer marker))
7125 (pos (marker-position marker))
7126 (hdmarker (get-text-property (point) 'org-hd-marker))
7127 (buffer-read-only nil)
7128 newhead)
7129 (with-current-buffer buffer
7130 (widen)
7131 (goto-char pos)
7132 (org-show-hidden-entry)
7133 (save-excursion
7134 (and (outline-next-heading)
7135 (org-flag-heading nil))) ; show the next heading
7136 (funcall 'org-priority force-direction)
7137 (end-of-line 1)
7138 (setq newhead (org-get-heading)))
7139 (org-agenda-change-all-lines newhead hdmarker)
7140 (beginning-of-line 1)))
7142 (defun org-get-tags-at (&optional pos)
7143 "Get a list of all headline tags applicable at POS.
7144 POS defaults to point. If tags are inherited, the list contains
7145 the targets in the same sequence as the headlines appear, i.e.
7146 the tags of the current headline come last."
7147 (interactive)
7148 (let (tags)
7149 (save-excursion
7150 (goto-char (or pos (point)))
7151 (save-match-data
7152 (org-back-to-heading t)
7153 (condition-case nil
7154 (while t
7155 (if (looking-at "[^\r\n]+?:\\([a-zA-Z_@0-9:]+\\):[ \t]*\\([\n\r]\\|\\'\\)")
7156 (setq tags (append (org-split-string
7157 (org-match-string-no-properties 1) ":")
7158 tags)))
7159 (or org-use-tag-inheritance (error ""))
7160 (org-up-heading-all 1))
7161 (error nil))))
7162 (message "%s" tags)
7163 tags))
7165 (defun org-agenda-set-tags ()
7166 "Set tags for the current headline."
7167 (interactive)
7168 (org-agenda-check-no-diary)
7169 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
7170 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
7171 (org-agenda-error)))
7172 (buffer (marker-buffer hdmarker))
7173 (pos (marker-position hdmarker))
7174 (buffer-read-only nil)
7175 newhead)
7176 (with-current-buffer buffer
7177 (widen)
7178 (goto-char pos)
7179 (org-show-hidden-entry)
7180 (save-excursion
7181 (and (outline-next-heading)
7182 (org-flag-heading nil))) ; show the next heading
7183 (call-interactively 'org-set-tags)
7184 (end-of-line 1)
7185 (setq newhead (org-get-heading)))
7186 (org-agenda-change-all-lines newhead hdmarker)
7187 (beginning-of-line 1)))
7189 (defun org-agenda-date-later (arg &optional what)
7190 "Change the date of this item to one day later."
7191 (interactive "p")
7192 (org-agenda-check-type t 'agenda 'timeline)
7193 (org-agenda-check-no-diary)
7194 (let* ((marker (or (get-text-property (point) 'org-marker)
7195 (org-agenda-error)))
7196 (buffer (marker-buffer marker))
7197 (pos (marker-position marker)))
7198 (with-current-buffer buffer
7199 (widen)
7200 (goto-char pos)
7201 (if (not (org-at-timestamp-p))
7202 (error "Cannot find time stamp"))
7203 (org-timestamp-change arg (or what 'day))
7204 (message "Time stamp changed to %s" org-last-changed-timestamp))))
7206 (defun org-agenda-date-earlier (arg &optional what)
7207 "Change the date of this item to one day earlier."
7208 (interactive "p")
7209 (org-agenda-date-later (- arg) what))
7211 (defun org-agenda-date-prompt (arg)
7212 "Change the date of this item. Date is prompted for, with default today.
7213 The prefix ARG is passed to the `org-time-stamp' command and can therefore
7214 be used to request time specification in the time stamp."
7215 (interactive "P")
7216 (org-agenda-check-type t 'agenda 'timeline)
7217 (org-agenda-check-no-diary)
7218 (let* ((marker (or (get-text-property (point) 'org-marker)
7219 (org-agenda-error)))
7220 (buffer (marker-buffer marker))
7221 (pos (marker-position marker)))
7222 (with-current-buffer buffer
7223 (widen)
7224 (goto-char pos)
7225 (if (not (org-at-timestamp-p))
7226 (error "Cannot find time stamp"))
7227 (org-time-stamp arg)
7228 (message "Time stamp changed to %s" org-last-changed-timestamp))))
7230 (defun org-agenda-schedule (arg)
7231 "Schedule the item at point."
7232 (interactive "P")
7233 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
7234 (org-agenda-check-no-diary)
7235 (let* ((marker (or (get-text-property (point) 'org-marker)
7236 (org-agenda-error)))
7237 (buffer (marker-buffer marker))
7238 (pos (marker-position marker))
7239 (org-insert-labeled-timestamps-at-point nil)
7241 (with-current-buffer buffer
7242 (widen)
7243 (goto-char pos)
7244 (setq ts (org-schedule))
7245 (message "Item scheduled for %s" ts))))
7247 (defun org-agenda-deadline (arg)
7248 "Schedule the item at point."
7249 (interactive "P")
7250 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
7251 (org-agenda-check-no-diary)
7252 (let* ((marker (or (get-text-property (point) 'org-marker)
7253 (org-agenda-error)))
7254 (buffer (marker-buffer marker))
7255 (pos (marker-position marker))
7256 (org-insert-labeled-timestamps-at-point nil)
7258 (with-current-buffer buffer
7259 (widen)
7260 (goto-char pos)
7261 (setq ts (org-deadline))
7262 (message "Deadline for this item set to %s" ts))))
7264 (defun org-get-heading ()
7265 "Return the heading of the current entry, without the stars."
7266 (save-excursion
7267 (and (memq (char-before) '(?\n ?\r)) (skip-chars-forward "^\n\r"))
7268 (if (and (re-search-backward "[\r\n]\\*" nil t)
7269 (looking-at "[\r\n]\\*+[ \t]+\\([^\r\n]*\\)"))
7270 (match-string 1)
7271 "")))
7273 (defun org-agenda-diary-entry ()
7274 "Make a diary entry, like the `i' command from the calendar.
7275 All the standard commands work: block, weekly etc."
7276 (interactive)
7277 (org-agenda-check-type t 'agenda 'timeline)
7278 (require 'diary-lib)
7279 (let* ((char (progn
7280 (message "Diary entry: [d]ay [w]eekly [m]onthly [y]early [a]nniversary [b]lock [c]yclic")
7281 (read-char-exclusive)))
7282 (cmd (cdr (assoc char
7283 '((?d . insert-diary-entry)
7284 (?w . insert-weekly-diary-entry)
7285 (?m . insert-monthly-diary-entry)
7286 (?y . insert-yearly-diary-entry)
7287 (?a . insert-anniversary-diary-entry)
7288 (?b . insert-block-diary-entry)
7289 (?c . insert-cyclic-diary-entry)))))
7290 (oldf (symbol-function 'calendar-cursor-to-date))
7291 (point (point))
7292 (mark (or (mark t) (point))))
7293 (unless cmd
7294 (error "No command associated with <%c>" char))
7295 (unless (and (get-text-property point 'day)
7296 (or (not (equal ?b char))
7297 (get-text-property mark 'day)))
7298 (error "Don't know which date to use for diary entry"))
7299 ;; We implement this by hacking the `calendar-cursor-to-date' function
7300 ;; and the `calendar-mark-ring' variable. Saves a lot of code.
7301 (let ((calendar-mark-ring
7302 (list (calendar-gregorian-from-absolute
7303 (or (get-text-property mark 'day)
7304 (get-text-property point 'day))))))
7305 (unwind-protect
7306 (progn
7307 (fset 'calendar-cursor-to-date
7308 (lambda (&optional error)
7309 (calendar-gregorian-from-absolute
7310 (get-text-property point 'day))))
7311 (call-interactively cmd))
7312 (fset 'calendar-cursor-to-date oldf)))))
7315 (defun org-agenda-execute-calendar-command (cmd)
7316 "Execute a calendar command from the agenda, with the date associated to
7317 the cursor position."
7318 (org-agenda-check-type t 'agenda 'timeline)
7319 (require 'diary-lib)
7320 (unless (get-text-property (point) 'day)
7321 (error "Don't know which date to use for calendar command"))
7322 (let* ((oldf (symbol-function 'calendar-cursor-to-date))
7323 (point (point))
7324 (date (calendar-gregorian-from-absolute
7325 (get-text-property point 'day)))
7326 (displayed-day (extract-calendar-day date))
7327 (displayed-month (extract-calendar-month date))
7328 (displayed-year (extract-calendar-year date)))
7329 (unwind-protect
7330 (progn
7331 (fset 'calendar-cursor-to-date
7332 (lambda (&optional error)
7333 (calendar-gregorian-from-absolute
7334 (get-text-property point 'day))))
7335 (call-interactively cmd))
7336 (fset 'calendar-cursor-to-date oldf))))
7338 (defun org-agenda-phases-of-moon ()
7339 "Display the phases of the moon for the 3 months around the cursor date."
7340 (interactive)
7341 (org-agenda-execute-calendar-command 'calendar-phases-of-moon))
7343 (defun org-agenda-holidays ()
7344 "Display the holidays for the 3 months around the cursor date."
7345 (interactive)
7346 (org-agenda-execute-calendar-command 'list-calendar-holidays))
7348 (defun org-agenda-sunrise-sunset (arg)
7349 "Display sunrise and sunset for the cursor date.
7350 Latitude and longitude can be specified with the variables
7351 `calendar-latitude' and `calendar-longitude'. When called with prefix
7352 argument, latitude and longitude will be prompted for."
7353 (interactive "P")
7354 (let ((calendar-longitude (if arg nil calendar-longitude))
7355 (calendar-latitude (if arg nil calendar-latitude))
7356 (calendar-location-name
7357 (if arg "the given coordinates" calendar-location-name)))
7358 (org-agenda-execute-calendar-command 'calendar-sunrise-sunset)))
7360 (defun org-agenda-goto-calendar ()
7361 "Open the Emacs calendar with the date at the cursor."
7362 (interactive)
7363 (org-agenda-check-type t 'agenda 'timeline)
7364 (let* ((day (or (get-text-property (point) 'day)
7365 (error "Don't know which date to open in calendar")))
7366 (date (calendar-gregorian-from-absolute day))
7367 (calendar-move-hook nil)
7368 (view-calendar-holidays-initially nil)
7369 (view-diary-entries-initially nil))
7370 (calendar)
7371 (calendar-goto-date date)))
7373 (defun org-calendar-goto-agenda ()
7374 "Compute the Org-mode agenda for the calendar date displayed at the cursor.
7375 This is a command that has to be installed in `calendar-mode-map'."
7376 (interactive)
7377 (org-agenda-list nil (calendar-absolute-from-gregorian
7378 (calendar-cursor-to-date))
7379 nil t))
7381 (defun org-agenda-convert-date ()
7382 (interactive)
7383 (org-agenda-check-type t 'agenda 'timeline)
7384 (let ((day (get-text-property (point) 'day))
7385 date s)
7386 (unless day
7387 (error "Don't know which date to convert"))
7388 (setq date (calendar-gregorian-from-absolute day))
7389 (setq s (concat
7390 "Gregorian: " (calendar-date-string date) "\n"
7391 "ISO: " (calendar-iso-date-string date) "\n"
7392 "Day of Yr: " (calendar-day-of-year-string date) "\n"
7393 "Julian: " (calendar-julian-date-string date) "\n"
7394 "Astron. JD: " (calendar-astro-date-string date)
7395 " (Julian date number at noon UTC)\n"
7396 "Hebrew: " (calendar-hebrew-date-string date) " (until sunset)\n"
7397 "Islamic: " (calendar-islamic-date-string date) " (until sunset)\n"
7398 "French: " (calendar-french-date-string date) "\n"
7399 "Mayan: " (calendar-mayan-date-string date) "\n"
7400 "Coptic: " (calendar-coptic-date-string date) "\n"
7401 "Ethiopic: " (calendar-ethiopic-date-string date) "\n"
7402 "Persian: " (calendar-persian-date-string date) "\n"
7403 "Chinese: " (calendar-chinese-date-string date) "\n"))
7404 (with-output-to-temp-buffer "*Dates*"
7405 (princ s))
7406 (if (fboundp 'fit-window-to-buffer)
7407 (fit-window-to-buffer (get-buffer-window "*Dates*")))))
7409 ;;; Tags
7411 (defun org-scan-tags (action matcher &optional todo-only)
7412 "Scan headline tags with inheritance and produce output ACTION.
7413 ACTION can be `sparse-tree' or `agenda'. MATCHER is a Lisp form to be
7414 evaluated, testing if a given set of tags qualifies a headline for
7415 inclusion. When TODO-ONLY is non-nil, only lines with a TODO keyword
7416 are included in the output."
7417 (let* ((re (concat "[\n\r]" outline-regexp " *\\(\\<\\("
7418 (mapconcat 'regexp-quote
7419 (nreverse (cdr (reverse org-todo-keywords)))
7420 "\\|")
7421 "\\>\\)\\)? *\\(.*?\\)\\(:[A-Za-z_@0-9:]+:\\)?[ \t]*[\n\r]"))
7422 (props (list 'face nil
7423 'done-face 'org-done
7424 'undone-face nil
7425 'mouse-face 'highlight
7426 'keymap org-agenda-keymap
7427 'help-echo
7428 (format "mouse-2 or RET jump to org file %s"
7429 (abbreviate-file-name buffer-file-name))))
7430 lspos
7431 tags tags-list tags-alist (llast 0) rtn level category i txt
7432 todo marker)
7434 (save-excursion
7435 (goto-char (point-min))
7436 (when (eq action 'sparse-tree) (org-overview))
7437 (while (re-search-forward re nil t)
7438 (setq todo (if (match-end 1) (match-string 2))
7439 tags (if (match-end 4) (match-string 4)))
7440 (goto-char (setq lspos (1+ (match-beginning 0))))
7441 (setq level (funcall outline-level)
7442 category (org-get-category))
7443 (setq i llast llast level)
7444 ;; remove tag lists from same and sublevels
7445 (while (>= i level)
7446 (when (setq entry (assoc i tags-alist))
7447 (setq tags-alist (delete entry tags-alist)))
7448 (setq i (1- i)))
7449 ;; add the nex tags
7450 (when tags
7451 (setq tags (mapcar 'downcase (org-split-string tags ":"))
7452 tags-alist
7453 (cons (cons level tags) tags-alist)))
7454 ;; compile tags for current headline
7455 (setq tags-list
7456 (if org-use-tag-inheritance
7457 (apply 'append (mapcar 'cdr tags-alist))
7458 tags))
7459 (when (and (or (not todo-only) todo)
7460 (eval matcher))
7461 ;; list this headline
7462 (if (eq action 'sparse-tree)
7463 (progn
7464 (org-show-hierarchy-above))
7465 (setq txt (org-format-agenda-item
7467 (concat
7468 (if org-tags-match-list-sublevels
7469 (make-string (1- level) ?.) "")
7470 (org-get-heading))
7471 category tags-list))
7472 (goto-char lspos)
7473 (setq marker (org-agenda-new-marker))
7474 (org-add-props txt props
7475 'org-marker marker 'org-hd-marker marker 'category category)
7476 (push txt rtn))
7477 ;; if we are to skip sublevels, jump to end of subtree
7478 (point)
7479 (or org-tags-match-list-sublevels (org-end-of-subtree)))))
7480 (nreverse rtn)))
7482 (defun org-tags-sparse-tree (&optional arg match)
7483 "Create a sparse tree according to tags search string MATCH.
7484 MATCH can contain positive and negative selection of tags, like
7485 \"+WORK+URGENT-WITHBOSS\"."
7486 (interactive "P")
7487 (let ((org-show-following-heading nil)
7488 (org-show-hierarchy-above nil))
7489 (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match)))))
7491 (defun org-make-tags-matcher (match)
7492 "Create the TAGS matcher form for the tags-selecting string MATCH."
7493 (unless match
7494 ;; Get a new match request, with completion
7495 (setq org-last-tags-completion-table
7496 (or (org-get-buffer-tags)
7497 org-last-tags-completion-table))
7498 (setq match (completing-read
7499 "Tags: " 'org-tags-completion-function nil nil nil
7500 'org-tags-history)))
7501 ;; parse the string and create a lisp form
7502 (let ((match0 match) minus tag mm matcher orterms term orlist)
7503 (setq orterms (org-split-string match "|"))
7504 (while (setq term (pop orterms))
7505 (while (string-match "^&?\\([-+:]\\)?\\([A-Za-z_@0-9]+\\)" term)
7506 (setq minus (and (match-end 1)
7507 (equal (match-string 1 term) "-"))
7508 tag (match-string 2 term)
7509 term (substring term (match-end 0))
7510 mm (list 'member (downcase tag) 'tags-list)
7511 mm (if minus (list 'not mm) mm))
7512 (push mm matcher))
7513 (push (if (> (length matcher) 1) (cons 'and matcher) (car matcher))
7514 orlist)
7515 (setq matcher nil))
7516 (setq matcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist)))
7517 ;; Return the string and lisp forms of the matcher
7518 (cons match0 matcher)))
7520 ;;;###autoload
7521 (defun org-tags-view (&optional todo-only match keep-modes)
7522 "Show all headlines for all `org-agenda-files' matching a TAGS criterion.
7523 The prefix arg TODO-ONLY limits the search to TODO entries."
7524 (interactive "P")
7525 (org-agenda-maybe-reset-markers 'force)
7526 (org-compile-prefix-format org-agenda-prefix-format)
7527 (let* ((org-agenda-keep-modes keep-modes)
7528 (org-tags-match-list-sublevels
7529 (if todo-only t org-tags-match-list-sublevels))
7530 (win (selected-window))
7531 (completion-ignore-case t)
7532 rtn rtnall files file pos matcher
7533 buffer)
7534 (setq matcher (org-make-tags-matcher match)
7535 match (car matcher) matcher (cdr matcher))
7536 (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name)))
7537 (progn
7538 (delete-other-windows)
7539 (switch-to-buffer-other-window
7540 (get-buffer-create org-agenda-buffer-name))))
7541 (setq buffer-read-only nil)
7542 (erase-buffer)
7543 (org-agenda-mode) (setq buffer-read-only nil)
7544 (set (make-local-variable 'org-agenda-type) 'tags)
7545 (set (make-local-variable 'org-agenda-redo-command)
7546 (list 'org-tags-view (list 'quote todo-only)
7547 (list 'if 'current-prefix-arg nil match) t))
7548 (setq files (org-agenda-files)
7549 rtnall nil)
7550 (while (setq file (pop files))
7551 (catch 'nextfile
7552 (org-check-agenda-file file)
7553 (setq buffer (if (file-exists-p file)
7554 (org-get-agenda-file-buffer file)
7555 (error "No such file %s" file)))
7556 (if (not buffer)
7557 ;; If file does not exist, merror message to agenda
7558 (setq rtn (list
7559 (format "ORG-AGENDA-ERROR: No such org-file %s" file))
7560 rtnall (append rtnall rtn))
7561 (with-current-buffer buffer
7562 (unless (eq major-mode 'org-mode)
7563 (error "Agenda file %s is not in `org-mode'" file))
7564 (setq org-category-table (org-get-category-table))
7565 (save-excursion
7566 (save-restriction
7567 (if org-respect-restriction
7568 (if (org-region-active-p)
7569 ;; Respect a region to restrict search
7570 (narrow-to-region (region-beginning) (region-end)))
7571 ;; If we work for the calendar or many files,
7572 ;; get rid of any restriction
7573 (widen))
7574 (setq rtn (org-scan-tags 'agenda matcher todo-only))
7575 (setq rtnall (append rtnall rtn))))))))
7576 (insert "Headlines with TAGS match: ")
7577 (add-text-properties (point-min) (1- (point))
7578 (list 'face 'org-level-3))
7579 (setq pos (point))
7580 (insert match "\n")
7581 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
7582 (setq pos (point))
7583 (insert "Press `C-u r' to search again with new search string\n")
7584 (add-text-properties pos (1- (point)) (list 'face 'org-level-3))
7585 (when rtnall
7586 (insert (mapconcat 'identity rtnall "\n")))
7587 (goto-char (point-min))
7588 (setq buffer-read-only t)
7589 (org-fit-agenda-window)
7590 (if (not org-select-agenda-window) (select-window win))))
7592 (defvar org-add-colon-after-tag-completion nil) ;; dynamically skoped param
7593 (defun org-set-tags (&optional arg just-align)
7594 "Set the tags for the current headline.
7595 With prefix ARG, realign all tags in headings in the current buffer."
7596 (interactive "P")
7597 (let* ((re (concat "^" outline-regexp))
7598 (col (current-column))
7599 (current (org-get-tags))
7600 table current-tags inherited-tags ; computed below when needed
7601 tags hd empty invis)
7602 (if arg
7603 (save-excursion
7604 (goto-char (point-min))
7605 (while (re-search-forward re nil t)
7606 (org-set-tags nil t))
7607 (message "All tags realigned to column %d" org-tags-column))
7608 (if just-align
7609 (setq tags current)
7610 (setq table (or org-tag-alist (org-get-buffer-tags))
7611 org-last-tags-completion-table table
7612 current-tags (org-split-string current ":")
7613 inherited-tags (nreverse
7614 (nthcdr (length current-tags)
7615 (nreverse (org-get-tags-at))))
7616 tags
7617 (if (or (eq t org-use-fast-tag-selection)
7618 (and org-use-fast-tag-selection (cdar table)))
7619 (org-fast-tag-selection current-tags inherited-tags table)
7620 (let ((org-add-colon-after-tag-completion t))
7621 (completing-read "Tags: " 'org-tags-completion-function
7622 nil nil current 'org-tags-history))))
7623 (while (string-match "[-+&]+" tags)
7624 (setq tags (replace-match ":" t t tags))))
7626 ;; FIXME: still optimize this by not checking when JUST-ALIGN?
7627 (unless (setq empty (string-match "\\`[\t ]*\\'" tags))
7628 (unless (string-match ":$" tags) (setq tags (concat tags ":")))
7629 (unless (string-match "^:" tags) (setq tags (concat ":" tags))))
7630 (if (equal current "")
7631 (progn
7632 (end-of-line 1)
7633 (or empty (insert-before-markers " ")))
7634 (beginning-of-line 1)
7635 (setq invis (org-invisible-p))
7636 (looking-at (concat "\\(.*\\)\\(" (regexp-quote current) "\\)[ \t]*"))
7637 (setq hd (match-string 1))
7638 (delete-region (match-beginning 0) (match-end 0))
7639 (insert-before-markers (org-trim hd) (if empty "" " ")))
7640 (unless (equal tags "")
7641 (move-to-column (max (current-column)
7642 (if (> org-tags-column 0)
7643 org-tags-column
7644 (- (- org-tags-column) (length tags))))
7646 (insert-before-markers tags)
7647 (if (and (not invis) (org-invisible-p))
7648 (outline-flag-region (point-at-bol) (point) nil)))
7649 (move-to-column col))))
7651 (defun org-tags-completion-function (string predicate &optional flag)
7652 (let (s1 s2 rtn (ctable org-last-tags-completion-table))
7653 (if (string-match "^\\(.*[-+:&|]\\)\\([^-+:&|]*\\)$" string)
7654 (setq s1 (match-string 1 string)
7655 s2 (match-string 2 string))
7656 (setq s1 "" s2 string))
7657 (cond
7658 ((eq flag nil)
7659 ;; try completion
7660 (setq rtn (try-completion s2 ctable))
7661 (if (stringp rtn)
7662 (concat s1 s2 (substring rtn (length s2))
7663 (if (and org-add-colon-after-tag-completion
7664 (assoc rtn ctable))
7665 ":" "")))
7667 ((eq flag t)
7668 ;; all-completions
7669 (all-completions s2 ctable)
7671 ((eq flag 'lambda)
7672 ;; exact match?
7673 (assoc s2 ctable)))
7676 (defun org-fast-tag-insert (kwd tags face &optional end)
7677 "Insert KDW, and the TAGS, the latter with face FACE. Also inser END."
7678 (insert (format "%-12s" (concat kwd ":"))
7679 (org-add-props (mapconcat 'identity tags " ") nil 'face face)
7680 (or end "")))
7682 (defun org-fast-tag-selection (current inherited table)
7683 "Fast tag selection with single keys.
7684 CURRENT is the current list of tags in the headline, INHERITED is the
7685 list of inherited tags, and TABLE is an alist of tags and corresponding keys.
7686 If the keys are nil, a-z are automatically assigned.
7687 Returns the new tags string, or nil to not change the current settings."
7688 (let* ((maxlen (apply 'max (mapcar (lambda (x)
7689 (string-width (car x))) table)))
7690 (fwidth (+ maxlen 3 1 3))
7691 (ncol (/ (window-width) fwidth))
7692 (i-face 'org-done)
7693 (c-face 'org-tag)
7694 tg cnt e c char ntable tbl rtn)
7695 (save-window-excursion
7696 (delete-other-windows)
7697 (split-window-vertically)
7698 (switch-to-buffer-other-window (get-buffer-create " *Org tags*"))
7699 (erase-buffer)
7700 (org-fast-tag-insert "Inherited" inherited i-face "\n")
7701 (org-fast-tag-insert "Current" current c-face "\n\n")
7702 (setq tbl table char (1- ?a) cnt 0)
7703 (while (setq e (pop tbl))
7704 (setq tg (car e) c (or (cdr e) (setq char (1+ char))))
7705 (setq tg (org-add-props tg nil 'face
7706 (cond
7707 ((member tg current) c-face)
7708 ((member tg inherited) i-face)
7709 (t nil))))
7710 (insert "[" c "] " tg (make-string
7711 (- fwidth 4 (length tg)) ?\ ))
7712 (push (cons tg c) ntable)
7713 (when (= (setq cnt (1+ cnt)) ncol)
7714 (insert "\n")
7715 (setq cnt 0)))
7716 (insert "\n")
7717 (goto-char (point-min))
7718 (if (fboundp 'fit-window-to-buffer) (fit-window-to-buffer))
7719 (setq rtn
7720 (catch 'exit
7721 (while t
7722 (message "[key]:Toggle SPC: clear current RET accept")
7723 (setq c (read-char-exclusive))
7724 (cond
7725 ((= c ?\r) (throw 'exit t))
7726 ((= c ?\C-g) (throw 'exit nil))
7727 ((= c ?\ ) (setq current nil))
7728 (t (setq e (rassoc c ntable) tg (car e))
7729 (if (member tg current)
7730 (setq current (delete tg current))
7731 (setq current (append current (list tg))))))
7732 (goto-char (point-min))
7733 (beginning-of-line 2)
7734 (delete-region (point) (point-at-eol))
7735 (org-fast-tag-insert "Current" current c-face)
7736 (while (re-search-forward "\\[.\\] \\([a-zA-Z0-9_@]+\\)" nil t)
7737 (setq tg (match-string 1))
7738 (add-text-properties (match-beginning 1) (match-end 1)
7739 (list 'face
7740 (cond
7741 ((member tg current) c-face)
7742 ((member tg inherited) i-face)
7743 (t nil)))))
7744 (goto-char (point-min)))))
7745 (if rtn
7746 (mapconcat 'identity current ":")
7747 nil))))
7749 (defun org-get-tags ()
7750 "Get the TAGS string in the current headline."
7751 (unless (org-on-heading-p)
7752 (error "Not on a heading"))
7753 (save-excursion
7754 (beginning-of-line 1)
7755 (if (looking-at ".*[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \t]*\\(\r\\|$\\)")
7756 (org-match-string-no-properties 1)
7757 "")))
7759 (defun org-get-buffer-tags ()
7760 "Get a table of all tags used in the buffer, for completion."
7761 (let (tags)
7762 (save-excursion
7763 (goto-char (point-min))
7764 (while (re-search-forward "[ \t]:\\([A-Za-z_@0-9:]+\\):[ \t\r\n]" nil t)
7765 (mapc (lambda (x) (add-to-list 'tags x))
7766 (org-split-string (org-match-string-no-properties 1) ":"))))
7767 (mapcar 'list tags)))
7769 ;;; Link Stuff
7771 (defvar org-create-file-search-functions nil
7772 "List of functions to construct the right search string for a file link.
7773 These functions are called in turn with point at the location to
7774 which the link should point.
7776 A function in the hook should first test if it would like to
7777 handle this file type, for example by checking the major-mode or
7778 the file extension. If it decides not to handle this file, it
7779 should just return nil to give other functions a chance. If it
7780 does handle the file, it must return the search string to be used
7781 when following the link. The search string will be part of the
7782 file link, given after a double colon, and `org-open-at-point'
7783 will automatically search for it. If special measures must be
7784 taken to make the search successful, another function should be
7785 added to the companion hook `org-execute-file-search-functions',
7786 which see.
7788 A function in this hook may also use `setq' to set the variable
7789 `description' to provide a suggestion for the descriptive text to
7790 be used for this link when it gets inserted into an Org-mode
7791 buffer with \\[org-insert-link].")
7793 (defvar org-execute-file-search-functions nil
7794 "List of functions to execute a file search triggered by a link.
7796 Functions added to this hook must accept a single argument, the
7797 search string that was part of the file link, the part after the
7798 double colon. The function must first check if it would like to
7799 handle this search, for example by checking the major-mode or the
7800 file extension. If it decides not to handle this search, it
7801 should just return nil to give other functions a chance. If it
7802 does handle the search, it must return a non-nil value to keep
7803 other functions from trying.
7805 Each function can access the current prefix argument through the
7806 variable `current-prefix-argument'. Note that a single prefix is
7807 used to force opening a link in Emacs, so it may be good to only
7808 use a numeric or double prefix to guide the search function.
7810 In case this is needed, a function in this hook can also restore
7811 the window configuration before `org-open-at-point' was called using:
7813 (set-window-configuration org-window-config-before-follow-link)")
7815 (defun org-find-file-at-mouse (ev)
7816 "Open file link or URL at mouse."
7817 (interactive "e")
7818 (mouse-set-point ev)
7819 (org-open-at-point 'in-emacs))
7821 (defun org-open-at-mouse (ev)
7822 "Open file link or URL at mouse."
7823 (interactive "e")
7824 (mouse-set-point ev)
7825 (org-open-at-point))
7827 (defvar org-window-config-before-follow-link nil
7828 "The window configuration before following a link.
7829 This is saved in case the need arises to restore it.")
7831 (defun org-open-at-point (&optional in-emacs)
7832 "Open link at or after point.
7833 If there is no link at point, this function will search forward up to
7834 the end of the current subtree.
7835 Normally, files will be opened by an appropriate application. If the
7836 optional argument IN-EMACS is non-nil, Emacs will visit the file."
7837 (interactive "P")
7838 (setq org-window-config-before-follow-link (current-window-configuration))
7839 (org-remove-occur-highlights nil nil t)
7840 (if (org-at-timestamp-p)
7841 (org-agenda-list nil (time-to-days (org-time-string-to-time
7842 (substring (match-string 1) 0 10)))
7844 (let (type path link line search (pos (point)))
7845 (catch 'match
7846 (save-excursion
7847 (skip-chars-forward "^]\n\r")
7848 (when (and (re-search-backward "\\[\\[" nil t)
7849 (looking-at org-bracket-link-regexp)
7850 (<= (match-beginning 0) pos)
7851 (>= (match-end 0) pos))
7852 (setq link (org-link-unescape (org-match-string-no-properties 1)))
7853 (while (string-match " *\n *" link)
7854 (setq link (replace-match " " t t link)))
7855 (if (string-match org-link-re-with-space2 link)
7856 (setq type (match-string 1 link)
7857 path (match-string 2 link))
7858 (setq type "thisfile"
7859 path link))
7860 (throw 'match t)))
7862 (when (get-text-property (point) 'org-linked-text)
7863 (setq type "thisfile"
7864 pos (if (get-text-property (1+ (point)) 'org-linked-text)
7865 (1+ (point)) (point))
7866 path (buffer-substring
7867 (previous-single-property-change pos 'org-linked-text)
7868 (next-single-property-change pos 'org-linked-text)))
7869 (throw 'match t))
7871 (save-excursion
7872 (skip-chars-backward (concat "^[]" org-non-link-chars " "))
7873 (if (equal (char-before) ?<) (backward-char 1))
7874 (when (or (looking-at org-angle-link-re)
7875 (looking-at org-plain-link-re)
7876 (and (or (re-search-forward org-angle-link-re (point-at-eol) t)
7877 (re-search-forward org-plain-link-re (point-at-eol) t))
7878 (<= (match-beginning 0) pos)
7879 (>= (match-end 0) pos)))
7880 (setq type (match-string 1)
7881 path (match-string 2))
7882 (throw 'match t)))
7883 (save-excursion
7884 (skip-chars-backward "^ \t\n\r")
7885 (when (looking-at "\\(:[A-Za-z_@0-9:]+\\):[ \t\r\n]")
7886 (setq type "tags"
7887 path (match-string 1))
7888 (while (string-match ":" path)
7889 (setq path (replace-match "+" t t path)))
7890 (throw 'match t)))
7891 (save-excursion
7892 (skip-chars-backward "a-zA-Z_")
7893 (when (and (memq 'camel org-activate-links)
7894 (looking-at org-camel-regexp))
7895 (setq type "camel" path (match-string 0))
7896 (if (equal (char-before) ?*)
7897 (setq path (concat "*" path))))
7898 (throw 'match t)))
7899 (unless path
7900 (error "No link found"))
7901 ;; Remove any trailing spaces in path
7902 (if (string-match " +\\'" path)
7903 (setq path (replace-match "" t t path)))
7905 (cond
7907 ((member type '("http" "https" "ftp" "mailto" "news"))
7908 (browse-url (concat type ":" path)))
7910 ((string= type "tags")
7911 (org-tags-view in-emacs path))
7912 ((or (string= type "camel")
7913 (string= type "thisfile"))
7914 (org-mark-ring-push)
7915 (org-link-search
7916 path
7917 (cond ((equal in-emacs '(4)) 'occur)
7918 ((equal in-emacs '(16)) 'org-occur)
7919 (t nil))))
7921 ((string= type "file")
7922 (if (string-match "::?\\([0-9]+\\)\\'" path) ;; second : optional
7923 ;; FIXME: It is unsafe to allow a single colon.
7924 (setq line (string-to-number (match-string 1 path))
7925 path (substring path 0 (match-beginning 0)))
7926 (if (string-match "::\\(.+\\)\\'" path)
7927 (setq search (match-string 1 path)
7928 path (substring path 0 (match-beginning 0)))))
7929 (org-open-file path in-emacs line search))
7931 ((string= type "news")
7932 (org-follow-gnus-link path))
7934 ((string= type "bbdb")
7935 (org-follow-bbdb-link path))
7937 ((string= type "info")
7938 (org-follow-info-link path))
7940 ((string= type "gnus")
7941 (let (group article)
7942 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
7943 (error "Error in Gnus link"))
7944 (setq group (match-string 1 path)
7945 article (match-string 3 path))
7946 (org-follow-gnus-link group article)))
7948 ((string= type "vm")
7949 (let (folder article)
7950 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
7951 (error "Error in VM link"))
7952 (setq folder (match-string 1 path)
7953 article (match-string 3 path))
7954 ;; in-emacs is the prefix arg, will be interpreted as read-only
7955 (org-follow-vm-link folder article in-emacs)))
7957 ((string= type "wl")
7958 (let (folder article)
7959 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
7960 (error "Error in Wanderlust link"))
7961 (setq folder (match-string 1 path)
7962 article (match-string 3 path))
7963 (org-follow-wl-link folder article)))
7965 ((string= type "mhe")
7966 (let (folder article)
7967 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
7968 (error "Error in MHE link"))
7969 (setq folder (match-string 1 path)
7970 article (match-string 3 path))
7971 (org-follow-mhe-link folder article)))
7973 ((string= type "rmail")
7974 (let (folder article)
7975 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
7976 (error "Error in RMAIL link"))
7977 (setq folder (match-string 1 path)
7978 article (match-string 3 path))
7979 (org-follow-rmail-link folder article)))
7981 ((string= type "shell")
7982 (let ((cmd path))
7983 (while (string-match "@{" cmd)
7984 (setq cmd (replace-match "<" t t cmd)))
7985 (while (string-match "@}" cmd)
7986 (setq cmd (replace-match ">" t t cmd)))
7987 (if (or (not org-confirm-shell-link-function)
7988 (funcall org-confirm-shell-link-function
7989 (format "Execute \"%s\" in shell? "
7990 (org-add-props cmd nil
7991 'face 'org-warning))))
7992 (progn
7993 (message "Executing %s" cmd)
7994 (shell-command cmd))
7995 (error "Abort"))))
7997 ((string= type "elisp")
7998 (let ((cmd path))
7999 (if (or (not org-confirm-elisp-link-function)
8000 (funcall org-confirm-elisp-link-function
8001 (format "Execute \"%s\" as elisp? "
8002 (org-add-props cmd nil
8003 'face 'org-warning))))
8004 (message "%s => %s" cmd (eval (read cmd)))
8005 (error "Abort"))))
8008 (browse-url-at-point))))))
8010 (defun org-link-search (s &optional type)
8011 "Search for a link search option.
8012 When S is a CamelCaseWord, search for a target, or for a sentence containing
8013 the words. If S is surrounded by forward slashes, it is interpreted as a
8014 regular expression. In org-mode files, this will create an `org-occur'
8015 sparse tree. In ordinary files, `occur' will be used to list matches.
8016 If the current buffer is in `dired-mode', grep will be used to search
8017 in all files."
8018 (let ((case-fold-search t)
8019 (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " "))
8020 (pos (point))
8021 (pre "") (post "")
8022 words re0 re1 re2 re3 re4 re5 re2a reall camel)
8023 (cond
8024 ;; First check if there are any special
8025 ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
8026 ;; Now try the builtin stuff
8027 ((save-excursion
8028 (goto-char (point-min))
8029 (and
8030 (re-search-forward
8031 (concat "<<" (regexp-quote s0) ">>") nil t)
8032 (setq pos (match-beginning 0))))
8033 ;; There is an exact target for this
8034 (goto-char pos))
8035 ((string-match "^/\\(.*\\)/$" s)
8036 ;; A regular expression
8037 (cond
8038 ((eq major-mode 'org-mode)
8039 (org-occur (match-string 1 s)))
8040 ;;((eq major-mode 'dired-mode)
8041 ;; (grep (concat "grep -n -e '" (match-string 1 s) "' *")))
8042 (t (org-do-occur (match-string 1 s)))))
8043 ((or (setq camel (string-match (concat "^" org-camel-regexp "$") s))
8045 ;; A camel or a normal search string
8046 (when (equal (string-to-char s) ?*)
8047 ;; Anchor on headlines, post may include tags.
8048 (setq pre "^\\*+[ \t]*\\(?:\\sw+\\)?[ \t]*"
8049 post "[ \t]*\\(?:[ \t]+:[a-zA-Z_@0-9:+]:[ \t]*\\)?$"
8050 s (substring s 1)))
8051 (remove-text-properties
8052 0 (length s)
8053 '(face nil mouse-face nil keymap nil fontified nil) s)
8054 ;; Make a series of regular expressions to find a match
8055 (setq words
8056 (if camel
8057 (org-camel-to-words s)
8058 (org-split-string s "[ \n\r\t]+"))
8059 re0 (concat "\\(<<" (regexp-quote s0) ">>\\)")
8060 re2 (concat "[ \t\r\n]\\(" (mapconcat 'downcase words "[ \t]+") "\\)[ \t\r\n]")
8061 re2a (concat "[ \t\r\n]\\(" (mapconcat 'downcase words "[ \t\r\n]+") "\\)[ \t\r\n]")
8062 re4 (concat "[^a-zA-Z_]\\(" (mapconcat 'downcase words "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
8063 re1 (concat pre re2 post)
8064 re3 (concat pre re4 post)
8065 re5 (concat pre ".*" re4)
8066 re2 (concat pre re2)
8067 re2a (concat pre re2a)
8068 re4 (concat pre re4)
8069 reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2
8070 "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\("
8071 re5 "\\)"
8073 (cond
8074 ((eq type 'org-occur) (org-occur reall))
8075 ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
8076 (t (goto-char (point-min))
8077 (if (or (org-search-not-link re0 nil t)
8078 (org-search-not-link re1 nil t)
8079 (org-search-not-link re2 nil t)
8080 (org-search-not-link re2a nil t)
8081 (org-search-not-link re3 nil t)
8082 (org-search-not-link re4 nil t)
8083 (org-search-not-link re5 nil t)
8085 (goto-char (match-beginning 1))
8086 (goto-char pos)
8087 (error "No match")))))
8089 ;; Normal string-search
8090 (goto-char (point-min))
8091 (if (search-forward s nil t)
8092 (goto-char (match-beginning 0))
8093 (error "No match"))))
8094 (and (eq major-mode 'org-mode) (org-show-hierarchy-above))))
8096 (defun org-search-not-link (&rest args)
8097 "Execute `re-search-forward', but only accept matches that are not a link."
8098 (catch 'exit
8099 (let ((pos (point)) p1)
8100 (while (apply 're-search-forward args)
8101 (setq p1 (point))
8102 (if (not (save-match-data
8103 (and (re-search-backward "\\[\\[" nil t)
8104 (looking-at org-bracket-link-regexp)
8105 (<= (match-beginning 0) p1)
8106 (>= (match-end 0) p1))))
8107 (progn (goto-char (match-end 0))
8108 (throw 'exit (point)))
8109 (goto-char (match-end 0)))))))
8111 (defun org-do-occur (regexp &optional cleanup)
8112 "Call the Emacs command `occur'.
8113 If CLEANUP is non-nil, remove the printout of the regular expression
8114 in the *Occur* buffer. This is useful if the regex is long and not useful
8115 to read."
8116 (occur regexp)
8117 (when cleanup
8118 (let ((cwin (selected-window)) win beg end)
8119 (when (setq win (get-buffer-window "*Occur*"))
8120 (select-window win))
8121 (goto-char (point-min))
8122 (when (re-search-forward "match[a-z]+" nil t)
8123 (setq beg (match-end 0))
8124 (if (re-search-forward "^[ \t]*[0-9]+" nil t)
8125 (setq end (1- (match-beginning 0)))))
8126 (and beg end (let ((buffer-read-only)) (delete-region beg end)))
8127 (goto-char (point-min))
8128 (select-window cwin))))
8130 (defvar org-mark-ring nil
8131 "Mark ring for positions before jumps in Org-mode.")
8132 (defvar org-mark-ring-last-goto nil
8133 "Last position in the mark ring used to go back.")
8134 ;; Fill and close the ring
8135 (setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is reloaded
8136 (loop for i from 1 to org-mark-ring-length do
8137 (push (make-marker) org-mark-ring))
8138 (setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring)
8139 org-mark-ring)
8141 (defun org-mark-ring-push (&optional pos buffer)
8142 "Put the current position or POS into the mark ring and rotate it."
8143 (interactive)
8144 (setq pos (or pos (point)))
8145 (setq org-mark-ring (nthcdr (1- org-mark-ring-length) org-mark-ring))
8146 (move-marker (car org-mark-ring)
8147 (or pos (point))
8148 (or buffer (current-buffer)))
8149 (message
8150 (substitute-command-keys
8151 "Position saved to mark ring, go back with \\[org-mark-ring-goto].")))
8153 (defun org-mark-ring-goto (&optional n)
8154 "Jump to the previous position in the mark ring.
8155 With prefix arg N, jump back that many stored positions. When
8156 called several times in succession, walk through the entire ring.
8157 Org-mode commands jumping to a different position in the current file,
8158 or to another Org-mode file, automatically push the old position
8159 onto the ring."
8160 (interactive "p")
8161 (let (p m)
8162 (if (eq last-command this-command)
8163 (setq p (nthcdr n (or org-mark-ring-last-goto org-mark-ring)))
8164 (setq p org-mark-ring))
8165 (setq org-mark-ring-last-goto p)
8166 (setq m (car p))
8167 (switch-to-buffer (marker-buffer m))
8168 (goto-char m)
8169 (if (or (org-invisible-p) (org-invisible-p2)) (org-show-hierarchy-above))))
8171 (defun org-camel-to-words (s)
8172 "Split \"CamelCaseWords\" to (\"Camel\" \"Case\" \"Words\")."
8173 (let ((case-fold-search nil)
8174 words)
8175 (while (string-match "[a-z][A-Z]" s)
8176 (push (substring s 0 (1+ (match-beginning 0))) words)
8177 (setq s (substring s (1+ (match-beginning 0)))))
8178 (nreverse (cons s words))))
8180 (defun org-remove-angle-brackets (s)
8181 (if (equal (substring s 0 1) "<") (setq s (substring s 1)))
8182 (if (equal (substring s -1) ">") (setq s (substring s 0 -1)))
8184 (defun org-add-angle-brackets (s)
8185 (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s)))
8186 (if (equal (substring s -1) ">") nil (setq s (concat s ">")))
8189 (defun org-follow-bbdb-link (name)
8190 "Follow a BBDB link to NAME."
8191 (require 'bbdb)
8192 (let ((inhibit-redisplay t)
8193 (bbdb-electric-p nil))
8194 (catch 'exit
8195 ;; Exact match on name
8196 (bbdb-name (concat "\\`" name "\\'") nil)
8197 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
8198 ;; Exact match on name
8199 (bbdb-company (concat "\\`" name "\\'") nil)
8200 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
8201 ;; Partial match on name
8202 (bbdb-name name nil)
8203 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
8204 ;; Partial match on company
8205 (bbdb-company name nil)
8206 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
8207 ;; General match including network address and notes
8208 (bbdb name nil)
8209 (when (= 0 (buffer-size (get-buffer "*BBDB*")))
8210 (delete-window (get-buffer-window "*BBDB*"))
8211 (error "No matching BBDB record")))))
8214 (defun org-follow-info-link (name)
8215 "Follow an info file & node link to NAME."
8216 (if (or (string-match "\\(.*\\)::?\\(.*\\)" name)
8217 (string-match "\\(.*\\)" name))
8218 (progn
8219 (require 'info)
8220 (if (match-string 2 name) ; If there isn't a node, choose "Top"
8221 (Info-find-node (match-string 1 name) (match-string 2 name))
8222 (Info-find-node (match-string 1 name) "Top")))
8223 (message (concat "Could not open: " name))))
8225 (defun org-follow-gnus-link (&optional group article)
8226 "Follow a Gnus link to GROUP and ARTICLE."
8227 (require 'gnus)
8228 (funcall (cdr (assq 'gnus org-link-frame-setup)))
8229 (if group (gnus-fetch-group group))
8230 (if article
8231 (or (gnus-summary-goto-article article nil 'force)
8232 (if (fboundp 'gnus-summary-insert-cached-articles)
8233 (progn
8234 (gnus-summary-insert-cached-articles)
8235 (gnus-summary-goto-article article nil 'force))
8236 (message "Message could not be found.")))))
8238 (defun org-follow-vm-link (&optional folder article readonly)
8239 "Follow a VM link to FOLDER and ARTICLE."
8240 (require 'vm)
8241 (setq article (org-add-angle-brackets article))
8242 (if (string-match "^//\\([a-zA-Z]+@\\)?\\([^:]+\\):\\(.*\\)" folder)
8243 ;; ange-ftp or efs or tramp access
8244 (let ((user (or (match-string 1 folder) (user-login-name)))
8245 (host (match-string 2 folder))
8246 (file (match-string 3 folder)))
8247 (cond
8248 ((featurep 'tramp)
8249 ;; use tramp to access the file
8250 (if (featurep 'xemacs)
8251 (setq folder (format "[%s@%s]%s" user host file))
8252 (setq folder (format "/%s@%s:%s" user host file))))
8254 ;; use ange-ftp or efs
8255 (require (if (featurep 'xemacs) 'efs 'ange-ftp))
8256 (setq folder (format "/%s@%s:%s" user host file))))))
8257 (when folder
8258 (funcall (cdr (assq 'vm org-link-frame-setup)) folder readonly)
8259 (sit-for 0.1)
8260 (when article
8261 (vm-select-folder-buffer)
8262 (widen)
8263 (let ((case-fold-search t))
8264 (goto-char (point-min))
8265 (if (not (re-search-forward
8266 (concat "^" "message-id: *" (regexp-quote article))))
8267 (error "Could not find the specified message in this folder"))
8268 (vm-isearch-update)
8269 (vm-isearch-narrow)
8270 (vm-beginning-of-message)
8271 (vm-summarize)))))
8273 (defun org-follow-wl-link (folder article)
8274 "Follow a Wanderlust link to FOLDER and ARTICLE."
8275 (setq article (org-add-angle-brackets article))
8276 (wl-summary-goto-folder-subr folder 'no-sync t nil t)
8277 (if article (wl-summary-jump-to-msg-by-message-id article ">"))
8278 (wl-summary-redisplay))
8280 (defun org-follow-rmail-link (folder article)
8281 "Follow an RMAIL link to FOLDER and ARTICLE."
8282 (setq article (org-add-angle-brackets article))
8283 (let (message-number)
8284 (save-excursion
8285 (save-window-excursion
8286 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
8287 (setq message-number
8288 (save-restriction
8289 (widen)
8290 (goto-char (point-max))
8291 (if (re-search-backward
8292 (concat "^Message-ID:\\s-+" (regexp-quote
8293 (or article "")))
8294 nil t)
8295 (rmail-what-message))))))
8296 (if message-number
8297 (progn
8298 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
8299 (rmail-show-message message-number)
8300 message-number)
8301 (error "Message not found"))))
8303 ;; mh-e integration based on planner-mode
8304 (defun org-mhe-get-message-real-folder ()
8305 "Return the name of the current message real folder, so if you use
8306 sequences, it will now work."
8307 (save-excursion
8308 (let* ((folder
8309 (if (equal major-mode 'mh-folder-mode)
8310 mh-current-folder
8311 ;; Refer to the show buffer
8312 mh-show-folder-buffer))
8313 (end-index
8314 (if (boundp 'mh-index-folder)
8315 (min (length mh-index-folder) (length folder))))
8317 ;; a simple test on mh-index-data does not work, because
8318 ;; mh-index-data is always nil in a show buffer.
8319 (if (and (boundp 'mh-index-folder)
8320 (string= mh-index-folder (substring folder 0 end-index)))
8321 (if (equal major-mode 'mh-show-mode)
8322 (save-window-excursion
8323 (when (buffer-live-p (get-buffer folder))
8324 (progn
8325 (pop-to-buffer folder)
8326 (org-mhe-get-message-folder-from-index)
8329 (org-mhe-get-message-folder-from-index)
8331 folder
8335 (defun org-mhe-get-message-folder-from-index ()
8336 "Returns the name of the message folder in a index folder buffer."
8337 (save-excursion
8338 (mh-index-previous-folder)
8339 (re-search-forward "^\\(+.*\\)$" nil t)
8340 (message (match-string 1))))
8342 (defun org-mhe-get-message-folder ()
8343 "Return the name of the current message folder. Be careful if you
8344 use sequences."
8345 (save-excursion
8346 (if (equal major-mode 'mh-folder-mode)
8347 mh-current-folder
8348 ;; Refer to the show buffer
8349 mh-show-folder-buffer)))
8351 (defun org-mhe-get-message-num ()
8352 "Return the number of the current message. Be careful if you
8353 use sequences."
8354 (save-excursion
8355 (if (equal major-mode 'mh-folder-mode)
8356 (mh-get-msg-num nil)
8357 ;; Refer to the show buffer
8358 (mh-show-buffer-message-number))))
8360 (defun org-mhe-get-header (header)
8361 "Return a header of the message in folder mode. This will create a
8362 show buffer for the corresponding message. If you have a more clever
8363 idea..."
8364 (let* ((folder (org-mhe-get-message-folder))
8365 (num (org-mhe-get-message-num))
8366 (buffer (get-buffer-create (concat "show-" folder)))
8367 (header-field))
8368 (with-current-buffer buffer
8369 (mh-display-msg num folder)
8370 (if (equal major-mode 'mh-folder-mode)
8371 (mh-header-display)
8372 (mh-show-header-display))
8373 (set-buffer buffer)
8374 (setq header-field (mh-get-header-field header))
8375 (if (equal major-mode 'mh-folder-mode)
8376 (mh-show)
8377 (mh-show-show))
8378 header-field)))
8380 (defun org-follow-mhe-link (folder article)
8381 "Follow an MHE link to FOLDER and ARTICLE.
8382 If ARTICLE is nil FOLDER is shown. If the configuration variable
8383 `org-mhe-search-all-folders' is t and `mh-searcher' is pick,
8384 ARTICLE is searched in all folders. Indexed searches (swish++,
8385 namazu, and others supported by MH-E) will always search in all
8386 folders."
8387 (require 'mh-e)
8388 (require 'mh-search)
8389 (require 'mh-utils)
8390 (mh-find-path)
8391 (if (not article)
8392 (mh-visit-folder (mh-normalize-folder-name folder))
8393 (setq article (org-add-angle-brackets article))
8394 (mh-search-choose)
8395 (if (equal mh-searcher 'pick)
8396 (progn
8397 (mh-search folder (list "--message-id" article))
8398 (when (and org-mhe-search-all-folders
8399 (not (org-mhe-get-message-real-folder)))
8400 (kill-this-buffer)
8401 (mh-search "+" (list "--message-id" article))))
8402 (mh-search "+" article))
8403 (if (org-mhe-get-message-real-folder)
8404 (mh-show-msg 1)
8405 (kill-this-buffer)
8406 (error "Message not found"))))
8408 ;; BibTeX links
8410 ;; Use the custom search meachnism to construct and use search strings for
8411 ;; file links to BibTeX database entries.
8413 (defun org-create-file-search-in-bibtex ()
8414 "Create the search string and description for a BibTeX database entry."
8415 (when (eq major-mode 'bibtex-mode)
8416 ;; yes, we want to construct this search string.
8417 ;; Make a good description for this entry, using names, year and the title
8418 ;; Put it into the `description' variable which is dynamically scoped.
8419 (let ((bibtex-autokey-names 1)
8420 (bibtex-autokey-names-stretch 1)
8421 (bibtex-autokey-name-case-convert-function 'identity)
8422 (bibtex-autokey-name-separator " & ")
8423 (bibtex-autokey-additional-names " et al.")
8424 (bibtex-autokey-year-length 4)
8425 (bibtex-autokey-name-year-separator " ")
8426 (bibtex-autokey-titlewords 3)
8427 (bibtex-autokey-titleword-separator " ")
8428 (bibtex-autokey-titleword-case-convert-function 'identity)
8429 (bibtex-autokey-titleword-length 'infty)
8430 (bibtex-autokey-year-title-separator ": "))
8431 (setq description (bibtex-generate-autokey)))
8432 ;; Now parse the entry, get the key and return it.
8433 (save-excursion
8434 (bibtex-beginning-of-entry)
8435 (cdr (assoc "=key=" (bibtex-parse-entry))))))
8437 (defun org-execute-file-search-in-bibtex (s)
8438 "Find the link search string S as a key for a database entry."
8439 (when (eq major-mode 'bibtex-mode)
8440 ;; Yes, we want to do the search in this file.
8441 ;; We construct a regexp that searches for "@entrytype{" followed by the key
8442 (goto-char (point-min))
8443 (and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*"
8444 (regexp-quote s) "[ \t\n]*,") nil t)
8445 (goto-char (match-beginning 0)))
8446 (if (and (match-beginning 0) (equal current-prefix-arg '(16)))
8447 ;; Use double prefix to indicate that any web link should be browsed
8448 (let ((b (current-buffer)) (p (point)))
8449 ;; Restore the window configuration because we just use the web link
8450 (set-window-configuration org-window-config-before-follow-link)
8451 (save-excursion (set-buffer b) (goto-char p)
8452 (bibtex-url)))
8453 (recenter 0)) ; Move entry start to beginning of window
8454 ;; return t to indicate that the search is done.
8457 ;; Finally add the functions to the right hooks.
8458 (add-hook 'org-create-file-search-functions 'org-create-file-search-in-bibtex)
8459 (add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-bibtex)
8461 ;; end of Bibtex link setup
8463 (defun org-upgrade-old-links (&optional query-description)
8464 "Transfer old <...> style links to new [[...]] style links.
8465 With arg query-description, ask at each match for a description text to use
8466 for this link."
8467 (interactive (list (y-or-n-p "Would you like to be queried for a description at each link?")))
8468 (save-excursion
8469 (goto-char (point-min))
8470 (let ((re (concat "\\([^[]\\)<\\("
8471 "\\(" (mapconcat 'identity org-link-types "\\|")
8472 "\\):"
8473 "[^" org-non-link-chars "]+\\)>"))
8474 l1 l2 (cnt 0))
8475 (while (re-search-forward re nil t)
8476 (setq cnt (1+ cnt)
8477 l1 (org-match-string-no-properties 2)
8478 l2 (save-match-data (org-link-escape l1)))
8479 (when query-description (setq l1 (read-string "Desc: " l1)))
8480 (if (equal l1 l2)
8481 (replace-match (concat (match-string 1) "[[" l1 "]]") t t)
8482 (replace-match (concat (match-string 1) "[[" l2 "][" l1 "]]") t t)))
8483 (message "%d matches have beed treated" cnt))))
8485 (defun org-open-file (path &optional in-emacs line search)
8486 "Open the file at PATH.
8487 First, this expands any special file name abbreviations. Then the
8488 configuration variable `org-file-apps' is checked if it contains an
8489 entry for this file type, and if yes, the corresponding command is launched.
8490 If no application is found, Emacs simply visits the file.
8491 With optional argument IN-EMACS, Emacs will visit the file.
8492 Optional LINE specifies a line to go to, optional SEARCH a string to
8493 search for. If LINE or SEARCH is given, the file will always be
8494 opened in Emacs.
8495 If the file does not exist, an error is thrown."
8496 (setq in-emacs (or in-emacs line search))
8497 (let* ((file (if (equal path "")
8498 buffer-file-name
8499 (convert-standard-filename (org-expand-file-name path))))
8500 (dirp (file-directory-p file))
8501 (dfile (downcase file))
8502 (old-buffer (current-buffer))
8503 (old-pos (point))
8504 (old-mode major-mode)
8505 ext cmd apps)
8506 (if (and (not (file-exists-p file))
8507 (not org-open-non-existing-files))
8508 (error "No such file: %s" file))
8509 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
8510 (setq ext (match-string 1 dfile))
8511 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
8512 (setq ext (match-string 1 dfile))))
8513 (setq apps (append org-file-apps (org-default-apps)))
8514 (if in-emacs
8515 (setq cmd 'emacs)
8516 (setq cmd (or (and dirp (cdr (assoc 'directory apps)))
8517 (cdr (assoc ext apps))
8518 (cdr (assoc t apps)))))
8519 (when (eq cmd 'mailcap)
8520 (require 'mailcap)
8521 (mailcap-parse-mailcaps)
8522 (let* ((mime-type (mailcap-extension-to-mime (or ext "")))
8523 (command (mailcap-mime-info mime-type)))
8524 (if (stringp command)
8525 (setq cmd command)
8526 (setq cmd 'emacs))))
8527 (cond
8528 ((and (stringp cmd) (not (string-match "^\\s-*$" cmd)))
8529 ;; Normalize use of quote, this can vary.
8530 (if (string-match "['\"]%s['\"]" cmd)
8531 (setq cmd (replace-match "'%s'" t t cmd)))
8532 (setq cmd (format cmd file))
8533 (save-window-excursion
8534 (shell-command (concat cmd " &"))))
8535 ((or (stringp cmd)
8536 (eq cmd 'emacs))
8537 (unless (equal (file-truename file) (file-truename (or buffer-file-name "")))
8538 (funcall (cdr (assq 'file org-link-frame-setup)) file))
8539 (if line (goto-line line)
8540 (if search (org-link-search search))))
8541 ((consp cmd)
8542 (eval cmd))
8543 (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
8544 (and (eq major-mode 'org-mode) (eq old-mode 'org-mode)
8545 (or (not (equal old-buffer (current-buffer)))
8546 (not (equal old-pos (point))))
8547 (org-mark-ring-push old-pos old-buffer))))
8549 (defun org-default-apps ()
8550 "Return the default applications for this operating system."
8551 (cond
8552 ((eq system-type 'darwin)
8553 org-file-apps-defaults-macosx)
8554 ((eq system-type 'windows-nt)
8555 org-file-apps-defaults-windowsnt)
8556 (t org-file-apps-defaults-gnu)))
8558 (defun org-expand-file-name (path)
8559 "Replace special path abbreviations and expand the file name."
8560 (expand-file-name path))
8563 (defvar org-insert-link-history nil
8564 "Minibuffer history for links inserted with `org-insert-link'.")
8566 (defvar org-stored-links nil
8567 "Contains the links stored with `org-store-link'.")
8569 ;;;###autoload
8570 (defun org-store-link (arg)
8571 "\\<org-mode-map>Store an org-link to the current location.
8572 This link can later be inserted into an org-buffer with
8573 \\[org-insert-link].
8574 For some link types, a prefix arg is interpreted:
8575 For links to usenet articles, arg negates `org-usenet-links-prefer-google'.
8576 For file links, arg negates `org-context-in-file-links'."
8577 (interactive "P")
8578 (let (link cpltxt desc description search txt (pos (point)))
8579 (cond
8581 ((eq major-mode 'bbdb-mode)
8582 (setq cpltxt (concat
8583 "bbdb:"
8584 (or (bbdb-record-name (bbdb-current-record))
8585 (bbdb-record-company (bbdb-current-record))))
8586 link (org-make-link cpltxt)))
8588 ((eq major-mode 'Info-mode)
8589 (setq link (org-make-link "info:"
8590 (file-name-nondirectory Info-current-file)
8591 ":" Info-current-node))
8592 (setq cpltxt (concat (file-name-nondirectory Info-current-file)
8593 ":" Info-current-node)))
8595 ((eq major-mode 'calendar-mode)
8596 (let ((cd (calendar-cursor-to-date)))
8597 (setq link
8598 (format-time-string
8599 (car org-time-stamp-formats)
8600 (apply 'encode-time
8601 (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
8602 nil nil nil))))))
8604 ((or (eq major-mode 'vm-summary-mode)
8605 (eq major-mode 'vm-presentation-mode))
8606 (and (eq major-mode 'vm-presentation-mode) (vm-summarize))
8607 (vm-follow-summary-cursor)
8608 (save-excursion
8609 (vm-select-folder-buffer)
8610 (let* ((message (car vm-message-pointer))
8611 (folder buffer-file-name)
8612 (subject (vm-su-subject message))
8613 (author (vm-su-full-name message))
8614 (message-id (vm-su-message-id message)))
8615 (setq message-id (org-remove-angle-brackets message-id))
8616 (setq folder (abbreviate-file-name folder))
8617 (if (string-match (concat "^" (regexp-quote vm-folder-directory))
8618 folder)
8619 (setq folder (replace-match "" t t folder)))
8620 (setq cpltxt (concat author " on: " subject))
8621 (setq link (org-make-link "vm:" folder "#" message-id)))))
8623 ((eq major-mode 'wl-summary-mode)
8624 (let* ((msgnum (wl-summary-message-number))
8625 (message-id (elmo-message-field wl-summary-buffer-elmo-folder
8626 msgnum 'message-id))
8627 (wl-message-entity (elmo-msgdb-overview-get-entity
8628 msgnum (wl-summary-buffer-msgdb)))
8629 (author (wl-summary-line-from)) ; FIXME: correct?
8630 (subject "???")) ; FIXME:
8631 (setq message-id (org-remove-angle-brackets message-id))
8632 (setq cpltxt (concat author " on: " subject))
8633 (setq link (org-make-link "wl:" wl-summary-buffer-folder-name
8634 "#" message-id))))
8636 ((or (equal major-mode 'mh-folder-mode)
8637 (equal major-mode 'mh-show-mode))
8638 (let ((from-header (org-mhe-get-header "From:"))
8639 (to-header (org-mhe-get-header "To:"))
8640 (subject (org-mhe-get-header "Subject:")))
8641 (setq cpltxt (concat from-header " on: " subject))
8642 (setq link (org-make-link "mhe:" (org-mhe-get-message-real-folder) "#"
8643 (org-remove-angle-brackets
8644 (org-mhe-get-header "Message-Id:"))))))
8646 ((eq major-mode 'rmail-mode)
8647 (save-excursion
8648 (save-restriction
8649 (rmail-narrow-to-non-pruned-header)
8650 (let ((folder buffer-file-name)
8651 (message-id (mail-fetch-field "message-id"))
8652 (author (mail-fetch-field "from"))
8653 (subject (mail-fetch-field "subject")))
8654 (setq message-id (org-remove-angle-brackets message-id))
8655 (setq cpltxt (concat author " on: " subject))
8656 (setq link (org-make-link "rmail:" folder "#" message-id))))))
8658 ((eq major-mode 'gnus-group-mode)
8659 (let ((group (cond ((fboundp 'gnus-group-group-name) ; depending on Gnus
8660 (gnus-group-group-name)) ; version
8661 ((fboundp 'gnus-group-name)
8662 (gnus-group-name))
8663 (t "???"))))
8664 (setq cpltxt (concat
8665 (if (org-xor arg org-usenet-links-prefer-google)
8666 "http://groups.google.com/groups?group="
8667 "gnus:")
8668 group)
8669 link (org-make-link cpltxt))))
8671 ((memq major-mode '(gnus-summary-mode gnus-article-mode))
8672 (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary))
8673 (gnus-summary-beginning-of-article)
8674 (let* ((group (car gnus-article-current))
8675 (article (cdr gnus-article-current))
8676 (header (gnus-summary-article-header article))
8677 (author (mail-header-from header))
8678 (message-id (mail-header-id header))
8679 (date (mail-header-date header))
8680 (subject (gnus-summary-subject-string)))
8681 (setq cpltxt (concat author " on: " subject))
8682 (if (org-xor arg org-usenet-links-prefer-google)
8683 (setq link
8684 (concat
8685 cpltxt "\n "
8686 (format "http://groups.google.com/groups?as_umsgid=%s"
8687 (org-fixup-message-id-for-http message-id))))
8688 (setq link (org-make-link "gnus:" group
8689 "#" (number-to-string article))))))
8691 ((eq major-mode 'w3-mode)
8692 (setq cpltxt (url-view-url t)
8693 link (org-make-link cpltxt)))
8694 ((eq major-mode 'w3m-mode)
8695 (setq cpltxt w3m-current-url
8696 link (org-make-link cpltxt)))
8698 ((setq search (run-hook-with-args-until-success
8699 'org-create-file-search-functions))
8700 (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
8701 "::" search))
8702 (setq cpltxt (or description link))) ;; FIXME: is this the best way?
8704 ((eq major-mode 'org-mode)
8705 ;; Just link to current headline
8706 (setq cpltxt (concat "file:"
8707 (abbreviate-file-name buffer-file-name)))
8708 ;; Add a context search string
8709 (when (org-xor org-context-in-file-links arg)
8710 ;; Check if we are on a target
8711 (if (save-excursion
8712 (skip-chars-forward "^>\n\r")
8713 (and (re-search-backward "<<" nil t)
8714 (looking-at "<<\\(.*?\\)>>")
8715 (<= (match-beginning 0) pos)
8716 (>= (match-end 0) pos)))
8717 (setq cpltxt (concat cpltxt "::" (match-string 1)))
8718 (setq txt (cond
8719 ((org-on-heading-p) nil)
8720 ((org-region-active-p)
8721 (buffer-substring (region-beginning) (region-end)))
8722 (t (buffer-substring (point-at-bol) (point-at-eol)))))
8723 (when (string-match "\\S-" txt)
8724 (setq cpltxt
8725 (concat cpltxt "::"
8726 (if org-file-link-context-use-camel-case
8727 (org-make-org-heading-camel txt)
8728 (org-make-org-heading-search-string txt)))
8729 desc "NONE"))))
8730 (if (string-match "::\\'" cpltxt)
8731 (setq cpltxt (substring cpltxt 0 -2)))
8732 (setq link (org-make-link cpltxt)))
8734 (buffer-file-name
8735 ;; Just link to this file here.
8736 (setq cpltxt (concat "file:"
8737 (abbreviate-file-name buffer-file-name)))
8738 ;; Add a context string
8739 (when (org-xor org-context-in-file-links arg)
8740 (setq txt (if (org-region-active-p)
8741 (buffer-substring (region-beginning) (region-end))
8742 (buffer-substring (point-at-bol) (point-at-eol))))
8743 ;; Only use search option if there is some text.
8744 (when (string-match "\\S-" txt)
8745 (setq cpltxt
8746 (concat cpltxt "::"
8747 (if org-file-link-context-use-camel-case
8748 (org-make-org-heading-camel txt)
8749 (org-make-org-heading-search-string txt)))
8750 desc "NONE")))
8751 (setq link (org-make-link cpltxt)))
8753 ((interactive-p)
8754 (error "Cannot link to a buffer which is not visiting a file"))
8756 (t (setq link nil)))
8758 (if (consp link) (setq cpltxt (car link) link (cdr link)))
8759 (setq link (or link cpltxt)
8760 desc (or desc cpltxt))
8761 (if (equal desc "NONE") (setq desc nil))
8763 (if (and (interactive-p) link)
8764 (progn
8765 (setq org-stored-links
8766 (cons (list cpltxt link desc) org-stored-links))
8767 (message "Stored: %s" (or cpltxt link)))
8768 (org-make-link-string link desc))))
8770 (defun org-make-org-heading-search-string (&optional string heading)
8771 "Make search string for STRING or current headline."
8772 (interactive)
8773 (let ((s (or string (org-get-heading))))
8774 (unless (and string (not heading))
8775 ;; We are using a headline, clean up garbage in there.
8776 (if (string-match org-todo-regexp s)
8777 (setq s (replace-match "" t t s)))
8778 (if (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" s)
8779 (setq s (replace-match "" t t s)))
8780 (setq s (org-trim s))
8781 (if (string-match (concat "^\\(" org-quote-string "\\|"
8782 org-comment-string "\\)") s)
8783 (setq s (replace-match "" t t s)))
8784 (while (string-match org-ts-regexp s)
8785 (setq s (replace-match "" t t s))))
8786 (while (string-match "[^a-zA-Z_0-9 \t]+" s)
8787 (setq s (replace-match " " t t s)))
8788 (or string (setq s (concat "*" s))) ; Add * for headlines
8789 (mapconcat 'identity (org-split-string s "[ \t]+") " ")))
8791 (defun org-make-org-heading-camel (&optional string heading)
8792 "Make a CamelCase string for STRING or the current headline."
8793 (interactive)
8794 (let ((s (or string (org-get-heading))))
8795 (unless (and string (not heading))
8796 ;; We are using a headline, clean up garbage in there.
8797 (if (string-match org-todo-regexp s)
8798 (setq s (replace-match "" t t s)))
8799 (if (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" s)
8800 (setq s (replace-match "" t t s)))
8801 (setq s (org-trim s))
8802 (if (string-match (concat "^\\(" org-quote-string "\\|"
8803 org-comment-string "\\)") s)
8804 (setq s (replace-match "" t t s)))
8805 (while (string-match org-ts-regexp s)
8806 (setq s (replace-match "" t t s))))
8807 (while (string-match "[^a-zA-Z_ \t]+" s)
8808 (setq s (replace-match " " t t s)))
8809 (or string (setq s (concat "*" s))) ; Add * for headlines
8810 (mapconcat 'capitalize (org-split-string s "[ \t]+") "")))
8812 (defun org-make-link (&rest strings)
8813 "Concatenate STRINGS, format resulting string with `org-link-format'."
8814 (format org-link-format (apply 'concat strings)))
8816 (defun org-make-link-string (link &optional description)
8817 "Make a link with brackets, consisting of LINK and DESCRIPTION."
8818 (if (eq org-link-style 'plain)
8819 (if (equal description link)
8820 link
8821 (concat description "\n" link))
8822 (when (stringp description)
8823 ;; Remove brackets from the description, they are fatal.
8824 (while (string-match "\\[\\|\\]" description)
8825 (setq description (replace-match "" t t description))))
8826 (when (equal (org-link-escape link) description)
8827 ;; No description needed, it is identical
8828 (setq description nil))
8829 (when (and (not description)
8830 (not (equal link (org-link-escape link))))
8831 (setq description link))
8832 (concat "[[" (org-link-escape link) "]"
8833 (if description (concat "[" description "]") "")
8834 "]")))
8836 (defconst org-link-escape-chars '(("[" . "%5B") ("]" . "%5D") (" " . "%20"))
8837 "Association list of escapes for some characters problematic in links.")
8839 (defun org-link-escape (text)
8840 "Escape charaters in TEXT that are problematic for links."
8841 (when text
8842 (let ((re (mapconcat (lambda (x) (regexp-quote (car x)))
8843 org-link-escape-chars "\\|")))
8844 (while (string-match re text)
8845 (setq text
8846 (replace-match
8847 (cdr (assoc (match-string 0 text) org-link-escape-chars))
8848 t t text)))
8849 text)))
8851 (defun org-link-unescape (text)
8852 "Reverse the action of `org-link-escape'."
8853 (when text
8854 (let ((re (mapconcat (lambda (x) (regexp-quote (cdr x)))
8855 org-link-escape-chars "\\|")))
8856 (while (string-match re text)
8857 (setq text
8858 (replace-match
8859 (car (rassoc (match-string 0 text) org-link-escape-chars))
8860 t t text)))
8861 text)))
8863 (defun org-xor (a b)
8864 "Exclusive or."
8865 (if a (not b) b))
8867 (defun org-get-header (header)
8868 "Find a header field in the current buffer."
8869 (save-excursion
8870 (goto-char (point-min))
8871 (let ((case-fold-search t) s)
8872 (cond
8873 ((eq header 'from)
8874 (if (re-search-forward "^From:\\s-+\\(.*\\)" nil t)
8875 (setq s (match-string 1)))
8876 (while (string-match "\"" s)
8877 (setq s (replace-match "" t t s)))
8878 (if (string-match "[<(].*" s)
8879 (setq s (replace-match "" t t s))))
8880 ((eq header 'message-id)
8881 (if (re-search-forward "^message-id:\\s-+\\(.*\\)" nil t)
8882 (setq s (match-string 1))))
8883 ((eq header 'subject)
8884 (if (re-search-forward "^subject:\\s-+\\(.*\\)" nil t)
8885 (setq s (match-string 1)))))
8886 (if (string-match "\\`[ \t\]+" s) (setq s (replace-match "" t t s)))
8887 (if (string-match "[ \t\]+\\'" s) (setq s (replace-match "" t t s)))
8888 s)))
8891 (defun org-fixup-message-id-for-http (s)
8892 "Replace special characters in a message id, so it can be used in an http query."
8893 (while (string-match "<" s)
8894 (setq s (replace-match "%3C" t t s)))
8895 (while (string-match ">" s)
8896 (setq s (replace-match "%3E" t t s)))
8897 (while (string-match "@" s)
8898 (setq s (replace-match "%40" t t s)))
8901 (defun org-insert-link (&optional complete-file)
8902 "Insert a link. At the prompt, enter the link.
8904 Completion can be used to select a link previously stored with
8905 `org-store-link'. When the empty string is entered (i.e. if you just
8906 press RET at the prompt), the link defaults to the most recently
8907 stored link. As SPC triggers completion in the minibuffer, you need to
8908 use M-SPC or C-q SPC to force the insertion of a space character.
8910 You will also be prompted for a description, and if one is given, it will
8911 be displayed in the buffer instead of the link.
8913 If there is already a link at point, this command will allow you to edit link
8914 and description parts.
8916 With a \\[universal-argument] prefix, prompts for a file to link to. The file name can be
8917 selected using completion. The path to the file will be relative to
8918 the current directory if the file is in the current directory or a
8919 subdirectory. Otherwise, the link will be the absolute path as
8920 completed in the minibuffer (i.e. normally ~/path/to/file).
8922 With two \\[universal-argument] prefixes, enforce an absolute path even if the file
8923 is in the current directory or below."
8924 (interactive "P")
8925 (let (link desc entry remove file (pos (point)))
8926 (cond
8927 ((save-excursion
8928 (skip-chars-forward "^]\n\r")
8929 (and (re-search-backward "\\[\\[" nil t)
8930 (looking-at org-bracket-link-regexp)
8931 (<= (match-beginning 0) pos)
8932 (>= (match-end 0) pos)))
8933 ;; We do have a link at point, and we are going to edit it.
8934 (setq remove (list (match-beginning 0) (match-end 0)))
8935 (setq desc (if (match-end 3) (org-match-string-no-properties 3)))
8936 (setq link (read-string "Link: "
8937 (org-link-unescape
8938 (org-match-string-no-properties 1)))))
8939 (complete-file
8940 ;; Completing read for file names.
8941 (setq file (read-file-name "File: "))
8942 (let ((pwd (file-name-as-directory (expand-file-name ".")))
8943 (pwd1 (file-name-as-directory (abbreviate-file-name
8944 (expand-file-name ".")))))
8945 (cond
8946 ((equal complete-file '(16))
8947 (setq link (org-make-link
8948 "file:"
8949 (abbreviate-file-name (expand-file-name file)))))
8950 ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
8951 (setq link (org-make-link "file:" (match-string 1 file))))
8952 ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
8953 (expand-file-name file))
8954 (setq link (org-make-link
8955 "file:" (match-string 1 (expand-file-name file)))))
8956 (t (setq link (org-make-link "file:" file))))))
8958 ;; Read link, with completion for stored links.
8959 (setq link (org-completing-read
8960 "Link: " org-stored-links nil nil nil
8961 org-insert-link-history
8962 (or (car (car org-stored-links)))))
8963 (setq entry (assoc link org-stored-links))
8964 (if (not org-keep-stored-link-after-insertion)
8965 (setq org-stored-links (delq (assoc link org-stored-links)
8966 org-stored-links)))
8967 (setq link (if entry (nth 1 entry) link)
8968 desc (or desc (nth 2 entry)))))
8970 (if (string-match org-plain-link-re link)
8971 ;; URL-like link, normalize the use of angular brackets.
8972 (setq link (org-make-link (org-remove-angle-brackets link))))
8974 ;; Check if we are linking to the current file with a search option
8975 ;; If yes, simplify the link by using only the search option.
8976 (when (string-match "\\<file:\\(.+?\\)::\\([^>]+\\)" link)
8977 (let* ((path (match-string 1 link))
8978 (case-fold-search nil)
8979 (search (match-string 2 link)))
8980 (save-match-data
8981 (if (equal (file-truename buffer-file-name) (file-truename path))
8982 ;; We are linking to this same file, with a search option
8983 (setq link search)))))
8985 ;; Check if we can/should use a relative path. If yes, simplify the link
8986 (when (string-match "\\<file:\\(.*\\)" link)
8987 (let* ((path (match-string 1 link))
8988 (case-fold-search nil))
8989 (cond
8990 ((eq org-link-file-path-type 'absolute)
8991 (setq path (abbreviate-file-name (expand-file-name path))))
8992 ((eq org-link-file-path-type 'noabbrev)
8993 (setq path (expand-file-name path)))
8994 ((eq org-link-file-path-type 'relative)
8995 (setq path (file-relative-name path)))
8997 (save-match-data
8998 (if (string-match (concat "^" (regexp-quote
8999 (file-name-as-directory
9000 (expand-file-name "."))))
9001 (expand-file-name path))
9002 ;; We are linking a file with relative path name.
9003 (setq path (substring (expand-file-name path)
9004 (match-end 0)))))))
9005 (setq link (concat "file:" path))))
9007 (setq desc (read-string "Description: " desc))
9008 (unless (string-match "\\S-" desc) (setq desc nil))
9009 (if remove (apply 'delete-region remove))
9010 (insert (org-make-link-string link desc))))
9012 (defun org-completing-read (&rest args)
9013 (let ((minibuffer-local-completion-map
9014 (copy-keymap minibuffer-local-completion-map)))
9015 (define-key minibuffer-local-completion-map " " 'self-insert-command)
9016 (apply 'completing-read args)))
9018 ;;; Hooks for remember.el
9020 (defvar org-finish-function nil)
9022 ;;;###autoload
9023 (defun org-remember-annotation ()
9024 "Return a link to the current location as an annotation for remember.el.
9025 If you are using Org-mode files as target for data storage with
9026 remember.el, then the annotations should include a link compatible with the
9027 conventions in Org-mode. This function returns such a link."
9028 (org-store-link nil))
9030 (defconst org-remember-help
9031 "Select a destination location for the note.
9032 UP/DOWN=headline TAB=cycle visibility [Q]uit RET/<left>/<right>=Store
9033 RET at beg-of-buf -> Append to file as level 2 headline
9034 RET on headline -> Store as sublevel entry to current headline
9035 <left>/<right> -> before/after current headline, same headings level")
9037 ;;;###autoload
9038 (defun org-remember-apply-template ()
9039 "Initialize *remember* buffer with template, invoke `org-mode'.
9040 This function should be placed into `remember-mode-hook' and in fact requires
9041 to be run from that hook to fucntion properly."
9042 (if org-remember-templates
9044 (let* ((entry (if (= (length org-remember-templates) 1)
9045 (cdar org-remember-templates)
9046 (message "Select template: %s"
9047 (mapconcat
9048 (lambda (x) (char-to-string (car x)))
9049 org-remember-templates " "))
9050 (cdr (assoc (read-char-exclusive) org-remember-templates))))
9051 (tpl (car entry))
9052 (file (if (consp (cdr entry)) (nth 1 entry)))
9053 (v-t (format-time-string (car org-time-stamp-formats) (org-current-time)))
9054 (v-T (format-time-string (cdr org-time-stamp-formats) (org-current-time)))
9055 (v-u (concat "[" (substring v-t 1 -1) "]"))
9056 (v-U (concat "[" (substring v-T 1 -1) "]"))
9057 (v-a annotation) ; defined in `remember-mode'
9058 (v-i initial) ; defined in `remember-mode'
9059 (v-n user-full-name)
9061 (unless tpl (setq tpl "") (message "No template") (ding))
9062 (insert tpl) (goto-char (point-min))
9063 (while (re-search-forward "%\\([tTuTai]\\)" nil t)
9064 (when (and initial (equal (match-string 0) "%i"))
9065 (save-match-data
9066 (let* ((lead (buffer-substring
9067 (point-at-bol) (match-beginning 0))))
9068 (setq v-i (mapconcat 'identity
9069 (org-split-string initial "\n")
9070 (concat "\n" lead))))))
9071 (replace-match
9072 (or (eval (intern (concat "v-" (match-string 1)))) "")
9073 t t))
9074 (let ((org-startup-folded nil)
9075 (org-startup-with-deadline-check nil))
9076 (org-mode))
9077 (if (and file (string-match "\\S-" file) (not (file-directory-p file)))
9078 (set (make-local-variable 'org-default-notes-file) file))
9079 (goto-char (point-min))
9080 (if (re-search-forward "%\\?" nil t) (replace-match "")))
9081 (let ((org-startup-folded nil)
9082 (org-startup-with-deadline-check nil))
9083 (org-mode)))
9084 (set (make-local-variable 'org-finish-function) 'remember-buffer))
9086 ;;;###autoload
9087 (defun org-remember-handler ()
9088 "Store stuff from remember.el into an org file.
9089 First prompts for an org file. If the user just presses return, the value
9090 of `org-default-notes-file' is used.
9091 Then the command offers the headings tree of the selected file in order to
9092 file the text at a specific location.
9093 You can either immediately press RET to get the note appended to the
9094 file, or you can use vertical cursor motion and visibility cycling (TAB) to
9095 find a better place. Then press RET or <left> or <right> in insert the note.
9097 Key Cursor position Note gets inserted
9098 -----------------------------------------------------------------------------
9099 RET buffer-start as level 2 heading at end of file
9100 RET on headline as sublevel of the heading at cursor
9101 RET no heading at cursor position, level taken from context.
9102 Or use prefix arg to specify level manually.
9103 <left> on headline as same level, before current heading
9104 <right> on headline as same level, after current heading
9106 So the fastest way to store the note is to press RET RET to append it to
9107 the default file. This way your current train of thought is not
9108 interrupted, in accordance with the principles of remember.el. But with
9109 little extra effort, you can push it directly to the correct location.
9111 Before being stored away, the function ensures that the text has a
9112 headline, i.e. a first line that starts with a \"*\". If not, a headline
9113 is constructed from the current date and some additional data.
9115 If the variable `org-adapt-indentation' is non-nil, the entire text is
9116 also indented so that it starts in the same column as the headline
9117 \(i.e. after the stars).
9119 See also the variable `org-reverse-note-order'."
9120 (catch 'quit
9121 (let* ((txt (buffer-substring (point-min) (point-max)))
9122 (fastp current-prefix-arg)
9123 (file (if fastp org-default-notes-file (org-get-org-file)))
9124 (visiting (find-buffer-visiting file))
9125 (org-startup-with-deadline-check nil)
9126 (org-startup-folded nil)
9127 (org-startup-align-all-tables nil)
9128 spos level indent reversed)
9129 ;; Modify text so that it becomes a nice subtree which can be inserted
9130 ;; into an org tree.
9131 (let* ((lines (split-string txt "\n"))
9132 first)
9133 ;; remove empty lines at the beginning
9134 (while (and lines (string-match "^[ \t]*\n" (car lines)))
9135 (setq lines (cdr lines)))
9136 (setq first (car lines) lines (cdr lines))
9137 (if (string-match "^\\*+" first)
9138 ;; Is already a headline
9139 (setq indent nil)
9140 ;; We need to add a headline: Use time and first buffer line
9141 (setq lines (cons first lines)
9142 first (concat "* " (current-time-string)
9143 " (" (remember-buffer-desc) ")")
9144 indent " "))
9145 (if (and org-adapt-indentation indent)
9146 (setq lines (mapcar (lambda (x) (concat indent x)) lines)))
9147 (setq txt (concat first "\n"
9148 (mapconcat 'identity lines "\n"))))
9149 ;; Find the file
9150 (if (not visiting)
9151 (find-file-noselect file))
9152 (with-current-buffer (get-file-buffer file)
9153 (save-excursion (and (goto-char (point-min))
9154 (not (re-search-forward "^\\* " nil t))
9155 (insert "\n* Notes\n")))
9156 (setq reversed (org-notes-order-reversed-p))
9157 (save-excursion
9158 (save-restriction
9159 (widen)
9160 ;; Ask the User for a location
9161 (setq spos (if fastp 1 (org-get-location
9162 (current-buffer)
9163 org-remember-help)))
9164 (if (not spos) (throw 'quit nil)) ; return nil to show we did
9165 ; not handle this note
9166 (goto-char spos)
9167 (cond ((bobp)
9168 ;; Put it at the start or end, as level 2
9169 (save-restriction
9170 (widen)
9171 (goto-char (if reversed (point-min) (point-max)))
9172 (if (not (bolp)) (newline))
9173 (org-paste-subtree 2 txt)))
9174 ((and (org-on-heading-p nil) (not current-prefix-arg))
9175 ;; Put it below this entry, at the beg/end of the subtree
9176 (org-back-to-heading)
9177 (setq level (funcall outline-level))
9178 (if reversed
9179 (outline-end-of-heading)
9180 (outline-end-of-subtree))
9181 (if (not (bolp)) (newline))
9182 (beginning-of-line 1)
9183 (org-paste-subtree (1+ level) txt))
9185 ;; Put it right there, with automatic level determined by
9186 ;; org-paste-subtree or from prefix arg
9187 (org-paste-subtree current-prefix-arg txt)))
9188 (when remember-save-after-remembering
9189 (save-buffer)
9190 (if (not visiting) (kill-buffer (current-buffer)))))))))
9191 t) ;; return t to indicate that we took care of this note.
9193 (defun org-get-org-file ()
9194 "Read a filename, with default directory `org-directory'."
9195 (let ((default (or org-default-notes-file remember-data-file)))
9196 (read-file-name (format "File name [%s]: " default)
9197 (file-name-as-directory org-directory)
9198 default)))
9200 (defun org-notes-order-reversed-p ()
9201 "Check if the current file should receive notes in reversed order."
9202 (cond
9203 ((not org-reverse-note-order) nil)
9204 ((eq t org-reverse-note-order) t)
9205 ((not (listp org-reverse-note-order)) nil)
9206 (t (catch 'exit
9207 (let ((all org-reverse-note-order)
9208 entry)
9209 (while (setq entry (pop all))
9210 (if (string-match (car entry) buffer-file-name)
9211 (throw 'exit (cdr entry))))
9212 nil)))))
9214 ;;; Tables
9216 ;; Watch out: Here we are talking about two different kind of tables.
9217 ;; Most of the code is for the tables created with the Org-mode table editor.
9218 ;; Sometimes, we talk about tables created and edited with the table.el
9219 ;; Emacs package. We call the former org-type tables, and the latter
9220 ;; table.el-type tables.
9223 (defun org-before-change-function (beg end)
9224 "Every change indicates that a table might need an update."
9225 (setq org-table-may-need-update t))
9227 (defconst org-table-line-regexp "^[ \t]*|"
9228 "Detects an org-type table line.")
9229 (defconst org-table-dataline-regexp "^[ \t]*|[^-]"
9230 "Detects an org-type table line.")
9231 (defconst org-table-auto-recalculate-regexp "^[ \t]*| *# *\\(|\\|$\\)"
9232 "Detects a table line marked for automatic recalculation.")
9233 (defconst org-table-recalculate-regexp "^[ \t]*| *[#*] *\\(|\\|$\\)"
9234 "Detects a table line marked for automatic recalculation.")
9235 (defconst org-table-calculate-mark-regexp "^[ \t]*| *[!$^_#*] *\\(|\\|$\\)"
9236 "Detects a table line marked for automatic recalculation.")
9237 (defconst org-table-hline-regexp "^[ \t]*|-"
9238 "Detects an org-type table hline.")
9239 (defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]"
9240 "Detects a table-type table hline.")
9241 (defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)"
9242 "Detects an org-type or table-type table.")
9243 (defconst org-table-border-regexp "^[ \t]*[^| \t]"
9244 "Searching from within a table (any type) this finds the first line
9245 outside the table.")
9246 (defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]"
9247 "Searching from within a table (any type) this finds the first line
9248 outside the table.")
9250 (defun org-table-create-with-table.el ()
9251 "Use the table.el package to insert a new table.
9252 If there is already a table at point, convert between Org-mode tables
9253 and table.el tables."
9254 (interactive)
9255 (require 'table)
9256 (cond
9257 ((org-at-table.el-p)
9258 (if (y-or-n-p "Convert table to Org-mode table? ")
9259 (org-table-convert)))
9260 ((org-at-table-p)
9261 (if (y-or-n-p "Convert table to table.el table? ")
9262 (org-table-convert)))
9263 (t (call-interactively 'table-insert))))
9265 (defun org-table-create-or-convert-from-region (arg)
9266 "Convert region to table, or create an empty table.
9267 If there is an active region, convert it to a table. If there is no such
9268 region, create an empty table."
9269 (interactive "P")
9270 (if (org-region-active-p)
9271 (org-table-convert-region (region-beginning) (region-end) arg)
9272 (org-table-create arg)))
9274 (defun org-table-create (&optional size)
9275 "Query for a size and insert a table skeleton.
9276 SIZE is a string Columns x Rows like for example \"3x2\"."
9277 (interactive "P")
9278 (unless size
9279 (setq size (read-string
9280 (concat "Table size Columns x Rows [e.g. "
9281 org-table-default-size "]: ")
9282 "" nil org-table-default-size)))
9284 (let* ((pos (point))
9285 (indent (make-string (current-column) ?\ ))
9286 (split (org-split-string size " *x *"))
9287 (rows (string-to-number (nth 1 split)))
9288 (columns (string-to-number (car split)))
9289 (line (concat (apply 'concat indent "|" (make-list columns " |"))
9290 "\n")))
9291 (if (string-match "^[ \t]*$" (buffer-substring-no-properties
9292 (point-at-bol) (point)))
9293 (beginning-of-line 1)
9294 (newline))
9295 ;; (mapcar (lambda (x) (insert line)) (make-list rows t))
9296 (dotimes (i rows) (insert line))
9297 (goto-char pos)
9298 (if (> rows 1)
9299 ;; Insert a hline after the first row.
9300 (progn
9301 (end-of-line 1)
9302 (insert "\n|-")
9303 (goto-char pos)))
9304 (org-table-align)))
9306 (defun org-table-convert-region (beg0 end0 &optional nspace)
9307 "Convert region to a table.
9308 The region goes from BEG0 to END0, but these borders will be moved
9309 slightly, to make sure a beginning of line in the first line is included.
9310 When NSPACE is non-nil, it indicates the minimum number of spaces that
9311 separate columns (default: just one space)."
9312 (interactive "rP")
9313 (let* ((beg (min beg0 end0))
9314 (end (max beg0 end0))
9315 (tabsep t)
9317 (goto-char beg)
9318 (beginning-of-line 1)
9319 (setq beg (move-marker (make-marker) (point)))
9320 (goto-char end)
9321 (if (bolp) (backward-char 1) (end-of-line 1))
9322 (setq end (move-marker (make-marker) (point)))
9323 ;; Lets see if this is tab-separated material. If every nonempty line
9324 ;; contains a tab, we will assume that it is tab-separated material
9325 (if nspace
9326 (setq tabsep nil)
9327 (goto-char beg)
9328 (and (re-search-forward "^[^\n\t]+$" end t) (setq tabsep nil)))
9329 (if nspace (setq tabsep nil))
9330 (if tabsep
9331 (setq re "^\\|\t")
9332 (setq re (format "^ *\\| *\t *\\| \\{%d,\\}"
9333 (max 1 (prefix-numeric-value nspace)))))
9334 (goto-char beg)
9335 (while (re-search-forward re end t)
9336 (replace-match "|" t t))
9337 (goto-char beg)
9338 (insert " ")
9339 (org-table-align)))
9341 (defun org-table-import (file arg)
9342 "Import FILE as a table.
9343 The file is assumed to be tab-separated. Such files can be produced by most
9344 spreadsheet and database applications. If no tabs (at least one per line)
9345 are found, lines will be split on whitespace into fields."
9346 (interactive "f\nP")
9347 (or (bolp) (newline))
9348 (let ((beg (point))
9349 (pm (point-max)))
9350 (insert-file-contents file)
9351 (org-table-convert-region beg (+ (point) (- (point-max) pm)) arg)))
9353 (defun org-table-export ()
9354 "Export table as a tab-separated file.
9355 Such a file can be imported into a spreadsheet program like Excel."
9356 (interactive)
9357 (let* ((beg (org-table-begin))
9358 (end (org-table-end))
9359 (table (buffer-substring beg end))
9360 (file (read-file-name "Export table to: "))
9361 buf)
9362 (unless (or (not (file-exists-p file))
9363 (y-or-n-p (format "Overwrite file %s? " file)))
9364 (error "Abort"))
9365 (with-current-buffer (find-file-noselect file)
9366 (setq buf (current-buffer))
9367 (erase-buffer)
9368 (fundamental-mode)
9369 (insert table)
9370 (goto-char (point-min))
9371 (while (re-search-forward "^[ \t]*|[ \t]*" nil t)
9372 (replace-match "" t t)
9373 (end-of-line 1))
9374 (goto-char (point-min))
9375 (while (re-search-forward "[ \t]*|[ \t]*$" nil t)
9376 (replace-match "" t t)
9377 (goto-char (min (1+ (point)) (point-max))))
9378 (goto-char (point-min))
9379 (while (re-search-forward "^-[-+]*$" nil t)
9380 (replace-match "")
9381 (if (looking-at "\n")
9382 (delete-char 1)))
9383 (goto-char (point-min))
9384 (while (re-search-forward "[ \t]*|[ \t]*" nil t)
9385 (replace-match "\t" t t))
9386 (save-buffer))
9387 (kill-buffer buf)))
9389 (defvar org-table-aligned-begin-marker (make-marker)
9390 "Marker at the beginning of the table last aligned.
9391 Used to check if cursor still is in that table, to minimize realignment.")
9392 (defvar org-table-aligned-end-marker (make-marker)
9393 "Marker at the end of the table last aligned.
9394 Used to check if cursor still is in that table, to minimize realignment.")
9395 (defvar org-table-last-alignment nil
9396 "List of flags for flushright alignment, from the last re-alignment.
9397 This is being used to correctly align a single field after TAB or RET.")
9398 (defvar org-table-last-column-widths nil
9399 "List of max width of fields in each column.
9400 This is being used to correctly align a single field after TAB or RET.")
9402 (defvar org-last-recalc-line nil)
9403 (defconst org-narrow-column-arrow "=>"
9404 "Used as display property in narrowed table columns.")
9406 (defun org-table-align ()
9407 "Align the table at point by aligning all vertical bars."
9408 (interactive)
9409 (let* (
9410 ;; Limits of table
9411 (beg (org-table-begin))
9412 (end (org-table-end))
9413 ;; Current cursor position
9414 (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
9415 (colpos (org-table-current-column))
9416 (winstart (window-start))
9417 text lines (new "") lengths l typenums ty fields maxfields i
9418 column
9419 (indent "") cnt frac
9420 rfmt hfmt
9421 (spaces '(1 . 1))
9422 (sp1 (car spaces))
9423 (sp2 (cdr spaces))
9424 (rfmt1 (concat
9425 (make-string sp2 ?\ ) "%%%s%ds" (make-string sp1 ?\ ) "|"))
9426 (hfmt1 (concat
9427 (make-string sp2 ?-) "%s" (make-string sp1 ?-) "+"))
9428 emptystrings xx links narrow fmax fmin f1 len c e)
9429 (untabify beg end)
9430 (remove-text-properties beg end '(org-cwidth t display t))
9431 ;; Check if we have links
9432 (goto-char beg)
9433 (setq links (re-search-forward org-bracket-link-regexp end t))
9434 ;; Make sure the link properties are right FIXME: Can this be optimized????
9435 (when links (goto-char beg) (while (org-activate-bracket-links end)))
9436 ;; Check if we are narrowing any columns
9437 (goto-char beg)
9438 (setq narrow (and org-format-transports-properties-p
9439 (re-search-forward "<[0-9]+>" end t)))
9440 ;; Get the rows
9441 (setq lines (org-split-string
9442 (buffer-substring beg end) "\n"))
9443 ;; Store the indentation of the first line
9444 (if (string-match "^ *" (car lines))
9445 (setq indent (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
9446 ;; Mark the hlines by setting the corresponding element to nil
9447 ;; At the same time, we remove trailing space.
9448 (setq lines (mapcar (lambda (l)
9449 (if (string-match "^ *|-" l)
9451 (if (string-match "[ \t]+$" l)
9452 (substring l 0 (match-beginning 0))
9453 l)))
9454 lines))
9455 ;; Get the data fields by splitting the lines.
9456 (setq fields (mapcar
9457 (lambda (l)
9458 (org-split-string l " *| *"))
9459 (delq nil (copy-sequence lines))))
9460 ;; How many fields in the longest line?
9461 (condition-case nil
9462 (setq maxfields (apply 'max (mapcar 'length fields)))
9463 (error
9464 (kill-region beg end)
9465 (org-table-create org-table-default-size)
9466 (error "Empty table - created default table")))
9467 ;; A list of empty string to fill any short rows on output
9468 (setq emptystrings (make-list maxfields ""))
9469 ;; Check for special formatting.
9470 (setq i -1)
9471 (while (< (setq i (1+ i)) maxfields) ;; Loop over all columns
9472 (setq column (mapcar (lambda (x) (or (nth i x) "")) fields))
9473 ;; Check if there is an explicit width specified
9474 (when (and org-table-limit-column-width narrow)
9475 (setq c column fmax nil)
9476 (while c
9477 (setq e (pop c))
9478 (if (and (stringp e) (string-match "^<\\([0-9]+\\)>$" e))
9479 (setq fmax (string-to-number (match-string 1 e)) c nil)))
9480 ;; Find fields that are wider than fmax, and shorten them
9481 (when fmax
9482 (loop for xx in column do
9483 (when (and (stringp xx)
9484 (> (org-string-width xx) fmax))
9485 (org-add-props xx nil
9486 'help-echo
9487 (concat "Clipped table field, use C-c ` to edit. Full value is:\n" (org-no-properties (copy-sequence xx))))
9488 (setq f1 (min fmax (or (string-match org-bracket-link-regexp xx) fmax)))
9489 (unless (> f1 1)
9490 (error "Cannot narrow field starting with wide link \"%s\""
9491 (match-string 0 xx)))
9492 (add-text-properties f1 (length xx) (list 'org-cwidth t) xx)
9493 (add-text-properties (- f1 2) f1
9494 (list 'display org-narrow-column-arrow)
9495 xx)))))
9496 ;; Get the maximum width for each column
9497 (push (apply 'max 1 (mapcar 'org-string-width column)) lengths)
9498 ;; Get the fraction of numbers, to decide about alignment of the column
9499 (setq cnt 0 frac 0.0)
9500 (loop for x in column do
9501 (if (equal x "")
9503 (setq frac ( / (+ (* frac cnt)
9504 (if (string-match org-table-number-regexp x) 1 0))
9505 (setq cnt (1+ cnt))))))
9506 (push (>= frac org-table-number-fraction) typenums))
9507 (setq lengths (nreverse lengths) typenums (nreverse typenums))
9509 ;; Store the alignment of this table, for later editing of single fields
9510 (setq org-table-last-alignment typenums
9511 org-table-last-column-widths lengths)
9513 ;; With invisible characters, `format' does not get the field width right
9514 ;; So we need to make these fields wide by hand.
9515 (when links
9516 (loop for i from 0 upto (1- maxfields) do
9517 (setq len (nth i lengths))
9518 (loop for j from 0 upto (1- (length fields)) do
9519 (setq c (nthcdr i (car (nthcdr j fields))))
9520 (if (and (stringp (car c))
9521 (string-match org-bracket-link-regexp (car c))
9522 (< (org-string-width (car c)) len))
9523 (setcar c (concat (car c) (make-string (- len (org-string-width (car c))) ?\ )))))))
9525 ;; Compute the formats needed for output of the table
9526 (setq rfmt (concat indent "|") hfmt (concat indent "|"))
9527 (while (setq l (pop lengths))
9528 (setq ty (if (pop typenums) "" "-")) ; number types flushright
9529 (setq rfmt (concat rfmt (format rfmt1 ty l))
9530 hfmt (concat hfmt (format hfmt1 (make-string l ?-)))))
9531 (setq rfmt (concat rfmt "\n")
9532 hfmt (concat (substring hfmt 0 -1) "|\n"))
9534 (setq new (mapconcat
9535 (lambda (l)
9536 (if l (apply 'format rfmt
9537 (append (pop fields) emptystrings))
9538 hfmt))
9539 lines ""))
9540 ;; Replace the old one
9541 (delete-region beg end)
9542 (move-marker end nil)
9543 (move-marker org-table-aligned-begin-marker (point))
9544 (insert new)
9545 (move-marker org-table-aligned-end-marker (point))
9546 (when (and orgtbl-mode (not (eq major-mode 'org-mode)))
9547 (goto-char org-table-aligned-begin-marker)
9548 (while (org-hide-wide-columns org-table-aligned-end-marker)))
9549 ;; Try to move to the old location (approximately)
9550 (goto-line linepos)
9551 (set-window-start (selected-window) winstart 'noforce)
9552 (org-table-goto-column colpos)
9553 (setq org-table-may-need-update nil)
9556 (defun org-string-width (s)
9557 "Compute width of string, ignoring invisible characters.
9558 This ignores character with invisibility property `org-link', and also
9559 characters with property `org-cwidth', because these will become invisible
9560 upon the next fontification round."
9561 (let (b)
9562 (when (or (eq t buffer-invisibility-spec)
9563 (assq 'org-link buffer-invisibility-spec))
9564 (while (setq b (text-property-any 0 (length s)
9565 'invisible 'org-link s))
9566 (setq s (concat (substring s 0 b)
9567 (substring s (or (next-single-property-change
9568 b 'invisible s) (length s)))))))
9569 (while (setq b (text-property-any 0 (length s) 'org-cwidth t s))
9570 (setq s (concat (substring s 0 b)
9571 (substring s (or (next-single-property-change
9572 b 'org-cwidth s) (length s))))))
9573 (string-width s)))
9575 (defun org-table-begin (&optional table-type)
9576 "Find the beginning of the table and return its position.
9577 With argument TABLE-TYPE, go to the beginning of a table.el-type table."
9578 (save-excursion
9579 (if (not (re-search-backward
9580 (if table-type org-table-any-border-regexp
9581 org-table-border-regexp)
9582 nil t))
9583 (progn (goto-char (point-min)) (point))
9584 (goto-char (match-beginning 0))
9585 (beginning-of-line 2)
9586 (point))))
9588 (defun org-table-end (&optional table-type)
9589 "Find the end of the table and return its position.
9590 With argument TABLE-TYPE, go to the end of a table.el-type table."
9591 (save-excursion
9592 (if (not (re-search-forward
9593 (if table-type org-table-any-border-regexp
9594 org-table-border-regexp)
9595 nil t))
9596 (goto-char (point-max))
9597 (goto-char (match-beginning 0)))
9598 (point-marker)))
9600 (defun org-table-justify-field-maybe (&optional new)
9601 "Justify the current field, text to left, number to right.
9602 Optional argument NEW may specify text to replace the current field content."
9603 (cond
9604 ((and (not new) org-table-may-need-update)) ; Realignment will happen anyway
9605 ((org-at-table-hline-p))
9606 ((and (not new)
9607 (or (not (equal (marker-buffer org-table-aligned-begin-marker)
9608 (current-buffer)))
9609 (< (point) org-table-aligned-begin-marker)
9610 (>= (point) org-table-aligned-end-marker)))
9611 ;; This is not the same table, force a full re-align
9612 (setq org-table-may-need-update t))
9613 (t ;; realign the current field, based on previous full realign
9614 (let* ((pos (point)) s
9615 (col (org-table-current-column))
9616 (num (if (> col 0) (nth (1- col) org-table-last-alignment)))
9617 l f n o e)
9618 (when (> col 0)
9619 (skip-chars-backward "^|\n")
9620 (if (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)")
9621 (progn
9622 (setq s (match-string 1)
9623 o (match-string 0)
9624 l (max 1 (- (match-end 0) (match-beginning 0) 3))
9625 e (not (= (match-beginning 2) (match-end 2))))
9626 (setq f (format (if num " %%%ds %s" " %%-%ds %s")
9627 l (if e "|" (setq org-table-may-need-update t) ""))
9628 n (format f s))
9629 (if new
9630 (if (<= (length new) l) ;; FIXME: length -> str-width?
9631 (setq n (format f new))
9632 (setq n (concat new "|") org-table-may-need-update t)))
9633 (or (equal n o)
9634 (let (org-table-may-need-update)
9635 (replace-match n))))
9636 (setq org-table-may-need-update t))
9637 (goto-char pos))))))
9639 (defun org-table-next-field ()
9640 "Go to the next field in the current table, creating new lines as needed.
9641 Before doing so, re-align the table if necessary."
9642 (interactive)
9643 (org-table-maybe-eval-formula)
9644 (org-table-maybe-recalculate-line)
9645 (if (and org-table-automatic-realign
9646 org-table-may-need-update)
9647 (org-table-align))
9648 (let ((end (org-table-end)))
9649 (if (org-at-table-hline-p)
9650 (end-of-line 1))
9651 (condition-case nil
9652 (progn
9653 (re-search-forward "|" end)
9654 (if (looking-at "[ \t]*$")
9655 (re-search-forward "|" end))
9656 (if (and (looking-at "-")
9657 org-table-tab-jumps-over-hlines
9658 (re-search-forward "^[ \t]*|\\([^-]\\)" end t))
9659 (goto-char (match-beginning 1)))
9660 (if (looking-at "-")
9661 (progn
9662 (beginning-of-line 0)
9663 (org-table-insert-row 'below))
9664 (if (looking-at " ") (forward-char 1))))
9665 (error
9666 (org-table-insert-row 'below)))))
9668 (defun org-table-previous-field ()
9669 "Go to the previous field in the table.
9670 Before doing so, re-align the table if necessary."
9671 (interactive)
9672 (org-table-justify-field-maybe)
9673 (org-table-maybe-recalculate-line)
9674 (if (and org-table-automatic-realign
9675 org-table-may-need-update)
9676 (org-table-align))
9677 (if (org-at-table-hline-p)
9678 (end-of-line 1))
9679 (re-search-backward "|" (org-table-begin))
9680 (re-search-backward "|" (org-table-begin))
9681 (while (looking-at "|\\(-\\|[ \t]*$\\)")
9682 (re-search-backward "|" (org-table-begin)))
9683 (if (looking-at "| ?")
9684 (goto-char (match-end 0))))
9686 (defun org-table-next-row ()
9687 "Go to the next row (same column) in the current table.
9688 Before doing so, re-align the table if necessary."
9689 (interactive)
9690 (org-table-maybe-eval-formula)
9691 (org-table-maybe-recalculate-line)
9692 (if (or (looking-at "[ \t]*$")
9693 (save-excursion (skip-chars-backward " \t") (bolp)))
9694 (newline)
9695 (if (and org-table-automatic-realign
9696 org-table-may-need-update)
9697 (org-table-align))
9698 (let ((col (org-table-current-column)))
9699 (beginning-of-line 2)
9700 (if (or (not (org-at-table-p))
9701 (org-at-table-hline-p))
9702 (progn
9703 (beginning-of-line 0)
9704 (org-table-insert-row 'below)))
9705 (org-table-goto-column col)
9706 (skip-chars-backward "^|\n\r")
9707 (if (looking-at " ") (forward-char 1)))))
9709 (defun org-table-copy-down (n)
9710 "Copy a field down in the current column.
9711 If the field at the cursor is empty, copy into it the content of the nearest
9712 non-empty field above. With argument N, use the Nth non-empty field.
9713 If the current field is not empty, it is copied down to the next row, and
9714 the cursor is moved with it. Therefore, repeating this command causes the
9715 column to be filled row-by-row.
9716 If the variable `org-table-copy-increment' is non-nil and the field is an
9717 integer, it will be incremented while copying."
9718 (interactive "p")
9719 (let* ((colpos (org-table-current-column))
9720 (field (org-table-get-field))
9721 (non-empty (string-match "[^ \t]" field))
9722 (beg (org-table-begin))
9723 txt)
9724 (org-table-check-inside-data-field)
9725 (if non-empty
9726 (progn
9727 (setq txt (org-trim field))
9728 (org-table-next-row)
9729 (org-table-blank-field))
9730 (save-excursion
9731 (setq txt
9732 (catch 'exit
9733 (while (progn (beginning-of-line 1)
9734 (re-search-backward org-table-dataline-regexp
9735 beg t))
9736 (org-table-goto-column colpos t)
9737 (if (and (looking-at
9738 "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|")
9739 (= (setq n (1- n)) 0))
9740 (throw 'exit (match-string 1))))))))
9741 (if txt
9742 (progn
9743 (if (and org-table-copy-increment
9744 (string-match "^[0-9]+$" txt))
9745 (setq txt (format "%d" (+ (string-to-number txt) 1))))
9746 (insert txt)
9747 (org-table-maybe-recalculate-line)
9748 (org-table-align))
9749 (error "No non-empty field found"))))
9751 (defun org-table-check-inside-data-field ()
9752 "Is point inside a table data field?
9753 I.e. not on a hline or before the first or after the last column?
9754 This actually throws an error, so it aborts the current command."
9755 (if (or (not (org-at-table-p))
9756 (= (org-table-current-column) 0)
9757 (org-at-table-hline-p)
9758 (looking-at "[ \t]*$"))
9759 (error "Not in table data field")))
9761 (defvar org-table-clip nil
9762 "Clipboard for table regions.")
9764 (defun org-table-blank-field ()
9765 "Blank the current table field or active region."
9766 (interactive)
9767 (org-table-check-inside-data-field)
9768 (if (and (interactive-p) (org-region-active-p))
9769 (let (org-table-clip)
9770 (org-table-cut-region (region-beginning) (region-end)))
9771 (skip-chars-backward "^|")
9772 (backward-char 1)
9773 (if (looking-at "|[^|\n]+")
9774 (let* ((pos (match-beginning 0))
9775 (match (match-string 0))
9776 (len (org-string-width match)))
9777 (replace-match (concat "|" (make-string (1- len) ?\ )))
9778 (goto-char (+ 2 pos))
9779 (substring match 1)))))
9781 (defun org-table-get-field (&optional n replace)
9782 "Return the value of the field in column N of current row.
9783 N defaults to current field.
9784 If REPLACE is a string, replace field with this value. The return value
9785 is always the old value."
9786 (and n (org-table-goto-column n))
9787 (skip-chars-backward "^|\n")
9788 (backward-char 1)
9789 (if (looking-at "|[^|\r\n]*")
9790 (let* ((pos (match-beginning 0))
9791 (val (buffer-substring (1+ pos) (match-end 0))))
9792 (if replace
9793 (replace-match (concat "|" replace)))
9794 (goto-char (min (point-at-eol) (+ 2 pos)))
9795 val)
9796 (forward-char 1) ""))
9798 (defun org-table-current-column ()
9799 "Find out which column we are in.
9800 When called interactively, column is also displayed in echo area."
9801 (interactive)
9802 (if (interactive-p) (org-table-check-inside-data-field))
9803 (save-excursion
9804 (let ((cnt 0) (pos (point)))
9805 (beginning-of-line 1)
9806 (while (search-forward "|" pos t)
9807 (setq cnt (1+ cnt)))
9808 (if (interactive-p) (message "This is table column %d" cnt))
9809 cnt)))
9811 (defun org-table-goto-column (n &optional on-delim force)
9812 "Move the cursor to the Nth column in the current table line.
9813 With optional argument ON-DELIM, stop with point before the left delimiter
9814 of the field.
9815 If there are less than N fields, just go to after the last delimiter.
9816 However, when FORCE is non-nil, create new columns if necessary."
9817 (interactive "p")
9818 (let ((pos (point-at-eol)))
9819 (beginning-of-line 1)
9820 (when (> n 0)
9821 (while (and (> (setq n (1- n)) -1)
9822 (or (search-forward "|" pos t)
9823 (and force
9824 (progn (end-of-line 1)
9825 (skip-chars-backward "^|")
9826 (insert " | "))))))
9827 ; (backward-char 2) t)))))
9828 (when (and force (not (looking-at ".*|")))
9829 (save-excursion (end-of-line 1) (insert " | ")))
9830 (if on-delim
9831 (backward-char 1)
9832 (if (looking-at " ") (forward-char 1))))))
9834 (defun org-at-table-p (&optional table-type)
9835 "Return t if the cursor is inside an org-type table.
9836 If TABLE-TYPE is non-nil, also check for table.el-type tables."
9837 (if org-enable-table-editor
9838 (save-excursion
9839 (beginning-of-line 1)
9840 (looking-at (if table-type org-table-any-line-regexp
9841 org-table-line-regexp)))
9842 nil))
9844 (defun org-at-table.el-p ()
9845 "Return t if and only if we are at a table.el table."
9846 (and (org-at-table-p 'any)
9847 (save-excursion
9848 (goto-char (org-table-begin 'any))
9849 (looking-at org-table1-hline-regexp))))
9851 (defun org-table-recognize-table.el ()
9852 "If there is a table.el table nearby, recognize it and move into it."
9853 (if org-table-tab-recognizes-table.el
9854 (if (org-at-table.el-p)
9855 (progn
9856 (beginning-of-line 1)
9857 (if (looking-at org-table-dataline-regexp)
9859 (if (looking-at org-table1-hline-regexp)
9860 (progn
9861 (beginning-of-line 2)
9862 (if (looking-at org-table-any-border-regexp)
9863 (beginning-of-line -1)))))
9864 (if (re-search-forward "|" (org-table-end t) t)
9865 (progn
9866 (require 'table)
9867 (if (table--at-cell-p (point))
9869 (message "recognizing table.el table...")
9870 (table-recognize-table)
9871 (message "recognizing table.el table...done")))
9872 (error "This should not happen..."))
9874 nil)
9875 nil))
9877 (defun org-at-table-hline-p ()
9878 "Return t if the cursor is inside a hline in a table."
9879 (if org-enable-table-editor
9880 (save-excursion
9881 (beginning-of-line 1)
9882 (looking-at org-table-hline-regexp))
9883 nil))
9885 (defun org-table-insert-column ()
9886 "Insert a new column into the table."
9887 (interactive)
9888 (if (not (org-at-table-p))
9889 (error "Not at a table"))
9890 (org-table-find-dataline)
9891 (let* ((col (max 1 (org-table-current-column)))
9892 (beg (org-table-begin))
9893 (end (org-table-end))
9894 ;; Current cursor position
9895 (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
9896 (colpos col))
9897 (goto-char beg)
9898 (while (< (point) end)
9899 (if (org-at-table-hline-p)
9901 (org-table-goto-column col t)
9902 (insert "| "))
9903 (beginning-of-line 2))
9904 (move-marker end nil)
9905 (goto-line linepos)
9906 (org-table-goto-column colpos)
9907 (org-table-align)
9908 (org-table-modify-formulas 'insert col)))
9910 (defun org-table-find-dataline ()
9911 "Find a dataline in the current table, which is needed for column commands."
9912 (if (and (org-at-table-p)
9913 (not (org-at-table-hline-p)))
9915 (let ((col (current-column))
9916 (end (org-table-end)))
9917 (move-to-column col)
9918 (while (and (< (point) end)
9919 (or (not (= (current-column) col))
9920 (org-at-table-hline-p)))
9921 (beginning-of-line 2)
9922 (move-to-column col))
9923 (if (and (org-at-table-p)
9924 (not (org-at-table-hline-p)))
9926 (error
9927 "Please position cursor in a data line for column operations")))))
9929 (defun org-table-delete-column ()
9930 "Delete a column from the table."
9931 (interactive)
9932 (if (not (org-at-table-p))
9933 (error "Not at a table"))
9934 (org-table-find-dataline)
9935 (org-table-check-inside-data-field)
9936 (let* ((col (org-table-current-column))
9937 (beg (org-table-begin))
9938 (end (org-table-end))
9939 ;; Current cursor position
9940 (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
9941 (colpos col))
9942 (goto-char beg)
9943 (while (< (point) end)
9944 (if (org-at-table-hline-p)
9946 (org-table-goto-column col t)
9947 (and (looking-at "|[^|\n]+|")
9948 (replace-match "|")))
9949 (beginning-of-line 2))
9950 (move-marker end nil)
9951 (goto-line linepos)
9952 (org-table-goto-column colpos)
9953 (org-table-align)
9954 (org-table-modify-formulas 'remove col)))
9956 (defun org-table-move-column-right ()
9957 "Move column to the right."
9958 (interactive)
9959 (org-table-move-column nil))
9960 (defun org-table-move-column-left ()
9961 "Move column to the left."
9962 (interactive)
9963 (org-table-move-column 'left))
9965 (defun org-table-move-column (&optional left)
9966 "Move the current column to the right. With arg LEFT, move to the left."
9967 (interactive "P")
9968 (if (not (org-at-table-p))
9969 (error "Not at a table"))
9970 (org-table-find-dataline)
9971 (org-table-check-inside-data-field)
9972 (let* ((col (org-table-current-column))
9973 (col1 (if left (1- col) col))
9974 (beg (org-table-begin))
9975 (end (org-table-end))
9976 ;; Current cursor position
9977 (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
9978 (colpos (if left (1- col) (1+ col))))
9979 (if (and left (= col 1))
9980 (error "Cannot move column further left"))
9981 (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$"))
9982 (error "Cannot move column further right"))
9983 (goto-char beg)
9984 (while (< (point) end)
9985 (if (org-at-table-hline-p)
9987 (org-table-goto-column col1 t)
9988 (and (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|")
9989 (replace-match "|\\2|\\1|")))
9990 (beginning-of-line 2))
9991 (move-marker end nil)
9992 (goto-line linepos)
9993 (org-table-goto-column colpos)
9994 (org-table-align)
9995 (org-table-modify-formulas 'swap col (if left (1- col) (1+ col)))))
9997 (defun org-table-move-row-down ()
9998 "Move table row down."
9999 (interactive)
10000 (org-table-move-row nil))
10001 (defun org-table-move-row-up ()
10002 "Move table row up."
10003 (interactive)
10004 (org-table-move-row 'up))
10006 (defun org-table-move-row (&optional up)
10007 "Move the current table line down. With arg UP, move it up."
10008 (interactive "P")
10009 (let ((col (current-column))
10010 (pos (point))
10011 (tonew (if up 0 2))
10012 txt)
10013 (beginning-of-line tonew)
10014 (if (not (org-at-table-p))
10015 (progn
10016 (goto-char pos)
10017 (error "Cannot move row further")))
10018 (goto-char pos)
10019 (beginning-of-line 1)
10020 (setq pos (point))
10021 (setq txt (buffer-substring (point) (1+ (point-at-eol))))
10022 (delete-region (point) (1+ (point-at-eol)))
10023 (beginning-of-line tonew)
10024 (insert txt)
10025 (beginning-of-line 0)
10026 (move-to-column col)))
10028 (defun org-table-insert-row (&optional arg)
10029 "Insert a new row above the current line into the table.
10030 With prefix ARG, insert below the current line."
10031 (interactive "P")
10032 (if (not (org-at-table-p))
10033 (error "Not at a table"))
10034 (let* ((line (buffer-substring (point-at-bol) (point-at-eol)))
10035 (new (org-table-clean-line line)))
10036 ;; Fix the first field if necessary
10037 (if (string-match "^[ \t]*| *[#$] *|" line)
10038 (setq new (replace-match (match-string 0 line) t t new)))
10039 (beginning-of-line (if arg 2 1))
10040 (let (org-table-may-need-update) (insert-before-markers new "\n"))
10041 (beginning-of-line 0)
10042 (re-search-forward "| ?" (point-at-eol) t)
10043 (and org-table-may-need-update (org-table-align))))
10045 (defun org-table-insert-hline (&optional arg)
10046 "Insert a horizontal-line below the current line into the table.
10047 With prefix ARG, insert above the current line."
10048 (interactive "P")
10049 (if (not (org-at-table-p))
10050 (error "Not at a table"))
10051 (let ((line (org-table-clean-line
10052 (buffer-substring (point-at-bol) (point-at-eol))))
10053 (col (current-column)))
10054 (while (string-match "|\\( +\\)|" line)
10055 (setq line (replace-match
10056 (concat "+" (make-string (- (match-end 1) (match-beginning 1))
10057 ?-) "|") t t line)))
10058 (and (string-match "\\+" line) (setq line (replace-match "|" t t line)))
10059 (beginning-of-line (if arg 1 2))
10060 (insert line "\n")
10061 (beginning-of-line (if arg 1 -1))
10062 (move-to-column col)))
10064 (defun org-table-clean-line (s)
10065 "Convert a table line S into a string with only \"|\" and space.
10066 In particular, this does handle wide and invisible characters."
10067 (if (string-match "^[ \t]*|-" s)
10068 ;; It's a hline, just map the characters
10069 (setq s (mapconcat (lambda (x) (if (member x '(?| ?+)) "|" " ")) s ""))
10070 (while (string-match "|\\([ \t]*?[^ \t\r\n|][^\r\n|]*\\)|" s)
10071 (setq s (replace-match
10072 (concat "|" (make-string (org-string-width (match-string 1 s))
10073 ?\ ) "|")
10074 t t s)))
10077 (defun org-table-kill-row ()
10078 "Delete the current row or horizontal line from the table."
10079 (interactive)
10080 (if (not (org-at-table-p))
10081 (error "Not at a table"))
10082 (let ((col (current-column)))
10083 (kill-region (point-at-bol) (min (1+ (point-at-eol)) (point-max)))
10084 (if (not (org-at-table-p)) (beginning-of-line 0))
10085 (move-to-column col)))
10087 (defun org-table-sort-lines (beg end numericp)
10088 "Sort table lines in region.
10089 Point and mark define the first and last line to include. Both point and
10090 mark should be in the column that is used for sorting. For example, to
10091 sort according to column 3, put the mark in the first line to sort, in
10092 table column 3. Put point into the last line to be included in the sorting,
10093 also in table column 3. The command will prompt for the sorting method
10094 \(n for numerical, a for alphanumeric)."
10095 (interactive "r\nsSorting method: [n]=numeric [a]=alpha: ")
10096 (setq numericp (string-match "[nN]" numericp))
10097 (org-table-align) ;; Just to be safe
10098 (let* (bcol ecol cmp column lns)
10099 (goto-char beg)
10100 (org-table-check-inside-data-field)
10101 (setq column (org-table-current-column)
10102 beg (move-marker (make-marker) (point-at-bol)))
10103 (goto-char end)
10104 (org-table-check-inside-data-field)
10105 (setq end (move-marker (make-marker) (1+ (point-at-eol))))
10106 (untabify beg end)
10107 (goto-char beg)
10108 (org-table-goto-column column)
10109 (skip-chars-backward "^|")
10110 (setq bcol (current-column))
10111 (org-table-goto-column (1+ column))
10112 (skip-chars-backward "^|")
10113 (setq ecol (1- (current-column)))
10114 (setq cmp (if numericp
10115 (lambda (a b) (< (car a) (car b)))
10116 (lambda (a b) (string< (car a) (car b)))))
10117 (setq lns (mapcar (lambda(x) (cons (org-trim (substring x bcol ecol)) x))
10118 (org-split-string (buffer-substring beg end) "\n")))
10119 (if numericp
10120 (setq lns (mapcar (lambda(x)
10121 (cons (string-to-number (car x)) (cdr x)))
10122 lns)))
10123 (delete-region beg end)
10124 (move-marker beg nil)
10125 (move-marker end nil)
10126 (insert (mapconcat 'cdr (setq lns (sort lns cmp)) "\n") "\n")
10127 (message "%d lines sorted %s based on column %d"
10128 (length lns)
10129 (if numericp "numerically" "alphabetically") column)))
10131 (defun org-table-cut-region (beg end)
10132 "Copy region in table to the clipboard and blank all relevant fields."
10133 (interactive "r")
10134 (org-table-copy-region beg end 'cut))
10136 (defun org-table-copy-region (beg end &optional cut)
10137 "Copy rectangular region in table to clipboard.
10138 A special clipboard is used which can only be accessed
10139 with `org-table-paste-rectangle'."
10140 (interactive "rP")
10141 (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2
10142 region cols
10143 (rpl (if cut " " nil)))
10144 (goto-char beg)
10145 (org-table-check-inside-data-field)
10146 (setq l01 (count-lines (point-min) (point))
10147 c01 (org-table-current-column))
10148 (goto-char end)
10149 (org-table-check-inside-data-field)
10150 (setq l02 (count-lines (point-min) (point))
10151 c02 (org-table-current-column))
10152 (setq l1 (min l01 l02) l2 (max l01 l02)
10153 c1 (min c01 c02) c2 (max c01 c02))
10154 (catch 'exit
10155 (while t
10156 (catch 'nextline
10157 (if (> l1 l2) (throw 'exit t))
10158 (goto-line l1)
10159 (if (org-at-table-hline-p) (throw 'nextline (setq l1 (1+ l1))))
10160 (setq cols nil ic1 c1 ic2 c2)
10161 (while (< ic1 (1+ ic2))
10162 (push (org-table-get-field ic1 rpl) cols)
10163 (setq ic1 (1+ ic1)))
10164 (push (nreverse cols) region)
10165 (setq l1 (1+ l1)))))
10166 (setq org-table-clip (nreverse region))
10167 (if cut (org-table-align))
10168 org-table-clip))
10170 (defun org-table-paste-rectangle ()
10171 "Paste a rectangular region into a table.
10172 The upper right corner ends up in the current field. All involved fields
10173 will be overwritten. If the rectangle does not fit into the present table,
10174 the table is enlarged as needed. The process ignores horizontal separator
10175 lines."
10176 (interactive)
10177 (unless (and org-table-clip (listp org-table-clip))
10178 (error "First cut/copy a region to paste!"))
10179 (org-table-check-inside-data-field)
10180 (let* ((clip org-table-clip)
10181 (line (count-lines (point-min) (point)))
10182 (col (org-table-current-column))
10183 (org-enable-table-editor t)
10184 (org-table-automatic-realign nil)
10185 c cols field)
10186 (while (setq cols (pop clip))
10187 (while (org-at-table-hline-p) (beginning-of-line 2))
10188 (if (not (org-at-table-p))
10189 (progn (end-of-line 0) (org-table-next-field)))
10190 (setq c col)
10191 (while (setq field (pop cols))
10192 (org-table-goto-column c nil 'force)
10193 (org-table-get-field nil field)
10194 (setq c (1+ c)))
10195 (beginning-of-line 2))
10196 (goto-line line)
10197 (org-table-goto-column col)
10198 (org-table-align)))
10200 (defun org-table-convert ()
10201 "Convert from `org-mode' table to table.el and back.
10202 Obviously, this only works within limits. When an Org-mode table is
10203 converted to table.el, all horizontal separator lines get lost, because
10204 table.el uses these as cell boundaries and has no notion of horizontal lines.
10205 A table.el table can be converted to an Org-mode table only if it does not
10206 do row or column spanning. Multiline cells will become multiple cells.
10207 Beware, Org-mode does not test if the table can be successfully converted - it
10208 blindly applies a recipe that works for simple tables."
10209 (interactive)
10210 (require 'table)
10211 (if (org-at-table.el-p)
10212 ;; convert to Org-mode table
10213 (let ((beg (move-marker (make-marker) (org-table-begin t)))
10214 (end (move-marker (make-marker) (org-table-end t))))
10215 (table-unrecognize-region beg end)
10216 (goto-char beg)
10217 (while (re-search-forward "^\\([ \t]*\\)\\+-.*\n" end t)
10218 (replace-match ""))
10219 (goto-char beg))
10220 (if (org-at-table-p)
10221 ;; convert to table.el table
10222 (let ((beg (move-marker (make-marker) (org-table-begin)))
10223 (end (move-marker (make-marker) (org-table-end))))
10224 ;; first, get rid of all horizontal lines
10225 (goto-char beg)
10226 (while (re-search-forward "^\\([ \t]*\\)|-.*\n" end t)
10227 (replace-match ""))
10228 ;; insert a hline before first
10229 (goto-char beg)
10230 (org-table-insert-hline 'above)
10231 (beginning-of-line -1)
10232 ;; insert a hline after each line
10233 (while (progn (beginning-of-line 3) (< (point) end))
10234 (org-table-insert-hline))
10235 (goto-char beg)
10236 (setq end (move-marker end (org-table-end)))
10237 ;; replace "+" at beginning and ending of hlines
10238 (while (re-search-forward "^\\([ \t]*\\)|-" end t)
10239 (replace-match "\\1+-"))
10240 (goto-char beg)
10241 (while (re-search-forward "-|[ \t]*$" end t)
10242 (replace-match "-+"))
10243 (goto-char beg)))))
10245 (defun org-table-wrap-region (arg)
10246 "Wrap several fields in a column like a paragraph.
10247 This is useful if you'd like to spread the contents of a field over several
10248 lines, in order to keep the table compact.
10250 If there is an active region, and both point and mark are in the same column,
10251 the text in the column is wrapped to minimum width for the given number of
10252 lines. Generally, this makes the table more compact. A prefix ARG may be
10253 used to change the number of desired lines. For example, `C-2 \\[org-table-wrap]'
10254 formats the selected text to two lines. If the region was longer than two
10255 lines, the remaining lines remain empty. A negative prefix argument reduces
10256 the current number of lines by that amount. The wrapped text is pasted back
10257 into the table. If you formatted it to more lines than it was before, fields
10258 further down in the table get overwritten - so you might need to make space in
10259 the table first.
10261 If there is no region, the current field is split at the cursor position and
10262 the text fragment to the right of the cursor is prepended to the field one
10263 line down.
10265 If there is no region, but you specify a prefix ARG, the current field gets
10266 blank, and the content is appended to the field above."
10267 (interactive "P")
10268 (org-table-check-inside-data-field)
10269 (if (org-region-active-p)
10270 ;; There is a region: fill as a paragraph
10271 (let ((beg (region-beginning))
10272 nlines)
10273 (org-table-cut-region (region-beginning) (region-end))
10274 (if (> (length (car org-table-clip)) 1)
10275 (error "Region must be limited to single column"))
10276 (setq nlines (if arg
10277 (if (< arg 1)
10278 (+ (length org-table-clip) arg)
10279 arg)
10280 (length org-table-clip)))
10281 (setq org-table-clip
10282 (mapcar 'list (org-wrap (mapconcat 'car org-table-clip " ")
10283 nil nlines)))
10284 (goto-char beg)
10285 (org-table-paste-rectangle))
10286 ;; No region, split the current field at point
10287 (if arg
10288 ;; combine with field above
10289 (let ((s (org-table-blank-field))
10290 (col (org-table-current-column)))
10291 (beginning-of-line 0)
10292 (while (org-at-table-hline-p) (beginning-of-line 0))
10293 (org-table-goto-column col)
10294 (skip-chars-forward "^|")
10295 (skip-chars-backward " ")
10296 (insert " " (org-trim s))
10297 (org-table-align))
10298 ;; split field
10299 (when (looking-at "\\([^|]+\\)+|")
10300 (let ((s (match-string 1)))
10301 (replace-match " |")
10302 (goto-char (match-beginning 0))
10303 (org-table-next-row)
10304 (insert (org-trim s) " ")
10305 (org-table-align))))))
10307 (defvar org-field-marker nil)
10309 (defun org-table-edit-field (arg)
10310 "Edit table field in a different window.
10311 This is mainly useful for fields that contain hidden parts.
10312 When called with a \\[universal-argument] prefix, just make the full field visible so that
10313 it can be edited in place."
10314 (interactive "P")
10315 (if arg
10316 (let ((b (save-excursion (skip-chars-backward "^|") (point)))
10317 (e (save-excursion (skip-chars-forward "^|\r\n") (point))))
10318 (remove-text-properties b e '(org-cwidth t invisible t
10319 display t intangible t))
10320 (if (and (boundp 'font-lock-mode) font-lock-mode)
10321 (font-lock-fontify-block)))
10322 (let ((pos (move-marker (make-marker) (point)))
10323 (field (org-table-get-field))
10324 (cw (current-window-configuration))
10326 (switch-to-buffer-other-window "*Org tmp*")
10327 (erase-buffer)
10328 (insert "#\n# Edit field and finish with C-c C-c\n#\n")
10329 (org-mode)
10330 (goto-char (setq p (point-max)))
10331 (insert (org-trim field))
10332 (remove-text-properties p (point-max)
10333 '(invisible t org-cwidth t display t
10334 intangible t))
10335 (goto-char p)
10336 (set (make-local-variable 'org-finish-function)
10337 'org-table-finish-edit-field)
10338 (set (make-local-variable 'org-window-configuration) cw)
10339 (set (make-local-variable 'org-field-marker) pos)
10340 (message "Edit and finish with C-c C-c"))))
10342 (defun org-table-finish-edit-field ()
10343 "Finish editing a table data field.
10344 Remove all newline characters, insert the result into the table, realign
10345 the table and kill the editing buffer."
10346 (let ((pos org-field-marker)
10347 (cw org-window-configuration)
10348 (cb (current-buffer))
10349 text)
10350 (goto-char (point-min))
10351 (while (re-search-forward "^#.*\n?" nil t) (replace-match ""))
10352 (while (re-search-forward "\\([ \t]*\n[ \t]*\\)+" nil t)
10353 (replace-match " "))
10354 (setq text (org-trim (buffer-string)))
10355 (set-window-configuration cw)
10356 (kill-buffer cb)
10357 (select-window (get-buffer-window (marker-buffer pos)))
10358 (goto-char pos)
10359 (move-marker pos nil)
10360 (org-table-check-inside-data-field)
10361 (org-table-get-field nil text)
10362 (org-table-align)
10363 (message "New field value inserted")))
10365 (defun org-trim (s)
10366 "Remove whitespace at beginning and end of string."
10367 (if (string-match "^[ \t]+" s) (setq s (replace-match "" t t s)))
10368 (if (string-match "[ \t]+$" s) (setq s (replace-match "" t t s)))
10371 (defun org-wrap (string &optional width lines)
10372 "Wrap string to either a number of lines, or a width in characters.
10373 If WIDTH is non-nil, the string is wrapped to that width, however many lines
10374 that costs. If there is a word longer than WIDTH, the text is actually
10375 wrapped to the length of that word.
10376 IF WIDTH is nil and LINES is non-nil, the string is forced into at most that
10377 many lines, whatever width that takes.
10378 The return value is a list of lines, without newlines at the end."
10379 (let* ((words (org-split-string string "[ \t\n]+"))
10380 (maxword (apply 'max (mapcar 'org-string-width words)))
10381 w ll)
10382 (cond (width
10383 (org-do-wrap words (max maxword width)))
10384 (lines
10385 (setq w maxword)
10386 (setq ll (org-do-wrap words maxword))
10387 (if (<= (length ll) lines)
10389 (setq ll words)
10390 (while (> (length ll) lines)
10391 (setq w (1+ w))
10392 (setq ll (org-do-wrap words w)))
10393 ll))
10394 (t (error "Cannot wrap this")))))
10397 (defun org-do-wrap (words width)
10398 "Create lines of maximum width WIDTH (in characters) from word list WORDS."
10399 (let (lines line)
10400 (while words
10401 (setq line (pop words))
10402 (while (and words (< (+ (length line) (length (car words))) width))
10403 (setq line (concat line " " (pop words))))
10404 (setq lines (push line lines)))
10405 (nreverse lines)))
10407 (defun org-split-string (string &optional separators)
10408 "Splits STRING into substrings at SEPARATORS.
10409 No empty strings are returned if there are matches at the beginning
10410 and end of string."
10411 (let ((rexp (or separators "[ \f\t\n\r\v]+"))
10412 (start 0)
10413 notfirst
10414 (list nil))
10415 (while (and (string-match rexp string
10416 (if (and notfirst
10417 (= start (match-beginning 0))
10418 (< start (length string)))
10419 (1+ start) start))
10420 (< (match-beginning 0) (length string)))
10421 (setq notfirst t)
10422 (or (eq (match-beginning 0) 0)
10423 (and (eq (match-beginning 0) (match-end 0))
10424 (eq (match-beginning 0) start))
10425 (setq list
10426 (cons (substring string start (match-beginning 0))
10427 list)))
10428 (setq start (match-end 0)))
10429 (or (eq start (length string))
10430 (setq list
10431 (cons (substring string start)
10432 list)))
10433 (nreverse list)))
10435 (defun org-table-map-tables (function)
10436 "Apply FUNCTION to the start of all tables in the buffer."
10437 (save-excursion
10438 (save-restriction
10439 (widen)
10440 (goto-char (point-min))
10441 (while (re-search-forward org-table-any-line-regexp nil t)
10442 (message "Mapping tables: %d%%" (/ (* 100.0 (point)) (buffer-size)))
10443 (beginning-of-line 1)
10444 (if (looking-at org-table-line-regexp)
10445 (save-excursion (funcall function)))
10446 (re-search-forward org-table-any-border-regexp nil 1))))
10447 (message "Mapping tables: done"))
10449 (defun org-table-sum (&optional beg end nlast)
10450 "Sum numbers in region of current table column.
10451 The result will be displayed in the echo area, and will be available
10452 as kill to be inserted with \\[yank].
10454 If there is an active region, it is interpreted as a rectangle and all
10455 numbers in that rectangle will be summed. If there is no active
10456 region and point is located in a table column, sum all numbers in that
10457 column.
10459 If at least one number looks like a time HH:MM or HH:MM:SS, all other
10460 numbers are assumed to be times as well (in decimal hours) and the
10461 numbers are added as such.
10463 If NLAST is a number, only the NLAST fields will actually be summed."
10464 (interactive)
10465 (save-excursion
10466 (let (col (timecnt 0) diff h m s org-table-clip)
10467 (cond
10468 ((and beg end)) ; beg and end given explicitly
10469 ((org-region-active-p)
10470 (setq beg (region-beginning) end (region-end)))
10472 (setq col (org-table-current-column))
10473 (goto-char (org-table-begin))
10474 (unless (re-search-forward "^[ \t]*|[^-]" nil t)
10475 (error "No table data"))
10476 (org-table-goto-column col)
10477 ;not needed? (skip-chars-backward "^|")
10478 (setq beg (point))
10479 (goto-char (org-table-end))
10480 (unless (re-search-backward "^[ \t]*|[^-]" nil t)
10481 (error "No table data"))
10482 (org-table-goto-column col)
10483 ;not needed? (skip-chars-forward "^|")
10484 (setq end (point))))
10485 (let* ((items (apply 'append (org-table-copy-region beg end)))
10486 (items1 (cond ((not nlast) items)
10487 ((>= nlast (length items)) items)
10488 (t (setq items (reverse items))
10489 (setcdr (nthcdr (1- nlast) items) nil)
10490 (nreverse items))))
10491 (numbers (delq nil (mapcar 'org-table-get-number-for-summing
10492 items1)))
10493 (res (apply '+ numbers))
10494 (sres (if (= timecnt 0)
10495 (format "%g" res)
10496 (setq diff (* 3600 res)
10497 h (floor (/ diff 3600)) diff (mod diff 3600)
10498 m (floor (/ diff 60)) diff (mod diff 60)
10499 s diff)
10500 (format "%d:%02d:%02d" h m s))))
10501 (kill-new sres)
10502 (if (interactive-p)
10503 (message "%s"
10504 (substitute-command-keys
10505 (format "Sum of %d items: %-20s (\\[yank] will insert result into buffer)"
10506 (length numbers) sres))))
10507 sres))))
10509 (defun org-table-get-number-for-summing (s)
10510 (let (n)
10511 (if (string-match "^ *|? *" s)
10512 (setq s (replace-match "" nil nil s)))
10513 (if (string-match " *|? *$" s)
10514 (setq s (replace-match "" nil nil s)))
10515 (setq n (string-to-number s))
10516 (cond
10517 ((and (string-match "0" s)
10518 (string-match "\\`[-+ \t0.edED]+\\'" s)) 0)
10519 ((string-match "\\`[ \t]+\\'" s) nil)
10520 ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?\\'" s)
10521 (let ((h (string-to-number (or (match-string 1 s) "0")))
10522 (m (string-to-number (or (match-string 2 s) "0")))
10523 (s (string-to-number (or (match-string 4 s) "0"))))
10524 (if (boundp 'timecnt) (setq timecnt (1+ timecnt)))
10525 (* 1.0 (+ h (/ m 60.0) (/ s 3600.0)))))
10526 ((equal n 0) nil)
10527 (t n))))
10529 (defun org-table-get-vertical-vector (desc &optional tbeg col)
10530 "Get a calc vector from a column, accorting to descriptor DESC.
10531 Optional arguments TBEG and COL can give the beginning of the table and
10532 the current column, to avoid unnecessary parsing."
10533 (save-excursion
10534 (or tbeg (setq tbeg (org-table-begin)))
10535 (or col (setq col (org-table-current-column)))
10536 (let (beg end nn n n1 n2 l (thisline (org-current-line)) hline-list)
10537 (cond
10538 ((string-match "\\(I+\\)\\(-\\(I+\\)\\)?" desc)
10539 (setq n1 (- (match-end 1) (match-beginning 1)))
10540 (if (match-beginning 3)
10541 (setq n2 (- (match-end 2) (match-beginning 3))))
10542 (setq n (if n2 (max n1 n2) n1))
10543 (setq n1 (if n2 (min n1 n2)))
10544 (setq nn n)
10545 (while (and (> nn 0)
10546 (re-search-backward org-table-hline-regexp tbeg t))
10547 (push (org-current-line) hline-list)
10548 (setq nn (1- nn)))
10549 (setq hline-list (nreverse hline-list))
10550 (goto-line (nth (1- n) hline-list))
10551 (when (re-search-forward org-table-dataline-regexp)
10552 (org-table-goto-column col)
10553 (setq beg (point)))
10554 (goto-line (if n1 (nth (1- n1) hline-list) thisline))
10555 (when (re-search-backward org-table-dataline-regexp)
10556 (org-table-goto-column col)
10557 (setq end (point)))
10558 (setq l (apply 'append (org-table-copy-region beg end)))
10559 (concat "[" (mapconcat (lambda (x) (setq x (org-trim x))
10560 (if (equal x "") "0" x))
10561 l ",") "]"))
10562 ((string-match "\\([0-9]+\\)-\\([0-9]+\\)" desc)
10563 (setq n1 (string-to-number (match-string 1 desc))
10564 n2 (string-to-number (match-string 2 desc)))
10565 (beginning-of-line 1)
10566 (save-excursion
10567 (when (re-search-backward org-table-dataline-regexp tbeg t n1)
10568 (org-table-goto-column col)
10569 (setq beg (point))))
10570 (when (re-search-backward org-table-dataline-regexp tbeg t n2)
10571 (org-table-goto-column col)
10572 (setq end (point)))
10573 (setq l (apply 'append (org-table-copy-region beg end)))
10574 (concat "[" (mapconcat
10575 (lambda (x) (setq x (org-trim x))
10576 (if (equal x "") "0" x))
10577 l ",") "]"))
10578 ((string-match "\\([0-9]+\\)" desc)
10579 (beginning-of-line 1)
10580 (when (re-search-backward org-table-dataline-regexp tbeg t
10581 (string-to-number (match-string 0 desc)))
10582 (org-table-goto-column col)
10583 (org-trim (org-table-get-field))))))))
10585 (defvar org-table-formula-history nil)
10587 (defvar org-table-column-names nil
10588 "Alist with column names, derived from the `!' line.")
10589 (defvar org-table-column-name-regexp nil
10590 "Regular expression matching the current column names.")
10591 (defvar org-table-local-parameters nil
10592 "Alist with parameter names, derived from the `$' line.")
10593 (defvar org-table-named-field-locations nil
10594 "Alist with locations of named fields.")
10596 (defun org-table-get-formula (&optional equation named)
10597 "Read a formula from the minibuffer, offer stored formula as default."
10598 (let* ((name (car (rassoc (list (org-current-line)
10599 (org-table-current-column))
10600 org-table-named-field-locations)))
10601 (scol (if named
10602 (if name name
10603 (error "Not in a named field"))
10604 (int-to-string (org-table-current-column))))
10605 (dummy (and name (not named)
10606 (not (y-or-n-p "Replace named-field formula with column equation? " ))
10607 (error "Abort")))
10608 (org-table-may-need-update nil)
10609 (stored-list (org-table-get-stored-formulas))
10610 (stored (cdr (assoc scol stored-list)))
10611 (eq (cond
10612 ((and stored equation (string-match "^ *=? *$" equation))
10613 stored)
10614 ((stringp equation)
10615 equation)
10616 (t (read-string
10617 (format "%s formula $%s=" (if named "Field" "Column") scol)
10618 (or stored "") 'org-table-formula-history
10619 ;stored
10620 ))))
10621 mustsave)
10622 (when (not (string-match "\\S-" eq))
10623 ;; remove formula
10624 (setq stored-list (delq (assoc scol stored-list) stored-list))
10625 (org-table-store-formulas stored-list)
10626 (error "Formula removed"))
10627 (if (string-match "^ *=?" eq) (setq eq (replace-match "" t t eq)))
10628 (if (string-match " *$" eq) (setq eq (replace-match "" t t eq)))
10629 (if (and name (not named))
10630 ;; We set the column equation, delete the named one.
10631 (setq stored-list (delq (assoc name stored-list) stored-list)
10632 mustsave t))
10633 (if stored
10634 (setcdr (assoc scol stored-list) eq)
10635 (setq stored-list (cons (cons scol eq) stored-list)))
10636 (if (or mustsave (not (equal stored eq)))
10637 (org-table-store-formulas stored-list))
10638 eq))
10640 (defun org-table-store-formulas (alist)
10641 "Store the list of formulas below the current table."
10642 (setq alist (sort alist (lambda (a b) (string< (car a) (car b)))))
10643 (save-excursion
10644 (goto-char (org-table-end))
10645 (if (looking-at "\\([ \t]*\n\\)*#\\+TBLFM:.*\n?")
10646 (delete-region (point) (match-end 0)))
10647 (insert "#+TBLFM: "
10648 (mapconcat (lambda (x)
10649 (concat "$" (car x) "=" (cdr x)))
10650 alist "::")
10651 "\n")))
10653 (defun org-table-get-stored-formulas ()
10654 "Return an alist with the stored formulas directly after current table."
10655 (interactive)
10656 (let (scol eq eq-alist strings string seen)
10657 (save-excursion
10658 (goto-char (org-table-end))
10659 (when (looking-at "\\([ \t]*\n\\)*#\\+TBLFM: *\\(.*\\)")
10660 (setq strings (org-split-string (match-string 2) " *:: *"))
10661 (while (setq string (pop strings))
10662 (when (string-match "\\$\\([a-zA-Z0-9]+\\) *= *\\(.*[^ \t]\\)" string)
10663 (setq scol (match-string 1 string)
10664 eq (match-string 2 string)
10665 eq-alist (cons (cons scol eq) eq-alist))
10666 (if (member scol seen)
10667 (error "Double definition `$%s=' in TBLFM line, please fix by hand" scol)
10668 (push scol seen))))))
10669 (nreverse eq-alist)))
10671 (defun org-table-modify-formulas (action &rest columns)
10672 "Modify the formulas stored below the current table.
10673 ACTION can be `remove', `insert', `swap'. For `swap', two column numbers are
10674 expected, for the other actions only a single column number is needed."
10675 (let ((list (org-table-get-stored-formulas))
10676 (nmax (length (org-split-string
10677 (buffer-substring (point-at-bol) (point-at-eol))
10678 "|")))
10679 col col1 col2 scol si sc1 sc2)
10680 (cond
10681 ((null list)) ; No action needed if there are no stored formulas
10682 ((eq action 'remove)
10683 (setq col (car columns)
10684 scol (int-to-string col))
10685 (org-table-replace-in-formulas list scol "INVALID")
10686 (if (assoc scol list) (setq list (delq (assoc scol list) list)))
10687 (loop for i from (1+ col) upto nmax by 1 do
10688 (setq si (int-to-string i))
10689 (org-table-replace-in-formulas list si (int-to-string (1- i)))
10690 (if (assoc si list) (setcar (assoc si list)
10691 (int-to-string (1- i))))))
10692 ((eq action 'insert)
10693 (setq col (car columns))
10694 (loop for i from nmax downto col by 1 do
10695 (setq si (int-to-string i))
10696 (org-table-replace-in-formulas list si (int-to-string (1+ i)))
10697 (if (assoc si list) (setcar (assoc si list)
10698 (int-to-string (1+ i))))))
10699 ((eq action 'swap)
10700 (setq col1 (car columns) col2 (nth 1 columns)
10701 sc1 (int-to-string col1) sc2 (int-to-string col2))
10702 ;; Hopefully, ZqZtZ will never be a name in a table
10703 (org-table-replace-in-formulas list sc1 "ZqZtZ")
10704 (org-table-replace-in-formulas list sc2 sc1)
10705 (org-table-replace-in-formulas list "ZqZtZ" sc2)
10706 (if (assoc sc1 list) (setcar (assoc sc1 list) "ZqZtZ"))
10707 (if (assoc sc2 list) (setcar (assoc sc2 list) sc1))
10708 (if (assoc "ZqZtZ" list) (setcar (assoc "ZqZtZ" list) sc2)))
10709 (t (error "Invalid action in `org-table-modify-formulas'")))
10710 (if list (org-table-store-formulas list))))
10712 (defun org-table-replace-in-formulas (list s1 s2)
10713 (let (elt re s)
10714 (setq s1 (concat "$" (if (integerp s1) (int-to-string s1) s1))
10715 s2 (concat "$" (if (integerp s2) (int-to-string s2) s2))
10716 re (concat (regexp-quote s1) "\\>"))
10717 (while (setq elt (pop list))
10718 (setq s (cdr elt))
10719 (while (string-match re s)
10720 (setq s (replace-match s2 t t s)))
10721 (setcdr elt s))))
10723 (defun org-table-get-specials ()
10724 "Get the column names and local parameters for this table."
10725 (save-excursion
10726 (let ((beg (org-table-begin)) (end (org-table-end))
10727 names name fields fields1 field cnt c v line col)
10728 (setq org-table-column-names nil
10729 org-table-local-parameters nil
10730 org-table-named-field-locations nil)
10731 (goto-char beg)
10732 (when (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t)
10733 (setq names (org-split-string (match-string 1) " *| *")
10734 cnt 1)
10735 (while (setq name (pop names))
10736 (setq cnt (1+ cnt))
10737 (if (string-match "^[a-zA-Z][a-zA-Z0-9]*$" name)
10738 (push (cons name (int-to-string cnt)) org-table-column-names))))
10739 (setq org-table-column-names (nreverse org-table-column-names))
10740 (setq org-table-column-name-regexp
10741 (concat "\\$\\(" (mapconcat 'car org-table-column-names "\\|") "\\)\\>"))
10742 (goto-char beg)
10743 (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t)
10744 (setq fields (org-split-string (match-string 1) " *| *"))
10745 (while (setq field (pop fields))
10746 (if (string-match "^\\([a-zA-Z][a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field)
10747 (push (cons (match-string 1 field) (match-string 2 field))
10748 org-table-local-parameters))))
10749 (goto-char beg)
10750 (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t)
10751 (setq c (match-string 1)
10752 fields (org-split-string (match-string 2) " *| *"))
10753 (save-excursion
10754 (beginning-of-line (if (equal c "_") 2 0))
10755 (setq line (org-current-line) col 1)
10756 (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)")
10757 (setq fields1 (org-split-string (match-string 1) " *| *"))))
10758 (while (and fields1 (setq field (pop fields)))
10759 (setq v (pop fields1) col (1+ col))
10760 (when (and (stringp field) (stringp v)
10761 (string-match "^[a-zA-Z][a-zA-Z0-9]*$" field))
10762 (push (cons field v) org-table-local-parameters)
10763 (push (list field line col) org-table-named-field-locations)))))))
10765 (defun org-this-word ()
10766 ;; Get the current word
10767 (save-excursion
10768 (let ((beg (progn (skip-chars-backward "^ \t\n") (point)))
10769 (end (progn (skip-chars-forward "^ \t\n") (point))))
10770 (buffer-substring-no-properties beg end))))
10772 (defun org-table-maybe-eval-formula ()
10773 "Check if the current field starts with \"=\" or \":=\".
10774 If yes, store the formula and apply it."
10775 ;; We already know we are in a table. Get field will only return a formula
10776 ;; when appropriate. It might return a separator line, but no problem.
10777 (when org-table-formula-evaluate-inline
10778 (let* ((field (org-trim (or (org-table-get-field) "")))
10779 named eq)
10780 (when (string-match "^:?=\\(.*\\)" field)
10781 (setq named (equal (string-to-char field) ?:)
10782 eq (match-string 1 field))
10783 (if (fboundp 'calc-eval)
10784 (org-table-eval-formula (if named '(4) nil) eq))))))
10786 (defvar org-recalc-commands nil
10787 "List of commands triggering the recalculation of a line.
10788 Will be filled automatically during use.")
10790 (defvar org-recalc-marks
10791 '((" " . "Unmarked: no special line, no automatic recalculation")
10792 ("#" . "Automatically recalculate this line upon TAB, RET, and C-c C-c in the line")
10793 ("*" . "Recalculate only when entire table is recalculated with `C-u C-c *'")
10794 ("!" . "Column name definition line. Reference in formula as $name.")
10795 ("$" . "Parameter definition line name=value. Reference in formula as $name.")
10796 ("_" . "Names for values in row below this one.")
10797 ("^" . "Names for values in row above this one.")))
10799 (defun org-table-rotate-recalc-marks (&optional newchar)
10800 "Rotate the recalculation mark in the first column.
10801 If in any row, the first field is not consistent with a mark,
10802 insert a new column for the markers.
10803 When there is an active region, change all the lines in the region,
10804 after prompting for the marking character.
10805 After each change, a message will be displayed indicating the meaning
10806 of the new mark."
10807 (interactive)
10808 (unless (org-at-table-p) (error "Not at a table"))
10809 (let* ((marks (append (mapcar 'car org-recalc-marks) '(" ")))
10810 (beg (org-table-begin))
10811 (end (org-table-end))
10812 (l (org-current-line))
10813 (l1 (if (org-region-active-p) (org-current-line (region-beginning))))
10814 (l2 (if (org-region-active-p) (org-current-line (region-end))))
10815 (have-col
10816 (save-excursion
10817 (goto-char beg)
10818 (not (re-search-forward "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" end t))))
10819 (col (org-table-current-column))
10820 (forcenew (car (assoc newchar org-recalc-marks)))
10821 epos new)
10822 (when l1
10823 (message "Change region to what mark? Type # * ! $ or SPC: ")
10824 (setq newchar (char-to-string (read-char-exclusive))
10825 forcenew (car (assoc newchar org-recalc-marks))))
10826 (if (and newchar (not forcenew))
10827 (error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'"
10828 newchar))
10829 (if l1 (goto-line l1))
10830 (save-excursion
10831 (beginning-of-line 1)
10832 (unless (looking-at org-table-dataline-regexp)
10833 (error "Not at a table data line")))
10834 (unless have-col
10835 (org-table-goto-column 1)
10836 (org-table-insert-column)
10837 (org-table-goto-column (1+ col)))
10838 (setq epos (point-at-eol))
10839 (save-excursion
10840 (beginning-of-line 1)
10841 (org-table-get-field
10842 1 (if (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|")
10843 (concat " "
10844 (setq new (or forcenew
10845 (cadr (member (match-string 1) marks))))
10846 " ")
10847 " # ")))
10848 (if (and l1 l2)
10849 (progn
10850 (goto-line l1)
10851 (while (progn (beginning-of-line 2) (not (= (org-current-line) l2)))
10852 (and (looking-at org-table-dataline-regexp)
10853 (org-table-get-field 1 (concat " " new " "))))
10854 (goto-line l1)))
10855 (if (not (= epos (point-at-eol))) (org-table-align))
10856 (goto-line l)
10857 (and (interactive-p) (message (cdr (assoc new org-recalc-marks))))))
10859 (defun org-table-maybe-recalculate-line ()
10860 "Recompute the current line if marked for it, and if we haven't just done it."
10861 (interactive)
10862 (and org-table-allow-automatic-line-recalculation
10863 (not (and (memq last-command org-recalc-commands)
10864 (equal org-last-recalc-line (org-current-line))))
10865 (save-excursion (beginning-of-line 1)
10866 (looking-at org-table-auto-recalculate-regexp))
10867 (fboundp 'calc-eval)
10868 (org-table-recalculate) t))
10870 (defvar org-table-formula-debug nil
10871 "Non-nil means, debug table formulas.
10872 When nil, simply write \"#ERROR\" in corrupted fields.")
10874 (defvar modes)
10875 (defsubst org-set-calc-mode (var &optional value)
10876 (if (stringp var)
10877 (setq var (assoc var '(("D" calc-angle-mode deg)
10878 ("R" calc-angle-mode rad)
10879 ("F" calc-prefer-frac t)
10880 ("S" calc-symbolic-mode t)))
10881 value (nth 2 var) var (nth 1 var)))
10882 (if (memq var modes)
10883 (setcar (cdr (memq var modes)) value)
10884 (cons var (cons value modes)))
10885 modes)
10887 (defun org-table-eval-formula (&optional arg equation
10888 suppress-align suppress-const
10889 suppress-store)
10890 "Replace the table field value at the cursor by the result of a calculation.
10892 This function makes use of Dave Gillespie's Calc package, in my view the
10893 most exciting program ever written for GNU Emacs. So you need to have Calc
10894 installed in order to use this function.
10896 In a table, this command replaces the value in the current field with the
10897 result of a formula. It also installs the formula as the \"current\" column
10898 formula, by storing it in a special line below the table. When called
10899 with a `C-u' prefix, the current field must ba a named field, and the
10900 formula is installed as valid in only this specific field.
10902 When called, the command first prompts for a formula, which is read in
10903 the minibuffer. Previously entered formulas are available through the
10904 history list, and the last used formula is offered as a default.
10905 These stored formulas are adapted correctly when moving, inserting, or
10906 deleting columns with the corresponding commands.
10908 The formula can be any algebraic expression understood by the Calc package.
10909 For details, see the Org-mode manual.
10911 This function can also be called from Lisp programs and offers
10912 additional arguments: EQUATION can be the formula to apply. If this
10913 argument is given, the user will not be prompted. SUPPRESS-ALIGN is
10914 used to speed-up recursive calls by by-passing unnecessary aligns.
10915 SUPPRESS-CONST suppresses the interpretation of constants in the
10916 formula, assuming that this has been done already outside the function.
10917 SUPPRESS-STORE means the formula should not be stored, either because
10918 it is already stored, or because it is a modified equation that should
10919 not overwrite the stored one."
10920 (interactive "P")
10921 (require 'calc)
10922 (org-table-check-inside-data-field)
10923 (org-table-get-specials)
10924 (let* (fields
10925 (ndown (if (integerp arg) arg 1))
10926 (org-table-automatic-realign nil)
10927 (case-fold-search nil)
10928 (down (> ndown 1))
10929 (formula (if (and equation suppress-store)
10930 equation
10931 (org-table-get-formula equation (equal arg '(4)))))
10932 (n0 (org-table-current-column))
10933 (modes (copy-sequence org-calc-default-modes))
10934 n form fmt x ev orig c lispp)
10935 ;; Parse the format string. Since we have a lot of modes, this is
10936 ;; a lot of work. However, I think calc still uses most of the time.
10937 (if (string-match ";" formula)
10938 (let ((tmp (org-split-string formula ";")))
10939 (setq formula (car tmp)
10940 fmt (concat (cdr (assoc "%" org-table-local-parameters))
10941 (nth 1 tmp)))
10942 (while (string-match "[pnfse]\\(-?[0-9]+\\)" fmt)
10943 (setq c (string-to-char (match-string 1 fmt))
10944 n (string-to-number (or (match-string 1 fmt) "")))
10945 (if (= c ?p) (setq modes (org-set-calc-mode 'calc-internal-prec n))
10946 (setq modes (org-set-calc-mode
10947 'calc-float-format
10948 (list (cdr (assoc c '((?n . float) (?f . fix)
10949 (?s . sci) (?e . eng))))
10950 n))))
10951 (setq fmt (replace-match "" t t fmt)))
10952 (while (string-match "[DRFS]" fmt)
10953 (setq modes (org-set-calc-mode (match-string 0 fmt)))
10954 (setq fmt (replace-match "" t t fmt)))
10955 (unless (string-match "\\S-" fmt)
10956 (setq fmt nil))))
10957 (if (and (not suppress-const) org-table-formula-use-constants)
10958 (setq formula (org-table-formula-substitute-names formula)))
10959 (setq orig (or (get-text-property 1 :orig-formula formula) "?"))
10960 (while (> ndown 0)
10961 (setq fields (org-split-string
10962 (buffer-substring
10963 (point-at-bol) (point-at-eol)) " *| *"))
10964 (if org-table-formula-numbers-only
10965 (setq fields (mapcar
10966 (lambda (x) (number-to-string (string-to-number x)))
10967 fields)))
10968 (setq ndown (1- ndown))
10969 (setq form (copy-sequence formula)
10970 lispp (equal (substring form 0 2) "'("))
10971 ;; Insert the references to fields in same row
10972 (while (string-match "\\$\\([0-9]+\\)?" form)
10973 (setq n (if (match-beginning 1)
10974 (string-to-number (match-string 1 form))
10976 x (nth (1- n) fields))
10977 (unless x (error "Invalid field specifier \"%s\""
10978 (match-string 0 form)))
10979 (if (equal x "") (setq x "0"))
10980 (setq form (replace-match
10981 (if lispp x (concat "(" x ")"))
10982 t t form)))
10983 ;; Insert ranges in current column
10984 (while (string-match "\\&[-I0-9]+" form)
10985 (setq form (replace-match
10986 (save-match-data
10987 (org-table-get-vertical-vector (match-string 0 form)
10988 nil n0))
10989 t t form)))
10990 (if lispp
10991 (setq ev (eval (eval (read form)))
10992 ev (if (numberp ev) (number-to-string ev) ev))
10993 (setq ev (calc-eval (cons form modes)
10994 (if org-table-formula-numbers-only 'num))))
10996 (when org-table-formula-debug
10997 (with-output-to-temp-buffer "*Help*"
10998 (princ (format "Substitution history of formula
10999 Orig: %s
11000 $xyz-> %s
11001 $1-> %s\n" orig formula form))
11002 (if (listp ev)
11003 (princ (format " %s^\nError: %s"
11004 (make-string (car ev) ?\-) (nth 1 ev)))
11005 (princ (format "Result: %s\nFormat: %s\nFinal: %s"
11006 ev (or fmt "NONE")
11007 (if fmt (format fmt (string-to-number ev)) ev)))))
11008 (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*"))
11009 (unless (and (interactive-p) (not ndown))
11010 (unless (let (inhibit-redisplay)
11011 (y-or-n-p "Debugging Formula. Continue to next? "))
11012 (org-table-align)
11013 (error "Abort"))
11014 (delete-window (get-buffer-window "*Help*"))
11015 (message "")))
11016 (if (listp ev) (setq fmt nil ev "#ERROR"))
11017 (org-table-justify-field-maybe
11018 (if fmt (format fmt (string-to-number ev)) ev))
11019 (if (and down (> ndown 0) (looking-at ".*\n[ \t]*|[^-]"))
11020 (call-interactively 'org-return)
11021 (setq ndown 0)))
11022 (and down (org-table-maybe-recalculate-line))
11023 (or suppress-align (and org-table-may-need-update
11024 (org-table-align)))))
11026 (defun org-table-recalculate (&optional all noalign)
11027 "Recalculate the current table line by applying all stored formulas.
11028 With prefix arg ALL, do this for all lines in the table."
11029 (interactive "P")
11030 (or (memq this-command org-recalc-commands)
11031 (setq org-recalc-commands (cons this-command org-recalc-commands)))
11032 (unless (org-at-table-p) (error "Not at a table"))
11033 (org-table-get-specials)
11034 (let* ((eqlist (sort (org-table-get-stored-formulas)
11035 (lambda (a b) (string< (car a) (car b)))))
11036 (inhibit-redisplay t)
11037 (line-re org-table-dataline-regexp)
11038 (thisline (+ (if (bolp) 1 0) (count-lines (point-min) (point))))
11039 (thiscol (org-table-current-column))
11040 beg end entry eqlnum eqlname eql (cnt 0) eq a name)
11041 ;; Insert constants in all formulas
11042 (setq eqlist
11043 (mapcar (lambda (x)
11044 (setcdr x (org-table-formula-substitute-names (cdr x)))
11046 eqlist))
11047 ;; Split the equation list
11048 (while (setq eq (pop eqlist))
11049 (if (<= (string-to-char (car eq)) ?9)
11050 (push eq eqlnum)
11051 (push eq eqlname)))
11052 (setq eqlnum (nreverse eqlnum) eqlname (nreverse eqlname))
11053 (if all
11054 (progn
11055 (setq end (move-marker (make-marker) (1+ (org-table-end))))
11056 (goto-char (setq beg (org-table-begin)))
11057 (if (re-search-forward org-table-calculate-mark-regexp end t)
11058 ;; This is a table with marked lines, only compute selected lines
11059 (setq line-re org-table-recalculate-regexp)
11060 ;; Move forward to the first non-header line
11061 (if (and (re-search-forward org-table-dataline-regexp end t)
11062 (re-search-forward org-table-hline-regexp end t)
11063 (re-search-forward org-table-dataline-regexp end t))
11064 (setq beg (match-beginning 0))
11065 nil))) ;; just leave beg where it is
11066 (setq beg (point-at-bol)
11067 end (move-marker (make-marker) (1+ (point-at-eol)))))
11068 (goto-char beg)
11069 (and all (message "Re-applying formulas to full table..."))
11070 (while (re-search-forward line-re end t)
11071 (unless (string-match "^ *[_^!$] *$" (org-table-get-field 1))
11072 ;; Unprotected line, recalculate
11073 (and all (message "Re-applying formulas to full table...(line %d)"
11074 (setq cnt (1+ cnt))))
11075 (setq org-last-recalc-line (org-current-line))
11076 (setq eql eqlnum)
11077 (while (setq entry (pop eql))
11078 (goto-line org-last-recalc-line)
11079 (org-table-goto-column (string-to-number (car entry)) nil 'force)
11080 (org-table-eval-formula nil (cdr entry) 'noalign 'nocst 'nostore))))
11081 (goto-line thisline)
11082 (org-table-goto-column thiscol)
11083 (or noalign (and org-table-may-need-update (org-table-align))
11084 (and all (message "Re-applying formulas to %d lines...done" cnt)))
11085 ;; Now do the names fields
11086 (while (setq eq (pop eqlname))
11087 (setq name (car eq)
11088 a (assoc name org-table-named-field-locations))
11089 (when a
11090 (message "Re-applying formula to named field: %s" name)
11091 (goto-line (nth 1 a))
11092 (org-table-goto-column (nth 2 a))
11093 (org-table-eval-formula nil (cdr eq) 'noalign 'nocst 'nostore)))
11094 ;; back to initial position
11095 (goto-line thisline)
11096 (org-table-goto-column thiscol)
11097 (or noalign (and org-table-may-need-update (org-table-align))
11098 (and all (message "Re-applying formulas...done")))))
11100 (defun org-table-formula-substitute-names (f)
11101 "Replace $const with values in string F."
11102 (let ((start 0) a n1 n2 nn1 nn2 s (f1 f))
11103 ;; First, check for column names
11104 (while (setq start (string-match org-table-column-name-regexp f start))
11105 (setq start (1+ start))
11106 (setq a (assoc (match-string 1 f) org-table-column-names))
11107 (setq f (replace-match (concat "$" (cdr a)) t t f)))
11108 ;; Expand ranges to vectors
11109 (while (string-match "\\$\\([0-9]+\\)\\.\\.\\.?\\$\\([0-9]+\\)" f)
11110 (setq n1 (string-to-number (match-string 1 f))
11111 n2 (string-to-number (match-string 2 f))
11112 nn1 (1+ (min n1 n2)) nn2 (max n1 n2)
11113 s (concat "[($" (number-to-string (1- nn1)) ")"))
11114 (loop for i from nn1 upto nn2 do
11115 (setq s (concat s ",($" (int-to-string i) ")")))
11116 (setq s (concat s "]"))
11117 (if (< n2 n1) (setq s (concat "rev(" s ")")))
11118 (setq f (replace-match s t t f)))
11119 ;; Parameters and constants
11120 (setq start 0)
11121 (while (setq start (string-match "\\$\\([a-zA-Z][a-zA-Z0-9]*\\)" f start))
11122 (setq start (1+ start))
11123 (if (setq a (save-match-data
11124 (org-table-get-constant (match-string 1 f))))
11125 (setq f (replace-match (concat "(" a ")") t t f))))
11126 (if org-table-formula-debug
11127 (put-text-property 0 (length f) :orig-formula f1 f))
11130 (defun org-table-get-constant (const)
11131 "Find the value for a parameter or constant in a formula.
11132 Parameters get priority."
11133 (or (cdr (assoc const org-table-local-parameters))
11134 (cdr (assoc const org-table-formula-constants))
11135 (and (fboundp 'constants-get) (constants-get const))
11136 "#UNDEFINED_NAME"))
11138 (defvar org-edit-formulas-map (make-sparse-keymap))
11139 (define-key org-edit-formulas-map "\C-c\C-c" 'org-finish-edit-formulas)
11140 (define-key org-edit-formulas-map "\C-c\C-q" 'org-abort-edit-formulas)
11141 (define-key org-edit-formulas-map "\C-c?" 'org-show-variable)
11143 (defvar org-pos)
11145 (defun org-table-edit-formulas ()
11146 "Edit the formulas of the current table in a separate buffer."
11147 (interactive)
11148 (unless (org-at-table-p)
11149 (error "Not at a table"))
11150 (org-table-get-specials)
11151 (let ((eql (org-table-get-stored-formulas))
11152 (pos (move-marker (make-marker) (point)))
11153 (wc (current-window-configuration))
11154 entry loc s)
11155 (switch-to-buffer-other-window "*Edit Formulas*")
11156 (erase-buffer)
11157 (fundamental-mode)
11158 (set (make-local-variable 'org-pos) pos)
11159 (set (make-local-variable 'org-window-configuration) wc)
11160 (use-local-map org-edit-formulas-map)
11161 (setq s "# Edit formulas and finish with `C-c C-c'.
11162 # Use `C-u C-c C-c' to also appy them immediately to the entire table.
11163 # Use `C-c ?' to get information about $name at point.
11164 # To cancel editing, press `C-c C-q'.\n")
11165 (put-text-property 0 (length s) 'face 'font-lock-comment-face s)
11166 (insert s)
11167 (while (setq entry (pop eql))
11168 (when (setq loc (assoc (car entry) org-table-named-field-locations))
11169 (setq s (format "# Named formula, referring to column %d in line %d\n"
11170 (nth 2 loc) (nth 1 loc)))
11171 (put-text-property 0 (length s) 'face 'font-lock-comment-face s)
11172 (insert s))
11173 (setq s (concat "$" (car entry) "=" (cdr entry) "\n"))
11174 (remove-text-properties 0 (length s) '(face nil) s)
11175 (insert s))
11176 (goto-char (point-min))
11177 (message "Edit formulas and finish with `C-c C-c'.")))
11179 (defun org-show-variable ()
11180 "Show the location/value of the $ expression at point."
11181 (interactive)
11182 (let (var (pos org-pos) (win (selected-window)) e)
11183 (save-excursion
11184 (or (looking-at "\\$") (skip-chars-backward "$a-zA-Z0-9"))
11185 (if (looking-at "\\$\\([a-zA-Z0-9]+\\)")
11186 (setq var (match-string 1))
11187 (error "No variable at point")))
11188 (cond
11189 ((setq e (assoc var org-table-named-field-locations))
11190 (switch-to-buffer-other-window (marker-buffer pos))
11191 (goto-line (nth 1 e))
11192 (org-table-goto-column (nth 2 e))
11193 (select-window win)
11194 (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e)))
11195 ((setq e (assoc var org-table-column-names))
11196 (switch-to-buffer-other-window (marker-buffer pos))
11197 (goto-char pos)
11198 (goto-char (org-table-begin))
11199 (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|")
11200 (org-table-end) t)
11201 (progn
11202 (goto-char (match-beginning 1))
11203 (message "Named column (column %s)" (cdr e)))
11204 (error "Column name not found"))
11205 (select-window win))
11206 ((string-match "^[0-9]$" var)
11207 ;; column number
11208 (switch-to-buffer-other-window (marker-buffer pos))
11209 (goto-char pos)
11210 (goto-char (org-table-begin))
11211 (recenter 1)
11212 (if (re-search-forward org-table-dataline-regexp
11213 (org-table-end) t)
11214 (progn
11215 (goto-char (match-beginning 0))
11216 (org-table-goto-column (string-to-number var))
11217 (message "Column %s" var))
11218 (error "Column name not found"))
11219 (select-window win))
11220 ((setq e (assoc var org-table-local-parameters))
11221 (switch-to-buffer-other-window (marker-buffer pos))
11222 (goto-char pos)
11223 (goto-char (org-table-begin))
11224 (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") nil t)
11225 (progn
11226 (goto-char (match-beginning 1))
11227 (message "Local parameter."))
11228 (error "Parameter not found"))
11229 (select-window win))
11231 (cond
11232 ((setq e (assoc var org-table-formula-constants))
11233 (message "Constant: $%s=%s in `org-table-formula-constants'." var (cdr e)))
11234 ((setq e (and (fboundp 'constants-get) (constants-get var)))
11235 (message "Constant: $%s=%s, retrieved from `constants.el'." var e))
11236 (t (error "Undefined name $%s" var)))))))
11238 (defun org-finish-edit-formulas (&optional arg)
11239 "Parse the buffer for formula definitions and install them.
11240 With prefix ARG, apply the new formulas to the table."
11241 (interactive "P")
11242 (let ((pos org-pos) eql)
11243 (goto-char (point-min))
11244 (while (re-search-forward "^\\$\\([a-zA-Z0-9]+\\) *= *\\(.*?\\) *$" nil t)
11245 (push (cons (match-string 1) (match-string 2)) eql))
11246 (set-window-configuration org-window-configuration)
11247 (select-window (get-buffer-window (marker-buffer pos)))
11248 (goto-char pos)
11249 (unless (org-at-table-p)
11250 (error "Lost table position - cannot install formulae"))
11251 (org-table-store-formulas eql)
11252 (move-marker pos nil)
11253 (kill-buffer "*Edit Formulas*")
11254 (if arg
11255 (org-table-recalculate 'all)
11256 (message "New formulas installed - press C-u C-c C-c to apply."))))
11258 (defun org-abort-edit-formulas ()
11259 "Abort editing formulas, without installing the changes."
11260 (interactive)
11261 (let ((pos org-pos))
11262 (set-window-configuration org-window-configuration)
11263 (select-window (get-buffer-window (marker-buffer pos)))
11264 (goto-char pos)
11265 (message "Formula editing aborted without installing changes")))
11267 ;;; The orgtbl minor mode
11269 ;; Define a minor mode which can be used in other modes in order to
11270 ;; integrate the org-mode table editor.
11272 ;; This is really a hack, because the org-mode table editor uses several
11273 ;; keys which normally belong to the major mode, for example the TAB and
11274 ;; RET keys. Here is how it works: The minor mode defines all the keys
11275 ;; necessary to operate the table editor, but wraps the commands into a
11276 ;; function which tests if the cursor is currently inside a table. If that
11277 ;; is the case, the table editor command is executed. However, when any of
11278 ;; those keys is used outside a table, the function uses `key-binding' to
11279 ;; look up if the key has an associated command in another currently active
11280 ;; keymap (minor modes, major mode, global), and executes that command.
11281 ;; There might be problems if any of the keys used by the table editor is
11282 ;; otherwise used as a prefix key.
11284 ;; Another challenge is that the key binding for TAB can be tab or \C-i,
11285 ;; likewise the binding for RET can be return or \C-m. Orgtbl-mode
11286 ;; addresses this by checking explicitly for both bindings.
11288 ;; The optimized version (see variable `orgtbl-optimized') takes over
11289 ;; all keys which are bound to `self-insert-command' in the *global map*.
11290 ;; Some modes bind other commands to simple characters, for example
11291 ;; AUCTeX binds the double quote to `Tex-insert-quote'. With orgtbl-mode
11292 ;; active, this binding is ignored inside tables and replaced with a
11293 ;; modified self-insert.
11295 (defvar orgtbl-mode nil
11296 "Variable controlling `orgtbl-mode', a minor mode enabling the `org-mode'
11297 table editor in arbitrary modes.")
11298 (make-variable-buffer-local 'orgtbl-mode)
11300 (defvar orgtbl-mode-map (make-keymap)
11301 "Keymap for `orgtbl-mode'.")
11303 ;;;###autoload
11304 (defun turn-on-orgtbl ()
11305 "Unconditionally turn on `orgtbl-mode'."
11306 (orgtbl-mode 1))
11308 ;;;###autoload
11309 (defun orgtbl-mode (&optional arg)
11310 "The `org-mode' table editor as a minor mode for use in other modes."
11311 (interactive)
11312 (if (eq major-mode 'org-mode)
11313 ;; Exit without error, in case some hook functions calls this
11314 ;; by accident in org-mode.
11315 (message "Orgtbl-mode is not useful in org-mode, command ignored")
11316 (setq orgtbl-mode
11317 (if arg (> (prefix-numeric-value arg) 0) (not orgtbl-mode)))
11318 (if orgtbl-mode
11319 (progn
11320 (and (orgtbl-setup) (defun orgtbl-setup () nil))
11321 ;; Make sure we are first in minor-mode-map-alist
11322 (let ((c (assq 'orgtbl-mode minor-mode-map-alist)))
11323 (and c (setq minor-mode-map-alist
11324 (cons c (delq c minor-mode-map-alist)))))
11325 (set (make-local-variable (quote org-table-may-need-update)) t)
11326 (org-add-hook 'before-change-functions 'org-before-change-function
11327 nil 'local)
11328 (set (make-local-variable 'org-old-auto-fill-inhibit-regexp)
11329 auto-fill-inhibit-regexp)
11330 (set (make-local-variable 'auto-fill-inhibit-regexp)
11331 (if auto-fill-inhibit-regexp
11332 (concat "\\([ \t]*|\\|" auto-fill-inhibit-regexp)
11333 "[ \t]*|"))
11334 (org-add-to-invisibility-spec '(org-cwidth))
11335 (easy-menu-add orgtbl-mode-menu)
11336 (run-hooks 'orgtbl-mode-hook))
11337 (setq auto-fill-inhibit-regexp org-old-auto-fill-inhibit-regexp)
11338 (org-cleanup-narrow-column-properties)
11339 (org-remove-from-invisibility-spec '(org-cwidth))
11340 (remove-hook 'before-change-functions 'org-before-change-function t)
11341 (easy-menu-remove orgtbl-mode-menu)
11342 (force-mode-line-update 'all))))
11344 (defun org-cleanup-narrow-column-properties ()
11345 "Remove all properties related to narrow-column invisibility."
11346 (let ((s 1))
11347 (while (setq s (text-property-any s (point-max)
11348 'display org-narrow-column-arrow))
11349 (remove-text-properties s (1+ s) '(display t)))
11350 (setq s 1)
11351 (while (setq s (text-property-any s (point-max) 'org-cwidth 1))
11352 (remove-text-properties s (1+ s) '(org-cwidth t)))
11353 (setq s 1)
11354 (while (setq s (text-property-any s (point-max) 'invisible 'org-cwidth))
11355 (remove-text-properties s (1+ s) '(invisible t)))))
11357 ;; Install it as a minor mode.
11358 (put 'orgtbl-mode :included t)
11359 (put 'orgtbl-mode :menu-tag "Org Table Mode")
11360 (add-minor-mode 'orgtbl-mode " OrgTbl" orgtbl-mode-map)
11362 (defun orgtbl-make-binding (fun n &rest keys)
11363 "Create a function for binding in the table minor mode.
11364 FUN is the command to call inside a table. N is used to create a unique
11365 command name. KEYS are keys that should be checked in for a command
11366 to execute outside of tables."
11367 (eval
11368 (list 'defun
11369 (intern (concat "orgtbl-hijacker-command-" (int-to-string n)))
11370 '(arg)
11371 (concat "In tables, run `" (symbol-name fun) "'.\n"
11372 "Outside of tables, run the binding of `"
11373 (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
11374 "'.")
11375 '(interactive "p")
11376 (list 'if
11377 '(org-at-table-p)
11378 (list 'call-interactively (list 'quote fun))
11379 (list 'let '(orgtbl-mode)
11380 (list 'call-interactively
11381 (append '(or)
11382 (mapcar (lambda (k)
11383 (list 'key-binding k))
11384 keys)
11385 '('orgtbl-error))))))))
11387 (defun orgtbl-error ()
11388 "Error when there is no default binding for a table key."
11389 (interactive)
11390 (error "This key is has no function outside tables"))
11392 (defun orgtbl-setup ()
11393 "Setup orgtbl keymaps."
11394 (let ((nfunc 0)
11395 (bindings
11396 (list
11397 '([(meta shift left)] org-table-delete-column)
11398 '([(meta left)] org-table-move-column-left)
11399 '([(meta right)] org-table-move-column-right)
11400 '([(meta shift right)] org-table-insert-column)
11401 '([(meta shift up)] org-table-kill-row)
11402 '([(meta shift down)] org-table-insert-row)
11403 '([(meta up)] org-table-move-row-up)
11404 '([(meta down)] org-table-move-row-down)
11405 '("\C-c\C-w" org-table-cut-region)
11406 '("\C-c\M-w" org-table-copy-region)
11407 '("\C-c\C-y" org-table-paste-rectangle)
11408 '("\C-c-" org-table-insert-hline)
11409 ; '([(shift tab)] org-table-previous-field)
11410 '("\C-m" org-table-next-row)
11411 (list (org-key 'S-return) 'org-table-copy-down)
11412 '([(meta return)] org-table-wrap-region)
11413 '("\C-c\C-q" org-table-wrap-region)
11414 '("\C-c?" org-table-current-column)
11415 '("\C-c " org-table-blank-field)
11416 '("\C-c+" org-table-sum)
11417 '("\C-c=" org-table-eval-formula)
11418 '("\C-c'" org-table-edit-formulas)
11419 '("\C-c`" org-table-edit-field)
11420 '("\C-c*" org-table-recalculate)
11421 '("\C-c|" org-table-create-or-convert-from-region)
11422 '("\C-c^" org-table-sort-lines)
11423 '([(control ?#)] org-table-rotate-recalc-marks)))
11424 elt key fun cmd)
11425 (while (setq elt (pop bindings))
11426 (setq nfunc (1+ nfunc))
11427 (setq key (car elt)
11428 fun (nth 1 elt)
11429 cmd (orgtbl-make-binding fun nfunc key))
11430 (define-key orgtbl-mode-map key cmd))
11431 ;; Special treatment needed for TAB and RET
11432 (define-key orgtbl-mode-map [(return)]
11433 (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m"))
11434 (define-key orgtbl-mode-map "\C-m"
11435 (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)]))
11436 (define-key orgtbl-mode-map [(tab)]
11437 (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i"))
11438 (define-key orgtbl-mode-map "\C-i"
11439 (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)])))
11440 (define-key orgtbl-mode-map "\C-i"
11441 (orgtbl-make-binding 'orgtbl-tab 104 [(shift tab)]))
11442 (define-key orgtbl-mode-map "\C-c\C-c"
11443 (orgtbl-make-binding 'org-ctrl-c-ctrl-c 105 "\C-c\C-c"))
11444 (when orgtbl-optimized
11445 ;; If the user wants maximum table support, we need to hijack
11446 ;; some standard editing functions
11447 (org-remap orgtbl-mode-map
11448 'self-insert-command 'orgtbl-self-insert-command
11449 'delete-char 'org-delete-char
11450 'delete-backward-char 'org-delete-backward-char)
11451 (define-key orgtbl-mode-map "|" 'org-force-self-insert))
11452 (easy-menu-define orgtbl-mode-menu orgtbl-mode-map "OrgTbl menu"
11453 '("OrgTbl"
11454 ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p) :keys "C-c C-c"]
11455 ["Next Field" org-cycle :active (org-at-table-p) :keys "TAB"]
11456 ["Previous Field" org-shifttab :active (org-at-table-p) :keys "S-TAB"]
11457 ["Next Row" org-return :active (org-at-table-p) :keys "RET"]
11458 "--"
11459 ["Blank Field" org-table-blank-field :active (org-at-table-p) :keys "C-c SPC"]
11460 ["Edit Field" org-table-edit-field :active (org-at-table-p) :keys "C-c ` "]
11461 ["Copy Field from Above"
11462 org-table-copy-down :active (org-at-table-p) :keys "S-RET"]
11463 "--"
11464 ("Column"
11465 ["Move Column Left" org-metaleft :active (org-at-table-p) :keys "M-<left>"]
11466 ["Move Column Right" org-metaright :active (org-at-table-p) :keys "M-<right>"]
11467 ["Delete Column" org-shiftmetaleft :active (org-at-table-p) :keys "M-S-<left>"]
11468 ["Insert Column" org-shiftmetaright :active (org-at-table-p) :keys "M-S-<right>"]
11469 "--"
11470 ["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])
11471 ("Row"
11472 ["Move Row Up" org-metaup :active (org-at-table-p) :keys "M-<up>"]
11473 ["Move Row Down" org-metadown :active (org-at-table-p) :keys "M-<down>"]
11474 ["Delete Row" org-shiftmetaup :active (org-at-table-p) :keys "M-S-<up>"]
11475 ["Insert Row" org-shiftmetadown :active (org-at-table-p) :keys "M-S-<down>"]
11476 ["Sort lines in region" org-table-sort-lines (org-at-table-p) :keys "C-c ^"]
11477 "--"
11478 ["Insert Hline" org-table-insert-hline :active (org-at-table-p) :keys "C-c -"])
11479 ("Rectangle"
11480 ["Copy Rectangle" org-copy-special :active (org-at-table-p)]
11481 ["Cut Rectangle" org-cut-special :active (org-at-table-p)]
11482 ["Paste Rectangle" org-paste-special :active (org-at-table-p)]
11483 ["Fill Rectangle" org-table-wrap-region :active (org-at-table-p)])
11484 "--"
11485 ["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="]
11486 ["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
11487 ["Edit Formulas" org-table-edit-formulas :active (org-at-table-p) :keys "C-c '"]
11488 ["Recalculate line" org-table-recalculate :active (org-at-table-p) :keys "C-c *"]
11489 ["Recalculate all" (org-table-recalculate '(4)) :active (org-at-table-p) :keys "C-u C-c *"]
11490 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks :active (org-at-table-p) :keys "C-c #"]
11491 ["Sum Column/Rectangle" org-table-sum
11492 :active (or (org-at-table-p) (org-region-active-p)) :keys "C-c +"]
11493 ["Which Column?" org-table-current-column :active (org-at-table-p) :keys "C-c ?"]
11494 ["Debug Formulas"
11495 (setq org-table-formula-debug (not org-table-formula-debug))
11496 :style toggle :selected org-table-formula-debug]
11500 (defun orgtbl-tab (arg)
11501 "Justification and field motion for `orgtbl-mode'."
11502 (interactive "P")
11503 (if arg (org-table-edit-field t)
11504 (org-table-justify-field-maybe)
11505 (org-table-next-field)))
11507 (defun orgtbl-ret ()
11508 "Justification and field motion for `orgtbl-mode'."
11509 (interactive)
11510 (org-table-justify-field-maybe)
11511 (org-table-next-row))
11513 (defun orgtbl-self-insert-command (N)
11514 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
11515 If the cursor is in a table looking at whitespace, the whitespace is
11516 overwritten, and the table is not marked as requiring realignment."
11517 (interactive "p")
11518 (if (and (org-at-table-p)
11520 (and org-table-auto-blank-field
11521 (member last-command
11522 '(orgtbl-hijacker-command-100
11523 orgtbl-hijacker-command-101
11524 orgtbl-hijacker-command-102
11525 orgtbl-hijacker-command-103
11526 orgtbl-hijacker-command-104
11527 orgtbl-hijacker-command-105))
11528 (org-table-blank-field))
11530 (eq N 1)
11531 (looking-at "[^|\n]* +|"))
11532 (let (org-table-may-need-update)
11533 (goto-char (1- (match-end 0)))
11534 (delete-backward-char 1)
11535 (goto-char (match-beginning 0))
11536 (self-insert-command N))
11537 (setq org-table-may-need-update t)
11538 (let (orgtbl-mode)
11539 (call-interactively (key-binding (vector last-input-event))))))
11541 (defun org-force-self-insert (N)
11542 "Needed to enforce self-insert under remapping."
11543 (interactive "p")
11544 (self-insert-command N))
11546 ;;; Exporting
11548 (defconst org-level-max 20)
11550 (defvar org-export-html-preamble nil
11551 "Preamble, to be inserted just after <body>. Set by publishing functions.")
11552 (defvar org-export-html-postamble nil
11553 "Preamble, to be inserted just before </body>. Set by publishing functions.")
11554 (defvar org-export-html-auto-preamble t
11555 "Should default preamble be inserted? Set by publishing functions.")
11556 (defvar org-export-html-auto-postamble t
11557 "Should default postamble be inserted? Set by publishing functions.")
11559 (defconst org-export-plist-vars
11560 '((:language . org-export-default-language)
11561 (:headline-levels . org-export-headline-levels)
11562 (:section-numbers . org-export-with-section-numbers)
11563 (:table-of-contents . org-export-with-toc)
11564 (:emphasize . org-export-with-emphasize)
11565 (:sub-superscript . org-export-with-sub-superscripts)
11566 (:TeX-macros . org-export-with-TeX-macros)
11567 (:fixed-width . org-export-with-fixed-width)
11568 (:timestamps . org-export-with-timestamps)
11569 (:tables . org-export-with-tables)
11570 (:table-auto-headline . org-export-highlight-first-table-line)
11571 (:style . org-export-html-style)
11572 (:convert-org-links . org-export-html-link-org-files-as-html)
11573 (:inline-images . org-export-html-inline-images)
11574 (:expand-quoted-html . org-export-html-expand)
11575 (:timestamp . org-export-html-with-timestamp)
11576 (:publishing-directory . org-export-publishing-directory)
11577 (:preamble . org-export-html-preamble)
11578 (:postamble . org-export-html-postamble)
11579 (:auto-preamble . org-export-html-auto-preamble)
11580 (:auto-postamble . org-export-html-auto-postamble)
11581 (:author . user-full-name)
11582 (:email . user-mail-address)))
11584 (defun org-default-export-plist ()
11585 "Return the property list with default settings for the export variables."
11586 (let ((l org-export-plist-vars) rtn e)
11587 (while (setq e (pop l))
11588 (setq rtn (cons (car e) (cons (symbol-value (cdr e)) rtn))))
11589 rtn))
11591 (defun org-infile-export-plist ()
11592 "Return the property list with file-local settings for export."
11593 (save-excursion
11594 (goto-char 0)
11595 (let ((re (org-make-options-regexp
11596 '("TITLE" "AUTHOR" "EMAIL" "TEXT" "OPTIONS" "LANGUAGE")))
11597 (text nil)
11598 p key val text options)
11599 (while (re-search-forward re nil t)
11600 (setq key (org-match-string-no-properties 1)
11601 val (org-match-string-no-properties 2))
11602 (cond
11603 ((string-equal key "TITLE") (setq p (plist-put p :title val)))
11604 ((string-equal key "AUTHOR")(setq p (plist-put p :author val)))
11605 ((string-equal key "EMAIL") (setq p (plist-put p :email val)))
11606 ((string-equal key "LANGUAGE") (setq p (plist-put p :language val)))
11607 ((string-equal key "TEXT")
11608 (setq text (if text (concat text "\n" val) val)))
11609 ((string-equal key "OPTIONS") (setq options val))))
11610 (setq p (plist-put p :text text))
11611 (when options
11612 (let ((op '(("H" . :headline-levels)
11613 ("num" . :section-numbers)
11614 ("toc" . :table-of-contents)
11615 ("\\n" . :preserve-breaks)
11616 ("@" . :expand-quoted-html)
11617 (":" . :fixed-width)
11618 ("|" . :tables)
11619 ("^" . :sub-superscript)
11620 ("*" . :emphasize)
11621 ("TeX" . :TeX-macros)))
11623 (while (setq o (pop op))
11624 (if (string-match (concat (regexp-quote (car o))
11625 ":\\([^ \t\n\r;,.]*\\)")
11626 options)
11627 (setq p (plist-put p (cdr o)
11628 (car (read-from-string
11629 (match-string 1 options)))))))))
11630 p)))
11632 (defun org-combine-plists (&rest plists)
11633 "Create a single property list from all plists in PLISTS.
11634 The process starts by copying the last list, and then setting properties
11635 from the other lists. Settings in the first list are the most significant
11636 ones and overrule settings in the other lists."
11637 (let ((rtn (copy-sequence (pop plists)))
11638 p v ls)
11639 (while plists
11640 (setq ls (pop plists))
11641 (while ls
11642 (setq p (pop ls) v (pop ls))
11643 (setq rtn (plist-put rtn p v))))
11644 rtn))
11646 (defun org-export-directory (type plist)
11647 (let* ((val (plist-get plist :publishing-directory))
11648 (dir (if (listp val)
11649 (or (cdr (assoc type val)) ".")
11650 val)))
11651 dir))
11653 (defun org-export-find-first-heading-line (list)
11654 "Remove all lines from LIST which are before the first headline."
11655 (let ((orig-list list)
11656 (re (concat "^" outline-regexp)))
11657 (while (and list
11658 (not (string-match re (car list))))
11659 (pop list))
11660 (or list orig-list)))
11662 (defun org-skip-comments (lines)
11663 "Skip lines starting with \"#\" and subtrees starting with COMMENT."
11664 (let ((re1 (concat "^\\(\\*+\\)[ \t]+" org-comment-string))
11665 (re2 "^\\(\\*+\\)[ \t\n\r]")
11666 rtn line level)
11667 (while (setq line (pop lines))
11668 (cond
11669 ((and (string-match re1 line)
11670 (setq level (- (match-end 1) (match-beginning 1))))
11671 ;; Beginning of a COMMENT subtree. Skip it.
11672 (while (and (setq line (pop lines))
11673 (or (not (string-match re2 line))
11674 (> (- (match-end 1) (match-beginning 1)) level))))
11675 (setq lines (cons line lines)))
11676 ((string-match "^#" line)
11677 ;; an ordinary comment line
11679 ((and org-export-table-remove-special-lines
11680 (string-match "^[ \t]*| *[!_^] *|" line))
11681 ;; a special table line that should be removed
11683 (t (setq rtn (cons line rtn)))))
11684 (nreverse rtn)))
11686 ;; ASCII
11688 (defconst org-ascii-underline '(?\$ ?\# ?^ ?\~ ?\= ?\-)
11689 "Characters for underlining headings in ASCII export.")
11691 (defconst org-html-entities
11692 '(("nbsp")
11693 ("iexcl")
11694 ("cent")
11695 ("pound")
11696 ("curren")
11697 ("yen")
11698 ("brvbar")
11699 ("sect")
11700 ("uml")
11701 ("copy")
11702 ("ordf")
11703 ("laquo")
11704 ("not")
11705 ("shy")
11706 ("reg")
11707 ("macr")
11708 ("deg")
11709 ("plusmn")
11710 ("sup2")
11711 ("sup3")
11712 ("acute")
11713 ("micro")
11714 ("para")
11715 ("middot")
11716 ("odot"."o")
11717 ("star"."*")
11718 ("cedil")
11719 ("sup1")
11720 ("ordm")
11721 ("raquo")
11722 ("frac14")
11723 ("frac12")
11724 ("frac34")
11725 ("iquest")
11726 ("Agrave")
11727 ("Aacute")
11728 ("Acirc")
11729 ("Atilde")
11730 ("Auml")
11731 ("Aring") ("AA"."&Aring;")
11732 ("AElig")
11733 ("Ccedil")
11734 ("Egrave")
11735 ("Eacute")
11736 ("Ecirc")
11737 ("Euml")
11738 ("Igrave")
11739 ("Iacute")
11740 ("Icirc")
11741 ("Iuml")
11742 ("ETH")
11743 ("Ntilde")
11744 ("Ograve")
11745 ("Oacute")
11746 ("Ocirc")
11747 ("Otilde")
11748 ("Ouml")
11749 ("times")
11750 ("Oslash")
11751 ("Ugrave")
11752 ("Uacute")
11753 ("Ucirc")
11754 ("Uuml")
11755 ("Yacute")
11756 ("THORN")
11757 ("szlig")
11758 ("agrave")
11759 ("aacute")
11760 ("acirc")
11761 ("atilde")
11762 ("auml")
11763 ("aring")
11764 ("aelig")
11765 ("ccedil")
11766 ("egrave")
11767 ("eacute")
11768 ("ecirc")
11769 ("euml")
11770 ("igrave")
11771 ("iacute")
11772 ("icirc")
11773 ("iuml")
11774 ("eth")
11775 ("ntilde")
11776 ("ograve")
11777 ("oacute")
11778 ("ocirc")
11779 ("otilde")
11780 ("ouml")
11781 ("divide")
11782 ("oslash")
11783 ("ugrave")
11784 ("uacute")
11785 ("ucirc")
11786 ("uuml")
11787 ("yacute")
11788 ("thorn")
11789 ("yuml")
11790 ("fnof")
11791 ("Alpha")
11792 ("Beta")
11793 ("Gamma")
11794 ("Delta")
11795 ("Epsilon")
11796 ("Zeta")
11797 ("Eta")
11798 ("Theta")
11799 ("Iota")
11800 ("Kappa")
11801 ("Lambda")
11802 ("Mu")
11803 ("Nu")
11804 ("Xi")
11805 ("Omicron")
11806 ("Pi")
11807 ("Rho")
11808 ("Sigma")
11809 ("Tau")
11810 ("Upsilon")
11811 ("Phi")
11812 ("Chi")
11813 ("Psi")
11814 ("Omega")
11815 ("alpha")
11816 ("beta")
11817 ("gamma")
11818 ("delta")
11819 ("epsilon")
11820 ("varepsilon"."&epsilon;")
11821 ("zeta")
11822 ("eta")
11823 ("theta")
11824 ("iota")
11825 ("kappa")
11826 ("lambda")
11827 ("mu")
11828 ("nu")
11829 ("xi")
11830 ("omicron")
11831 ("pi")
11832 ("rho")
11833 ("sigmaf") ("varsigma"."&sigmaf;")
11834 ("sigma")
11835 ("tau")
11836 ("upsilon")
11837 ("phi")
11838 ("chi")
11839 ("psi")
11840 ("omega")
11841 ("thetasym") ("vartheta"."&thetasym;")
11842 ("upsih")
11843 ("piv")
11844 ("bull") ("bullet"."&bull;")
11845 ("hellip") ("dots"."&hellip;")
11846 ("prime")
11847 ("Prime")
11848 ("oline")
11849 ("frasl")
11850 ("weierp")
11851 ("image")
11852 ("real")
11853 ("trade")
11854 ("alefsym")
11855 ("larr") ("leftarrow"."&larr;") ("gets"."&larr;")
11856 ("uarr") ("uparrow"."&uarr;")
11857 ("rarr") ("to"."&rarr;") ("rightarrow"."&rarr;")
11858 ("darr")("downarrow"."&darr;")
11859 ("harr") ("leftrightarrow"."&harr;")
11860 ("crarr") ("hookleftarrow"."&crarr;") ; has round hook, not quite CR
11861 ("lArr") ("Leftarrow"."&lArr;")
11862 ("uArr") ("Uparrow"."&uArr;")
11863 ("rArr") ("Rightarrow"."&rArr;")
11864 ("dArr") ("Downarrow"."&dArr;")
11865 ("hArr") ("Leftrightarrow"."&hArr;")
11866 ("forall")
11867 ("part") ("partial"."&part;")
11868 ("exist") ("exists"."&exist;")
11869 ("empty") ("emptyset"."&empty;")
11870 ("nabla")
11871 ("isin") ("in"."&isin;")
11872 ("notin")
11873 ("ni")
11874 ("prod")
11875 ("sum")
11876 ("minus")
11877 ("lowast") ("ast"."&lowast;")
11878 ("radic")
11879 ("prop") ("proptp"."&prop;")
11880 ("infin") ("infty"."&infin;")
11881 ("ang") ("angle"."&ang;")
11882 ("and") ("vee"."&and;")
11883 ("or") ("wedge"."&or;")
11884 ("cap")
11885 ("cup")
11886 ("int")
11887 ("there4")
11888 ("sim")
11889 ("cong") ("simeq"."&cong;")
11890 ("asymp")("approx"."&asymp;")
11891 ("ne") ("neq"."&ne;")
11892 ("equiv")
11893 ("le")
11894 ("ge")
11895 ("sub") ("subset"."&sub;")
11896 ("sup") ("supset"."&sup;")
11897 ("nsub")
11898 ("sube")
11899 ("supe")
11900 ("oplus")
11901 ("otimes")
11902 ("perp")
11903 ("sdot") ("cdot"."&sdot;")
11904 ("lceil")
11905 ("rceil")
11906 ("lfloor")
11907 ("rfloor")
11908 ("lang")
11909 ("rang")
11910 ("loz") ("Diamond"."&loz;")
11911 ("spades") ("spadesuit"."&spades;")
11912 ("clubs") ("clubsuit"."&clubs;")
11913 ("hearts") ("diamondsuit"."&hearts;")
11914 ("diams") ("diamondsuit"."&diams;")
11915 ("quot")
11916 ("amp")
11917 ("lt")
11918 ("gt")
11919 ("OElig")
11920 ("oelig")
11921 ("Scaron")
11922 ("scaron")
11923 ("Yuml")
11924 ("circ")
11925 ("tilde")
11926 ("ensp")
11927 ("emsp")
11928 ("thinsp")
11929 ("zwnj")
11930 ("zwj")
11931 ("lrm")
11932 ("rlm")
11933 ("ndash")
11934 ("mdash")
11935 ("lsquo")
11936 ("rsquo")
11937 ("sbquo")
11938 ("ldquo")
11939 ("rdquo")
11940 ("bdquo")
11941 ("dagger")
11942 ("Dagger")
11943 ("permil")
11944 ("lsaquo")
11945 ("rsaquo")
11946 ("euro")
11948 ("arccos"."arccos")
11949 ("arcsin"."arcsin")
11950 ("arctan"."arctan")
11951 ("arg"."arg")
11952 ("cos"."cos")
11953 ("cosh"."cosh")
11954 ("cot"."cot")
11955 ("coth"."coth")
11956 ("csc"."csc")
11957 ("deg"."deg")
11958 ("det"."det")
11959 ("dim"."dim")
11960 ("exp"."exp")
11961 ("gcd"."gcd")
11962 ("hom"."hom")
11963 ("inf"."inf")
11964 ("ker"."ker")
11965 ("lg"."lg")
11966 ("lim"."lim")
11967 ("liminf"."liminf")
11968 ("limsup"."limsup")
11969 ("ln"."ln")
11970 ("log"."log")
11971 ("max"."max")
11972 ("min"."min")
11973 ("Pr"."Pr")
11974 ("sec"."sec")
11975 ("sin"."sin")
11976 ("sinh"."sinh")
11977 ("sup"."sup")
11978 ("tan"."tan")
11979 ("tanh"."tanh")
11981 "Entities for TeX->HTML translation.
11982 Entries can be like (\"ent\"), in which case \"\\ent\" will be translated to
11983 \"&ent;\". An entry can also be a dotted pair like (\"ent\".\"&other;\").
11984 In that case, \"\\ent\" will be translated to \"&other;\".
11985 The list contains HTML entities for Latin-1, Greek and other symbols.
11986 It is supplemented by a number of commonly used TeX macros with appropriate
11987 translations. There is currently no way for users to extend this.")
11989 (defun org-cleaned-string-for-export (string)
11990 "Cleanup a buffer substring so that links can be created safely."
11991 (interactive)
11992 (let* ((cb (current-buffer))
11993 (re-radio (and org-target-link-regexp
11994 (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)")))
11995 (re-plain-link (concat "\\([^[<]\\)" org-plain-link-re))
11996 (re-angle-link (concat "\\([^[]\\)" org-angle-link-re))
11997 rtn)
11998 (save-excursion
11999 (set-buffer (get-buffer-create " org-mode-tmp"))
12000 (erase-buffer)
12001 (insert string)
12002 (org-mode)
12003 ;; Find targets in comments and move them out of comments,
12004 ;; but mark them as targets that should be invisible
12005 (goto-char (point-min))
12006 (while (re-search-forward "^#.*?\\(<<<?[^>\r\n]+>>>?\\).*" nil t)
12007 (replace-match "\\1(INVISIBLE)"))
12008 ;; Find matches for radio targets and turn them into internal links
12009 (goto-char (point-min))
12010 (when re-radio
12011 (while (re-search-forward re-radio nil t)
12012 (replace-match "\\1[[\\2]]")))
12013 ;; Find all links that contain a newline and put them into a single line
12014 (goto-char (point-min))
12015 (while (re-search-forward "\\(\\(\\[\\|\\]\\)\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\(\\[\\|\\]\\)\\)" nil t)
12016 (replace-match "\\1 \\3")
12017 (goto-char (match-beginning 0)))
12018 ;; Normalize links: Convert angle and plain links into bracket links
12019 (goto-char (point-min))
12020 (while (re-search-forward re-plain-link nil t)
12021 (replace-match
12022 (concat
12023 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
12024 t t))
12025 (goto-char (point-min))
12026 (while (re-search-forward re-angle-link nil t)
12027 (replace-match
12028 (concat
12029 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
12030 t t))
12032 ;; Remove comments
12033 (goto-char (point-min))
12034 (while (re-search-forward "^#.*\n?" nil t)
12035 (replace-match ""))
12036 (setq rtn (buffer-string)))
12037 (kill-buffer " org-mode-tmp")
12038 rtn))
12040 (defun org-solidify-link-text (s &optional alist)
12041 "Take link text and make a safe target out of it."
12042 (save-match-data
12043 (let* ((rtn
12044 (mapconcat
12045 'identity
12046 (org-split-string s "[ \t\r\n]+") "--"))
12047 (a (assoc rtn alist)))
12048 (or (cdr a) rtn))))
12050 (defun org-convert-to-odd-levels ()
12051 "Convert an org-mode file with all levels allowed to one with odd levels.
12052 This will leave level 1 alone, convert level 2 to level 3, level 3 to
12053 level 5 etc."
12054 (interactive)
12055 (when (yes-or-no-p "Are you sure you want to globally change levels to odd? ")
12056 (let ((org-odd-levels-only nil) n)
12057 (save-excursion
12058 (goto-char (point-min))
12059 (while (re-search-forward "^\\*\\*+" nil t)
12060 (setq n (1- (length (match-string 0))))
12061 (while (>= (setq n (1- n)) 0)
12062 (org-demote))
12063 (end-of-line 1))))))
12066 (defun org-convert-to-oddeven-levels ()
12067 "Convert an org-mode file with only odd levels to one with odd and even levels.
12068 This promotes level 3 to level 2, level 5 to level 3 etc. If the file contains a
12069 section with an even level, conversion would destroy the structure of the file. An error
12070 is signaled in this case."
12071 (interactive)
12072 (goto-char (point-min))
12073 ;; First check if there are no even levels
12074 (when (re-search-forward "^\\(\\*\\*\\)+[^*]" nil t)
12075 (org-show-hierarchy-above)
12076 (error "Not all levels are odd in this file. Conversion not possible."))
12077 (when (yes-or-no-p "Are you sure you want to globally change levels to odd-even? ")
12078 (let ((org-odd-levels-only nil) n)
12079 (save-excursion
12080 (goto-char (point-min))
12081 (while (re-search-forward "^\\*\\*+" nil t)
12082 (setq n (/ (length (match-string 0)) 2))
12083 (while (>= (setq n (1- n)) 0)
12084 (org-promote))
12085 (end-of-line 1))))))
12087 (defun org-tr-level (n)
12088 "Make N odd if required."
12089 (if org-odd-levels-only (1+ (/ n 2)) n))
12091 (defvar org-last-level nil) ; dynamically scoped variable
12093 (defun org-export-as-ascii (arg)
12094 "Export the outline as a pretty ASCII file.
12095 If there is an active region, export only the region.
12096 The prefix ARG specifies how many levels of the outline should become
12097 underlined headlines. The default is 3."
12098 (interactive "P")
12099 (setq-default org-todo-line-regexp org-todo-line-regexp)
12100 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
12101 (org-infile-export-plist)))
12102 (region
12103 (buffer-substring
12104 (if (org-region-active-p) (region-beginning) (point-min))
12105 (if (org-region-active-p) (region-end) (point-max))))
12106 (lines (org-export-find-first-heading-line
12107 (org-skip-comments
12108 (org-split-string
12109 (org-cleaned-string-for-export region)
12110 "[\r\n]"))))
12111 (org-startup-with-deadline-check nil)
12112 (level 0) line txt
12113 (umax nil)
12114 (case-fold-search nil)
12115 (filename (concat (file-name-as-directory
12116 (org-export-directory :ascii opt-plist))
12117 (file-name-sans-extension
12118 (file-name-nondirectory buffer-file-name))
12119 ".txt"))
12120 (buffer (find-file-noselect filename))
12121 (levels-open (make-vector org-level-max nil))
12122 (odd org-odd-levels-only)
12123 (date (format-time-string "%Y/%m/%d" (current-time)))
12124 (time (format-time-string "%X" (org-current-time)))
12125 (author (plist-get opt-plist :author))
12126 (title (or (plist-get opt-plist :title)
12127 (file-name-sans-extension
12128 (file-name-nondirectory buffer-file-name))))
12129 (options nil)
12130 (email (plist-get opt-plist :email))
12131 (language (plist-get opt-plist :language))
12132 (text nil)
12133 (todo nil)
12134 (lang-words nil))
12136 (setq org-last-level 1)
12137 (org-init-section-numbers)
12139 (find-file-noselect filename)
12141 (setq lang-words (or (assoc language org-export-language-setup)
12142 (assoc "en" org-export-language-setup)))
12143 (if org-export-ascii-show-new-buffer
12144 (switch-to-buffer-other-window buffer)
12145 (set-buffer buffer))
12146 (erase-buffer)
12147 (fundamental-mode)
12148 ;; create local variables for all options, to make sure all called
12149 ;; functions get the correct information
12150 (mapcar (lambda (x)
12151 (set (make-local-variable (cdr x))
12152 (plist-get opt-plist (car x))))
12153 org-export-plist-vars)
12154 (set (make-local-variable 'org-odd-levels-only) odd)
12155 (setq umax (if arg (prefix-numeric-value arg)
12156 org-export-headline-levels))
12158 ;; File header
12159 (if title (org-insert-centered title ?=))
12160 (insert "\n")
12161 (if (or author email)
12162 (insert (concat (nth 1 lang-words) ": " (or author "")
12163 (if email (concat " <" email ">") "")
12164 "\n")))
12165 (if (and date time)
12166 (insert (concat (nth 2 lang-words) ": " date " " time "\n")))
12167 (if text (insert (concat (org-html-expand-for-ascii text) "\n\n")))
12169 (insert "\n\n")
12171 (if org-export-with-toc
12172 (progn
12173 (insert (nth 3 lang-words) "\n"
12174 (make-string (length (nth 3 lang-words)) ?=) "\n")
12175 (mapcar '(lambda (line)
12176 (if (string-match org-todo-line-regexp
12177 line)
12178 ;; This is a headline
12179 (progn
12180 (setq level (- (match-end 1) (match-beginning 1))
12181 level (org-tr-level level)
12182 txt (match-string 3 line)
12183 todo
12184 (or (and org-export-mark-todo-in-toc
12185 (match-beginning 2)
12186 (not (equal (match-string 2 line)
12187 org-done-string)))
12188 ; TODO, not DONE
12189 (and org-export-mark-todo-in-toc
12190 (= level umax)
12191 (org-search-todo-below
12192 line lines level))))
12193 (setq txt (org-html-expand-for-ascii txt))
12195 (if org-export-with-section-numbers
12196 (setq txt (concat (org-section-number level)
12197 " " txt)))
12198 (if (<= level umax)
12199 (progn
12200 (insert
12201 (make-string (* (1- level) 4) ?\ )
12202 (format (if todo "%s (*)\n" "%s\n") txt))
12203 (setq org-last-level level))
12204 ))))
12205 lines)))
12207 (org-init-section-numbers)
12208 (while (setq line (pop lines))
12209 ;; Remove the quoted HTML tags.
12210 (setq line (org-html-expand-for-ascii line))
12211 ;; Remove targets
12212 (while (string-match "<<<?[^<>]*>>>?[ \t]*\n?" line)
12213 (setq line (replace-match "" t t line)))
12214 ;; Replace internal links
12215 (while (string-match org-bracket-link-regexp line)
12216 (setq line (replace-match
12217 (if (match-end 3) "[\\3]" "[\\1]")
12218 t nil line)))
12219 (cond
12220 ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line)
12221 ;; a Headline
12222 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
12223 txt (match-string 2 line))
12224 (org-ascii-level-start level txt umax))
12225 (t (insert line "\n"))))
12226 (normal-mode)
12227 (save-buffer)
12228 ;; remove display and invisible chars
12229 (let (beg end s)
12230 (goto-char (point-min))
12231 (while (setq beg (next-single-property-change (point) 'display))
12232 (setq end (next-single-property-change beg 'display))
12233 (delete-region beg end)
12234 (goto-char beg)
12235 (insert "=>"))
12236 (goto-char (point-min))
12237 (while (setq beg (next-single-property-change (point) 'org-cwidth))
12238 (setq end (next-single-property-change beg 'org-cwidth))
12239 (delete-region beg end)
12240 (goto-char beg)))
12241 (goto-char (point-min))))
12243 (defun org-search-todo-below (line lines level)
12244 "Search the subtree below LINE for any TODO entries."
12245 (let ((rest (cdr (memq line lines)))
12246 (re org-todo-line-regexp)
12247 line lv todo)
12248 (catch 'exit
12249 (while (setq line (pop rest))
12250 (if (string-match re line)
12251 (progn
12252 (setq lv (- (match-end 1) (match-beginning 1))
12253 todo (and (match-beginning 2)
12254 (not (equal (match-string 2 line)
12255 org-done-string))))
12256 ; TODO, not DONE
12257 (if (<= lv level) (throw 'exit nil))
12258 (if todo (throw 'exit t))))))))
12260 ;; FIXME: Try to handle <b> and <i> as faces via text properties.
12261 ;; We could also implement *bold*,/italic/ and _underline_ for ASCII export
12262 (defun org-html-expand-for-ascii (line)
12263 "Handle quoted HTML for ASCII export."
12264 (if org-export-html-expand
12265 (while (string-match "@<[^<>\n]*>" line)
12266 ;; We just remove the tags for now.
12267 (setq line (replace-match "" nil nil line))))
12268 line)
12270 (defun org-insert-centered (s &optional underline)
12271 "Insert the string S centered and underline it with character UNDERLINE."
12272 (let ((ind (max (/ (- 80 (string-width s)) 2) 0)))
12273 (insert (make-string ind ?\ ) s "\n")
12274 (if underline
12275 (insert (make-string ind ?\ )
12276 (make-string (string-width s) underline)
12277 "\n"))))
12279 (defun org-ascii-level-start (level title umax)
12280 "Insert a new level in ASCII export."
12281 (let (char)
12282 (if (> level umax)
12283 (insert (make-string (* 2 (- level umax 1)) ?\ ) "* " title "\n")
12284 (if (or (not (equal (char-before) ?\n))
12285 (not (equal (char-before (1- (point))) ?\n)))
12286 (insert "\n"))
12287 (setq char (nth (- umax level) (reverse org-ascii-underline)))
12288 (if org-export-with-section-numbers
12289 (setq title (concat (org-section-number level) " " title)))
12290 (insert title "\n" (make-string (string-width title) char) "\n"))))
12292 (defun org-export-visible (type arg)
12293 "Create a copy of the visible part of the current buffer, and export it.
12294 The copy is created in a temporary buffer and removed after use.
12295 TYPE is the final key (as a string) of the `C-c C-x' key sequence that will
12296 run the export command - in interactive use, the command prompts for this
12297 key. As a special case, if the you type SPC at the prompt, the temporary
12298 org-mode file will not be removed but presented to you so that you can
12299 continue to use it. The prefix arg ARG is passed through to the exporting
12300 command."
12301 (interactive
12302 (list (progn
12303 (message "Export visible: [a]SCII [h]tml [b]rowse HTML [x]OXO [ ]keep buffer")
12304 (char-to-string (read-char-exclusive)))
12305 current-prefix-arg))
12306 (if (not (member type '("a" "\C-a" "b" "\C-b" "h" "x" " ")))
12307 (error "Invalid export key"))
12308 (let* ((binding (key-binding (concat "\C-c\C-x" type)))
12309 (keepp (equal type " "))
12310 (file buffer-file-name)
12311 (buffer (get-buffer-create "*Org Export Visible*"))
12312 s e)
12313 (with-current-buffer buffer (erase-buffer))
12314 (save-excursion
12315 (setq s (goto-char (point-min)))
12316 (while (not (= (point) (point-max)))
12317 (goto-char (org-find-invisible))
12318 (append-to-buffer buffer s (point))
12319 (setq s (goto-char (org-find-visible))))
12320 (goto-char (point-min))
12321 (unless keepp
12322 ;; Copy all comment lines to the end, to make sure #+ settings are
12323 ;; still available for the second export step. Kind of a hack, but
12324 ;; does do the trick.
12325 (if (looking-at "#[^\r\n]*")
12326 (append-to-buffer buffer (match-beginning 0) (1+ (match-end 0))))
12327 (while (re-search-forward "[\n\r]#[^\n\r]*" nil t)
12328 (append-to-buffer buffer (1+ (match-beginning 0))
12329 (min (point-max) (1+ (match-end 0))))))
12330 (set-buffer buffer)
12331 (let ((buffer-file-name file)
12332 (org-inhibit-startup t))
12333 (org-mode)
12334 (show-all)
12335 (unless keepp (funcall binding arg))))
12336 (if (not keepp)
12337 (kill-buffer buffer)
12338 (switch-to-buffer-other-window buffer)
12339 (goto-char (point-min)))))
12341 (defun org-find-visible ()
12342 (if (featurep 'noutline)
12343 (let ((s (point)))
12344 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
12345 (get-char-property s 'invisible)))
12347 (skip-chars-forward "^\n")
12348 (point)))
12349 (defun org-find-invisible ()
12350 (if (featurep 'noutline)
12351 (let ((s (point)))
12352 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
12353 (not (get-char-property s 'invisible))))
12355 (skip-chars-forward "^\r")
12356 (point)))
12358 ;; HTML
12360 (defun org-get-current-options ()
12361 "Return a string with current options as keyword options.
12362 Does include HTML export options as well as TODO and CATEGORY stuff."
12363 (format
12364 "#+TITLE: %s
12365 #+AUTHOR: %s
12366 #+EMAIL: %s
12367 #+LANGUAGE: %s
12368 #+TEXT: Some descriptive text to be emitted. Several lines OK.
12369 #+OPTIONS: H:%d num:%s toc:%s \\n:%s @:%s ::%s |:%s ^:%s *:%s TeX:%s
12370 #+CATEGORY: %s
12371 #+SEQ_TODO: %s
12372 #+TYP_TODO: %s
12373 #+STARTUP: %s %s %s %s %s %s
12374 #+TAGS: %s
12375 #+ARCHIVE: %s
12377 (buffer-name) (user-full-name) user-mail-address org-export-default-language
12378 org-export-headline-levels
12379 org-export-with-section-numbers
12380 org-export-with-toc
12381 org-export-preserve-breaks
12382 org-export-html-expand
12383 org-export-with-fixed-width
12384 org-export-with-tables
12385 org-export-with-sub-superscripts
12386 org-export-with-emphasize
12387 org-export-with-TeX-macros
12388 (file-name-nondirectory buffer-file-name)
12389 (if (equal org-todo-interpretation 'sequence)
12390 (mapconcat 'identity org-todo-keywords " ")
12391 "TODO FEEDBACK VERIFY DONE")
12392 (if (equal org-todo-interpretation 'type)
12393 (mapconcat 'identity org-todo-keywords " ")
12394 "Me Jason Marie DONE")
12395 (cdr (assoc org-startup-folded
12396 '((nil . "showall") (t . "overview") (content . "content"))))
12397 (if org-startup-with-deadline-check "dlcheck" "nodlcheck")
12398 (if org-odd-levels-only "odd" "oddeven")
12399 (if org-hide-leading-stars "hidestars" "showstars")
12400 (if org-startup-align-all-tables "align" "noalign")
12401 (if org-log-done "logging" "nologging")
12402 (if org-tag-alist (mapconcat 'car org-tag-alist " ") "")
12403 org-archive-location
12406 (defun org-insert-export-options-template ()
12407 "Insert into the buffer a template with information for exporting."
12408 (interactive)
12409 (if (not (bolp)) (newline))
12410 (let ((s (org-get-current-options)))
12411 (and (string-match "#\\+CATEGORY" s)
12412 (setq s (substring s 0 (match-beginning 0))))
12413 (insert s)))
12415 (defun org-toggle-fixed-width-section (arg)
12416 "Toggle the fixed-width export.
12417 If there is no active region, the QUOTE keyword at the current headline is
12418 inserted or removed. When present, it causes the text between this headline
12419 and the next to be exported as fixed-width text, and unmodified.
12420 If there is an active region, this command adds or removes a colon as the
12421 first character of this line. If the first character of a line is a colon,
12422 this line is also exported in fixed-width font."
12423 (interactive "P")
12424 (let* ((cc 0)
12425 (regionp (org-region-active-p))
12426 (beg (if regionp (region-beginning) (point)))
12427 (end (if regionp (region-end)))
12428 (nlines (or arg (if (and beg end) (count-lines beg end) 1)))
12429 (re "[ \t]*\\(:\\)")
12430 off)
12431 (if regionp
12432 (save-excursion
12433 (goto-char beg)
12434 (setq cc (current-column))
12435 (beginning-of-line 1)
12436 (setq off (looking-at re))
12437 (while (> nlines 0)
12438 (setq nlines (1- nlines))
12439 (beginning-of-line 1)
12440 (cond
12441 (arg
12442 (move-to-column cc t)
12443 (insert ":\n")
12444 (forward-line -1))
12445 ((and off (looking-at re))
12446 (replace-match "" t t nil 1))
12447 ((not off) (move-to-column cc t) (insert ":")))
12448 (forward-line 1)))
12449 (save-excursion
12450 (org-back-to-heading)
12451 (if (looking-at (concat outline-regexp
12452 "\\( +\\<" org-quote-string "\\>\\)"))
12453 (replace-match "" t t nil 1)
12454 (if (looking-at outline-regexp)
12455 (progn
12456 (goto-char (match-end 0))
12457 (insert " " org-quote-string))))))))
12459 (defun org-export-as-html-and-open (arg)
12460 "Export the outline as HTML and immediately open it with a browser.
12461 If there is an active region, export only the region.
12462 The prefix ARG specifies how many levels of the outline should become
12463 headlines. The default is 3. Lower levels will become bulleted lists."
12464 (interactive "P")
12465 (org-export-as-html arg 'hidden)
12466 (org-open-file buffer-file-name))
12468 (defun org-export-as-html-batch ()
12469 "Call `org-export-as-html', may be used in batch processing as
12470 emacs --batch
12471 --load=$HOME/lib/emacs/org.el
12472 --eval \"(setq org-export-headline-levels 2)\"
12473 --visit=MyFile --funcall org-export-as-html-batch"
12474 (org-export-as-html org-export-headline-levels 'hidden))
12476 (defun org-export-as-html (arg &optional hidden ext-plist)
12477 "Export the outline as a pretty HTML file.
12478 If there is an active region, export only the region.
12479 The prefix ARG specifies how many levels of the outline should become
12480 headlines. The default is 3. Lower levels will become bulleted lists.
12481 When HIDDEN is non-nil, don't display the HTML buffer.
12482 EXT-PLIST is a property list with external parameters overriding
12483 org-mode's default settings, but still inferior to file-local settings."
12484 (interactive "P")
12485 (setq-default org-todo-line-regexp org-todo-line-regexp)
12486 (setq-default org-deadline-line-regexp org-deadline-line-regexp)
12487 (setq-default org-done-string org-done-string)
12488 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
12489 ext-plist
12490 (org-infile-export-plist)))
12492 (style (plist-get opt-plist :style))
12493 (odd org-odd-levels-only)
12494 (region-p (org-region-active-p))
12495 (region
12496 (buffer-substring
12497 (if region-p (region-beginning) (point-min))
12498 (if region-p (region-end) (point-max))))
12499 (all_lines
12500 (org-skip-comments (org-split-string
12501 (org-cleaned-string-for-export region)
12502 "[\r\n]")))
12503 (lines (org-export-find-first-heading-line all_lines))
12504 (level 0) (line "") (origline "") txt todo
12505 (umax nil)
12506 (filename (concat (file-name-as-directory
12507 (org-export-directory :html opt-plist))
12508 (file-name-sans-extension
12509 (file-name-nondirectory buffer-file-name))
12510 ".html"))
12511 (buffer (find-file-noselect filename))
12512 (levels-open (make-vector org-level-max nil))
12513 (date (format-time-string "%Y/%m/%d" (current-time)))
12514 (time (format-time-string "%X" (org-current-time)))
12515 (author (plist-get opt-plist :author))
12516 (title (or (plist-get opt-plist :title)
12517 (file-name-sans-extension
12518 (file-name-nondirectory buffer-file-name))))
12519 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
12520 (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
12521 (inquote nil)
12522 (infixed nil)
12523 (in-local-list nil)
12524 (local-list-num nil)
12525 (local-list-indent nil)
12526 (llt org-plain-list-ordered-item-terminator)
12527 (email (plist-get opt-plist :email))
12528 (language (plist-get opt-plist :language))
12529 (text (plist-get opt-plist :text))
12530 (lang-words nil)
12531 (target-alist nil) tg
12532 (head-count 0) cnt
12533 (start 0)
12534 ;; FIXME: The following returns always nil under XEmacs
12535 (coding-system (and (fboundp 'coding-system-get)
12536 (boundp 'buffer-file-coding-system)
12537 buffer-file-coding-system))
12538 (coding-system-for-write (or coding-system coding-system-for-write))
12539 (save-buffer-coding-system (or coding-system save-buffer-coding-system))
12540 (charset (and coding-system
12541 (coding-system-get coding-system 'mime-charset)))
12542 table-open type
12543 table-buffer table-orig-buffer
12544 ind start-is-num starter
12545 rpl path desc descp desc1 desc2 link
12547 (message "Exporting...")
12549 (setq org-last-level 1)
12550 (org-init-section-numbers)
12552 ;; Get the language-dependent settings
12553 (setq lang-words (or (assoc language org-export-language-setup)
12554 (assoc "en" org-export-language-setup)))
12556 ;; Switch to the output buffer
12557 (if (or hidden (not org-export-html-show-new-buffer))
12558 (set-buffer buffer)
12559 (switch-to-buffer-other-window buffer))
12560 (erase-buffer)
12561 (fundamental-mode)
12562 (let ((case-fold-search nil)
12563 (org-odd-levels-only odd))
12564 ;; create local variables for all options, to make sure all called
12565 ;; functions get the correct information
12566 (mapcar (lambda (x)
12567 (set (make-local-variable (cdr x))
12568 (plist-get opt-plist (car x))))
12569 org-export-plist-vars)
12570 (setq umax (if arg (prefix-numeric-value arg)
12571 org-export-headline-levels))
12573 ;; File header
12574 (insert (format
12575 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"
12576 \"http://www.w3.org/TR/REC-html40/loose.dtd\">
12577 <html lang=\"%s\"><head>
12578 <title>%s</title>
12579 <meta http-equiv=\"Content-Type\" content=\"text/html;charset=%s\">
12580 <meta name=generator content=\"Org-mode\">
12581 <meta name=generated content=\"%s %s\">
12582 <meta name=author content=\"%s\">
12584 </head><body>
12586 language (org-html-expand title) (or charset "iso-8859-1")
12587 date time author style))
12590 (insert (or (plist-get opt-plist :preamble) ""))
12592 (when (plist-get opt-plist :auto-preamble)
12593 (if title (insert (concat "<H1 class=\"title\">"
12594 (org-html-expand title) "</H1>\n")))
12595 ; (if author (insert (concat (nth 1 lang-words) ": " author "\n")))
12596 ; (if email (insert (concat "<a href=\"mailto:" email "\">&lt;"
12597 ; email "&gt;</a>\n")))
12598 ; (if (or author email) (insert "<br>\n"))
12599 ; (if (and date time) (insert (concat (nth 2 lang-words) ": "
12600 ; date " " time "<br>\n")))
12601 (if text (insert (concat "<p>\n" (org-html-expand text)))))
12603 (if org-export-with-toc
12604 (progn
12605 (insert (format "<H2>%s</H2>\n" (nth 3 lang-words)))
12606 (insert "<ul>\n")
12607 (setq lines
12608 (mapcar '(lambda (line)
12609 (if (string-match org-todo-line-regexp line)
12610 ;; This is a headline
12611 (progn
12612 (setq level (- (match-end 1) (match-beginning 1))
12613 level (org-tr-level level)
12614 txt (save-match-data
12615 (org-html-expand
12616 (org-html-cleanup-toc-line
12617 (match-string 3 line))))
12618 todo
12619 (or (and org-export-mark-todo-in-toc
12620 (match-beginning 2)
12621 (not (equal (match-string 2 line)
12622 org-done-string)))
12623 ; TODO, not DONE
12624 (and org-export-mark-todo-in-toc
12625 (= level umax)
12626 (org-search-todo-below
12627 line lines level))))
12628 (if org-export-with-section-numbers
12629 (setq txt (concat (org-section-number level)
12630 " " txt)))
12631 (if (<= level umax)
12632 (progn
12633 (setq head-count (+ head-count 1))
12634 (if (> level org-last-level)
12635 (progn
12636 (setq cnt (- level org-last-level))
12637 (while (>= (setq cnt (1- cnt)) 0)
12638 (insert "<ul>"))
12639 (insert "\n")))
12640 (if (< level org-last-level)
12641 (progn
12642 (setq cnt (- org-last-level level))
12643 (while (>= (setq cnt (1- cnt)) 0)
12644 (insert "</ul>"))
12645 (insert "\n")))
12646 ;; Check for targets
12647 (while (string-match org-target-regexp line)
12648 (setq tg (match-string 1 line)
12649 line (replace-match
12650 (concat "@<span class=\"target\">" tg "@</span> ")
12651 t t line))
12652 (push (cons (org-solidify-link-text tg)
12653 (format "sec-%d" head-count))
12654 target-alist))
12655 (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
12656 (setq txt (replace-match "" t t txt)))
12657 (insert
12658 (format
12659 (if todo
12660 "<li><a href=\"#sec-%d\"><span class=\"todo\">%s</span></a>\n"
12661 "<li><a href=\"#sec-%d\">%s</a>\n")
12662 head-count txt))
12664 (setq org-last-level level))
12666 line)
12667 lines))
12668 (while (> org-last-level 0)
12669 (setq org-last-level (1- org-last-level))
12670 (insert "</ul>\n"))
12672 (setq head-count 0)
12673 (org-init-section-numbers)
12675 (while (setq line (pop lines) origline line)
12676 (catch 'nextline
12678 ;; end of quote section?
12679 (when (and inquote (string-match "^\\*+" line))
12680 (insert "</pre>\n")
12681 (setq inquote nil))
12682 ;; inside a quote section?
12683 (when inquote
12684 (insert (org-html-protect line) "\n")
12685 (throw 'nextline nil))
12687 ;; verbatim lines
12688 (when (and org-export-with-fixed-width
12689 (string-match "^[ \t]*:\\(.*\\)" line))
12690 (when (not infixed)
12691 (setq infixed t)
12692 (insert "<pre>\n"))
12693 (insert (org-html-protect (match-string 1 line)) "\n")
12694 (when (and lines
12695 (not (string-match "^[ \t]*\\(:.*\\)"
12696 (car lines))))
12697 (setq infixed nil)
12698 (insert "</pre>\n"))
12699 (throw 'nextline nil))
12702 ;; make targets to anchors
12703 (while (string-match "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line)
12704 (cond
12705 ((match-end 2)
12706 (setq line (replace-match
12707 (concat "@<a name=\""
12708 (org-solidify-link-text (match-string 1 line))
12709 "\">\\nbsp@</a>")
12710 t t line)))
12711 ((and org-export-with-toc (equal (string-to-char line) ?*))
12712 (setq line (replace-match
12713 (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
12714 ; (concat "@<i>" (match-string 1 line) "@</i> ")
12715 t t line)))
12717 (setq line (replace-match
12718 (concat "@<a name=\""
12719 (org-solidify-link-text (match-string 1 line))
12720 "\" class=\"target\">" (match-string 1 line) "@</a> ")
12721 t t line)))))
12723 (setq line (org-html-handle-time-stamps line))
12725 ;; replace "&" by "&amp;", "<" and ">" by "&lt;" and "&gt;"
12726 ;; handle @<..> HTML tags (replace "@&gt;..&lt;" by "<..>")
12727 ;; Also handle sub_superscripts and checkboxes
12728 ;; FIXME: is there no better place for checkboxes
12729 (setq line (org-html-expand line))
12731 ;; Format the links
12732 (setq start 0)
12733 (while (string-match org-bracket-link-analytic-regexp line start)
12734 (setq start (match-beginning 0))
12735 (setq type (if (match-end 2) (match-string 2 line) "internal"))
12736 (setq path (match-string 3 line))
12737 (setq desc1 (if (match-end 5) (match-string 5 line))
12738 desc2 (if (match-end 2) (concat type ":" path) path)
12739 descp (and desc1 (not (equal desc1 desc2)))
12740 desc (or desc1 desc2))
12741 ;; FIXME: do we need to unescape here somewhere?
12742 (cond
12743 ((equal type "internal")
12744 (setq rpl
12745 (concat
12746 "<a href=\"#"
12747 (org-solidify-link-text path target-alist)
12748 "\">" desc "</a>")))
12749 ((member type '("http" "https" "ftp" "mailto" "news"))
12750 ;; standard URL
12751 (setq link (concat type ":" path))
12752 (setq rpl (concat "<a href=\"" link "\">" desc "</a>")))
12753 ((string= type "file")
12754 ;; FILE link
12755 (let* ((filename path)
12756 (abs-p (file-name-absolute-p filename))
12757 thefile file-is-image-p search)
12758 (save-match-data
12759 (if (string-match "::\\(.*\\)" filename)
12760 (setq search (match-string 1 filename)
12761 filename (replace-match "" nil nil filename)))
12762 (setq file-is-image-p
12763 (string-match (org-image-file-name-regexp) filename))
12764 (setq thefile (if abs-p (expand-file-name filename) filename))
12765 (when (and org-export-html-link-org-files-as-html
12766 (string-match "\\.org$" thefile))
12767 (setq thefile (concat (substring thefile 0
12768 (match-beginning 0))
12769 ".html"))
12770 (if (and search
12771 ;; make sure this is can be used as target search
12772 (not (string-match "^[0-9]*$" search))
12773 (not (string-match "^\\*" search))
12774 (not (string-match "^/.*/$" search)))
12775 (setq thefile (concat thefile "#"
12776 (org-solidify-link-text
12777 (org-link-unescape search)))))
12778 (when (string-match "^file:" desc)
12779 (setq desc (replace-match "" t t desc))
12780 (if (string-match "\\.org$" desc)
12781 (setq desc (replace-match "" t t desc))))))
12782 (setq rpl (if (and file-is-image-p
12783 (or (eq t org-export-html-inline-images)
12784 (and org-export-html-inline-images
12785 (not descp))))
12786 (concat "<img src=\"" thefile "\"/>")
12787 (concat "<a href=\"" thefile "\">" desc "</a>")))))
12788 ((member type '("bbdb" "vm" "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
12789 (setq rpl (concat "<i>&lt;" type ":"
12790 (save-match-data (org-link-unescape path))
12791 "&gt;</i>"))))
12792 (setq line (replace-match rpl t t line)
12793 start (+ start (length rpl))))
12794 ;; TODO items
12795 (if (and (string-match org-todo-line-regexp line)
12796 (match-beginning 2))
12797 (if (equal (match-string 2 line) org-done-string)
12798 (setq line (replace-match
12799 "<span class=\"done\">\\2</span>"
12800 nil nil line 2))
12801 (setq line (replace-match "<span class=\"todo\">\\2</span>"
12802 nil nil line 2))))
12804 (cond
12805 ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line)
12806 ;; This is a headline
12807 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
12808 txt (match-string 2 line))
12809 (if (string-match quote-re0 txt)
12810 (setq txt (replace-match "" t t txt)))
12811 (if (<= level umax) (setq head-count (+ head-count 1)))
12812 (when in-local-list
12813 ;; Close any local lists before inserting a new header line
12814 (while local-list-num
12815 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
12816 (pop local-list-num))
12817 (setq local-list-indent nil
12818 in-local-list nil))
12819 (org-html-level-start level txt umax
12820 (and org-export-with-toc (<= level umax))
12821 head-count)
12822 ;; QUOTES
12823 (when (string-match quote-re line)
12824 (insert "<pre>")
12825 (setq inquote t)))
12827 ((and org-export-with-tables
12828 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
12829 (if (not table-open)
12830 ;; New table starts
12831 (setq table-open t table-buffer nil table-orig-buffer nil))
12832 ;; Accumulate lines
12833 (setq table-buffer (cons line table-buffer)
12834 table-orig-buffer (cons origline table-orig-buffer))
12835 (when (or (not lines)
12836 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
12837 (car lines))))
12838 (setq table-open nil
12839 table-buffer (nreverse table-buffer)
12840 table-orig-buffer (nreverse table-orig-buffer))
12841 (insert (org-format-table-html table-buffer table-orig-buffer))))
12843 ;; Normal lines
12844 (when (string-match
12845 (cond
12846 ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*]\\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
12847 ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*]\\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
12848 ((= llt ?\)) "^\\( \t]*\\)\\(\\([-+*]\\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
12849 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
12850 line)
12851 (setq ind (org-get-string-indentation line)
12852 start-is-num (match-beginning 4)
12853 starter (if (match-beginning 2)
12854 (substring (match-string 2 line) 0 -1))
12855 line (substring line (match-beginning 5)))
12856 (unless (string-match "[^ \t]" line)
12857 ;; empty line. Pretend indentation is large.
12858 (setq ind (1+ (or (car local-list-indent) 1))))
12859 (while (and in-local-list
12860 (or (and (= ind (car local-list-indent))
12861 (not starter))
12862 (< ind (car local-list-indent))))
12863 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
12864 (pop local-list-num) (pop local-list-indent)
12865 (setq in-local-list local-list-indent))
12866 (cond
12867 ((and starter
12868 (or (not in-local-list)
12869 (> ind (car local-list-indent))))
12870 ;; Start new (level of ) list
12871 (insert (if start-is-num "<ol>\n<li>\n" "<ul>\n<li>\n"))
12872 (push start-is-num local-list-num)
12873 (push ind local-list-indent)
12874 (setq in-local-list t))
12875 (starter
12876 ;; continue current list
12877 (insert "<li>\n")))
12878 (if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
12879 (setq line
12880 (replace-match
12881 (if (equal (match-string 1 line) "X")
12882 "<b>[X]</b>"
12883 "<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
12884 t t line))))
12886 ;; Empty lines start a new paragraph. If hand-formatted lists
12887 ;; are not fully interpreted, lines starting with "-", "+", "*"
12888 ;; also start a new paragraph.
12889 (if (string-match "^ [-+*]-\\|^[ \t]*$" line) (insert "<p>"))
12890 (insert line (if org-export-preserve-breaks "<br>\n" "\n"))))
12893 ;; Properly close all local lists and other lists
12894 (when inquote (insert "</pre>\n"))
12895 (when in-local-list
12896 ;; Close any local lists before inserting a new header line
12897 (while local-list-num
12898 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
12899 (pop local-list-num))
12900 (setq local-list-indent nil
12901 in-local-list nil))
12902 (org-html-level-start 1 nil umax
12903 (and org-export-with-toc (<= level umax))
12904 head-count)
12906 (when (plist-get opt-plist :auto-postamble)
12907 (insert "<p>")
12908 (if author (insert (concat (nth 1 lang-words) ": " author "\n")))
12909 (if email (insert (concat "<a href=\"mailto:" email "\">&lt;"
12910 email "&gt;</a>\n")))
12911 (if (or author email) (insert "<br>\n"))
12912 (if (and date time) (insert (concat (nth 2 lang-words) ": "
12913 date " " time "<br>\n"))))
12915 (if org-export-html-with-timestamp
12916 (insert org-export-html-html-helper-timestamp))
12917 (insert (or (plist-get opt-plist :postamble) ""))
12918 (insert "</body>\n</html>\n")
12919 (normal-mode)
12920 (save-buffer)
12921 (goto-char (point-min)))))
12923 (defun org-format-table-html (lines olines)
12924 "Find out which HTML converter to use and return the HTML code."
12925 (if (string-match "^[ \t]*|" (car lines))
12926 ;; A normal org table
12927 (org-format-org-table-html lines)
12928 ;; Table made by table.el - test for spanning
12929 (let* ((hlines (delq nil (mapcar
12930 (lambda (x)
12931 (if (string-match "^[ \t]*\\+-" x) x
12932 nil))
12933 lines)))
12934 (first (car hlines))
12935 (ll (and (string-match "\\S-+" first)
12936 (match-string 0 first)))
12937 (re (concat "^[ \t]*" (regexp-quote ll)))
12938 (spanning (delq nil (mapcar (lambda (x) (not (string-match re x)))
12939 hlines))))
12940 (if (and (not spanning)
12941 (not org-export-prefer-native-exporter-for-tables))
12942 ;; We can use my own converter with HTML conversions
12943 (org-format-table-table-html lines)
12944 ;; Need to use the code generator in table.el, with the original text.
12945 (org-format-table-table-html-using-table-generate-source olines)))))
12947 (defun org-format-org-table-html (lines)
12948 "Format a table into HTML."
12949 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
12950 (setq lines (nreverse lines))
12951 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
12952 (setq lines (nreverse lines))
12953 (when org-export-table-remove-special-lines
12954 ;; Check if the table has a marking column. If yes remove the
12955 ;; column and the special lines
12956 (let* ((special
12957 (not
12958 (memq nil
12959 (mapcar
12960 (lambda (x)
12961 (or (string-match "^[ \t]*|-" x)
12962 (string-match "^[ \t]*| *\\([#!$*_^ ]\\) *|" x)))
12963 lines)))))
12964 (if special
12965 (setq lines
12966 (delq nil
12967 (mapcar
12968 (lambda (x)
12969 (if (string-match "^[ \t]*| *[!_^] *|" x)
12970 nil ; ignore this line
12971 (and (or (string-match "^[ \t]*|-+\\+" x)
12972 (string-match "^[ \t]*|[^|]*|" x))
12973 (replace-match "|" t t x))))
12974 lines))))))
12976 (let ((head (and org-export-highlight-first-table-line
12977 (delq nil (mapcar
12978 (lambda (x) (string-match "^[ \t]*|-" x))
12979 (cdr lines)))))
12980 line fields html)
12981 (setq html (concat org-export-html-table-tag "\n"))
12982 (while (setq line (pop lines))
12983 (catch 'next-line
12984 (if (string-match "^[ \t]*|-" line)
12985 (progn
12986 (setq head nil) ;; head ends here, first time around
12987 ;; ignore this line
12988 (throw 'next-line t)))
12989 ;; Break the line into fields
12990 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
12991 (setq html (concat
12992 html
12993 "<tr>"
12994 (mapconcat (lambda (x)
12995 (if head
12996 (concat "<th>" x "</th>")
12997 (concat "<td>" x "</td>")))
12998 fields "")
12999 "</tr>\n"))))
13000 (setq html (concat html "</table>\n"))
13001 html))
13003 (defun org-fake-empty-table-line (line)
13004 "Replace everything except \"|\" with spaces."
13005 (let ((i (length line))
13006 (newstr (copy-sequence line)))
13007 (while (> i 0)
13008 (setq i (1- i))
13009 (if (not (eq (aref newstr i) ?|))
13010 (aset newstr i ?\ )))
13011 newstr))
13013 (defun org-format-table-table-html (lines)
13014 "Format a table generated by table.el into HTML.
13015 This conversion does *not* use `table-generate-source' from table.el.
13016 This has the advantage that Org-mode's HTML conversions can be used.
13017 But it has the disadvantage, that no cell- or row-spanning is allowed."
13018 (let (line field-buffer
13019 (head org-export-highlight-first-table-line)
13020 fields html empty)
13021 (setq html (concat org-export-html-table-tag "\n"))
13022 (while (setq line (pop lines))
13023 (setq empty "&nbsp")
13024 (catch 'next-line
13025 (if (string-match "^[ \t]*\\+-" line)
13026 (progn
13027 (if field-buffer
13028 (progn
13029 (setq html (concat
13030 html
13031 "<tr>"
13032 (mapconcat
13033 (lambda (x)
13034 (if (equal x "") (setq x empty))
13035 (if head
13036 (concat "<th>" x "</th>\n")
13037 (concat "<td>" x "</td>\n")))
13038 field-buffer "\n")
13039 "</tr>\n"))
13040 (setq head nil)
13041 (setq field-buffer nil)))
13042 ;; Ignore this line
13043 (throw 'next-line t)))
13044 ;; Break the line into fields and store the fields
13045 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
13046 (if field-buffer
13047 (setq field-buffer (mapcar
13048 (lambda (x)
13049 (concat x "<br>" (pop fields)))
13050 field-buffer))
13051 (setq field-buffer fields))))
13052 (setq html (concat html "</table>\n"))
13053 html))
13055 (defun org-format-table-table-html-using-table-generate-source (lines)
13056 "Format a table into html, using `table-generate-source' from table.el.
13057 This has the advantage that cell- or row-spanning is allowed.
13058 But it has the disadvantage, that Org-mode's HTML conversions cannot be used."
13059 (require 'table)
13060 (with-current-buffer (get-buffer-create " org-tmp1 ")
13061 (erase-buffer)
13062 (insert (mapconcat 'identity lines "\n"))
13063 (goto-char (point-min))
13064 (if (not (re-search-forward "|[^+]" nil t))
13065 (error "Error processing table"))
13066 (table-recognize-table)
13067 (with-current-buffer (get-buffer-create " org-tmp2 ") (erase-buffer))
13068 (table-generate-source 'html " org-tmp2 ")
13069 (set-buffer " org-tmp2 ")
13070 (buffer-substring (point-min) (point-max))))
13072 (defun org-html-handle-time-stamps (s)
13073 "Format time stamps in string S, or remove them."
13074 (let (r b)
13075 (while (string-match org-maybe-keyword-time-regexp s)
13076 (or b (setq b (substring s 0 (match-beginning 0))))
13077 (if (not org-export-with-timestamps)
13078 (setq r (concat r (substring s 0 (match-beginning 0)))
13079 s (substring s (match-end 0)))
13080 (setq r (concat
13081 r (substring s 0 (match-beginning 0))
13082 (if (match-end 1)
13083 (format "@<span class=\"timestamp-kwd\">%s @</span>"
13084 (match-string 1 s)))
13085 (format " @<span class=\"timestamp\">%s@</span>"
13086 (substring (match-string 3 s) 1 -1)))
13087 s (substring s (match-end 0)))))
13088 ;; Line break of line started and ended with time stamp stuff
13089 (if (not r)
13091 (setq r (concat r s))
13092 (unless (string-match "\\S-" (concat b s))
13093 (setq r (concat r "@<br>")))
13094 r)))
13096 (defun org-html-protect (s)
13097 ;; convert & to &amp;, < to &lt; and > to &gt;
13098 (let ((start 0))
13099 (while (string-match "&" s start)
13100 (setq s (replace-match "&amp;" t t s)
13101 start (1+ (match-beginning 0))))
13102 (while (string-match "<" s)
13103 (setq s (replace-match "&lt;" t t s)))
13104 (while (string-match ">" s)
13105 (setq s (replace-match "&gt;" t t s))))
13108 (defun org-html-cleanup-toc-line (s)
13109 "Remove tags and time staps from lines going into the toc."
13110 (if (string-match " +:[a-zA-Z0-9_@:]+: *$" s)
13111 (setq s (replace-match "" t t s)))
13112 (while (string-match org-maybe-keyword-time-regexp s)
13113 (setq s (replace-match "" t t s)))
13116 (defun org-html-expand (string)
13117 "Prepare STRING for HTML export. Applies all active conversions.
13118 If there are links in the string, don't modify these."
13119 (let* (m s l res)
13120 (while (setq m (string-match org-bracket-link-regexp string))
13121 (setq s (substring string 0 m)
13122 l (match-string 0 string)
13123 string (substring string (match-end 0)))
13124 (push (org-html-do-expand s) res)
13125 (push l res))
13126 (push (org-html-do-expand string) res)
13127 (apply 'concat (nreverse res))))
13129 (defun org-html-do-expand (s)
13130 "Apply all active conversions to translate special ASCII to HTML."
13131 (setq s (org-html-protect s))
13132 (if org-export-html-expand
13133 (while (string-match "@&lt;\\([^&]*\\)&gt;" s)
13134 (setq s (replace-match "<\\1>" nil nil s))))
13135 (if org-export-with-emphasize
13136 (setq s (org-export-html-convert-emphasize s)))
13137 (if org-export-with-sub-superscripts
13138 (setq s (org-export-html-convert-sub-super s)))
13139 (if org-export-with-TeX-macros
13140 (let ((start 0) wd ass)
13141 (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)" s start))
13142 (setq wd (match-string 1 s))
13143 (if (setq ass (assoc wd org-html-entities))
13144 (setq s (replace-match (or (cdr ass)
13145 (concat "&" (car ass) ";"))
13146 t t s))
13147 (setq start (+ start (length wd)))))))
13150 (defun org-create-multibrace-regexp (left right n)
13151 "Create a regular expression which will match a balanced sexp.
13152 Opening delimiter is LEFT, and closing delimiter is RIGHT, both given
13153 as single character strings.
13154 The regexp returned will match the entire expression including the
13155 delimiters. It will also define a single group which contains the
13156 match except for the outermost delimiters. The maximum depth of
13157 stacked delimiters is N. Escaping delimiters is not possible."
13158 (let* ((nothing (concat "[^" "\\" left "\\" right "]*?"))
13159 (or "\\|")
13160 (re nothing)
13161 (next (concat "\\(?:" nothing left nothing right "\\)+" nothing)))
13162 (while (> n 1)
13163 (setq n (1- n)
13164 re (concat re or next)
13165 next (concat "\\(?:" nothing left next right "\\)+" nothing)))
13166 (concat left "\\(" re "\\)" right)))
13168 (defvar org-match-substring-regexp
13169 (concat
13170 "\\([^\\]\\)\\([_^]\\)\\("
13171 "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
13172 "\\|"
13173 "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
13174 "\\|"
13175 "\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
13176 "The regular expression matching a sub- or superscript.")
13178 (defun org-export-html-convert-sub-super (string)
13179 "Convert sub- and superscripts in STRING to HTML."
13180 (let (key c)
13181 (while (string-match org-match-substring-regexp string)
13182 (setq key (if (string= (match-string 2 string) "_") "sub" "sup"))
13183 (setq c (or (match-string 8 string)
13184 (match-string 6 string)
13185 (match-string 5 string)))
13186 (setq string (replace-match
13187 (concat (match-string 1 string)
13188 "<" key ">" c "</" key ">")
13189 t t string)))
13190 (while (string-match "\\\\\\([_^]\\)" string)
13191 (setq string (replace-match (match-string 1 string) t t string))))
13192 string)
13194 (defun org-export-html-convert-emphasize (string)
13195 (while (string-match org-italic-re string)
13196 (setq string (replace-match "\\1<i>\\3</i>\\4" t nil string)))
13197 (while (string-match org-bold-re string)
13198 (setq string (replace-match "\\1<b>\\3</b>\\4" t nil string)))
13199 (while (string-match org-underline-re string)
13200 (setq string (replace-match "\\1<u>\\3</u>\\4" t nil string)))
13201 string)
13203 (defun org-html-level-start (level title umax with-toc head-count)
13204 "Insert a new level in HTML export.
13205 When TITLE is nil, just close all open levels."
13206 (let ((l (1+ (max level umax))))
13207 (while (<= l org-level-max)
13208 (if (aref levels-open (1- l))
13209 (progn
13210 (org-html-level-close l)
13211 (aset levels-open (1- l) nil)))
13212 (setq l (1+ l)))
13213 (when title
13214 ;; If title is nil, this means this function is called to close
13215 ;; all levels, so the rest is done only if title is given
13216 (if (> level umax)
13217 (progn
13218 (if (aref levels-open (1- level))
13219 (insert "<li>" title "<p>\n")
13220 (aset levels-open (1- level) t)
13221 (insert "<ul><li>" title "<p>\n")))
13222 (if org-export-with-section-numbers
13223 (setq title (concat (org-section-number level) " " title)))
13224 (setq level (+ level 1))
13225 (when (string-match "\\(:[a-zA-Z0-9_@:]+:\\)[ \t]*$" title)
13226 (setq title (replace-match
13227 (if org-export-with-tags
13228 (save-match-data
13229 (concat
13230 "&nbsp;&nbsp;&nbsp;<span class=\"tag\">"
13231 (mapconcat 'identity (org-split-string
13232 (match-string 1 title) ":")
13233 "&nbsp;")
13234 "</span>"))
13236 t t title)))
13237 (if with-toc
13238 (insert (format "\n<H%d><a name=\"sec-%d\">%s</a></H%d>\n"
13239 level head-count title level))
13240 (insert (format "\n<H%d>%s</H%d>\n" level title level)))))))
13242 (defun org-html-level-close (&rest args)
13243 "Terminate one level in HTML export."
13244 (insert "</ul>"))
13246 ;; Variable holding the vector with section numbers
13247 (defvar org-section-numbers (make-vector org-level-max 0))
13249 (defun org-init-section-numbers ()
13250 "Initialize the vector for the section numbers."
13251 (let* ((level -1)
13252 (numbers (nreverse (org-split-string "" "\\.")))
13253 (depth (1- (length org-section-numbers)))
13254 (i depth) number-string)
13255 (while (>= i 0)
13256 (if (> i level)
13257 (aset org-section-numbers i 0)
13258 (setq number-string (or (car numbers) "0"))
13259 (if (string-match "\\`[A-Z]\\'" number-string)
13260 (aset org-section-numbers i
13261 (- (string-to-char number-string) ?A -1))
13262 (aset org-section-numbers i (string-to-number number-string)))
13263 (pop numbers))
13264 (setq i (1- i)))))
13266 (defun org-section-number (&optional level)
13267 "Return a string with the current section number.
13268 When LEVEL is non-nil, increase section numbers on that level."
13269 (let* ((depth (1- (length org-section-numbers))) idx n (string ""))
13270 (when level
13271 (when (> level -1)
13272 (aset org-section-numbers
13273 level (1+ (aref org-section-numbers level))))
13274 (setq idx (1+ level))
13275 (while (<= idx depth)
13276 (if (not (= idx 1))
13277 (aset org-section-numbers idx 0))
13278 (setq idx (1+ idx))))
13279 (setq idx 0)
13280 (while (<= idx depth)
13281 (setq n (aref org-section-numbers idx))
13282 (setq string (concat string (if (not (string= string "")) "." "")
13283 (int-to-string n)))
13284 (setq idx (1+ idx)))
13285 (save-match-data
13286 (if (string-match "\\`\\([@0]\\.\\)+" string)
13287 (setq string (replace-match "" nil nil string)))
13288 (if (string-match "\\(\\.0\\)+\\'" string)
13289 (setq string (replace-match "" nil nil string))))
13290 string))
13293 (defun org-export-icalendar-this-file ()
13294 "Export current file as an iCalendar file.
13295 The iCalendar file will be located in the same directory as the Org-mode
13296 file, but with extension `.ics'."
13297 (interactive)
13298 (org-export-icalendar nil buffer-file-name))
13300 (defun org-export-as-xml (arg)
13301 "Export current buffer as XOXO XML buffer."
13302 (interactive "P")
13303 (cond ((eq org-export-xml-type 'xoxo)
13304 (org-export-as-xoxo (current-buffer)))))
13306 (defun org-export-as-xoxo-insert-into (buffer &rest output)
13307 (with-current-buffer buffer
13308 (apply 'insert output)))
13310 (defun org-export-as-xoxo (&optional buffer)
13311 "Export the org buffer as XOXO.
13312 The XOXO buffer is named *xoxo-<source buffer name>*"
13313 (interactive (list (current-buffer)))
13314 ;; A quickie abstraction
13316 ;; Output everything as XOXO
13317 (with-current-buffer (get-buffer buffer)
13318 (goto-char (point-min)) ;; CD: beginning-of-buffer is not allowed.
13319 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
13320 (org-infile-export-plist)))
13321 (filename (concat (file-name-as-directory
13322 (org-export-directory :xoxo opt-plist))
13323 (file-name-sans-extension
13324 (file-name-nondirectory buffer-file-name))
13325 ".html"))
13326 (out (find-file-noselect filename))
13327 (last-level 1)
13328 (hanging-li nil))
13329 ;; Check the output buffer is empty.
13330 (with-current-buffer out (erase-buffer))
13331 ;; Kick off the output
13332 (org-export-as-xoxo-insert-into out "<ol class='xoxo'>\n")
13333 (while (re-search-forward "^\\(\\*+\\) \\(.+\\)" (point-max) 't)
13334 (let* ((hd (match-string-no-properties 1))
13335 (level (length hd))
13336 (text (concat
13337 (match-string-no-properties 2)
13338 (save-excursion
13339 (goto-char (match-end 0))
13340 (let ((str ""))
13341 (catch 'loop
13342 (while 't
13343 (forward-line)
13344 (if (looking-at "^[ \t]\\(.*\\)")
13345 (setq str (concat str (match-string-no-properties 1)))
13346 (throw 'loop str)))))))))
13348 ;; Handle level rendering
13349 (cond
13350 ((> level last-level)
13351 (org-export-as-xoxo-insert-into out "\n<ol>\n"))
13353 ((< level last-level)
13354 (dotimes (- (- last-level level) 1)
13355 (if hanging-li
13356 (org-export-as-xoxo-insert-into out "</li>\n"))
13357 (org-export-as-xoxo-insert-into out "</ol>\n"))
13358 (when hanging-li
13359 (org-export-as-xoxo-insert-into out "</li>\n")
13360 (setq hanging-li nil)))
13362 ((equal level last-level)
13363 (if hanging-li
13364 (org-export-as-xoxo-insert-into out "</li>\n")))
13367 (setq last-level level)
13369 ;; And output the new li
13370 (setq hanging-li 't)
13371 (if (equal ?+ (elt text 0))
13372 (org-export-as-xoxo-insert-into out "<li class='" (substring text 1) "'>")
13373 (org-export-as-xoxo-insert-into out "<li>" text))))
13375 ;; Finally finish off the ol
13376 (dotimes (- last-level 1)
13377 (if hanging-li
13378 (org-export-as-xoxo-insert-into out "</li>\n"))
13379 (org-export-as-xoxo-insert-into out "</ol>\n"))
13381 ;; Finish the buffer off and clean it up.
13382 (switch-to-buffer-other-window out)
13383 (indent-region (point-min) (point-max) nil)
13384 (save-buffer)
13385 (goto-char (point-min))
13388 ;;;###autoload
13389 (defun org-export-icalendar-all-agenda-files ()
13390 "Export all files in `org-agenda-files' to iCalendar .ics files.
13391 Each iCalendar file will be located in the same directory as the Org-mode
13392 file, but with extension `.ics'."
13393 (interactive)
13394 (apply 'org-export-icalendar nil (org-agenda-files t)))
13396 ;;;###autoload
13397 (defun org-export-icalendar-combine-agenda-files ()
13398 "Export all files in `org-agenda-files' to a single combined iCalendar file.
13399 The file is stored under the name `org-combined-agenda-icalendar-file'."
13400 (interactive)
13401 (apply 'org-export-icalendar t (org-agenda-files t)))
13403 (defun org-export-icalendar (combine &rest files)
13404 "Create iCalendar files for all elements of FILES.
13405 If COMBINE is non-nil, combine all calendar entries into a single large
13406 file and store it under the name `org-combined-agenda-icalendar-file'."
13407 (save-excursion
13408 (let* ((dir (org-export-directory
13409 :ical (list :publishing-directory
13410 org-export-publishing-directory)))
13411 file ical-file ical-buffer category started org-agenda-new-buffers)
13413 (when combine
13414 (setq ical-file
13415 (if (file-name-absolute-p org-combined-agenda-icalendar-file)
13416 org-combined-agenda-icalendar-file
13417 (expand-file-name org-combined-agenda-icalendar-file dir))
13418 ical-buffer (org-get-agenda-file-buffer ical-file))
13419 (set-buffer ical-buffer) (erase-buffer))
13420 (while (setq file (pop files))
13421 (catch 'nextfile
13422 (org-check-agenda-file file)
13423 (set-buffer (org-get-agenda-file-buffer file))
13424 (unless combine
13425 (setq ical-file (concat (file-name-as-directory dir)
13426 (file-name-sans-extension
13427 (file-name-nondirectory buffer-file-name))
13428 ".ics"))
13429 (setq ical-buffer (org-get-agenda-file-buffer ical-file))
13430 (with-current-buffer ical-buffer (erase-buffer)))
13431 (setq category (or org-category
13432 (file-name-sans-extension
13433 (file-name-nondirectory buffer-file-name))))
13434 (if (symbolp category) (setq category (symbol-name category)))
13435 (let ((standard-output ical-buffer))
13436 (if combine
13437 (and (not started) (setq started t)
13438 (org-start-icalendar-file org-icalendar-combined-name))
13439 (org-start-icalendar-file category))
13440 (org-print-icalendar-entries combine category)
13441 (when (or (and combine (not files)) (not combine))
13442 (org-finish-icalendar-file)
13443 (set-buffer ical-buffer)
13444 (save-buffer)
13445 (run-hooks 'org-after-save-iCalendar-file-hook)))))
13446 (org-release-buffers org-agenda-new-buffers))))
13448 (defvar org-after-save-iCalendar-file-hook nil
13449 "Hook run after an iCalendar file has been saved.
13450 The iCalendar buffer is still current when this hook is run.
13451 A good way to use this is to tell a desktop calenndar application to re-read
13452 the iCalendar file.")
13454 (defun org-print-icalendar-entries (&optional combine category)
13455 "Print iCalendar entries for the current Org-mode file to `standard-output'.
13456 When COMBINE is non nil, add the category to each line."
13457 (let ((re2 (concat "--?-?\\(" org-ts-regexp "\\)"))
13458 (dts (org-ical-ts-to-string
13459 (format-time-string (cdr org-time-stamp-formats) (current-time))
13460 "DTSTART"))
13461 hd ts ts2 state (inc t) pos scheduledp deadlinep tmp pri)
13462 (save-excursion
13463 (goto-char (point-min))
13464 (while (re-search-forward org-ts-regexp nil t)
13465 (setq pos (match-beginning 0)
13466 ts (match-string 0)
13467 inc t
13468 hd (org-get-heading))
13469 (if (looking-at re2)
13470 (progn
13471 (goto-char (match-end 0))
13472 (setq ts2 (match-string 1) inc nil))
13473 (setq ts2 ts
13474 tmp (buffer-substring (max (point-min)
13475 (- pos org-ds-keyword-length))
13476 pos)
13477 deadlinep (string-match org-deadline-regexp tmp)
13478 scheduledp (string-match org-scheduled-regexp tmp)
13479 ;; donep (org-entry-is-done-p)
13481 (if (or (string-match org-tr-regexp hd)
13482 (string-match org-ts-regexp hd))
13483 (setq hd (replace-match "" t t hd)))
13484 (if combine
13485 (setq hd (concat hd " (category " category ")")))
13486 (if deadlinep (setq hd (concat "DL: " hd " This is a deadline")))
13487 (if scheduledp (setq hd (concat "S: " hd " Scheduled for this date")))
13488 (princ (format "BEGIN:VEVENT
13491 SUMMARY:%s
13492 END:VEVENT\n"
13493 (org-ical-ts-to-string ts "DTSTART")
13494 (org-ical-ts-to-string ts2 "DTEND" inc)
13495 hd)))
13496 (when org-icalendar-include-todo
13497 (goto-char (point-min))
13498 (while (re-search-forward org-todo-line-regexp nil t)
13499 (setq state (match-string 1))
13500 (unless (equal state org-done-string)
13501 (setq hd (match-string 3))
13502 (if (string-match org-priority-regexp hd)
13503 (setq pri (string-to-char (match-string 2 hd))
13504 hd (concat (substring hd 0 (match-beginning 1))
13505 (substring hd (- (match-end 1)))))
13506 (setq pri org-default-priority))
13507 (setq pri (floor (1+ (* 8. (/ (float (- org-lowest-priority pri))
13508 (- org-lowest-priority ?A))))))
13510 (princ (format "BEGIN:VTODO
13512 SUMMARY:%s
13513 SEQUENCE:1
13514 PRIORITY:%d
13515 END:VTODO\n"
13516 dts hd pri))))))))
13518 (defun org-start-icalendar-file (name)
13519 "Start an iCalendar file by inserting the header."
13520 (let ((user user-full-name)
13521 (name (or name "unknown"))
13522 (timezone (cadr (current-time-zone))))
13523 (princ
13524 (format "BEGIN:VCALENDAR
13525 VERSION:2.0
13526 X-WR-CALNAME:%s
13527 PRODID:-//%s//Emacs with Org-mode//EN
13528 X-WR-TIMEZONE:%s
13529 CALSCALE:GREGORIAN\n" name user timezone))))
13531 (defun org-finish-icalendar-file ()
13532 "Finish an iCalendar file by inserting the END statement."
13533 (princ "END:VCALENDAR\n"))
13535 (defun org-ical-ts-to-string (s keyword &optional inc)
13536 "Take a time string S and convert it to iCalendar format.
13537 KEYWORD is added in front, to make a complete line like DTSTART....
13538 When INC is non-nil, increase the hour by two (if time string contains
13539 a time), or the day by one (if it does not contain a time)."
13540 (let ((t1 (org-parse-time-string s 'nodefault))
13541 t2 fmt have-time time)
13542 (if (and (car t1) (nth 1 t1) (nth 2 t1))
13543 (setq t2 t1 have-time t)
13544 (setq t2 (org-parse-time-string s)))
13545 (let ((s (car t2)) (mi (nth 1 t2)) (h (nth 2 t2))
13546 (d (nth 3 t2)) (m (nth 4 t2)) (y (nth 5 t2)))
13547 (when inc
13548 (if have-time (setq h (+ 2 h)) (setq d (1+ d))))
13549 (setq time (encode-time s mi h d m y)))
13550 (setq fmt (if have-time ":%Y%m%dT%H%M%S" ";VALUE=DATE:%Y%m%d"))
13551 (concat keyword (format-time-string fmt time))))
13554 ;;; Key bindings
13556 ;; - Bindings in Org-mode map are currently
13557 ;; 0123456789abcdefghijklmnopqrstuvwxyz!?@#$%^&-+*/=()_{}[]:;"|,.<>~`'\t the alphabet
13558 ;; abcd fgh j lmnopqrstuvwxyz!? #$ ^ -+*/= [] ; |,.<>~ '\t necessary bindings
13559 ;; e (?) useful from outline-mode
13560 ;; i k @ expendable from outline-mode
13561 ;; 0123456789 % & ()_{} " ` free
13563 ;; Make `C-c C-x' a prefix key
13564 (define-key org-mode-map "\C-c\C-x" (make-sparse-keymap))
13565 (define-key org-mode-map "\C-c\C-e" (make-sparse-keymap))
13567 ;; TAB key with modifiers
13568 (define-key org-mode-map "\C-i" 'org-cycle)
13569 (define-key org-mode-map [(tab)] 'org-cycle)
13570 (define-key org-mode-map [(meta tab)] 'org-complete)
13571 (define-key org-mode-map "\M-\C-i" 'org-complete) ; for tty emacs
13572 ;; The following line is necessary under Suse GNU/Linux
13573 (unless (featurep 'xemacs)
13574 (define-key org-mode-map [S-iso-lefttab] 'org-shifttab))
13575 (define-key org-mode-map [(shift tab)] 'org-shifttab)
13577 (define-key org-mode-map (org-key 'S-return) 'org-table-copy-down)
13578 (define-key org-mode-map "\C-c\C-xc" 'org-table-copy-down) ; tty
13579 (define-key org-mode-map [(meta shift return)] 'org-insert-todo-heading)
13580 (define-key org-mode-map "\C-c\C-xM" 'org-insert-todo-heading) ; tty
13581 (define-key org-mode-map [(meta return)] 'org-meta-return)
13582 (define-key org-mode-map "\C-c\C-xm" 'org-meta-return) ; tty emacs
13583 (define-key org-mode-map [?\e (return)] 'org-meta-return) ; tty emacs
13585 ;; Cursor keys with modifiers
13586 (define-key org-mode-map [(meta left)] 'org-metaleft)
13587 (define-key org-mode-map [?\e (left)] 'org-metaleft) ; for tty emacs
13588 (define-key org-mode-map "\C-c\C-xl" 'org-metaleft) ; for tty emacs
13589 (define-key org-mode-map [(meta right)] 'org-metaright)
13590 (define-key org-mode-map [?\e (right)] 'org-metaright) ; for tty emacs
13591 (define-key org-mode-map "\C-c\C-xr" 'org-metaright) ; for tty emacs
13592 (define-key org-mode-map [(meta up)] 'org-metaup)
13593 (define-key org-mode-map [?\e (up)] 'org-metaup) ; for tty emacs
13594 (define-key org-mode-map "\C-c\C-xu" 'org-metaup) ; for tty emacs
13595 (define-key org-mode-map [(meta down)] 'org-metadown)
13596 (define-key org-mode-map [?\e (down)] 'org-metadown) ; for tty emacs
13597 (define-key org-mode-map "\C-c\C-xd" 'org-metadown) ; for tty emacs
13599 (define-key org-mode-map [(meta shift left)] 'org-shiftmetaleft)
13600 (define-key org-mode-map "\C-c\C-xL" 'org-shiftmetaleft) ; tty
13601 (define-key org-mode-map [(meta shift right)] 'org-shiftmetaright)
13602 (define-key org-mode-map "\C-c\C-xR" 'org-shiftmetaright) ; tty
13603 (define-key org-mode-map [(meta shift up)] 'org-shiftmetaup)
13604 (define-key org-mode-map "\C-c\C-xU" 'org-shiftmetaup) ; tty
13605 (define-key org-mode-map [(meta shift down)] 'org-shiftmetadown)
13606 (define-key org-mode-map "\C-c\C-xD" 'org-shiftmetadown) ; tty
13607 (define-key org-mode-map (org-key 'S-up) 'org-shiftup)
13608 (define-key org-mode-map [?\C-c ?\C-x (up)] 'org-shiftup)
13609 (define-key org-mode-map (org-key 'S-down) 'org-shiftdown)
13610 (define-key org-mode-map [?\C-c ?\C-x (down)] 'org-shiftdown)
13611 (define-key org-mode-map (org-key 'S-left) 'org-shiftleft)
13612 (define-key org-mode-map [?\C-c ?\C-x (left)] 'org-shiftleft)
13613 (define-key org-mode-map (org-key 'S-right) 'org-shiftright)
13614 (define-key org-mode-map [?\C-c ?\C-x (right)] 'org-shiftright)
13616 ;; All the other keys
13618 (define-key org-mode-map "\C-c\C-a" 'show-all) ; in case allout messed up.
13619 (define-key org-mode-map "\C-c$" 'org-archive-subtree)
13620 (define-key org-mode-map "\C-c\C-j" 'org-goto)
13621 (define-key org-mode-map "\C-c\C-t" 'org-todo)
13622 (define-key org-mode-map "\C-c\C-s" 'org-schedule)
13623 (define-key org-mode-map "\C-c\C-d" 'org-deadline)
13624 (define-key org-mode-map "\C-c;" 'org-toggle-comment)
13625 (define-key org-mode-map "\C-c\C-v" 'org-show-todo-tree)
13626 (define-key org-mode-map "\C-c\C-w" 'org-check-deadlines)
13627 (define-key org-mode-map "\C-c/" 'org-occur) ; Minor-mode reserved
13628 (define-key org-mode-map "\C-c\\" 'org-tags-sparse-tree) ; Minor-mode res.
13629 (define-key org-mode-map "\C-c\C-m" 'org-insert-heading)
13630 (define-key org-mode-map "\M-\C-m" 'org-insert-heading)
13631 (define-key org-mode-map "\C-c\C-l" 'org-insert-link)
13632 (define-key org-mode-map "\C-c\C-o" 'org-open-at-point)
13633 (define-key org-mode-map "\C-c%" 'org-mark-ring-push)
13634 (define-key org-mode-map "\C-c&" 'org-mark-ring-goto)
13635 (define-key org-mode-map "\C-c\C-z" 'org-time-stamp) ; Alternative binding
13636 (define-key org-mode-map "\C-c." 'org-time-stamp) ; Minor-mode reserved
13637 (define-key org-mode-map "\C-c!" 'org-time-stamp-inactive) ; Minor-mode r.
13638 (define-key org-mode-map "\C-c," 'org-priority) ; Minor-mode reserved
13639 (define-key org-mode-map "\C-c\C-y" 'org-evaluate-time-range)
13640 (define-key org-mode-map "\C-c>" 'org-goto-calendar)
13641 (define-key org-mode-map "\C-c<" 'org-date-from-calendar)
13642 (define-key org-mode-map [(control ?,)] 'org-cycle-agenda-files)
13643 (define-key org-mode-map "\C-c[" 'org-agenda-file-to-front)
13644 (define-key org-mode-map "\C-c]" 'org-remove-file)
13645 (define-key org-mode-map "\C-c\C-r" 'org-timeline)
13646 (define-key org-mode-map "\C-c-" 'org-table-insert-hline)
13647 (define-key org-mode-map "\C-c^" 'org-table-sort-lines)
13648 (define-key org-mode-map "\C-c\C-c" 'org-ctrl-c-ctrl-c)
13649 (define-key org-mode-map "\C-m" 'org-return)
13650 (define-key org-mode-map "\C-c?" 'org-table-current-column)
13651 (define-key org-mode-map "\C-c " 'org-table-blank-field)
13652 (define-key org-mode-map "\C-c+" 'org-table-sum)
13653 (define-key org-mode-map "\C-c=" 'org-table-eval-formula)
13654 (define-key org-mode-map "\C-c'" 'org-table-edit-formulas)
13655 (define-key org-mode-map "\C-c`" 'org-table-edit-field)
13656 (define-key org-mode-map "\C-c|" 'org-table-create-or-convert-from-region)
13657 (define-key org-mode-map "\C-c*" 'org-table-recalculate)
13658 (define-key org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks)
13659 (define-key org-mode-map "\C-c~" 'org-table-create-with-table.el)
13660 (define-key org-mode-map "\C-c\C-q" 'org-table-wrap-region)
13661 (define-key org-mode-map "\C-c\C-xa" 'org-export-as-ascii)
13662 (define-key org-mode-map "\C-c\C-x\C-a" 'org-export-as-ascii)
13663 (define-key org-mode-map "\C-c\C-xv" 'org-export-visible)
13664 (define-key org-mode-map "\C-c\C-x\C-v" 'org-export-visible)
13665 ;; OPML support is only an option for the future
13666 ;(define-key org-mode-map "\C-c\C-xo" 'org-export-as-opml)
13667 ;(define-key org-mode-map "\C-c\C-x\C-o" 'org-export-as-opml)
13668 (define-key org-mode-map "\C-c\C-xi" 'org-export-icalendar-this-file)
13669 (define-key org-mode-map "\C-c\C-x\C-i" 'org-export-icalendar-all-agenda-files)
13670 (define-key org-mode-map "\C-c\C-xc" 'org-export-icalendar-combine-agenda-files)
13671 (define-key org-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files)
13672 (define-key org-mode-map "\C-c\C-xt" 'org-insert-export-options-template)
13673 (define-key org-mode-map "\C-c:" 'org-toggle-fixed-width-section)
13674 (define-key org-mode-map "\C-c\C-xh" 'org-export-as-html)
13675 (define-key org-mode-map "\C-c\C-xx" 'org-export-as-xml)
13676 (define-key org-mode-map "\C-c\C-x\C-x" 'org-export-as-xml)
13677 (define-key org-mode-map "\C-c\C-xb" 'org-export-as-html-and-open)
13678 (define-key org-mode-map "\C-c\C-x\C-b" 'org-export-as-html-and-open)
13680 (define-key org-mode-map "\C-c\C-x\C-k" 'org-cut-special)
13681 (define-key org-mode-map "\C-c\C-x\C-w" 'org-cut-special)
13682 (define-key org-mode-map "\C-c\C-x\M-w" 'org-copy-special)
13683 (define-key org-mode-map "\C-c\C-x\C-y" 'org-paste-special)
13685 (define-key org-mode-map "\C-c\C-ef" 'org-publish-current-file)
13686 (define-key org-mode-map "\C-c\C-ep" 'org-publish-current-project)
13687 (define-key org-mode-map "\C-c\C-ec" 'org-publish)
13688 (define-key org-mode-map "\C-c\C-ea" 'org-publish-all)
13689 (define-key org-mode-map "\C-c\C-e\C-f" 'org-publish-current-file)
13690 (define-key org-mode-map "\C-c\C-e\C-p" 'org-publish-current-project)
13691 (define-key org-mode-map "\C-c\C-e\C-c" 'org-publish)
13692 (define-key org-mode-map "\C-c\C-e\C-a" 'org-publish-all)
13694 (when (featurep 'xemacs)
13695 (define-key org-mode-map 'button3 'popup-mode-menu))
13697 (defsubst org-table-p () (org-at-table-p))
13699 (defun org-self-insert-command (N)
13700 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
13701 If the cursor is in a table looking at whitespace, the whitespace is
13702 overwritten, and the table is not marked as requiring realignment."
13703 (interactive "p")
13704 (if (and (org-table-p)
13705 (progn
13706 ;; check if we blank the field, and if that triggers align
13707 (and org-table-auto-blank-field
13708 (member last-command
13709 '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c))
13710 (if (or (equal (char-after) ?\ ) (looking-at "[^|\n]* |"))
13711 ;; got extra space, this field does not determine column width
13712 (let (org-table-may-need-update) (org-table-blank-field))
13713 ;; no extra space, this field may determine column width
13714 (org-table-blank-field)))
13716 (eq N 1)
13717 (looking-at "[^|\n]* |"))
13718 (let (org-table-may-need-update)
13719 (goto-char (1- (match-end 0)))
13720 (delete-backward-char 1)
13721 (goto-char (match-beginning 0))
13722 (self-insert-command N))
13723 (setq org-table-may-need-update t)
13724 (self-insert-command N)))
13726 (defun org-delete-backward-char (N)
13727 "Like `delete-backward-char', insert whitespace at field end in tables.
13728 When deleting backwards, in tables this function will insert whitespace in
13729 front of the next \"|\" separator, to keep the table aligned. The table will
13730 still be marked for re-alignment if the field did fill the entire column,
13731 because, in this case the deletion might narrow the column."
13732 (interactive "p")
13733 (if (and (org-table-p)
13734 (eq N 1)
13735 (string-match "|" (buffer-substring (point-at-bol) (point)))
13736 (looking-at ".*?|"))
13737 (let ((pos (point))
13738 (noalign (looking-at "[^|\n\r]* |"))
13739 (c org-table-may-need-update))
13740 (backward-delete-char N)
13741 (skip-chars-forward "^|")
13742 (insert " ")
13743 (goto-char (1- pos))
13744 ;; noalign: if there were two spaces at the end, this field
13745 ;; does not determine the width of the column.
13746 (if noalign (setq org-table-may-need-update c)))
13747 (backward-delete-char N)))
13749 (defun org-delete-char (N)
13750 "Like `delete-char', but insert whitespace at field end in tables.
13751 When deleting characters, in tables this function will insert whitespace in
13752 front of the next \"|\" separator, to keep the table aligned. The table will
13753 still be marked for re-alignment if the field did fill the entire column,
13754 because, in this case the deletion might narrow the column."
13755 (interactive "p")
13756 (if (and (org-table-p)
13757 (not (bolp))
13758 (not (= (char-after) ?|))
13759 (eq N 1))
13760 (if (looking-at ".*?|")
13761 (let ((pos (point))
13762 (noalign (looking-at "[^|\n\r]* |"))
13763 (c org-table-may-need-update))
13764 (replace-match (concat
13765 (substring (match-string 0) 1 -1)
13766 " |"))
13767 (goto-char pos)
13768 ;; noalign: if there were two spaces at the end, this field
13769 ;; does not determine the width of the column.
13770 (if noalign (setq org-table-may-need-update c)))
13771 (delete-char N))
13772 (delete-char N)))
13774 ;; How to do this: Measure non-white length of current string
13775 ;; If equal to column width, we should realign.
13777 (defun org-remap (map &rest commands)
13778 "In MAP, remap the functions given in COMMANDS.
13779 COMMANDS is a list of alternating OLDDEF NEWDEF command names."
13780 (let (new old)
13781 (while commands
13782 (setq old (pop commands) new (pop commands))
13783 (if (fboundp 'command-remapping)
13784 (define-key map (vector 'remap old) new)
13785 (substitute-key-definition old new map global-map)))))
13787 (when (eq org-enable-table-editor 'optimized)
13788 ;; If the user wants maximum table support, we need to hijack
13789 ;; some standard editing functions
13790 (org-remap org-mode-map
13791 'self-insert-command 'org-self-insert-command
13792 'delete-char 'org-delete-char
13793 'delete-backward-char 'org-delete-backward-char)
13794 (define-key org-mode-map "|" 'org-force-self-insert))
13796 (defun org-shiftcursor-error ()
13797 "Throw an error because Shift-Cursor command was applied in wrong context."
13798 (error "This command is active in special context like tables, headlines or timestamps"))
13800 (defun org-shifttab ()
13801 "Global visibility cycling or move to previous table field.
13802 Calls `org-cycle' with argument t, or `org-table-previous-field', depending
13803 on context.
13804 See the individual commands for more information."
13805 (interactive)
13806 (cond
13807 ((org-at-table-p) (call-interactively 'org-table-previous-field))
13808 (t (call-interactively 'org-global-cycle))))
13810 (defun org-shiftmetaleft ()
13811 "Promote subtree or delete table column.
13812 Calls `org-promote-subtree' or `org-table-delete-column', depending on context.
13813 See the individual commands for more information."
13814 (interactive)
13815 (cond
13816 ((org-at-table-p) (call-interactively 'org-table-delete-column))
13817 ((org-on-heading-p) (call-interactively 'org-promote-subtree))
13818 ((org-at-item-p) (call-interactively 'org-outdent-item))
13819 (t (org-shiftcursor-error))))
13821 (defun org-shiftmetaright ()
13822 "Demote subtree or insert table column.
13823 Calls `org-demote-subtree' or `org-table-insert-column', depending on context.
13824 See the individual commands for more information."
13825 (interactive)
13826 (cond
13827 ((org-at-table-p) (call-interactively 'org-table-insert-column))
13828 ((org-on-heading-p) (call-interactively 'org-demote-subtree))
13829 ((org-at-item-p) (call-interactively 'org-indent-item))
13830 (t (org-shiftcursor-error))))
13832 (defun org-shiftmetaup (&optional arg)
13833 "Move subtree up or kill table row.
13834 Calls `org-move-subtree-up' or `org-table-kill-row' or
13835 `org-move-item-up' depending on context. See the individual commands
13836 for more information."
13837 (interactive "P")
13838 (cond
13839 ((org-at-table-p) (call-interactively 'org-table-kill-row))
13840 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
13841 ((org-at-item-p) (call-interactively 'org-move-item-up))
13842 (t (org-shiftcursor-error))))
13843 (defun org-shiftmetadown (&optional arg)
13844 "Move subtree down or insert table row.
13845 Calls `org-move-subtree-down' or `org-table-insert-row' or
13846 `org-move-item-down', depending on context. See the individual
13847 commands for more information."
13848 (interactive "P")
13849 (cond
13850 ((org-at-table-p) (call-interactively 'org-table-insert-row))
13851 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
13852 ((org-at-item-p) (call-interactively 'org-move-item-down))
13853 (t (org-shiftcursor-error))))
13855 (defun org-metaleft (&optional arg)
13856 "Promote heading or move table column to left.
13857 Calls `org-do-promote' or `org-table-move-column', depending on context.
13858 With no specific context, calls the Emacs default `backward-word'.
13859 See the individual commands for more information."
13860 (interactive "P")
13861 (cond
13862 ((org-at-table-p) (org-call-with-arg 'org-table-move-column 'left))
13863 ((or (org-on-heading-p) (org-region-active-p))
13864 (call-interactively 'org-do-promote))
13865 (t (call-interactively 'backward-word))))
13867 (defun org-metaright (&optional arg)
13868 "Demote subtree or move table column to right.
13869 Calls `org-do-demote' or `org-table-move-column', depending on context.
13870 With no specific context, calls the Emacs default `forward-word'.
13871 See the individual commands for more information."
13872 (interactive "P")
13873 (cond
13874 ((org-at-table-p) (call-interactively 'org-table-move-column))
13875 ((or (org-on-heading-p) (org-region-active-p))
13876 (call-interactively 'org-do-demote))
13877 (t (call-interactively 'forward-word))))
13879 (defun org-metaup (&optional arg)
13880 "Move subtree up or move table row up.
13881 Calls `org-move-subtree-up' or `org-table-move-row' or
13882 `org-move-item-up', depending on context. See the individual commands
13883 for more information."
13884 (interactive "P")
13885 (cond
13886 ((org-at-table-p) (org-call-with-arg 'org-table-move-row 'up))
13887 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
13888 ((org-at-item-p) (call-interactively 'org-move-item-up))
13889 (t (org-shiftcursor-error))))
13891 (defun org-metadown (&optional arg)
13892 "Move subtree down or move table row down.
13893 Calls `org-move-subtree-down' or `org-table-move-row' or
13894 `org-move-item-down', depending on context. See the individual
13895 commands for more information."
13896 (interactive "P")
13897 (cond
13898 ((org-at-table-p) (call-interactively 'org-table-move-row))
13899 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
13900 ((org-at-item-p) (call-interactively 'org-move-item-down))
13901 (t (org-shiftcursor-error))))
13903 (defun org-shiftup (&optional arg)
13904 "Increase item in timestamp or increase priority of current headline.
13905 Calls `org-timestamp-up' or `org-priority-up', depending on context.
13906 See the individual commands for more information."
13907 (interactive "P")
13908 (cond
13909 ((org-at-timestamp-p) (call-interactively 'org-timestamp-up))
13910 ((org-on-heading-p) (call-interactively 'org-priority-up))
13911 ((org-at-item-p) (call-interactively 'org-previous-item))
13912 (t (call-interactively 'org-beginning-of-item) (beginning-of-line 1))))
13914 (defun org-shiftdown (&optional arg)
13915 "Decrease item in timestamp or decrease priority of current headline.
13916 Calls `org-timestamp-down' or `org-priority-down', depending on context.
13917 See the individual commands for more information."
13918 (interactive "P")
13919 (cond
13920 ((org-at-timestamp-p) (call-interactively 'org-timestamp-down))
13921 ((org-on-heading-p) (call-interactively 'org-priority-down))
13922 (t (call-interactively 'org-next-item))))
13924 (defun org-shiftright ()
13925 "Next TODO keyword or timestamp one day later, depending on context."
13926 (interactive)
13927 (cond
13928 ((org-at-timestamp-p) (call-interactively 'org-timestamp-up-day))
13929 ((org-on-heading-p) (org-call-with-arg 'org-todo 'right))
13930 (t (org-shiftcursor-error))))
13932 (defun org-shiftleft ()
13933 "Previous TODO keyword or timestamp one day earlier, depending on context."
13934 (interactive)
13935 (cond
13936 ((org-at-timestamp-p) (call-interactively 'org-timestamp-down-day))
13937 ((org-on-heading-p) (org-call-with-arg 'org-todo 'left))
13938 (t (org-shiftcursor-error))))
13940 (defun org-copy-special ()
13941 "Copy region in table or copy current subtree.
13942 Calls `org-table-copy' or `org-copy-subtree', depending on context.
13943 See the individual commands for more information."
13944 (interactive)
13945 (call-interactively
13946 (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree)))
13948 (defun org-cut-special ()
13949 "Cut region in table or cut current subtree.
13950 Calls `org-table-copy' or `org-cut-subtree', depending on context.
13951 See the individual commands for more information."
13952 (interactive)
13953 (call-interactively
13954 (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree)))
13956 (defun org-paste-special (arg)
13957 "Paste rectangular region into table, or past subtree relative to level.
13958 Calls `org-table-paste-rectangle' or `org-paste-subtree', depending on context.
13959 See the individual commands for more information."
13960 (interactive "P")
13961 (if (org-at-table-p)
13962 (org-table-paste-rectangle)
13963 (org-paste-subtree arg)))
13965 (defun org-ctrl-c-ctrl-c (&optional arg)
13966 "Set tags in headline, or update according to changed information at point.
13968 This command does many different things, depending on context:
13970 - If the cursor is in a headline, prompt for tags and insert them
13971 into the current line, aligned to `org-tags-column'. When called
13972 with prefix arg, realign all tags in the current buffer.
13974 - If the cursor is in one of the special #+KEYWORD lines, this
13975 triggers scanning the buffer for these lines and updating the
13976 information.
13978 - If the cursor is inside a table, realign the table. This command
13979 works even if the automatic table editor has been turned off.
13981 - If the cursor is on a #+TBLFM line, re-apply the formulas to
13982 the entire table.
13984 - If the cursor is inside a table created by the table.el package,
13985 activate that table.
13987 - If the current buffer is a remember buffer, close note and file it.
13988 with a prefix argument, file it without further interaction to the default
13989 location.
13991 - If the cursor is on a <<<target>>>, update radio targets and corresponding
13992 links in this buffer.
13994 - If the cursor is on a numbered item in a plain list, renumber the
13995 ordered list."
13996 (interactive "P")
13997 (let ((org-enable-table-editor t))
13998 (cond
13999 ((and (local-variable-p 'org-finish-function (current-buffer))
14000 (fboundp org-finish-function))
14001 (funcall org-finish-function))
14002 ((org-on-target-p) (call-interactively 'org-update-radio-target-regexp))
14003 ((org-on-heading-p) (call-interactively 'org-set-tags))
14004 ((org-at-table.el-p)
14005 (require 'table)
14006 (beginning-of-line 1)
14007 (re-search-forward "|" (save-excursion (end-of-line 2) (point)))
14008 (call-interactively 'table-recognize-table))
14009 ((org-at-table-p)
14010 (org-table-maybe-eval-formula)
14011 (if arg
14012 (call-interactively 'org-table-recalculate)
14013 (org-table-maybe-recalculate-line))
14014 (call-interactively 'org-table-align))
14015 ((org-at-item-checkbox-p)
14016 (call-interactively 'org-toggle-checkbox))
14017 ((org-at-item-p)
14018 (call-interactively 'org-renumber-ordered-list))
14019 ((save-excursion (beginning-of-line 1) (looking-at "#\\+\\([A-Z]+\\)"))
14020 (cond
14021 ((equal (match-string 1) "TBLFM")
14022 ;; Recalculate the table before this line
14023 (save-excursion
14024 (beginning-of-line 1)
14025 (skip-chars-backward " \r\n\t")
14026 (if (org-at-table-p)
14027 (org-call-with-arg 'org-table-recalculate t))))
14029 (call-interactively 'org-mode-restart))))
14030 (t (error "C-c C-c can do nothing useful at this location.")))))
14032 (defun org-mode-restart ()
14033 "Restart Org-mode, to scan again for special lines.
14034 Also updates the keyword regular expressions."
14035 (interactive)
14036 (let ((org-inhibit-startup t)) (org-mode))
14037 (message "Org-mode restarted to refresh keyword and special line setup"))
14039 (defun org-return ()
14040 "Goto next table row or insert a newline.
14041 Calls `org-table-next-row' or `newline', depending on context.
14042 See the individual commands for more information."
14043 (interactive)
14044 (cond
14045 ((org-at-table-p)
14046 (org-table-justify-field-maybe)
14047 (call-interactively 'org-table-next-row))
14048 (t (newline))))
14050 (defun org-meta-return (&optional arg)
14051 "Insert a new heading or wrap a region in a table.
14052 Calls `org-insert-heading' or `org-table-wrap-region', depending on context.
14053 See the individual commands for more information."
14054 (interactive "P")
14055 (cond
14056 ((org-at-table-p)
14057 (call-interactively 'org-table-wrap-region))
14058 (t (call-interactively 'org-insert-heading))))
14060 ;;; Menu entries
14062 ;; Define the Org-mode menus
14063 (easy-menu-define org-tbl-menu org-mode-map "Tbl menu"
14064 '("Tbl"
14065 ["Align" org-ctrl-c-ctrl-c (org-at-table-p)]
14066 ["Next Field" org-cycle (org-at-table-p)]
14067 ["Previous Field" org-shifttab (org-at-table-p)]
14068 ["Next Row" org-return (org-at-table-p)]
14069 "--"
14070 ["Blank Field" org-table-blank-field (org-at-table-p)]
14071 ["Edit Field" org-table-edit-field (org-at-table-p)]
14072 ["Copy Field from Above" org-table-copy-down (org-at-table-p)]
14073 "--"
14074 ("Column"
14075 ["Move Column Left" org-metaleft (org-at-table-p)]
14076 ["Move Column Right" org-metaright (org-at-table-p)]
14077 ["Delete Column" org-shiftmetaleft (org-at-table-p)]
14078 ["Insert Column" org-shiftmetaright (org-at-table-p)]
14079 "--"
14080 ["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])
14081 ("Row"
14082 ["Move Row Up" org-metaup (org-at-table-p)]
14083 ["Move Row Down" org-metadown (org-at-table-p)]
14084 ["Delete Row" org-shiftmetaup (org-at-table-p)]
14085 ["Insert Row" org-shiftmetadown (org-at-table-p)]
14086 ["Sort lines in region" org-table-sort-lines (org-at-table-p)]
14087 "--"
14088 ["Insert Hline" org-table-insert-hline (org-at-table-p)])
14089 ("Rectangle"
14090 ["Copy Rectangle" org-copy-special (org-at-table-p)]
14091 ["Cut Rectangle" org-cut-special (org-at-table-p)]
14092 ["Paste Rectangle" org-paste-special (org-at-table-p)]
14093 ["Fill Rectangle" org-table-wrap-region (org-at-table-p)])
14094 "--"
14095 ("Calculate"
14096 ["Set Column Formula" org-table-eval-formula (org-at-table-p)]
14097 ["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
14098 ["Edit Formulas" org-table-edit-formulas (org-at-table-p)]
14099 "--"
14100 ["Recalculate line" org-table-recalculate (org-at-table-p)]
14101 ["Recalculate all" (lambda () (interactive) (org-table-recalculate '(4))) :active (org-at-table-p) :keys "C-u C-c *"]
14102 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks (org-at-table-p)]
14103 "--"
14104 ["Sum Column/Rectangle" org-table-sum
14105 (or (org-at-table-p) (org-region-active-p))]
14106 ["Which Column?" org-table-current-column (org-at-table-p)])
14107 ["Debug Formulas"
14108 (setq org-table-formula-debug (not org-table-formula-debug))
14109 :style toggle :selected org-table-formula-debug]
14110 "--"
14111 ["Create" org-table-create (and (not (org-at-table-p))
14112 org-enable-table-editor)]
14113 ["Convert Region" org-table-convert-region (not (org-at-table-p 'any))]
14114 ["Import from File" org-table-import (not (org-at-table-p))]
14115 ["Export to File" org-table-export (org-at-table-p)]
14116 "--"
14117 ["Create/Convert from/to table.el" org-table-create-with-table.el t]))
14119 (easy-menu-define org-org-menu org-mode-map "Org menu"
14120 '("Org"
14121 ["Cycle Visibility" org-cycle (or (bobp) (outline-on-heading-p))]
14122 ["Cycle Global Visibility" org-shifttab (not (org-at-table-p))]
14123 ["Sparse Tree" org-occur t]
14124 ["Show All" show-all t]
14125 "--"
14126 ["New Heading" org-insert-heading t]
14127 ("Navigate Headings"
14128 ["Up" outline-up-heading t]
14129 ["Next" outline-next-visible-heading t]
14130 ["Previous" outline-previous-visible-heading t]
14131 ["Next Same Level" outline-forward-same-level t]
14132 ["Previous Same Level" outline-backward-same-level t]
14133 "--"
14134 ["Jump" org-goto t])
14135 ("Edit Structure"
14136 ["Move Subtree Up" org-shiftmetaup (not (org-at-table-p))]
14137 ["Move Subtree Down" org-shiftmetadown (not (org-at-table-p))]
14138 "--"
14139 ["Copy Subtree" org-copy-special (not (org-at-table-p))]
14140 ["Cut Subtree" org-cut-special (not (org-at-table-p))]
14141 ["Paste Subtree" org-paste-special (not (org-at-table-p))]
14142 "--"
14143 ["Promote Heading" org-metaleft (not (org-at-table-p))]
14144 ["Promote Subtree" org-shiftmetaleft (not (org-at-table-p))]
14145 ["Demote Heading" org-metaright (not (org-at-table-p))]
14146 ["Demote Subtree" org-shiftmetaright (not (org-at-table-p))]
14147 "--"
14148 ["Archive Subtree" org-archive-subtree t]
14149 "--"
14150 ["Convert to odd levels" org-convert-to-odd-levels t]
14151 ["Convert to odd/even levels" org-convert-to-oddeven-levels t])
14152 "--"
14153 ("TODO Lists"
14154 ["TODO/DONE/-" org-todo t]
14155 ["Show TODO Tree" org-show-todo-tree t]
14156 ["Global TODO list" org-todo-list t]
14157 "--"
14158 ["Set Priority" org-priority t]
14159 ["Priority Up" org-shiftup t]
14160 ["Priority Down" org-shiftdown t])
14161 ("Dates and Scheduling"
14162 ["Timestamp" org-time-stamp t]
14163 ["Timestamp (inactive)" org-time-stamp-inactive t]
14164 ("Change Date"
14165 ["1 Day Later" org-timestamp-up-day t]
14166 ["1 Day Earlier" org-timestamp-down-day t]
14167 ["1 ... Later" org-shiftup t]
14168 ["1 ... Earlier" org-shiftdown t])
14169 ["Compute Time Range" org-evaluate-time-range t]
14170 ["Schedule Item" org-schedule t]
14171 ["Deadline" org-deadline t]
14172 "--"
14173 ["Goto Calendar" org-goto-calendar t]
14174 ["Date from Calendar" org-date-from-calendar t])
14175 "--"
14176 ["Agenda Command" org-agenda t]
14177 ("File List for Agenda")
14178 ("Special views current file"
14179 ["TODO Tree" org-show-todo-tree t]
14180 ["Check Deadlines" org-check-deadlines t]
14181 ["Timeline" org-timeline t]
14182 ["Tags Tree" org-tags-sparse-tree t])
14183 "--"
14184 ("Hyperlinks"
14185 ["Store Link (Global)" org-store-link t]
14186 ["Insert Link" org-insert-link t]
14187 ["Follow Link" org-open-at-point t]
14188 "--"
14189 ["Descriptive Links"
14190 (progn (org-add-to-invisibility-spec '(org-link)) (org-restart-font-lock))
14191 :style radio :selected (member '(org-link) buffer-invisibility-spec)]
14192 ["Literal Links"
14193 (progn
14194 (org-remove-from-invisibility-spec '(org-link)) (org-restart-font-lock))
14195 :style radio :selected (not (member '(org-link) buffer-invisibility-spec))]
14196 "--"
14197 ["Upgrade all <link> to [[link][desc]]" org-upgrade-old-links
14198 (save-excursion (goto-char (point-min))
14199 (re-search-forward "<[a-z]+:" nil t))])
14200 "--"
14201 ("Export"
14202 ["ASCII" org-export-as-ascii t]
14203 ["Export visible part..." org-export-visible t]
14204 ["HTML" org-export-as-html t]
14205 ["HTML and Open" org-export-as-html-and-open t]
14206 ["XOXO" org-export-as-xml t]
14207 "--"
14208 ["iCalendar this file" org-export-icalendar-this-file t]
14209 ["iCalendar all agenda files" org-export-icalendar-all-agenda-files
14210 :active t :keys "C-c C-x C-i"]
14211 ["iCalendar combined" org-export-icalendar-combine-agenda-files t]
14212 "--"
14213 ["Option Template" org-insert-export-options-template t]
14214 ["Toggle Fixed Width" org-toggle-fixed-width-section t])
14215 ("Publish"
14216 ["Current File" org-publish-current-file t]
14217 ["Current Project" org-publish-current-project t]
14218 ["Project..." org-publish t]
14219 ["All Projects" org-publish-all t])
14220 "--"
14221 ("Documentation"
14222 ["Show Version" org-version t]
14223 ["Info Documentation" org-info t])
14224 ("Customize"
14225 ["Browse Org Group" org-customize t]
14226 "--"
14227 ["Expand This Menu" org-create-customize-menu
14228 (fboundp 'customize-menu-create)])
14229 "--"
14230 ["Refresh setup" org-mode-restart t]
14233 (defun org-info (&optional node)
14234 "Read documentation for Org-mode in the info system.
14235 With optional NODE, go directly to that node."
14236 (interactive)
14237 (require 'info)
14238 (Info-goto-node (format "(org)%s" (or node ""))))
14240 (defun org-install-agenda-files-menu ()
14241 (let ((bl (buffer-list)))
14242 (save-excursion
14243 (while bl
14244 (set-buffer (pop bl))
14245 (if (eq major-mode 'org-mode) (setq bl nil)))
14246 (when (eq major-mode 'org-mode)
14247 (easy-menu-change
14248 '("Org") "File List for Agenda"
14249 (append
14250 (list
14251 ["Edit File List" (org-edit-agenda-file-list) t]
14252 ["Add/Move Current File to Front of List" org-agenda-file-to-front t]
14253 ["Remove Current File from List" org-remove-file t]
14254 ["Cycle through agenda files" org-cycle-agenda-files t]
14255 "--")
14256 (mapcar 'org-file-menu-entry (org-agenda-files t))))))))
14258 ;;; Documentation
14260 (defun org-customize ()
14261 "Call the customize function with org as argument."
14262 (interactive)
14263 (customize-browse 'org))
14265 (defun org-create-customize-menu ()
14266 "Create a full customization menu for Org-mode, insert it into the menu."
14267 (interactive)
14268 (if (fboundp 'customize-menu-create)
14269 (progn
14270 (easy-menu-change
14271 '("Org") "Customize"
14272 `(["Browse Org group" org-customize t]
14273 "--"
14274 ,(customize-menu-create 'org)
14275 ["Set" Custom-set t]
14276 ["Save" Custom-save t]
14277 ["Reset to Current" Custom-reset-current t]
14278 ["Reset to Saved" Custom-reset-saved t]
14279 ["Reset to Standard Settings" Custom-reset-standard t]))
14280 (message "\"Org\"-menu now contains full customization menu"))
14281 (error "Cannot expand menu (outdated version of cus-edit.el)")))
14283 ;;; Miscellaneous stuff
14285 (defun org-move-line-down (arg)
14286 "Move the current line down. With prefix argument, move it past ARG lines."
14287 (interactive "p")
14288 (let ((col (current-column))
14289 beg end pos)
14290 (beginning-of-line 1) (setq beg (point))
14291 (beginning-of-line 2) (setq end (point))
14292 (beginning-of-line (+ 1 arg))
14293 (setq pos (move-marker (make-marker) (point)))
14294 (insert (delete-and-extract-region beg end))
14295 (goto-char pos)
14296 (move-to-column col)))
14298 (defun org-move-line-up (arg)
14299 "Move the current line up. With prefix argument, move it past ARG lines."
14300 (interactive "p")
14301 (let ((col (current-column))
14302 beg end pos)
14303 (beginning-of-line 1) (setq beg (point))
14304 (beginning-of-line 2) (setq end (point))
14305 (beginning-of-line (- arg))
14306 (setq pos (move-marker (make-marker) (point)))
14307 (insert (delete-and-extract-region beg end))
14308 (goto-char pos)
14309 (move-to-column col)))
14311 ;; Paragraph filling stuff.
14312 ;; We want this to be just right, so use the full arsenal.
14313 ;; FIXME: This very likely does not work correctly for XEmacs, because the
14314 ;; filladapt package works slightly differently.
14316 (defun org-set-autofill-regexps ()
14317 (interactive)
14318 ;; In the paragraph separator we include headlines, because filling
14319 ;; text in a line directly attached to a headline would otherwise
14320 ;; fill the headline as well.
14321 (set (make-local-variable 'paragraph-separate) "\f\\|\\*\\|[ ]*$\\|[ \t]*[:|]")
14322 ;; The paragraph starter includes hand-formatted lists.
14323 (set (make-local-variable 'paragraph-start)
14324 "\f\\|[ ]*$\\|\\([*\f]+\\)\\|[ \t]*\\([-+*]\\|[0-9]+[.)][ \t]+\\)\\|[ \t]*[:|]")
14325 ;; Inhibit auto-fill for headers, tables and fixed-width lines.
14326 ;; But only if the user has not turned off tables or fixed-width regions
14327 (set (make-local-variable 'auto-fill-inhibit-regexp)
14328 (concat "\\*\\|#"
14329 (if (or org-enable-table-editor org-enable-fixed-width-editor)
14330 (concat
14331 "\\|[ \t]*["
14332 (if org-enable-table-editor "|" "")
14333 (if org-enable-fixed-width-editor ":" "")
14334 "]"))))
14335 ;; We use our own fill-paragraph function, to make sure that tables
14336 ;; and fixed-width regions are not wrapped. That function will pass
14337 ;; through to `fill-paragraph' when appropriate.
14338 (set (make-local-variable 'fill-paragraph-function) 'org-fill-paragraph)
14339 ;; Adaptive filling: To get full control, first make sure that
14340 ;; `adaptive-fill-regexp' never matches. Then install our own matcher.
14341 (set (make-local-variable 'adaptive-fill-regexp) "\000")
14342 (set (make-local-variable 'adaptive-fill-function)
14343 'org-adaptive-fill-function))
14345 (defun org-fill-paragraph (&optional justify)
14346 "Re-align a table, pass through to fill-paragraph if no table."
14347 (let ((table-p (org-at-table-p))
14348 (table.el-p (org-at-table.el-p)))
14349 (cond ((equal (char-after (point-at-bol)) ?*) t) ; skip headlines
14350 (table.el-p t) ; skip table.el tables
14351 (table-p (org-table-align) t) ; align org-mode tables
14352 (t nil)))) ; call paragraph-fill
14354 ;; For reference, this is the default value of adaptive-fill-regexp
14355 ;; "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*"
14357 (defun org-adaptive-fill-function ()
14358 "Return a fill prefix for org-mode files.
14359 In particular, this makes sure hanging paragraphs for hand-formatted lists
14360 work correctly."
14361 (if (looking-at " *\\([-*+] \\|[0-9]+[.)] \\)?")
14362 (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
14364 ;; Functions needed for Emacs/XEmacs region compatibility
14366 (defun org-add-hook (hook function &optional append local)
14367 "Add-hook, compatible with both Emacsen."
14368 (if (and local (featurep 'xemacs))
14369 (add-local-hook hook function append)
14370 (add-hook hook function append local)))
14372 (defun org-region-active-p ()
14373 "Is `transient-mark-mode' on and the region active?
14374 Works on both Emacs and XEmacs."
14375 (if org-ignore-region
14377 (if (featurep 'xemacs)
14378 (and zmacs-regions (region-active-p))
14379 (and transient-mark-mode mark-active))))
14381 (defun org-add-to-invisibility-spec (arg)
14382 "Add elements to `buffer-invisibility-spec'.
14383 See documentation for `buffer-invisibility-spec' for the kind of elements
14384 that can be added."
14385 (cond
14386 ((fboundp 'add-to-invisibility-spec)
14387 (add-to-invisibility-spec arg))
14388 ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t))
14389 (setq buffer-invisibility-spec (list arg)))
14391 (setq buffer-invisibility-spec
14392 (cons arg buffer-invisibility-spec)))))
14394 (defun org-remove-from-invisibility-spec (arg)
14395 "Remove elements from `buffer-invisibility-spec'."
14396 (if (fboundp 'remove-from-invisibility-spec)
14397 (remove-from-invisibility-spec arg)
14398 (if (consp buffer-invisibility-spec)
14399 (setq buffer-invisibility-spec
14400 (delete arg buffer-invisibility-spec)))))
14402 (defun org-in-invisibility-spec-p (arg)
14403 "Is ARG a member of `buffer-invisibility-spec'?"
14404 (if (consp buffer-invisibility-spec)
14405 (member arg buffer-invisibility-spec)
14406 nil))
14408 (defun org-image-file-name-regexp ()
14409 "Return regexp matching the file names of images."
14410 (if (fboundp 'image-file-name-regexp)
14411 (image-file-name-regexp)
14412 (let ((image-file-name-extensions
14413 '("png" "jpeg" "jpg" "gif" "tiff" "tif"
14414 "xbm" "xpm" "pbm" "pgm" "ppm")))
14415 (concat "\\."
14416 (regexp-opt (nconc (mapcar 'upcase
14417 image-file-name-extensions)
14418 image-file-name-extensions)
14420 "\\'"))))
14422 ;; Functions needed for compatibility with old outline.el.
14424 ;; Programming for the old outline.el (that uses selective display
14425 ;; instead of `invisible' text properties) is a nightmare, mostly
14426 ;; because regular expressions can no longer be anchored at
14427 ;; beginning/end of line. Therefore a number of function need special
14428 ;; treatment when the old outline.el is being used.
14430 ;; The following functions capture almost the entire compatibility code
14431 ;; between the different versions of outline-mode. The only other
14432 ;; places where this is important are the font-lock-keywords, and in
14433 ;; `org-export-visible'. Search for `org-noutline-p' to find them.
14435 ;; C-a should go to the beginning of a *visible* line, also in the
14436 ;; new outline.el. I guess this should be patched into Emacs?
14437 (defun org-beginning-of-line ()
14438 "Go to the beginning of the current line. If that is invisible, continue
14439 to a visible line beginning. This makes the function of C-a more intuitive."
14440 (interactive)
14441 (beginning-of-line 1)
14442 (if (bobp)
14444 (backward-char 1)
14445 (if (org-invisible-p)
14446 (while (and (not (bobp)) (org-invisible-p))
14447 (backward-char 1)
14448 (beginning-of-line 1))
14449 (forward-char 1))))
14451 (when org-noutline-p
14452 (define-key org-mode-map "\C-a" 'org-beginning-of-line))
14453 ;; FIXME: should I use substitute-key-definition to reach other bindings
14454 ;; of beginning-of-line?
14456 (defun org-invisible-p ()
14457 "Check if point is at a character currently not visible."
14458 (if org-noutline-p
14459 ;; Early versions of noutline don't have `outline-invisible-p'.
14460 (if (fboundp 'outline-invisible-p)
14461 (outline-invisible-p)
14462 (get-char-property (point) 'invisible))
14463 (save-excursion
14464 (skip-chars-backward "^\r\n")
14465 (equal (char-before) ?\r))))
14467 (defun org-invisible-p2 ()
14468 "Check if point is at a character currently not visible."
14469 (save-excursion
14470 (if org-noutline-p
14471 (progn
14472 (if (and (eolp) (not (bobp))) (backward-char 1))
14473 ;; Early versions of noutline don't have `outline-invisible-p'.
14474 (if (fboundp 'outline-invisible-p)
14475 (outline-invisible-p)
14476 (get-char-property (point) 'invisible)))
14477 (skip-chars-backward "^\r\n")
14478 (equal (char-before) ?\r))))
14480 (defun org-back-to-heading (&optional invisible-ok)
14481 "Move to previous heading line, or beg of this line if it's a heading.
14482 Only visible heading lines are considered, unless INVISIBLE-OK is non-nil."
14483 (if org-noutline-p
14484 (outline-back-to-heading invisible-ok)
14485 (if (and (or (bobp) (memq (char-before) '(?\n ?\r)))
14486 (looking-at outline-regexp))
14488 (if (re-search-backward (concat (if invisible-ok "\\([\r\n]\\|^\\)" "^")
14489 outline-regexp)
14490 nil t)
14491 (if invisible-ok
14492 (progn (goto-char (or (match-end 1) (match-beginning 0)))
14493 (looking-at outline-regexp)))
14494 (error "Before first heading")))))
14496 (defun org-on-heading-p (&optional invisible-ok)
14497 "Return t if point is on a (visible) heading line.
14498 If INVISIBLE-OK is non-nil, an invisible heading line is ok too."
14499 (if org-noutline-p
14500 (outline-on-heading-p 'invisible-ok)
14501 (save-excursion
14502 (skip-chars-backward "^\n\r")
14503 (and (looking-at outline-regexp)
14504 (or invisible-ok
14505 (bobp)
14506 (equal (char-before) ?\n))))))
14508 (defun org-on-target-p ()
14509 (let ((pos (point)))
14510 (save-excursion
14511 (skip-chars-forward "<")
14512 (and (re-search-backward "<<" nil t)
14513 (or (looking-at org-radio-target-regexp)
14514 (looking-at org-target-regexp))
14515 (<= (match-beginning 0) pos)
14516 (>= (1+ (match-end 0)) pos)))))
14518 (defun org-up-heading-all (arg)
14519 "Move to the heading line of which the present line is a subheading.
14520 This function considers both visible and invisible heading lines.
14521 With argument, move up ARG levels."
14522 (if org-noutline-p
14523 (if (fboundp 'outline-up-heading-all)
14524 (outline-up-heading-all arg) ; emacs 21 version of outline.el
14525 (outline-up-heading arg t)) ; emacs 22 version of outline.el
14526 (org-back-to-heading t)
14527 (looking-at outline-regexp)
14528 (if (<= (- (match-end 0) (match-beginning 0)) arg)
14529 (error "Cannot move up %d levels" arg)
14530 (re-search-backward
14531 (concat "[\n\r]" (regexp-quote
14532 (make-string (- (match-end 0) (match-beginning 0) arg)
14533 ?*))
14534 "[^*]"))
14535 (forward-char 1))))
14537 (defun org-show-hidden-entry ()
14538 "Show an entry where even the heading is hidden."
14539 (save-excursion
14540 (if (not org-noutline-p)
14541 (progn
14542 (org-back-to-heading t)
14543 (org-flag-heading nil)))
14544 (org-show-entry)))
14546 (defun org-check-occur-regexp (regexp)
14547 "If REGEXP starts with \"^\", modify it to check for \\r as well.
14548 Of course, only for the old outline mode."
14549 (if org-noutline-p
14550 regexp
14551 (if (string-match "^\\^" regexp)
14552 (concat "[\n\r]" (substring regexp 1))
14553 regexp)))
14555 (defun org-flag-heading (flag &optional entry)
14556 "Flag the current heading. FLAG non-nil means make invisible.
14557 When ENTRY is non-nil, show the entire entry."
14558 (save-excursion
14559 (org-back-to-heading t)
14560 (if (not org-noutline-p)
14561 ;; Make the current headline visible
14562 (outline-flag-region (max 1 (1- (point))) (point) (if flag ?\r ?\n)))
14563 ;; Check if we should show the entire entry
14564 (if entry
14565 (progn
14566 (org-show-entry)
14567 (save-excursion
14568 (and (outline-next-heading)
14569 (org-flag-heading nil))))
14570 (outline-flag-region (max 1 (1- (point)))
14571 (save-excursion (outline-end-of-heading) (point))
14572 (if org-noutline-p
14573 flag
14574 (if flag ?\r ?\n))))))
14576 (defun org-end-of-subtree (&optional invisible-OK)
14577 ;; This is an exact copy of the original function, but it uses
14578 ;; `org-back-to-heading', to make it work also in invisible
14579 ;; trees. And is uses an invisible-OK argument.
14580 ;; Under Emacs this is not needed, but the old outline.el needs this fix.
14581 (org-back-to-heading invisible-OK)
14582 (let ((first t)
14583 (level (funcall outline-level)))
14584 (while (and (not (eobp))
14585 (or first (> (funcall outline-level) level)))
14586 (setq first nil)
14587 (outline-next-heading))
14588 (if (memq (preceding-char) '(?\n ?\^M))
14589 (progn
14590 ;; Go to end of line before heading
14591 (forward-char -1)
14592 (if (memq (preceding-char) '(?\n ?\^M))
14593 ;; leave blank line before heading
14594 (forward-char -1))))))
14596 (defun org-show-subtree ()
14597 "Show everything after this heading at deeper levels."
14598 (outline-flag-region
14599 (point)
14600 (save-excursion
14601 (outline-end-of-subtree) (outline-next-heading) (point))
14602 (if org-noutline-p nil ?\n)))
14604 (defun org-show-entry ()
14605 "Show the body directly following this heading.
14606 Show the heading too, if it is currently invisible."
14607 (interactive)
14608 (save-excursion
14609 (org-back-to-heading t)
14610 (outline-flag-region
14611 (max 1 (1- (point)))
14612 (save-excursion
14613 (re-search-forward (concat "[\r\n]\\(" outline-regexp "\\)") nil 'move)
14614 (or (match-beginning 1) (point-max)))
14615 (if org-noutline-p nil ?\n))))
14617 (defun org-make-options-regexp (kwds)
14618 "Make a regular expression for keyword lines."
14619 (concat
14620 (if org-noutline-p "^" "[\n\r]")
14621 "#?[ \t]*\\+\\("
14622 (mapconcat 'regexp-quote kwds "\\|")
14623 "\\):[ \t]*"
14624 (if org-noutline-p "\\(.+\\)" "\\([^\n\r]+\\)")))
14626 ;; Make `bookmark-jump' show the jump location if it was hidden.
14627 (eval-after-load "bookmark"
14628 '(if (boundp 'bookmark-after-jump-hook)
14629 ;; We can use the hook
14630 (add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide)
14631 ;; Hook not available, use advice
14632 (defadvice bookmark-jump (after org-make-visible activate)
14633 "Make the position visible."
14634 (org-bookmark-jump-unhide))))
14636 (defun org-bookmark-jump-unhide ()
14637 "Unhide the current position, to show the bookmark location."
14638 (and (eq major-mode 'org-mode)
14639 (or (org-invisible-p)
14640 (save-excursion (goto-char (max (point-min) (1- (point))))
14641 (org-invisible-p)))
14642 (org-show-hierarchy-above)))
14644 ;;; Finish up
14646 (provide 'org)
14648 (run-hooks 'org-load-hook)
14651 ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
14652 ;;; org.el ends here