Merge from emacs-23; up to 2010-06-15T03:34:12Z!rgm@gnu.org.
[bpt/emacs.git] / lisp / org / org.el
CommitLineData
a3fbe8c4 1;;; org.el --- Outline-based notes management and organizer
791d856f 2;; Carstens outline-mode for keeping track of everything.
95df8112 3;; Copyright (C) 2004-2011 Free Software Foundation, Inc.
ef943dba 4;;
0b8568f5 5;; Author: Carsten Dominik <carsten at orgmode dot org>
4da1a99d 6;; Keywords: outlines, hypermedia, calendar, wp
0b8568f5 7;; Homepage: http://orgmode.org
acedf35c 8;; Version: 7.4
ef943dba 9;;
359ec616 10;; This file is part of GNU Emacs.
ef943dba 11;;
b1fc2b50 12;; GNU Emacs is free software: you can redistribute it and/or modify
359ec616 13;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
891f4676 16
359ec616
RS
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.
891f4676
RS
21
22;; You should have received a copy of the GNU General Public License
b1fc2b50 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
891f4676 24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
891f4676
RS
25;;
26;;; Commentary:
27;;
28;; Org-mode is a mode for keeping notes, maintaining ToDo lists, and doing
29;; project planning with a fast and effective plain-text system.
30;;
f85d958a
CD
31;; Org-mode develops organizational tasks around NOTES files that contain
32;; information about projects as plain text. Org-mode is implemented on
33;; top of outline-mode, which makes it possible to keep the content of
34;; large files well structured. Visibility cycling and structure editing
35;; help to work with the tree. Tables are easily created with a built-in
36;; table editor. Org-mode supports ToDo items, deadlines, time stamps,
37;; and scheduling. It dynamically compiles entries into an agenda that
38;; utilizes and smoothly integrates much of the Emacs calendar and diary.
39;; Plain text URL-like links connect to websites, emails, Usenet
40;; messages, BBDB entries, and any files related to the projects. For
41;; printing and sharing of notes, an Org-mode file can be exported as a
42;; structured ASCII file, as HTML, or (todo and agenda items only) as an
43;; iCalendar file. It can also serve as a publishing tool for a set of
44;; linked webpages.
45;;
3278a016
CD
46;; Installation and Activation
47;; ---------------------------
48;; See the corresponding sections in the manual at
891f4676 49;;
0b8568f5 50;; http://orgmode.org/org.html#Installation
891f4676
RS
51;;
52;; Documentation
53;; -------------
eb2f9c59
CD
54;; The documentation of Org-mode can be found in the TeXInfo file. The
55;; distribution also contains a PDF version of it. At the homepage of
56;; Org-mode, you can read the same text online as HTML. There is also an
7a368970
CD
57;; excellent reference card made by Philip Rooke. This card can be found
58;; in the etc/ directory of Emacs 22.
891f4676 59;;
d3f4dbe8 60;; A list of recent changes can be found at
d5098885 61;; http://orgmode.org/Changes.html
0fee8d6e 62;;
891f4676
RS
63;;; Code:
64
20908596
CD
65(defvar org-inhibit-highlight-removal nil) ; dynamically scoped param
66(defvar org-table-formula-constants-local nil
67 "Local version of `org-table-formula-constants'.")
68(make-variable-buffer-local 'org-table-formula-constants-local)
69
d3f4dbe8
CD
70;;;; Require other packages
71
edd21304 72(eval-when-compile
ab27a4a0 73 (require 'cl)
3820f429
CD
74 (require 'gnus-sum))
75
76(require 'calendar)
acedf35c 77
3820f429 78;; Emacs 22 calendar compatibility: Make sure the new variables are available
86fbb8ca
CD
79(when (fboundp 'defvaralias)
80 (unless (boundp 'calendar-view-holidays-initially-flag)
81 (defvaralias 'calendar-view-holidays-initially-flag
82 'view-calendar-holidays-initially))
83 (unless (boundp 'calendar-view-diary-initially-flag)
84 (defvaralias 'calendar-view-diary-initially-flag
85 'view-diary-entries-initially))
86 (unless (boundp 'diary-fancy-buffer)
87 (defvaralias 'diary-fancy-buffer 'fancy-diary-buffer)))
3820f429 88
0fee8d6e
CD
89(require 'outline) (require 'noutline)
90;; Other stuff we need.
891f4676 91(require 'time-date)
8c6fb58b 92(unless (fboundp 'time-subtract) (defalias 'time-subtract 'subtract-time))
891f4676 93(require 'easymenu)
86fbb8ca 94(require 'overlay)
891f4676 95
20908596 96(require 'org-macs)
ed21c5c8 97(require 'org-entities)
20908596
CD
98(require 'org-compat)
99(require 'org-faces)
621f83e4 100(require 'org-list)
acedf35c 101(require 'org-complete)
c8d0cf5c 102(require 'org-src)
0bd48b37 103(require 'org-footnote)
20908596 104
86fbb8ca
CD
105;; babel
106(require 'ob)
107(require 'ob-table)
108(require 'ob-lob)
109(require 'ob-ref)
110(require 'ob-tangle)
111(require 'ob-comint)
112(require 'ob-keys)
113
114;; load languages based on value of `org-babel-load-languages'
115(defvar org-babel-load-languages)
116;;;###autoload
117(defun org-babel-do-load-languages (sym value)
118 "Load the languages defined in `org-babel-load-languages'."
119 (set-default sym value)
120 (mapc (lambda (pair)
121 (let ((active (cdr pair)) (lang (symbol-name (car pair))))
122 (if active
123 (progn
124 (require (intern (concat "ob-" lang))))
125 (progn
126 (funcall 'fmakunbound
127 (intern (concat "org-babel-execute:" lang)))
128 (funcall 'fmakunbound
129 (intern (concat "org-babel-expand-body:" lang)))))))
130 org-babel-load-languages))
131
132(defcustom org-babel-load-languages '((emacs-lisp . t))
133 "Languages which can be evaluated in Org-mode buffers.
134This list can be used to load support for any of the languages
135below, note that each language will depend on a different set of
136system executables and/or Emacs modes. When a language is
137\"loaded\", then code blocks in that language can be evaluated
138with `org-babel-execute-src-block' bound by default to C-c
139C-c (note the `org-babel-no-eval-on-ctrl-c-ctrl-c' variable can
140be set to remove code block evaluation from the C-c C-c
141keybinding. By default only Emacs Lisp (which has no
142requirements) is loaded."
143 :group 'org-babel
144 :set 'org-babel-do-load-languages
145 :type '(alist :tag "Babel Languages"
146 :key-type
147 (choice
148 (const :tag "C" C)
149 (const :tag "R" R)
150 (const :tag "Asymptote" asymptote)
afe98dfa 151 (const :tag "Calc" calc)
86fbb8ca
CD
152 (const :tag "Clojure" clojure)
153 (const :tag "CSS" css)
154 (const :tag "Ditaa" ditaa)
155 (const :tag "Dot" dot)
156 (const :tag "Emacs Lisp" emacs-lisp)
157 (const :tag "Gnuplot" gnuplot)
158 (const :tag "Haskell" haskell)
afe98dfa 159 (const :tag "Javascript" js)
86fbb8ca 160 (const :tag "Latex" latex)
afe98dfa 161 (const :tag "Ledger" ledger)
86fbb8ca
CD
162 (const :tag "Matlab" matlab)
163 (const :tag "Mscgen" mscgen)
164 (const :tag "Ocaml" ocaml)
165 (const :tag "Octave" octave)
afe98dfa 166 (const :tag "Org" org)
86fbb8ca 167 (const :tag "Perl" perl)
afe98dfa 168 (const :tag "PlantUML" plantuml)
86fbb8ca
CD
169 (const :tag "Python" python)
170 (const :tag "Ruby" ruby)
171 (const :tag "Sass" sass)
afe98dfa 172 (const :tag "Scheme" scheme)
86fbb8ca
CD
173 (const :tag "Screen" screen)
174 (const :tag "Shell Script" sh)
175 (const :tag "Sql" sql)
176 (const :tag "Sqlite" sqlite))
177 :value-type (boolean :tag "Activate" :value t)))
178
d3f4dbe8 179;;;; Customization variables
86fbb8ca
CD
180(defcustom org-clone-delete-id nil
181 "Remove ID property of clones of a subtree.
182When non-nil, clones of a subtree don't inherit the ID property.
183Otherwise they inherit the ID property with a new unique
184identifier."
185 :type 'boolean
186 :group 'org-id)
891f4676 187
d3f4dbe8
CD
188;;; Version
189
acedf35c 190(defconst org-version "7.4"
891f4676 191 "The version number of the file org.el.")
2a57416f
CD
192
193(defun org-version (&optional here)
194 "Show the org-mode version in the echo area.
195With prefix arg HERE, insert it at point."
196 (interactive "P")
8bfe682a
CD
197 (let* ((origin default-directory)
198 (version org-version)
54a0dee5
CD
199 (git-version)
200 (dir (concat (file-name-directory (locate-library "org")) "../" )))
8bfe682a
CD
201 (when (and (file-exists-p (expand-file-name ".git" dir))
202 (executable-find "git"))
203 (unwind-protect
204 (progn
205 (cd dir)
206 (when (eql 0 (shell-command "git describe --abbrev=4 HEAD"))
81ad75af 207 (with-current-buffer "*Shell Command Output*"
54a0dee5 208 (goto-char (point-min))
8bfe682a
CD
209 (setq git-version (buffer-substring (point) (point-at-eol))))
210 (subst-char-in-string ?- ?. git-version t)
211 (when (string-match "\\S-"
212 (shell-command-to-string
213 "git diff-index --name-only HEAD --"))
214 (setq git-version (concat git-version ".dirty")))
215 (setq version (concat version " (" git-version ")"))))
216 (cd origin)))
54a0dee5
CD
217 (setq version (format "Org-mode version %s" version))
218 (if here (insert version))
8bfe682a 219 (message version)))
891f4676 220
d3f4dbe8 221;;; Compatibility constants
38f8646b 222
d3f4dbe8
CD
223;;; The custom variables
224
891f4676 225(defgroup org nil
b0a10108 226 "Outline-based notes management and organizer."
891f4676
RS
227 :tag "Org"
228 :group 'outlines
891f4676
RS
229 :group 'calendar)
230
8bfe682a
CD
231(defcustom org-mode-hook nil
232 "Mode hook for Org-mode, run after the mode was turned on."
233 :group 'org
234 :type 'hook)
235
2a57416f
CD
236(defcustom org-load-hook nil
237 "Hook that is run after org.el has been loaded."
238 :group 'org
239 :type 'hook)
240
20908596
CD
241(defvar org-modules) ; defined below
242(defvar org-modules-loaded nil
243 "Have the modules been loaded already?")
244
245(defun org-load-modules-maybe (&optional force)
ce4fdcb9 246 "Load all extensions listed in `org-modules'."
20908596
CD
247 (when (or force (not org-modules-loaded))
248 (mapc (lambda (ext)
249 (condition-case nil (require ext)
250 (error (message "Problems while trying to load feature `%s'" ext))))
251 org-modules)
252 (setq org-modules-loaded t)))
253
254(defun org-set-modules (var value)
255 "Set VAR to VALUE and call `org-load-modules-maybe' with the force flag."
256 (set var value)
257 (when (featurep 'org)
258 (org-load-modules-maybe 'force)))
259
6dc30f44
CD
260(when (org-bound-and-true-p org-modules)
261 (let ((a (member 'org-infojs org-modules)))
262 (and a (setcar a 'org-jsinfo))))
263
ed21c5c8 264(defcustom org-modules '(org-bbdb org-bibtex org-docview org-gnus org-info org-jsinfo org-irc org-mew org-mhe org-rmail org-vm org-w3m org-wl)
20908596 265 "Modules that should always be loaded together with org.el.
efc054e6 266If a description starts with <C>, the file is not part of Emacs
20908596
CD
267and loading it will require that you have downloaded and properly installed
268the org-mode distribution.
269
270You can also use this system to load external packages (i.e. neither Org
8d642074 271core modules, nor modules from the CONTRIB directory). Just add symbols
efc054e6 272to the end of the list. If the package is called org-xyz.el, then you need
20908596
CD
273to add the symbol `xyz', and the package must have a call to
274
275 (provide 'org-xyz)"
15841868 276 :group 'org
20908596
CD
277 :set 'org-set-modules
278 :type
279 '(set :greedy t
280 (const :tag " bbdb: Links to BBDB entries" org-bbdb)
281 (const :tag " bibtex: Links to BibTeX entries" org-bibtex)
8d642074 282 (const :tag " crypt: Encryption of subtrees" org-crypt)
ed21c5c8
CD
283 (const :tag " ctags: Access to Emacs tags with links" org-ctags)
284 (const :tag " docview: Links to doc-view buffers" org-docview)
20908596 285 (const :tag " gnus: Links to GNUS folders/messages" org-gnus)
db55f368 286 (const :tag " id: Global IDs for identifying entries" org-id)
20908596 287 (const :tag " info: Links to Info nodes" org-info)
6dc30f44 288 (const :tag " jsinfo: Set up Sebastian Rose's JavaScript org-info.js" org-jsinfo)
8bfe682a 289 (const :tag " habit: Track your consistency with habits" org-habit)
c8d0cf5c 290 (const :tag " inlinetask: Tasks independent of outline hierarchy" org-inlinetask)
20908596
CD
291 (const :tag " irc: Links to IRC/ERC chat sessions" org-irc)
292 (const :tag " mac-message: Links to messages in Apple Mail" org-mac-message)
293 (const :tag " mew Links to Mew folders/messages" org-mew)
294 (const :tag " mhe: Links to MHE folders/messages" org-mhe)
c8d0cf5c 295 (const :tag " protocol: Intercept calls from emacsclient" org-protocol)
20908596
CD
296 (const :tag " rmail: Links to RMAIL folders/messages" org-rmail)
297 (const :tag " vm: Links to VM folders/messages" org-vm)
298 (const :tag " wl: Links to Wanderlust folders/messages" org-wl)
8bfe682a 299 (const :tag " w3m: Special cut/paste from w3m to Org-mode." org-w3m)
20908596 300 (const :tag " mouse: Additional mouse support" org-mouse)
afe98dfa 301 (const :tag " TaskJuggler: Export tasks to a TaskJuggler project" org-taskjuggler)
20908596
CD
302
303 (const :tag "C annotate-file: Annotate a file with org syntax" org-annotate-file)
8bfe682a 304 (const :tag "C bookmark: Org-mode links to bookmarks" org-bookmark)
c8d0cf5c
CD
305 (const :tag "C checklist: Extra functions for checklists in repeated tasks" org-checklist)
306 (const :tag "C choose: Use TODO keywords to mark decisions states" org-choose)
307 (const :tag "C collector: Collect properties into tables" org-collector)
8d642074 308 (const :tag "C depend: TODO dependencies for Org-mode\n\t\t\t(PARTIALLY OBSOLETE, see built-in dependency support))" org-depend)
8bfe682a 309 (const :tag "C elisp-symbol: Org-mode links to emacs-lisp symbols" org-elisp-symbol)
b349f79f 310 (const :tag "C eval: Include command output as text" org-eval)
ce4fdcb9 311 (const :tag "C eval-light: Evaluate inbuffer-code on demand" org-eval-light)
8bfe682a 312 (const :tag "C expiry: Expiry mechanism for Org-mode entries" org-expiry)
c8d0cf5c 313 (const :tag "C exp-bibtex: Export citations using BibTeX" org-exp-bibtex)
8bfe682a 314 (const :tag "C git-link: Provide org links to specific file version" org-git-link)
8d642074
CD
315 (const :tag "C interactive-query: Interactive modification of tags query\n\t\t\t(PARTIALLY OBSOLETE, see secondary filtering)" org-interactive-query)
316
8bfe682a 317 (const :tag "C invoice: Help manage client invoices in Org-mode" org-invoice)
8d642074 318
8bfe682a
CD
319 (const :tag "C jira: Add a jira:ticket protocol to Org-mode" org-jira)
320 (const :tag "C learn: SuperMemo's incremental learning algorithm" org-learn)
321 (const :tag "C mairix: Hook mairix search into Org-mode for different MUAs" org-mairix)
c8d0cf5c 322 (const :tag "C mac-iCal Imports events from iCal.app to the Emacs diary" org-mac-iCal)
86fbb8ca 323 (const :tag "C mac-link-grabber Grab links and URLs from various Mac applications" org-mac-link-grabber)
20908596 324 (const :tag "C man: Support for links to manpages in Org-mode" org-man)
b349f79f 325 (const :tag "C mtags: Support for muse-like tags" org-mtags)
20908596 326 (const :tag "C panel: Simple routines for us with bad memory" org-panel)
8bfe682a 327 (const :tag "C registry: A registry for Org-mode links" org-registry)
20908596
CD
328 (const :tag "C org2rem: Convert org appointments into reminders" org2rem)
329 (const :tag "C screen: Visit screen sessions through Org-mode links" org-screen)
ed21c5c8 330 (const :tag "C secretary: Team management with org-mode" org-secretary)
c8d0cf5c 331 (const :tag "C special-blocks: Turn blocks into LaTeX envs and HTML divs" org-special-blocks)
20908596 332 (const :tag "C sqlinsert: Convert Org-mode tables to SQL insertions" orgtbl-sqlinsert)
c8d0cf5c 333 (const :tag "C toc: Table of contents for Org-mode buffer" org-toc)
8bfe682a 334 (const :tag "C track: Keep up with Org-mode development" org-track)
afe98dfa
CD
335 (const :tag "C velocity Something like Notational Velocity for Org" org-velocity)
336 (const :tag "C wikinodes: CamelCase wiki-like links" org-wikinodes)
20908596
CD
337 (repeat :tag "External packages" :inline t (symbol :tag "Package"))))
338
65c439fd 339(defcustom org-support-shift-select nil
ed21c5c8 340 "Non-nil means make shift-cursor commands select text when possible.
65c439fd
CD
341
342In Emacs 23, when `shift-select-mode' is on, shifted cursor keys start
86fbb8ca 343selecting a region, or enlarge regions started in this way.
65c439fd
CD
344In Org-mode, in special contexts, these same keys are used for other
345purposes, important enough to compete with shift selection. Org tries
346to balance these needs by supporting `shift-select-mode' outside these
347special contexts, under control of this variable.
348
349The default of this variable is nil, to avoid confusing behavior. Shifted
350cursor keys will then execute Org commands in the following contexts:
351- on a headline, changing TODO state (left/right) and priority (up/down)
352- on a time stamp, changing the time
353- in a plain list item, changing the bullet type
354- in a property definition line, switching between allowed values
355- in the BEGIN line of a clock table (changing the time block).
356Outside these contexts, the commands will throw an error.
357
358When this variable is t and the cursor is not in a special context,
359Org-mode will support shift-selection for making and enlarging regions.
360To make this more effective, the bullet cycling will no longer happen
361anywhere in an item line, but only if the cursor is exactly on the bullet.
362
363If you set this variable to the symbol `always', then the keys
364will not be special in headlines, property lines, and item lines, to make
365shift selection work there as well. If this is what you want, you can
366use the following alternative commands: `C-c C-t' and `C-c ,' to
367change TODO state and priority, `C-u C-u C-c C-t' can be used to switch
368TODO sets, `C-c -' to cycle item bullet types, and properties can be
369edited by hand or in column view.
370
371However, when the cursor is on a timestamp, shift-cursor commands
372will still edit the time stamp - this is just too good to give up.
373
374XEmacs user should have this variable set to nil, because shift-select-mode
375is Emacs 23 only."
376 :group 'org
377 :type '(choice
378 (const :tag "Never" nil)
379 (const :tag "When outside special context" t)
380 (const :tag "Everywhere except timestamps" always)))
15841868 381
891f4676
RS
382(defgroup org-startup nil
383 "Options concerning startup of Org-mode."
384 :tag "Org Startup"
385 :group 'org)
386
387(defcustom org-startup-folded t
ed21c5c8 388 "Non-nil means entering Org-mode will switch to OVERVIEW.
ef943dba
CD
389This can also be configured on a per-file basis by adding one of
390the following lines anywhere in the buffer:
391
8d642074
CD
392 #+STARTUP: fold (or `overview', this is equivalent)
393 #+STARTUP: nofold (or `showall', this is equivalent)
394 #+STARTUP: content
395 #+STARTUP: showeverything"
891f4676 396 :group 'org-startup
35fb9989 397 :type '(choice
c8d16429
CD
398 (const :tag "nofold: show all" nil)
399 (const :tag "fold: overview" t)
8d642074
CD
400 (const :tag "content: all headlines" content)
401 (const :tag "show everything, even drawers" showeverything)))
891f4676
RS
402
403(defcustom org-startup-truncated t
ed21c5c8 404 "Non-nil means entering Org-mode will set `truncate-lines'.
891f4676
RS
405This is useful since some lines containing links can be very long and
406uninteresting. Also tables look terrible when wrapped."
407 :group 'org-startup
408 :type 'boolean)
409
c8d0cf5c 410(defcustom org-startup-indented nil
ed21c5c8 411 "Non-nil means turn on `org-indent-mode' on startup.
c8d0cf5c
CD
412This can also be configured on a per-file basis by adding one of
413the following lines anywhere in the buffer:
414
415 #+STARTUP: indent
416 #+STARTUP: noindent"
417 :group 'org-structure
418 :type '(choice
419 (const :tag "Not" nil)
420 (const :tag "Globally (slow on startup in large files)" t)))
421
86fbb8ca
CD
422(defcustom org-use-sub-superscripts t
423 "Non-nil means interpret \"_\" and \"^\" for export.
424When this option is turned on, you can use TeX-like syntax for sub- and
425superscripts. Several characters after \"_\" or \"^\" will be
426considered as a single item - so grouping with {} is normally not
427needed. For example, the following things will be parsed as single
428sub- or superscripts.
429
430 10^24 or 10^tau several digits will be considered 1 item.
431 10^-12 or 10^-tau a leading sign with digits or a word
432 x^2-y^3 will be read as x^2 - y^3, because items are
433 terminated by almost any nonword/nondigit char.
434 x_{i^2} or x^(2-i) braces or parenthesis do grouping.
435
436Still, ambiguity is possible - so when in doubt use {} to enclose the
437sub/superscript. If you set this variable to the symbol `{}',
438the braces are *required* in order to trigger interpretations as
439sub/superscript. This can be helpful in documents that need \"_\"
440frequently in plain text.
441
442Not all export backends support this, but HTML does.
443
444This option can also be set with the +OPTIONS line, e.g. \"^:nil\"."
445 :group 'org-startup
446 :group 'org-export-translation
447 :type '(choice
448 (const :tag "Always interpret" t)
449 (const :tag "Only with braces" {})
450 (const :tag "Never interpret" nil)))
451
452(if (fboundp 'defvaralias)
453 (defvaralias 'org-export-with-sub-superscripts 'org-use-sub-superscripts))
454
455
ed21c5c8
CD
456(defcustom org-startup-with-beamer-mode nil
457 "Non-nil means turn on `org-beamer-mode' on startup.
458This can also be configured on a per-file basis by adding one of
459the following lines anywhere in the buffer:
460
461 #+STARTUP: beamer"
462 :group 'org-startup
463 :type 'boolean)
464
ab27a4a0 465(defcustom org-startup-align-all-tables nil
ed21c5c8 466 "Non-nil means align all tables when visiting a file.
ab27a4a0 467This is useful when the column width in tables is forced with <N> cookies
4146eb16
CD
468in table fields. Such tables will look correct only after the first re-align.
469This can also be configured on a per-file basis by adding one of
470the following lines anywhere in the buffer:
471 #+STARTUP: align
472 #+STARTUP: noalign"
ab27a4a0
CD
473 :group 'org-startup
474 :type 'boolean)
475
afe98dfa
CD
476(defcustom org-startup-with-inline-images nil
477 "Non-nil means show inline images when loading a new Org file.
478This can also be configured on a per-file basis by adding one of
479the following lines anywhere in the buffer:
480 #+STARTUP: inlineimages
481 #+STARTUP: noinlineimages"
482 :group 'org-startup
483 :type 'boolean)
484
c52dbe8c 485(defcustom org-insert-mode-line-in-empty-file nil
891f4676 486 "Non-nil means insert the first line setting Org-mode in empty files.
35fb9989 487When the function `org-mode' is called interactively in an empty file, this
891f4676
RS
488normally means that the file name does not automatically trigger Org-mode.
489To ensure that the file will always be in Org-mode in the future, a
35fb9989
CD
490line enforcing Org-mode will be inserted into the buffer, if this option
491has been set."
891f4676
RS
492 :group 'org-startup
493 :type 'boolean)
494
a3fbe8c4
CD
495(defcustom org-replace-disputed-keys nil
496 "Non-nil means use alternative key bindings for some keys.
497Org-mode uses S-<cursor> keys for changing timestamps and priorities.
c8d0cf5c
CD
498These keys are also used by other packages like shift-selection-mode'
499\(built into Emacs 23), `CUA-mode' or `windmove.el'.
a3fbe8c4
CD
500If you want to use Org-mode together with one of these other modes,
501or more generally if you would like to move some Org-mode commands to
502other keys, set this variable and configure the keys with the variable
ab27a4a0 503`org-disputed-keys'.
891f4676 504
d3f4dbe8
CD
505This option is only relevant at load-time of Org-mode, and must be set
506*before* org.el is loaded. Changing it requires a restart of Emacs to
507become effective."
ab27a4a0
CD
508 :group 'org-startup
509 :type 'boolean)
891f4676 510
621f83e4 511(defcustom org-use-extra-keys nil
86fbb8ca
CD
512 "Non-nil means use extra key sequence definitions for certain commands.
513This happens automatically if you run XEmacs or if `window-system'
514is nil. This variable lets you do the same manually. You must
515set it before loading org.
621f83e4
CD
516
517Example: on Carbon Emacs 22 running graphically, with an external
518keyboard on a Powerbook, the default way of setting M-left might
519not work for either Alt or ESC. Setting this variable will make
520it work for ESC."
521 :group 'org-startup
522 :type 'boolean)
523
a3fbe8c4
CD
524(if (fboundp 'defvaralias)
525 (defvaralias 'org-CUA-compatible 'org-replace-disputed-keys))
526
527(defcustom org-disputed-keys
528 '(([(shift up)] . [(meta p)])
529 ([(shift down)] . [(meta n)])
530 ([(shift left)] . [(meta -)])
531 ([(shift right)] . [(meta +)])
532 ([(control shift right)] . [(meta shift +)])
533 ([(control shift left)] . [(meta shift -)]))
ab27a4a0 534 "Keys for which Org-mode and other modes compete.
a3fbe8c4
CD
535This is an alist, cars are the default keys, second element specifies
536the alternative to use when `org-replace-disputed-keys' is t.
537
538Keys can be specified in any syntax supported by `define-key'.
539The value of this option takes effect only at Org-mode's startup,
540therefore you'll have to restart Emacs to apply it after changing."
541 :group 'org-startup
542 :type 'alist)
ab27a4a0
CD
543
544(defun org-key (key)
a3fbe8c4 545 "Select key according to `org-replace-disputed-keys' and `org-disputed-keys'.
86fbb8ca
CD
546Or return the original if not disputed.
547Also apply the translations defined in `org-xemacs-key-equivalents'."
548 (when org-replace-disputed-keys
549 (let* ((nkey (key-description key))
550 (x (org-find-if (lambda (x)
551 (equal (key-description (car x)) nkey))
552 org-disputed-keys)))
553 (setq key (if x (cdr x) key))))
554 (when (featurep 'xemacs)
555 (setq key (or (cdr (assoc key org-xemacs-key-equivalents)) key)))
556 key)
a3fbe8c4
CD
557
558(defun org-find-if (predicate seq)
559 (catch 'exit
560 (while seq
561 (if (funcall predicate (car seq))
562 (throw 'exit (car seq))
563 (pop seq)))))
564
565(defun org-defkey (keymap key def)
566 "Define a key, possibly translated, as returned by `org-key'."
567 (define-key keymap (org-key key) def))
ab27a4a0 568
8c6fb58b 569(defcustom org-ellipsis nil
ab27a4a0
CD
570 "The ellipsis to use in the Org-mode outline.
571When nil, just use the standard three dots. When a string, use that instead,
33306645 572When a face, use the standard 3 dots, but with the specified face.
374585c9 573The change affects only Org-mode (which will then use its own display table).
ab27a4a0
CD
574Changing this requires executing `M-x org-mode' in a buffer to become
575effective."
576 :group 'org-startup
577 :type '(choice (const :tag "Default" nil)
374585c9 578 (face :tag "Face" :value org-warning)
ab27a4a0
CD
579 (string :tag "String" :value "...#")))
580
581(defvar org-display-table nil
582 "The display table for org-mode, in case `org-ellipsis' is non-nil.")
583
584(defgroup org-keywords nil
585 "Keywords in Org-mode."
586 :tag "Org Keywords"
587 :group 'org)
891f4676
RS
588
589(defcustom org-deadline-string "DEADLINE:"
590 "String to mark deadline entries.
591A deadline is this string, followed by a time stamp. Should be a word,
592terminated by a colon. You can insert a schedule keyword and
593a timestamp with \\[org-deadline].
594Changes become only effective after restarting Emacs."
595 :group 'org-keywords
596 :type 'string)
597
598(defcustom org-scheduled-string "SCHEDULED:"
599 "String to mark scheduled TODO entries.
600A schedule is this string, followed by a time stamp. Should be a word,
601terminated by a colon. You can insert a schedule keyword and
602a timestamp with \\[org-schedule].
603Changes become only effective after restarting Emacs."
604 :group 'org-keywords
605 :type 'string)
606
7ac93e3c 607(defcustom org-closed-string "CLOSED:"
b0a10108 608 "String used as the prefix for timestamps logging closing a TODO entry."
7ac93e3c
CD
609 :group 'org-keywords
610 :type 'string)
611
edd21304
CD
612(defcustom org-clock-string "CLOCK:"
613 "String used as prefix for timestamps clocking work hours on an item."
614 :group 'org-keywords
615 :type 'string)
616
891f4676
RS
617(defcustom org-comment-string "COMMENT"
618 "Entries starting with this keyword will never be exported.
619An entry can be toggled between COMMENT and normal with
620\\[org-toggle-comment].
621Changes become only effective after restarting Emacs."
622 :group 'org-keywords
623 :type 'string)
624
b9661543
CD
625(defcustom org-quote-string "QUOTE"
626 "Entries starting with this keyword will be exported in fixed-width font.
627Quoting applies only to the text in the entry following the headline, and does
628not extend beyond the next headline, even if that is lower level.
629An entry can be toggled between QUOTE and normal with
b0a10108 630\\[org-toggle-fixed-width-section]."
b9661543
CD
631 :group 'org-keywords
632 :type 'string)
633
a3fbe8c4 634(defconst org-repeat-re
8bfe682a 635 "<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [^>\n]*?\\([.+]?\\+[0-9]+[dwmy]\\(/[0-9]+[dwmy]\\)?\\)"
d3f4dbe8
CD
636 "Regular expression for specifying repeated events.
637After a match, group 1 contains the repeat expression.")
638
ab27a4a0
CD
639(defgroup org-structure nil
640 "Options concerning the general structure of Org-mode files."
641 :tag "Org Structure"
642 :group 'org)
634a7d0b 643
d3f4dbe8
CD
644(defgroup org-reveal-location nil
645 "Options about how to make context of a location visible."
646 :tag "Org Reveal Location"
647 :group 'org-structure)
648
8c6fb58b
CD
649(defconst org-context-choice
650 '(choice
651 (const :tag "Always" t)
652 (const :tag "Never" nil)
653 (repeat :greedy t :tag "Individual contexts"
654 (cons
655 (choice :tag "Context"
656 (const agenda)
657 (const org-goto)
658 (const occur-tree)
659 (const tags-tree)
660 (const link-search)
661 (const mark-goto)
662 (const bookmark-jump)
663 (const isearch)
664 (const default))
665 (boolean))))
666 "Contexts for the reveal options.")
667
d3f4dbe8 668(defcustom org-show-hierarchy-above '((default . t))
ed21c5c8 669 "Non-nil means show full hierarchy when revealing a location.
d3f4dbe8
CD
670Org-mode often shows locations in an org-mode file which might have
671been invisible before. When this is set, the hierarchy of headings
672above the exposed location is shown.
673Turning this off for example for sparse trees makes them very compact.
674Instead of t, this can also be an alist specifying this option for different
675contexts. Valid contexts are
676 agenda when exposing an entry from the agenda
677 org-goto when using the command `org-goto' on key C-c C-j
678 occur-tree when using the command `org-occur' on key C-c /
679 tags-tree when constructing a sparse tree based on tags matches
680 link-search when exposing search matches associated with a link
681 mark-goto when exposing the jump goal of a mark
682 bookmark-jump when exposing a bookmark location
683 isearch when exiting from an incremental search
684 default default for all contexts not set explicitly"
685 :group 'org-reveal-location
8c6fb58b 686 :type org-context-choice)
d3f4dbe8 687
a3fbe8c4 688(defcustom org-show-following-heading '((default . nil))
ed21c5c8 689 "Non-nil means show following heading when revealing a location.
d3f4dbe8
CD
690Org-mode often shows locations in an org-mode file which might have
691been invisible before. When this is set, the heading following the
692match is shown.
693Turning this off for example for sparse trees makes them very compact,
694but makes it harder to edit the location of the match. In such a case,
695use the command \\[org-reveal] to show more context.
696Instead of t, this can also be an alist specifying this option for different
697contexts. See `org-show-hierarchy-above' for valid contexts."
698 :group 'org-reveal-location
8c6fb58b 699 :type org-context-choice)
d3f4dbe8
CD
700
701(defcustom org-show-siblings '((default . nil) (isearch t))
ed21c5c8 702 "Non-nil means show all sibling heading when revealing a location.
d3f4dbe8
CD
703Org-mode often shows locations in an org-mode file which might have
704been invisible before. When this is set, the sibling of the current entry
705heading are all made visible. If `org-show-hierarchy-above' is t,
706the same happens on each level of the hierarchy above the current entry.
707
708By default this is on for the isearch context, off for all other contexts.
709Turning this off for example for sparse trees makes them very compact,
710but makes it harder to edit the location of the match. In such a case,
711use the command \\[org-reveal] to show more context.
712Instead of t, this can also be an alist specifying this option for different
713contexts. See `org-show-hierarchy-above' for valid contexts."
714 :group 'org-reveal-location
8c6fb58b
CD
715 :type org-context-choice)
716
717(defcustom org-show-entry-below '((default . nil))
ed21c5c8 718 "Non-nil means show the entry below a headline when revealing a location.
8c6fb58b
CD
719Org-mode often shows locations in an org-mode file which might have
720been invisible before. When this is set, the text below the headline that is
721exposed is also shown.
722
723By default this is off for all contexts.
724Instead of t, this can also be an alist specifying this option for different
725contexts. See `org-show-hierarchy-above' for valid contexts."
726 :group 'org-reveal-location
727 :type org-context-choice)
d3f4dbe8 728
20908596
CD
729(defcustom org-indirect-buffer-display 'other-window
730 "How should indirect tree buffers be displayed?
731This applies to indirect buffers created with the commands
732\\[org-tree-to-indirect-buffer] and \\[org-agenda-tree-to-indirect-buffer].
733Valid values are:
734current-window Display in the current window
735other-window Just display in another window.
736dedicated-frame Create one new frame, and re-use it each time.
737new-frame Make a new frame each time. Note that in this case
738 previously-made indirect buffers are kept, and you need to
739 kill these buffers yourself."
740 :group 'org-structure
741 :group 'org-agenda-windows
742 :type '(choice
743 (const :tag "In current window" current-window)
744 (const :tag "In current frame, other window" other-window)
745 (const :tag "Each time a new frame" new-frame)
746 (const :tag "One dedicated frame" dedicated-frame)))
747
8bfe682a 748(defcustom org-use-speed-commands nil
ed21c5c8 749 "Non-nil means activate single letter commands at beginning of a headline.
1bcdebed
CD
750This may also be a function to test for appropriate locations where speed
751commands should be active."
8bfe682a 752 :group 'org-structure
1bcdebed
CD
753 :type '(choice
754 (const :tag "Never" nil)
755 (const :tag "At beginning of headline stars" t)
756 (function)))
8bfe682a
CD
757
758(defcustom org-speed-commands-user nil
759 "Alist of additional speed commands.
760This list will be checked before `org-speed-commands-default'
761when the variable `org-use-speed-commands' is non-nil
762and when the cursor is at the beginning of a headline.
763The car if each entry is a string with a single letter, which must
764be assigned to `self-insert-command' in the global map.
765The cdr is either a command to be called interactively, a function
1bcdebed
CD
766to be called, or a form to be evaluated.
767An entry that is just a list with a single string will be interpreted
768as a descriptive headline that will be added when listing the speed
86fbb8ca 769commands in the Help buffer using the `?' speed command."
8bfe682a 770 :group 'org-structure
1bcdebed
CD
771 :type '(repeat :value ("k" . ignore)
772 (choice :value ("k" . ignore)
773 (list :tag "Descriptive Headline" (string :tag "Headline"))
774 (cons :tag "Letter and Command"
775 (string :tag "Command letter")
776 (choice
777 (function)
778 (sexp))))))
8bfe682a 779
ab27a4a0
CD
780(defgroup org-cycle nil
781 "Options concerning visibility cycling in Org-mode."
782 :tag "Org Cycle"
783 :group 'org-structure)
634a7d0b 784
c8d0cf5c 785(defcustom org-cycle-skip-children-state-if-no-children t
ed21c5c8 786 "Non-nil means skip CHILDREN state in entries that don't have any."
c8d0cf5c
CD
787 :group 'org-cycle
788 :type 'boolean)
789
790(defcustom org-cycle-max-level nil
791 "Maximum level which should still be subject to visibility cycling.
792Levels higher than this will, for cycling, be treated as text, not a headline.
793When `org-odd-levels-only' is set, a value of N in this variable actually
794means 2N-1 stars as the limiting headline.
795When nil, cycle all levels.
796Note that the limiting level of cycling is also influenced by
797`org-inlinetask-min-level'. When `org-cycle-max-level' is not set but
798`org-inlinetask-min-level' is, cycling will be limited to levels one less
799than its value."
800 :group 'org-cycle
801 :type '(choice
802 (const :tag "No limit" nil)
803 (integer :tag "Maximum level")))
804
805(defcustom org-drawers '("PROPERTIES" "CLOCK" "LOGBOOK")
5152b597
CD
806 "Names of drawers. Drawers are not opened by cycling on the headline above.
807Drawers only open with a TAB on the drawer line itself. A drawer looks like
808this:
809 :DRAWERNAME:
810 .....
38f8646b
CD
811 :END:
812The drawer \"PROPERTIES\" is special for capturing properties through
03f3cf35
JW
813the property API.
814
815Drawers can be defined on the per-file basis with a line like:
816
817#+DRAWERS: HIDDEN STATE PROPERTIES"
5152b597 818 :group 'org-structure
c8d0cf5c 819 :group 'org-cycle
5152b597
CD
820 :type '(repeat (string :tag "Drawer Name")))
821
c8d0cf5c 822(defcustom org-hide-block-startup nil
ed21c5c8 823 "Non-nil means entering Org-mode will fold all blocks.
c8d0cf5c
CD
824This can also be set in on a per-file basis with
825
826#+STARTUP: hideblocks
827#+STARTUP: showblocks"
828 :group 'org-startup
829 :group 'org-cycle
830 :type 'boolean)
831
374585c9 832(defcustom org-cycle-global-at-bob nil
4b3a9ba7
CD
833 "Cycle globally if cursor is at beginning of buffer and not at a headline.
834This makes it possible to do global cycling without having to use S-TAB or
86fbb8ca
CD
835\\[universal-argument] TAB. For this special case to work, the first line \
836of the buffer
20106e31 837must not be a headline - it may be empty or some other text. When used in
4b3a9ba7
CD
838this way, `org-cycle-hook' is disables temporarily, to make sure the
839cursor stays at the beginning of the buffer.
840When this option is nil, don't do anything special at the beginning
841of the buffer."
842 :group 'org-cycle
843 :type 'boolean)
844
8bfe682a 845(defcustom org-cycle-level-after-item/entry-creation t
ed21c5c8 846 "Non-nil means cycle entry level or item indentation in new empty entries.
8bfe682a
CD
847
848When the cursor is at the end of an empty headline, i.e with only stars
849and maybe a TODO keyword, TAB will then switch the entry to become a child,
86fbb8ca 850and then all possible ancestor states, before returning to the original state.
8bfe682a
CD
851This makes data entry extremely fast: M-RET to create a new headline,
852on TAB to make it a child, two or more tabs to make it a (grand-)uncle.
853
854When the cursor is at the end of an empty plain list item, one TAB will
855make it a subitem, two or more tabs will back up to make this an item
856higher up in the item hierarchy."
857 :group 'org-cycle
858 :type 'boolean)
859
ab27a4a0
CD
860(defcustom org-cycle-emulate-tab t
861 "Where should `org-cycle' emulate TAB.
7d143c25
CD
862nil Never
863white Only in completely white lines
a0d892d4 864whitestart Only at the beginning of lines, before the first non-white char
7d143c25 865t Everywhere except in headlines
a3fbe8c4 866exc-hl-bol Everywhere except at the start of a headline
7d143c25
CD
867If TAB is used in a place where it does not emulate TAB, the current subtree
868visibility is cycled."
ab27a4a0
CD
869 :group 'org-cycle
870 :type '(choice (const :tag "Never" nil)
871 (const :tag "Only in completely white lines" white)
7d143c25 872 (const :tag "Before first char in a line" whitestart)
ab27a4a0 873 (const :tag "Everywhere except in headlines" t)
a3fbe8c4 874 (const :tag "Everywhere except at bol in headlines" exc-hl-bol)
ab27a4a0 875 ))
094f65d4 876
a3fbe8c4
CD
877(defcustom org-cycle-separator-lines 2
878 "Number of empty lines needed to keep an empty line between collapsed trees.
879If you leave an empty line between the end of a subtree and the following
880headline, this empty line is hidden when the subtree is folded.
881Org-mode will leave (exactly) one empty line visible if the number of
882empty lines is equal or larger to the number given in this variable.
ed21c5c8 883So the default 2 means at least 2 empty lines after the end of a subtree
a3fbe8c4
CD
884are needed to produce free space between a collapsed subtree and the
885following headline.
886
54a0dee5
CD
887If the number is negative, and the number of empty lines is at least -N,
888all empty lines are shown.
889
a3fbe8c4
CD
890Special case: when 0, never leave empty lines in collapsed view."
891 :group 'org-cycle
892 :type 'integer)
621f83e4 893(put 'org-cycle-separator-lines 'safe-local-variable 'integerp)
a3fbe8c4 894
c8d0cf5c
CD
895(defcustom org-pre-cycle-hook nil
896 "Hook that is run before visibility cycling is happening.
897The function(s) in this hook must accept a single argument which indicates
898the new state that will be set right after running this hook. The
899argument is a symbol. Before a global state change, it can have the values
900`overview', `content', or `all'. Before a local state change, it can have
901the values `folded', `children', or `subtree'."
902 :group 'org-cycle
903 :type 'hook)
904
6769c0dc 905(defcustom org-cycle-hook '(org-cycle-hide-archived-subtrees
5152b597 906 org-cycle-hide-drawers
a3fbe8c4 907 org-cycle-show-empty-lines
6769c0dc 908 org-optimize-window-after-visibility-change)
ab27a4a0
CD
909 "Hook that is run after `org-cycle' has changed the buffer visibility.
910The function(s) in this hook must accept a single argument which indicates
911the new state that was set by the most recent `org-cycle' command. The
912argument is a symbol. After a global state change, it can have the values
913`overview', `content', or `all'. After a local state change, it can have
914the values `folded', `children', or `subtree'."
915 :group 'org-cycle
916 :type 'hook)
094f65d4 917
ab27a4a0
CD
918(defgroup org-edit-structure nil
919 "Options concerning structure editing in Org-mode."
920 :tag "Org Edit Structure"
921 :group 'org-structure)
634a7d0b 922
2a57416f 923(defcustom org-odd-levels-only nil
ed21c5c8 924 "Non-nil means skip even levels and only use odd levels for the outline.
2a57416f
CD
925This has the effect that two stars are being added/taken away in
926promotion/demotion commands. It also influences how levels are
927handled by the exporters.
928Changing it requires restart of `font-lock-mode' to become effective
929for fontification also in regions already fontified.
930You may also set this on a per-file basis by adding one of the following
931lines to the buffer:
932
933 #+STARTUP: odd
934 #+STARTUP: oddeven"
935 :group 'org-edit-structure
ed21c5c8 936 :group 'org-appearance
2a57416f
CD
937 :type 'boolean)
938
939(defcustom org-adapt-indentation t
ed21c5c8 940 "Non-nil means adapt indentation to outline node level.
c8d0cf5c
CD
941
942When this variable is set, Org assumes that you write outlines by
943indenting text in each node to align with the headline (after the stars).
944The following issues are influenced by this variable:
945
946- When this is set and the *entire* text in an entry is indented, the
947 indentation is increased by one space in a demotion command, and
948 decreased by one in a promotion command. If any line in the entry
949 body starts with text at column 0, indentation is not changed at all.
950
951- Property drawers and planning information is inserted indented when
952 this variable s set. When nil, they will not be indented.
953
954- TAB indents a line relative to context. The lines below a headline
955 will be indented when this variable is set.
956
957Note that this is all about true indentation, by adding and removing
958space characters. See also `org-indent.el' which does level-dependent
959indentation in a virtual way, i.e. at display time in Emacs."
2a57416f
CD
960 :group 'org-edit-structure
961 :type 'boolean)
962
1e8fbb6d 963(defcustom org-special-ctrl-a/e nil
48aaad2d 964 "Non-nil means `C-a' and `C-e' behave specially in headlines and items.
c8d0cf5c 965
374585c9 966When t, `C-a' will bring back the cursor to the beginning of the
a3fbe8c4 967headline text, i.e. after the stars and after a possible TODO keyword.
48aaad2d 968In an item, this will be the position after the bullet.
a3fbe8c4 969When the cursor is already at that position, another `C-a' will bring
1e8fbb6d 970it to the beginning of the line.
c8d0cf5c 971
1e8fbb6d
CD
972`C-e' will jump to the end of the headline, ignoring the presence of tags
973in the headline. A second `C-e' will then jump to the true end of the
8d642074
CD
974line, after any tags. This also means that, when this variable is
975non-nil, `C-e' also will never jump beyond the end of the heading of a
976folded section, i.e. not after the ellipses.
c8d0cf5c 977
374585c9 978When set to the symbol `reversed', the first `C-a' or `C-e' works normally,
c8d0cf5c
CD
979going to the true line boundary first. Only a directly following, identical
980keypress will bring the cursor to the special positions.
981
982This may also be a cons cell where the behavior for `C-a' and `C-e' is
983set separately."
a3fbe8c4 984 :group 'org-edit-structure
374585c9
CD
985 :type '(choice
986 (const :tag "off" nil)
8d642074
CD
987 (const :tag "on: after stars/bullet and before tags first" t)
988 (const :tag "reversed: true line boundary first" reversed)
c8d0cf5c
CD
989 (cons :tag "Set C-a and C-e separately"
990 (choice :tag "Special C-a"
991 (const :tag "off" nil)
8d642074
CD
992 (const :tag "on: after stars/bullet first" t)
993 (const :tag "reversed: before stars/bullet first" reversed))
c8d0cf5c
CD
994 (choice :tag "Special C-e"
995 (const :tag "off" nil)
8d642074
CD
996 (const :tag "on: before tags first" t)
997 (const :tag "reversed: after tags first" reversed)))))
1e8fbb6d
CD
998(if (fboundp 'defvaralias)
999 (defvaralias 'org-special-ctrl-a 'org-special-ctrl-a/e))
1000
2a57416f
CD
1001(defcustom org-special-ctrl-k nil
1002 "Non-nil means `C-k' will behave specially in headlines.
1003When nil, `C-k' will call the default `kill-line' command.
1004When t, the following will happen while the cursor is in the headline:
4146eb16 1005
2a57416f
CD
1006- When the cursor is at the beginning of a headline, kill the entire
1007 line and possible the folded subtree below the line.
1008- When in the middle of the headline text, kill the headline up to the tags.
1009- When after the headline text, kill the tags."
ab27a4a0 1010 :group 'org-edit-structure
ab27a4a0 1011 :type 'boolean)
891f4676 1012
86fbb8ca
CD
1013(defcustom org-ctrl-k-protect-subtree nil
1014 "Non-nil means, do not delete a hidden subtree with C-k.
1015When set to the symbol `error', simply throw an error when C-k is
1016used to kill (part-of) a headline that has hidden text behind it.
1017Any other non-nil value will result in a query to the user, if it is
1018OK to kill that hidden subtree. When nil, kill without remorse."
1019 :group 'org-edit-structure
1020 :type '(choice
1021 (const :tag "Do not protect hidden subtrees" nil)
1022 (const :tag "Protect hidden subtrees with a security query" t)
1023 (const :tag "Never kill a hidden subtree with C-k" error)))
1024
621f83e4 1025(defcustom org-yank-folded-subtrees t
ed21c5c8 1026 "Non-nil means when yanking subtrees, fold them.
621f83e4
CD
1027If the kill is a single subtree, or a sequence of subtrees, i.e. if
1028it starts with a heading and all other headings in it are either children
93b62de8
CD
1029or siblings, then fold all the subtrees. However, do this only if no
1030text after the yank would be swallowed into a folded tree by this action."
1031 :group 'org-edit-structure
1032 :type 'boolean)
1033
5ace2fe5 1034(defcustom org-yank-adjusted-subtrees nil
ed21c5c8 1035 "Non-nil means when yanking subtrees, adjust the level.
93b62de8
CD
1036With this setting, `org-paste-subtree' is used to insert the subtree, see
1037this function for details."
621f83e4
CD
1038 :group 'org-edit-structure
1039 :type 'boolean)
1040
2a57416f 1041(defcustom org-M-RET-may-split-line '((default . t))
ed21c5c8 1042 "Non-nil means M-RET will split the line at the cursor position.
2a57416f
CD
1043When nil, it will go to the end of the line before making a
1044new line.
1045You may also set this option in a different way for different
1046contexts. Valid contexts are:
1047
1048headline when creating a new headline
1049item when creating a new item
1050table in a table field
1051default the value to be used for all contexts not explicitly
1052 customized"
1053 :group 'org-structure
1054 :group 'org-table
1055 :type '(choice
1056 (const :tag "Always" t)
1057 (const :tag "Never" nil)
1058 (repeat :greedy t :tag "Individual contexts"
1059 (cons
1060 (choice :tag "Context"
1061 (const headline)
1062 (const item)
1063 (const table)
1064 (const default))
1065 (boolean)))))
1066
30313b90 1067
621f83e4 1068(defcustom org-insert-heading-respect-content nil
ed21c5c8 1069 "Non-nil means insert new headings after the current subtree.
621f83e4
CD
1070When nil, the new heading is created directly after the current line.
1071The commands \\[org-insert-heading-respect-content] and
1072\\[org-insert-todo-heading-respect-content] turn this variable on
1073for the duration of the command."
1074 :group 'org-structure
1075 :type 'boolean)
1076
0bd48b37
CD
1077(defcustom org-blank-before-new-entry '((heading . auto)
1078 (plain-list-item . auto))
3278a016
CD
1079 "Should `org-insert-heading' leave a blank line before new heading/item?
1080The value is an alist, with `heading' and `plain-list-item' as car,
01c35094 1081and a boolean flag as cdr. The cdr may lso be the symbol `auto', and then
afe98dfa
CD
1082Org will look at the surrounding headings/items and try to make an
1083intelligent decision wether to insert a blank line or not.
1084
1085For plain lists, if the variable `org-empty-line-terminates-plain-lists' is
1086set, the setting here is ignored and no empty line is inserted, to avoid
1087breaking the list structure."
3278a016
CD
1088 :group 'org-edit-structure
1089 :type '(list
0bd48b37
CD
1090 (cons (const heading)
1091 (choice (const :tag "Never" nil)
1092 (const :tag "Always" t)
1093 (const :tag "Auto" auto)))
1094 (cons (const plain-list-item)
1095 (choice (const :tag "Never" nil)
1096 (const :tag "Always" t)
1097 (const :tag "Auto" auto)))))
3278a016 1098
4b3a9ba7
CD
1099(defcustom org-insert-heading-hook nil
1100 "Hook being run after inserting a new heading."
1101 :group 'org-edit-structure
8c6fb58b 1102 :type 'hook)
4b3a9ba7 1103
ab27a4a0 1104(defcustom org-enable-fixed-width-editor t
ed21c5c8
CD
1105 "Non-nil means lines starting with \":\" are treated as fixed-width.
1106This currently only means they are never auto-wrapped.
ab27a4a0
CD
1107When nil, such lines will be treated like ordinary lines.
1108See also the QUOTE keyword."
1109 :group 'org-edit-structure
1110 :type 'boolean)
30313b90 1111
2a57416f 1112(defcustom org-goto-auto-isearch t
86fbb8ca 1113 "Non-nil means typing characters in `org-goto' starts incremental search."
2a57416f
CD
1114 :group 'org-edit-structure
1115 :type 'boolean)
1116
ab27a4a0
CD
1117(defgroup org-sparse-trees nil
1118 "Options concerning sparse trees in Org-mode."
1119 :tag "Org Sparse Trees"
1120 :group 'org-structure)
891f4676 1121
ab27a4a0 1122(defcustom org-highlight-sparse-tree-matches t
ed21c5c8 1123 "Non-nil means highlight all matches that define a sparse tree.
ab27a4a0
CD
1124The highlights will automatically disappear the next time the buffer is
1125changed by an edit command."
1126 :group 'org-sparse-trees
15f43010 1127 :type 'boolean)
891f4676 1128
3278a016 1129(defcustom org-remove-highlights-with-change t
ed21c5c8 1130 "Non-nil means any change to the buffer will remove temporary highlights.
3278a016
CD
1131Such highlights are created by `org-occur' and `org-clock-display'.
1132When nil, `C-c C-c needs to be used to get rid of the highlights.
1133The highlights created by `org-preview-latex-fragment' always need
1134`C-c C-c' to be removed."
ab27a4a0 1135 :group 'org-sparse-trees
3278a016 1136 :group 'org-time
891f4676
RS
1137 :type 'boolean)
1138
7ac93e3c 1139
ab27a4a0
CD
1140(defcustom org-occur-hook '(org-first-headline-recenter)
1141 "Hook that is run after `org-occur' has constructed a sparse tree.
1142This can be used to recenter the window to show as much of the structure
1143as possible."
1144 :group 'org-sparse-trees
1145 :type 'hook)
d924f2e5 1146
8c6fb58b
CD
1147(defgroup org-imenu-and-speedbar nil
1148 "Options concerning imenu and speedbar in Org-mode."
1149 :tag "Org Imenu and Speedbar"
1150 :group 'org-structure)
1151
1152(defcustom org-imenu-depth 2
1153 "The maximum level for Imenu access to Org-mode headlines.
1154This also applied for speedbar access."
1155 :group 'org-imenu-and-speedbar
c8d0cf5c 1156 :type 'integer)
8c6fb58b 1157
ab27a4a0
CD
1158(defgroup org-table nil
1159 "Options concerning tables in Org-mode."
1160 :tag "Org Table"
1161 :group 'org)
eb2f9c59 1162
ab27a4a0 1163(defcustom org-enable-table-editor 'optimized
ed21c5c8 1164 "Non-nil means lines starting with \"|\" are handled by the table editor.
ab27a4a0 1165When nil, such lines will be treated like ordinary lines.
eb2f9c59 1166
ab27a4a0
CD
1167When equal to the symbol `optimized', the table editor will be optimized to
1168do the following:
3278a016
CD
1169- Automatic overwrite mode in front of whitespace in table fields.
1170 This makes the structure of the table stay in tact as long as the edited
ab27a4a0
CD
1171 field does not exceed the column width.
1172- Minimize the number of realigns. Normally, the table is aligned each time
1173 TAB or RET are pressed to move to another field. With optimization this
1174 happens only if changes to a field might have changed the column width.
1175Optimization requires replacing the functions `self-insert-command',
1176`delete-char', and `backward-delete-char' in Org-mode buffers, with a
1177slight (in fact: unnoticeable) speed impact for normal typing. Org-mode is
1178very good at guessing when a re-align will be necessary, but you can always
1179force one with \\[org-ctrl-c-ctrl-c].
eb2f9c59 1180
ab27a4a0
CD
1181If you would like to use the optimized version in Org-mode, but the
1182un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'.
eb2f9c59 1183
ab27a4a0
CD
1184This variable can be used to turn on and off the table editor during a session,
1185but in order to toggle optimization, a restart is required.
634a7d0b 1186
ab27a4a0
CD
1187See also the variable `org-table-auto-blank-field'."
1188 :group 'org-table
1189 :type '(choice
1190 (const :tag "off" nil)
1191 (const :tag "on" t)
1192 (const :tag "on, optimized" optimized)))
634a7d0b 1193
c8d0cf5c
CD
1194(defcustom org-self-insert-cluster-for-undo t
1195 "Non-nil means cluster self-insert commands for undo when possible.
8bfe682a 1196If this is set, then, like in the Emacs command loop, 20 consecutive
c8d0cf5c
CD
1197characters will be undone together.
1198This is configurable, because there is some impact on typing performance."
1199 :group 'org-table
1200 :type 'boolean)
1201
ab27a4a0 1202(defcustom org-table-tab-recognizes-table.el t
ed21c5c8 1203 "Non-nil means TAB will automatically notice a table.el table.
ab27a4a0
CD
1204When it sees such a table, it moves point into it and - if necessary -
1205calls `table-recognize-table'."
1206 :group 'org-table-editing
79c4be8e
CD
1207 :type 'boolean)
1208
891f4676
RS
1209(defgroup org-link nil
1210 "Options concerning links in Org-mode."
1211 :tag "Org Link"
1212 :group 'org)
1213
3278a016 1214(defvar org-link-abbrev-alist-local nil
a3fbe8c4 1215 "Buffer-local version of `org-link-abbrev-alist', which see.
3278a016
CD
1216The value of this is taken from the #+LINK lines.")
1217(make-variable-buffer-local 'org-link-abbrev-alist-local)
1218
1219(defcustom org-link-abbrev-alist nil
1220 "Alist of link abbreviations.
1221The car of each element is a string, to be replaced at the start of a link.
1222The cdrs are replacement values, like (\"linkkey\" . REPLACE). Abbreviated
1223links in Org-mode buffers can have an optional tag after a double colon, e.g.
1224
d3f4dbe8 1225 [[linkkey:tag][description]]
3278a016 1226
c8d0cf5c
CD
1227The 'linkkey' must be a word word, starting with a letter, followed
1228by letters, numbers, '-' or '_'.
1229
3278a016 1230If REPLACE is a string, the tag will simply be appended to create the link.
ce4fdcb9
CD
1231If the string contains \"%s\", the tag will be inserted there. Alternatively,
1232the placeholder \"%h\" will cause a url-encoded version of the tag to
1233be inserted at that point (see the function `url-hexify-string').
8c6fb58b
CD
1234
1235REPLACE may also be a function that will be called with the tag as the
1236only argument to create the link, which should be returned as a string.
1237
1238See the manual for examples."
3278a016 1239 :group 'org-link
93b62de8
CD
1240 :type '(repeat
1241 (cons
1242 (string :tag "Protocol")
1243 (choice
1244 (string :tag "Format")
1245 (function)))))
3278a016 1246
ab27a4a0 1247(defcustom org-descriptive-links t
ed21c5c8 1248 "Non-nil means hide link part and only show description of bracket links.
33306645 1249Bracket links are like [[link][description]]. This variable sets the initial
ab27a4a0
CD
1250state in new org-mode buffers. The setting can then be toggled on a
1251per-buffer basis from the Org->Hyperlinks menu."
4da1a99d
CD
1252 :group 'org-link
1253 :type 'boolean)
1254
4b3a9ba7
CD
1255(defcustom org-link-file-path-type 'adaptive
1256 "How the path name in file links should be stored.
1257Valid values are:
1258
a0d892d4 1259relative Relative to the current directory, i.e. the directory of the file
4b3a9ba7 1260 into which the link is being inserted.
a0d892d4
JB
1261absolute Absolute path, if possible with ~ for home directory.
1262noabbrev Absolute path, no abbreviation of home directory.
4b3a9ba7
CD
1263adaptive Use relative path for files in the current directory and sub-
1264 directories of it. For other files, use an absolute path."
1265 :group 'org-link
1266 :type '(choice
1267 (const relative)
1268 (const absolute)
1269 (const noabbrev)
1270 (const adaptive)))
1271
0bd48b37 1272(defcustom org-activate-links '(bracket angle plain radio tag date footnote)
ab27a4a0
CD
1273 "Types of links that should be activated in Org-mode files.
1274This is a list of symbols, each leading to the activation of a certain link
1275type. In principle, it does not hurt to turn on most link types - there may
1276be a small gain when turning off unused link types. The types are:
1277
1278bracket The recommended [[link][description]] or [[link]] links with hiding.
afe98dfa 1279angle Links in angular brackets that may contain whitespace like
ab27a4a0
CD
1280 <bbdb:Carsten Dominik>.
1281plain Plain links in normal text, no whitespace, like http://google.com.
1282radio Text that is matched by a radio target, see manual for details.
1283tag Tag settings in a headline (link to tag search).
1284date Time stamps (link to calendar).
0bd48b37 1285footnote Footnote labels.
ab27a4a0
CD
1286
1287Changing this variable requires a restart of Emacs to become effective."
a96ee7df 1288 :group 'org-link
0bd48b37 1289 :type '(set :greedy t
afe98dfa
CD
1290 (const :tag "Double bracket links" bracket)
1291 (const :tag "Angular bracket links" angle)
2a57416f 1292 (const :tag "Plain text links" plain)
ab27a4a0
CD
1293 (const :tag "Radio target matches" radio)
1294 (const :tag "Tags" tag)
0bd48b37
CD
1295 (const :tag "Timestamps" date)
1296 (const :tag "Footnotes" footnote)))
ab27a4a0 1297
20908596 1298(defcustom org-make-link-description-function nil
86fbb8ca
CD
1299 "Function to use to generate link descriptions from links.
1300If nil the link location will be used. This function must take
1301two parameters; the first is the link and the second the
1302description `org-insert-link' has generated, and should return the
1303description to use."
20908596
CD
1304 :group 'org-link
1305 :type 'function)
1306
ab27a4a0 1307(defgroup org-link-store nil
5bf7807a 1308 "Options concerning storing links in Org-mode."
ab27a4a0
CD
1309 :tag "Org Store Link"
1310 :group 'org-link)
891f4676 1311
d3f4dbe8
CD
1312(defcustom org-email-link-description-format "Email %c: %.30s"
1313 "Format of the description part of a link to an email or usenet message.
33306645 1314The following %-escapes will be replaced by corresponding information:
d3f4dbe8
CD
1315
1316%F full \"From\" field
1317%f name, taken from \"From\" field, address if no name
1318%T full \"To\" field
1319%t first name in \"To\" field, address if no name
33306645 1320%c correspondent. Usually \"from NAME\", but if you sent it yourself, it
d3f4dbe8
CD
1321 will be \"to NAME\". See also the variable `org-from-is-user-regexp'.
1322%s subject
1323%m message-id.
1324
1325You may use normal field width specification between the % and the letter.
1326This is for example useful to limit the length of the subject.
1327
1328Examples: \"%f on: %.30s\", \"Email from %f\", \"Email %c\""
1329 :group 'org-link-store
1330 :type 'string)
1331
1332(defcustom org-from-is-user-regexp
1333 (let (r1 r2)
1334 (when (and user-mail-address (not (string= user-mail-address "")))
1335 (setq r1 (concat "\\<" (regexp-quote user-mail-address) "\\>")))
1336 (when (and user-full-name (not (string= user-full-name "")))
1337 (setq r2 (concat "\\<" (regexp-quote user-full-name) "\\>")))
1338 (if (and r1 r2) (concat r1 "\\|" r2) (or r1 r2)))
33306645 1339 "Regexp matched against the \"From:\" header of an email or usenet message.
d3f4dbe8
CD
1340It should match if the message is from the user him/herself."
1341 :group 'org-link-store
1342 :type 'regexp)
1343
c8d0cf5c 1344(defcustom org-link-to-org-use-id 'create-if-interactive-and-no-custom-id
ed21c5c8 1345 "Non-nil means storing a link to an Org file will use entry IDs.
db55f368
CD
1346
1347Note that before this variable is even considered, org-id must be loaded,
c8d0cf5c 1348so please customize `org-modules' and turn it on.
db55f368
CD
1349
1350The variable can have the following values:
1351
1352t Create an ID if needed to make a link to the current entry.
1353
1354create-if-interactive
1355 If `org-store-link' is called directly (interactively, as a user
1356 command), do create an ID to support the link. But when doing the
1357 job for remember, only use the ID if it already exists. The
1358 purpose of this setting is to avoid proliferation of unwanted
1359 IDs, just because you happen to be in an Org file when you
1360 call `org-remember' that automatically and preemptively
1361 creates a link. If you do want to get an ID link in a remember
1362 template to an entry not having an ID, create it first by
1363 explicitly creating a link to it, using `C-c C-l' first.
1364
c8d0cf5c
CD
1365create-if-interactive-and-no-custom-id
1366 Like create-if-interactive, but do not create an ID if there is
1367 a CUSTOM_ID property defined in the entry. This is the default.
1368
db55f368
CD
1369use-existing
1370 Use existing ID, do not create one.
1371
1372nil Never use an ID to make a link, instead link using a text search for
1373 the headline text."
1374 :group 'org-link-store
1375 :type '(choice
1376 (const :tag "Create ID to make link" t)
c8d0cf5c
CD
1377 (const :tag "Create if storing link interactively"
1378 create-if-interactive)
1379 (const :tag "Create if storing link interactively and no CUSTOM_ID is present"
1380 create-if-interactive-and-no-custom-id)
1381 (const :tag "Only use existing" use-existing)
db55f368
CD
1382 (const :tag "Do not use ID to create link" nil)))
1383
f425a6ea 1384(defcustom org-context-in-file-links t
ed21c5c8 1385 "Non-nil means file links from `org-store-link' contain context.
a96ee7df 1386A search string will be added to the file name with :: as separator and
01c35094
JB
1387used to find the context when the link is activated by the command
1388`org-open-at-point'. When this option is t, the entire active region
1389will be placed in the search string of the file link. If set to a
acedf35c
CD
1390positive integer, only the first n lines of context will be stored.
1391
891f4676
RS
1392Using a prefix arg to the command \\[org-store-link] (`org-store-link')
1393negates this setting for the duration of the command."
ab27a4a0 1394 :group 'org-link-store
acedf35c 1395 :type '(choice boolean integer))
891f4676
RS
1396
1397(defcustom org-keep-stored-link-after-insertion nil
ed21c5c8 1398 "Non-nil means keep link in list for entire session.
891f4676
RS
1399
1400The command `org-store-link' adds a link pointing to the current
2dd9129f 1401location to an internal list. These links accumulate during a session.
891f4676
RS
1402The command `org-insert-link' can be used to insert links into any
1403Org-mode file (offering completion for all stored links). When this
634a7d0b 1404option is nil, every link which has been inserted once using \\[org-insert-link]
891f4676
RS
1405will be removed from the list, to make completing the unused links
1406more efficient."
ab27a4a0
CD
1407 :group 'org-link-store
1408 :type 'boolean)
1409
ab27a4a0 1410(defgroup org-link-follow nil
5bf7807a 1411 "Options concerning following links in Org-mode."
ab27a4a0
CD
1412 :tag "Org Follow Link"
1413 :group 'org-link)
1414
ce4fdcb9
CD
1415(defcustom org-link-translation-function nil
1416 "Function to translate links with different syntax to Org syntax.
1417This can be used to translate links created for example by the Planner
1418or emacs-wiki packages to Org syntax.
1419The function must accept two parameters, a TYPE containing the link
1420protocol name like \"rmail\" or \"gnus\" as a string, and the linked path,
1421which is everything after the link protocol. It should return a cons
33306645 1422with possibly modified values of type and path.
ce4fdcb9
CD
1423Org contains a function for this, so if you set this variable to
1424`org-translate-link-from-planner', you should be able follow many
1425links created by planner."
1426 :group 'org-link-follow
1427 :type 'function)
1428
2a57416f
CD
1429(defcustom org-follow-link-hook nil
1430 "Hook that is run after a link has been followed."
1431 :group 'org-link-follow
1432 :type 'hook)
1433
ab27a4a0 1434(defcustom org-tab-follows-link nil
ed21c5c8 1435 "Non-nil means on links TAB will follow the link.
c8d0cf5c
CD
1436Needs to be set before org.el is loaded.
1437This really should not be used, it does not make sense, and the
1438implementation is bad."
ab27a4a0
CD
1439 :group 'org-link-follow
1440 :type 'boolean)
1441
cc6dbcb7 1442(defcustom org-return-follows-link nil
86fbb8ca 1443 "Non-nil means on links RET will follow the link."
ab27a4a0 1444 :group 'org-link-follow
891f4676
RS
1445 :type 'boolean)
1446
2a57416f
CD
1447(defcustom org-mouse-1-follows-link
1448 (if (boundp 'mouse-1-click-follows-link) mouse-1-click-follows-link t)
ed21c5c8 1449 "Non-nil means mouse-1 on a link will follow the link.
2a57416f 1450A longer mouse click will still set point. Does not work on XEmacs.
a4b39e39
CD
1451Needs to be set before org.el is loaded."
1452 :group 'org-link-follow
1453 :type 'boolean)
1454
ab27a4a0 1455(defcustom org-mark-ring-length 4
86fbb8ca 1456 "Number of different positions to be recorded in the ring.
ab27a4a0
CD
1457Changing this requires a restart of Emacs to work correctly."
1458 :group 'org-link-follow
33306645 1459 :type 'integer)
ab27a4a0 1460
afe98dfa
CD
1461(defcustom org-link-search-must-match-exact-headline 'query-to-create
1462 "Non-nil means internal links in Org files must exactly match a headline.
1463When nil, the link search tries to match a phrase will all words
1464in the search text."
1465 :group 'org-link-follow
1466 :type '(choice
1467 (const :tag "Use fuzy text search" nil)
1468 (const :tag "Match only exact headline" t)
1469 (const :tag "Match extact headline or query to create it"
1470 query-to-create)))
1471
891f4676
RS
1472(defcustom org-link-frame-setup
1473 '((vm . vm-visit-folder-other-frame)
86fbb8ca
CD
1474 (gnus . org-gnus-no-new-news)
1475 (file . find-file-other-window)
1476 (wl . wl-other-frame))
891f4676
RS
1477 "Setup the frame configuration for following links.
1478When following a link with Emacs, it may often be useful to display
1479this link in another window or frame. This variable can be used to
1480set this up for the different types of links.
1481For VM, use any of
634a7d0b
CD
1482 `vm-visit-folder'
1483 `vm-visit-folder-other-frame'
891f4676 1484For Gnus, use any of
634a7d0b
CD
1485 `gnus'
1486 `gnus-other-frame'
93b62de8 1487 `org-gnus-no-new-news'
891f4676 1488For FILE, use any of
634a7d0b
CD
1489 `find-file'
1490 `find-file-other-window'
1491 `find-file-other-frame'
86fbb8ca
CD
1492For Wanderlust use any of
1493 `wl'
1494 `wl-other-frame'
891f4676
RS
1495For the calendar, use the variable `calendar-setup'.
1496For BBDB, it is currently only possible to display the matches in
1497another window."
ab27a4a0 1498 :group 'org-link-follow
891f4676 1499 :type '(list
c8d16429
CD
1500 (cons (const vm)
1501 (choice
1502 (const vm-visit-folder)
1503 (const vm-visit-folder-other-window)
1504 (const vm-visit-folder-other-frame)))
1505 (cons (const gnus)
1506 (choice
1507 (const gnus)
93b62de8
CD
1508 (const gnus-other-frame)
1509 (const org-gnus-no-new-news)))
c8d16429
CD
1510 (cons (const file)
1511 (choice
1512 (const find-file)
1513 (const find-file-other-window)
86fbb8ca
CD
1514 (const find-file-other-frame)))
1515 (cons (const wl)
1516 (choice
1517 (const wl)
1518 (const wl-other-frame)))))
891f4676 1519
3278a016 1520(defcustom org-display-internal-link-with-indirect-buffer nil
ed21c5c8 1521 "Non-nil means use indirect buffer to display infile links.
3278a016
CD
1522Activating internal links (from one location in a file to another location
1523in the same file) normally just jumps to the location. When the link is
86fbb8ca
CD
1524activated with a \\[universal-argument] prefix (or with mouse-3), the link \
1525is displayed in
3278a016
CD
1526another window. When this option is set, the other window actually displays
1527an indirect buffer clone of the current buffer, to avoid any visibility
1528changes to the current buffer."
1529 :group 'org-link-follow
1530 :type 'boolean)
1531
891f4676 1532(defcustom org-open-non-existing-files nil
ed21c5c8 1533 "Non-nil means `org-open-file' will open non-existing files.
c8d0cf5c
CD
1534When nil, an error will be generated.
1535This variable applies only to external applications because they
1536might choke on non-existing files. If the link is to a file that
8bfe682a 1537will be opened in Emacs, the variable is ignored."
ab27a4a0 1538 :group 'org-link-follow
891f4676
RS
1539 :type 'boolean)
1540
2c3ad40d 1541(defcustom org-open-directory-means-index-dot-org nil
ed21c5c8 1542 "Non-nil means a link to a directory really means to index.org.
2c3ad40d
CD
1543When nil, following a directory link will run dired or open a finder/explorer
1544window on that directory."
1545 :group 'org-link-follow
1546 :type 'boolean)
1547
3278a016
CD
1548(defcustom org-link-mailto-program '(browse-url "mailto:%a?subject=%s")
1549 "Function and arguments to call for following mailto links.
86fbb8ca 1550This is a list with the first element being a Lisp function, and the
3278a016
CD
1551remaining elements being arguments to the function. In string arguments,
1552%a will be replaced by the address, and %s will be replaced by the subject
1553if one was given like in <mailto:arthur@galaxy.org::this subject>."
1554 :group 'org-link-follow
1555 :type '(choice
1556 (const :tag "browse-url" (browse-url-mail "mailto:%a?subject=%s"))
1557 (const :tag "compose-mail" (compose-mail "%a" "%s"))
1558 (const :tag "message-mail" (message-mail "%a" "%s"))
1559 (cons :tag "other" (function) (repeat :tag "argument" sexp))))
1560
4b3a9ba7 1561(defcustom org-confirm-shell-link-function 'yes-or-no-p
ed21c5c8 1562 "Non-nil means ask for confirmation before executing shell links.
03f3cf35 1563Shell links can be dangerous: just think about a link
ab27a4a0
CD
1564
1565 [[shell:rm -rf ~/*][Google Search]]
1566
03f3cf35 1567This link would show up in your Org-mode document as \"Google Search\",
4b3a9ba7 1568but really it would remove your entire home directory.
03f3cf35 1569Therefore we advise against setting this variable to nil.
c8d0cf5c 1570Just change it to `y-or-n-p' if you want to confirm with a
03f3cf35 1571single keystroke rather than having to type \"yes\"."
4b3a9ba7
CD
1572 :group 'org-link-follow
1573 :type '(choice
1574 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1575 (const :tag "with y-or-n (faster)" y-or-n-p)
1576 (const :tag "no confirmation (dangerous)" nil)))
86fbb8ca
CD
1577(put 'org-confirm-shell-link-function
1578 'safe-local-variable
4f91a816 1579 (lambda (x) (member x '(yes-or-no-p y-or-n-p))))
4b3a9ba7
CD
1580
1581(defcustom org-confirm-elisp-link-function 'yes-or-no-p
ed21c5c8 1582 "Non-nil means ask for confirmation before executing Emacs Lisp links.
03f3cf35 1583Elisp links can be dangerous: just think about a link
4b3a9ba7
CD
1584
1585 [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]]
1586
03f3cf35 1587This link would show up in your Org-mode document as \"Google Search\",
4b3a9ba7 1588but really it would remove your entire home directory.
03f3cf35 1589Therefore we advise against setting this variable to nil.
c8d0cf5c 1590Just change it to `y-or-n-p' if you want to confirm with a
03f3cf35 1591single keystroke rather than having to type \"yes\"."
ab27a4a0
CD
1592 :group 'org-link-follow
1593 :type '(choice
1594 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1595 (const :tag "with y-or-n (faster)" y-or-n-p)
1596 (const :tag "no confirmation (dangerous)" nil)))
86fbb8ca
CD
1597(put 'org-confirm-shell-link-function
1598 'safe-local-variable
4f91a816 1599 (lambda (x) (member x '(yes-or-no-p y-or-n-p))))
891f4676 1600
ee53c9b7 1601(defconst org-file-apps-defaults-gnu
6769c0dc 1602 '((remote . emacs)
93b62de8 1603 (system . mailcap)
6769c0dc 1604 (t . mailcap))
b0a10108 1605 "Default file applications on a UNIX or GNU/Linux system.
891f4676
RS
1606See `org-file-apps'.")
1607
1608(defconst org-file-apps-defaults-macosx
6769c0dc 1609 '((remote . emacs)
3278a016 1610 (t . "open %s")
93b62de8 1611 (system . "open %s")
891f4676 1612 ("ps.gz" . "gv %s")
891f4676
RS
1613 ("eps.gz" . "gv %s")
1614 ("dvi" . "xdvi %s")
1615 ("fig" . "xfig %s"))
1616 "Default file applications on a MacOS X system.
1617The system \"open\" is known as a default, but we use X11 applications
1618for some files for which the OS does not have a good default.
1619See `org-file-apps'.")
1620
1621(defconst org-file-apps-defaults-windowsnt
c44f0d75 1622 (list
6769c0dc
CD
1623 '(remote . emacs)
1624 (cons t
93b62de8
CD
1625 (list (if (featurep 'xemacs)
1626 'mswindows-shell-execute
1627 'w32-shell-execute)
1628 "open" 'file))
1629 (cons 'system
6769c0dc
CD
1630 (list (if (featurep 'xemacs)
1631 'mswindows-shell-execute
1632 'w32-shell-execute)
1633 "open" 'file)))
891f4676
RS
1634 "Default file applications on a Windows NT system.
1635The system \"open\" is used for most files.
1636See `org-file-apps'.")
1637
1638(defcustom org-file-apps
1639 '(
621f83e4 1640 (auto-mode . emacs)
8bfe682a 1641 ("\\.mm\\'" . default)
621f83e4 1642 ("\\.x?html?\\'" . default)
71d35b24 1643 ("\\.pdf\\'" . default)
891f4676
RS
1644 )
1645 "External applications for opening `file:path' items in a document.
1646Org-mode uses system defaults for different file types, but
1647you can use this variable to set the application for a given file
4b3a9ba7
CD
1648extension. The entries in this list are cons cells where the car identifies
1649files and the cdr the corresponding command. Possible values for the
1650file identifier are
86fbb8ca
CD
1651 \"string\" A string as a file identifier can be interpreted in different
1652 ways, depending on its contents:
1653
1654 - Alphanumeric characters only:
1655 Match links with this file extension.
1656 Example: (\"pdf\" . \"evince %s\")
1657 to open PDFs with evince.
1658
1659 - Regular expression: Match links where the
1660 filename matches the regexp. If you want to
1661 use groups here, use shy groups.
1662
1663 Example: (\"\\.x?html\\'\" . \"firefox %s\")
1664 (\"\\(?:xhtml\\|html\\)\" . \"firefox %s\")
1665 to open *.html and *.xhtml with firefox.
1666
1667 - Regular expression which contains (non-shy) groups:
1668 Match links where the whole link, including \"::\", and
1669 anything after that, matches the regexp.
1670 In a custom command string, %1, %2, etc. are replaced with
1671 the parts of the link that were matched by the groups.
1672 For backwards compatibility, if a command string is given
1673 that does not use any of the group matches, this case is
1674 handled identically to the second one (i.e. match against
1675 file name only).
1676 In a custom lisp form, you can access the group matches with
1677 (match-string n link).
1678
1679 Example: (\"\\.pdf::\\(\\d+\\)\\'\" . \"evince -p %1 %s\")
1680 to open [[file:document.pdf::5]] with evince at page 5.
1681
4b3a9ba7 1682 `directory' Matches a directory
5137195a 1683 `remote' Matches a remote file, accessible through tramp or efs.
c44f0d75 1684 Remote files most likely should be visited through Emacs
6769c0dc 1685 because external applications cannot handle such paths.
33306645 1686`auto-mode' Matches files that are matched by any entry in `auto-mode-alist',
93b62de8 1687 so all files Emacs knows how to handle. Using this with
621f83e4 1688 command `emacs' will open most files in Emacs. Beware that this
33306645 1689 will also open html files inside Emacs, unless you add
621f83e4
CD
1690 (\"html\" . default) to the list as well.
1691 t Default for files not matched by any of the other options.
93b62de8
CD
1692 `system' The system command to open files, like `open' on Windows
1693 and Mac OS X, and mailcap under GNU/Linux. This is the command
1694 that will be selected if you call `C-c C-o' with a double
86fbb8ca 1695 \\[universal-argument] \\[universal-argument] prefix.
4b3a9ba7
CD
1696
1697Possible values for the command are:
1698 `emacs' The file will be visited by the current Emacs process.
621f83e4
CD
1699 `default' Use the default application for this file type, which is the
1700 association for t in the list, most likely in the system-specific
1701 part.
33306645 1702 This can be used to overrule an unwanted setting in the
621f83e4 1703 system-specific variable.
93b62de8
CD
1704 `system' Use the system command for opening files, like \"open\".
1705 This command is specified by the entry whose car is `system'.
1706 Most likely, the system-specific version of this variable
1707 does define this command, but you can overrule/replace it
1708 here.
4b3a9ba7 1709 string A command to be executed by a shell; %s will be replaced
86fbb8ca 1710 by the path to the file.
4b3a9ba7 1711 sexp A Lisp form which will be evaluated. The file path will
86fbb8ca 1712 be available in the Lisp variable `file'.
891f4676
RS
1713For more examples, see the system specific constants
1714`org-file-apps-defaults-macosx'
1715`org-file-apps-defaults-windowsnt'
ee53c9b7 1716`org-file-apps-defaults-gnu'."
ab27a4a0 1717 :group 'org-link-follow
891f4676 1718 :type '(repeat
a96ee7df
CD
1719 (cons (choice :value ""
1720 (string :tag "Extension")
93b62de8 1721 (const :tag "System command to open files" system)
a96ee7df 1722 (const :tag "Default for unrecognized files" t)
6769c0dc 1723 (const :tag "Remote file" remote)
621f83e4
CD
1724 (const :tag "Links to a directory" directory)
1725 (const :tag "Any files that have Emacs modes"
1726 auto-mode))
c8d16429 1727 (choice :value ""
a96ee7df 1728 (const :tag "Visit with Emacs" emacs)
93b62de8
CD
1729 (const :tag "Use default" default)
1730 (const :tag "Use the system command" system)
a96ee7df
CD
1731 (string :tag "Command")
1732 (sexp :tag "Lisp form")))))
891f4676 1733
86fbb8ca
CD
1734
1735
20908596
CD
1736(defgroup org-refile nil
1737 "Options concerning refiling entries in Org-mode."
d60b1ba1 1738 :tag "Org Refile"
891f4676
RS
1739 :group 'org)
1740
1741(defcustom org-directory "~/org"
1742 "Directory with org files.
c8d0cf5c
CD
1743This is just a default location to look for Org files. There is no need
1744at all to put your files into this directory. It is only used in the
1745following situations:
1746
17471. When a remember template specifies a target file that is not an
1748 absolute path. The path will then be interpreted relative to
1749 `org-directory'
17502. When a remember note is filed away in an interactive way (when exiting the
04e65fdb 1751 note buffer with `C-1 C-c C-c'. The user is prompted for an org file,
c8d0cf5c 1752 with `org-directory' as the default path."
20908596 1753 :group 'org-refile
891f4676
RS
1754 :group 'org-remember
1755 :type 'directory)
1756
0a505855 1757(defcustom org-default-notes-file (convert-standard-filename "~/.notes")
891f4676 1758 "Default target for storing notes.
86fbb8ca
CD
1759Used as a fall back file for org-remember.el and org-capture.el, for
1760templates that do not specify a target file."
20908596 1761 :group 'org-refile
891f4676
RS
1762 :group 'org-remember
1763 :type '(choice
c8d16429
CD
1764 (const :tag "Default from remember-data-file" nil)
1765 file))
891f4676 1766
2a57416f
CD
1767(defcustom org-goto-interface 'outline
1768 "The default interface to be used for `org-goto'.
33306645 1769Allowed values are:
2a57416f
CD
1770outline The interface shows an outline of the relevant file
1771 and the correct heading is found by moving through
1772 the outline or by searching with incremental search.
1773outline-path-completion Headlines in the current buffer are offered via
d60b1ba1
CD
1774 completion. This is the interface also used by
1775 the refile command."
20908596 1776 :group 'org-refile
2a57416f
CD
1777 :type '(choice
1778 (const :tag "Outline" outline)
1779 (const :tag "Outline-path-completion" outline-path-completion)))
8c6fb58b 1780
db55f368 1781(defcustom org-goto-max-level 5
86fbb8ca 1782 "Maximum target level when running `org-goto' with refile interface."
db55f368 1783 :group 'org-refile
c8d0cf5c 1784 :type 'integer)
db55f368 1785
891f4676 1786(defcustom org-reverse-note-order nil
ed21c5c8 1787 "Non-nil means store new notes at the beginning of a file or entry.
8c6fb58b
CD
1788When nil, new notes will be filed to the end of a file or entry.
1789This can also be a list with cons cells of regular expressions that
1790are matched against file names, and values."
891f4676 1791 :group 'org-remember
d60b1ba1 1792 :group 'org-refile
891f4676 1793 :type '(choice
c8d16429
CD
1794 (const :tag "Reverse always" t)
1795 (const :tag "Reverse never" nil)
1796 (repeat :tag "By file name regexp"
1797 (cons regexp boolean))))
891f4676 1798
ed21c5c8
CD
1799(defcustom org-log-refile nil
1800 "Information to record when a task is refiled.
1801
1802Possible values are:
1803
1804nil Don't add anything
1805time Add a time stamp to the task
1806note Prompt for a note and add it with template `org-log-note-headings'
1807
1808This option can also be set with on a per-file-basis with
1809
1810 #+STARTUP: nologrefile
1811 #+STARTUP: logrefile
1812 #+STARTUP: lognoterefile
1813
1814You can have local logging settings for a subtree by setting the LOGGING
1815property to one or more of these keywords.
1816
1817When bulk-refiling from the agenda, the value `note' is forbidden and
1818will temporarily be changed to `time'."
1819 :group 'org-refile
1820 :group 'org-progress
1821 :type '(choice
1822 (const :tag "No logging" nil)
1823 (const :tag "Record timestamp" time)
1824 (const :tag "Record timestamp with note." note)))
1825
8c6fb58b
CD
1826(defcustom org-refile-targets nil
1827 "Targets for refiling entries with \\[org-refile].
1828This is list of cons cells. Each cell contains:
1829- a specification of the files to be considered, either a list of files,
20908596 1830 or a symbol whose function or variable value will be used to retrieve
fdf730ed 1831 a file name or a list of file names. If you use `org-agenda-files' for
afe98dfa
CD
1832 that, all agenda files will be scanned for targets. Nil means consider
1833 headings in the current buffer.
c8d0cf5c
CD
1834- A specification of how to find candidate refile targets. This may be
1835 any of:
8c6fb58b
CD
1836 - a cons cell (:tag . \"TAG\") to identify refile targets by a tag.
1837 This tag has to be present in all target headlines, inheritance will
1838 not be considered.
1839 - a cons cell (:todo . \"KEYWORD\") to identify refile targets by
1840 todo keyword.
1841 - a cons cell (:regexp . \"REGEXP\") with a regular expression matching
1842 headlines that are refiling targets.
1843 - a cons cell (:level . N). Any headline of level N is considered a target.
c8d0cf5c
CD
1844 Note that, when `org-odd-levels-only' is set, level corresponds to
1845 order in hierarchy, not to the number of stars.
01c35094 1846 - a cons cell (:maxlevel . N). Any headline with level <= N is a target.
c8d0cf5c
CD
1847 Note that, when `org-odd-levels-only' is set, level corresponds to
1848 order in hierarchy, not to the number of stars.
1849
1850You can set the variable `org-refile-target-verify-function' to a function
86fbb8ca 1851to verify each headline found by the simple criteria above.
621f83e4
CD
1852
1853When this variable is nil, all top-level headlines in the current buffer
93b62de8 1854are used, equivalent to the value `((nil . (:level . 1))'."
d60b1ba1 1855 :group 'org-refile
8c6fb58b
CD
1856 :type '(repeat
1857 (cons
1858 (choice :value org-agenda-files
1859 (const :tag "All agenda files" org-agenda-files)
1860 (const :tag "Current buffer" nil)
1861 (function) (variable) (file))
1862 (choice :tag "Identify target headline by"
ce4fdcb9
CD
1863 (cons :tag "Specific tag" (const :value :tag) (string))
1864 (cons :tag "TODO keyword" (const :value :todo) (string))
1865 (cons :tag "Regular expression" (const :value :regexp) (regexp))
1866 (cons :tag "Level number" (const :value :level) (integer))
1867 (cons :tag "Max Level number" (const :value :maxlevel) (integer))))))
8c6fb58b 1868
c8d0cf5c
CD
1869(defcustom org-refile-target-verify-function nil
1870 "Function to verify if the headline at point should be a refile target.
1871The function will be called without arguments, with point at the
1872beginning of the headline. It should return t and leave point
1873where it is if the headline is a valid target for refiling.
1874
1875If the target should not be selected, the function must return nil.
1876In addition to this, it may move point to a place from where the search
1877should be continued. For example, the function may decide that the entire
1878subtree of the current entry should be excluded and move point to the end
1879of the subtree."
1880 :group 'org-refile
1881 :type 'function)
1882
86fbb8ca
CD
1883(defcustom org-refile-use-cache nil
1884 "Non-nil means cache refile targets to speed up the process.
1885The cache for a particular file will be updated automatically when
1886the buffer has been killed, or when any of the marker used for flagging
1887refile targets no longer points at a live buffer.
1888If you have added new entries to a buffer that might themselves be targets,
1889you need to clear the cache manually by pressing `C-0 C-c C-w' or, if you
1890find that easier, `C-u C-u C-u C-c C-w'."
1891 :group 'org-refile
1892 :type 'boolean)
1893
8c6fb58b 1894(defcustom org-refile-use-outline-path nil
ed21c5c8 1895 "Non-nil means provide refile targets as paths.
8c6fb58b 1896So a level 3 headline will be available as level1/level2/level3.
c8d0cf5c 1897
8c6fb58b 1898When the value is `file', also include the file name (without directory)
c8d0cf5c
CD
1899into the path. In this case, you can also stop the completion after
1900the file name, to get entries inserted as top level in the file.
1901
1902 When `full-file-path', include the full file path."
d60b1ba1 1903 :group 'org-refile
8c6fb58b
CD
1904 :type '(choice
1905 (const :tag "Not" nil)
1906 (const :tag "Yes" t)
1907 (const :tag "Start with file name" file)
1908 (const :tag "Start with full file path" full-file-path)))
1909
d60b1ba1 1910(defcustom org-outline-path-complete-in-steps t
ed21c5c8 1911 "Non-nil means complete the outline path in hierarchical steps.
d60b1ba1
CD
1912When Org-mode uses the refile interface to select an outline path
1913\(see variable `org-refile-use-outline-path'), the completion of
1914the path can be done is a single go, or if can be done in steps down
1915the headline hierarchy. Going in steps is probably the best if you
1916do not use a special completion package like `ido' or `icicles'.
1917However, when using these packages, going in one step can be very
1918fast, while still showing the whole path to the entry."
1919 :group 'org-refile
1920 :type 'boolean)
1921
c8d0cf5c 1922(defcustom org-refile-allow-creating-parent-nodes nil
ed21c5c8 1923 "Non-nil means allow to create new nodes as refile targets.
c8d0cf5c
CD
1924New nodes are then created by adding \"/new node name\" to the completion
1925of an existing node. When the value of this variable is `confirm',
1926new node creation must be confirmed by the user (recommended)
1927When nil, the completion must match an existing entry.
1928
1929Note that, if the new heading is not seen by the criteria
1930listed in `org-refile-targets', multiple instances of the same
1931heading would be created by trying again to file under the new
1932heading."
1933 :group 'org-refile
1934 :type '(choice
1935 (const :tag "Never" nil)
1936 (const :tag "Always" t)
1937 (const :tag "Prompt for confirmation" confirm)))
1938
ab27a4a0
CD
1939(defgroup org-todo nil
1940 "Options concerning TODO items in Org-mode."
1941 :tag "Org TODO"
891f4676
RS
1942 :group 'org)
1943
d3f4dbe8
CD
1944(defgroup org-progress nil
1945 "Options concerning Progress logging in Org-mode."
1946 :tag "Org Progress"
1947 :group 'org-time)
1948
c8d0cf5c
CD
1949(defvar org-todo-interpretation-widgets
1950 '(
1951 (:tag "Sequence (cycling hits every state)" sequence)
1952 (:tag "Type (cycling directly to DONE)" type))
86fbb8ca
CD
1953 "The available interpretation symbols for customizing `org-todo-keywords'.
1954Interested libraries should add to this list.")
c8d0cf5c 1955
a3fbe8c4
CD
1956(defcustom org-todo-keywords '((sequence "TODO" "DONE"))
1957 "List of TODO entry keyword sequences and their interpretation.
1958\\<org-mode-map>This is a list of sequences.
1959
1960Each sequence starts with a symbol, either `sequence' or `type',
1961indicating if the keywords should be interpreted as a sequence of
1962action steps, or as different types of TODO items. The first
1963keywords are states requiring action - these states will select a headline
1964for inclusion into the global TODO list Org-mode produces. If one of
acedf35c 1965the \"keywords\" is the vertical bar, \"|\", the remaining keywords
a3fbe8c4
CD
1966signify that no further action is necessary. If \"|\" is not found,
1967the last keyword is treated as the only DONE state of the sequence.
1968
1969The command \\[org-todo] cycles an entry through these states, and one
ab27a4a0 1970additional state where no keyword is present. For details about this
a3fbe8c4
CD
1971cycling, see the manual.
1972
1973TODO keywords and interpretation can also be set on a per-file basis with
1974the special #+SEQ_TODO and #+TYP_TODO lines.
1975
2a57416f
CD
1976Each keyword can optionally specify a character for fast state selection
1977\(in combination with the variable `org-use-fast-todo-selection')
1978and specifiers for state change logging, using the same syntax
1979that is used in the \"#+TODO:\" lines. For example, \"WAIT(w)\" says
86fbb8ca 1980that the WAIT state can be selected with the \"w\" key. \"WAIT(w!)\"
2a57416f
CD
1981indicates to record a time stamp each time this state is selected.
1982
1983Each keyword may also specify if a timestamp or a note should be
1984recorded when entering or leaving the state, by adding additional
1985characters in the parenthesis after the keyword. This looks like this:
1986\"WAIT(w@/!)\". \"@\" means to add a note (with time), \"!\" means to
1987record only the time of the state change. With X and Y being either
1988\"@\" or \"!\", \"X/Y\" means use X when entering the state, and use
1989Y when leaving the state if and only if the *target* state does not
1990define X. You may omit any of the fast-selection key or X or /Y,
1991so WAIT(w@), WAIT(w/@) and WAIT(@/@) are all valid.
1992
a3fbe8c4 1993For backward compatibility, this variable may also be just a list
33306645 1994of keywords - in this case the interpretation (sequence or type) will be
a3fbe8c4 1995taken from the (otherwise obsolete) variable `org-todo-interpretation'."
ab27a4a0
CD
1996 :group 'org-todo
1997 :group 'org-keywords
a3fbe8c4
CD
1998 :type '(choice
1999 (repeat :tag "Old syntax, just keywords"
2000 (string :tag "Keyword"))
2001 (repeat :tag "New syntax"
2002 (cons
2003 (choice
2004 :tag "Interpretation"
c8d0cf5c
CD
2005 ;;Quick and dirty way to see
2006 ;;`org-todo-interpretations'. This takes the
2007 ;;place of item arguments
2008 :convert-widget
2009 (lambda (widget)
2010 (widget-put widget
2011 :args (mapcar
2012 #'(lambda (x)
2013 (widget-convert
2014 (cons 'const x)))
2015 org-todo-interpretation-widgets))
2016 widget))
a3fbe8c4
CD
2017 (repeat
2018 (string :tag "Keyword"))))))
2019
2a57416f
CD
2020(defvar org-todo-keywords-1 nil
2021 "All TODO and DONE keywords active in a buffer.")
a3fbe8c4
CD
2022(make-variable-buffer-local 'org-todo-keywords-1)
2023(defvar org-todo-keywords-for-agenda nil)
2024(defvar org-done-keywords-for-agenda nil)
8d642074 2025(defvar org-drawers-for-agenda nil)
621f83e4
CD
2026(defvar org-todo-keyword-alist-for-agenda nil)
2027(defvar org-tag-alist-for-agenda nil)
20908596 2028(defvar org-agenda-contributing-files nil)
a3fbe8c4
CD
2029(defvar org-not-done-keywords nil)
2030(make-variable-buffer-local 'org-not-done-keywords)
2031(defvar org-done-keywords nil)
2032(make-variable-buffer-local 'org-done-keywords)
2033(defvar org-todo-heads nil)
2034(make-variable-buffer-local 'org-todo-heads)
2035(defvar org-todo-sets nil)
2036(make-variable-buffer-local 'org-todo-sets)
d5098885
JW
2037(defvar org-todo-log-states nil)
2038(make-variable-buffer-local 'org-todo-log-states)
a3fbe8c4
CD
2039(defvar org-todo-kwd-alist nil)
2040(make-variable-buffer-local 'org-todo-kwd-alist)
0b8568f5
JW
2041(defvar org-todo-key-alist nil)
2042(make-variable-buffer-local 'org-todo-key-alist)
2043(defvar org-todo-key-trigger nil)
2044(make-variable-buffer-local 'org-todo-key-trigger)
791d856f 2045
ab27a4a0
CD
2046(defcustom org-todo-interpretation 'sequence
2047 "Controls how TODO keywords are interpreted.
a3fbe8c4
CD
2048This variable is in principle obsolete and is only used for
2049backward compatibility, if the interpretation of todo keywords is
2050not given already in `org-todo-keywords'. See that variable for
2051more information."
ab27a4a0
CD
2052 :group 'org-todo
2053 :group 'org-keywords
2054 :type '(choice (const sequence)
2055 (const type)))
28e5b051 2056
5ace2fe5 2057(defcustom org-use-fast-todo-selection t
ed21c5c8 2058 "Non-nil means use the fast todo selection scheme with C-c C-t.
0b8568f5
JW
2059This variable describes if and under what circumstances the cycling
2060mechanism for TODO keywords will be replaced by a single-key, direct
2061selection scheme.
2062
2063When nil, fast selection is never used.
2064
2065When the symbol `prefix', it will be used when `org-todo' is called with
2066a prefix argument, i.e. `C-u C-c C-t' in an Org-mode buffer, and `C-u t'
2067in an agenda buffer.
2068
2069When t, fast selection is used by default. In this case, the prefix
2070argument forces cycling instead.
2071
2072In all cases, the special interface is only used if access keys have actually
2073been assigned by the user, i.e. if keywords in the configuration are followed
2074by a letter in parenthesis, like TODO(t)."
2075 :group 'org-todo
2076 :type '(choice
2077 (const :tag "Never" nil)
2078 (const :tag "By default" t)
2079 (const :tag "Only with C-u C-c C-t" prefix)))
2080
b349f79f 2081(defcustom org-provide-todo-statistics t
ed21c5c8 2082 "Non-nil means update todo statistics after insert and toggle.
c8d0cf5c
CD
2083ALL-HEADLINES means update todo statistics by including headlines
2084with no TODO keyword as well, counting them as not done.
2085A list of TODO keywords means the same, but skip keywords that are
2086not in this list.
2087
2088When this is set, todo statistics is updated in the parent of the
2089current entry each time a todo state is changed."
2090 :group 'org-todo
2091 :type '(choice
2092 (const :tag "Yes, only for TODO entries" t)
2093 (const :tag "Yes, including all entries" 'all-headlines)
2094 (repeat :tag "Yes, for TODOs in this list"
2095 (string :tag "TODO keyword"))
2096 (other :tag "No TODO statistics" nil)))
2097
2098(defcustom org-hierarchical-todo-statistics t
ed21c5c8 2099 "Non-nil means TODO statistics covers just direct children.
c8d0cf5c 2100When nil, all entries in the subtree are considered.
54a0dee5
CD
2101This has only an effect if `org-provide-todo-statistics' is set.
2102To set this to nil for only a single subtree, use a COOKIE_DATA
2103property and include the word \"recursive\" into the value."
b349f79f
CD
2104 :group 'org-todo
2105 :type 'boolean)
2106
ab27a4a0
CD
2107(defcustom org-after-todo-state-change-hook nil
2108 "Hook which is run after the state of a TODO item was changed.
2109The new state (a string with a TODO keyword, or nil) is available in the
2110Lisp variable `state'."
2111 :group 'org-todo
2112 :type 'hook)
891f4676 2113
d6685abc
CD
2114(defvar org-blocker-hook nil
2115 "Hook for functions that are allowed to block a state change.
2116
2117Each function gets as its single argument a property list, see
2118`org-trigger-hook' for more information about this list.
2119
2120If any of the functions in this hook returns nil, the state change
2121is blocked.")
2122
2123(defvar org-trigger-hook nil
2124 "Hook for functions that are triggered by a state change.
2125
2126Each function gets as its single argument a property list with at least
2127the following elements:
2128
2129 (:type type-of-change :position pos-at-entry-start
2130 :from old-state :to new-state)
2131
2132Depending on the type, more properties may be present.
2133
2134This mechanism is currently implemented for:
2135
2136TODO state changes
2137------------------
2138:type todo-state-change
2139:from previous state (keyword as a string), or nil, or a symbol
2140 'todo' or 'done', to indicate the general type of state.
2141:to new state, like in :from")
2142
2143(defcustom org-enforce-todo-dependencies nil
ed21c5c8 2144 "Non-nil means undone TODO entries will block switching the parent to DONE.
d6685abc
CD
2145Also, if a parent has an :ORDERED: property, switching an entry to DONE will
2146be blocked if any prior sibling is not yet done.
c8d0cf5c
CD
2147Finally, if the parent is blocked because of ordered siblings of its own,
2148the child will also be blocked.
5ace2fe5
CD
2149This variable needs to be set before org.el is loaded, and you need to
2150restart Emacs after a change to make the change effective. The only way
2151to change is while Emacs is running is through the customize interface."
d6685abc
CD
2152 :set (lambda (var val)
2153 (set var val)
2154 (if val
6c817206 2155 (add-hook 'org-blocker-hook
c8d0cf5c 2156 'org-block-todo-from-children-or-siblings-or-parent)
6c817206 2157 (remove-hook 'org-blocker-hook
c8d0cf5c 2158 'org-block-todo-from-children-or-siblings-or-parent)))
6c817206
CD
2159 :group 'org-todo
2160 :type 'boolean)
2161
2162(defcustom org-enforce-todo-checkbox-dependencies nil
ed21c5c8 2163 "Non-nil means unchecked boxes will block switching the parent to DONE.
6c817206
CD
2164When this is nil, checkboxes have no influence on switching TODO states.
2165When non-nil, you first need to check off all check boxes before the TODO
2166entry can be switched to DONE.
5ace2fe5
CD
2167This variable needs to be set before org.el is loaded, and you need to
2168restart Emacs after a change to make the change effective. The only way
2169to change is while Emacs is running is through the customize interface."
6c817206
CD
2170 :set (lambda (var val)
2171 (set var val)
2172 (if val
2173 (add-hook 'org-blocker-hook
2174 'org-block-todo-from-checkboxes)
2175 (remove-hook 'org-blocker-hook
2176 'org-block-todo-from-checkboxes)))
d6685abc
CD
2177 :group 'org-todo
2178 :type 'boolean)
2179
c8d0cf5c 2180(defcustom org-treat-insert-todo-heading-as-state-change nil
ed21c5c8 2181 "Non-nil means inserting a TODO heading is treated as state change.
c8d0cf5c
CD
2182So when the command \\[org-insert-todo-heading] is used, state change
2183logging will apply if appropriate. When nil, the new TODO item will
2184be inserted directly, and no logging will take place."
2185 :group 'org-todo
2186 :type 'boolean)
2187
2188(defcustom org-treat-S-cursor-todo-selection-as-state-change t
ed21c5c8 2189 "Non-nil means switching TODO states with S-cursor counts as state change.
c8d0cf5c
CD
2190This is the default behavior. However, setting this to nil allows a
2191convenient way to select a TODO state and bypass any logging associated
2192with that."
2193 :group 'org-todo
2194 :type 'boolean)
2195
71d35b24
CD
2196(defcustom org-todo-state-tags-triggers nil
2197 "Tag changes that should be triggered by TODO state changes.
2198This is a list. Each entry is
2199
2200 (state-change (tag . flag) .......)
2201
2202State-change can be a string with a state, and empty string to indicate the
2203state that has no TODO keyword, or it can be one of the symbols `todo'
2204or `done', meaning any not-done or done state, respectively."
2205 :group 'org-todo
2206 :group 'org-tags
2207 :type '(repeat
2208 (cons (choice :tag "When changing to"
2209 (const :tag "Not-done state" todo)
2210 (const :tag "Done state" done)
2211 (string :tag "State"))
2212 (repeat
2213 (cons :tag "Tag action"
2214 (string :tag "Tag")
2215 (choice (const :tag "Add" t) (const :tag "Remove" nil)))))))
2216
ab27a4a0 2217(defcustom org-log-done nil
db55f368
CD
2218 "Information to record when a task moves to the DONE state.
2219
2220Possible values are:
2221
2222nil Don't add anything, just change the keyword
2223time Add a time stamp to the task
8bfe682a 2224note Prompt for a note and add it with template `org-log-note-headings'
4b3a9ba7 2225
db55f368
CD
2226This option can also be set with on a per-file-basis with
2227
2228 #+STARTUP: nologdone
d3f4dbe8 2229 #+STARTUP: logdone
d3f4dbe8 2230 #+STARTUP: lognotedone
db55f368
CD
2231
2232You can have local logging settings for a subtree by setting the LOGGING
2233property to one or more of these keywords."
ab27a4a0 2234 :group 'org-todo
d3f4dbe8 2235 :group 'org-progress
3278a016 2236 :type '(choice
2a57416f
CD
2237 (const :tag "No logging" nil)
2238 (const :tag "Record CLOSED timestamp" time)
8bfe682a 2239 (const :tag "Record CLOSED timestamp with note." note)))
2a57416f
CD
2240
2241;; Normalize old uses of org-log-done.
2242(cond
2243 ((eq org-log-done t) (setq org-log-done 'time))
2244 ((and (listp org-log-done) (memq 'done org-log-done))
2245 (setq org-log-done 'note)))
2246
8bfe682a
CD
2247(defcustom org-log-reschedule nil
2248 "Information to record when the scheduling date of a tasks is modified.
2249
2250Possible values are:
2251
2252nil Don't add anything, just change the date
2253time Add a time stamp to the task
2254note Prompt for a note and add it with template `org-log-note-headings'
2255
2256This option can also be set with on a per-file-basis with
2257
2258 #+STARTUP: nologreschedule
2259 #+STARTUP: logreschedule
2260 #+STARTUP: lognotereschedule"
2261 :group 'org-todo
2262 :group 'org-progress
2263 :type '(choice
2264 (const :tag "No logging" nil)
2265 (const :tag "Record timestamp" time)
2266 (const :tag "Record timestamp with note." note)))
2267
2268(defcustom org-log-redeadline nil
2269 "Information to record when the deadline date of a tasks is modified.
2270
2271Possible values are:
2272
2273nil Don't add anything, just change the date
2274time Add a time stamp to the task
2275note Prompt for a note and add it with template `org-log-note-headings'
2276
2277This option can also be set with on a per-file-basis with
2278
2279 #+STARTUP: nologredeadline
2280 #+STARTUP: logredeadline
2281 #+STARTUP: lognoteredeadline
2282
2283You can have local logging settings for a subtree by setting the LOGGING
2284property to one or more of these keywords."
2285 :group 'org-todo
2286 :group 'org-progress
2287 :type '(choice
2288 (const :tag "No logging" nil)
2289 (const :tag "Record timestamp" time)
2290 (const :tag "Record timestamp with note." note)))
2291
2a57416f 2292(defcustom org-log-note-clock-out nil
ed21c5c8 2293 "Non-nil means record a note when clocking out of an item.
2a57416f
CD
2294This can also be configured on a per-file basis by adding one of
2295the following lines anywhere in the buffer:
2296
2297 #+STARTUP: lognoteclock-out
2298 #+STARTUP: nolognoteclock-out"
2299 :group 'org-todo
2300 :group 'org-progress
2301 :type 'boolean)
d3f4dbe8 2302
a3fbe8c4 2303(defcustom org-log-done-with-time t
ed21c5c8 2304 "Non-nil means the CLOSED time stamp will contain date and time.
a3fbe8c4
CD
2305When nil, only the date will be recorded."
2306 :group 'org-progress
2307 :type 'boolean)
2308
d3f4dbe8 2309(defcustom org-log-note-headings
20908596 2310 '((done . "CLOSING NOTE %t")
c8d0cf5c 2311 (state . "State %-12s from %-12S %t")
20908596 2312 (note . "Note taken on %t")
8bfe682a 2313 (reschedule . "Rescheduled from %S on %t")
ed21c5c8 2314 (delschedule . "Not scheduled, was %S on %t")
8bfe682a 2315 (redeadline . "New deadline from %S on %t")
ed21c5c8
CD
2316 (deldeadline . "Removed deadline, was %S on %t")
2317 (refile . "Refiled on %t")
d3f4dbe8 2318 (clock-out . ""))
20908596 2319 "Headings for notes added to entries.
48aaad2d 2320The value is an alist, with the car being a symbol indicating the note
3278a016 2321context, and the cdr is the heading to be used. The heading may also be the
d3f4dbe8
CD
2322empty string.
2323%t in the heading will be replaced by a time stamp.
86fbb8ca 2324%T will be an active time stamp instead the default inactive one
d3f4dbe8 2325%s will be replaced by the new TODO state, in double quotes.
c8d0cf5c 2326%S will be replaced by the old TODO state, in double quotes.
d3f4dbe8 2327%u will be replaced by the user name.
ed21c5c8
CD
2328%U will be replaced by the full user name.
2329
2330In fact, it is not a good idea to change the `state' entry, because
2331agenda log mode depends on the format of these entries."
3278a016 2332 :group 'org-todo
d3f4dbe8 2333 :group 'org-progress
3278a016
CD
2334 :type '(list :greedy t
2335 (cons (const :tag "Heading when closing an item" done) string)
d3f4dbe8
CD
2336 (cons (const :tag
2337 "Heading when changing todo state (todo sequence only)"
2338 state) string)
20908596 2339 (cons (const :tag "Heading when just taking a note" note) string)
8bfe682a 2340 (cons (const :tag "Heading when clocking out" clock-out) string)
ed21c5c8 2341 (cons (const :tag "Heading when an item is no longer scheduled" delschedule) string)
8bfe682a 2342 (cons (const :tag "Heading when rescheduling" reschedule) string)
ed21c5c8
CD
2343 (cons (const :tag "Heading when changing deadline" redeadline) string)
2344 (cons (const :tag "Heading when deleting a deadline" deldeadline) string)
2345 (cons (const :tag "Heading when refiling" refile) string)))
e0e66b8e 2346
20908596
CD
2347(unless (assq 'note org-log-note-headings)
2348 (push '(note . "%t") org-log-note-headings))
2349
c8d0cf5c 2350(defcustom org-log-into-drawer nil
ed21c5c8 2351 "Non-nil means insert state change notes and time stamps into a drawer.
c8d0cf5c
CD
2352When nil, state changes notes will be inserted after the headline and
2353any scheduling and clock lines, but not inside a drawer.
2354
2355The value of this variable should be the name of the drawer to use.
2356LOGBOOK is proposed at the default drawer for this purpose, you can
2357also set this to a string to define the drawer of your choice.
2358
2359A value of t is also allowed, representing \"LOGBOOK\".
2360
2361If this variable is set, `org-log-state-notes-insert-after-drawers'
2362will be ignored.
2363
2364You can set the property LOG_INTO_DRAWER to overrule this setting for
2365a subtree."
2366 :group 'org-todo
2367 :group 'org-progress
2368 :type '(choice
2369 (const :tag "Not into a drawer" nil)
2370 (const :tag "LOGBOOK" t)
2371 (string :tag "Other")))
2372
2373(if (fboundp 'defvaralias)
2374 (defvaralias 'org-log-state-notes-into-drawer 'org-log-into-drawer))
2375
2376(defun org-log-into-drawer ()
2377 "Return the value of `org-log-into-drawer', but let properties overrule.
2378If the current entry has or inherits a LOG_INTO_DRAWER property, it will be
2379used instead of the default value."
2380 (let ((p (ignore-errors (org-entry-get nil "LOG_INTO_DRAWER" 'inherit))))
2381 (cond
2382 ((or (not p) (equal p "nil")) org-log-into-drawer)
2383 ((equal p "t") "LOGBOOK")
2384 (t p))))
2385
71d35b24 2386(defcustom org-log-state-notes-insert-after-drawers nil
ed21c5c8 2387 "Non-nil means insert state change notes after any drawers in entry.
71d35b24
CD
2388Only the drawers that *immediately* follow the headline and the
2389deadline/scheduled line are skipped.
2390When nil, insert notes right after the heading and perhaps the line
c8d0cf5c
CD
2391with deadline/scheduling if present.
2392
2393This variable will have no effect if `org-log-into-drawer' is
2394set."
71d35b24
CD
2395 :group 'org-todo
2396 :group 'org-progress
2397 :type 'boolean)
2398
48aaad2d 2399(defcustom org-log-states-order-reversed t
ed21c5c8
CD
2400 "Non-nil means the latest state note will be directly after heading.
2401When nil, the state change notes will be ordered according to time."
48aaad2d
CD
2402 :group 'org-todo
2403 :group 'org-progress
2404 :type 'boolean)
2405
86fbb8ca
CD
2406(defcustom org-todo-repeat-to-state nil
2407 "The TODO state to which a repeater should return the repeating task.
2408By default this is the first task in a TODO sequence, or the previous state
2409in a TODO_TYP set. But you can specify another task here.
2410alternatively, set the :REPEAT_TO_STATE: property of the entry."
2411 :group 'org-todo
2412 :type '(choice (const :tag "Head of sequence" nil)
2413 (string :tag "Specific state")))
2414
2a57416f 2415(defcustom org-log-repeat 'time
ed21c5c8 2416 "Non-nil means record moving through the DONE state when triggering repeat.
8d642074 2417An auto-repeating task is immediately switched back to TODO when
86fbb8ca 2418marked DONE. If you are not logging state changes (by adding \"@\"
8d642074
CD
2419or \"!\" to the TODO keyword definition), or set `org-log-done' to
2420record a closing note, there will be no record of the task moving
01c35094 2421through DONE. This variable forces taking a note anyway.
2a57416f
CD
2422
2423nil Don't force a record
2424time Record a time stamp
2425note Record a note
2426
15841868
JW
2427This option can also be set with on a per-file-basis with
2428
2429 #+STARTUP: logrepeat
2a57416f 2430 #+STARTUP: lognoterepeat
15841868
JW
2431 #+STARTUP: nologrepeat
2432
2433You can have local logging settings for a subtree by setting the LOGGING
2434property to one or more of these keywords."
d3f4dbe8
CD
2435 :group 'org-todo
2436 :group 'org-progress
2a57416f
CD
2437 :type '(choice
2438 (const :tag "Don't force a record" nil)
2439 (const :tag "Force recording the DONE state" time)
2440 (const :tag "Force recording a note with the DONE state" note)))
d3f4dbe8 2441
8c6fb58b 2442
ab27a4a0 2443(defgroup org-priorities nil
4146eb16 2444 "Priorities in Org-mode."
ab27a4a0
CD
2445 :tag "Org Priorities"
2446 :group 'org-todo)
28e5b051 2447
c8d0cf5c 2448(defcustom org-enable-priority-commands t
ed21c5c8 2449 "Non-nil means priority commands are active.
c8d0cf5c
CD
2450When nil, these commands will be disabled, so that you never accidentally
2451set a priority."
2452 :group 'org-priorities
2453 :type 'boolean)
2454
a3fbe8c4
CD
2455(defcustom org-highest-priority ?A
2456 "The highest priority of TODO items. A character like ?A, ?B etc.
2457Must have a smaller ASCII number than `org-lowest-priority'."
ab27a4a0
CD
2458 :group 'org-priorities
2459 :type 'character)
891f4676 2460
ab27a4a0 2461(defcustom org-lowest-priority ?C
a3fbe8c4
CD
2462 "The lowest priority of TODO items. A character like ?A, ?B etc.
2463Must have a larger ASCII number than `org-highest-priority'."
2464 :group 'org-priorities
2465 :type 'character)
2466
2467(defcustom org-default-priority ?B
2468 "The default priority of TODO items.
2469This is the priority an item get if no explicit priority is given."
ab27a4a0
CD
2470 :group 'org-priorities
2471 :type 'character)
2472
15841868 2473(defcustom org-priority-start-cycle-with-default t
ed21c5c8 2474 "Non-nil means start with default priority when starting to cycle.
15841868
JW
2475When this is nil, the first step in the cycle will be (depending on the
2476command used) one higher or lower that the default priority."
2477 :group 'org-priorities
2478 :type 'boolean)
2479
acedf35c
CD
2480(defcustom org-get-priority-function nil
2481 "Function to extract the priority from a string.
2482The string is normally the headline. If this is nil Org computes the
2483priority from the priority cookie like [#A] in the headline. It returns
2484an integer, increasing by 1000 for each priority level.
2485The user can set a different function here, which should take a string
2486as an argument and return the numeric priority."
2487 :group 'org-priorities
2488 :type 'function)
2489
ab27a4a0
CD
2490(defgroup org-time nil
2491 "Options concerning time stamps and deadlines in Org-mode."
2492 :tag "Org Time"
2493 :group 'org)
2494
4b3a9ba7 2495(defcustom org-insert-labeled-timestamps-at-point nil
ed21c5c8 2496 "Non-nil means SCHEDULED and DEADLINE timestamps are inserted at point.
4b3a9ba7
CD
2497When nil, these labeled time stamps are forces into the second line of an
2498entry, just after the headline. When scheduling from the global TODO list,
2499the time stamp will always be forced into the second line."
2500 :group 'org-time
2501 :type 'boolean)
2502
ab27a4a0
CD
2503(defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
2504 "Formats for `format-time-string' which are used for time stamps.
2505It is not recommended to change this constant.")
2506
2a57416f
CD
2507(defcustom org-time-stamp-rounding-minutes '(0 5)
2508 "Number of minutes to round time stamps to.
2509These are two values, the first applies when first creating a time stamp.
2510The second applies when changing it with the commands `S-up' and `S-down'.
2511When changing the time stamp, this means that it will change in steps
5bf7807a 2512of N minutes, as given by the second value.
2a57416f
CD
2513
2514When a setting is 0 or 1, insert the time unmodified. Useful rounding
2515numbers should be factors of 60, so for example 5, 10, 15.
2516
86fbb8ca
CD
2517When this is larger than 1, you can still force an exact time stamp by using
2518a double prefix argument to a time stamp command like `C-c .' or `C-c !',
2a57416f
CD
2519and by using a prefix arg to `S-up/down' to specify the exact number
2520of minutes to shift."
ab27a4a0 2521 :group 'org-time
4f91a816 2522 :get (lambda (var) ; Make sure both elements are there
2a57416f
CD
2523 (if (integerp (default-value var))
2524 (list (default-value var) 5)
2525 (default-value var)))
2526 :type '(list
2527 (integer :tag "when inserting times")
2528 (integer :tag "when modifying times")))
2529
20908596 2530;; Normalize old customizations of this variable.
2a57416f
CD
2531(when (integerp org-time-stamp-rounding-minutes)
2532 (setq org-time-stamp-rounding-minutes
2533 (list org-time-stamp-rounding-minutes
2534 org-time-stamp-rounding-minutes)))
ab27a4a0 2535
3278a016 2536(defcustom org-display-custom-times nil
ed21c5c8 2537 "Non-nil means overlay custom formats over all time stamps.
3278a016
CD
2538The formats are defined through the variable `org-time-stamp-custom-formats'.
2539To turn this on on a per-file basis, insert anywhere in the file:
2540 #+STARTUP: customtime"
2541 :group 'org-time
2542 :set 'set-default
2543 :type 'sexp)
2544(make-variable-buffer-local 'org-display-custom-times)
2545
2546(defcustom org-time-stamp-custom-formats
2547 '("<%m/%d/%y %a>" . "<%m/%d/%y %a %H:%M>") ; american
2548 "Custom formats for time stamps. See `format-time-string' for the syntax.
2549These are overlayed over the default ISO format if the variable
b38c6895 2550`org-display-custom-times' is set. Time like %H:%M should be at the
c8d0cf5c
CD
2551end of the second format. The custom formats are also honored by export
2552commands, if custom time display is turned on at the time of export."
3278a016
CD
2553 :group 'org-time
2554 :type 'sexp)
2555
d3f4dbe8
CD
2556(defun org-time-stamp-format (&optional long inactive)
2557 "Get the right format for a time string."
2558 (let ((f (if long (cdr org-time-stamp-formats)
2559 (car org-time-stamp-formats))))
2560 (if inactive
2561 (concat "[" (substring f 1 -1) "]")
2562 f)))
2563
b349f79f 2564(defcustom org-time-clocksum-format "%d:%02d"
86fbb8ca
CD
2565 "The format string used when creating CLOCKSUM lines.
2566This is also used when org-mode generates a time duration."
b349f79f
CD
2567 :group 'org-time
2568 :type 'string)
ce4fdcb9 2569
8bfe682a
CD
2570(defcustom org-time-clocksum-use-fractional nil
2571 "If non-nil, \\[org-clock-display] uses fractional times.
2572org-mode generates a time duration."
2573 :group 'org-time
2574 :type 'boolean)
2575
2576(defcustom org-time-clocksum-fractional-format "%.2f"
2577 "The format string used when creating CLOCKSUM lines, or when
2578org-mode generates a time duration."
2579 :group 'org-time
2580 :type 'string)
2581
20908596
CD
2582(defcustom org-deadline-warning-days 14
2583 "No. of days before expiration during which a deadline becomes active.
2584This variable governs the display in sparse trees and in the agenda.
2585When 0 or negative, it means use this number (the absolute value of it)
c8d0cf5c
CD
2586even if a deadline has a different individual lead time specified.
2587
2588Custom commands can set this variable in the options section."
20908596
CD
2589 :group 'org-time
2590 :group 'org-agenda-daily/weekly
c8d0cf5c 2591 :type 'integer)
20908596 2592
8c6fb58b 2593(defcustom org-read-date-prefer-future t
ed21c5c8 2594 "Non-nil means assume future for incomplete date input from user.
8c6fb58b 2595This affects the following situations:
8bfe682a 25961. The user gives a month but not a year.
86fbb8ca
CD
2597 For example, if it is April and you enter \"feb 2\", this will be read
2598 as Feb 2, *next* year. \"May 5\", however, will be this year.
8bfe682a 25992. The user gives a day, but no month.
8c6fb58b
CD
2600 For example, if today is the 15th, and you enter \"3\", Org-mode will
2601 read this as the third of *next* month. However, if you enter \"17\",
2602 it will be considered as *this* month.
8c6fb58b 2603
8bfe682a
CD
2604If you set this variable to the symbol `time', then also the following
2605will work:
2606
26073. If the user gives a time, but no day. If the time is before now,
2608 to will be interpreted as tomorrow.
20908596 2609
8bfe682a
CD
2610Currently none of this works for ISO week specifications.
2611
2612When this option is nil, the current day, month and year will always be
afe98dfa
CD
2613used as defaults.
2614
2615See also `org-agenda-jump-prefer-future'."
8c6fb58b 2616 :group 'org-time
8bfe682a
CD
2617 :type '(choice
2618 (const :tag "Never" nil)
2619 (const :tag "Check month and day" t)
2620 (const :tag "Check month, day, and time" time)))
8c6fb58b 2621
afe98dfa
CD
2622(defcustom org-agenda-jump-prefer-future 'org-read-date-prefer-future
2623 "Should the agenda jump command prefer the future for incomplete dates?
2624The default is to do the same as configured in `org-read-date-prefer-future'.
2625But you can alse set a deviating value here.
2626This may t or nil, or the symbol `org-read-date-prefer-future'."
01c35094
JB
2627 :group 'org-agenda
2628 :group 'org-time
afe98dfa 2629 :type '(choice
acedf35c 2630 (const :tag "Use org-read-date-prefer-future"
afe98dfa
CD
2631 org-read-date-prefer-future)
2632 (const :tag "Never" nil)
2633 (const :tag "Always" t)))
2634
8c6fb58b 2635(defcustom org-read-date-display-live t
ed21c5c8 2636 "Non-nil means display current interpretation of date prompt live.
8c6fb58b
CD
2637This display will be in an overlay, in the minibuffer."
2638 :group 'org-time
2639 :type 'boolean)
2640
2641(defcustom org-read-date-popup-calendar t
ed21c5c8 2642 "Non-nil means pop up a calendar when prompting for a date.
ab27a4a0
CD
2643In the calendar, the date can be selected with mouse-1. However, the
2644minibuffer will also be active, and you can simply enter the date as well.
2645When nil, only the minibuffer will be available."
2646 :group 'org-time
891f4676 2647 :type 'boolean)
8c6fb58b
CD
2648(if (fboundp 'defvaralias)
2649 (defvaralias 'org-popup-calendar-for-date-prompt
2650 'org-read-date-popup-calendar))
2651
c8d0cf5c
CD
2652(defcustom org-read-date-minibuffer-setup-hook nil
2653 "Hook to be used to set up keys for the date/time interface.
2654Add key definitions to `minibuffer-local-map', which will be a temporary
2655copy."
2656 :group 'org-time
2657 :type 'hook)
2658
8c6fb58b 2659(defcustom org-extend-today-until 0
621f83e4 2660 "The hour when your day really ends. Must be an integer.
8c6fb58b
CD
2661This has influence for the following applications:
2662- When switching the agenda to \"today\". It it is still earlier than
2663 the time given here, the day recognized as TODAY is actually yesterday.
2664- When a date is read from the user and it is still before the time given
2665 here, the current date and time will be assumed to be yesterday, 23:59.
621f83e4 2666 Also, timestamps inserted in remember templates follow this rule.
8c6fb58b 2667
621f83e4
CD
2668IMPORTANT: This is a feature whose implementation is and likely will
2669remain incomplete. Really, it is only here because past midnight seems to
71d35b24 2670be the favorite working time of John Wiegley :-)"
8c6fb58b 2671 :group 'org-time
c8d0cf5c 2672 :type 'integer)
891f4676 2673
0b8568f5 2674(defcustom org-edit-timestamp-down-means-later nil
ed21c5c8 2675 "Non-nil means S-down will increase the time in a time stamp.
0b8568f5
JW
2676When nil, S-up will increase."
2677 :group 'org-time
2678 :type 'boolean)
2679
ab27a4a0 2680(defcustom org-calendar-follow-timestamp-change t
ed21c5c8 2681 "Non-nil means make the calendar window follow timestamp changes.
ab27a4a0
CD
2682When a timestamp is modified and the calendar window is visible, it will be
2683moved to the new date."
2684 :group 'org-time
2685 :type 'boolean)
891f4676 2686
ab27a4a0 2687(defgroup org-tags nil
4146eb16 2688 "Options concerning tags in Org-mode."
ab27a4a0
CD
2689 :tag "Org Tags"
2690 :group 'org)
891f4676 2691
4b3a9ba7
CD
2692(defcustom org-tag-alist nil
2693 "List of tags allowed in Org-mode files.
2694When this list is nil, Org-mode will base TAG input on what is already in the
2695buffer.
0b8568f5
JW
2696The value of this variable is an alist, the car of each entry must be a
2697keyword as a string, the cdr may be a character that is used to select
2698that tag through the fast-tag-selection interface.
2699See the manual for details."
4b3a9ba7
CD
2700 :group 'org-tags
2701 :type '(repeat
7d143c25
CD
2702 (choice
2703 (cons (string :tag "Tag name")
2704 (character :tag "Access char"))
8bfe682a
CD
2705 (list :tag "Start radio group"
2706 (const :startgroup)
2707 (option (string :tag "Group description")))
2708 (list :tag "End radio group"
2709 (const :endgroup)
2710 (option (string :tag "Group description")))
c8d0cf5c
CD
2711 (const :tag "New line" (:newline)))))
2712
2713(defcustom org-tag-persistent-alist nil
2714 "List of tags that will always appear in all Org-mode files.
2715This is in addition to any in buffer settings or customizations
2716of `org-tag-alist'.
2717When this list is nil, Org-mode will base TAG input on `org-tag-alist'.
2718The value of this variable is an alist, the car of each entry must be a
2719keyword as a string, the cdr may be a character that is used to select
2720that tag through the fast-tag-selection interface.
2721See the manual for details.
2722To disable these tags on a per-file basis, insert anywhere in the file:
2723 #+STARTUP: noptag"
2724 :group 'org-tags
2725 :type '(repeat
2726 (choice
2727 (cons (string :tag "Tag name")
2728 (character :tag "Access char"))
2729 (const :tag "Start radio group" (:startgroup))
2730 (const :tag "End radio group" (:endgroup))
2731 (const :tag "New line" (:newline)))))
4b3a9ba7 2732
ed21c5c8
CD
2733(defcustom org-complete-tags-always-offer-all-agenda-tags nil
2734 "If non-nil, always offer completion for all tags of all agenda files.
2735Instead of customizing this variable directly, you might want to
acedf35c 2736set it locally for capture buffers, because there no list of
ed21c5c8
CD
2737tags in that file can be created dynamically (there are none).
2738
acedf35c 2739 (add-hook 'org-capture-mode-hook
ed21c5c8
CD
2740 (lambda ()
2741 (set (make-local-variable
2742 'org-complete-tags-always-offer-all-agenda-tags)
2743 t)))"
2744 :group 'org-tags
2745 :type 'boolean)
2746
b349f79f
CD
2747(defvar org-file-tags nil
2748 "List of tags that can be inherited by all entries in the file.
2749The tags will be inherited if the variable `org-use-tag-inheritance'
2750says they should be.
8bfe682a 2751This variable is populated from #+FILETAGS lines.")
b349f79f 2752
4b3a9ba7 2753(defcustom org-use-fast-tag-selection 'auto
ed21c5c8 2754 "Non-nil means use fast tag selection scheme.
4b3a9ba7
CD
2755This is a special interface to select and deselect tags with single keys.
2756When nil, fast selection is never used.
2757When the symbol `auto', fast selection is used if and only if selection
2758characters for tags have been configured, either through the variable
2759`org-tag-alist' or through a #+TAGS line in the buffer.
2760When t, fast selection is always used and selection keys are assigned
2761automatically if necessary."
2762 :group 'org-tags
2763 :type '(choice
2764 (const :tag "Always" t)
2765 (const :tag "Never" nil)
2766 (const :tag "When selection characters are configured" 'auto)))
2767
3278a016 2768(defcustom org-fast-tag-selection-single-key nil
ed21c5c8 2769 "Non-nil means fast tag selection exits after first change.
3278a016 2770When nil, you have to press RET to exit it.
d3f4dbe8
CD
2771During fast tag selection, you can toggle this flag with `C-c'.
2772This variable can also have the value `expert'. In this case, the window
2773displaying the tags menu is not even shown, until you press C-c again."
3278a016 2774 :group 'org-tags
d3f4dbe8
CD
2775 :type '(choice
2776 (const :tag "No" nil)
2777 (const :tag "Yes" t)
2778 (const :tag "Expert" expert)))
3278a016 2779
d5098885 2780(defvar org-fast-tag-selection-include-todo nil
ed21c5c8 2781 "Non-nil means fast tags selection interface will also offer TODO states.
d5098885 2782This is an undocumented feature, you should not rely on it.")
0b8568f5 2783
5ace2fe5 2784(defcustom org-tags-column (if (featurep 'xemacs) -76 -77)
ab27a4a0
CD
2785 "The column to which tags should be indented in a headline.
2786If this number is positive, it specifies the column. If it is negative,
2787it means that the tags should be flushright to that column. For example,
15841868 2788-80 works well for a normal 80 character screen."
ab27a4a0
CD
2789 :group 'org-tags
2790 :type 'integer)
891f4676 2791
ab27a4a0 2792(defcustom org-auto-align-tags t
ed21c5c8 2793 "Non-nil means realign tags after pro/demotion of TODO state change.
ab27a4a0
CD
2794These operations change the length of a headline and therefore shift
2795the tags around. With this options turned on, after each such operation
2796the tags are again aligned to `org-tags-column'."
2797 :group 'org-tags
2798 :type 'boolean)
891f4676 2799
ab27a4a0 2800(defcustom org-use-tag-inheritance t
ed21c5c8 2801 "Non-nil means tags in levels apply also for sublevels.
ab27a4a0 2802When nil, only the tags directly given in a specific line apply there.
20908596 2803This may also be a list of tags that should be inherited, or a regexp that
ff4be292
CD
2804matches tags that should be inherited. Additional control is possible
2805with the variable `org-tags-exclude-from-inheritance' which gives an
2806explicit list of tags to be excluded from inheritance., even if the value of
2807`org-use-tag-inheritance' would select it for inheritance.
2808
2809If this option is t, a match early-on in a tree can lead to a large
2810number of matches in the subtree when constructing the agenda or creating
2811a sparse tree. If you only want to see the first match in a tree during
2812a search, check out the variable `org-tags-match-list-sublevels'."
ab27a4a0 2813 :group 'org-tags
20908596
CD
2814 :type '(choice
2815 (const :tag "Not" nil)
2816 (const :tag "Always" t)
2817 (repeat :tag "Specific tags" (string :tag "Tag"))
2818 (regexp :tag "Tags matched by regexp")))
2819
ff4be292
CD
2820(defcustom org-tags-exclude-from-inheritance nil
2821 "List of tags that should never be inherited.
2822This is a way to exclude a few tags from inheritance. For way to do
2823the opposite, to actively allow inheritance for selected tags,
2824see the variable `org-use-tag-inheritance'."
2825 :group 'org-tags
2826 :type '(repeat (string :tag "Tag")))
2827
20908596
CD
2828(defun org-tag-inherit-p (tag)
2829 "Check if TAG is one that should be inherited."
2830 (cond
ff4be292 2831 ((member tag org-tags-exclude-from-inheritance) nil)
20908596
CD
2832 ((eq org-use-tag-inheritance t) t)
2833 ((not org-use-tag-inheritance) nil)
2834 ((stringp org-use-tag-inheritance)
2835 (string-match org-use-tag-inheritance tag))
2836 ((listp org-use-tag-inheritance)
2837 (member tag org-use-tag-inheritance))
2838 (t (error "Invalid setting of `org-use-tag-inheritance'"))))
ab27a4a0 2839
b349f79f 2840(defcustom org-tags-match-list-sublevels t
c8d0cf5c
CD
2841 "Non-nil means list also sublevels of headlines matching a search.
2842This variable applies to tags/property searches, and also to stuck
2843projects because this search is based on a tags match as well.
2844
2845When set to the symbol `indented', sublevels are indented with
2846leading dots.
2847
ab27a4a0
CD
2848Because of tag inheritance (see variable `org-use-tag-inheritance'),
2849the sublevels of a headline matching a tag search often also match
2850the same search. Listing all of them can create very long lists.
2851Setting this variable to nil causes subtrees of a match to be skipped.
ff4be292
CD
2852
2853This variable is semi-obsolete and probably should always be true. It
2854is better to limit inheritance to certain tags using the variables
33306645 2855`org-use-tag-inheritance' and `org-tags-exclude-from-inheritance'."
ab27a4a0 2856 :group 'org-tags
c8d0cf5c
CD
2857 :type '(choice
2858 (const :tag "No, don't list them" nil)
2859 (const :tag "Yes, do list them" t)
2860 (const :tag "List them, indented with leading dots" indented)))
2861
2862(defcustom org-tags-sort-function nil
86fbb8ca 2863 "When set, tags are sorted using this function as a comparator."
c8d0cf5c
CD
2864 :group 'org-tags
2865 :type '(choice
2866 (const :tag "No sorting" nil)
2867 (const :tag "Alphabetical" string<)
2868 (const :tag "Reverse alphabetical" string>)
2869 (function :tag "Custom function" nil)))
ab27a4a0
CD
2870
2871(defvar org-tags-history nil
2872 "History of minibuffer reads for tags.")
2873(defvar org-last-tags-completion-table nil
2874 "The last used completion table for tags.")
d5098885
JW
2875(defvar org-after-tags-change-hook nil
2876 "Hook that is run after the tags in a line have changed.")
ab27a4a0 2877
38f8646b
CD
2878(defgroup org-properties nil
2879 "Options concerning properties in Org-mode."
2880 :tag "Org Properties"
2881 :group 'org)
2882
2883(defcustom org-property-format "%-10s %s"
2884 "How property key/value pairs should be formatted by `indent-line'.
2885When `indent-line' hits a property definition, it will format the line
2886according to this format, mainly to make sure that the values are
2887lined-up with respect to each other."
2888 :group 'org-properties
2889 :type 'string)
2890
03f3cf35 2891(defcustom org-use-property-inheritance nil
ed21c5c8 2892 "Non-nil means properties apply also for sublevels.
20908596 2893
86fbb8ca 2894This setting is chiefly used during property searches. Turning it on can
20908596
CD
2895cause significant overhead when doing a search, which is why it is not
2896on by default.
2897
03f3cf35 2898When nil, only the properties directly given in the current entry count.
20908596
CD
2899When t, every property is inherited. The value may also be a list of
2900properties that should have inheritance, or a regular expression matching
2901properties that should be inherited.
03f3cf35
JW
2902
2903However, note that some special properties use inheritance under special
2904circumstances (not in searches). Examples are CATEGORY, ARCHIVE, COLUMNS,
2905and the properties ending in \"_ALL\" when they are used as descriptor
20908596
CD
2906for valid values of a property.
2907
2908Note for programmers:
2909When querying an entry with `org-entry-get', you can control if inheritance
2910should be used. By default, `org-entry-get' looks only at the local
2911properties. You can request inheritance by setting the inherit argument
2912to t (to force inheritance) or to `selective' (to respect the setting
2913in this variable)."
03f3cf35 2914 :group 'org-properties
8c6fb58b
CD
2915 :type '(choice
2916 (const :tag "Not" nil)
20908596
CD
2917 (const :tag "Always" t)
2918 (repeat :tag "Specific properties" (string :tag "Property"))
2919 (regexp :tag "Properties matched by regexp")))
2920
2921(defun org-property-inherit-p (property)
2922 "Check if PROPERTY is one that should be inherited."
2923 (cond
2924 ((eq org-use-property-inheritance t) t)
2925 ((not org-use-property-inheritance) nil)
2926 ((stringp org-use-property-inheritance)
2927 (string-match org-use-property-inheritance property))
2928 ((listp org-use-property-inheritance)
2929 (member property org-use-property-inheritance))
2930 (t (error "Invalid setting of `org-use-property-inheritance'"))))
03f3cf35 2931
7d58338e 2932(defcustom org-columns-default-format "%25ITEM %TODO %3PRIORITY %TAGS"
38f8646b
CD
2933 "The default column format, if no other format has been defined.
2934This variable can be set on the per-file basis by inserting a line
2935
2936#+COLUMNS: %25ITEM ....."
2937 :group 'org-properties
2938 :type 'string)
2939
b349f79f
CD
2940(defcustom org-columns-ellipses ".."
2941 "The ellipses to be used when a field in column view is truncated.
2942When this is the empty string, as many characters as possible are shown,
2943but then there will be no visual indication that the field has been truncated.
2944When this is a string of length N, the last N characters of a truncated
2945field are replaced by this string. If the column is narrower than the
2946ellipses string, only part of the ellipses string will be shown."
2947 :group 'org-properties
2948 :type 'string)
2949
621f83e4
CD
2950(defcustom org-columns-modify-value-for-display-function nil
2951 "Function that modifies values for display in column view.
2952For example, it can be used to cut out a certain part from a time stamp.
40ac2137 2953The function must take 2 arguments:
621f83e4 2954
33306645 2955column-title The title of the column (*not* the property name)
621f83e4
CD
2956value The value that should be modified.
2957
2958The function should return the value that should be displayed,
2959or nil if the normal value should be used."
2960 :group 'org-properties
2961 :type 'function)
b349f79f 2962
20908596
CD
2963(defcustom org-effort-property "Effort"
2964 "The property that is being used to keep track of effort estimates.
2965Effort estimates given in this property need to have the format H:MM."
2966 :group 'org-properties
2967 :group 'org-progress
2968 :type '(string :tag "Property"))
2969
b349f79f 2970(defconst org-global-properties-fixed
c8d0cf5c
CD
2971 '(("VISIBILITY_ALL" . "folded children content all")
2972 ("CLOCK_MODELINE_TOTAL_ALL" . "current today repeat all auto"))
b349f79f 2973 "List of property/value pairs that can be inherited by any entry.
b349f79f 2974
c8d0cf5c
CD
2975These are fixed values, for the preset properties. The user variable
2976that can be used to add to this list is `org-global-properties'.
2977
2978The entries in this list are cons cells where the car is a property
2979name and cdr is a string with the value. If the value represents
2980multiple items like an \"_ALL\" property, separate the items by
2981spaces.")
b349f79f 2982
48aaad2d
CD
2983(defcustom org-global-properties nil
2984 "List of property/value pairs that can be inherited by any entry.
c8d0cf5c
CD
2985
2986This list will be combined with the constant `org-global-properties-fixed'.
2987
2988The entries in this list are cons cells where the car is a property
2989name and cdr is a string with the value.
2990
ce4fdcb9
CD
2991You can set buffer-local values for the same purpose in the variable
2992`org-file-properties' this by adding lines like
48aaad2d
CD
2993
2994#+PROPERTY: NAME VALUE"
2995 :group 'org-properties
2996 :type '(repeat
2997 (cons (string :tag "Property")
2998 (string :tag "Value"))))
2999
b349f79f 3000(defvar org-file-properties nil
48aaad2d
CD
3001 "List of property/value pairs that can be inherited by any entry.
3002Valid for the current buffer.
3003This variable is populated from #+PROPERTY lines.")
b349f79f 3004(make-variable-buffer-local 'org-file-properties)
38f8646b 3005
ab27a4a0 3006(defgroup org-agenda nil
d3f4dbe8 3007 "Options concerning agenda views in Org-mode."
ab27a4a0
CD
3008 :tag "Org Agenda"
3009 :group 'org)
3010
3011(defvar org-category nil
3012 "Variable used by org files to set a category for agenda display.
3013Such files should use a file variable to set it, for example
3014
a3fbe8c4 3015# -*- mode: org; org-category: \"ELisp\"
ab27a4a0
CD
3016
3017or contain a special line
3018
3019#+CATEGORY: ELisp
3020
3021If the file does not specify a category, then file's base name
3022is used instead.")
3023(make-variable-buffer-local 'org-category)
4f91a816 3024(put 'org-category 'safe-local-variable (lambda (x) (or (symbolp x) (stringp x))))
ab27a4a0
CD
3025
3026(defcustom org-agenda-files nil
3027 "The files to be used for agenda display.
3028Entries may be added to this list with \\[org-agenda-file-to-front] and removed with
3029\\[org-remove-file]. You can also use customize to edit the list.
3030
03f3cf35
JW
3031If an entry is a directory, all files in that directory that are matched by
3032`org-agenda-file-regexp' will be part of the file list.
3033
ab27a4a0
CD
3034If the value of the variable is not a list but a single file name, then
3035the list of agenda files is actually stored and maintained in that file, one
ed21c5c8
CD
3036agenda file per line. In this file paths can be given relative to
3037`org-directory'. Tilde expansion and environment variable substitution
3038are also made."
ab27a4a0 3039 :group 'org-agenda
891f4676 3040 :type '(choice
03f3cf35 3041 (repeat :tag "List of files and directories" file)
ab27a4a0 3042 (file :tag "Store list in a file\n" :value "~/.agenda_files")))
891f4676 3043
8c6fb58b 3044(defcustom org-agenda-file-regexp "\\`[^.].*\\.org\\'"
03f3cf35 3045 "Regular expression to match files for `org-agenda-files'.
fbe6c10d 3046If any element in the list in that variable contains a directory instead
03f3cf35
JW
3047of a normal file, all files in that directory that are matched by this
3048regular expression will be included."
3049 :group 'org-agenda
3050 :type 'regexp)
3051
2a57416f
CD
3052(defcustom org-agenda-text-search-extra-files nil
3053 "List of extra files to be searched by text search commands.
20908596 3054These files will be search in addition to the agenda files by the
2a57416f
CD
3055commands `org-search-view' (`C-c a s') and `org-occur-in-agenda-files'.
3056Note that these files will only be searched for text search commands,
20908596 3057not for the other agenda views like todo lists, tag searches or the weekly
2a57416f 3058agenda. This variable is intended to list notes and possibly archive files
20908596
CD
3059that should also be searched by these two commands.
3060In fact, if the first element in the list is the symbol `agenda-archives',
3061than all archive files of all agenda files will be added to the search
3062scope."
03f3cf35 3063 :group 'org-agenda
20908596
CD
3064 :type '(set :greedy t
3065 (const :tag "Agenda Archives" agenda-archives)
3066 (repeat :inline t (file))))
03f3cf35 3067
2a57416f
CD
3068(if (fboundp 'defvaralias)
3069 (defvaralias 'org-agenda-multi-occur-extra-files
3070 'org-agenda-text-search-extra-files))
3071
20908596 3072(defcustom org-agenda-skip-unavailable-files nil
cf7241c8
JB
3073 "Non-nil means to just skip non-reachable files in `org-agenda-files'.
3074A nil value means to remove them, after a query, from the list."
d3f4dbe8 3075 :group 'org-agenda
20908596 3076 :type 'boolean)
d3f4dbe8
CD
3077
3078(defcustom org-calendar-to-agenda-key [?c]
3079 "The key to be installed in `calendar-mode-map' for switching to the agenda.
3080The command `org-calendar-goto-agenda' will be bound to this key. The
3081default is the character `c' because then `c' can be used to switch back and
3082forth between agenda and calendar."
3083 :group 'org-agenda
3084 :type 'sexp)
3085
b349f79f
CD
3086(defcustom org-calendar-agenda-action-key [?k]
3087 "The key to be installed in `calendar-mode-map' for agenda-action.
3088The command `org-agenda-action' will be bound to this key. The
3089default is the character `k' because we use the same key in the agenda."
3090 :group 'org-agenda
3091 :type 'sexp)
3092
8bfe682a
CD
3093(defcustom org-calendar-insert-diary-entry-key [?i]
3094 "The key to be installed in `calendar-mode-map' for adding diary entries.
3095This option is irrelevant until `org-agenda-diary-file' has been configured
3096to point to an Org-mode file. When that is the case, the command
3097`org-agenda-diary-entry' will be bound to the key given here, by default
3098`i'. In the calendar, `i' normally adds entries to `diary-file'. So
3099if you want to continue doing this, you need to change this to a different
3100key."
3101 :group 'org-agenda
3102 :type 'sexp)
3103
3104(defcustom org-agenda-diary-file 'diary-file
3105 "File to which to add new entries with the `i' key in agenda and calendar.
3106When this is the symbol `diary-file', the functionality in the Emacs
3107calendar will be used to add entries to the `diary-file'. But when this
3108points to a file, `org-agenda-diary-entry' will be used instead."
3109 :group 'org-agenda
3110 :type '(choice
3111 (const :tag "The standard Emacs diary file" diary-file)
3112 (file :tag "Special Org file diary entries")))
3113
20908596 3114(eval-after-load "calendar"
b349f79f
CD
3115 '(progn
3116 (org-defkey calendar-mode-map org-calendar-to-agenda-key
3117 'org-calendar-goto-agenda)
3118 (org-defkey calendar-mode-map org-calendar-agenda-action-key
8bfe682a
CD
3119 'org-agenda-action)
3120 (add-hook 'calendar-mode-hook
3121 (lambda ()
3122 (unless (eq org-agenda-diary-file 'diary-file)
3123 (define-key calendar-mode-map
3124 org-calendar-insert-diary-entry-key
3125 'org-agenda-diary-entry))))))
03f3cf35 3126
6769c0dc 3127(defgroup org-latex nil
5bf7807a 3128 "Options for embedding LaTeX code into Org-mode."
6769c0dc
CD
3129 :tag "Org LaTeX"
3130 :group 'org)
3131
3132(defcustom org-format-latex-options
a3fbe8c4 3133 '(:foreground default :background default :scale 1.0
afe98dfa
CD
3134 :html-foreground "Black" :html-background "Transparent"
3135 :html-scale 1.0 :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))
6769c0dc
CD
3136 "Options for creating images from LaTeX fragments.
3137This is a property list with the following properties:
efc054e6
JB
3138:foreground the foreground color for images embedded in Emacs, e.g. \"Black\".
3139 `default' means use the foreground of the default face.
6769c0dc 3140:background the background color, or \"Transparent\".
a3fbe8c4 3141 `default' means use the background of the default face.
afe98dfa 3142:scale a scaling factor for the size of the images, to get more pixels
a3fbe8c4 3143:html-foreground, :html-background, :html-scale
efc054e6 3144 the same numbers for HTML export.
6769c0dc
CD
3145:matchers a list indicating which matchers should be used to
3146 find LaTeX fragments. Valid members of this list are:
3147 \"begin\" find environments
0bd48b37 3148 \"$1\" find single characters surrounded by $.$
e39856be 3149 \"$\" find math expressions surrounded by $...$
6769c0dc 3150 \"$$\" find math expressions surrounded by $$....$$
e39856be
CD
3151 \"\\(\" find math expressions surrounded by \\(...\\)
3152 \"\\ [\" find math expressions surrounded by \\ [...\\]"
15841868 3153 :group 'org-latex
6769c0dc
CD
3154 :type 'plist)
3155
ed21c5c8
CD
3156(defcustom org-format-latex-signal-error t
3157 "Non-nil means signal an error when image creation of LaTeX snippets fails.
3158When nil, just push out a message."
3159 :group 'org-latex
3160 :type 'boolean)
3161
a3fbe8c4 3162(defcustom org-format-latex-header "\\documentclass{article}
a3fbe8c4
CD
3163\\usepackage[usenames]{color}
3164\\usepackage{amsmath}
a3fbe8c4 3165\\usepackage[mathscr]{eucal}
8d642074 3166\\pagestyle{empty} % do not remove
ed21c5c8
CD
3167\[PACKAGES]
3168\[DEFAULT-PACKAGES]
8d642074
CD
3169% The settings below are copied from fullpage.sty
3170\\setlength{\\textwidth}{\\paperwidth}
3171\\addtolength{\\textwidth}{-3cm}
3172\\setlength{\\oddsidemargin}{1.5cm}
3173\\addtolength{\\oddsidemargin}{-2.54cm}
3174\\setlength{\\evensidemargin}{\\oddsidemargin}
3175\\setlength{\\textheight}{\\paperheight}
3176\\addtolength{\\textheight}{-\\headheight}
3177\\addtolength{\\textheight}{-\\headsep}
3178\\addtolength{\\textheight}{-\\footskip}
3179\\addtolength{\\textheight}{-3cm}
3180\\setlength{\\topmargin}{1.5cm}
3181\\addtolength{\\topmargin}{-2.54cm}"
3182 "The document header used for processing LaTeX fragments.
3183It is imperative that this header make sure that no page number
ed21c5c8
CD
3184appears on the page. The package defined in the variables
3185`org-export-latex-default-packages-alist' and `org-export-latex-packages-alist'
3186will either replace the placeholder \"[PACKAGES]\" in this header, or they
3187will be appended."
15841868 3188 :group 'org-latex
a3fbe8c4
CD
3189 :type 'string)
3190
ed21c5c8
CD
3191(defvar org-format-latex-header-extra nil)
3192
86fbb8ca
CD
3193(defun org-set-packages-alist (var val)
3194 "Set the packages alist and make sure it has 3 elements per entry."
3195 (set var (mapcar (lambda (x)
3196 (if (and (consp x) (= (length x) 2))
3197 (list (car x) (nth 1 x) t)
3198 x))
3199 val)))
3200
3201(defun org-get-packages-alist (var)
3202
3203 "Get the packages alist and make sure it has 3 elements per entry."
3204 (mapcar (lambda (x)
3205 (if (and (consp x) (= (length x) 2))
3206 (list (car x) (nth 1 x) t)
3207 x))
3208 (default-value var)))
3209
ed21c5c8 3210;; The following variables are defined here because is it also used
5dec9555
CD
3211;; when formatting latex fragments. Originally it was part of the
3212;; LaTeX exporter, which is why the name includes "export".
ed21c5c8 3213(defcustom org-export-latex-default-packages-alist
86fbb8ca
CD
3214 '(("AUTO" "inputenc" t)
3215 ("T1" "fontenc" t)
3216 ("" "fixltx2e" nil)
3217 ("" "graphicx" t)
3218 ("" "longtable" nil)
3219 ("" "float" nil)
3220 ("" "wrapfig" nil)
3221 ("" "soul" t)
86fbb8ca
CD
3222 ("" "textcomp" t)
3223 ("" "marvosym" t)
3224 ("" "wasysym" t)
3225 ("" "latexsym" t)
3226 ("" "amssymb" t)
3227 ("" "hyperref" nil)
ed21c5c8
CD
3228 "\\tolerance=1000"
3229 )
3230 "Alist of default packages to be inserted in the header.
3231Change this only if one of the packages here causes an incompatibility
3232with another package you are using.
3233The packages in this list are needed by one part or another of Org-mode
86fbb8ca 3234to function properly.
ed21c5c8 3235
afe98dfa 3236- inputenc, fontenc: for basic font and character selection
ed21c5c8
CD
3237- textcomp, marvosymb, wasysym, latexsym, amssym: for various symbols used
3238 for interpreting the entities in `org-entities'. You can skip some of these
3239 packages if you don't use any of the symbols in it.
3240- graphicx: for including images
3241- float, wrapfig: for figure placement
3242- longtable: for long tables
3243- hyperref: for cross references
3244
3245Therefore you should not modify this variable unless you know what you
3246are doing. The one reason to change it anyway is that you might be loading
3247some other package that conflicts with one of the default packages.
86fbb8ca
CD
3248Each cell is of the format \( \"options\" \"package\" snippet-flag\).
3249If SNIPPET-FLAG is t, the package also needs to be included when
3250compiling LaTeX snippets into images for inclusion into HTML."
5dec9555 3251 :group 'org-export-latex
86fbb8ca
CD
3252 :set 'org-set-packages-alist
3253 :get 'org-get-packages-alist
5dec9555 3254 :type '(repeat
86fbb8ca 3255 (choice
ed21c5c8
CD
3256 (list :tag "options/package pair"
3257 (string :tag "options")
86fbb8ca
CD
3258 (string :tag "package")
3259 (boolean :tag "Snippet"))
3260 (string :tag "A line of LaTeX"))))
5152b597 3261
ed21c5c8 3262(defcustom org-export-latex-packages-alist nil
86fbb8ca 3263 "Alist of packages to be inserted in every LaTeX header.
ed21c5c8 3264These will be inserted after `org-export-latex-default-packages-alist'.
86fbb8ca
CD
3265Each cell is of the format \( \"options\" \"package\" snippet-flag \).
3266SNIPPET-FLAG, when t, indicates that this package is also needed when
3267turning LaTeX snippets into images for inclusion into HTML.
3268Make sure that you only list packages here which:
ed21c5c8
CD
3269- you want in every file
3270- do not conflict with the default packages in
3271 `org-export-latex-default-packages-alist'
3272- do not conflict with the setup in `org-format-latex-header'."
3273 :group 'org-export-latex
86fbb8ca
CD
3274 :set 'org-set-packages-alist
3275 :get 'org-get-packages-alist
ed21c5c8 3276 :type '(repeat
86fbb8ca 3277 (choice
ed21c5c8
CD
3278 (list :tag "options/package pair"
3279 (string :tag "options")
86fbb8ca
CD
3280 (string :tag "package")
3281 (boolean :tag "Snippet"))
3282 (string :tag "A line of LaTeX"))))
3283
ed21c5c8
CD
3284
3285(defgroup org-appearance nil
3286 "Settings for Org-mode appearance."
3287 :tag "Org Appearance"
20908596 3288 :group 'org)
8c6fb58b 3289
20908596
CD
3290(defcustom org-level-color-stars-only nil
3291 "Non-nil means fontify only the stars in each headline.
3292When nil, the entire headline is fontified.
3293Changing it requires restart of `font-lock-mode' to become effective
3294also in regions already fontified."
ed21c5c8 3295 :group 'org-appearance
6769c0dc
CD
3296 :type 'boolean)
3297
20908596 3298(defcustom org-hide-leading-stars nil
ed21c5c8 3299 "Non-nil means hide the first N-1 stars in a headline.
20908596
CD
3300This works by using the face `org-hide' for these stars. This
3301face is white for a light background, and black for a dark
3302background. You may have to customize the face `org-hide' to
3303make this work.
3304Changing it requires restart of `font-lock-mode' to become effective
3305also in regions already fontified.
3306You may also set this on a per-file basis by adding one of the following
3307lines to the buffer:
891f4676 3308
20908596
CD
3309 #+STARTUP: hidestars
3310 #+STARTUP: showstars"
ed21c5c8 3311 :group 'org-appearance
891f4676
RS
3312 :type 'boolean)
3313
ed21c5c8
CD
3314(defcustom org-hidden-keywords nil
3315 "List of keywords that should be hidden when typed in the org buffer.
3316For example, add #+TITLE to this list in order to make the
3317document title appear in the buffer without the initial #+TITLE:
3318keyword."
3319 :group 'org-appearance
3320 :type '(set (const :tag "#+AUTHOR" author)
3321 (const :tag "#+DATE" date)
3322 (const :tag "#+EMAIL" email)
3323 (const :tag "#+TITLE" title)))
3324
20908596 3325(defcustom org-fontify-done-headline nil
ed21c5c8 3326 "Non-nil means change the face of a headline if it is marked DONE.
20908596
CD
3327Normally, only the TODO/DONE keyword indicates the state of a headline.
3328When this is non-nil, the headline after the keyword is set to the
3329`org-headline-done' as an additional indication."
ed21c5c8 3330 :group 'org-appearance
ab27a4a0
CD
3331 :type 'boolean)
3332
20908596
CD
3333(defcustom org-fontify-emphasized-text t
3334 "Non-nil means fontify *bold*, /italic/ and _underlined_ text.
3335Changing this variable requires a restart of Emacs to take effect."
ed21c5c8 3336 :group 'org-appearance
891f4676
RS
3337 :type 'boolean)
3338
c8d0cf5c
CD
3339(defcustom org-fontify-whole-heading-line nil
3340 "Non-nil means fontify the whole line for headings.
3341This is useful when setting a background color for the
8bfe682a 3342org-level-* faces."
ed21c5c8 3343 :group 'org-appearance
c8d0cf5c
CD
3344 :type 'boolean)
3345
20908596 3346(defcustom org-highlight-latex-fragments-and-specials nil
ed21c5c8
CD
3347 "Non-nil means fontify what is treated specially by the exporters."
3348 :group 'org-appearance
a96ee7df
CD
3349 :type 'boolean)
3350
20908596
CD
3351(defcustom org-hide-emphasis-markers nil
3352 "Non-nil mean font-lock should hide the emphasis marker characters."
ed21c5c8 3353 :group 'org-appearance
8c6fb58b
CD
3354 :type 'boolean)
3355
86fbb8ca
CD
3356(defcustom org-pretty-entities nil
3357 "Non-nil means show entities as UTF8 characters.
3358When nil, the \\name form remains in the buffer."
3359 :group 'org-appearance
3360 :type 'boolean)
3361
3362(defcustom org-pretty-entities-include-sub-superscripts t
3363 "Non-nil means, pretty entity display includes formatting sub/superscripts."
3364 :group 'org-appearance
3365 :type 'boolean)
3366
edd21304 3367(defvar org-emph-re nil
86fbb8ca
CD
3368 "Regular expression for matching emphasis.
3369After a match, the match groups contain these elements:
afe98dfa
CD
33700 The match of the full regular expression, including the characters
3371 before and after the proper match
86fbb8ca
CD
33721 The character before the proper match, or empty at beginning of line
33732 The proper match, including the leading and trailing markers
33743 The leading marker like * or /, indicating the type of highlighting
33754 The text between the emphasis markers, not including the markers
33765 The character after the match, empty at the end of a line")
8c6fb58b
CD
3377(defvar org-verbatim-re nil
3378 "Regular expression for matching verbatim text.")
edd21304
CD
3379(defvar org-emphasis-regexp-components) ; defined just below
3380(defvar org-emphasis-alist) ; defined just below
3381(defun org-set-emph-re (var val)
3382 "Set variable and compute the emphasis regular expression."
3383 (set var val)
3384 (when (and (boundp 'org-emphasis-alist)
3385 (boundp 'org-emphasis-regexp-components)
3386 org-emphasis-alist org-emphasis-regexp-components)
3387 (let* ((e org-emphasis-regexp-components)
3388 (pre (car e))
3389 (post (nth 1 e))
3390 (border (nth 2 e))
3391 (body (nth 3 e))
3392 (nl (nth 4 e))
edd21304 3393 (body1 (concat body "*?"))
8c6fb58b
CD
3394 (markers (mapconcat 'car org-emphasis-alist ""))
3395 (vmarkers (mapconcat
3396 (lambda (x) (if (eq (nth 4 x) 'verbatim) (car x) ""))
3397 org-emphasis-alist "")))
edd21304
CD
3398 ;; make sure special characters appear at the right position in the class
3399 (if (string-match "\\^" markers)
3400 (setq markers (concat (replace-match "" t t markers) "^")))
3401 (if (string-match "-" markers)
3402 (setq markers (concat (replace-match "" t t markers) "-")))
8c6fb58b
CD
3403 (if (string-match "\\^" vmarkers)
3404 (setq vmarkers (concat (replace-match "" t t vmarkers) "^")))
3405 (if (string-match "-" vmarkers)
3406 (setq vmarkers (concat (replace-match "" t t vmarkers) "-")))
3278a016
CD
3407 (if (> nl 0)
3408 (setq body1 (concat body1 "\\(?:\n" body "*?\\)\\{0,"
3409 (int-to-string nl) "\\}")))
edd21304
CD
3410 ;; Make the regexp
3411 (setq org-emph-re
65c439fd 3412 (concat "\\([" pre "]\\|^\\)"
edd21304
CD
3413 "\\("
3414 "\\([" markers "]\\)"
3415 "\\("
8c6fb58b 3416 "[^" border "]\\|"
65c439fd 3417 "[^" border "]"
edd21304 3418 body1
65c439fd 3419 "[^" border "]"
edd21304
CD
3420 "\\)"
3421 "\\3\\)"
65c439fd 3422 "\\([" post "]\\|$\\)"))
8c6fb58b
CD
3423 (setq org-verbatim-re
3424 (concat "\\([" pre "]\\|^\\)"
3425 "\\("
3426 "\\([" vmarkers "]\\)"
3427 "\\("
3428 "[^" border "]\\|"
3429 "[^" border "]"
3430 body1
3431 "[^" border "]"
3432 "\\)"
3433 "\\3\\)"
3434 "\\([" post "]\\|$\\)")))))
edd21304
CD
3435
3436(defcustom org-emphasis-regexp-components
c8d0cf5c 3437 '(" \t('\"{" "- \t.,:!?;'\")}\\" " \t\r\n,\"'" "." 1)
8c6fb58b 3438 "Components used to build the regular expression for emphasis.
acedf35c 3439This is a list with five entries. Terminology: In an emphasis string
edd21304
CD
3440like \" *strong word* \", we call the initial space PREMATCH, the final
3441space POSTMATCH, the stars MARKERS, \"s\" and \"d\" are BORDER characters
3442and \"trong wor\" is the body. The different components in this variable
3443specify what is allowed/forbidden in each part:
3444
3445pre Chars allowed as prematch. Beginning of line will be allowed too.
3446post Chars allowed as postmatch. End of line will be allowed too.
a3fbe8c4 3447border The chars *forbidden* as border characters.
edd21304
CD
3448body-regexp A regexp like \".\" to match a body character. Don't use
3449 non-shy groups here, and don't allow newline here.
3450newline The maximum number of newlines allowed in an emphasis exp.
8c6fb58b 3451
c44f0d75 3452Use customize to modify this, or restart Emacs after changing it."
ed21c5c8 3453 :group 'org-appearance
edd21304
CD
3454 :set 'org-set-emph-re
3455 :type '(list
3456 (sexp :tag "Allowed chars in pre ")
3457 (sexp :tag "Allowed chars in post ")
3458 (sexp :tag "Forbidden chars in border ")
3459 (sexp :tag "Regexp for body ")
3460 (integer :tag "number of newlines allowed")
b349f79f 3461 (option (boolean :tag "Please ignore this button"))))
edd21304
CD
3462
3463(defcustom org-emphasis-alist
20908596 3464 `(("*" bold "<b>" "</b>")
edd21304 3465 ("/" italic "<i>" "</i>")
93b62de8 3466 ("_" underline "<span style=\"text-decoration:underline;\">" "</span>")
8c6fb58b 3467 ("=" org-code "<code>" "</code>" verbatim)
93b62de8 3468 ("~" org-verbatim "<code>" "</code>" verbatim)
20908596
CD
3469 ("+" ,(if (featurep 'xemacs) 'org-table '(:strike-through t))
3470 "<del>" "</del>")
a3fbe8c4 3471 )
8c6fb58b 3472 "Special syntax for emphasized text.
edd21304
CD
3473Text starting and ending with a special character will be emphasized, for
3474example *bold*, _underlined_ and /italic/. This variable sets the marker
a3fbe8c4 3475characters, the face to be used by font-lock for highlighting in Org-mode
c44f0d75 3476Emacs buffers, and the HTML tags to be used for this.
c8d0cf5c 3477For LaTeX export, see the variable `org-export-latex-emphasis-alist'.
86fbb8ca 3478For DocBook export, see the variable `org-export-docbook-emphasis-alist'.
c44f0d75 3479Use customize to modify this, or restart Emacs after changing it."
ed21c5c8 3480 :group 'org-appearance
edd21304
CD
3481 :set 'org-set-emph-re
3482 :type '(repeat
3483 (list
3484 (string :tag "Marker character")
0fee8d6e
CD
3485 (choice
3486 (face :tag "Font-lock-face")
3487 (plist :tag "Face property list"))
edd21304 3488 (string :tag "HTML start tag")
8c6fb58b
CD
3489 (string :tag "HTML end tag")
3490 (option (const verbatim)))))
edd21304 3491
c8d0cf5c
CD
3492(defvar org-protecting-blocks
3493 '("src" "example" "latex" "ascii" "html" "docbook" "ditaa" "dot" "r" "R")
3494 "Blocks that contain text that is quoted, i.e. not processed as Org syntax.
3495This is needed for font-lock setup.")
3496
20908596
CD
3497;;; Miscellaneous options
3498
3499(defgroup org-completion nil
3500 "Completion in Org-mode."
3501 :tag "Org Completion"
3502 :group 'org)
891f4676 3503
ce4fdcb9 3504(defcustom org-completion-use-ido nil
ed21c5c8 3505 "Non-nil means use ido completion wherever possible.
0bd48b37
CD
3506Note that `ido-mode' must be active for this variable to be relevant.
3507If you decide to turn this variable on, you might well want to turn off
54a0dee5
CD
3508`org-outline-path-complete-in-steps'.
3509See also `org-completion-use-iswitchb'."
3510 :group 'org-completion
3511 :type 'boolean)
3512
3513(defcustom org-completion-use-iswitchb nil
ed21c5c8 3514 "Non-nil means use iswitchb completion wherever possible.
54a0dee5
CD
3515Note that `iswitchb-mode' must be active for this variable to be relevant.
3516If you decide to turn this variable on, you might well want to turn off
3517`org-outline-path-complete-in-steps'.
8bfe682a 3518Note that this variable has only an effect if `org-completion-use-ido' is nil."
ce4fdcb9 3519 :group 'org-completion
ff4be292 3520 :type 'boolean)
ce4fdcb9 3521
20908596 3522(defcustom org-completion-fallback-command 'hippie-expand
acedf35c
CD
3523 "The expansion command called by \\[pcomplete] in normal context.
3524Normal means, no org-mode-specific context."
20908596
CD
3525 :group 'org-completion
3526 :type 'function)
ab27a4a0 3527
8bfe682a 3528;;; Functions and variables from their packages
8c6fb58b
CD
3529;; Declared here to avoid compiler warnings
3530
8c6fb58b
CD
3531;; XEmacs only
3532(defvar outline-mode-menu-heading)
3533(defvar outline-mode-menu-show)
3534(defvar outline-mode-menu-hide)
3535(defvar zmacs-regions) ; XEmacs regions
3536
3537;; Emacs only
3538(defvar mark-active)
3539
3540;; Various packages
bf9f6f03 3541(declare-function calendar-absolute-from-iso "cal-iso" (date))
f30cf46c 3542(declare-function calendar-forward-day "cal-move" (arg))
f30cf46c
GM
3543(declare-function calendar-goto-date "cal-move" (date))
3544(declare-function calendar-goto-today "cal-move" ())
bf9f6f03 3545(declare-function calendar-iso-from-absolute "cal-iso" (date))
20908596
CD
3546(defvar calc-embedded-close-formula)
3547(defvar calc-embedded-open-formula)
182aef95
DN
3548(declare-function cdlatex-tab "ext:cdlatex" ())
3549(declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
8c6fb58b 3550(defvar font-lock-unfontify-region-function)
64a51001
GM
3551(declare-function iswitchb-read-buffer "iswitchb"
3552 (prompt &optional default require-match start matches-set))
20908596
CD
3553(defvar iswitchb-temp-buflist)
3554(declare-function org-gnus-follow-link "org-gnus" (&optional group article))
0bd48b37 3555(defvar org-agenda-tags-todo-honor-ignore-options)
20908596 3556(declare-function org-agenda-skip "org-agenda" ())
1bcdebed
CD
3557(declare-function
3558 org-format-agenda-item "org-agenda"
3559 (extra txt &optional category tags dotime noprefix remove-re habitp))
20908596
CD
3560(declare-function org-agenda-new-marker "org-agenda" (&optional pos))
3561(declare-function org-agenda-change-all-lines "org-agenda"
d60b1ba1 3562 (newhead hdmarker &optional fixface just-this))
20908596
CD
3563(declare-function org-agenda-set-restriction-lock "org-agenda" (&optional type))
3564(declare-function org-agenda-maybe-redo "org-agenda" ())
b349f79f
CD
3565(declare-function org-agenda-save-markers-for-cut-and-paste "org-agenda"
3566 (beg end))
ce4fdcb9 3567(declare-function org-agenda-copy-local-variable "org-agenda" (var))
0bd48b37
CD
3568(declare-function org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item
3569 "org-agenda" (&optional end))
c8d0cf5c 3570(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
afe98dfa 3571(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
acedf35c
CD
3572(declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
3573(declare-function org-inlinetask-goto-end "org-inlinetask" ())
9d459fc5 3574(declare-function org-indent-mode "org-indent" (&optional arg))
f30cf46c 3575(declare-function parse-time-string "parse-time" (string))
8bfe682a 3576(declare-function org-attach-reveal "org-attach" (&optional if-exists))
86fbb8ca 3577(declare-function org-export-latex-fix-inputenc "org-latex" ())
acedf35c 3578(declare-function orgtbl-send-table "org-table" (&optional maybe))
8c6fb58b 3579(defvar remember-data-file)
8c6fb58b 3580(defvar texmathp-why)
20908596
CD
3581(declare-function speedbar-line-directory "speedbar" (&optional depth))
3582(declare-function table--at-cell-p "table" (position &optional object at-column))
3583
8c6fb58b
CD
3584(defvar w3m-current-url)
3585(defvar w3m-current-title)
8c6fb58b
CD
3586
3587(defvar org-latex-regexps)
d3f4dbe8 3588
20908596 3589;;; Autoload and prepare some org modules
4b3a9ba7 3590
20908596
CD
3591;; Some table stuff that needs to be defined here, because it is used
3592;; by the functions setting up org-mode or checking for table context.
4b3a9ba7 3593
20908596 3594(defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)"
86fbb8ca 3595 "Detect an org-type or table-type table.")
20908596 3596(defconst org-table-line-regexp "^[ \t]*|"
86fbb8ca 3597 "Detect an org-type table line.")
20908596 3598(defconst org-table-dataline-regexp "^[ \t]*|[^-]"
86fbb8ca 3599 "Detect an org-type table line.")
20908596 3600(defconst org-table-hline-regexp "^[ \t]*|-"
86fbb8ca 3601 "Detect an org-type table hline.")
20908596 3602(defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]"
86fbb8ca 3603 "Detect a table-type table hline.")
20908596 3604(defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]"
86fbb8ca
CD
3605 "Detect the first line outside a table when searching from within it.
3606This works for both table types.")
4b3a9ba7 3607
20908596 3608;; Autoload the functions in org-table.el that are needed by functions here.
ab27a4a0 3609
20908596
CD
3610(eval-and-compile
3611 (org-autoload "org-table"
3612 '(org-table-align org-table-begin org-table-blank-field
3613 org-table-convert org-table-convert-region org-table-copy-down
3614 org-table-copy-region org-table-create
3615 org-table-create-or-convert-from-region
3616 org-table-create-with-table.el org-table-current-dline
3617 org-table-cut-region org-table-delete-column org-table-edit-field
3618 org-table-edit-formulas org-table-end org-table-eval-formula
3619 org-table-export org-table-field-info
3620 org-table-get-stored-formulas org-table-goto-column
3621 org-table-hline-and-move org-table-import org-table-insert-column
3622 org-table-insert-hline org-table-insert-row org-table-iterate
3623 org-table-justify-field-maybe org-table-kill-row
3624 org-table-maybe-eval-formula org-table-maybe-recalculate-line
3625 org-table-move-column org-table-move-column-left
3626 org-table-move-column-right org-table-move-row
3627 org-table-move-row-down org-table-move-row-up
3628 org-table-next-field org-table-next-row org-table-paste-rectangle
3629 org-table-previous-field org-table-recalculate
3630 org-table-rotate-recalc-marks org-table-sort-lines org-table-sum
3631 org-table-toggle-coordinate-overlays
3632 org-table-toggle-formula-debugger org-table-wrap-region
86fbb8ca
CD
3633 orgtbl-mode turn-on-orgtbl org-table-to-lisp
3634 orgtbl-to-generic orgtbl-to-tsv orgtbl-to-csv orgtbl-to-latex
3635 orgtbl-to-orgtbl orgtbl-to-html orgtbl-to-texinfo)))
3278a016 3636
20908596
CD
3637(defun org-at-table-p (&optional table-type)
3638 "Return t if the cursor is inside an org-type table.
3639If TABLE-TYPE is non-nil, also check for table.el-type tables."
3640 (if org-enable-table-editor
1d676e9f 3641 (save-excursion
20908596
CD
3642 (beginning-of-line 1)
3643 (looking-at (if table-type org-table-any-line-regexp
3644 org-table-line-regexp)))
3645 nil))
3646(defsubst org-table-p () (org-at-table-p))
edd21304 3647
20908596
CD
3648(defun org-at-table.el-p ()
3649 "Return t if and only if we are at a table.el table."
3650 (and (org-at-table-p 'any)
3651 (save-excursion
3652 (goto-char (org-table-begin 'any))
3653 (looking-at org-table1-hline-regexp))))
3654(defun org-table-recognize-table.el ()
3655 "If there is a table.el table nearby, recognize it and move into it."
3656 (if org-table-tab-recognizes-table.el
3657 (if (org-at-table.el-p)
3658 (progn
3659 (beginning-of-line 1)
3660 (if (looking-at org-table-dataline-regexp)
3661 nil
3662 (if (looking-at org-table1-hline-regexp)
3663 (progn
3664 (beginning-of-line 2)
3665 (if (looking-at org-table-any-border-regexp)
3666 (beginning-of-line -1)))))
3667 (if (re-search-forward "|" (org-table-end t) t)
3668 (progn
3669 (require 'table)
3670 (if (table--at-cell-p (point))
3671 t
3672 (message "recognizing table.el table...")
3673 (table-recognize-table)
3674 (message "recognizing table.el table...done")))
86fbb8ca 3675 (error "This should not happen"))
20908596
CD
3676 t)
3677 nil)
3678 nil))
edd21304 3679
20908596
CD
3680(defun org-at-table-hline-p ()
3681 "Return t if the cursor is inside a hline in a table."
3682 (if org-enable-table-editor
3683 (save-excursion
3684 (beginning-of-line 1)
3685 (looking-at org-table-hline-regexp))
3686 nil))
edd21304 3687
20908596 3688(defvar org-table-clean-did-remove-column nil)
6769c0dc 3689
86fbb8ca 3690(defun org-table-map-tables (function &optional quietly)
d3f4dbe8
CD
3691 "Apply FUNCTION to the start of all tables in the buffer."
3692 (save-excursion
3693 (save-restriction
3694 (widen)
3695 (goto-char (point-min))
3696 (while (re-search-forward org-table-any-line-regexp nil t)
86fbb8ca
CD
3697 (unless quietly
3698 (message "Mapping tables: %d%%" (/ (* 100.0 (point)) (buffer-size))))
d3f4dbe8 3699 (beginning-of-line 1)
c8d0cf5c
CD
3700 (when (looking-at org-table-line-regexp)
3701 (save-excursion (funcall function))
3702 (or (looking-at org-table-line-regexp)
3703 (forward-char 1)))
d3f4dbe8 3704 (re-search-forward org-table-any-border-regexp nil 1))))
86fbb8ca 3705 (unless quietly (message "Mapping tables: done")))
edd21304 3706
c8d0cf5c 3707;; Declare and autoload functions from org-exp.el & Co
d3f4dbe8 3708
20908596
CD
3709(declare-function org-default-export-plist "org-exp")
3710(declare-function org-infile-export-plist "org-exp")
3711(declare-function org-get-current-options "org-exp")
3712(eval-and-compile
3713 (org-autoload "org-exp"
c8d0cf5c
CD
3714 '(org-export org-export-visible
3715 org-insert-export-options-template
3716 org-table-clean-before-export))
3717 (org-autoload "org-ascii"
3718 '(org-export-as-ascii org-export-ascii-preprocess
3719 org-export-as-ascii-to-buffer org-replace-region-by-ascii
3720 org-export-region-as-ascii))
ed21c5c8
CD
3721 (org-autoload "org-latex"
3722 '(org-export-as-latex-batch org-export-as-latex-to-buffer
3723 org-replace-region-by-latex org-export-region-as-latex
3724 org-export-as-latex org-export-as-pdf
3725 org-export-as-pdf-and-open))
c8d0cf5c
CD
3726 (org-autoload "org-html"
3727 '(org-export-as-html-and-open
3728 org-export-as-html-batch org-export-as-html-to-buffer
3729 org-replace-region-by-html org-export-region-as-html
3730 org-export-as-html))
ed21c5c8
CD
3731 (org-autoload "org-docbook"
3732 '(org-export-as-docbook-batch org-export-as-docbook-to-buffer
3733 org-replace-region-by-docbook org-export-region-as-docbook
3734 org-export-as-docbook-pdf org-export-as-docbook-pdf-and-open
3735 org-export-as-docbook))
c8d0cf5c
CD
3736 (org-autoload "org-icalendar"
3737 '(org-export-icalendar-this-file
3738 org-export-icalendar-all-agenda-files
3739 org-export-icalendar-combine-agenda-files))
ed21c5c8
CD
3740 (org-autoload "org-xoxo" '(org-export-as-xoxo))
3741 (org-autoload "org-beamer" '(org-beamer-mode org-beamer-sectioning)))
d3f4dbe8 3742
621f83e4 3743;; Declare and autoload functions from org-agenda.el
d3f4dbe8 3744
20908596 3745(eval-and-compile
621f83e4 3746 (org-autoload "org-agenda"
20908596
CD
3747 '(org-agenda org-agenda-list org-search-view
3748 org-todo-list org-tags-view org-agenda-list-stuck-projects
0bd48b37
CD
3749 org-diary org-agenda-to-appt
3750 org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item)))
d3f4dbe8 3751
20908596
CD
3752;; Autoload org-remember
3753
3754(eval-and-compile
3755 (org-autoload "org-remember"
3756 '(org-remember-insinuate org-remember-annotation
3757 org-remember-apply-template org-remember org-remember-handler)))
3758
86fbb8ca
CD
3759(eval-and-compile
3760 (org-autoload "org-capture"
3761 '(org-capture org-capture-insert-template-here
3762 org-capture-import-remember-templates)))
3763
20908596
CD
3764;; Autoload org-clock.el
3765
b349f79f
CD
3766(declare-function org-clock-save-markers-for-cut-and-paste "org-clock"
3767 (beg end))
0bd48b37 3768(declare-function org-clock-update-mode-line "org-clock" ())
8bfe682a
CD
3769(declare-function org-resolve-clocks "org-clock"
3770 (&optional also-non-dangling-p prompt last-valid))
b349f79f 3771(defvar org-clock-start-time)
20908596
CD
3772(defvar org-clock-marker (make-marker)
3773 "Marker recording the last clock-in.")
54a0dee5
CD
3774(defvar org-clock-hd-marker (make-marker)
3775 "Marker recording the last clock-in, but the headline position.")
8bfe682a
CD
3776(defvar org-clock-heading ""
3777 "The heading of the current clock entry.")
c8d0cf5c
CD
3778(defun org-clock-is-active ()
3779 "Return non-nil if clock is currently running.
3780The return value is actually the clock marker."
3781 (marker-buffer org-clock-marker))
20908596
CD
3782
3783(eval-and-compile
3784 (org-autoload
3785 "org-clock"
3786 '(org-clock-in org-clock-out org-clock-cancel
3787 org-clock-goto org-clock-sum org-clock-display
0bd48b37 3788 org-clock-remove-overlays org-clock-report
20908596 3789 org-clocktable-shift org-dblock-write:clocktable
8bfe682a 3790 org-get-clocktable org-resolve-clocks)))
20908596
CD
3791
3792(defun org-clock-update-time-maybe ()
3793 "If this is a CLOCK line, update it and return t.
3794Otherwise, return nil."
0fee8d6e 3795 (interactive)
5137195a 3796 (save-excursion
20908596
CD
3797 (beginning-of-line 1)
3798 (skip-chars-forward " \t")
3799 (when (looking-at org-clock-string)
3800 (let ((re (concat "[ \t]*" org-clock-string
b349f79f
CD
3801 " *[[<]\\([^]>]+\\)[]>]\\(-+[[<]\\([^]>]+\\)[]>]"
3802 "\\([ \t]*=>.*\\)?\\)?"))
71d35b24 3803 ts te h m s neg)
b349f79f
CD
3804 (cond
3805 ((not (looking-at re))
3806 nil)
3807 ((not (match-end 2))
3808 (when (and (equal (marker-buffer org-clock-marker) (current-buffer))
3809 (> org-clock-marker (point))
3810 (<= org-clock-marker (point-at-eol)))
3811 ;; The clock is running here
3812 (setq org-clock-start-time
ce4fdcb9 3813 (apply 'encode-time
b349f79f 3814 (org-parse-time-string (match-string 1))))
0bd48b37 3815 (org-clock-update-mode-line)))
b349f79f
CD
3816 (t
3817 (and (match-end 4) (delete-region (match-beginning 4) (match-end 4)))
20908596
CD
3818 (end-of-line 1)
3819 (setq ts (match-string 1)
b349f79f 3820 te (match-string 3))
54a0dee5 3821 (setq s (- (org-float-time
20908596 3822 (apply 'encode-time (org-parse-time-string te)))
54a0dee5 3823 (org-float-time
20908596 3824 (apply 'encode-time (org-parse-time-string ts))))
71d35b24
CD
3825 neg (< s 0)
3826 s (abs s)
20908596
CD
3827 h (floor (/ s 3600))
3828 s (- s (* 3600 h))
3829 m (floor (/ s 60))
3830 s (- s (* 60 s)))
71d35b24 3831 (insert " => " (format (if neg "-%d:%02d" "%2d:%02d") h m))
b349f79f 3832 t))))))
5137195a 3833
20908596
CD
3834(defun org-check-running-clock ()
3835 "Check if the current buffer contains the running clock.
3836If yes, offer to stop it and to save the buffer with the changes."
3837 (when (and (equal (marker-buffer org-clock-marker) (current-buffer))
3838 (y-or-n-p (format "Clock-out in buffer %s before killing it? "
3839 (buffer-name))))
3840 (org-clock-out)
3841 (when (y-or-n-p "Save changed buffer?")
3842 (save-buffer))))
3843
3844(defun org-clocktable-try-shift (dir n)
3845 "Check if this line starts a clock table, if yes, shift the time block."
3846 (when (org-match-line "#\\+BEGIN: clocktable\\>")
3847 (org-clocktable-shift dir n)))
3848
ff4be292
CD
3849;; Autoload org-timer.el
3850
ff4be292
CD
3851(eval-and-compile
3852 (org-autoload
3853 "org-timer"
3854 '(org-timer-start org-timer org-timer-item
c8d0cf5c
CD
3855 org-timer-change-times-in-region
3856 org-timer-set-timer
3857 org-timer-reset-timers
3858 org-timer-show-remaining-time)))
3859
3860;; Autoload org-feed.el
3861
3862(eval-and-compile
3863 (org-autoload
3864 "org-feed"
3865 '(org-feed-update org-feed-update-all org-feed-goto-inbox)))
3866
ff4be292 3867
c8d0cf5c
CD
3868;; Autoload org-indent.el
3869
8bfe682a
CD
3870;; Define the variable already here, to make sure we have it.
3871(defvar org-indent-mode nil
3872 "Non-nil if Org-Indent mode is enabled.
3873Use the command `org-indent-mode' to change this variable.")
3874
c8d0cf5c
CD
3875(eval-and-compile
3876 (org-autoload
3877 "org-indent"
3878 '(org-indent-mode)))
ff4be292 3879
8d642074
CD
3880;; Autoload org-mobile.el
3881
3882(eval-and-compile
3883 (org-autoload
3884 "org-mobile"
3885 '(org-mobile-push org-mobile-pull org-mobile-create-sumo-agenda)))
3886
20908596
CD
3887;; Autoload archiving code
3888;; The stuff that is needed for cycling and tags has to be defined here.
3889
3890(defgroup org-archive nil
3891 "Options concerning archiving in Org-mode."
3892 :tag "Org Archive"
3893 :group 'org-structure)
3894
3895(defcustom org-archive-location "%s_archive::"
3896 "The location where subtrees should be archived.
3897
ce4fdcb9
CD
3898The value of this variable is a string, consisting of two parts,
3899separated by a double-colon. The first part is a filename and
3900the second part is a headline.
20908596 3901
ce4fdcb9
CD
3902When the filename is omitted, archiving happens in the same file.
3903%s in the filename will be replaced by the current file
3904name (without the directory part). Archiving to a different file
3905is useful to keep archived entries from contributing to the
3906Org-mode Agenda.
20908596 3907
ce4fdcb9
CD
3908The archived entries will be filed as subtrees of the specified
3909headline. When the headline is omitted, the subtrees are simply
0bd48b37
CD
3910filed away at the end of the file, as top-level entries. Also in
3911the heading you can use %s to represent the file name, this can be
3912useful when using the same archive for a number of different files.
20908596
CD
3913
3914Here are a few examples:
3915\"%s_archive::\"
3916 If the current file is Projects.org, archive in file
3917 Projects.org_archive, as top-level trees. This is the default.
3918
3919\"::* Archived Tasks\"
3920 Archive in the current file, under the top-level headline
3921 \"* Archived Tasks\".
3922
3923\"~/org/archive.org::\"
3924 Archive in file ~/org/archive.org (absolute path), as top-level trees.
3925
0bd48b37 3926\"~/org/archive.org::From %s\"
8bfe682a 3927 Archive in file ~/org/archive.org (absolute path), under headlines
0bd48b37
CD
3928 \"From FILENAME\" where file name is the current file name.
3929
20908596
CD
3930\"basement::** Finished Tasks\"
3931 Archive in file ./basement (relative path), as level 3 trees
3932 below the level 2 heading \"** Finished Tasks\".
3933
3934You may set this option on a per-file basis by adding to the buffer a
3935line like
3936
3937#+ARCHIVE: basement::** Finished Tasks
3938
3939You may also define it locally for a subtree by setting an ARCHIVE property
3940in the entry. If such a property is found in an entry, or anywhere up
3941the hierarchy, it will be used."
3942 :group 'org-archive
3943 :type 'string)
3944
3945(defcustom org-archive-tag "ARCHIVE"
3946 "The tag that marks a subtree as archived.
3947An archived subtree does not open during visibility cycling, and does
3948not contribute to the agenda listings.
3949After changing this, font-lock must be restarted in the relevant buffers to
3950get the proper fontification."
3951 :group 'org-archive
3952 :group 'org-keywords
3953 :type 'string)
3954
3955(defcustom org-agenda-skip-archived-trees t
ed21c5c8 3956 "Non-nil means the agenda will skip any items located in archived trees.
2c3ad40d
CD
3957An archived tree is a tree marked with the tag ARCHIVE. The use of this
3958variable is no longer recommended, you should leave it at the value t.
3959Instead, use the key `v' to cycle the archives-mode in the agenda."
20908596
CD
3960 :group 'org-archive
3961 :group 'org-agenda-skip
3962 :type 'boolean)
3963
8bfe682a 3964(defcustom org-columns-skip-archived-trees t
ed21c5c8 3965 "Non-nil means ignore archived trees when creating column view."
c8d0cf5c
CD
3966 :group 'org-archive
3967 :group 'org-properties
3968 :type 'boolean)
3969
20908596 3970(defcustom org-cycle-open-archived-trees nil
ed21c5c8 3971 "Non-nil means `org-cycle' will open archived trees.
20908596
CD
3972An archived tree is a tree marked with the tag ARCHIVE.
3973When nil, archived trees will stay folded. You can still open them with
3974normal outline commands like `show-all', but not with the cycling commands."
3975 :group 'org-archive
3976 :group 'org-cycle
3977 :type 'boolean)
3978
3979(defcustom org-sparse-tree-open-archived-trees nil
3980 "Non-nil means sparse tree construction shows matches in archived trees.
3981When nil, matches in these trees are highlighted, but the trees are kept in
3982collapsed state."
3983 :group 'org-archive
3984 :group 'org-sparse-trees
3985 :type 'boolean)
3986
3987(defun org-cycle-hide-archived-subtrees (state)
3988 "Re-hide all archived subtrees after a visibility state change."
3989 (when (and (not org-cycle-open-archived-trees)
3990 (not (memq state '(overview folded))))
d3f4dbe8 3991 (save-excursion
20908596
CD
3992 (let* ((globalp (memq state '(contents all)))
3993 (beg (if globalp (point-min) (point)))
3994 (end (if globalp (point-max) (org-end-of-subtree t))))
3995 (org-hide-archived-subtrees beg end)
3996 (goto-char beg)
3997 (if (looking-at (concat ".*:" org-archive-tag ":"))
3998 (message "%s" (substitute-command-keys
3999 "Subtree is archived and stays closed. Use \\[org-force-cycle-archived] to cycle it anyway.")))))))
4000
4001(defun org-force-cycle-archived ()
4002 "Cycle subtree even if it is archived."
d3f4dbe8 4003 (interactive)
20908596
CD
4004 (setq this-command 'org-cycle)
4005 (let ((org-cycle-open-archived-trees t))
4006 (call-interactively 'org-cycle)))
3278a016 4007
20908596
CD
4008(defun org-hide-archived-subtrees (beg end)
4009 "Re-hide all archived subtrees after a visibility state change."
4010 (save-excursion
4011 (let* ((re (concat ":" org-archive-tag ":")))
38f8646b 4012 (goto-char beg)
20908596 4013 (while (re-search-forward re end t)
ed21c5c8
CD
4014 (when (org-on-heading-p)
4015 (org-flag-subtree t)
4016 (org-end-of-subtree t))))))
a3fbe8c4 4017
8bfe682a
CD
4018(defun org-flag-subtree (flag)
4019 (save-excursion
4020 (org-back-to-heading t)
4021 (outline-end-of-heading)
4022 (outline-flag-region (point)
4023 (progn (org-end-of-subtree t) (point))
4024 flag)))
4025
20908596 4026(defalias 'org-advertized-archive-subtree 'org-archive-subtree)
ab27a4a0 4027
20908596
CD
4028(eval-and-compile
4029 (org-autoload "org-archive"
4030 '(org-add-archive-files org-archive-subtree
5dec9555
CD
4031 org-archive-to-archive-sibling org-toggle-archive-tag
4032 org-archive-subtree-default
4033 org-archive-subtree-default-with-confirmation)))
ab27a4a0 4034
20908596 4035;; Autoload Column View Code
a3fbe8c4 4036
20908596
CD
4037(declare-function org-columns-number-to-string "org-colview")
4038(declare-function org-columns-get-format-and-top-level "org-colview")
4039(declare-function org-columns-compute "org-colview")
a3fbe8c4 4040
20908596
CD
4041(org-autoload (if (featurep 'xemacs) "org-colview-xemacs" "org-colview")
4042 '(org-columns-number-to-string org-columns-get-format-and-top-level
4043 org-columns-compute org-agenda-columns org-columns-remove-overlays
0627c265 4044 org-columns org-insert-columns-dblock org-dblock-write:columnview))
a3fbe8c4 4045
b349f79f
CD
4046;; Autoload ID code
4047
db55f368 4048(declare-function org-id-store-link "org-id")
c8d0cf5c
CD
4049(declare-function org-id-locations-load "org-id")
4050(declare-function org-id-locations-save "org-id")
4051(defvar org-id-track-globally)
b349f79f 4052(org-autoload "org-id"
ce4fdcb9
CD
4053 '(org-id-get-create org-id-new org-id-copy org-id-get
4054 org-id-get-with-outline-path-completion
afe98dfa 4055 org-id-get-with-outline-drilling org-id-store-link
db55f368 4056 org-id-goto org-id-find org-id-store-link))
b349f79f 4057
c8d0cf5c
CD
4058;; Autoload Plotting Code
4059
4060(org-autoload "org-plot"
4061 '(org-plot/gnuplot))
4062
20908596 4063;;; Variables for pre-computed regular expressions, all buffer local
a3fbe8c4 4064
20908596
CD
4065(defvar org-drawer-regexp nil
4066 "Matches first line of a hidden block.")
4067(make-variable-buffer-local 'org-drawer-regexp)
4068(defvar org-todo-regexp nil
4069 "Matches any of the TODO state keywords.")
4070(make-variable-buffer-local 'org-todo-regexp)
4071(defvar org-not-done-regexp nil
4072 "Matches any of the TODO state keywords except the last one.")
4073(make-variable-buffer-local 'org-not-done-regexp)
c8d0cf5c
CD
4074(defvar org-not-done-heading-regexp nil
4075 "Matches a TODO headline that is not done.")
4076(make-variable-buffer-local 'org-not-done-regexp)
20908596
CD
4077(defvar org-todo-line-regexp nil
4078 "Matches a headline and puts TODO state into group 2 if present.")
4079(make-variable-buffer-local 'org-todo-line-regexp)
4080(defvar org-complex-heading-regexp nil
4081 "Matches a headline and puts everything into groups:
4082group 1: the stars
4083group 2: The todo keyword, maybe
4084group 3: Priority cookie
4085group 4: True headline
4086group 5: Tags")
4087(make-variable-buffer-local 'org-complex-heading-regexp)
afe98dfa
CD
4088(defvar org-complex-heading-regexp-format nil
4089 "Printf format to make regexp to match an exact headline.
4090This regexp will match the headline of any node which hase the exact
4091headline text that is put into the format, but may have any TODO state,
4092priority and tags.")
8d642074 4093(make-variable-buffer-local 'org-complex-heading-regexp-format)
20908596
CD
4094(defvar org-todo-line-tags-regexp nil
4095 "Matches a headline and puts TODO state into group 2 if present.
4096Also put tags into group 4 if tags are present.")
4097(make-variable-buffer-local 'org-todo-line-tags-regexp)
4098(defvar org-nl-done-regexp nil
4099 "Matches newline followed by a headline with the DONE keyword.")
4100(make-variable-buffer-local 'org-nl-done-regexp)
4101(defvar org-looking-at-done-regexp nil
4102 "Matches the DONE keyword a point.")
4103(make-variable-buffer-local 'org-looking-at-done-regexp)
4104(defvar org-ds-keyword-length 12
4105 "Maximum length of the Deadline and SCHEDULED keywords.")
4106(make-variable-buffer-local 'org-ds-keyword-length)
4107(defvar org-deadline-regexp nil
4108 "Matches the DEADLINE keyword.")
4109(make-variable-buffer-local 'org-deadline-regexp)
4110(defvar org-deadline-time-regexp nil
4111 "Matches the DEADLINE keyword together with a time stamp.")
4112(make-variable-buffer-local 'org-deadline-time-regexp)
4113(defvar org-deadline-line-regexp nil
4114 "Matches the DEADLINE keyword and the rest of the line.")
4115(make-variable-buffer-local 'org-deadline-line-regexp)
4116(defvar org-scheduled-regexp nil
4117 "Matches the SCHEDULED keyword.")
4118(make-variable-buffer-local 'org-scheduled-regexp)
4119(defvar org-scheduled-time-regexp nil
4120 "Matches the SCHEDULED keyword together with a time stamp.")
4121(make-variable-buffer-local 'org-scheduled-time-regexp)
4122(defvar org-closed-time-regexp nil
4123 "Matches the CLOSED keyword together with a time stamp.")
4124(make-variable-buffer-local 'org-closed-time-regexp)
a3fbe8c4 4125
20908596
CD
4126(defvar org-keyword-time-regexp nil
4127 "Matches any of the 4 keywords, together with the time stamp.")
4128(make-variable-buffer-local 'org-keyword-time-regexp)
4129(defvar org-keyword-time-not-clock-regexp nil
4130 "Matches any of the 3 keywords, together with the time stamp.")
4131(make-variable-buffer-local 'org-keyword-time-not-clock-regexp)
4132(defvar org-maybe-keyword-time-regexp nil
86fbb8ca 4133 "Matches a timestamp, possibly preceded by a keyword.")
20908596
CD
4134(make-variable-buffer-local 'org-maybe-keyword-time-regexp)
4135(defvar org-planning-or-clock-line-re nil
4136 "Matches a line with planning or clock info.")
4137(make-variable-buffer-local 'org-planning-or-clock-line-re)
ed21c5c8
CD
4138(defvar org-all-time-keywords nil
4139 "List of time keywords.")
4140(make-variable-buffer-local 'org-all-time-keywords)
a3fbe8c4 4141
20908596
CD
4142(defconst org-plain-time-of-day-regexp
4143 (concat
4144 "\\(\\<[012]?[0-9]"
4145 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
4146 "\\(--?"
4147 "\\(\\<[012]?[0-9]"
4148 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
4149 "\\)?")
4150 "Regular expression to match a plain time or time range.
4151Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
4152groups carry important information:
41530 the full match
41541 the first time, range or not
41558 the second time, if it is a range.")
a3fbe8c4 4156
20908596
CD
4157(defconst org-plain-time-extension-regexp
4158 (concat
4159 "\\(\\<[012]?[0-9]"
4160 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
4161 "\\+\\([0-9]+\\)\\(:\\([0-5][0-9]\\)\\)?")
4162 "Regular expression to match a time range like 13:30+2:10 = 13:30-15:40.
4163Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
4164groups carry important information:
41650 the full match
41667 hours of duration
41679 minutes of duration")
4168
4169(defconst org-stamp-time-of-day-regexp
4170 (concat
4171 "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +\\sw+ +\\)"
4172 "\\([012][0-9]:[0-5][0-9]\\(-\\([012][0-9]:[0-5][0-9]\\)\\)?[^\n\r>]*?\\)>"
4173 "\\(--?"
4174 "<\\1\\([012][0-9]:[0-5][0-9]\\)>\\)?")
4175 "Regular expression to match a timestamp time or time range.
4176After a match, the following groups carry important information:
41770 the full match
8bfe682a 41781 date plus weekday, for back referencing to make sure both times are on the same day
20908596
CD
41792 the first time, range or not
41804 the second time, if it is a range.")
4181
4182(defconst org-startup-options
4183 '(("fold" org-startup-folded t)
4184 ("overview" org-startup-folded t)
4185 ("nofold" org-startup-folded nil)
4186 ("showall" org-startup-folded nil)
8d642074 4187 ("showeverything" org-startup-folded showeverything)
20908596 4188 ("content" org-startup-folded content)
c8d0cf5c
CD
4189 ("indent" org-startup-indented t)
4190 ("noindent" org-startup-indented nil)
20908596
CD
4191 ("hidestars" org-hide-leading-stars t)
4192 ("showstars" org-hide-leading-stars nil)
4193 ("odd" org-odd-levels-only t)
4194 ("oddeven" org-odd-levels-only nil)
4195 ("align" org-startup-align-all-tables t)
4196 ("noalign" org-startup-align-all-tables nil)
afe98dfa
CD
4197 ("inlineimages" org-startup-with-inline-images t)
4198 ("noinlineimages" org-startup-with-inline-images nil)
20908596
CD
4199 ("customtime" org-display-custom-times t)
4200 ("logdone" org-log-done time)
4201 ("lognotedone" org-log-done note)
4202 ("nologdone" org-log-done nil)
4203 ("lognoteclock-out" org-log-note-clock-out t)
4204 ("nolognoteclock-out" org-log-note-clock-out nil)
4205 ("logrepeat" org-log-repeat state)
4206 ("lognoterepeat" org-log-repeat note)
4207 ("nologrepeat" org-log-repeat nil)
8bfe682a
CD
4208 ("logreschedule" org-log-reschedule time)
4209 ("lognotereschedule" org-log-reschedule note)
4210 ("nologreschedule" org-log-reschedule nil)
4211 ("logredeadline" org-log-redeadline time)
4212 ("lognoteredeadline" org-log-redeadline note)
4213 ("nologredeadline" org-log-redeadline nil)
ed21c5c8
CD
4214 ("logrefile" org-log-refile time)
4215 ("lognoterefile" org-log-refile note)
4216 ("nologrefile" org-log-refile nil)
0bd48b37
CD
4217 ("fninline" org-footnote-define-inline t)
4218 ("nofninline" org-footnote-define-inline nil)
4219 ("fnlocal" org-footnote-section nil)
4220 ("fnauto" org-footnote-auto-label t)
4221 ("fnprompt" org-footnote-auto-label nil)
4222 ("fnconfirm" org-footnote-auto-label confirm)
4223 ("fnplain" org-footnote-auto-label plain)
c8d0cf5c
CD
4224 ("fnadjust" org-footnote-auto-adjust t)
4225 ("nofnadjust" org-footnote-auto-adjust nil)
20908596 4226 ("constcgs" constants-unit-system cgs)
c8d0cf5c
CD
4227 ("constSI" constants-unit-system SI)
4228 ("noptag" org-tag-persistent-alist nil)
4229 ("hideblocks" org-hide-block-startup t)
ed21c5c8 4230 ("nohideblocks" org-hide-block-startup nil)
86fbb8ca
CD
4231 ("beamer" org-startup-with-beamer-mode t)
4232 ("entitiespretty" org-pretty-entities t)
4233 ("entitiesplain" org-pretty-entities nil))
20908596
CD
4234 "Variable associated with STARTUP options for org-mode.
4235Each element is a list of three items: The startup options as written
4236in the #+STARTUP line, the corresponding variable, and the value to
4237set this variable to if the option is found. An optional forth element PUSH
4238means to push this value onto the list in the variable.")
4239
4240(defun org-set-regexps-and-options ()
4241 "Precompute regular expressions for current buffer."
4242 (when (org-mode-p)
4243 (org-set-local 'org-todo-kwd-alist nil)
4244 (org-set-local 'org-todo-key-alist nil)
4245 (org-set-local 'org-todo-key-trigger nil)
4246 (org-set-local 'org-todo-keywords-1 nil)
4247 (org-set-local 'org-done-keywords nil)
4248 (org-set-local 'org-todo-heads nil)
4249 (org-set-local 'org-todo-sets nil)
4250 (org-set-local 'org-todo-log-states nil)
b349f79f
CD
4251 (org-set-local 'org-file-properties nil)
4252 (org-set-local 'org-file-tags nil)
20908596 4253 (let ((re (org-make-options-regexp
c8d0cf5c 4254 '("CATEGORY" "TODO" "COLUMNS"
b349f79f 4255 "STARTUP" "ARCHIVE" "FILETAGS" "TAGS" "LINK" "PRIORITIES"
86fbb8ca
CD
4256 "CONSTANTS" "PROPERTY" "DRAWERS" "SETUPFILE" "LATEX_CLASS"
4257 "OPTIONS")
c8d0cf5c 4258 "\\(?:[a-zA-Z][0-9a-zA-Z_]*_TODO\\)"))
20908596 4259 (splitre "[ \t]+")
86fbb8ca 4260 (scripts org-use-sub-superscripts)
20908596 4261 kwds kws0 kwsa key log value cat arch tags const links hw dws
ed21c5c8 4262 tail sep kws1 prio props ftags drawers beamer-p
b349f79f 4263 ext-setup-or-nil setup-contents (start 0))
a3fbe8c4 4264 (save-excursion
20908596
CD
4265 (save-restriction
4266 (widen)
4267 (goto-char (point-min))
b349f79f
CD
4268 (while (or (and ext-setup-or-nil
4269 (string-match re ext-setup-or-nil start)
4270 (setq start (match-end 0)))
4271 (and (setq ext-setup-or-nil nil start 0)
4272 (re-search-forward re nil t)))
4273 (setq key (upcase (match-string 1 ext-setup-or-nil))
4274 value (org-match-string-no-properties 2 ext-setup-or-nil))
86fbb8ca 4275 (if (stringp value) (setq value (org-trim value)))
20908596
CD
4276 (cond
4277 ((equal key "CATEGORY")
20908596
CD
4278 (setq cat value))
4279 ((member key '("SEQ_TODO" "TODO"))
4280 (push (cons 'sequence (org-split-string value splitre)) kwds))
4281 ((equal key "TYP_TODO")
4282 (push (cons 'type (org-split-string value splitre)) kwds))
c8d0cf5c
CD
4283 ((string-match "\\`\\([a-zA-Z][0-9a-zA-Z_]*\\)_TODO\\'" key)
4284 ;; general TODO-like setup
4285 (push (cons (intern (downcase (match-string 1 key)))
4286 (org-split-string value splitre)) kwds))
20908596 4287 ((equal key "TAGS")
c8d0cf5c
CD
4288 (setq tags (append tags (if tags '("\\n") nil)
4289 (org-split-string value splitre))))
20908596
CD
4290 ((equal key "COLUMNS")
4291 (org-set-local 'org-columns-default-format value))
4292 ((equal key "LINK")
4293 (when (string-match "^\\(\\S-+\\)[ \t]+\\(.+\\)" value)
4294 (push (cons (match-string 1 value)
4295 (org-trim (match-string 2 value)))
4296 links)))
4297 ((equal key "PRIORITIES")
4298 (setq prio (org-split-string value " +")))
4299 ((equal key "PROPERTY")
4300 (when (string-match "\\(\\S-+\\)\\s-+\\(.*\\)" value)
4301 (push (cons (match-string 1 value) (match-string 2 value))
4302 props)))
b349f79f
CD
4303 ((equal key "FILETAGS")
4304 (when (string-match "\\S-" value)
4305 (setq ftags
4306 (append
4307 ftags
4308 (apply 'append
4309 (mapcar (lambda (x) (org-split-string x ":"))
4310 (org-split-string value)))))))
20908596
CD
4311 ((equal key "DRAWERS")
4312 (setq drawers (org-split-string value splitre)))
4313 ((equal key "CONSTANTS")
4314 (setq const (append const (org-split-string value splitre))))
4315 ((equal key "STARTUP")
4316 (let ((opts (org-split-string value splitre))
4317 l var val)
4318 (while (setq l (pop opts))
4319 (when (setq l (assoc l org-startup-options))
4320 (setq var (nth 1 l) val (nth 2 l))
4321 (if (not (nth 3 l))
4322 (set (make-local-variable var) val)
4323 (if (not (listp (symbol-value var)))
4324 (set (make-local-variable var) nil))
4325 (set (make-local-variable var) (symbol-value var))
4326 (add-to-list var val))))))
4327 ((equal key "ARCHIVE")
86fbb8ca 4328 (setq arch value)
20908596 4329 (remove-text-properties 0 (length arch)
b349f79f 4330 '(face t fontified t) arch))
ed21c5c8
CD
4331 ((equal key "LATEX_CLASS")
4332 (setq beamer-p (equal value "beamer")))
86fbb8ca
CD
4333 ((equal key "OPTIONS")
4334 (if (string-match "\\([ \t]\\|\\`\\)\\^:\\(t\\|nil\\|{}\\)" value)
4335 (setq scripts (read (match-string 2 value)))))
b349f79f
CD
4336 ((equal key "SETUPFILE")
4337 (setq setup-contents (org-file-contents
4338 (expand-file-name
4339 (org-remove-double-quotes value))
4340 'noerror))
4341 (if (not ext-setup-or-nil)
4342 (setq ext-setup-or-nil setup-contents start 0)
4343 (setq ext-setup-or-nil
4344 (concat (substring ext-setup-or-nil 0 start)
4345 "\n" setup-contents "\n"
4346 (substring ext-setup-or-nil start)))))
4347 ))))
86fbb8ca 4348 (org-set-local 'org-use-sub-superscripts scripts)
20908596
CD
4349 (when cat
4350 (org-set-local 'org-category (intern cat))
4351 (push (cons "CATEGORY" cat) props))
4352 (when prio
4353 (if (< (length prio) 3) (setq prio '("A" "C" "B")))
4354 (setq prio (mapcar 'string-to-char prio))
4355 (org-set-local 'org-highest-priority (nth 0 prio))
4356 (org-set-local 'org-lowest-priority (nth 1 prio))
4357 (org-set-local 'org-default-priority (nth 2 prio)))
b349f79f 4358 (and props (org-set-local 'org-file-properties (nreverse props)))
c8d0cf5c
CD
4359 (and ftags (org-set-local 'org-file-tags
4360 (mapcar 'org-add-prop-inherited ftags)))
20908596
CD
4361 (and drawers (org-set-local 'org-drawers drawers))
4362 (and arch (org-set-local 'org-archive-location arch))
4363 (and links (setq org-link-abbrev-alist-local (nreverse links)))
4364 ;; Process the TODO keywords
4365 (unless kwds
4366 ;; Use the global values as if they had been given locally.
4367 (setq kwds (default-value 'org-todo-keywords))
4368 (if (stringp (car kwds))
4369 (setq kwds (list (cons org-todo-interpretation
4370 (default-value 'org-todo-keywords)))))
4371 (setq kwds (reverse kwds)))
4372 (setq kwds (nreverse kwds))
4373 (let (inter kws kw)
4374 (while (setq kws (pop kwds))
c8d0cf5c
CD
4375 (let ((kws (or
4376 (run-hook-with-args-until-success
4377 'org-todo-setup-filter-hook kws)
4378 kws)))
4379 (setq inter (pop kws) sep (member "|" kws)
4380 kws0 (delete "|" (copy-sequence kws))
4381 kwsa nil
4382 kws1 (mapcar
4383 (lambda (x)
4384 ;; 1 2
4385 (if (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?.*?)\\)?$" x)
4386 (progn
4387 (setq kw (match-string 1 x)
4388 key (and (match-end 2) (match-string 2 x))
4389 log (org-extract-log-state-settings x))
4390 (push (cons kw (and key (string-to-char key))) kwsa)
4391 (and log (push log org-todo-log-states))
4392 kw)
4393 (error "Invalid TODO keyword %s" x)))
4394 kws0)
4395 kwsa (if kwsa (append '((:startgroup))
4396 (nreverse kwsa)
4397 '((:endgroup))))
4398 hw (car kws1)
4399 dws (if sep (org-remove-keyword-keys (cdr sep)) (last kws1))
4400 tail (list inter hw (car dws) (org-last dws))))
20908596
CD
4401 (add-to-list 'org-todo-heads hw 'append)
4402 (push kws1 org-todo-sets)
4403 (setq org-done-keywords (append org-done-keywords dws nil))
4404 (setq org-todo-key-alist (append org-todo-key-alist kwsa))
4405 (mapc (lambda (x) (push (cons x tail) org-todo-kwd-alist)) kws1)
4406 (setq org-todo-keywords-1 (append org-todo-keywords-1 kws1 nil)))
4407 (setq org-todo-sets (nreverse org-todo-sets)
4408 org-todo-kwd-alist (nreverse org-todo-kwd-alist)
4409 org-todo-key-trigger (delq nil (mapcar 'cdr org-todo-key-alist))
4410 org-todo-key-alist (org-assign-fast-keys org-todo-key-alist)))
4411 ;; Process the constants
4412 (when const
4413 (let (e cst)
4414 (while (setq e (pop const))
4415 (if (string-match "^\\([a-zA-Z0][_a-zA-Z0-9]*\\)=\\(.*\\)" e)
4416 (push (cons (match-string 1 e) (match-string 2 e)) cst)))
4417 (setq org-table-formula-constants-local cst)))
a3fbe8c4 4418
20908596
CD
4419 ;; Process the tags.
4420 (when tags
4421 (let (e tgs)
4422 (while (setq e (pop tags))
4423 (cond
4424 ((equal e "{") (push '(:startgroup) tgs))
4425 ((equal e "}") (push '(:endgroup) tgs))
c8d0cf5c 4426 ((equal e "\\n") (push '(:newline) tgs))
afe98dfa 4427 ((string-match (org-re "^\\([[:alnum:]_@#%]+\\)(\\(.\\))$") e)
20908596
CD
4428 (push (cons (match-string 1 e)
4429 (string-to-char (match-string 2 e)))
4430 tgs))
4431 (t (push (list e) tgs))))
4432 (org-set-local 'org-tag-alist nil)
4433 (while (setq e (pop tgs))
4434 (or (and (stringp (car e))
4435 (assoc (car e) org-tag-alist))
b349f79f
CD
4436 (push e org-tag-alist)))))
4437
4438 ;; Compute the regular expressions and other local variables
4439 (if (not org-done-keywords)
54a0dee5
CD
4440 (setq org-done-keywords (and org-todo-keywords-1
4441 (list (org-last org-todo-keywords-1)))))
b349f79f
CD
4442 (setq org-ds-keyword-length (+ 2 (max (length org-deadline-string)
4443 (length org-scheduled-string)
4444 (length org-clock-string)
4445 (length org-closed-string)))
4446 org-drawer-regexp
4447 (concat "^[ \t]*:\\("
4448 (mapconcat 'regexp-quote org-drawers "\\|")
4449 "\\):[ \t]*$")
4450 org-not-done-keywords
4451 (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1))
4452 org-todo-regexp
4453 (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords-1
4454 "\\|") "\\)\\>")
4455 org-not-done-regexp
4456 (concat "\\<\\("
4457 (mapconcat 'regexp-quote org-not-done-keywords "\\|")
4458 "\\)\\>")
c8d0cf5c
CD
4459 org-not-done-heading-regexp
4460 (concat "^\\(\\*+\\)[ \t]+\\("
4461 (mapconcat 'regexp-quote org-not-done-keywords "\\|")
4462 "\\)\\>")
b349f79f
CD
4463 org-todo-line-regexp
4464 (concat "^\\(\\*+\\)[ \t]+\\(?:\\("
4465 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
4466 "\\)\\>\\)?[ \t]*\\(.*\\)")
4467 org-complex-heading-regexp
0bd48b37 4468 (concat "^\\(\\*+\\)[ \t]+\\(?:\\("
b349f79f
CD
4469 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
4470 "\\)\\>\\)?\\(?:[ \t]*\\(\\[#.\\]\\)\\)?[ \t]*\\(.*?\\)"
afe98dfa 4471 "\\(?:[ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)?[ \t]*$")
8d642074
CD
4472 org-complex-heading-regexp-format
4473 (concat "^\\(\\*+\\)[ \t]+\\(?:\\("
4474 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
86fbb8ca
CD
4475 "\\)\\>\\)?"
4476 "\\(?:[ \t]*\\(\\[#.\\]\\)\\)?"
4477 "\\(?:[ \t]*\\(?:\\[[0-9%%/]+\\]\\)\\)?" ;; stats cookie
4478 "[ \t]*\\(%s\\)"
4479 "\\(?:[ \t]*\\(?:\\[[0-9%%/]+\\]\\)\\)?" ;; stats cookie
afe98dfa 4480 "\\(?:[ \t]+\\(:[[:alnum:]_@#%%:]+:\\)\\)?[ \t]*$")
b349f79f
CD
4481 org-nl-done-regexp
4482 (concat "\n\\*+[ \t]+"
4483 "\\(?:" (mapconcat 'regexp-quote org-done-keywords "\\|")
4484 "\\)" "\\>")
4485 org-todo-line-tags-regexp
4486 (concat "^\\(\\*+\\)[ \t]+\\(?:\\("
4487 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
4488 (org-re
afe98dfa 4489 "\\)\\>\\)? *\\(.*?\\([ \t]:[[:alnum:]:_@#%]+:[ \t]*\\)?$\\)"))
b349f79f
CD
4490 org-looking-at-done-regexp
4491 (concat "^" "\\(?:"
4492 (mapconcat 'regexp-quote org-done-keywords "\\|") "\\)"
4493 "\\>")
4494 org-deadline-regexp (concat "\\<" org-deadline-string)
4495 org-deadline-time-regexp
4496 (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
4497 org-deadline-line-regexp
4498 (concat "\\<\\(" org-deadline-string "\\).*")
4499 org-scheduled-regexp
4500 (concat "\\<" org-scheduled-string)
4501 org-scheduled-time-regexp
4502 (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
4503 org-closed-time-regexp
4504 (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
4505 org-keyword-time-regexp
4506 (concat "\\<\\(" org-scheduled-string
4507 "\\|" org-deadline-string
4508 "\\|" org-closed-string
4509 "\\|" org-clock-string "\\)"
4510 " *[[<]\\([^]>]+\\)[]>]")
4511 org-keyword-time-not-clock-regexp
4512 (concat "\\<\\(" org-scheduled-string
4513 "\\|" org-deadline-string
4514 "\\|" org-closed-string
4515 "\\)"
4516 " *[[<]\\([^]>]+\\)[]>]")
4517 org-maybe-keyword-time-regexp
4518 (concat "\\(\\<\\(" org-scheduled-string
4519 "\\|" org-deadline-string
4520 "\\|" org-closed-string
4521 "\\|" org-clock-string "\\)\\)?"
4522 " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^]\r\n>]*?[]>]\\|<%%([^\r\n>]*>\\)")
4523 org-planning-or-clock-line-re
4524 (concat "\\(?:^[ \t]*\\(" org-scheduled-string
4525 "\\|" org-deadline-string
4526 "\\|" org-closed-string "\\|" org-clock-string
4527 "\\)\\>\\)")
ed21c5c8
CD
4528 org-all-time-keywords
4529 (mapcar (lambda (w) (substring w 0 -1))
4530 (list org-scheduled-string org-deadline-string
4531 org-clock-string org-closed-string))
b349f79f
CD
4532 )
4533 (org-compute-latex-and-specials-regexp)
4534 (org-set-font-lock-defaults))))
4535
4536(defun org-file-contents (file &optional noerror)
4537 "Return the contents of FILE, as a string."
4538 (if (or (not file)
4539 (not (file-readable-p file)))
4540 (if noerror
4541 (progn
86fbb8ca 4542 (message "Cannot read file \"%s\"" file)
b349f79f
CD
4543 (ding) (sit-for 2)
4544 "")
86fbb8ca 4545 (error "Cannot read file \"%s\"" file))
b349f79f
CD
4546 (with-temp-buffer
4547 (insert-file-contents file)
4548 (buffer-string))))
891f4676 4549
20908596
CD
4550(defun org-extract-log-state-settings (x)
4551 "Extract the log state setting from a TODO keyword string.
4552This will extract info from a string like \"WAIT(w@/!)\"."
4553 (let (kw key log1 log2)
4554 (when (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?\\([!@]\\)?\\(?:/\\([!@]\\)\\)?)\\)?$" x)
4555 (setq kw (match-string 1 x)
4556 key (and (match-end 2) (match-string 2 x))
4557 log1 (and (match-end 3) (match-string 3 x))
4558 log2 (and (match-end 4) (match-string 4 x)))
4559 (and (or log1 log2)
4560 (list kw
4561 (and log1 (if (equal log1 "!") 'time 'note))
4562 (and log2 (if (equal log2 "!") 'time 'note)))))))
891f4676 4563
20908596
CD
4564(defun org-remove-keyword-keys (list)
4565 "Remove a pair of parenthesis at the end of each string in LIST."
4566 (mapcar (lambda (x)
4567 (if (string-match "(.*)$" x)
4568 (substring x 0 (match-beginning 0))
4569 x))
4570 list))
891f4676 4571
20908596
CD
4572(defun org-assign-fast-keys (alist)
4573 "Assign fast keys to a keyword-key alist.
4574Respect keys that are already there."
ed21c5c8 4575 (let (new e (alt ?0))
20908596 4576 (while (setq e (pop alist))
ed21c5c8
CD
4577 (if (or (memq (car e) '(:newline :endgroup :startgroup))
4578 (cdr e)) ;; Key already assigned.
4579 (push e new)
4580 (let ((clist (string-to-list (downcase (car e))))
4581 (used (append new alist)))
4582 (when (= (car clist) ?@)
4583 (pop clist))
4584 (while (and clist (rassoc (car clist) used))
4585 (pop clist))
4586 (unless clist
4587 (while (rassoc alt used)
4588 (incf alt)))
4589 (push (cons (car e) (or (car clist) alt)) new))))
20908596 4590 (nreverse new)))
d3f4dbe8 4591
20908596 4592;;; Some variables used in various places
d3f4dbe8 4593
20908596
CD
4594(defvar org-window-configuration nil
4595 "Used in various places to store a window configuration.")
8d642074
CD
4596(defvar org-selected-window nil
4597 "Used in various places to store a window configuration.")
20908596
CD
4598(defvar org-finish-function nil
4599 "Function to be called when `C-c C-c' is used.
4600This is for getting out of special buffers like remember.")
d3f4dbe8 4601
d3f4dbe8 4602
20908596
CD
4603;; FIXME: Occasionally check by commenting these, to make sure
4604;; no other functions uses these, forgetting to let-bind them.
4605(defvar entry)
20908596
CD
4606(defvar last-state)
4607(defvar date)
d3f4dbe8 4608
20908596 4609;; Defined somewhere in this file, but used before definition.
ed21c5c8 4610(defvar org-entities) ;; defined in org-entities.el
20908596
CD
4611(defvar org-struct-menu)
4612(defvar org-org-menu)
4613(defvar org-tbl-menu)
3278a016 4614
20908596 4615;;;; Define the Org-mode
3278a016 4616
20908596 4617(if (and (not (keymapp outline-mode-map)) (featurep 'allout))
86fbb8ca 4618 (error "Conflict with outdated version of allout.el. Load org.el before allout.el, or upgrade to newer allout, for example by switching to Emacs 22"))
891f4676 4619
d3f4dbe8 4620
20908596
CD
4621;; We use a before-change function to check if a table might need
4622;; an update.
4623(defvar org-table-may-need-update t
4624 "Indicates that a table might need an update.
4625This variable is set by `org-before-change-function'.
4626`org-table-align' sets it back to nil.")
4627(defun org-before-change-function (beg end)
4628 "Every change indicates that a table might need an update."
4629 (setq org-table-may-need-update t))
4630(defvar org-mode-map)
20908596 4631(defvar org-inhibit-startup nil) ; Dynamically-scoped param.
ed21c5c8 4632(defvar org-inhibit-startup-visibility-stuff nil) ; Dynamically-scoped param.
20908596 4633(defvar org-agenda-keep-modes nil) ; Dynamically-scoped param.
c8d0cf5c
CD
4634(defvar org-inhibit-logging nil) ; Dynamically-scoped param.
4635(defvar org-inhibit-blocking nil) ; Dynamically-scoped param.
20908596
CD
4636(defvar org-table-buffer-is-an nil)
4637(defconst org-outline-regexp "\\*+ ")
f425a6ea
CD
4638
4639;;;###autoload
20908596
CD
4640(define-derived-mode org-mode outline-mode "Org"
4641 "Outline-based notes management and organizer, alias
4642\"Carsten's outline-mode for keeping track of everything.\"
891f4676 4643
20908596
CD
4644Org-mode develops organizational tasks around a NOTES file which
4645contains information about projects as plain text. Org-mode is
4646implemented on top of outline-mode, which is ideal to keep the content
4647of large files well structured. It supports ToDo items, deadlines and
4648time stamps, which magically appear in the diary listing of the Emacs
4649calendar. Tables are easily created with a built-in table editor.
4650Plain text URL-like links connect to websites, emails (VM), Usenet
4651messages (Gnus), BBDB entries, and any files related to the project.
4652For printing and sharing of notes, an Org-mode file (or a part of it)
4653can be exported as a structured ASCII or HTML file.
35fb9989 4654
20908596 4655The following commands are available:
35fb9989 4656
20908596 4657\\{org-mode-map}"
634a7d0b 4658
20908596
CD
4659 ;; Get rid of Outline menus, they are not needed
4660 ;; Need to do this here because define-derived-mode sets up
4661 ;; the keymap so late. Still, it is a waste to call this each time
4662 ;; we switch another buffer into org-mode.
4663 (if (featurep 'xemacs)
4664 (when (boundp 'outline-mode-menu-heading)
86fbb8ca 4665 ;; Assume this is Greg's port, it uses easymenu
20908596
CD
4666 (easy-menu-remove outline-mode-menu-heading)
4667 (easy-menu-remove outline-mode-menu-show)
4668 (easy-menu-remove outline-mode-menu-hide))
4669 (define-key org-mode-map [menu-bar headings] 'undefined)
4670 (define-key org-mode-map [menu-bar hide] 'undefined)
4671 (define-key org-mode-map [menu-bar show] 'undefined))
a3fbe8c4 4672
20908596
CD
4673 (org-load-modules-maybe)
4674 (easy-menu-add org-org-menu)
4675 (easy-menu-add org-tbl-menu)
4676 (org-install-agenda-files-menu)
86fbb8ca
CD
4677 (if org-descriptive-links (add-to-invisibility-spec '(org-link)))
4678 (add-to-invisibility-spec '(org-cwidth))
4679 (add-to-invisibility-spec '(org-hide-block . t))
20908596
CD
4680 (when (featurep 'xemacs)
4681 (org-set-local 'line-move-ignore-invisible t))
4682 (org-set-local 'outline-regexp org-outline-regexp)
4683 (org-set-local 'outline-level 'org-outline-level)
4684 (when (and org-ellipsis
4685 (fboundp 'set-display-table-slot) (boundp 'buffer-display-table)
4686 (fboundp 'make-glyph-code))
4687 (unless org-display-table
4688 (setq org-display-table (make-display-table)))
4689 (set-display-table-slot
4690 org-display-table 4
4691 (vconcat (mapcar
4692 (lambda (c) (make-glyph-code c (and (not (stringp org-ellipsis))
4693 org-ellipsis)))
4694 (if (stringp org-ellipsis) org-ellipsis "..."))))
4695 (setq buffer-display-table org-display-table))
4696 (org-set-regexps-and-options)
fdf730ed
CD
4697 (when (and org-tag-faces (not org-tags-special-faces-re))
4698 ;; tag faces set outside customize.... force initialization.
4699 (org-set-tag-faces 'org-tag-faces org-tag-faces))
20908596
CD
4700 ;; Calc embedded
4701 (org-set-local 'calc-embedded-open-mode "# ")
20908596
CD
4702 (modify-syntax-entry ?@ "w")
4703 (if org-startup-truncated (setq truncate-lines t))
4704 (org-set-local 'font-lock-unfontify-region-function
4705 'org-unfontify-region)
4706 ;; Activate before-change-function
4707 (org-set-local 'org-table-may-need-update t)
4708 (org-add-hook 'before-change-functions 'org-before-change-function nil
4709 'local)
4710 ;; Check for running clock before killing a buffer
4711 (org-add-hook 'kill-buffer-hook 'org-check-running-clock nil 'local)
4712 ;; Paragraphs and auto-filling
4713 (org-set-autofill-regexps)
4714 (setq indent-line-function 'org-indent-line-function)
4715 (org-update-radio-target-regexp)
86fbb8ca
CD
4716 ;; Beginning/end of defun
4717 (org-set-local 'beginning-of-defun-function 'org-beginning-of-defun)
4718 (org-set-local 'end-of-defun-function 'org-end-of-defun)
5ace2fe5
CD
4719 ;; Make sure dependence stuff works reliably, even for users who set it
4720 ;; too late :-(
4721 (if org-enforce-todo-dependencies
4722 (add-hook 'org-blocker-hook
c8d0cf5c 4723 'org-block-todo-from-children-or-siblings-or-parent)
5ace2fe5 4724 (remove-hook 'org-blocker-hook
c8d0cf5c 4725 'org-block-todo-from-children-or-siblings-or-parent))
5ace2fe5
CD
4726 (if org-enforce-todo-checkbox-dependencies
4727 (add-hook 'org-blocker-hook
4728 'org-block-todo-from-checkboxes)
4729 (remove-hook 'org-blocker-hook
4730 'org-block-todo-from-checkboxes))
7ac93e3c 4731
20908596 4732 ;; Comment characters
86fbb8ca 4733 (org-set-local 'comment-start "#")
20908596 4734 (org-set-local 'comment-padding " ")
891f4676 4735
20908596
CD
4736 ;; Align options lines
4737 (org-set-local
4738 'align-mode-rules-list
4739 '((org-in-buffer-settings
4740 (regexp . "^#\\+[A-Z_]+:\\(\\s-*\\)\\S-+")
4741 (modes . '(org-mode)))))
891f4676 4742
20908596
CD
4743 ;; Imenu
4744 (org-set-local 'imenu-create-index-function
4745 'org-imenu-get-tree)
891f4676 4746
20908596
CD
4747 ;; Make isearch reveal context
4748 (if (or (featurep 'xemacs)
4749 (not (boundp 'outline-isearch-open-invisible-function)))
4750 ;; Emacs 21 and XEmacs make use of the hook
4751 (org-add-hook 'isearch-mode-end-hook 'org-isearch-end 'append 'local)
4752 ;; Emacs 22 deals with this through a special variable
4753 (org-set-local 'outline-isearch-open-invisible-function
4754 (lambda (&rest ignore) (org-show-context 'isearch))))
634a7d0b 4755
ed21c5c8
CD
4756 ;; Turn on org-beamer-mode?
4757 (and org-startup-with-beamer-mode (org-beamer-mode 1))
4758
acedf35c
CD
4759 ;; Setup the pcomplete hooks
4760 (set (make-local-variable 'pcomplete-command-completion-function)
4761 'org-complete-initial)
4762 (set (make-local-variable 'pcomplete-command-name-function)
4763 'org-command-at-point)
4764 (set (make-local-variable 'pcomplete-default-completion-function)
4765 'ignore)
4766 (set (make-local-variable 'pcomplete-parse-arguments-function)
4767 'org-parse-arguments)
4768 (set (make-local-variable 'pcomplete-termination-string) "")
4769
20908596
CD
4770 ;; If empty file that did not turn on org-mode automatically, make it to.
4771 (if (and org-insert-mode-line-in-empty-file
4772 (interactive-p)
4773 (= (point-min) (point-max)))
4774 (insert "# -*- mode: org -*-\n\n"))
20908596
CD
4775 (unless org-inhibit-startup
4776 (when org-startup-align-all-tables
4777 (let ((bmp (buffer-modified-p)))
86fbb8ca 4778 (org-table-map-tables 'org-table-align 'quietly)
20908596 4779 (set-buffer-modified-p bmp)))
afe98dfa
CD
4780 (when org-startup-with-inline-images
4781 (org-display-inline-images))
c8d0cf5c
CD
4782 (when org-startup-indented
4783 (require 'org-indent)
4784 (org-indent-mode 1))
ed21c5c8
CD
4785 (unless org-inhibit-startup-visibility-stuff
4786 (org-set-startup-visibility))))
ef943dba 4787
8bfe682a
CD
4788(when (fboundp 'abbrev-table-put)
4789 (abbrev-table-put org-mode-abbrev-table
4790 :parents (list text-mode-abbrev-table)))
4791
20908596 4792(put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify)
b9661543 4793
20908596
CD
4794(defun org-current-time ()
4795 "Current time, possibly rounded to `org-time-stamp-rounding-minutes'."
4796 (if (> (car org-time-stamp-rounding-minutes) 1)
4797 (let ((r (car org-time-stamp-rounding-minutes))
4798 (time (decode-time)))
4799 (apply 'encode-time
4800 (append (list 0 (* r (floor (+ .5 (/ (float (nth 1 time)) r)))))
4801 (nthcdr 2 time))))
4802 (current-time)))
ef943dba 4803
acedf35c
CD
4804(defun org-today ()
4805 "Return today date, considering `org-extend-today-until'."
4806 (time-to-days
4807 (time-subtract (current-time)
4808 (list 0 (* 3600 org-extend-today-until) 0))))
4809
20908596 4810;;;; Font-Lock stuff, including the activators
ef943dba 4811
20908596 4812(defvar org-mouse-map (make-sparse-keymap))
86fbb8ca
CD
4813(org-defkey org-mouse-map [mouse-2] 'org-open-at-mouse)
4814(org-defkey org-mouse-map [mouse-3] 'org-find-file-at-mouse)
20908596
CD
4815(when org-mouse-1-follows-link
4816 (org-defkey org-mouse-map [follow-link] 'mouse-face))
4817(when org-tab-follows-link
4818 (org-defkey org-mouse-map [(tab)] 'org-open-at-point)
4819 (org-defkey org-mouse-map "\C-i" 'org-open-at-point))
48aaad2d 4820
20908596 4821(require 'font-lock)
48aaad2d 4822
20908596
CD
4823(defconst org-non-link-chars "]\t\n\r<>")
4824(defvar org-link-types '("http" "https" "ftp" "mailto" "file" "news"
afe98dfa 4825 "shell" "elisp" "doi" "message"))
20908596
CD
4826(defvar org-link-types-re nil
4827 "Matches a link that has a url-like prefix like \"http:\"")
4828(defvar org-link-re-with-space nil
4829 "Matches a link with spaces, optional angular brackets around it.")
4830(defvar org-link-re-with-space2 nil
4831 "Matches a link with spaces, optional angular brackets around it.")
ce4fdcb9
CD
4832(defvar org-link-re-with-space3 nil
4833 "Matches a link with spaces, only for internal part in bracket links.")
20908596
CD
4834(defvar org-angle-link-re nil
4835 "Matches link with angular brackets, spaces are allowed.")
4836(defvar org-plain-link-re nil
4837 "Matches plain link, without spaces.")
4838(defvar org-bracket-link-regexp nil
4839 "Matches a link in double brackets.")
4840(defvar org-bracket-link-analytic-regexp nil
4841 "Regular expression used to analyze links.
4842Here is what the match groups contain after a match:
48431: http:
48442: http
48453: path
48464: [desc]
48475: desc")
0bd48b37 4848(defvar org-bracket-link-analytic-regexp++ nil
86fbb8ca 4849 "Like `org-bracket-link-analytic-regexp', but include coderef internal type.")
20908596
CD
4850(defvar org-any-link-re nil
4851 "Regular expression matching any link.")
48aaad2d 4852
86fbb8ca
CD
4853(defcustom org-match-sexp-depth 3
4854 "Number of stacked braces for sub/superscript matching.
4855This has to be set before loading org.el to be effective."
4856 :group 'org-export-translation ; ??????????????????????????/
4857 :type 'integer)
4858
4859(defun org-create-multibrace-regexp (left right n)
4860 "Create a regular expression which will match a balanced sexp.
4861Opening delimiter is LEFT, and closing delimiter is RIGHT, both given
4862as single character strings.
4863The regexp returned will match the entire expression including the
4864delimiters. It will also define a single group which contains the
4865match except for the outermost delimiters. The maximum depth of
4866stacked delimiters is N. Escaping delimiters is not possible."
4867 (let* ((nothing (concat "[^" left right "]*?"))
4868 (or "\\|")
4869 (re nothing)
4870 (next (concat "\\(?:" nothing left nothing right "\\)+" nothing)))
4871 (while (> n 1)
4872 (setq n (1- n)
4873 re (concat re or next)
4874 next (concat "\\(?:" nothing left next right "\\)+" nothing)))
4875 (concat left "\\(" re "\\)" right)))
4876
4877(defvar org-match-substring-regexp
4878 (concat
4879 "\\([^\\]\\)\\([_^]\\)\\("
4880 "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
4881 "\\|"
4882 "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
4883 "\\|"
4884 "\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
4885 "The regular expression matching a sub- or superscript.")
4886
4887(defvar org-match-substring-with-braces-regexp
4888 (concat
4889 "\\([^\\]\\)\\([_^]\\)\\("
4890 "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
4891 "\\)")
4892 "The regular expression matching a sub- or superscript, forcing braces.")
4893
20908596
CD
4894(defun org-make-link-regexps ()
4895 "Update the link regular expressions.
4896This should be called after the variable `org-link-types' has changed."
4897 (setq org-link-types-re
4898 (concat
ed21c5c8 4899 "\\`\\(" (mapconcat 'regexp-quote org-link-types "\\|") "\\):")
20908596
CD
4900 org-link-re-with-space
4901 (concat
ed21c5c8 4902 "<?\\(" (mapconcat 'regexp-quote org-link-types "\\|") "\\):"
20908596
CD
4903 "\\([^" org-non-link-chars " ]"
4904 "[^" org-non-link-chars "]*"
4905 "[^" org-non-link-chars " ]\\)>?")
4906 org-link-re-with-space2
4907 (concat
ed21c5c8 4908 "<?\\(" (mapconcat 'regexp-quote org-link-types "\\|") "\\):"
20908596 4909 "\\([^" org-non-link-chars " ]"
93b62de8 4910 "[^\t\n\r]*"
20908596 4911 "[^" org-non-link-chars " ]\\)>?")
ce4fdcb9
CD
4912 org-link-re-with-space3
4913 (concat
ed21c5c8 4914 "<?\\(" (mapconcat 'regexp-quote org-link-types "\\|") "\\):"
ce4fdcb9
CD
4915 "\\([^" org-non-link-chars " ]"
4916 "[^\t\n\r]*\\)")
20908596
CD
4917 org-angle-link-re
4918 (concat
ed21c5c8 4919 "<\\(" (mapconcat 'regexp-quote org-link-types "\\|") "\\):"
20908596
CD
4920 "\\([^" org-non-link-chars " ]"
4921 "[^" org-non-link-chars "]*"
4922 "\\)>")
4923 org-plain-link-re
4924 (concat
ed21c5c8 4925 "\\<\\(" (mapconcat 'regexp-quote org-link-types "\\|") "\\):"
afe98dfa 4926 (org-re "\\([^ \t\n()<>]+\\(?:([[:word:]0-9_]+)\\|\\([^[:punct:] \t\n]\\|/\\)\\)\\)"))
ed21c5c8 4927 ;; "\\([^]\t\n\r<>() ]+[^]\t\n\r<>,.;() ]\\)")
20908596
CD
4928 org-bracket-link-regexp
4929 "\\[\\[\\([^][]+\\)\\]\\(\\[\\([^][]+\\)\\]\\)?\\]"
4930 org-bracket-link-analytic-regexp
4931 (concat
4932 "\\[\\["
ed21c5c8 4933 "\\(\\(" (mapconcat 'regexp-quote org-link-types "\\|") "\\):\\)?"
20908596
CD
4934 "\\([^]]+\\)"
4935 "\\]"
4936 "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
4937 "\\]")
0bd48b37
CD
4938 org-bracket-link-analytic-regexp++
4939 (concat
4940 "\\[\\["
ed21c5c8 4941 "\\(\\(" (mapconcat 'regexp-quote (cons "coderef" org-link-types) "\\|") "\\):\\)?"
0bd48b37
CD
4942 "\\([^]]+\\)"
4943 "\\]"
4944 "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
4945 "\\]")
20908596
CD
4946 org-any-link-re
4947 (concat "\\(" org-bracket-link-regexp "\\)\\|\\("
4948 org-angle-link-re "\\)\\|\\("
4949 org-plain-link-re "\\)")))
48aaad2d 4950
20908596 4951(org-make-link-regexps)
8c6fb58b 4952
20908596
CD
4953(defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)>"
4954 "Regular expression for fast time stamp matching.")
4955(defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)[]>]"
4956 "Regular expression for fast time stamp matching.")
4957(defconst org-ts-regexp0 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) *\\([^]-+0-9>\r\n ]*\\)\\( \\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
4958 "Regular expression matching time strings for analysis.
4959This one does not require the space after the date, so it can be used
4960on a string that terminates immediately after the date.")
4961(defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) +\\([^]-+0-9>\r\n ]*\\)\\( \\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
4962 "Regular expression matching time strings for analysis.")
4963(defconst org-ts-regexp2 (concat "<" org-ts-regexp1 "[^>\n]\\{0,16\\}>")
4964 "Regular expression matching time stamps, with groups.")
4965(defconst org-ts-regexp3 (concat "[[<]" org-ts-regexp1 "[^]>\n]\\{0,16\\}[]>]")
4966 "Regular expression matching time stamps (also [..]), with groups.")
4967(defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp)
4968 "Regular expression matching a time stamp range.")
4969(defconst org-tr-regexp-both
4970 (concat org-ts-regexp-both "--?-?" org-ts-regexp-both)
4971 "Regular expression matching a time stamp range.")
4972(defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?"
4973 org-ts-regexp "\\)?")
4974 "Regular expression matching a time stamp or time stamp range.")
4975(defconst org-tsr-regexp-both (concat org-ts-regexp-both "\\(--?-?"
4976 org-ts-regexp-both "\\)?")
4977 "Regular expression matching a time stamp or time stamp range.
4978The time stamps may be either active or inactive.")
48aaad2d 4979
20908596 4980(defvar org-emph-face nil)
2a57416f 4981
20908596
CD
4982(defun org-do-emphasis-faces (limit)
4983 "Run through the buffer and add overlays to links."
c8d0cf5c 4984 (let (rtn a)
20908596
CD
4985 (while (and (not rtn) (re-search-forward org-emph-re limit t))
4986 (if (not (= (char-after (match-beginning 3))
4987 (char-after (match-beginning 4))))
4988 (progn
4989 (setq rtn t)
c8d0cf5c 4990 (setq a (assoc (match-string 3) org-emphasis-alist))
20908596
CD
4991 (font-lock-prepend-text-property (match-beginning 2) (match-end 2)
4992 'face
c8d0cf5c
CD
4993 (nth 1 a))
4994 (and (nth 4 a)
4995 (org-remove-flyspell-overlays-in
4996 (match-beginning 0) (match-end 0)))
20908596 4997 (add-text-properties (match-beginning 2) (match-end 2)
86fbb8ca 4998 '(font-lock-multiline t org-emphasis t))
20908596
CD
4999 (when org-hide-emphasis-markers
5000 (add-text-properties (match-end 4) (match-beginning 5)
5001 '(invisible org-link))
5002 (add-text-properties (match-beginning 3) (match-end 3)
5003 '(invisible org-link)))))
5004 (backward-char 1))
5005 rtn))
891f4676 5006
20908596
CD
5007(defun org-emphasize (&optional char)
5008 "Insert or change an emphasis, i.e. a font like bold or italic.
5009If there is an active region, change that region to a new emphasis.
5010If there is no region, just insert the marker characters and position
5011the cursor between them.
5012CHAR should be either the marker character, or the first character of the
5013HTML tag associated with that emphasis. If CHAR is a space, the means
5014to remove the emphasis of the selected region.
5015If char is not given (for example in an interactive call) it
5016will be prompted for."
5017 (interactive)
5018 (let ((eal org-emphasis-alist) e det
5019 (erc org-emphasis-regexp-components)
5020 (prompt "")
5021 (string "") beg end move tag c s)
5022 (if (org-region-active-p)
5023 (setq beg (region-beginning) end (region-end)
5024 string (buffer-substring beg end))
5025 (setq move t))
48aaad2d 5026
20908596
CD
5027 (while (setq e (pop eal))
5028 (setq tag (car (org-split-string (nth 2 e) "[ <>/]+"))
5029 c (aref tag 0))
5030 (push (cons c (string-to-char (car e))) det)
5031 (setq prompt (concat prompt (format " [%s%c]%s" (car e) c
5032 (substring tag 1)))))
93b62de8 5033 (setq det (nreverse det))
20908596
CD
5034 (unless char
5035 (message "%s" (concat "Emphasis marker or tag:" prompt))
5036 (setq char (read-char-exclusive)))
5037 (setq char (or (cdr (assoc char det)) char))
5038 (if (equal char ?\ )
5039 (setq s "" move nil)
5040 (unless (assoc (char-to-string char) org-emphasis-alist)
5041 (error "No such emphasis marker: \"%c\"" char))
5042 (setq s (char-to-string char)))
5043 (while (and (> (length string) 1)
5044 (equal (substring string 0 1) (substring string -1))
5045 (assoc (substring string 0 1) org-emphasis-alist))
5046 (setq string (substring string 1 -1)))
5047 (setq string (concat s string s))
5048 (if beg (delete-region beg end))
5049 (unless (or (bolp)
5050 (string-match (concat "[" (nth 0 erc) "\n]")
5051 (char-to-string (char-before (point)))))
5052 (insert " "))
ed21c5c8
CD
5053 (unless (or (eobp)
5054 (string-match (concat "[" (nth 1 erc) "\n]")
5055 (char-to-string (char-after (point)))))
20908596
CD
5056 (insert " ") (backward-char 1))
5057 (insert string)
5058 (and move (backward-char 1))))
891f4676 5059
20908596
CD
5060(defconst org-nonsticky-props
5061 '(mouse-face highlight keymap invisible intangible help-echo org-linked-text))
891f4676 5062
c8d0cf5c
CD
5063(defsubst org-rear-nonsticky-at (pos)
5064 (add-text-properties (1- pos) pos (list 'rear-nonsticky org-nonsticky-props)))
891f4676 5065
20908596
CD
5066(defun org-activate-plain-links (limit)
5067 "Run through the buffer and add overlays to links."
5068 (catch 'exit
5069 (let (f)
c8d0cf5c
CD
5070 (if (re-search-forward org-plain-link-re limit t)
5071 (progn
5072 (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
5073 (setq f (get-text-property (match-beginning 0) 'face))
5074 (if (or (eq f 'org-tag)
5075 (and (listp f) (memq 'org-tag f)))
5076 nil
5077 (add-text-properties (match-beginning 0) (match-end 0)
5078 (list 'mouse-face 'highlight
5dec9555 5079 'face 'org-link
c8d0cf5c
CD
5080 'keymap org-mouse-map))
5081 (org-rear-nonsticky-at (match-end 0)))
5082 t)))))
891f4676 5083
20908596 5084(defun org-activate-code (limit)
621f83e4
CD
5085 (if (re-search-forward "^[ \t]*\\(: .*\n?\\)" limit t)
5086 (progn
c8d0cf5c 5087 (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
20908596
CD
5088 (remove-text-properties (match-beginning 0) (match-end 0)
5089 '(display t invisible t intangible t))
5090 t)))
891f4676 5091
afe98dfa
CD
5092(defcustom org-src-fontify-natively nil
5093 "When non-nil, fontify code in code blocks."
5094 :type 'boolean
5095 :group 'org-appearance
5096 :group 'org-babel)
5097
c8d0cf5c
CD
5098(defun org-fontify-meta-lines-and-blocks (limit)
5099 "Fontify #+ lines and blocks, in the correct ways."
5100 (let ((case-fold-search t))
5101 (if (re-search-forward
afe98dfa 5102 "^\\([ \t]*#\\+\\(\\([a-zA-Z]+:?\\| \\|$\\)\\(_\\([a-zA-Z]+\\)\\)?\\)[ \t]*\\(\\([^ \t\n]*\\)[ \t]*\\(.*\\)\\)\\)"
c8d0cf5c
CD
5103 limit t)
5104 (let ((beg (match-beginning 0))
afe98dfa
CD
5105 (block-start (match-end 0))
5106 (block-end nil)
5107 (lang (match-string 7))
c8d0cf5c
CD
5108 (beg1 (line-beginning-position 2))
5109 (dc1 (downcase (match-string 2)))
5110 (dc3 (downcase (match-string 3)))
5dec9555 5111 end end1 quoting block-type)
c8d0cf5c
CD
5112 (cond
5113 ((member dc1 '("html:" "ascii:" "latex:" "docbook:"))
5114 ;; a single line of backend-specific content
5115 (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
5116 (remove-text-properties (match-beginning 0) (match-end 0)
5117 '(display t invisible t intangible t))
5118 (add-text-properties (match-beginning 1) (match-end 3)
5119 '(font-lock-fontified t face org-meta-line))
afe98dfa 5120 (add-text-properties (match-beginning 6) (+ (match-end 6) 1)
c8d0cf5c 5121 '(font-lock-fontified t face org-block))
afe98dfa 5122 ; for backend-specific code
c8d0cf5c
CD
5123 t)
5124 ((and (match-end 4) (equal dc3 "begin"))
86fbb8ca 5125 ;; Truly a block
5dec9555
CD
5126 (setq block-type (downcase (match-string 5))
5127 quoting (member block-type org-protecting-blocks))
c8d0cf5c
CD
5128 (when (re-search-forward
5129 (concat "^[ \t]*#\\+end" (match-string 4) "\\>.*")
5130 nil t) ;; on purpose, we look further than LIMIT
5131 (setq end (match-end 0) end1 (1- (match-beginning 0)))
afe98dfa 5132 (setq block-end (match-beginning 0))
c8d0cf5c
CD
5133 (when quoting
5134 (remove-text-properties beg end
5135 '(display t invisible t intangible t)))
5136 (add-text-properties
5137 beg end
5138 '(font-lock-fontified t font-lock-multiline t))
5139 (add-text-properties beg beg1 '(face org-meta-line))
afe98dfa
CD
5140 (add-text-properties end1 (+ end 1) '(face org-meta-line))
5141 ; for end_src
5dec9555 5142 (cond
afe98dfa
CD
5143 ((and lang org-src-fontify-natively)
5144 (org-src-font-lock-fontify-block lang block-start block-end))
5dec9555 5145 (quoting
afe98dfa
CD
5146 (add-text-properties beg1 (+ end1 1) '(face
5147 org-block)))
5148 ; end of source block
ed21c5c8 5149 ((not org-fontify-quote-and-verse-blocks))
5dec9555
CD
5150 ((string= block-type "quote")
5151 (add-text-properties beg1 end1 '(face org-quote)))
5152 ((string= block-type "verse")
5153 (add-text-properties beg1 end1 '(face org-verse))))
c8d0cf5c 5154 t))
ed21c5c8
CD
5155 ((member dc1 '("title:" "author:" "email:" "date:"))
5156 (add-text-properties
5157 beg (match-end 3)
5158 (if (member (intern (substring dc1 0 -1)) org-hidden-keywords)
5159 '(font-lock-fontified t invisible t)
5160 '(font-lock-fontified t face org-document-info-keyword)))
5161 (add-text-properties
5162 (match-beginning 6) (match-end 6)
5163 (if (string-equal dc1 "title:")
5164 '(font-lock-fontified t face org-document-title)
5165 '(font-lock-fontified t face org-document-info))))
c8d0cf5c
CD
5166 ((not (member (char-after beg) '(?\ ?\t)))
5167 ;; just any other in-buffer setting, but not indented
5168 (add-text-properties
5169 beg (match-end 0)
5170 '(font-lock-fontified t face org-meta-line))
5171 t)
8d642074 5172 ((or (member dc1 '("begin:" "end:" "caption:" "label:"
86fbb8ca
CD
5173 "orgtbl:" "tblfm:" "tblname:" "result:"
5174 "results:" "source:" "srcname:" "call:"))
c8d0cf5c
CD
5175 (and (match-end 4) (equal dc3 "attr")))
5176 (add-text-properties
5177 beg (match-end 0)
5178 '(font-lock-fontified t face org-meta-line))
5179 t)
8d642074
CD
5180 ((member dc3 '(" " ""))
5181 (add-text-properties
5182 beg (match-end 0)
5183 '(font-lock-fontified t face font-lock-comment-face)))
c8d0cf5c
CD
5184 (t nil))))))
5185
20908596
CD
5186(defun org-activate-angle-links (limit)
5187 "Run through the buffer and add overlays to links."
5188 (if (re-search-forward org-angle-link-re limit t)
5189 (progn
c8d0cf5c 5190 (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
20908596
CD
5191 (add-text-properties (match-beginning 0) (match-end 0)
5192 (list 'mouse-face 'highlight
c8d0cf5c
CD
5193 'keymap org-mouse-map))
5194 (org-rear-nonsticky-at (match-end 0))
20908596 5195 t)))
891f4676 5196
0bd48b37
CD
5197(defun org-activate-footnote-links (limit)
5198 "Run through the buffer and add overlays to links."
c8d0cf5c 5199 (if (re-search-forward "\\(^\\|[^][]\\)\\(\\[\\([0-9]+\\]\\|fn:[^ \t\r\n:]+?[]:]\\)\\)"
0bd48b37
CD
5200 limit t)
5201 (progn
c8d0cf5c 5202 (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
0bd48b37
CD
5203 (add-text-properties (match-beginning 2) (match-end 2)
5204 (list 'mouse-face 'highlight
0bd48b37
CD
5205 'keymap org-mouse-map
5206 'help-echo
5207 (if (= (point-at-bol) (match-beginning 2))
5208 "Footnote definition"
5209 "Footnote reference")
5210 ))
c8d0cf5c 5211 (org-rear-nonsticky-at (match-end 2))
0bd48b37
CD
5212 t)))
5213
20908596
CD
5214(defun org-activate-bracket-links (limit)
5215 "Run through the buffer and add overlays to bracketed links."
5216 (if (re-search-forward org-bracket-link-regexp limit t)
5217 (let* ((help (concat "LINK: "
5218 (org-match-string-no-properties 1)))
5219 ;; FIXME: above we should remove the escapes.
5220 ;; but that requires another match, protecting match data,
5221 ;; a lot of overhead for font-lock.
5222 (ip (org-maybe-intangible
c8d0cf5c 5223 (list 'invisible 'org-link
20908596
CD
5224 'keymap org-mouse-map 'mouse-face 'highlight
5225 'font-lock-multiline t 'help-echo help)))
c8d0cf5c
CD
5226 (vp (list 'keymap org-mouse-map 'mouse-face 'highlight
5227 'font-lock-multiline t 'help-echo help)))
20908596
CD
5228 ;; We need to remove the invisible property here. Table narrowing
5229 ;; may have made some of this invisible.
c8d0cf5c 5230 (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
20908596
CD
5231 (remove-text-properties (match-beginning 0) (match-end 0)
5232 '(invisible nil))
5233 (if (match-end 3)
5234 (progn
5235 (add-text-properties (match-beginning 0) (match-beginning 3) ip)
c8d0cf5c 5236 (org-rear-nonsticky-at (match-beginning 3))
20908596 5237 (add-text-properties (match-beginning 3) (match-end 3) vp)
c8d0cf5c
CD
5238 (org-rear-nonsticky-at (match-end 3))
5239 (add-text-properties (match-end 3) (match-end 0) ip)
5240 (org-rear-nonsticky-at (match-end 0)))
20908596 5241 (add-text-properties (match-beginning 0) (match-beginning 1) ip)
c8d0cf5c 5242 (org-rear-nonsticky-at (match-beginning 1))
20908596 5243 (add-text-properties (match-beginning 1) (match-end 1) vp)
c8d0cf5c
CD
5244 (org-rear-nonsticky-at (match-end 1))
5245 (add-text-properties (match-end 1) (match-end 0) ip)
5246 (org-rear-nonsticky-at (match-end 0)))
20908596 5247 t)))
891f4676 5248
20908596
CD
5249(defun org-activate-dates (limit)
5250 "Run through the buffer and add overlays to dates."
5251 (if (re-search-forward org-tsr-regexp-both limit t)
5252 (progn
c8d0cf5c 5253 (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
20908596
CD
5254 (add-text-properties (match-beginning 0) (match-end 0)
5255 (list 'mouse-face 'highlight
20908596 5256 'keymap org-mouse-map))
c8d0cf5c 5257 (org-rear-nonsticky-at (match-end 0))
20908596
CD
5258 (when org-display-custom-times
5259 (if (match-end 3)
5260 (org-display-custom-time (match-beginning 3) (match-end 3)))
5261 (org-display-custom-time (match-beginning 1) (match-end 1)))
5262 t)))
891f4676 5263
20908596
CD
5264(defvar org-target-link-regexp nil
5265 "Regular expression matching radio targets in plain text.")
ff4be292 5266(make-variable-buffer-local 'org-target-link-regexp)
20908596
CD
5267(defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>"
5268 "Regular expression matching a link target.")
5269(defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>"
5270 "Regular expression matching a radio target.")
5271(defvar org-any-target-regexp "<<<?\\([^<>\n\r]+\\)>>>?" ; FIXME, not exact, would match <<<aaa>> as a radio target.
5272 "Regular expression matching any target.")
a3fbe8c4 5273
20908596
CD
5274(defun org-activate-target-links (limit)
5275 "Run through the buffer and add overlays to target matches."
5276 (when org-target-link-regexp
5277 (let ((case-fold-search t))
5278 (if (re-search-forward org-target-link-regexp limit t)
5279 (progn
c8d0cf5c 5280 (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
20908596
CD
5281 (add-text-properties (match-beginning 0) (match-end 0)
5282 (list 'mouse-face 'highlight
20908596
CD
5283 'keymap org-mouse-map
5284 'help-echo "Radio target link"
5285 'org-linked-text t))
c8d0cf5c 5286 (org-rear-nonsticky-at (match-end 0))
20908596 5287 t)))))
891f4676 5288
20908596
CD
5289(defun org-update-radio-target-regexp ()
5290 "Find all radio targets in this file and update the regular expression."
5291 (interactive)
5292 (when (memq 'radio org-activate-links)
5293 (setq org-target-link-regexp
5294 (org-make-target-link-regexp (org-all-targets 'radio)))
5295 (org-restart-font-lock)))
891f4676 5296
20908596
CD
5297(defun org-hide-wide-columns (limit)
5298 (let (s e)
5299 (setq s (text-property-any (point) (or limit (point-max))
5300 'org-cwidth t))
5301 (when s
5302 (setq e (next-single-property-change s 'org-cwidth))
5303 (add-text-properties s e (org-maybe-intangible '(invisible org-cwidth)))
5304 (goto-char e)
5305 t)))
891f4676 5306
20908596
CD
5307(defvar org-latex-and-specials-regexp nil
5308 "Regular expression for highlighting export special stuff.")
5309(defvar org-match-substring-regexp)
5310(defvar org-match-substring-with-braces-regexp)
54a0dee5
CD
5311
5312;; This should be with the exporter code, but we also use if for font-locking
5313(defconst org-export-html-special-string-regexps
5314 '(("\\\\-" . "&shy;")
5315 ("---\\([^-]\\)" . "&mdash;\\1")
5316 ("--\\([^-]\\)" . "&ndash;\\1")
5317 ("\\.\\.\\." . "&hellip;"))
5318 "Regular expressions for special string conversion.")
5319
891f4676 5320
20908596
CD
5321(defun org-compute-latex-and-specials-regexp ()
5322 "Compute regular expression for stuff treated specially by exporters."
5323 (if (not org-highlight-latex-fragments-and-specials)
5324 (org-set-local 'org-latex-and-specials-regexp nil)
5325 (require 'org-exp)
5326 (let*
5327 ((matchers (plist-get org-format-latex-options :matchers))
5328 (latexs (delq nil (mapcar (lambda (x) (if (member (car x) matchers) x))
5329 org-latex-regexps)))
ed21c5c8 5330 (org-export-allow-BIND nil)
20908596
CD
5331 (options (org-combine-plists (org-default-export-plist)
5332 (org-infile-export-plist)))
5333 (org-export-with-sub-superscripts (plist-get options :sub-superscript))
5334 (org-export-with-LaTeX-fragments (plist-get options :LaTeX-fragments))
5335 (org-export-with-TeX-macros (plist-get options :TeX-macros))
5336 (org-export-html-expand (plist-get options :expand-quoted-html))
5337 (org-export-with-special-strings (plist-get options :special-strings))
5338 (re-sub
5339 (cond
5340 ((equal org-export-with-sub-superscripts '{})
5341 (list org-match-substring-with-braces-regexp))
5342 (org-export-with-sub-superscripts
5343 (list org-match-substring-regexp))
5344 (t nil)))
5345 (re-latex
5346 (if org-export-with-LaTeX-fragments
5347 (mapcar (lambda (x) (nth 1 x)) latexs)))
5348 (re-macros
5349 (if org-export-with-TeX-macros
5350 (list (concat "\\\\"
5351 (regexp-opt
86fbb8ca
CD
5352 (append
5353
5354 (delq nil
5355 (mapcar 'car-safe
5356 (append org-entities-user
5357 org-entities)))
5358 (if (boundp 'org-latex-entities)
5359 (mapcar (lambda (x)
5360 (or (car-safe x) x))
5361 org-latex-entities)
5362 nil))
20908596
CD
5363 'words))) ; FIXME
5364 ))
5365 ;; (list "\\\\\\(?:[a-zA-Z]+\\)")))
5366 (re-special (if org-export-with-special-strings
5367 (mapcar (lambda (x) (car x))
5368 org-export-html-special-string-regexps)))
5369 (re-rest
5370 (delq nil
5371 (list
5372 (if org-export-html-expand "@<[^>\n]+>")
5373 ))))
5374 (org-set-local
5375 'org-latex-and-specials-regexp
5376 (mapconcat 'identity (append re-latex re-sub re-macros re-special
5377 re-rest) "\\|")))))
d3f4dbe8 5378
20908596
CD
5379(defun org-do-latex-and-special-faces (limit)
5380 "Run through the buffer and add overlays to links."
5381 (when org-latex-and-specials-regexp
5382 (let (rtn d)
5383 (while (and (not rtn) (re-search-forward org-latex-and-specials-regexp
5384 limit t))
5385 (if (not (memq (car-safe (get-text-property (1+ (match-beginning 0))
5386 'face))
5387 '(org-code org-verbatim underline)))
5388 (progn
5389 (setq rtn t
5390 d (cond ((member (char-after (1+ (match-beginning 0)))
5391 '(?_ ?^)) 1)
5392 (t 0)))
5393 (font-lock-prepend-text-property
5394 (+ d (match-beginning 0)) (match-end 0)
5395 'face 'org-latex-and-export-specials)
5396 (add-text-properties (+ d (match-beginning 0)) (match-end 0)
5397 '(font-lock-multiline t)))))
5398 rtn)))
d3f4dbe8 5399
20908596 5400(defun org-restart-font-lock ()
86fbb8ca 5401 "Restart `font-lock-mode', to force refontification."
20908596
CD
5402 (when (and (boundp 'font-lock-mode) font-lock-mode)
5403 (font-lock-mode -1)
5404 (font-lock-mode 1)))
d3f4dbe8 5405
20908596
CD
5406(defun org-all-targets (&optional radio)
5407 "Return a list of all targets in this file.
5408With optional argument RADIO, only find radio targets."
5409 (let ((re (if radio org-radio-target-regexp org-target-regexp))
5410 rtn)
5411 (save-excursion
5412 (goto-char (point-min))
5413 (while (re-search-forward re nil t)
5414 (add-to-list 'rtn (downcase (org-match-string-no-properties 1))))
5415 rtn)))
891f4676 5416
20908596
CD
5417(defun org-make-target-link-regexp (targets)
5418 "Make regular expression matching all strings in TARGETS.
5419The regular expression finds the targets also if there is a line break
5420between words."
5421 (and targets
5422 (concat
5423 "\\<\\("
5424 (mapconcat
5425 (lambda (x)
5426 (while (string-match " +" x)
5427 (setq x (replace-match "\\s-+" t t x)))
5428 x)
5429 targets
5430 "\\|")
5431 "\\)\\>")))
3278a016 5432
20908596 5433(defun org-activate-tags (limit)
afe98dfa 5434 (if (re-search-forward (org-re "^\\*+.*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \r\n]") limit t)
20908596 5435 (progn
ed21c5c8 5436 (org-remove-flyspell-overlays-in (match-beginning 1) (match-end 1))
20908596
CD
5437 (add-text-properties (match-beginning 1) (match-end 1)
5438 (list 'mouse-face 'highlight
20908596 5439 'keymap org-mouse-map))
c8d0cf5c 5440 (org-rear-nonsticky-at (match-end 1))
20908596 5441 t)))
891f4676 5442
20908596 5443(defun org-outline-level ()
8bfe682a
CD
5444 "Compute the outline level of the heading at point.
5445This function assumes that the cursor is at the beginning of a line matched
86fbb8ca 5446by `outline-regexp'. Otherwise it returns garbage.
8bfe682a
CD
5447If this is called at a normal headline, the level is the number of stars.
5448Use `org-reduced-level' to remove the effect of `org-odd-levels'.
5449For plain list items, if they are matched by `outline-regexp', this returns
54501000 plus the line indentation."
20908596
CD
5451 (save-excursion
5452 (looking-at outline-regexp)
5453 (if (match-beginning 1)
5454 (+ (org-get-string-indentation (match-string 1)) 1000)
5455 (1- (- (match-end 0) (match-beginning 0))))))
15841868 5456
20908596 5457(defvar org-font-lock-keywords nil)
891f4676 5458
b349f79f 5459(defconst org-property-re (org-re "^[ \t]*\\(:\\([-[:alnum:]_]+\\):\\)[ \t]*\\([^ \t\r\n].*\\)")
20908596 5460 "Regular expression matching a property line.")
891f4676 5461
b349f79f
CD
5462(defvar org-font-lock-hook nil
5463 "Functions to be called for special font lock stuff.")
5464
afe98dfa
CD
5465(defvar org-font-lock-set-keywords-hook nil
5466 "Functions that can manipulate `org-font-lock-extra-keywords'.
5467This is calles after `org-font-lock-extra-keywords' is defined, but before
5468it is installed to be used by font lock. This can be useful if something
5469needs to be inserted at a specific position in the font-lock sequence.")
5470
b349f79f
CD
5471(defun org-font-lock-hook (limit)
5472 (run-hook-with-args 'org-font-lock-hook limit))
5473
20908596
CD
5474(defun org-set-font-lock-defaults ()
5475 (let* ((em org-fontify-emphasized-text)
5476 (lk org-activate-links)
5477 (org-font-lock-extra-keywords
5478 (list
b349f79f
CD
5479 ;; Call the hook
5480 '(org-font-lock-hook)
20908596 5481 ;; Headlines
c8d0cf5c
CD
5482 `(,(if org-fontify-whole-heading-line
5483 "^\\(\\**\\)\\(\\* \\)\\(.*\n?\\)"
5484 "^\\(\\**\\)\\(\\* \\)\\(.*\\)")
5485 (1 (org-get-level-face 1))
5486 (2 (org-get-level-face 2))
5487 (3 (org-get-level-face 3)))
20908596
CD
5488 ;; Table lines
5489 '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)"
5490 (1 'org-table t))
5491 ;; Table internals
5492 '("^[ \t]*|\\(?:.*?|\\)? *\\(:?=[^|\n]*\\)" (1 'org-formula t))
5493 '("^[ \t]*| *\\([#*]\\) *|" (1 'org-formula t))
5494 '("^[ \t]*|\\( *\\([$!_^/]\\) *|.*\\)|" (1 'org-formula t))
afe98dfa 5495 '("| *\\(<[lrc]?[0-9]*>\\)" (1 'org-formula t))
20908596
CD
5496 ;; Drawers
5497 (list org-drawer-regexp '(0 'org-special-keyword t))
5498 (list "^[ \t]*:END:" '(0 'org-special-keyword t))
5499 ;; Properties
5500 (list org-property-re
5501 '(1 'org-special-keyword t)
5502 '(3 'org-property-value t))
20908596
CD
5503 ;; Links
5504 (if (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
5505 (if (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
5dec9555 5506 (if (memq 'plain lk) '(org-activate-plain-links))
20908596
CD
5507 (if (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
5508 (if (memq 'radio lk) '(org-activate-target-links (0 'org-link t)))
5509 (if (memq 'date lk) '(org-activate-dates (0 'org-date t)))
0bd48b37
CD
5510 (if (memq 'footnote lk) '(org-activate-footnote-links
5511 (2 'org-footnote t)))
20908596
CD
5512 '("^&?%%(.*\\|<%%([^>\n]*?>" (0 'org-sexp-date t))
5513 '(org-hide-wide-columns (0 nil append))
5514 ;; TODO lines
c8d0cf5c 5515 (list (concat "^\\*+[ \t]+" org-todo-regexp "\\([ \t]\\|$\\)")
20908596
CD
5516 '(1 (org-get-todo-face 1) t))
5517 ;; DONE
5518 (if org-fontify-done-headline
5519 (list (concat "^[*]+ +\\<\\("
5520 (mapconcat 'regexp-quote org-done-keywords "\\|")
5521 "\\)\\(.*\\)")
5522 '(2 'org-headline-done t))
5523 nil)
5524 ;; Priorities
c8d0cf5c 5525 '(org-font-lock-add-priority-faces)
ff4be292
CD
5526 ;; Tags
5527 '(org-font-lock-add-tag-faces)
20908596
CD
5528 ;; Special keywords
5529 (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t))
5530 (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword t))
5531 (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t))
5532 (list (concat "\\<" org-clock-string) '(0 'org-special-keyword t))
5533 ;; Emphasis
5534 (if em
5535 (if (featurep 'xemacs)
5536 '(org-do-emphasis-faces (0 nil append))
5537 '(org-do-emphasis-faces)))
5538 ;; Checkboxes
afe98dfa
CD
5539 '("^[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\)[ \t]+\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\(\\[[- X]\\]\\)"
5540 1 'org-checkbox prepend)
5541 (if (cdr (assq 'checkbox org-list-automatic-rules))
20908596
CD
5542 '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
5543 (0 (org-get-checkbox-statistics-face) t)))
b349f79f 5544 ;; Description list items
afe98dfa 5545 '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\)[ \t]+\\(.*? ::\\)"
b349f79f 5546 2 'bold prepend)
c8d0cf5c 5547 ;; ARCHIVEd headings
20908596
CD
5548 (list (concat "^\\*+ \\(.*:" org-archive-tag ":.*\\)")
5549 '(1 'org-archived prepend))
5550 ;; Specials
5551 '(org-do-latex-and-special-faces)
86fbb8ca
CD
5552 '(org-fontify-entities)
5553 '(org-raise-scripts)
20908596
CD
5554 ;; Code
5555 '(org-activate-code (1 'org-code t))
5556 ;; COMMENT
5557 (list (concat "^\\*+[ \t]+\\<\\(" org-comment-string
5558 "\\|" org-quote-string "\\)\\>")
5559 '(1 'org-special-keyword t))
5560 '("^#.*" (0 'font-lock-comment-face t))
c8d0cf5c
CD
5561 ;; Blocks and meta lines
5562 '(org-fontify-meta-lines-and-blocks)
20908596
CD
5563 )))
5564 (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords))
afe98dfa 5565 (run-hooks 'org-font-lock-set-keywords-hook)
20908596
CD
5566 ;; Now set the full font-lock-keywords
5567 (org-set-local 'org-font-lock-keywords org-font-lock-extra-keywords)
5568 (org-set-local 'font-lock-defaults
5569 '(org-font-lock-keywords t nil nil backward-paragraph))
5570 (kill-local-variable 'font-lock-keywords) nil))
5571
86fbb8ca
CD
5572(defun org-toggle-pretty-entities ()
5573 "Toggle the composition display of entities as UTF8 characters."
5574 (interactive)
5575 (org-set-local 'org-pretty-entities (not org-pretty-entities))
5576 (org-restart-font-lock)
5577 (if org-pretty-entities
01c35094 5578 (message "Entities are displayed as UTF8 characters")
86fbb8ca
CD
5579 (save-restriction
5580 (widen)
afe98dfa 5581 (org-decompose-region (point-min) (point-max))
86fbb8ca
CD
5582 (message "Entities are displayed plain"))))
5583
5584(defun org-fontify-entities (limit)
5585 "Find an entity to fontify."
5586 (let (ee)
5587 (when org-pretty-entities
5588 (catch 'match
5589 (while (re-search-forward
5590 "\\\\\\([a-zA-Z][a-zA-Z0-9]*\\)\\($\\|[^[:alnum:]\n]\\)"
5591 limit t)
5592 (if (and (not (org-in-indented-comment-line))
5593 (setq ee (org-entity-get (match-string 1)))
5594 (= (length (nth 6 ee)) 1))
5595 (progn
5596 (add-text-properties
5597 (match-beginning 0) (match-end 1)
5598 (list 'font-lock-fontified t))
5599 (compose-region (match-beginning 0) (match-end 1)
5600 (nth 6 ee) nil)
5601 (backward-char 1)
5602 (throw 'match t))))
5603 nil))))
5604
c8d0cf5c 5605(defun org-fontify-like-in-org-mode (s &optional odd-levels)
86fbb8ca 5606 "Fontify string S like in Org-mode."
c8d0cf5c
CD
5607 (with-temp-buffer
5608 (insert s)
5609 (let ((org-odd-levels-only odd-levels))
5610 (org-mode)
5611 (font-lock-fontify-buffer)
5612 (buffer-string))))
5613
20908596
CD
5614(defvar org-m nil)
5615(defvar org-l nil)
5616(defvar org-f nil)
5617(defun org-get-level-face (n)
acedf35c
CD
5618 "Get the right face for match N in font-lock matching of headlines."
5619 (setq org-l (- (match-end 2) (match-beginning 1) 1))
5620 (if org-odd-levels-only (setq org-l (1+ (/ org-l 2))))
5621 (if org-cycle-level-faces
5622 (setq org-f (nth (% (1- org-l) org-n-level-faces) org-level-faces))
5623 (setq org-f (nth (1- (min org-l org-n-level-faces)) org-level-faces)))
5624 (cond
5625 ((eq n 1) (if org-hide-leading-stars 'org-hide org-f))
5626 ((eq n 2) org-f)
5627 (t (if org-level-color-stars-only nil org-f))))
5628
20908596
CD
5629
5630(defun org-get-todo-face (kwd)
5631 "Get the right face for a TODO keyword KWD.
5632If KWD is a number, get the corresponding match group."
5633 (if (numberp kwd) (setq kwd (match-string kwd)))
ed21c5c8
CD
5634 (or (org-face-from-face-or-color
5635 'todo 'org-todo (cdr (assoc kwd org-todo-keyword-faces)))
20908596
CD
5636 (and (member kwd org-done-keywords) 'org-done)
5637 'org-todo))
d3f4dbe8 5638
ed21c5c8
CD
5639(defun org-face-from-face-or-color (context inherit face-or-color)
5640 "Create a face list that inherits INHERIT, but sets the foreground color.
5641When FACE-OR-COLOR is not a string, just return it."
5642 (if (stringp face-or-color)
5643 (list :inherit inherit
5644 (cdr (assoc context org-faces-easy-properties))
5645 face-or-color)
5646 face-or-color))
5647
ff4be292
CD
5648(defun org-font-lock-add-tag-faces (limit)
5649 "Add the special tag faces."
5650 (when (and org-tag-faces org-tags-special-faces-re)
5651 (while (re-search-forward org-tags-special-faces-re limit t)
5652 (add-text-properties (match-beginning 1) (match-end 1)
5653 (list 'face (org-get-tag-face 1)
5654 'font-lock-fontified t))
5655 (backward-char 1))))
5656
c8d0cf5c
CD
5657(defun org-font-lock-add-priority-faces (limit)
5658 "Add the special priority faces."
5659 (while (re-search-forward "\\[#\\([A-Z0-9]\\)\\]" limit t)
5660 (add-text-properties
5661 (match-beginning 0) (match-end 0)
ed21c5c8
CD
5662 (list 'face (or (org-face-from-face-or-color
5663 'priority 'org-special-keyword
5664 (cdr (assoc (char-after (match-beginning 1))
5665 org-priority-faces)))
c8d0cf5c
CD
5666 'org-special-keyword)
5667 'font-lock-fontified t))))
5668
ff4be292
CD
5669(defun org-get-tag-face (kwd)
5670 "Get the right face for a TODO keyword KWD.
5671If KWD is a number, get the corresponding match group."
5672 (if (numberp kwd) (setq kwd (match-string kwd)))
ed21c5c8
CD
5673 (or (org-face-from-face-or-color
5674 'tag 'org-tag (cdr (assoc kwd org-tag-faces)))
ff4be292
CD
5675 'org-tag))
5676
20908596
CD
5677(defun org-unfontify-region (beg end &optional maybe_loudly)
5678 "Remove fontification and activation overlays from links."
5679 (font-lock-default-unfontify-region beg end)
5680 (let* ((buffer-undo-list t)
5681 (inhibit-read-only t) (inhibit-point-motion-hooks t)
5682 (inhibit-modification-hooks t)
5683 deactivate-mark buffer-file-name buffer-file-truename)
afe98dfa 5684 (org-decompose-region beg end)
8bfe682a
CD
5685 (remove-text-properties
5686 beg end
5687 (if org-indent-mode
5688 ;; also remove line-prefix and wrap-prefix properties
5689 '(mouse-face t keymap t org-linked-text t
5690 invisible t intangible t
5691 line-prefix t wrap-prefix t
86fbb8ca 5692 org-no-flyspell t org-emphasis t)
8bfe682a
CD
5693 '(mouse-face t keymap t org-linked-text t
5694 invisible t intangible t
86fbb8ca
CD
5695 org-no-flyspell t org-emphasis t)))
5696 (org-remove-font-lock-display-properties beg end)))
5697
5698(defconst org-script-display '(((raise -0.3) (height 0.7))
5699 ((raise 0.3) (height 0.7))
5700 ((raise -0.5))
5701 ((raise 0.5)))
5702 "Display properties for showing superscripts and subscripts.")
5703
5704(defun org-remove-font-lock-display-properties (beg end)
5705 "Remove specific display properties that have been added by font lock.
5706The will remove the raise properties that are used to show superscripts
5707and subscripts."
5708 (let (next prop)
5709 (while (< beg end)
5710 (setq next (next-single-property-change beg 'display nil end)
5711 prop (get-text-property beg 'display))
5712 (if (member prop org-script-display)
5713 (put-text-property beg next 'display nil))
5714 (setq beg next))))
5715
5716(defun org-raise-scripts (limit)
5717 "Add raise properties to sub/superscripts."
5718 (when (and org-pretty-entities org-pretty-entities-include-sub-superscripts)
5719 (if (re-search-forward
5720 (if (eq org-use-sub-superscripts t)
5721 org-match-substring-regexp
5722 org-match-substring-with-braces-regexp)
5723 limit t)
5724 (let* ((pos (point)) table-p comment-p
5725 (mpos (match-beginning 3))
5726 (emph-p (get-text-property mpos 'org-emphasis))
5727 (link-p (get-text-property mpos 'mouse-face))
5728 (keyw-p (eq 'org-special-keyword (get-text-property mpos 'face))))
5729 (goto-char (point-at-bol))
5730 (setq table-p (org-looking-at-p org-table-dataline-regexp)
5731 comment-p (org-looking-at-p "[ \t]*#"))
5732 (goto-char pos)
5733 ;; FIXME: Should we go back one character here, for a_b^c
5734 ;; (goto-char (1- pos)) ;????????????????????
5735 (if (or comment-p emph-p link-p keyw-p)
5736 t
5737 (put-text-property (match-beginning 3) (match-end 0)
5738 'display
5739 (if (equal (char-after (match-beginning 2)) ?^)
5740 (nth (if table-p 3 1) org-script-display)
5741 (nth (if table-p 2 0) org-script-display)))
5742 (add-text-properties (match-beginning 2) (match-end 2)
5743 (list 'invisible t
5744 'org-dwidth t 'org-dwidth-n 1))
5745 (if (and (eq (char-after (match-beginning 3)) ?{)
5746 (eq (char-before (match-end 3)) ?}))
5747 (progn
5748 (add-text-properties
5749 (match-beginning 3) (1+ (match-beginning 3))
5750 (list 'invisible t 'org-dwidth t 'org-dwidth-n 1))
5751 (add-text-properties
5752 (1- (match-end 3)) (match-end 3)
5753 (list 'invisible t 'org-dwidth t 'org-dwidth-n 1))))
5754 t)))))
d3f4dbe8 5755
20908596 5756;;;; Visibility cycling, including org-goto and indirect buffer
7ac93e3c 5757
20908596 5758;;; Cycling
891f4676 5759
20908596
CD
5760(defvar org-cycle-global-status nil)
5761(make-variable-buffer-local 'org-cycle-global-status)
5762(defvar org-cycle-subtree-status nil)
5763(make-variable-buffer-local 'org-cycle-subtree-status)
891f4676 5764
48aaad2d 5765;;;###autoload
c8d0cf5c
CD
5766
5767(defvar org-inlinetask-min-level)
5768
20908596 5769(defun org-cycle (&optional arg)
c8d0cf5c
CD
5770 "TAB-action and visibility cycling for Org-mode.
5771
54a0dee5 5772This is the command invoked in Org-mode by the TAB key. Its main purpose
8bfe682a 5773is outline visibility cycling, but it also invokes other actions
c8d0cf5c 5774in special contexts.
891f4676 5775
20908596
CD
5776- When this function is called with a prefix argument, rotate the entire
5777 buffer through 3 states (global cycling)
5778 1. OVERVIEW: Show only top-level headlines.
5779 2. CONTENTS: Show all headlines of all levels, but no body text.
5780 3. SHOW ALL: Show everything.
c8d0cf5c 5781 When called with two `C-u C-u' prefixes, switch to the startup visibility,
b349f79f
CD
5782 determined by the variable `org-startup-folded', and by any VISIBILITY
5783 properties in the buffer.
c8d0cf5c
CD
5784 When called with three `C-u C-u C-u' prefixed, show the entire buffer,
5785 including any drawers.
5786
5787- When inside a table, re-align the table and move to the next field.
eb2f9c59 5788
20908596
CD
5789- When point is at the beginning of a headline, rotate the subtree started
5790 by this line through 3 different states (local cycling)
5791 1. FOLDED: Only the main headline is shown.
5792 2. CHILDREN: The main headline and the direct children are shown.
5793 From this state, you can move to one of the children
5794 and zoom in further.
5795 3. SUBTREE: Show the entire subtree, including body text.
c8d0cf5c 5796 If there is no subtree, switch directly from CHILDREN to FOLDED.
eb2f9c59 5797
ed21c5c8
CD
5798- When point is at the beginning of an empty headline and the variable
5799 `org-cycle-level-after-item/entry-creation' is set, cycle the level
5800 of the headline by demoting and promoting it to likely levels. This
86fbb8ca 5801 speeds up creation document structure by pressing TAB once or several
ed21c5c8
CD
5802 times right after creating a new headline.
5803
20908596
CD
5804- When there is a numeric prefix, go up to a heading with level ARG, do
5805 a `show-subtree' and return to the previous cursor position. If ARG
5806 is negative, go up that many levels.
eb2f9c59 5807
b349f79f
CD
5808- When point is not at the beginning of a headline, execute the global
5809 binding for TAB, which is re-indenting the line. See the option
20908596 5810 `org-cycle-emulate-tab' for details.
c8d16429 5811
20908596 5812- Special case: if point is at the beginning of the buffer and there is
afe98dfa
CD
5813 no headline in line 1, this function will act as if called with prefix arg
5814 (C-u TAB, same as S-TAB) also when called without prefix arg.
20908596 5815 But only if also the variable `org-cycle-global-at-bob' is t."
d3f4dbe8 5816 (interactive "P")
20908596 5817 (org-load-modules-maybe)
8bfe682a
CD
5818 (unless (or (run-hook-with-args-until-success 'org-tab-first-hook)
5819 (and org-cycle-level-after-item/entry-creation
5820 (or (org-cycle-level)
5821 (org-cycle-item-indentation))))
c8d0cf5c
CD
5822 (let* ((limit-level
5823 (or org-cycle-max-level
5824 (and (boundp 'org-inlinetask-min-level)
5825 org-inlinetask-min-level
5826 (1- org-inlinetask-min-level))))
5827 (nstars (and limit-level
5828 (if org-odd-levels-only
5829 (and limit-level (1- (* limit-level 2)))
5830 limit-level)))
5831 (outline-regexp
5832 (cond
5833 ((not (org-mode-p)) outline-regexp)
5834 ((or (eq org-cycle-include-plain-lists 'integrate)
5835 (and org-cycle-include-plain-lists (org-at-item-p)))
5836 (concat "\\(?:\\*"
5837 (if nstars (format "\\{1,%d\\}" nstars) "+")
5838 " \\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) \\)"))
5839 (t (concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ ")))))
afe98dfa 5840 (bob-special (and org-cycle-global-at-bob (not arg) (bobp)
c8d0cf5c
CD
5841 (not (looking-at outline-regexp))))
5842 (org-cycle-hook
5843 (if bob-special
5844 (delq 'org-optimize-window-after-visibility-change
5845 (copy-sequence org-cycle-hook))
5846 org-cycle-hook))
5847 (pos (point)))
5848
5849 (if (or bob-special (equal arg '(4)))
5850 ;; special case: use global cycling
5851 (setq arg t))
fbe6c10d 5852
c8d0cf5c 5853 (cond
621f83e4 5854
c8d0cf5c 5855 ((equal arg '(16))
afe98dfa 5856 (setq last-command 'dummy)
c8d0cf5c
CD
5857 (org-set-startup-visibility)
5858 (message "Startup visibility, plus VISIBILITY properties"))
b349f79f 5859
c8d0cf5c
CD
5860 ((equal arg '(64))
5861 (show-all)
5862 (message "Entire buffer visible, including drawers"))
6e2752e7 5863
c8d0cf5c
CD
5864 ((org-at-table-p 'any)
5865 ;; Enter the table or move to the next field in the table
ed21c5c8
CD
5866 (if (org-at-table.el-p)
5867 (message "Use C-c ' to edit table.el tables")
5868 (if arg (org-table-edit-field t)
5869 (org-table-justify-field-maybe)
5870 (call-interactively 'org-table-next-field))))
c8d0cf5c
CD
5871
5872 ((run-hook-with-args-until-success
5873 'org-tab-after-check-for-table-hook))
5874
5875 ((eq arg t) ;; Global cycling
5876 (org-cycle-internal-global))
5877
5878 ((and org-drawers org-drawer-regexp
5879 (save-excursion
5880 (beginning-of-line 1)
5881 (looking-at org-drawer-regexp)))
5882 ;; Toggle block visibility
5883 (org-flag-drawer
5884 (not (get-char-property (match-end 0) 'invisible))))
5885
5886 ((integerp arg)
5887 ;; Show-subtree, ARG levels up from here.
5888 (save-excursion
5889 (org-back-to-heading)
5890 (outline-up-heading (if (< arg 0) (- arg)
5891 (- (funcall outline-level) arg)))
5892 (org-show-subtree)))
64f72ae1 5893
c8d0cf5c
CD
5894 ((and (save-excursion (beginning-of-line 1) (looking-at outline-regexp))
5895 (or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
20908596 5896
c8d0cf5c 5897 (org-cycle-internal-local))
20908596 5898
c8d0cf5c
CD
5899 ;; TAB emulation and template completion
5900 (buffer-read-only (org-back-to-heading))
20908596 5901
c8d0cf5c
CD
5902 ((run-hook-with-args-until-success
5903 'org-tab-after-check-for-cycling-hook))
20908596 5904
c8d0cf5c 5905 ((org-try-structure-completion))
eb2f9c59 5906
c8d0cf5c 5907 ((org-try-cdlatex-tab))
3278a016 5908
8bfe682a
CD
5909 ((run-hook-with-args-until-success
5910 'org-tab-before-tab-emulation-hook))
5911
c8d0cf5c
CD
5912 ((and (eq org-cycle-emulate-tab 'exc-hl-bol)
5913 (or (not (bolp))
5914 (not (looking-at outline-regexp))))
5915 (call-interactively (global-key-binding "\t")))
b349f79f 5916
c8d0cf5c
CD
5917 ((if (and (memq org-cycle-emulate-tab '(white whitestart))
5918 (save-excursion (beginning-of-line 1) (looking-at "[ \t]*"))
5919 (or (and (eq org-cycle-emulate-tab 'white)
5920 (= (match-end 0) (point-at-eol)))
5921 (and (eq org-cycle-emulate-tab 'whitestart)
5922 (>= (match-end 0) pos))))
5923 t
5924 (eq org-cycle-emulate-tab t))
5925 (call-interactively (global-key-binding "\t")))
eb2f9c59 5926
c8d0cf5c
CD
5927 (t (save-excursion
5928 (org-back-to-heading)
5929 (org-cycle)))))))
634a7d0b 5930
c8d0cf5c
CD
5931(defun org-cycle-internal-global ()
5932 "Do the global cycling action."
5933 (cond
5934 ((and (eq last-command this-command)
5935 (eq org-cycle-global-status 'overview))
5936 ;; We just created the overview - now do table of contents
5937 ;; This can be slow in very large buffers, so indicate action
5938 (run-hook-with-args 'org-pre-cycle-hook 'contents)
5939 (message "CONTENTS...")
5940 (org-content)
5941 (message "CONTENTS...done")
5942 (setq org-cycle-global-status 'contents)
5943 (run-hook-with-args 'org-cycle-hook 'contents))
5944
5945 ((and (eq last-command this-command)
5946 (eq org-cycle-global-status 'contents))
5947 ;; We just showed the table of contents - now show everything
5948 (run-hook-with-args 'org-pre-cycle-hook 'all)
5949 (show-all)
5950 (message "SHOW ALL")
5951 (setq org-cycle-global-status 'all)
5952 (run-hook-with-args 'org-cycle-hook 'all))
20908596 5953
c8d0cf5c
CD
5954 (t
5955 ;; Default action: go to overview
5956 (run-hook-with-args 'org-pre-cycle-hook 'overview)
5957 (org-overview)
5958 (message "OVERVIEW")
5959 (setq org-cycle-global-status 'overview)
5960 (run-hook-with-args 'org-cycle-hook 'overview))))
5961
5962(defun org-cycle-internal-local ()
5963 "Do the local cycling action."
c8d0cf5c
CD
5964 (let ((goal-column 0) eoh eol eos level has-children children-skipped)
5965 ;; First, some boundaries
5966 (save-excursion
5967 (org-back-to-heading)
5968 (setq level (funcall outline-level))
5969 (save-excursion
5970 (beginning-of-line 2)
5971 (if (or (featurep 'xemacs) (<= emacs-major-version 21))
5972 ; XEmacs does not have `next-single-char-property-change'
5973 ; I'm not sure about Emacs 21.
5974 (while (and (not (eobp)) ;; this is like `next-line'
5975 (get-char-property (1- (point)) 'invisible))
5976 (beginning-of-line 2))
5977 (while (and (not (eobp)) ;; this is like `next-line'
5978 (get-char-property (1- (point)) 'invisible))
5979 (goto-char (next-single-char-property-change (point) 'invisible))
c8d0cf5c
CD
5980 (and (eolp) (beginning-of-line 2))))
5981 (setq eol (point)))
5982 (outline-end-of-heading) (setq eoh (point))
5983 (save-excursion
5984 (outline-next-heading)
5985 (setq has-children (and (org-at-heading-p t)
5986 (> (funcall outline-level) level))))
afe98dfa
CD
5987 ;; if we're in a list, org-end-of-subtree is in fact org-end-of-item.
5988 (if (org-at-item-p)
5989 (setq eos (if (and (org-end-of-item) (bolp))
5990 (1- (point))
5991 (point)))
5992 (org-end-of-subtree t)
5993 (unless (eobp)
5994 (skip-chars-forward " \t\n"))
5995 (setq eos (if (eobp) (point) (1- (point))))))
c8d0cf5c
CD
5996 ;; Find out what to do next and set `this-command'
5997 (cond
5998 ((= eos eoh)
5999 ;; Nothing is hidden behind this heading
6000 (run-hook-with-args 'org-pre-cycle-hook 'empty)
6001 (message "EMPTY ENTRY")
6002 (setq org-cycle-subtree-status nil)
6003 (save-excursion
6004 (goto-char eos)
6005 (outline-next-heading)
6006 (if (org-invisible-p) (org-flag-heading nil))))
6007 ((and (or (>= eol eos)
6008 (not (string-match "\\S-" (buffer-substring eol eos))))
6009 (or has-children
6010 (not (setq children-skipped
6011 org-cycle-skip-children-state-if-no-children))))
6012 ;; Entire subtree is hidden in one line: children view
6013 (run-hook-with-args 'org-pre-cycle-hook 'children)
6014 (org-show-entry)
6015 (show-children)
6016 (message "CHILDREN")
6017 (save-excursion
6018 (goto-char eos)
6019 (outline-next-heading)
6020 (if (org-invisible-p) (org-flag-heading nil)))
6021 (setq org-cycle-subtree-status 'children)
6022 (run-hook-with-args 'org-cycle-hook 'children))
6023 ((or children-skipped
6024 (and (eq last-command this-command)
6025 (eq org-cycle-subtree-status 'children)))
6026 ;; We just showed the children, or no children are there,
6027 ;; now show everything.
6028 (run-hook-with-args 'org-pre-cycle-hook 'subtree)
afe98dfa 6029 (outline-flag-region eoh eos nil)
c8d0cf5c
CD
6030 (message (if children-skipped "SUBTREE (NO CHILDREN)" "SUBTREE"))
6031 (setq org-cycle-subtree-status 'subtree)
6032 (run-hook-with-args 'org-cycle-hook 'subtree))
6033 (t
6034 ;; Default action: hide the subtree.
6035 (run-hook-with-args 'org-pre-cycle-hook 'folded)
afe98dfa 6036 (outline-flag-region eoh eos t)
c8d0cf5c
CD
6037 (message "FOLDED")
6038 (setq org-cycle-subtree-status 'folded)
6039 (run-hook-with-args 'org-cycle-hook 'folded)))))
20908596
CD
6040
6041;;;###autoload
6042(defun org-global-cycle (&optional arg)
b349f79f 6043 "Cycle the global visibility. For details see `org-cycle'.
86fbb8ca 6044With \\[universal-argument] prefix arg, switch to startup visibility.
b349f79f 6045With a numeric prefix, show all headlines up to that level."
20908596
CD
6046 (interactive "P")
6047 (let ((org-cycle-include-plain-lists
6048 (if (org-mode-p) org-cycle-include-plain-lists nil)))
b349f79f
CD
6049 (cond
6050 ((integerp arg)
6051 (show-all)
6052 (hide-sublevels arg)
6053 (setq org-cycle-global-status 'contents))
6054 ((equal arg '(4))
6055 (org-set-startup-visibility)
6056 (message "Startup visibility, plus VISIBILITY properties."))
6057 (t
6058 (org-cycle '(4))))))
6059
6060(defun org-set-startup-visibility ()
6061 "Set the visibility required by startup options and properties."
6062 (cond
6063 ((eq org-startup-folded t)
6064 (org-cycle '(4)))
6065 ((eq org-startup-folded 'content)
6066 (let ((this-command 'org-cycle) (last-command 'org-cycle))
6067 (org-cycle '(4)) (org-cycle '(4)))))
8d642074
CD
6068 (unless (eq org-startup-folded 'showeverything)
6069 (if org-hide-block-startup (org-hide-block-all))
6070 (org-set-visibility-according-to-property 'no-cleanup)
6071 (org-cycle-hide-archived-subtrees 'all)
6072 (org-cycle-hide-drawers 'all)
86fbb8ca 6073 (org-cycle-show-empty-lines t)))
b349f79f
CD
6074
6075(defun org-set-visibility-according-to-property (&optional no-cleanup)
6076 "Switch subtree visibilities according to :VISIBILITY: property."
6077 (interactive)
65c439fd 6078 (let (org-show-entry-below state)
b349f79f 6079 (save-excursion
acedf35c
CD
6080 (goto-char (point-min))
6081 (while (re-search-forward
b349f79f
CD
6082 "^[ \t]*:VISIBILITY:[ \t]+\\([a-z]+\\)"
6083 nil t)
6084 (setq state (match-string 1))
6085 (save-excursion
6086 (org-back-to-heading t)
6087 (hide-subtree)
6088 (org-reveal)
6089 (cond
6090 ((equal state '("fold" "folded"))
6091 (hide-subtree))
6092 ((equal state "children")
6093 (org-show-hidden-entry)
6094 (show-children))
6095 ((equal state "content")
6096 (save-excursion
6097 (save-restriction
6098 (org-narrow-to-subtree)
6099 (org-content))))
6100 ((member state '("all" "showall"))
6101 (show-subtree)))))
6102 (unless no-cleanup
6103 (org-cycle-hide-archived-subtrees 'all)
6104 (org-cycle-hide-drawers 'all)
6105 (org-cycle-show-empty-lines 'all)))))
3278a016 6106
20908596 6107(defun org-overview ()
33306645 6108 "Switch to overview mode, showing only top-level headlines.
20908596
CD
6109Really, this shows all headlines with level equal or greater than the level
6110of the first headline in the buffer. This is important, because if the
6111first headline is not level one, then (hide-sublevels 1) gives confusing
6112results."
d3f4dbe8 6113 (interactive)
20908596
CD
6114 (let ((level (save-excursion
6115 (goto-char (point-min))
6116 (if (re-search-forward (concat "^" outline-regexp) nil t)
6117 (progn
6118 (goto-char (match-beginning 0))
6119 (funcall outline-level))))))
6120 (and level (hide-sublevels level))))
891f4676 6121
20908596
CD
6122(defun org-content (&optional arg)
6123 "Show all headlines in the buffer, like a table of contents.
6124With numerical argument N, show content up to level N."
6125 (interactive "P")
6126 (save-excursion
6127 ;; Visit all headings and show their offspring
6128 (and (integerp arg) (org-overview))
6129 (goto-char (point-max))
6130 (catch 'exit
6131 (while (and (progn (condition-case nil
6132 (outline-previous-visible-heading 1)
6133 (error (goto-char (point-min))))
6134 t)
6135 (looking-at outline-regexp))
6136 (if (integerp arg)
6137 (show-children (1- arg))
6138 (show-branches))
6139 (if (bobp) (throw 'exit nil))))))
891f4676 6140
d943b3c6 6141
20908596
CD
6142(defun org-optimize-window-after-visibility-change (state)
6143 "Adjust the window after a change in outline visibility.
6144This function is the default value of the hook `org-cycle-hook'."
6145 (when (get-buffer-window (current-buffer))
6146 (cond
20908596
CD
6147 ((eq state 'content) nil)
6148 ((eq state 'all) nil)
6149 ((eq state 'folded) nil)
6150 ((eq state 'children) (or (org-subtree-end-visible-p) (recenter 1)))
6151 ((eq state 'subtree) (or (org-subtree-end-visible-p) (recenter 1))))))
891f4676 6152
c8d0cf5c
CD
6153(defun org-remove-empty-overlays-at (pos)
6154 "Remove outline overlays that do not contain non-white stuff."
6155 (mapc
6156 (lambda (o)
86fbb8ca
CD
6157 (and (eq 'outline (overlay-get o 'invisible))
6158 (not (string-match "\\S-" (buffer-substring (overlay-start o)
6159 (overlay-end o))))
6160 (delete-overlay o)))
6161 (overlays-at pos)))
c8d0cf5c
CD
6162
6163(defun org-clean-visibility-after-subtree-move ()
6164 "Fix visibility issues after moving a subtree."
6165 ;; First, find a reasonable region to look at:
6166 ;; Start two siblings above, end three below
6167 (let* ((beg (save-excursion
54a0dee5
CD
6168 (and (org-get-last-sibling)
6169 (org-get-last-sibling))
c8d0cf5c
CD
6170 (point)))
6171 (end (save-excursion
54a0dee5
CD
6172 (and (org-get-next-sibling)
6173 (org-get-next-sibling)
6174 (org-get-next-sibling))
c8d0cf5c
CD
6175 (if (org-at-heading-p)
6176 (point-at-eol)
6177 (point))))
6178 (level (looking-at "\\*+"))
6179 (re (if level (concat "^" (regexp-quote (match-string 0)) " "))))
6180 (save-excursion
6181 (save-restriction
6182 (narrow-to-region beg end)
6183 (when re
6184 ;; Properly fold already folded siblings
6185 (goto-char (point-min))
6186 (while (re-search-forward re nil t)
ed21c5c8
CD
6187 (if (and (not (org-invisible-p))
6188 (save-excursion
6189 (goto-char (point-at-eol)) (org-invisible-p)))
c8d0cf5c
CD
6190 (hide-entry))))
6191 (org-cycle-show-empty-lines 'overview)
6192 (org-cycle-hide-drawers 'overview)))))
6193
20908596
CD
6194(defun org-cycle-show-empty-lines (state)
6195 "Show empty lines above all visible headlines.
6196The region to be covered depends on STATE when called through
6197`org-cycle-hook'. Lisp program can use t for STATE to get the
6198entire buffer covered. Note that an empty line is only shown if there
33306645 6199are at least `org-cycle-separator-lines' empty lines before the headline."
54a0dee5 6200 (when (not (= org-cycle-separator-lines 0))
20908596 6201 (save-excursion
54a0dee5 6202 (let* ((n (abs org-cycle-separator-lines))
20908596
CD
6203 (re (cond
6204 ((= n 1) "\\(\n[ \t]*\n\\*+\\) ")
6205 ((= n 2) "^[ \t]*\\(\n[ \t]*\n\\*+\\) ")
6206 (t (let ((ns (number-to-string (- n 2))))
6207 (concat "^\\(?:[ \t]*\n\\)\\{" ns "," ns "\\}"
6208 "[ \t]*\\(\n[ \t]*\n\\*+\\) ")))))
54a0dee5 6209 beg end b e)
20908596
CD
6210 (cond
6211 ((memq state '(overview contents t))
6212 (setq beg (point-min) end (point-max)))
6213 ((memq state '(children folded))
6214 (setq beg (point) end (progn (org-end-of-subtree t t)
6215 (beginning-of-line 2)
6216 (point)))))
6217 (when beg
6218 (goto-char beg)
6219 (while (re-search-forward re end t)
54a0dee5
CD
6220 (unless (get-char-property (match-end 1) 'invisible)
6221 (setq e (match-end 1))
6222 (if (< org-cycle-separator-lines 0)
6223 (setq b (save-excursion
6224 (goto-char (match-beginning 0))
6225 (org-back-over-empty-lines)
8d642074
CD
6226 (if (save-excursion
6227 (goto-char (max (point-min) (1- (point))))
6228 (org-on-heading-p))
6229 (1- (point))
6230 (point))))
54a0dee5
CD
6231 (setq b (match-beginning 1)))
6232 (outline-flag-region b e nil)))))))
20908596
CD
6233 ;; Never hide empty lines at the end of the file.
6234 (save-excursion
6235 (goto-char (point-max))
6236 (outline-previous-heading)
6237 (outline-end-of-heading)
6238 (if (and (looking-at "[ \t\n]+")
6239 (= (match-end 0) (point-max)))
6240 (outline-flag-region (point) (match-end 0) nil))))
48aaad2d 6241
2c3ad40d
CD
6242(defun org-show-empty-lines-in-parent ()
6243 "Move to the parent and re-show empty lines before visible headlines."
6244 (save-excursion
6245 (let ((context (if (org-up-heading-safe) 'children 'overview)))
6246 (org-cycle-show-empty-lines context))))
6247
8bfe682a
CD
6248(defun org-files-list ()
6249 "Return `org-agenda-files' list, plus all open org-mode files.
6250This is useful for operations that need to scan all of a user's
6251open and agenda-wise Org files."
6252 (let ((files (mapcar 'expand-file-name (org-agenda-files))))
6253 (dolist (buf (buffer-list))
6254 (with-current-buffer buf
6255 (if (and (eq major-mode 'org-mode) (buffer-file-name))
6256 (let ((file (expand-file-name (buffer-file-name))))
6257 (unless (member file files)
6258 (push file files))))))
6259 files))
6260
6261(defsubst org-entry-beginning-position ()
6262 "Return the beginning position of the current entry."
6263 (save-excursion (outline-back-to-heading t) (point)))
6264
6265(defsubst org-entry-end-position ()
6266 "Return the end position of the current entry."
6267 (save-excursion (outline-next-heading) (point)))
6268
20908596
CD
6269(defun org-cycle-hide-drawers (state)
6270 "Re-hide all drawers after a visibility state change."
6271 (when (and (org-mode-p)
c8d0cf5c 6272 (not (memq state '(overview folded contents))))
20908596
CD
6273 (save-excursion
6274 (let* ((globalp (memq state '(contents all)))
6275 (beg (if globalp (point-min) (point)))
c8d0cf5c
CD
6276 (end (if globalp (point-max)
6277 (if (eq state 'children)
6278 (save-excursion (outline-next-heading) (point))
6279 (org-end-of-subtree t)))))
20908596
CD
6280 (goto-char beg)
6281 (while (re-search-forward org-drawer-regexp end t)
6282 (org-flag-drawer t))))))
2a57416f 6283
20908596
CD
6284(defun org-flag-drawer (flag)
6285 (save-excursion
6286 (beginning-of-line 1)
6287 (when (looking-at "^[ \t]*:[a-zA-Z][a-zA-Z0-9]*:")
6288 (let ((b (match-end 0))
6289 (outline-regexp org-outline-regexp))
6290 (if (re-search-forward
6291 "^[ \t]*:END:"
6292 (save-excursion (outline-next-heading) (point)) t)
6293 (outline-flag-region b (point-at-eol) flag)
54a0dee5 6294 (error ":END: line missing at position %s" b))))))
891f4676 6295
20908596
CD
6296(defun org-subtree-end-visible-p ()
6297 "Is the end of the current subtree visible?"
6298 (pos-visible-in-window-p
6299 (save-excursion (org-end-of-subtree t) (point))))
2a57416f 6300
20908596
CD
6301(defun org-first-headline-recenter (&optional N)
6302 "Move cursor to the first headline and recenter the headline.
ed21c5c8 6303Optional argument N means put the headline into the Nth line of the window."
20908596
CD
6304 (goto-char (point-min))
6305 (when (re-search-forward (concat "^\\(" outline-regexp "\\)") nil t)
6306 (beginning-of-line)
6307 (recenter (prefix-numeric-value N))))
2a57416f 6308
afe98dfa
CD
6309;;; Saving and restoring visibility
6310
6311(defun org-outline-overlay-data (&optional use-markers)
6312 "Return a list of the locations of all outline overlays.
6313These are overlays with the `invisible' property value `outline'.
6314The return value is a list of cons cells, with start and stop
6315positions for each overlay.
6316If USE-MARKERS is set, return the positions as markers."
6317 (let (beg end)
6318 (save-excursion
6319 (save-restriction
6320 (widen)
6321 (delq nil
6322 (mapcar (lambda (o)
6323 (when (eq (overlay-get o 'invisible) 'outline)
6324 (setq beg (overlay-start o)
6325 end (overlay-end o))
6326 (and beg end (> end beg)
6327 (if use-markers
6328 (cons (move-marker (make-marker) beg)
6329 (move-marker (make-marker) end))
6330 (cons beg end)))))
6331 (overlays-in (point-min) (point-max))))))))
6332
6333(defun org-set-outline-overlay-data (data)
6334 "Create visibility overlays for all positions in DATA.
6335DATA should have been made by `org-outline-overlay-data'."
6336 (let (o)
6337 (save-excursion
6338 (save-restriction
6339 (widen)
6340 (show-all)
6341 (mapc (lambda (c)
6342 (setq o (make-overlay (car c) (cdr c)))
6343 (overlay-put o 'invisible 'outline))
6344 data)))))
ed21c5c8 6345
c8d0cf5c
CD
6346;;; Folding of blocks
6347
6348(defconst org-block-regexp
6349
6350 "^[ \t]*#\\+begin_\\([^ \n]+\\)\\(\\([^\n]+\\)\\)?\n\\([^\000]+?\\)#\\+end_\\1[ \t]*$"
6351 "Regular expression for hiding blocks.")
6352
6353(defvar org-hide-block-overlays nil
8bfe682a 6354 "Overlays hiding blocks.")
c8d0cf5c
CD
6355(make-variable-buffer-local 'org-hide-block-overlays)
6356
6357(defun org-block-map (function &optional start end)
86fbb8ca
CD
6358 "Call FUNCTION at the head of all source blocks in the current buffer.
6359Optional arguments START and END can be used to limit the range."
c8d0cf5c
CD
6360 (let ((start (or start (point-min)))
6361 (end (or end (point-max))))
6362 (save-excursion
6363 (goto-char start)
6364 (while (and (< (point) end) (re-search-forward org-block-regexp end t))
6365 (save-excursion
6366 (save-match-data
6367 (goto-char (match-beginning 0))
6368 (funcall function)))))))
6369
6370(defun org-hide-block-toggle-all ()
6371 "Toggle the visibility of all blocks in the current buffer."
6372 (org-block-map #'org-hide-block-toggle))
6373
6374(defun org-hide-block-all ()
6375 "Fold all blocks in the current buffer."
6376 (interactive)
6377 (org-show-block-all)
6378 (org-block-map #'org-hide-block-toggle-maybe))
6379
6380(defun org-show-block-all ()
6381 "Unfold all blocks in the current buffer."
86fbb8ca
CD
6382 (interactive)
6383 (mapc 'delete-overlay org-hide-block-overlays)
c8d0cf5c
CD
6384 (setq org-hide-block-overlays nil))
6385
6386(defun org-hide-block-toggle-maybe ()
6387 "Toggle visibility of block at point."
6388 (interactive)
6389 (let ((case-fold-search t))
6390 (if (save-excursion
6391 (beginning-of-line 1)
6392 (looking-at org-block-regexp))
6393 (progn (org-hide-block-toggle)
6394 t) ;; to signal that we took action
6395 nil))) ;; to signal that we did not
6396
6397(defun org-hide-block-toggle (&optional force)
6398 "Toggle the visibility of the current block."
6399 (interactive)
6400 (save-excursion
6401 (beginning-of-line)
6402 (if (re-search-forward org-block-regexp nil t)
6403 (let ((start (- (match-beginning 4) 1)) ;; beginning of body
54a0dee5
CD
6404 (end (match-end 0)) ;; end of entire body
6405 ov)
c8d0cf5c 6406 (if (memq t (mapcar (lambda (overlay)
86fbb8ca 6407 (eq (overlay-get overlay 'invisible)
c8d0cf5c 6408 'org-hide-block))
86fbb8ca 6409 (overlays-at start)))
54a0dee5
CD
6410 (if (or (not force) (eq force 'off))
6411 (mapc (lambda (ov)
6412 (when (member ov org-hide-block-overlays)
6413 (setq org-hide-block-overlays
6414 (delq ov org-hide-block-overlays)))
86fbb8ca 6415 (when (eq (overlay-get ov 'invisible)
54a0dee5 6416 'org-hide-block)
86fbb8ca
CD
6417 (delete-overlay ov)))
6418 (overlays-at start)))
6419 (setq ov (make-overlay start end))
6420 (overlay-put ov 'invisible 'org-hide-block)
54a0dee5 6421 ;; make the block accessible to isearch
86fbb8ca 6422 (overlay-put
54a0dee5
CD
6423 ov 'isearch-open-invisible
6424 (lambda (ov)
6425 (when (member ov org-hide-block-overlays)
6426 (setq org-hide-block-overlays
6427 (delq ov org-hide-block-overlays)))
86fbb8ca 6428 (when (eq (overlay-get ov 'invisible)
54a0dee5 6429 'org-hide-block)
86fbb8ca 6430 (delete-overlay ov))))
54a0dee5 6431 (push ov org-hide-block-overlays)))
c8d0cf5c
CD
6432 (error "Not looking at a source block"))))
6433
6434;; org-tab-after-check-for-cycling-hook
6435(add-hook 'org-tab-first-hook 'org-hide-block-toggle-maybe)
6436;; Remove overlays when changing major mode
6437(add-hook 'org-mode-hook
6438 (lambda () (org-add-hook 'change-major-mode-hook
6439 'org-show-block-all 'append 'local)))
6440
20908596 6441;;; Org-goto
2a57416f 6442
20908596
CD
6443(defvar org-goto-window-configuration nil)
6444(defvar org-goto-marker nil)
6445(defvar org-goto-map
6446 (let ((map (make-sparse-keymap)))
6447 (let ((cmds '(isearch-forward isearch-backward kill-ring-save set-mark-command mouse-drag-region universal-argument org-occur)) cmd)
6448 (while (setq cmd (pop cmds))
6449 (substitute-key-definition cmd cmd map global-map)))
6450 (suppress-keymap map)
6451 (org-defkey map "\C-m" 'org-goto-ret)
6452 (org-defkey map [(return)] 'org-goto-ret)
6453 (org-defkey map [(left)] 'org-goto-left)
6454 (org-defkey map [(right)] 'org-goto-right)
6455 (org-defkey map [(control ?g)] 'org-goto-quit)
6456 (org-defkey map "\C-i" 'org-cycle)
6457 (org-defkey map [(tab)] 'org-cycle)
6458 (org-defkey map [(down)] 'outline-next-visible-heading)
6459 (org-defkey map [(up)] 'outline-previous-visible-heading)
6460 (if org-goto-auto-isearch
6461 (if (fboundp 'define-key-after)
6462 (define-key-after map [t] 'org-goto-local-auto-isearch)
6463 nil)
6464 (org-defkey map "q" 'org-goto-quit)
6465 (org-defkey map "n" 'outline-next-visible-heading)
6466 (org-defkey map "p" 'outline-previous-visible-heading)
6467 (org-defkey map "f" 'outline-forward-same-level)
6468 (org-defkey map "b" 'outline-backward-same-level)
6469 (org-defkey map "u" 'outline-up-heading))
6470 (org-defkey map "/" 'org-occur)
6471 (org-defkey map "\C-c\C-n" 'outline-next-visible-heading)
6472 (org-defkey map "\C-c\C-p" 'outline-previous-visible-heading)
6473 (org-defkey map "\C-c\C-f" 'outline-forward-same-level)
6474 (org-defkey map "\C-c\C-b" 'outline-backward-same-level)
6475 (org-defkey map "\C-c\C-u" 'outline-up-heading)
6476 map))
2a57416f 6477
20908596
CD
6478(defconst org-goto-help
6479"Browse buffer copy, to find location or copy text. Just type for auto-isearch.
6480RET=jump to location [Q]uit and return to previous location
6481\[Up]/[Down]=next/prev headline TAB=cycle visibility [/] org-occur")
2a57416f 6482
20908596 6483(defvar org-goto-start-pos) ; dynamically scoped parameter
2a57416f 6484
8bfe682a 6485;; FIXME: Docstring does not mention both interfaces
20908596
CD
6486(defun org-goto (&optional alternative-interface)
6487 "Look up a different location in the current file, keeping current visibility.
2a57416f 6488
20908596
CD
6489When you want look-up or go to a different location in a document, the
6490fastest way is often to fold the entire buffer and then dive into the tree.
6491This method has the disadvantage, that the previous location will be folded,
6492which may not be what you want.
2a57416f 6493
20908596
CD
6494This command works around this by showing a copy of the current buffer
6495in an indirect buffer, in overview mode. You can dive into the tree in
6496that copy, use org-occur and incremental search to find a location.
6497When pressing RET or `Q', the command returns to the original buffer in
6498which the visibility is still unchanged. After RET is will also jump to
9b053e76 6499the location selected in the indirect buffer and expose
20908596
CD
6500the headline hierarchy above."
6501 (interactive "P")
db55f368 6502 (let* ((org-refile-targets `((nil . (:maxlevel . ,org-goto-max-level))))
20908596 6503 (org-refile-use-outline-path t)
c8d0cf5c 6504 (org-refile-target-verify-function nil)
20908596
CD
6505 (interface
6506 (if (not alternative-interface)
6507 org-goto-interface
6508 (if (eq org-goto-interface 'outline)
6509 'outline-path-completion
6510 'outline)))
6511 (org-goto-start-pos (point))
6512 (selected-point
6513 (if (eq interface 'outline)
6514 (car (org-get-location (current-buffer) org-goto-help))
afe98dfa
CD
6515 (let ((pa (org-refile-get-location "Goto: ")))
6516 (org-refile-check-position pa)
6517 (nth 3 pa)))))
20908596
CD
6518 (if selected-point
6519 (progn
6520 (org-mark-ring-push org-goto-start-pos)
6521 (goto-char selected-point)
6522 (if (or (org-invisible-p) (org-invisible-p2))
6523 (org-show-context 'org-goto)))
6524 (message "Quit"))))
2a57416f 6525
20908596
CD
6526(defvar org-goto-selected-point nil) ; dynamically scoped parameter
6527(defvar org-goto-exit-command nil) ; dynamically scoped parameter
6528(defvar org-goto-local-auto-isearch-map) ; defined below
891f4676 6529
20908596
CD
6530(defun org-get-location (buf help)
6531 "Let the user select a location in the Org-mode buffer BUF.
6532This function uses a recursive edit. It returns the selected position
6533or nil."
6534 (let ((isearch-mode-map org-goto-local-auto-isearch-map)
6535 (isearch-hide-immediately nil)
6536 (isearch-search-fun-function
621f83e4 6537 (lambda () 'org-goto-local-search-headings))
ed21c5c8
CD
6538 (org-goto-selected-point org-goto-exit-command)
6539 (pop-up-frames nil)
6540 (special-display-buffer-names nil)
6541 (special-display-regexps nil)
6542 (special-display-function nil))
20908596
CD
6543 (save-excursion
6544 (save-window-excursion
6545 (delete-other-windows)
6546 (and (get-buffer "*org-goto*") (kill-buffer "*org-goto*"))
6547 (switch-to-buffer
6548 (condition-case nil
6549 (make-indirect-buffer (current-buffer) "*org-goto*")
6550 (error (make-indirect-buffer (current-buffer) "*org-goto*"))))
6551 (with-output-to-temp-buffer "*Help*"
6552 (princ help))
93b62de8 6553 (org-fit-window-to-buffer (get-buffer-window "*Help*"))
20908596
CD
6554 (setq buffer-read-only nil)
6555 (let ((org-startup-truncated t)
6556 (org-startup-folded nil)
6557 (org-startup-align-all-tables nil))
6558 (org-mode)
6559 (org-overview))
6560 (setq buffer-read-only t)
6561 (if (and (boundp 'org-goto-start-pos)
6562 (integer-or-marker-p org-goto-start-pos))
6563 (let ((org-show-hierarchy-above t)
6564 (org-show-siblings t)
6565 (org-show-following-heading t))
6566 (goto-char org-goto-start-pos)
6567 (and (org-invisible-p) (org-show-context)))
6568 (goto-char (point-min)))
7b96ff9a 6569 (let (org-special-ctrl-a/e) (org-beginning-of-line))
20908596
CD
6570 (message "Select location and press RET")
6571 (use-local-map org-goto-map)
6572 (recursive-edit)
6573 ))
6574 (kill-buffer "*org-goto*")
6575 (cons org-goto-selected-point org-goto-exit-command)))
891f4676 6576
20908596
CD
6577(defvar org-goto-local-auto-isearch-map (make-sparse-keymap))
6578(set-keymap-parent org-goto-local-auto-isearch-map isearch-mode-map)
6579(define-key org-goto-local-auto-isearch-map "\C-i" 'isearch-other-control-char)
6580(define-key org-goto-local-auto-isearch-map "\C-m" 'isearch-other-control-char)
891f4676 6581
621f83e4
CD
6582(defun org-goto-local-search-headings (string bound noerror)
6583 "Search and make sure that any matches are in headlines."
20908596 6584 (catch 'return
621f83e4
CD
6585 (while (if isearch-forward
6586 (search-forward string bound noerror)
6587 (search-backward string bound noerror))
20908596
CD
6588 (when (let ((context (mapcar 'car (save-match-data (org-context)))))
6589 (and (member :headline context)
6590 (not (member :tags context))))
6591 (throw 'return (point))))))
a96ee7df 6592
20908596
CD
6593(defun org-goto-local-auto-isearch ()
6594 "Start isearch."
6595 (interactive)
6596 (goto-char (point-min))
6597 (let ((keys (this-command-keys)))
6598 (when (eq (lookup-key isearch-mode-map keys) 'isearch-printing-char)
6599 (isearch-mode t)
6600 (isearch-process-search-char (string-to-char keys)))))
d924f2e5 6601
20908596
CD
6602(defun org-goto-ret (&optional arg)
6603 "Finish `org-goto' by going to the new location."
6604 (interactive "P")
6605 (setq org-goto-selected-point (point)
6606 org-goto-exit-command 'return)
6607 (throw 'exit nil))
891f4676 6608
20908596
CD
6609(defun org-goto-left ()
6610 "Finish `org-goto' by going to the new location."
6611 (interactive)
6612 (if (org-on-heading-p)
6613 (progn
6614 (beginning-of-line 1)
6615 (setq org-goto-selected-point (point)
6616 org-goto-exit-command 'left)
6617 (throw 'exit nil))
6618 (error "Not on a heading")))
891f4676 6619
20908596
CD
6620(defun org-goto-right ()
6621 "Finish `org-goto' by going to the new location."
6622 (interactive)
6623 (if (org-on-heading-p)
6624 (progn
6625 (setq org-goto-selected-point (point)
6626 org-goto-exit-command 'right)
6627 (throw 'exit nil))
6628 (error "Not on a heading")))
891f4676 6629
20908596
CD
6630(defun org-goto-quit ()
6631 "Finish `org-goto' without cursor motion."
6632 (interactive)
6633 (setq org-goto-selected-point nil)
6634 (setq org-goto-exit-command 'quit)
6635 (throw 'exit nil))
4b3a9ba7 6636
20908596 6637;;; Indirect buffer display of subtrees
4b3a9ba7 6638
20908596
CD
6639(defvar org-indirect-dedicated-frame nil
6640 "This is the frame being used for indirect tree display.")
6641(defvar org-last-indirect-buffer nil)
891f4676 6642
20908596
CD
6643(defun org-tree-to-indirect-buffer (&optional arg)
6644 "Create indirect buffer and narrow it to current subtree.
6645With numerical prefix ARG, go up to this level and then take that tree.
6646If ARG is negative, go up that many levels.
6647If `org-indirect-buffer-display' is not `new-frame', the command removes the
6648indirect buffer previously made with this command, to avoid proliferation of
86fbb8ca
CD
6649indirect buffers. However, when you call the command with a \
6650\\[universal-argument] prefix, or
20908596
CD
6651when `org-indirect-buffer-display' is `new-frame', the last buffer
6652is kept so that you can work with several indirect buffers at the same time.
86fbb8ca
CD
6653If `org-indirect-buffer-display' is `dedicated-frame', the \
6654\\[universal-argument] prefix also
20908596
CD
6655requests that a new frame be made for the new buffer, so that the dedicated
6656frame is not changed."
6657 (interactive "P")
6658 (let ((cbuf (current-buffer))
6659 (cwin (selected-window))
d3f4dbe8 6660 (pos (point))
20908596
CD
6661 beg end level heading ibuf)
6662 (save-excursion
6663 (org-back-to-heading t)
6664 (when (numberp arg)
6665 (setq level (org-outline-level))
6666 (if (< arg 0) (setq arg (+ level arg)))
6667 (while (> (setq level (org-outline-level)) arg)
6668 (outline-up-heading 1 t)))
6669 (setq beg (point)
6670 heading (org-get-heading))
ed21c5c8
CD
6671 (org-end-of-subtree t t)
6672 (if (org-on-heading-p) (backward-char 1))
6673 (setq end (point)))
20908596
CD
6674 (if (and (buffer-live-p org-last-indirect-buffer)
6675 (not (eq org-indirect-buffer-display 'new-frame))
6676 (not arg))
6677 (kill-buffer org-last-indirect-buffer))
6678 (setq ibuf (org-get-indirect-buffer cbuf)
6679 org-last-indirect-buffer ibuf)
d3f4dbe8 6680 (cond
20908596
CD
6681 ((or (eq org-indirect-buffer-display 'new-frame)
6682 (and arg (eq org-indirect-buffer-display 'dedicated-frame)))
6683 (select-frame (make-frame))
6684 (delete-other-windows)
6685 (switch-to-buffer ibuf)
6686 (org-set-frame-title heading))
6687 ((eq org-indirect-buffer-display 'dedicated-frame)
6688 (raise-frame
6689 (select-frame (or (and org-indirect-dedicated-frame
6690 (frame-live-p org-indirect-dedicated-frame)
6691 org-indirect-dedicated-frame)
6692 (setq org-indirect-dedicated-frame (make-frame)))))
6693 (delete-other-windows)
6694 (switch-to-buffer ibuf)
6695 (org-set-frame-title (concat "Indirect: " heading)))
6696 ((eq org-indirect-buffer-display 'current-window)
6697 (switch-to-buffer ibuf))
6698 ((eq org-indirect-buffer-display 'other-window)
6699 (pop-to-buffer ibuf))
f924a367 6700 (t (error "Invalid value")))
20908596
CD
6701 (if (featurep 'xemacs)
6702 (save-excursion (org-mode) (turn-on-font-lock)))
6703 (narrow-to-region beg end)
6704 (show-all)
6705 (goto-char pos)
6706 (and (window-live-p cwin) (select-window cwin))))
edd21304 6707
20908596
CD
6708(defun org-get-indirect-buffer (&optional buffer)
6709 (setq buffer (or buffer (current-buffer)))
6710 (let ((n 1) (base (buffer-name buffer)) bname)
6711 (while (buffer-live-p
6712 (get-buffer (setq bname (concat base "-" (number-to-string n)))))
6713 (setq n (1+ n)))
6714 (condition-case nil
6715 (make-indirect-buffer buffer bname 'clone)
6716 (error (make-indirect-buffer buffer bname)))))
ef943dba 6717
20908596
CD
6718(defun org-set-frame-title (title)
6719 "Set the title of the current frame to the string TITLE."
6720 ;; FIXME: how to name a single frame in XEmacs???
6721 (unless (featurep 'xemacs)
6722 (modify-frame-parameters (selected-frame) (list (cons 'name title)))))
ef943dba 6723
20908596 6724;;;; Structure editing
ef943dba 6725
20908596 6726;;; Inserting headlines
ef943dba 6727
0bd48b37
CD
6728(defun org-previous-line-empty-p ()
6729 (save-excursion
6730 (and (not (bobp))
6731 (or (beginning-of-line 0) t)
6732 (save-match-data
6733 (looking-at "[ \t]*$")))))
c8d0cf5c 6734
ed21c5c8 6735(defun org-insert-heading (&optional force-heading invisible-ok)
20908596
CD
6736 "Insert a new heading or item with same depth at point.
6737If point is in a plain list and FORCE-HEADING is nil, create a new list item.
6738If point is at the beginning of a headline, insert a sibling before the
afe98dfa
CD
6739current headline. If point is not at the beginning, split the line,
6740create the new headline with the text in the current line after point
6741\(but see also the variable `org-M-RET-may-split-line').
6742
ed21c5c8
CD
6743When INVISIBLE-OK is set, stop at invisible headlines when going back.
6744This is important for non-interactive uses of the command."
20908596 6745 (interactive "P")
ed21c5c8 6746 (if (or (= (buffer-size) 0)
afe98dfa
CD
6747 (and (not (save-excursion
6748 (and (ignore-errors (org-back-to-heading invisible-ok))
6749 (org-on-heading-p))))
ed21c5c8 6750 (not (org-in-item-p))))
afe98dfa
CD
6751 (progn
6752 (insert "\n* ")
6753 (run-hooks 'org-insert-heading-hook))
20908596 6754 (when (or force-heading (not (org-insert-item)))
0bd48b37 6755 (let* ((empty-line-p nil)
afe98dfa
CD
6756 (level nil)
6757 (on-heading (org-on-heading-p))
0bd48b37 6758 (head (save-excursion
20908596
CD
6759 (condition-case nil
6760 (progn
ed21c5c8 6761 (org-back-to-heading invisible-ok)
afe98dfa
CD
6762 (when (and (not on-heading)
6763 (featurep 'org-inlinetask)
6764 (integerp org-inlinetask-min-level)
6765 (>= (length (match-string 0))
6766 org-inlinetask-min-level))
6767 ;; Find a heading level before the inline task
6768 (while (and (setq level (org-up-heading-safe))
6769 (>= level org-inlinetask-min-level)))
6770 (if (org-on-heading-p)
6771 (org-back-to-heading invisible-ok)
6772 (error "This should not happen")))
0bd48b37 6773 (setq empty-line-p (org-previous-line-empty-p))
20908596
CD
6774 (match-string 0))
6775 (error "*"))))
0bd48b37
CD
6776 (blank-a (cdr (assq 'heading org-blank-before-new-entry)))
6777 (blank (if (eq blank-a 'auto) empty-line-p blank-a))
93b62de8 6778 pos hide-previous previous-pos)
20908596
CD
6779 (cond
6780 ((and (org-on-heading-p) (bolp)
6781 (or (bobp)
6782 (save-excursion (backward-char 1) (not (org-invisible-p)))))
6783 ;; insert before the current line
6784 (open-line (if blank 2 1)))
6785 ((and (bolp)
54a0dee5 6786 (not org-insert-heading-respect-content)
20908596
CD
6787 (or (bobp)
6788 (save-excursion
6789 (backward-char 1) (not (org-invisible-p)))))
6790 ;; insert right here
6791 nil)
6792 (t
93b62de8 6793 ;; somewhere in the line
71d35b24 6794 (save-excursion
93b62de8 6795 (setq previous-pos (point-at-bol))
71d35b24
CD
6796 (end-of-line)
6797 (setq hide-previous (org-invisible-p)))
93b62de8 6798 (and org-insert-heading-respect-content (org-show-subtree))
20908596 6799 (let ((split
93b62de8
CD
6800 (and (org-get-alist-option org-M-RET-may-split-line 'headline)
6801 (save-excursion
6802 (let ((p (point)))
6803 (goto-char (point-at-bol))
6804 (and (looking-at org-complex-heading-regexp)
6805 (> p (match-beginning 4)))))))
20908596 6806 tags pos)
621f83e4
CD
6807 (cond
6808 (org-insert-heading-respect-content
6809 (org-end-of-subtree nil t)
afe98dfa
CD
6810 (when (featurep 'org-inlinetask)
6811 (while (and (not (eobp))
6812 (looking-at "\\(\\*+\\)[ \t]+")
6813 (>= (length (match-string 1))
6814 org-inlinetask-min-level))
6815 (org-end-of-subtree nil t)))
93b62de8 6816 (or (bolp) (newline))
0bd48b37
CD
6817 (or (org-previous-line-empty-p)
6818 (and blank (newline)))
621f83e4
CD
6819 (open-line 1))
6820 ((org-on-heading-p)
93b62de8
CD
6821 (when hide-previous
6822 (show-children)
6823 (org-show-entry))
afe98dfa 6824 (looking-at ".*?\\([ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)?[ \t]*$")
621f83e4
CD
6825 (setq tags (and (match-end 2) (match-string 2)))
6826 (and (match-end 1)
6827 (delete-region (match-beginning 1) (match-end 1)))
6828 (setq pos (point-at-bol))
20908596 6829 (or split (end-of-line 1))
621f83e4 6830 (delete-horizontal-space)
ed21c5c8
CD
6831 (if (string-match "\\`\\*+\\'"
6832 (buffer-substring (point-at-bol) (point)))
6833 (insert " "))
621f83e4
CD
6834 (newline (if blank 2 1))
6835 (when tags
6836 (save-excursion
6837 (goto-char pos)
6838 (end-of-line 1)
6839 (insert " " tags)
6840 (org-set-tags nil 'align))))
6841 (t
6842 (or split (end-of-line 1))
6843 (newline (if blank 2 1)))))))
20908596
CD
6844 (insert head) (just-one-space)
6845 (setq pos (point))
6846 (end-of-line 1)
6847 (unless (= (point) pos) (just-one-space) (backward-delete-char 1))
71d35b24
CD
6848 (when (and org-insert-heading-respect-content hide-previous)
6849 (save-excursion
93b62de8
CD
6850 (goto-char previous-pos)
6851 (hide-subtree)))
20908596 6852 (run-hooks 'org-insert-heading-hook)))))
ef943dba 6853
20908596
CD
6854(defun org-get-heading (&optional no-tags)
6855 "Return the heading of the current entry, without the stars."
6856 (save-excursion
6857 (org-back-to-heading t)
6858 (if (looking-at
6859 (if no-tags
afe98dfa 6860 (org-re "\\*+[ \t]+\\([^\n\r]*?\\)\\([ \t]+:[[:alnum:]:_@#%]+:[ \t]*\\)?$")
20908596
CD
6861 "\\*+[ \t]+\\([^\r\n]*\\)"))
6862 (match-string 1) "")))
ef943dba 6863
0bd48b37
CD
6864(defun org-heading-components ()
6865 "Return the components of the current heading.
6866This is a list with the following elements:
6867- the level as an integer
6868- the reduced level, different if `org-odd-levels-only' is set.
6869- the TODO keyword, or nil
6870- the priority character, like ?A, or nil if no priority is given
6871- the headline text itself, or the tags string if no headline text
6872- the tags string, or nil."
6873 (save-excursion
6874 (org-back-to-heading t)
ed21c5c8 6875 (if (let (case-fold-search) (looking-at org-complex-heading-regexp))
0bd48b37
CD
6876 (list (length (match-string 1))
6877 (org-reduced-level (length (match-string 1)))
6878 (org-match-string-no-properties 2)
6879 (and (match-end 3) (aref (match-string 3) 2))
6880 (org-match-string-no-properties 4)
6881 (org-match-string-no-properties 5)))))
6882
c8d0cf5c
CD
6883(defun org-get-entry ()
6884 "Get the entry text, after heading, entire subtree."
6885 (save-excursion
6886 (org-back-to-heading t)
6887 (buffer-substring (point-at-bol 2) (org-end-of-subtree t))))
6888
20908596
CD
6889(defun org-insert-heading-after-current ()
6890 "Insert a new heading with same level as current, after current subtree."
6891 (interactive)
6892 (org-back-to-heading)
6893 (org-insert-heading)
6894 (org-move-subtree-down)
6895 (end-of-line 1))
35fb9989 6896
621f83e4
CD
6897(defun org-insert-heading-respect-content ()
6898 (interactive)
6899 (let ((org-insert-heading-respect-content t))
71d35b24 6900 (org-insert-heading t)))
621f83e4 6901
71d35b24
CD
6902(defun org-insert-todo-heading-respect-content (&optional force-state)
6903 (interactive "P")
621f83e4 6904 (let ((org-insert-heading-respect-content t))
71d35b24 6905 (org-insert-todo-heading force-state t)))
621f83e4 6906
71d35b24 6907(defun org-insert-todo-heading (arg &optional force-heading)
20908596
CD
6908 "Insert a new heading with the same level and TODO state as current heading.
6909If the heading has no TODO state, or if the state is DONE, use the first
6910state (TODO by default). Also with prefix arg, force first state."
6911 (interactive "P")
71d35b24
CD
6912 (when (or force-heading (not (org-insert-item 'checkbox)))
6913 (org-insert-heading force-heading)
20908596
CD
6914 (save-excursion
6915 (org-back-to-heading)
6916 (outline-previous-heading)
6917 (looking-at org-todo-line-regexp))
c8d0cf5c
CD
6918 (let*
6919 ((new-mark-x
6920 (if (or arg
6921 (not (match-beginning 2))
6922 (member (match-string 2) org-done-keywords))
6923 (car org-todo-keywords-1)
6924 (match-string 2)))
6925 (new-mark
6926 (or
6927 (run-hook-with-args-until-success
6928 'org-todo-get-default-hook new-mark-x nil)
6929 new-mark-x)))
6930 (beginning-of-line 1)
6931 (and (looking-at "\\*+ ") (goto-char (match-end 0))
6932 (if org-treat-insert-todo-heading-as-state-change
6933 (org-todo new-mark)
6934 (insert new-mark " "))))
b349f79f
CD
6935 (when org-provide-todo-statistics
6936 (org-update-parent-todo-statistics))))
ef943dba 6937
20908596
CD
6938(defun org-insert-subheading (arg)
6939 "Insert a new subheading and demote it.
6940Works for outline headings and for plain lists alike."
6941 (interactive "P")
6942 (org-insert-heading arg)
6943 (cond
6944 ((org-on-heading-p) (org-do-demote))
afe98dfa 6945 ((org-at-item-p) (org-indent-item))))
4da1a99d 6946
20908596
CD
6947(defun org-insert-todo-subheading (arg)
6948 "Insert a new subheading with TODO keyword or checkbox and demote it.
6949Works for outline headings and for plain lists alike."
6950 (interactive "P")
6951 (org-insert-todo-heading arg)
d3f4dbe8 6952 (cond
20908596 6953 ((org-on-heading-p) (org-do-demote))
afe98dfa 6954 ((org-at-item-p) (org-indent-item))))
4da1a99d 6955
20908596 6956;;; Promotion and Demotion
4da1a99d 6957
c8d0cf5c
CD
6958(defvar org-after-demote-entry-hook nil
6959 "Hook run after an entry has been demoted.
6960The cursor will be at the beginning of the entry.
6961When a subtree is being demoted, the hook will be called for each node.")
6962
6963(defvar org-after-promote-entry-hook nil
6964 "Hook run after an entry has been promoted.
6965The cursor will be at the beginning of the entry.
6966When a subtree is being promoted, the hook will be called for each node.")
6967
20908596
CD
6968(defun org-promote-subtree ()
6969 "Promote the entire subtree.
6970See also `org-promote'."
6971 (interactive)
d3f4dbe8 6972 (save-excursion
20908596
CD
6973 (org-map-tree 'org-promote))
6974 (org-fix-position-after-promote))
6975
6976(defun org-demote-subtree ()
6977 "Demote the entire subtree. See `org-demote'.
6978See also `org-promote'."
6979 (interactive)
d3f4dbe8 6980 (save-excursion
20908596
CD
6981 (org-map-tree 'org-demote))
6982 (org-fix-position-after-promote))
4b3a9ba7 6983
20908596
CD
6984
6985(defun org-do-promote ()
6986 "Promote the current heading higher up the tree.
6987If the region is active in `transient-mark-mode', promote all headings
6988in the region."
6989 (interactive)
3278a016 6990 (save-excursion
20908596
CD
6991 (if (org-region-active-p)
6992 (org-map-region 'org-promote (region-beginning) (region-end))
6993 (org-promote)))
6994 (org-fix-position-after-promote))
6995
6996(defun org-do-demote ()
6997 "Demote the current heading lower down the tree.
6998If the region is active in `transient-mark-mode', demote all headings
6999in the region."
7000 (interactive)
4da1a99d 7001 (save-excursion
20908596
CD
7002 (if (org-region-active-p)
7003 (org-map-region 'org-demote (region-beginning) (region-end))
7004 (org-demote)))
7005 (org-fix-position-after-promote))
4b3a9ba7 7006
20908596
CD
7007(defun org-fix-position-after-promote ()
7008 "Make sure that after pro/demotion cursor position is right."
7009 (let ((pos (point)))
7010 (when (save-excursion
7011 (beginning-of-line 1)
7012 (looking-at org-todo-line-regexp)
7013 (or (equal pos (match-end 1)) (equal pos (match-end 2))))
7014 (cond ((eobp) (insert " "))
7015 ((eolp) (insert " "))
7016 ((equal (char-after) ?\ ) (forward-char 1))))))
4b3a9ba7 7017
8bfe682a
CD
7018(defun org-current-level ()
7019 "Return the level of the current entry, or nil if before the first headline.
7020The level is the number of stars at the beginning of the headline."
7021 (save-excursion
acedf35c
CD
7022 (let ((outline-regexp (org-get-limited-outline-regexp)))
7023 (condition-case nil
7024 (progn
7025 (org-back-to-heading t)
7026 (funcall outline-level))
7027 (error nil)))))
8bfe682a 7028
ed21c5c8
CD
7029(defun org-get-previous-line-level ()
7030 "Return the outline depth of the last headline before the current line.
7031Returns 0 for the first headline in the buffer, and nil if before the
7032first headline."
7033 (let ((current-level (org-current-level))
7034 (prev-level (when (> (line-number-at-pos) 1)
7035 (save-excursion
7036 (beginning-of-line 0)
7037 (org-current-level)))))
7038 (cond ((null current-level) nil) ; Before first headline
7039 ((null prev-level) 0) ; At first headline
7040 (prev-level))))
7041
20908596 7042(defun org-reduced-level (l)
0bd48b37
CD
7043 "Compute the effective level of a heading.
7044This takes into account the setting of `org-odd-levels-only'."
20908596 7045 (if org-odd-levels-only (1+ (floor (/ l 2))) l))
4b3a9ba7 7046
ed21c5c8
CD
7047(defun org-level-increment ()
7048 "Return the number of stars that will be added or removed at a
7049time to headlines when structure editing, based on the value of
7050`org-odd-levels-only'."
7051 (if org-odd-levels-only 2 1))
7052
20908596
CD
7053(defun org-get-valid-level (level &optional change)
7054 "Rectify a level change under the influence of `org-odd-levels-only'
7055LEVEL is a current level, CHANGE is by how much the level should be
7056modified. Even if CHANGE is nil, LEVEL may be returned modified because
7057even level numbers will become the next higher odd number."
7058 (if org-odd-levels-only
7059 (cond ((or (not change) (= 0 change)) (1+ (* 2 (/ level 2))))
7060 ((> change 0) (1+ (* 2 (/ (+ level (* 2 change)) 2))))
7061 ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2))))))
c8d0cf5c 7062 (max 1 (+ level (or change 0)))))
4b3a9ba7 7063
20908596
CD
7064(if (boundp 'define-obsolete-function-alias)
7065 (if (or (featurep 'xemacs) (< emacs-major-version 23))
7066 (define-obsolete-function-alias 'org-get-legal-level
7067 'org-get-valid-level)
7068 (define-obsolete-function-alias 'org-get-legal-level
7069 'org-get-valid-level "23.1")))
4b3a9ba7 7070
20908596
CD
7071(defun org-promote ()
7072 "Promote the current heading higher up the tree.
7073If the region is active in `transient-mark-mode', promote all headings
7074in the region."
7075 (org-back-to-heading t)
7076 (let* ((level (save-match-data (funcall outline-level)))
7077 (up-head (concat (make-string (org-get-valid-level level -1) ?*) " "))
7078 (diff (abs (- level (length up-head) -1))))
7079 (if (= level 1) (error "Cannot promote to level 0. UNDO to recover if necessary"))
7080 (replace-match up-head nil t)
7081 ;; Fixup tag positioning
7082 (and org-auto-align-tags (org-set-tags nil t))
c8d0cf5c
CD
7083 (if org-adapt-indentation (org-fixup-indentation (- diff)))
7084 (run-hooks 'org-after-promote-entry-hook)))
891f4676 7085
20908596
CD
7086(defun org-demote ()
7087 "Demote the current heading lower down the tree.
7088If the region is active in `transient-mark-mode', demote all headings
7089in the region."
7090 (org-back-to-heading t)
7091 (let* ((level (save-match-data (funcall outline-level)))
7092 (down-head (concat (make-string (org-get-valid-level level 1) ?*) " "))
7093 (diff (abs (- level (length down-head) -1))))
7094 (replace-match down-head nil t)
7095 ;; Fixup tag positioning
7096 (and org-auto-align-tags (org-set-tags nil t))
c8d0cf5c
CD
7097 (if org-adapt-indentation (org-fixup-indentation diff))
7098 (run-hooks 'org-after-demote-entry-hook)))
20908596 7099
8bfe682a 7100(defun org-cycle-level ()
ed21c5c8
CD
7101 "Cycle the level of an empty headline through possible states.
7102This goes first to child, then to parent, level, then up the hierarchy.
7103After top level, it switches back to sibling level."
7104 (interactive)
8bfe682a 7105 (let ((org-adapt-indentation nil))
ed21c5c8
CD
7106 (when (org-point-at-end-of-empty-headline)
7107 (setq this-command 'org-cycle-level) ; Only needed for caching
7108 (let ((cur-level (org-current-level))
7109 (prev-level (org-get-previous-line-level)))
7110 (cond
7111 ;; If first headline in file, promote to top-level.
7112 ((= prev-level 0)
7113 (loop repeat (/ (- cur-level 1) (org-level-increment))
7114 do (org-do-promote)))
7115 ;; If same level as prev, demote one.
7116 ((= prev-level cur-level)
7117 (org-do-demote))
7118 ;; If parent is top-level, promote to top level if not already.
7119 ((= prev-level 1)
7120 (loop repeat (/ (- cur-level 1) (org-level-increment))
7121 do (org-do-promote)))
7122 ;; If top-level, return to prev-level.
7123 ((= cur-level 1)
7124 (loop repeat (/ (- prev-level 1) (org-level-increment))
7125 do (org-do-demote)))
7126 ;; If less than prev-level, promote one.
7127 ((< cur-level prev-level)
7128 (org-do-promote))
7129 ;; If deeper than prev-level, promote until higher than
7130 ;; prev-level.
7131 ((> cur-level prev-level)
7132 (loop repeat (+ 1 (/ (- cur-level prev-level) (org-level-increment)))
7133 do (org-do-promote))))
7134 t))))
8bfe682a 7135
20908596
CD
7136(defun org-map-tree (fun)
7137 "Call FUN for every heading underneath the current one."
7138 (org-back-to-heading)
7139 (let ((level (funcall outline-level)))
7140 (save-excursion
7141 (funcall fun)
7142 (while (and (progn
7143 (outline-next-heading)
7144 (> (funcall outline-level) level))
7145 (not (eobp)))
7146 (funcall fun)))))
7147
7148(defun org-map-region (fun beg end)
7149 "Call FUN for every heading between BEG and END."
7150 (let ((org-ignore-region t))
7151 (save-excursion
7152 (setq end (copy-marker end))
7153 (goto-char beg)
7154 (if (and (re-search-forward (concat "^" outline-regexp) nil t)
7155 (< (point) end))
7156 (funcall fun))
7157 (while (and (progn
7158 (outline-next-heading)
7159 (< (point) end))
7160 (not (eobp)))
7161 (funcall fun)))))
7162
7163(defun org-fixup-indentation (diff)
86fbb8ca 7164 "Change the indentation in the current entry by DIFF.
20908596
CD
7165However, if any line in the current entry has no indentation, or if it
7166would end up with no indentation after the change, nothing at all is done."
7167 (save-excursion
7168 (let ((end (save-excursion (outline-next-heading)
7169 (point-marker)))
7170 (prohibit (if (> diff 0)
7171 "^\\S-"
7172 (concat "^ \\{0," (int-to-string (- diff)) "\\}\\S-")))
7173 col)
7174 (unless (save-excursion (end-of-line 1)
7175 (re-search-forward prohibit end t))
7176 (while (and (< (point) end)
7177 (re-search-forward "^[ \t]+" end t))
7178 (goto-char (match-end 0))
7179 (setq col (current-column))
7180 (if (< diff 0) (replace-match ""))
ce4fdcb9 7181 (org-indent-to-column (+ diff col))))
20908596
CD
7182 (move-marker end nil))))
7183
7184(defun org-convert-to-odd-levels ()
7185 "Convert an org-mode file with all levels allowed to one with odd levels.
7186This will leave level 1 alone, convert level 2 to level 3, level 3 to
7187level 5 etc."
7188 (interactive)
7189 (when (yes-or-no-p "Are you sure you want to globally change levels to odd? ")
8d642074
CD
7190 (let ((outline-regexp org-outline-regexp)
7191 (outline-level 'org-outline-level)
7192 (org-odd-levels-only nil) n)
20908596
CD
7193 (save-excursion
7194 (goto-char (point-min))
7195 (while (re-search-forward "^\\*\\*+ " nil t)
7196 (setq n (- (length (match-string 0)) 2))
7197 (while (>= (setq n (1- n)) 0)
7198 (org-demote))
7199 (end-of-line 1))))))
4b3a9ba7 7200
20908596 7201(defun org-convert-to-oddeven-levels ()
86fbb8ca
CD
7202 "Convert an org-mode file with only odd levels to one with odd/even levels.
7203This promotes level 3 to level 2, level 5 to level 3 etc. If the
7204file contains a section with an even level, conversion would
7205destroy the structure of the file. An error is signaled in this
7206case."
20908596
CD
7207 (interactive)
7208 (goto-char (point-min))
7209 ;; First check if there are no even levels
7210 (when (re-search-forward "^\\(\\*\\*\\)+ " nil t)
7211 (org-show-context t)
f924a367 7212 (error "Not all levels are odd in this file. Conversion not possible"))
20908596 7213 (when (yes-or-no-p "Are you sure you want to globally change levels to odd-even? ")
8d642074
CD
7214 (let ((outline-regexp org-outline-regexp)
7215 (outline-level 'org-outline-level)
7216 (org-odd-levels-only nil) n)
20908596
CD
7217 (save-excursion
7218 (goto-char (point-min))
7219 (while (re-search-forward "^\\*\\*+ " nil t)
7220 (setq n (/ (1- (length (match-string 0))) 2))
7221 (while (>= (setq n (1- n)) 0)
7222 (org-promote))
7223 (end-of-line 1))))))
a96ee7df 7224
20908596
CD
7225(defun org-tr-level (n)
7226 "Make N odd if required."
7227 (if org-odd-levels-only (1+ (/ n 2)) n))
8c6fb58b 7228
20908596 7229;;; Vertical tree motion, cutting and pasting of subtrees
8c6fb58b 7230
20908596
CD
7231(defun org-move-subtree-up (&optional arg)
7232 "Move the current subtree up past ARG headlines of the same level."
7233 (interactive "p")
7234 (org-move-subtree-down (- (prefix-numeric-value arg))))
b0a10108 7235
20908596
CD
7236(defun org-move-subtree-down (&optional arg)
7237 "Move the current subtree down past ARG headlines of the same level."
7238 (interactive "p")
7239 (setq arg (prefix-numeric-value arg))
54a0dee5
CD
7240 (let ((movfunc (if (> arg 0) 'org-get-next-sibling
7241 'org-get-last-sibling))
20908596
CD
7242 (ins-point (make-marker))
7243 (cnt (abs arg))
7244 beg beg0 end txt folded ne-beg ne-end ne-ins ins-end)
7245 ;; Select the tree
7246 (org-back-to-heading)
7247 (setq beg0 (point))
7248 (save-excursion
7249 (setq ne-beg (org-back-over-empty-lines))
7250 (setq beg (point)))
7251 (save-match-data
7252 (save-excursion (outline-end-of-heading)
7253 (setq folded (org-invisible-p)))
7254 (outline-end-of-subtree))
7255 (outline-next-heading)
7256 (setq ne-end (org-back-over-empty-lines))
7257 (setq end (point))
7258 (goto-char beg0)
7259 (when (and (> arg 0) (org-first-sibling-p) (< ne-end ne-beg))
7260 ;; include less whitespace
7261 (save-excursion
7262 (goto-char beg)
7263 (forward-line (- ne-beg ne-end))
7264 (setq beg (point))))
7265 ;; Find insertion point, with error handling
7266 (while (> cnt 0)
7267 (or (and (funcall movfunc) (looking-at outline-regexp))
7268 (progn (goto-char beg0)
7269 (error "Cannot move past superior level or buffer limit")))
7270 (setq cnt (1- cnt)))
7271 (if (> arg 0)
7272 ;; Moving forward - still need to move over subtree
7273 (progn (org-end-of-subtree t t)
7274 (save-excursion
7275 (org-back-over-empty-lines)
7276 (or (bolp) (newline)))))
7277 (setq ne-ins (org-back-over-empty-lines))
7278 (move-marker ins-point (point))
7279 (setq txt (buffer-substring beg end))
b349f79f 7280 (org-save-markers-in-region beg end)
20908596 7281 (delete-region beg end)
c8d0cf5c 7282 (org-remove-empty-overlays-at beg)
ff4be292
CD
7283 (or (= beg (point-min)) (outline-flag-region (1- beg) beg nil))
7284 (or (bobp) (outline-flag-region (1- (point)) (point) nil))
c8d0cf5c 7285 (and (not (bolp)) (looking-at "\n") (forward-char 1))
b349f79f
CD
7286 (let ((bbb (point)))
7287 (insert-before-markers txt)
7288 (org-reinstall-markers-in-region bbb)
7289 (move-marker ins-point bbb))
20908596
CD
7290 (or (bolp) (insert "\n"))
7291 (setq ins-end (point))
7292 (goto-char ins-point)
7293 (org-skip-whitespace)
7294 (when (and (< arg 0)
7295 (org-first-sibling-p)
7296 (> ne-ins ne-beg))
7297 ;; Move whitespace back to beginning
7298 (save-excursion
7299 (goto-char ins-end)
7300 (let ((kill-whole-line t))
7301 (kill-line (- ne-ins ne-beg)) (point)))
7302 (insert (make-string (- ne-ins ne-beg) ?\n)))
7303 (move-marker ins-point nil)
c8d0cf5c
CD
7304 (if folded
7305 (hide-subtree)
20908596
CD
7306 (org-show-entry)
7307 (show-children)
c8d0cf5c
CD
7308 (org-cycle-hide-drawers 'children))
7309 (org-clean-visibility-after-subtree-move)))
8c6fb58b 7310
20908596
CD
7311(defvar org-subtree-clip ""
7312 "Clipboard for cut and paste of subtrees.
7313This is actually only a copy of the kill, because we use the normal kill
7314ring. We need it to check if the kill was created by `org-copy-subtree'.")
8c6fb58b 7315
20908596
CD
7316(defvar org-subtree-clip-folded nil
7317 "Was the last copied subtree folded?
7318This is used to fold the tree back after pasting.")
b0a10108 7319
20908596
CD
7320(defun org-cut-subtree (&optional n)
7321 "Cut the current subtree into the clipboard.
7322With prefix arg N, cut this many sequential subtrees.
7323This is a short-hand for marking the subtree and then cutting it."
7324 (interactive "p")
7325 (org-copy-subtree n 'cut))
8c6fb58b 7326
b349f79f 7327(defun org-copy-subtree (&optional n cut force-store-markers)
20908596
CD
7328 "Cut the current subtree into the clipboard.
7329With prefix arg N, cut this many sequential subtrees.
7330This is a short-hand for marking the subtree and then copying it.
b349f79f
CD
7331If CUT is non-nil, actually cut the subtree.
7332If FORCE-STORE-MARKERS is non-nil, store the relative locations
7333of some markers in the region, even if CUT is non-nil. This is
7334useful if the caller implements cut-and-paste as copy-then-paste-then-cut."
20908596
CD
7335 (interactive "p")
7336 (let (beg end folded (beg0 (point)))
7337 (if (interactive-p)
7338 (org-back-to-heading nil) ; take what looks like a subtree
7339 (org-back-to-heading t)) ; take what is really there
7340 (org-back-over-empty-lines)
7341 (setq beg (point))
7342 (skip-chars-forward " \t\r\n")
7343 (save-match-data
7344 (save-excursion (outline-end-of-heading)
7345 (setq folded (org-invisible-p)))
7346 (condition-case nil
c8d0cf5c 7347 (org-forward-same-level (1- n) t)
20908596
CD
7348 (error nil))
7349 (org-end-of-subtree t t))
7350 (org-back-over-empty-lines)
7351 (setq end (point))
7352 (goto-char beg0)
7353 (when (> end beg)
7354 (setq org-subtree-clip-folded folded)
b349f79f
CD
7355 (when (or cut force-store-markers)
7356 (org-save-markers-in-region beg end))
20908596
CD
7357 (if cut (kill-region beg end) (copy-region-as-kill beg end))
7358 (setq org-subtree-clip (current-kill 0))
7359 (message "%s: Subtree(s) with %d characters"
7360 (if cut "Cut" "Copied")
7361 (length org-subtree-clip)))))
b0a10108 7362
93b62de8 7363(defun org-paste-subtree (&optional level tree for-yank)
20908596
CD
7364 "Paste the clipboard as a subtree, with modification of headline level.
7365The entire subtree is promoted or demoted in order to match a new headline
ce4fdcb9 7366level.
93b62de8
CD
7367
7368If the cursor is at the beginning of a headline, the same level as
7369that headline is used to paste the tree
7370
7371If not, the new level is derived from the *visible* headings
20908596
CD
7372before and after the insertion point, and taken to be the inferior headline
7373level of the two. So if the previous visible heading is level 3 and the
7374next is level 4 (or vice versa), level 4 will be used for insertion.
7375This makes sure that the subtree remains an independent subtree and does
7376not swallow low level entries.
03f3cf35 7377
20908596
CD
7378You can also force a different level, either by using a numeric prefix
7379argument, or by inserting the heading marker by hand. For example, if the
7380cursor is after \"*****\", then the tree will be shifted to level 5.
b0a10108 7381
93b62de8 7382If optional TREE is given, use this text instead of the kill ring.
b0a10108 7383
93b62de8
CD
7384When FOR-YANK is set, this is called by `org-yank'. In this case, do not
7385move back over whitespace before inserting, and move point to the end of
7386the inserted text when done."
20908596 7387 (interactive "P")
c8d0cf5c 7388 (setq tree (or tree (and kill-ring (current-kill 0))))
20908596
CD
7389 (unless (org-kill-is-subtree-p tree)
7390 (error "%s"
7391 (substitute-command-keys
7392 "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway")))
2c3ad40d 7393 (let* ((visp (not (org-invisible-p)))
c8d0cf5c 7394 (txt tree)
20908596
CD
7395 (^re (concat "^\\(" outline-regexp "\\)"))
7396 (re (concat "\\(" outline-regexp "\\)"))
7397 (^re_ (concat "\\(\\*+\\)[ \t]*"))
b0a10108 7398
20908596
CD
7399 (old-level (if (string-match ^re txt)
7400 (- (match-end 0) (match-beginning 0) 1)
7401 -1))
7402 (force-level (cond (level (prefix-numeric-value level))
93b62de8
CD
7403 ((and (looking-at "[ \t]*$")
7404 (string-match
7405 ^re_ (buffer-substring
7406 (point-at-bol) (point))))
20908596 7407 (- (match-end 1) (match-beginning 1)))
93b62de8
CD
7408 ((and (bolp)
7409 (looking-at org-outline-regexp))
7410 (- (match-end 0) (point) 1))
20908596
CD
7411 (t nil)))
7412 (previous-level (save-excursion
7413 (condition-case nil
7414 (progn
7415 (outline-previous-visible-heading 1)
7416 (if (looking-at re)
7417 (- (match-end 0) (match-beginning 0) 1)
7418 1))
7419 (error 1))))
7420 (next-level (save-excursion
7421 (condition-case nil
7422 (progn
7423 (or (looking-at outline-regexp)
7424 (outline-next-visible-heading 1))
7425 (if (looking-at re)
7426 (- (match-end 0) (match-beginning 0) 1)
7427 1))
7428 (error 1))))
7429 (new-level (or force-level (max previous-level next-level)))
7430 (shift (if (or (= old-level -1)
7431 (= new-level -1)
7432 (= old-level new-level))
7433 0
7434 (- new-level old-level)))
7435 (delta (if (> shift 0) -1 1))
7436 (func (if (> shift 0) 'org-demote 'org-promote))
7437 (org-odd-levels-only nil)
93b62de8 7438 beg end newend)
20908596
CD
7439 ;; Remove the forced level indicator
7440 (if force-level
7441 (delete-region (point-at-bol) (point)))
7442 ;; Paste
7443 (beginning-of-line 1)
93b62de8 7444 (unless for-yank (org-back-over-empty-lines))
20908596 7445 (setq beg (point))
db55f368 7446 (and (fboundp 'org-id-paste-tracker) (org-id-paste-tracker txt))
20908596
CD
7447 (insert-before-markers txt)
7448 (unless (string-match "\n\\'" txt) (insert "\n"))
93b62de8 7449 (setq newend (point))
b349f79f 7450 (org-reinstall-markers-in-region beg)
20908596
CD
7451 (setq end (point))
7452 (goto-char beg)
7453 (skip-chars-forward " \t\n\r")
7454 (setq beg (point))
2c3ad40d
CD
7455 (if (and (org-invisible-p) visp)
7456 (save-excursion (outline-show-heading)))
20908596
CD
7457 ;; Shift if necessary
7458 (unless (= shift 0)
7459 (save-restriction
7460 (narrow-to-region beg end)
7461 (while (not (= shift 0))
7462 (org-map-region func (point-min) (point-max))
7463 (setq shift (+ delta shift)))
93b62de8
CD
7464 (goto-char (point-min))
7465 (setq newend (point-max))))
7466 (when (or (interactive-p) for-yank)
20908596 7467 (message "Clipboard pasted as level %d subtree" new-level))
93b62de8
CD
7468 (if (and (not for-yank) ; in this case, org-yank will decide about folding
7469 kill-ring
20908596
CD
7470 (eq org-subtree-clip (current-kill 0))
7471 org-subtree-clip-folded)
7472 ;; The tree was folded before it was killed/copied
93b62de8
CD
7473 (hide-subtree))
7474 (and for-yank (goto-char newend))))
4b3a9ba7 7475
20908596
CD
7476(defun org-kill-is-subtree-p (&optional txt)
7477 "Check if the current kill is an outline subtree, or a set of trees.
7478Returns nil if kill does not start with a headline, or if the first
7479headline level is not the largest headline level in the tree.
7480So this will actually accept several entries of equal levels as well,
7481which is OK for `org-paste-subtree'.
7482If optional TXT is given, check this string instead of the current kill."
7483 (let* ((kill (or txt (and kill-ring (current-kill 0)) ""))
7484 (start-level (and kill
7485 (string-match (concat "\\`\\([ \t\n\r]*?\n\\)?\\("
7486 org-outline-regexp "\\)")
7487 kill)
7488 (- (match-end 2) (match-beginning 2) 1)))
7489 (re (concat "^" org-outline-regexp))
621f83e4 7490 (start (1+ (or (match-beginning 2) -1))))
20908596
CD
7491 (if (not start-level)
7492 (progn
7493 nil) ;; does not even start with a heading
7494 (catch 'exit
7495 (while (setq start (string-match re kill (1+ start)))
7496 (when (< (- (match-end 0) (match-beginning 0) 1) start-level)
7497 (throw 'exit nil)))
7498 t))))
8c6fb58b 7499
b349f79f
CD
7500(defvar org-markers-to-move nil
7501 "Markers that should be moved with a cut-and-paste operation.
7502Those markers are stored together with their positions relative to
7503the start of the region.")
7504
7505(defun org-save-markers-in-region (beg end)
7506 "Check markers in region.
7507If these markers are between BEG and END, record their position relative
7508to BEG, so that after moving the block of text, we can put the markers back
7509into place.
7510This function gets called just before an entry or tree gets cut from the
7511buffer. After re-insertion, `org-reinstall-markers-in-region' must be
7512called immediately, to move the markers with the entries."
7513 (setq org-markers-to-move nil)
7514 (when (featurep 'org-clock)
7515 (org-clock-save-markers-for-cut-and-paste beg end))
7516 (when (featurep 'org-agenda)
7517 (org-agenda-save-markers-for-cut-and-paste beg end)))
7518
7519(defun org-check-and-save-marker (marker beg end)
7520 "Check if MARKER is between BEG and END.
7521If yes, remember the marker and the distance to BEG."
7522 (when (and (marker-buffer marker)
7523 (equal (marker-buffer marker) (current-buffer)))
7524 (if (and (>= marker beg) (< marker end))
7525 (push (cons marker (- marker beg)) org-markers-to-move))))
7526
7527(defun org-reinstall-markers-in-region (beg)
7528 "Move all remembered markers to their position relative to BEG."
7529 (mapc (lambda (x)
7530 (move-marker (car x) (+ beg (cdr x))))
7531 org-markers-to-move)
7532 (setq org-markers-to-move nil))
7533
20908596
CD
7534(defun org-narrow-to-subtree ()
7535 "Narrow buffer to the current subtree."
7536 (interactive)
7537 (save-excursion
7538 (save-match-data
7539 (narrow-to-region
c8d0cf5c 7540 (progn (org-back-to-heading t) (point))
ed21c5c8 7541 (progn (org-end-of-subtree t t)
acedf35c 7542 (if (and (org-on-heading-p) (not (eobp))) (backward-char 1))
ed21c5c8 7543 (point))))))
8c6fb58b 7544
86fbb8ca
CD
7545(eval-when-compile
7546 (defvar org-property-drawer-re))
7547
acedf35c 7548(defvar org-property-start-re) ;; defined below
c8d0cf5c
CD
7549(defun org-clone-subtree-with-time-shift (n &optional shift)
7550 "Clone the task (subtree) at point N times.
7551The clones will be inserted as siblings.
7552
86fbb8ca
CD
7553In interactive use, the user will be prompted for the number of
7554clones to be produced, and for a time SHIFT, which may be a
7555repeater as used in time stamps, for example `+3d'.
c8d0cf5c 7556
86fbb8ca
CD
7557When a valid repeater is given and the entry contains any time
7558stamps, the clones will become a sequence in time, with time
7559stamps in the subtree shifted for each clone produced. If SHIFT
7560is nil or the empty string, time stamps will be left alone. The
7561ID property of the original subtree is removed.
c8d0cf5c
CD
7562
7563If the original subtree did contain time stamps with a repeater,
7564the following will happen:
7565- the repeater will be removed in each clone
7566- an additional clone will be produced, with the current, unshifted
7567 date(s) in the entry.
7568- the original entry will be placed *after* all the clones, with
7569 repeater intact.
7570- the start days in the repeater in the original entry will be shifted
7571 to past the last clone.
7572I this way you can spell out a number of instances of a repeating task,
7573and still retain the repeater to cover future instances of the task."
7574 (interactive "nNumber of clones to produce: \nsDate shift per clone (e.g. +1w, empty to copy unchanged): ")
86fbb8ca 7575 (let (beg end template task idprop
c8d0cf5c
CD
7576 shift-n shift-what doshift nmin nmax (n-no-remove -1))
7577 (if (not (and (integerp n) (> n 0)))
7578 (error "Invalid number of replications %s" n))
7579 (if (and (setq doshift (and (stringp shift) (string-match "\\S-" shift)))
7580 (not (string-match "\\`[ \t]*\\+?\\([0-9]+\\)\\([dwmy]\\)[ \t]*\\'"
7581 shift)))
7582 (error "Invalid shift specification %s" shift))
7583 (when doshift
7584 (setq shift-n (string-to-number (match-string 1 shift))
7585 shift-what (cdr (assoc (match-string 2 shift)
7586 '(("d" . day) ("w" . week)
7587 ("m" . month) ("y" . year))))))
7588 (if (eq shift-what 'week) (setq shift-n (* 7 shift-n) shift-what 'day))
7589 (setq nmin 1 nmax n)
7590 (org-back-to-heading t)
7591 (setq beg (point))
86fbb8ca 7592 (setq idprop (org-entry-get nil "ID"))
c8d0cf5c 7593 (org-end-of-subtree t t)
8bfe682a 7594 (or (bolp) (insert "\n"))
c8d0cf5c
CD
7595 (setq end (point))
7596 (setq template (buffer-substring beg end))
7597 (when (and doshift
7598 (string-match "<[^<>\n]+ \\+[0-9]+[dwmy][^<>\n]*>" template))
7599 (delete-region beg end)
7600 (setq end beg)
7601 (setq nmin 0 nmax (1+ nmax) n-no-remove nmax))
7602 (goto-char end)
7603 (loop for n from nmin to nmax do
86fbb8ca
CD
7604 ;; prepare clone
7605 (with-temp-buffer
7606 (insert template)
7607 (org-mode)
7608 (goto-char (point-min))
7609 (and idprop (if org-clone-delete-id
7610 (org-entry-delete nil "ID")
7611 (org-id-get-create t)))
acedf35c 7612 (while (re-search-forward org-property-start-re nil t)
86fbb8ca
CD
7613 (org-remove-empty-drawer-at "PROPERTIES" (point)))
7614 (goto-char (point-min))
7615 (when doshift
c8d0cf5c
CD
7616 (while (re-search-forward org-ts-regexp-both nil t)
7617 (org-timestamp-change (* n shift-n) shift-what))
7618 (unless (= n n-no-remove)
7619 (goto-char (point-min))
7620 (while (re-search-forward org-ts-regexp nil t)
7621 (save-excursion
7622 (goto-char (match-beginning 0))
7623 (if (looking-at "<[^<>\n]+\\( +\\+[0-9]+[dwmy]\\)")
86fbb8ca
CD
7624 (delete-region (match-beginning 1) (match-end 1)))))))
7625 (setq task (buffer-string)))
c8d0cf5c
CD
7626 (insert task))
7627 (goto-char beg)))
8c6fb58b 7628
20908596 7629;;; Outline Sorting
a0d892d4 7630
20908596 7631(defun org-sort (with-case)
afe98dfa 7632 "Call `org-sort-entries', `org-table-sort-lines' or `org-sort-list'.
c8d0cf5c
CD
7633Optional argument WITH-CASE means sort case-sensitively.
7634With a double prefix argument, also remove duplicate entries."
20908596 7635 (interactive "P")
afe98dfa
CD
7636 (cond
7637 ((org-at-table-p) (org-call-with-arg 'org-table-sort-lines with-case))
7638 ((org-at-item-p) (org-call-with-arg 'org-sort-list with-case))
7639 (t
7640 (org-call-with-arg 'org-sort-entries with-case))))
8c6fb58b 7641
20908596
CD
7642(defun org-sort-remove-invisible (s)
7643 (remove-text-properties 0 (length s) org-rm-props s)
7644 (while (string-match org-bracket-link-regexp s)
7645 (setq s (replace-match (if (match-end 2)
7646 (match-string 3 s)
7647 (match-string 1 s)) t t s)))
7648 s)
8c6fb58b 7649
20908596 7650(defvar org-priority-regexp) ; defined later in the file
8c6fb58b 7651
c8d0cf5c
CD
7652(defvar org-after-sorting-entries-or-items-hook nil
7653 "Hook that is run after a bunch of entries or items have been sorted.
7654When children are sorted, the cursor is in the parent line when this
7655hook gets called. When a region or a plain list is sorted, the cursor
7656will be in the first entry of the sorted region/list.")
7657
afe98dfa 7658(defun org-sort-entries
fdf730ed 7659 (&optional with-case sorting-type getkey-func compare-func property)
afe98dfa 7660 "Sort entries on a certain level of an outline tree.
20908596
CD
7661If there is an active region, the entries in the region are sorted.
7662Else, if the cursor is before the first entry, sort the top-level items.
7663Else, the children of the entry at point are sorted.
c8d0cf5c
CD
7664
7665Sorting can be alphabetically, numerically, by date/time as given by
7666a time stamp, by a property or by priority.
7667
7668The command prompts for the sorting type unless it has been given to the
86fbb8ca 7669function through the SORTING-TYPE argument, which needs to be a character,
c8d0cf5c
CD
7670\(?n ?N ?a ?A ?t ?T ?s ?S ?d ?D ?p ?P ?r ?R ?f ?F). Here is the
7671precise meaning of each character:
7672
7673n Numerically, by converting the beginning of the entry/item to a number.
7674a Alphabetically, ignoring the TODO keyword and the priority, if any.
7675t By date/time, either the first active time stamp in the entry, or, if
7676 none exist, by the first inactive one.
c8d0cf5c
CD
7677s By the scheduled date/time.
7678d By deadline date/time.
7679c By creation time, which is assumed to be the first inactive time stamp
7680 at the beginning of a line.
7681p By priority according to the cookie.
7682r By the value of a property.
7683
7684Capital letters will reverse the sort order.
2a57416f 7685
20908596
CD
7686If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies a function to be
7687called with point at the beginning of the record. It must return either
7688a string or a number that should serve as the sorting key for that record.
2a57416f 7689
20908596
CD
7690Comparing entries ignores case by default. However, with an optional argument
7691WITH-CASE, the sorting considers case as well."
8c6fb58b 7692 (interactive "P")
20908596
CD
7693 (let ((case-func (if with-case 'identity 'downcase))
7694 start beg end stars re re2
afe98dfa 7695 txt what tmp)
20908596
CD
7696 ;; Find beginning and end of region to sort
7697 (cond
7698 ((org-region-active-p)
7699 ;; we will sort the region
7700 (setq end (region-end)
7701 what "region")
7702 (goto-char (region-beginning))
7703 (if (not (org-on-heading-p)) (outline-next-heading))
7704 (setq start (point)))
20908596
CD
7705 ((or (org-on-heading-p)
7706 (condition-case nil (progn (org-back-to-heading) t) (error nil)))
7707 ;; we will sort the children of the current headline
7708 (org-back-to-heading)
7709 (setq start (point)
7710 end (progn (org-end-of-subtree t t)
5dec9555 7711 (or (bolp) (insert "\n"))
20908596
CD
7712 (org-back-over-empty-lines)
7713 (point))
7714 what "children")
7715 (goto-char start)
7716 (show-subtree)
7717 (outline-next-heading))
7718 (t
7719 ;; we will sort the top-level entries in this file
7720 (goto-char (point-min))
7721 (or (org-on-heading-p) (outline-next-heading))
5dec9555
CD
7722 (setq start (point))
7723 (goto-char (point-max))
7724 (beginning-of-line 1)
7725 (when (looking-at ".*?\\S-")
7726 ;; File ends in a non-white line
7727 (end-of-line 1)
7728 (insert "\n"))
7729 (setq end (point-max))
7730 (setq what "top-level")
20908596
CD
7731 (goto-char start)
7732 (show-all)))
2a57416f 7733
20908596
CD
7734 (setq beg (point))
7735 (if (>= beg end) (error "Nothing to sort"))
8c6fb58b 7736
afe98dfa
CD
7737 (looking-at "\\(\\*+\\)")
7738 (setq stars (match-string 1)
7739 re (concat "^" (regexp-quote stars) " +")
7740 re2 (concat "^" (regexp-quote (substring stars 0 -1)) "[^*]")
7741 txt (buffer-substring beg end))
7742 (if (not (equal (substring txt -1) "\n")) (setq txt (concat txt "\n")))
7743 (if (and (not (equal stars "*")) (string-match re2 txt))
7744 (error "Region to sort contains a level above the first entry"))
f425a6ea 7745
20908596
CD
7746 (unless sorting-type
7747 (message
afe98dfa 7748 "Sort %s: [a]lpha [n]umeric [p]riority p[r]operty todo[o]rder [f]unc
c8d0cf5c 7749 [t]ime [s]cheduled [d]eadline [c]reated
afe98dfa 7750 A/N/T/S/D/C/P/O/F means reversed:"
20908596
CD
7751 what)
7752 (setq sorting-type (read-char-exclusive))
3278a016 7753
20908596
CD
7754 (and (= (downcase sorting-type) ?f)
7755 (setq getkey-func
54a0dee5 7756 (org-icompleting-read "Sort using function: "
afe98dfa 7757 obarray 'fboundp t nil nil))
20908596 7758 (setq getkey-func (intern getkey-func)))
f425a6ea 7759
20908596
CD
7760 (and (= (downcase sorting-type) ?r)
7761 (setq property
54a0dee5 7762 (org-icompleting-read "Property: "
afe98dfa
CD
7763 (mapcar 'list (org-buffer-property-keys t))
7764 nil t))))
4ed31842 7765
20908596 7766 (message "Sorting entries...")
3278a016 7767
20908596
CD
7768 (save-restriction
7769 (narrow-to-region start end)
20908596 7770 (let ((dcst (downcase sorting-type))
c8d0cf5c 7771 (case-fold-search nil)
20908596
CD
7772 (now (current-time)))
7773 (sort-subr
7774 (/= dcst sorting-type)
7775 ;; This function moves to the beginning character of the "record" to
7776 ;; be sorted.
afe98dfa
CD
7777 (lambda nil
7778 (if (re-search-forward re nil t)
7779 (goto-char (match-beginning 0))
7780 (goto-char (point-max))))
20908596
CD
7781 ;; This function moves to the last character of the "record" being
7782 ;; sorted.
afe98dfa
CD
7783 (lambda nil
7784 (save-match-data
7785 (condition-case nil
7786 (outline-forward-same-level 1)
7787 (error
7788 (goto-char (point-max))))))
20908596 7789 ;; This function returns the value that gets sorted against.
afe98dfa
CD
7790 (lambda nil
7791 (cond
7792 ((= dcst ?n)
7793 (if (looking-at org-complex-heading-regexp)
7794 (string-to-number (match-string 4))
7795 nil))
7796 ((= dcst ?a)
7797 (if (looking-at org-complex-heading-regexp)
7798 (funcall case-func (match-string 4))
7799 nil))
7800 ((= dcst ?t)
7801 (let ((end (save-excursion (outline-next-heading) (point))))
7802 (if (or (re-search-forward org-ts-regexp end t)
7803 (re-search-forward org-ts-regexp-both end t))
7804 (org-time-string-to-seconds (match-string 0))
7805 (org-float-time now))))
7806 ((= dcst ?c)
7807 (let ((end (save-excursion (outline-next-heading) (point))))
7808 (if (re-search-forward
7809 (concat "^[ \t]*\\[" org-ts-regexp1 "\\]")
7810 end t)
7811 (org-time-string-to-seconds (match-string 0))
7812 (org-float-time now))))
7813 ((= dcst ?s)
7814 (let ((end (save-excursion (outline-next-heading) (point))))
7815 (if (re-search-forward org-scheduled-time-regexp end t)
7816 (org-time-string-to-seconds (match-string 1))
7817 (org-float-time now))))
7818 ((= dcst ?d)
7819 (let ((end (save-excursion (outline-next-heading) (point))))
7820 (if (re-search-forward org-deadline-time-regexp end t)
7821 (org-time-string-to-seconds (match-string 1))
7822 (org-float-time now))))
7823 ((= dcst ?p)
7824 (if (re-search-forward org-priority-regexp (point-at-eol) t)
7825 (string-to-char (match-string 2))
7826 org-default-priority))
7827 ((= dcst ?r)
7828 (or (org-entry-get nil property) ""))
7829 ((= dcst ?o)
7830 (if (looking-at org-complex-heading-regexp)
7831 (- 9999 (length (member (match-string 2)
7832 org-todo-keywords-1)))))
7833 ((= dcst ?f)
7834 (if getkey-func
7835 (progn
7836 (setq tmp (funcall getkey-func))
7837 (if (stringp tmp) (setq tmp (funcall case-func tmp)))
7838 tmp)
7839 (error "Invalid key function `%s'" getkey-func)))
7840 (t (error "Invalid sorting type `%c'" sorting-type))))
20908596
CD
7841 nil
7842 (cond
7843 ((= dcst ?a) 'string<)
fdf730ed 7844 ((= dcst ?f) compare-func)
c8d0cf5c 7845 ((member dcst '(?p ?t ?s ?d ?c)) '<)
20908596 7846 (t nil)))))
c8d0cf5c 7847 (run-hooks 'org-after-sorting-entries-or-items-hook)
20908596 7848 (message "Sorting entries...done")))
a96ee7df 7849
20908596
CD
7850(defun org-do-sort (table what &optional with-case sorting-type)
7851 "Sort TABLE of WHAT according to SORTING-TYPE.
7852The user will be prompted for the SORTING-TYPE if the call to this
7853function does not specify it. WHAT is only for the prompt, to indicate
7854what is being sorted. The sorting key will be extracted from
7855the car of the elements of the table.
7856If WITH-CASE is non-nil, the sorting will be case-sensitive."
7857 (unless sorting-type
7858 (message
7859 "Sort %s: [a]lphabetic. [n]umeric. [t]ime. A/N/T means reversed:"
7860 what)
7861 (setq sorting-type (read-char-exclusive)))
7862 (let ((dcst (downcase sorting-type))
7863 extractfun comparefun)
7864 ;; Define the appropriate functions
7865 (cond
7866 ((= dcst ?n)
7867 (setq extractfun 'string-to-number
7868 comparefun (if (= dcst sorting-type) '< '>)))
7869 ((= dcst ?a)
7870 (setq extractfun (if with-case (lambda(x) (org-sort-remove-invisible x))
7871 (lambda(x) (downcase (org-sort-remove-invisible x))))
7872 comparefun (if (= dcst sorting-type)
7873 'string<
7874 (lambda (a b) (and (not (string< a b))
7875 (not (string= a b)))))))
7876 ((= dcst ?t)
7877 (setq extractfun
7878 (lambda (x)
c8d0cf5c
CD
7879 (if (or (string-match org-ts-regexp x)
7880 (string-match org-ts-regexp-both x))
54a0dee5 7881 (org-float-time
20908596
CD
7882 (org-time-string-to-time (match-string 0 x)))
7883 0))
7884 comparefun (if (= dcst sorting-type) '< '>)))
7885 (t (error "Invalid sorting type `%c'" sorting-type)))
a96ee7df 7886
20908596
CD
7887 (sort (mapcar (lambda (x) (cons (funcall extractfun (car x)) (cdr x)))
7888 table)
7889 (lambda (a b) (funcall comparefun (car a) (car b))))))
891f4676 7890
4b3a9ba7 7891
20908596 7892;;; The orgstruct minor mode
4b3a9ba7 7893
20908596
CD
7894;; Define a minor mode which can be used in other modes in order to
7895;; integrate the org-mode structure editing commands.
374585c9 7896
20908596
CD
7897;; This is really a hack, because the org-mode structure commands use
7898;; keys which normally belong to the major mode. Here is how it
7899;; works: The minor mode defines all the keys necessary to operate the
7900;; structure commands, but wraps the commands into a function which
7901;; tests if the cursor is currently at a headline or a plain list
7902;; item. If that is the case, the structure command is used,
7903;; temporarily setting many Org-mode variables like regular
7904;; expressions for filling etc. However, when any of those keys is
7905;; used at a different location, function uses `key-binding' to look
7906;; up if the key has an associated command in another currently active
7907;; keymap (minor modes, major mode, global), and executes that
7908;; command. There might be problems if any of the keys is otherwise
7909;; used as a prefix key.
4b3a9ba7 7910
20908596
CD
7911;; Another challenge is that the key binding for TAB can be tab or \C-i,
7912;; likewise the binding for RET can be return or \C-m. Orgtbl-mode
7913;; addresses this by checking explicitly for both bindings.
2a94e282 7914
20908596
CD
7915(defvar orgstruct-mode-map (make-sparse-keymap)
7916 "Keymap for the minor `orgstruct-mode'.")
03f3cf35 7917
20908596 7918(defvar org-local-vars nil
86fbb8ca 7919 "List of local variables, for use by `orgstruct-mode'.")
03f3cf35 7920
20908596
CD
7921;;;###autoload
7922(define-minor-mode orgstruct-mode
86fbb8ca
CD
7923 "Toggle the minor mode `orgstruct-mode'.
7924This mode is for using Org-mode structure commands in other
7925modes. The following keys behave as if Org-mode were active, if
7926the cursor is on a headline, or on a plain list item (both as
7927defined by Org-mode).
03f3cf35 7928
20908596
CD
7929M-up Move entry/item up
7930M-down Move entry/item down
7931M-left Promote
7932M-right Demote
7933M-S-up Move entry/item up
7934M-S-down Move entry/item down
7935M-S-left Promote subtree
7936M-S-right Demote subtree
7937M-q Fill paragraph and items like in Org-mode
7938C-c ^ Sort entries
7939C-c - Cycle list bullet
7940TAB Cycle item visibility
7941M-RET Insert new heading/item
33306645 7942S-M-RET Insert new TODO heading / Checkbox item
20908596
CD
7943C-c C-c Set tags / toggle checkbox"
7944 nil " OrgStruct" nil
7945 (org-load-modules-maybe)
7946 (and (orgstruct-setup) (defun orgstruct-setup () nil)))
891f4676 7947
20908596
CD
7948;;;###autoload
7949(defun turn-on-orgstruct ()
7950 "Unconditionally turn on `orgstruct-mode'."
7951 (orgstruct-mode 1))
7952
c8d0cf5c
CD
7953(defun orgstruct++-mode (&optional arg)
7954 "Toggle `orgstruct-mode', the enhanced version of it.
7955In addition to setting orgstruct-mode, this also exports all indentation
7956and autofilling variables from org-mode into the buffer. It will also
7957recognize item context in multiline items.
7958Note that turning off orgstruct-mode will *not* remove the
7959indentation/paragraph settings. This can only be done by refreshing the
7960major mode, for example with \\[normal-mode]."
7961 (interactive "P")
7962 (setq arg (prefix-numeric-value (or arg (if orgstruct-mode -1 1))))
7963 (if (< arg 1)
7964 (orgstruct-mode -1)
7965 (orgstruct-mode 1)
7966 (let (var val)
7967 (mapc
7968 (lambda (x)
7969 (when (string-match
7970 "^\\(paragraph-\\|auto-fill\\|fill-paragraph\\|adaptive-fill\\|indent-\\)"
7971 (symbol-name (car x)))
7972 (setq var (car x) val (nth 1 x))
7973 (org-set-local var (if (eq (car-safe val) 'quote) (nth 1 val) val))))
7974 org-local-vars)
7975 (org-set-local 'orgstruct-is-++ t))))
7976
7977(defvar orgstruct-is-++ nil
86fbb8ca 7978 "Is `orgstruct-mode' in ++ version in the current-buffer?")
c8d0cf5c
CD
7979(make-variable-buffer-local 'orgstruct-is-++)
7980
20908596
CD
7981;;;###autoload
7982(defun turn-on-orgstruct++ ()
c8d0cf5c
CD
7983 "Unconditionally turn on `orgstruct++-mode'."
7984 (orgstruct++-mode 1))
20908596
CD
7985
7986(defun orgstruct-error ()
7987 "Error when there is no default binding for a structure key."
7988 (interactive)
7989 (error "This key has no function outside structure elements"))
891f4676 7990
20908596
CD
7991(defun orgstruct-setup ()
7992 "Setup orgstruct keymaps."
7993 (let ((nfunc 0)
7994 (bindings
7995 (list
7996 '([(meta up)] org-metaup)
7997 '([(meta down)] org-metadown)
7998 '([(meta left)] org-metaleft)
7999 '([(meta right)] org-metaright)
8000 '([(meta shift up)] org-shiftmetaup)
8001 '([(meta shift down)] org-shiftmetadown)
8002 '([(meta shift left)] org-shiftmetaleft)
8003 '([(meta shift right)] org-shiftmetaright)
c8d0cf5c
CD
8004 '([?\e (up)] org-metaup)
8005 '([?\e (down)] org-metadown)
8006 '([?\e (left)] org-metaleft)
8007 '([?\e (right)] org-metaright)
8008 '([?\e (shift up)] org-shiftmetaup)
8009 '([?\e (shift down)] org-shiftmetadown)
8010 '([?\e (shift left)] org-shiftmetaleft)
8011 '([?\e (shift right)] org-shiftmetaright)
20908596
CD
8012 '([(shift up)] org-shiftup)
8013 '([(shift down)] org-shiftdown)
ce4fdcb9
CD
8014 '([(shift left)] org-shiftleft)
8015 '([(shift right)] org-shiftright)
20908596
CD
8016 '("\C-c\C-c" org-ctrl-c-ctrl-c)
8017 '("\M-q" fill-paragraph)
8018 '("\C-c^" org-sort)
8019 '("\C-c-" org-cycle-list-bullet)))
8020 elt key fun cmd)
8021 (while (setq elt (pop bindings))
8022 (setq nfunc (1+ nfunc))
8023 (setq key (org-key (car elt))
8024 fun (nth 1 elt)
8025 cmd (orgstruct-make-binding fun nfunc key))
8026 (org-defkey orgstruct-mode-map key cmd))
891f4676 8027
20908596
CD
8028 ;; Special treatment needed for TAB and RET
8029 (org-defkey orgstruct-mode-map [(tab)]
8030 (orgstruct-make-binding 'org-cycle 102 [(tab)] "\C-i"))
8031 (org-defkey orgstruct-mode-map "\C-i"
8032 (orgstruct-make-binding 'org-cycle 103 "\C-i" [(tab)]))
6769c0dc 8033
20908596
CD
8034 (org-defkey orgstruct-mode-map "\M-\C-m"
8035 (orgstruct-make-binding 'org-insert-heading 105
8036 "\M-\C-m" [(meta return)]))
8037 (org-defkey orgstruct-mode-map [(meta return)]
8038 (orgstruct-make-binding 'org-insert-heading 106
8039 [(meta return)] "\M-\C-m"))
891f4676 8040
20908596
CD
8041 (org-defkey orgstruct-mode-map [(shift meta return)]
8042 (orgstruct-make-binding 'org-insert-todo-heading 107
8043 [(meta return)] "\M-\C-m"))
891f4676 8044
c8d0cf5c
CD
8045 (org-defkey orgstruct-mode-map "\e\C-m"
8046 (orgstruct-make-binding 'org-insert-heading 108
8047 "\e\C-m" [?\e (return)]))
8048 (org-defkey orgstruct-mode-map [?\e (return)]
8049 (orgstruct-make-binding 'org-insert-heading 109
8050 [?\e (return)] "\e\C-m"))
8051 (org-defkey orgstruct-mode-map [?\e (shift return)]
8052 (orgstruct-make-binding 'org-insert-todo-heading 110
8053 [?\e (return)] "\e\C-m"))
8054
20908596
CD
8055 (unless org-local-vars
8056 (setq org-local-vars (org-get-local-variables)))
891f4676 8057
20908596 8058 t))
891f4676 8059
20908596
CD
8060(defun orgstruct-make-binding (fun n &rest keys)
8061 "Create a function for binding in the structure minor mode.
8062FUN is the command to call inside a table. N is used to create a unique
8063command name. KEYS are keys that should be checked in for a command
8064to execute outside of tables."
8065 (eval
8066 (list 'defun
8067 (intern (concat "orgstruct-hijacker-command-" (int-to-string n)))
8068 '(arg)
8069 (concat "In Structure, run `" (symbol-name fun) "'.\n"
8070 "Outside of structure, run the binding of `"
8071 (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
8072 "'.")
8073 '(interactive "p")
8074 (list 'if
c8d0cf5c
CD
8075 `(org-context-p 'headline 'item
8076 (and orgstruct-is-++
8077 ,(and (memq fun '(org-insert-heading org-insert-todo-heading)) t)
8078 'item-body))
20908596
CD
8079 (list 'org-run-like-in-org-mode (list 'quote fun))
8080 (list 'let '(orgstruct-mode)
8081 (list 'call-interactively
8082 (append '(or)
8083 (mapcar (lambda (k)
8084 (list 'key-binding k))
8085 keys)
8086 '('orgstruct-error))))))))
64f72ae1 8087
20908596 8088(defun org-context-p (&rest contexts)
621f83e4 8089 "Check if local context is any of CONTEXTS.
20908596
CD
8090Possible values in the list of contexts are `table', `headline', and `item'."
8091 (let ((pos (point)))
8092 (goto-char (point-at-bol))
8093 (prog1 (or (and (memq 'table contexts)
8094 (looking-at "[ \t]*|"))
8095 (and (memq 'headline contexts)
621f83e4
CD
8096;;????????? (looking-at "\\*+"))
8097 (looking-at outline-regexp))
20908596 8098 (and (memq 'item contexts)
c8d0cf5c
CD
8099 (looking-at "[ \t]*\\([-+*] \\|[0-9]+[.)] \\)"))
8100 (and (memq 'item-body contexts)
8101 (org-in-item-p)))
20908596 8102 (goto-char pos))))
4b3a9ba7 8103
20908596
CD
8104(defun org-get-local-variables ()
8105 "Return a list of all local variables in an org-mode buffer."
8106 (let (varlist)
8107 (with-current-buffer (get-buffer-create "*Org tmp*")
8108 (erase-buffer)
8109 (org-mode)
8110 (setq varlist (buffer-local-variables)))
8111 (kill-buffer "*Org tmp*")
8112 (delq nil
8113 (mapcar
8114 (lambda (x)
8115 (setq x
8116 (if (symbolp x)
8117 (list x)
8118 (list (car x) (list 'quote (cdr x)))))
8119 (if (string-match
8120 "^\\(org-\\|orgtbl-\\|outline-\\|comment-\\|paragraph-\\|auto-fill\\|fill-paragraph\\|adaptive-fill\\|indent-\\)"
8121 (symbol-name (car x)))
8122 x nil))
8123 varlist))))
891f4676 8124
20908596
CD
8125;;;###autoload
8126(defun org-run-like-in-org-mode (cmd)
c8d0cf5c
CD
8127 "Run a command, pretending that the current buffer is in Org-mode.
8128This will temporarily bind local variables that are typically bound in
8129Org-mode to the values they have in Org-mode, and then interactively
8130call CMD."
20908596
CD
8131 (org-load-modules-maybe)
8132 (unless org-local-vars
8133 (setq org-local-vars (org-get-local-variables)))
8134 (eval (list 'let org-local-vars
8135 (list 'call-interactively (list 'quote cmd)))))
891f4676 8136
20908596 8137;;;; Archiving
891f4676 8138
20908596
CD
8139(defun org-get-category (&optional pos)
8140 "Get the category applying to position POS."
8141 (get-text-property (or pos (point)) 'org-category))
a96ee7df 8142
20908596
CD
8143(defun org-refresh-category-properties ()
8144 "Refresh category text properties in the buffer."
8145 (let ((def-cat (cond
8146 ((null org-category)
8147 (if buffer-file-name
8148 (file-name-sans-extension
8149 (file-name-nondirectory buffer-file-name))
8150 "???"))
8151 ((symbolp org-category) (symbol-name org-category))
8152 (t org-category)))
8153 beg end cat pos optionp)
8154 (org-unmodified
8155 (save-excursion
8156 (save-restriction
8157 (widen)
8158 (goto-char (point-min))
8159 (put-text-property (point) (point-max) 'org-category def-cat)
8160 (while (re-search-forward
8161 "^\\(#\\+CATEGORY:\\|[ \t]*:CATEGORY:\\)\\(.*\\)" nil t)
8162 (setq pos (match-end 0)
8163 optionp (equal (char-after (match-beginning 0)) ?#)
8164 cat (org-trim (match-string 2)))
8165 (if optionp
8166 (setq beg (point-at-bol) end (point-max))
8167 (org-back-to-heading t)
8168 (setq beg (point) end (org-end-of-subtree t t)))
8169 (put-text-property beg end 'org-category cat)
8170 (goto-char pos)))))))
891f4676 8171
891f4676 8172
20908596 8173;;;; Link Stuff
03f3cf35 8174
20908596 8175;;; Link abbreviations
891f4676 8176
20908596
CD
8177(defun org-link-expand-abbrev (link)
8178 "Apply replacements as defined in `org-link-abbrev-alist."
8179 (if (string-match "^\\([a-zA-Z][-_a-zA-Z0-9]*\\)\\(::?\\(.*\\)\\)?$" link)
8180 (let* ((key (match-string 1 link))
8181 (as (or (assoc key org-link-abbrev-alist-local)
8182 (assoc key org-link-abbrev-alist)))
8183 (tag (and (match-end 2) (match-string 3 link)))
8184 rpl)
8185 (if (not as)
8186 link
8187 (setq rpl (cdr as))
8188 (cond
8189 ((symbolp rpl) (funcall rpl tag))
8190 ((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
ce4fdcb9
CD
8191 ((string-match "%h" rpl)
8192 (replace-match (url-hexify-string (or tag "")) t t rpl))
20908596
CD
8193 (t (concat rpl tag)))))
8194 link))
4b3a9ba7 8195
20908596 8196;;; Storing and inserting links
0fee8d6e 8197
20908596
CD
8198(defvar org-insert-link-history nil
8199 "Minibuffer history for links inserted with `org-insert-link'.")
38f8646b 8200
20908596
CD
8201(defvar org-stored-links nil
8202 "Contains the links stored with `org-store-link'.")
38f8646b 8203
20908596
CD
8204(defvar org-store-link-plist nil
8205 "Plist with info about the most recently link created with `org-store-link'.")
fbe6c10d 8206
20908596
CD
8207(defvar org-link-protocols nil
8208 "Link protocols added to Org-mode using `org-add-link-type'.")
f425a6ea 8209
20908596
CD
8210(defvar org-store-link-functions nil
8211 "List of functions that are called to create and store a link.
8212Each function will be called in turn until one returns a non-nil
8213value. Each function should check if it is responsible for creating
8214this link (for example by looking at the major mode).
8215If not, it must exit and return nil.
8216If yes, it should return a non-nil value after a calling
8217`org-store-link-props' with a list of properties and values.
8218Special properties are:
30313b90 8219
86fbb8ca 8220:type The link prefix, like \"http\". This must be given.
20908596
CD
8221:link The link, like \"http://www.astro.uva.nl/~dominik\".
8222 This is obligatory as well.
8223:description Optional default description for the second pair
8224 of brackets in an Org-mode link. The user can still change
8225 this when inserting this link into an Org-mode buffer.
30313b90 8226
20908596
CD
8227In addition to these, any additional properties can be specified
8228and then used in remember templates.")
35402b98 8229
20908596
CD
8230(defun org-add-link-type (type &optional follow export)
8231 "Add TYPE to the list of `org-link-types'.
8232Re-compute all regular expressions depending on `org-link-types'
ab27a4a0 8233
20908596 8234FOLLOW and EXPORT are two functions.
891f4676 8235
20908596
CD
8236FOLLOW should take the link path as the single argument and do whatever
8237is necessary to follow the link, for example find a file or display
8238a mail message.
1e8fbb6d 8239
20908596
CD
8240EXPORT should format the link path for export to one of the export formats.
8241It should be a function accepting three arguments:
fbe6c10d 8242
20908596 8243 path the path of the link, the text after the prefix (like \"http:\")
33306645 8244 desc the description of the link, if any, nil if there was no description
afe98dfa 8245 format the export format, a symbol like `html' or `latex' or `ascii'..
fbe6c10d 8246
20908596
CD
8247The function may use the FORMAT information to return different values
8248depending on the format. The return value will be put literally into
afe98dfa
CD
8249the exported file. If the return value is nil, this means Org should
8250do what it normally does with links which do not have EXPORT defined.
8251
20908596
CD
8252Org-mode has a built-in default for exporting links. If you are happy with
8253this default, there is no need to define an export function for the link
8254type. For a simple example of an export function, see `org-bbdb.el'."
8255 (add-to-list 'org-link-types type t)
8256 (org-make-link-regexps)
8257 (if (assoc type org-link-protocols)
8258 (setcdr (assoc type org-link-protocols) (list follow export))
8259 (push (list type follow export) org-link-protocols)))
374585c9 8260
8d642074
CD
8261(defvar org-agenda-buffer-name)
8262
20908596
CD
8263;;;###autoload
8264(defun org-store-link (arg)
8265 "\\<org-mode-map>Store an org-link to the current location.
8266This link is added to `org-stored-links' and can later be inserted
8267into an org-buffer with \\[org-insert-link].
8268
8269For some link types, a prefix arg is interpreted:
ce4fdcb9 8270For links to usenet articles, arg negates `org-gnus-prefer-web-links'.
20908596
CD
8271For file links, arg negates `org-context-in-file-links'."
8272 (interactive "P")
8273 (org-load-modules-maybe)
8274 (setq org-store-link-plist nil) ; reset
c8d0cf5c 8275 (let ((outline-regexp (org-get-limited-outline-regexp))
afe98dfa 8276 link cpltxt desc description search txt custom-id agenda-link)
d3f4dbe8 8277 (cond
a96ee7df 8278
20908596
CD
8279 ((run-hook-with-args-until-success 'org-store-link-functions)
8280 (setq link (plist-get org-store-link-plist :link)
8281 desc (or (plist-get org-store-link-plist :description) link)))
8282
0bd48b37
CD
8283 ((equal (buffer-name) "*Org Edit Src Example*")
8284 (let (label gc)
8285 (while (or (not label)
8286 (save-excursion
8287 (save-restriction
8288 (widen)
8289 (goto-char (point-min))
8290 (re-search-forward
8291 (regexp-quote (format org-coderef-label-format label))
8292 nil t))))
8293 (when label (message "Label exists already") (sit-for 2))
8294 (setq label (read-string "Code line label: " label)))
8295 (end-of-line 1)
8296 (setq link (format org-coderef-label-format label))
8297 (setq gc (- 79 (length link)))
8298 (if (< (current-column) gc) (org-move-to-column gc t) (insert " "))
8299 (insert link)
8300 (setq link (concat "(" label ")") desc nil)))
8301
8d642074
CD
8302 ((equal (org-bound-and-true-p org-agenda-buffer-name) (buffer-name))
8303 ;; We are in the agenda, link to referenced location
8304 (let ((m (or (get-text-property (point) 'org-hd-marker)
8305 (get-text-property (point) 'org-marker))))
8306 (when m
8307 (org-with-point-at m
afe98dfa
CD
8308 (setq agenda-link
8309 (if (interactive-p)
8310 (call-interactively 'org-store-link)
8311 (org-store-link nil)))))))
8d642074 8312
20908596
CD
8313 ((eq major-mode 'calendar-mode)
8314 (let ((cd (calendar-cursor-to-date)))
8315 (setq link
8316 (format-time-string
8317 (car org-time-stamp-formats)
8318 (apply 'encode-time
8319 (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
8320 nil nil nil))))
8321 (org-store-link-props :type "calendar" :date cd)))
8322
8323 ((eq major-mode 'w3-mode)
c8d0cf5c
CD
8324 (setq cpltxt (if (and (buffer-name)
8325 (not (string-match "Untitled" (buffer-name))))
8326 (buffer-name)
8327 (url-view-url t))
8328 link (org-make-link (url-view-url t)))
20908596
CD
8329 (org-store-link-props :type "w3" :url (url-view-url t)))
8330
8331 ((eq major-mode 'w3m-mode)
8332 (setq cpltxt (or w3m-current-title w3m-current-url)
8333 link (org-make-link w3m-current-url))
8334 (org-store-link-props :type "w3m" :url (url-view-url t)))
8335
8336 ((setq search (run-hook-with-args-until-success
8337 'org-create-file-search-functions))
8338 (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
8339 "::" search))
8340 (setq cpltxt (or description link)))
8341
8342 ((eq major-mode 'image-mode)
8343 (setq cpltxt (concat "file:"
8344 (abbreviate-file-name buffer-file-name))
8345 link (org-make-link cpltxt))
8346 (org-store-link-props :type "image" :file buffer-file-name))
8347
8348 ((eq major-mode 'dired-mode)
8349 ;; link to the file in the current line
ed21c5c8
CD
8350 (let ((file (dired-get-filename nil t)))
8351 (setq file (if file
8352 (abbreviate-file-name
8353 (expand-file-name (dired-get-filename nil t)))
8354 ;; otherwise, no file so use current directory.
8355 default-directory))
8356 (setq cpltxt (concat "file:" file)
8357 link (org-make-link cpltxt))))
20908596 8358
afe98dfa 8359 ((and (buffer-file-name (buffer-base-buffer)) (org-mode-p))
c8d0cf5c 8360 (setq custom-id (ignore-errors (org-entry-get nil "CUSTOM_ID")))
db55f368
CD
8361 (cond
8362 ((org-in-regexp "<<\\(.*?\\)>>")
8363 (setq cpltxt
8364 (concat "file:"
afe98dfa
CD
8365 (abbreviate-file-name
8366 (buffer-file-name (buffer-base-buffer)))
db55f368
CD
8367 "::" (match-string 1))
8368 link (org-make-link cpltxt)))
8369 ((and (featurep 'org-id)
8370 (or (eq org-link-to-org-use-id t)
8371 (and (eq org-link-to-org-use-id 'create-if-interactive)
8372 (interactive-p))
c8d0cf5c
CD
8373 (and (eq org-link-to-org-use-id 'create-if-interactive-and-no-custom-id)
8374 (interactive-p)
8375 (not custom-id))
db55f368
CD
8376 (and org-link-to-org-use-id
8377 (condition-case nil
8378 (org-entry-get nil "ID")
8379 (error nil)))))
8380 ;; We can make a link using the ID.
8381 (setq link (condition-case nil
fdf730ed
CD
8382 (prog1 (org-id-store-link)
8383 (setq desc (plist-get org-store-link-plist
8384 :description)))
db55f368 8385 (error
33306645 8386 ;; probably before first headline, link to file only
db55f368 8387 (concat "file:"
afe98dfa
CD
8388 (abbreviate-file-name
8389 (buffer-file-name (buffer-base-buffer))))))))
db55f368
CD
8390 (t
8391 ;; Just link to current headline
8392 (setq cpltxt (concat "file:"
afe98dfa
CD
8393 (abbreviate-file-name
8394 (buffer-file-name (buffer-base-buffer)))))
db55f368
CD
8395 ;; Add a context search string
8396 (when (org-xor org-context-in-file-links arg)
20908596
CD
8397 (setq txt (cond
8398 ((org-on-heading-p) nil)
8399 ((org-region-active-p)
8400 (buffer-substring (region-beginning) (region-end)))
8401 (t nil)))
8402 (when (or (null txt) (string-match "\\S-" txt))
8403 (setq cpltxt
b349f79f
CD
8404 (concat cpltxt "::"
8405 (condition-case nil
8406 (org-make-org-heading-search-string txt)
8407 (error "")))
8d642074
CD
8408 desc (or (nth 4 (ignore-errors
8409 (org-heading-components))) "NONE"))))
db55f368
CD
8410 (if (string-match "::\\'" cpltxt)
8411 (setq cpltxt (substring cpltxt 0 -2)))
8412 (setq link (org-make-link cpltxt)))))
20908596
CD
8413
8414 ((buffer-file-name (buffer-base-buffer))
8415 ;; Just link to this file here.
8416 (setq cpltxt (concat "file:"
8417 (abbreviate-file-name
8418 (buffer-file-name (buffer-base-buffer)))))
8419 ;; Add a context string
8420 (when (org-xor org-context-in-file-links arg)
8421 (setq txt (if (org-region-active-p)
8422 (buffer-substring (region-beginning) (region-end))
8423 (buffer-substring (point-at-bol) (point-at-eol))))
8424 ;; Only use search option if there is some text.
8425 (when (string-match "\\S-" txt)
8426 (setq cpltxt
8427 (concat cpltxt "::" (org-make-org-heading-search-string txt))
8428 desc "NONE")))
8429 (setq link (org-make-link cpltxt)))
8430
8431 ((interactive-p)
8432 (error "Cannot link to a buffer which is not visiting a file"))
891f4676 8433
20908596 8434 (t (setq link nil)))
891f4676 8435
20908596
CD
8436 (if (consp link) (setq cpltxt (car link) link (cdr link)))
8437 (setq link (or link cpltxt)
8438 desc (or desc cpltxt))
8439 (if (equal desc "NONE") (setq desc nil))
ab27a4a0 8440
c8d0cf5c 8441 (if (and (or (interactive-p) executing-kbd-macro) link)
20908596
CD
8442 (progn
8443 (setq org-stored-links
8444 (cons (list link desc) org-stored-links))
c8d0cf5c
CD
8445 (message "Stored: %s" (or desc link))
8446 (when custom-id
8447 (setq link (concat "file:" (abbreviate-file-name (buffer-file-name))
8448 "::#" custom-id))
8449 (setq org-stored-links
8450 (cons (list link desc) org-stored-links))))
afe98dfa 8451 (or agenda-link (and link (org-make-link-string link desc))))))
20908596
CD
8452
8453(defun org-store-link-props (&rest plist)
8454 "Store link properties, extract names and addresses."
8455 (let (x adr)
8456 (when (setq x (plist-get plist :from))
8457 (setq adr (mail-extract-address-components x))
93b62de8
CD
8458 (setq plist (plist-put plist :fromname (car adr)))
8459 (setq plist (plist-put plist :fromaddress (nth 1 adr))))
20908596
CD
8460 (when (setq x (plist-get plist :to))
8461 (setq adr (mail-extract-address-components x))
93b62de8
CD
8462 (setq plist (plist-put plist :toname (car adr)))
8463 (setq plist (plist-put plist :toaddress (nth 1 adr)))))
20908596
CD
8464 (let ((from (plist-get plist :from))
8465 (to (plist-get plist :to)))
8466 (when (and from to org-from-is-user-regexp)
93b62de8
CD
8467 (setq plist
8468 (plist-put plist :fromto
8469 (if (string-match org-from-is-user-regexp from)
8470 (concat "to %t")
8471 (concat "from %f"))))))
20908596
CD
8472 (setq org-store-link-plist plist))
8473
8474(defun org-add-link-props (&rest plist)
8475 "Add these properties to the link property list."
8476 (let (key value)
8477 (while plist
8478 (setq key (pop plist) value (pop plist))
8479 (setq org-store-link-plist
8480 (plist-put org-store-link-plist key value)))))
8481
8482(defun org-email-link-description (&optional fmt)
8483 "Return the description part of an email link.
8484This takes information from `org-store-link-plist' and formats it
8485according to FMT (default from `org-email-link-description-format')."
8486 (setq fmt (or fmt org-email-link-description-format))
8487 (let* ((p org-store-link-plist)
8488 (to (plist-get p :toaddress))
8489 (from (plist-get p :fromaddress))
8490 (table
8491 (list
8492 (cons "%c" (plist-get p :fromto))
8493 (cons "%F" (plist-get p :from))
8494 (cons "%f" (or (plist-get p :fromname) (plist-get p :fromaddress) "?"))
8495 (cons "%T" (plist-get p :to))
8496 (cons "%t" (or (plist-get p :toname) (plist-get p :toaddress) "?"))
8497 (cons "%s" (plist-get p :subject))
8498 (cons "%m" (plist-get p :message-id)))))
8499 (when (string-match "%c" fmt)
8500 ;; Check if the user wrote this message
8501 (if (and org-from-is-user-regexp from to
8502 (save-match-data (string-match org-from-is-user-regexp from)))
8503 (setq fmt (replace-match "to %t" t t fmt))
8504 (setq fmt (replace-match "from %f" t t fmt))))
8505 (org-replace-escapes fmt table)))
8506
8507(defun org-make-org-heading-search-string (&optional string heading)
8508 "Make search string for STRING or current headline."
8509 (interactive)
acedf35c
CD
8510 (let ((s (or string (org-get-heading)))
8511 (lines org-context-in-file-links))
20908596
CD
8512 (unless (and string (not heading))
8513 ;; We are using a headline, clean up garbage in there.
8514 (if (string-match org-todo-regexp s)
8515 (setq s (replace-match "" t t s)))
afe98dfa 8516 (if (string-match (org-re ":[[:alnum:]_@#%:]+:[ \t]*$") s)
20908596
CD
8517 (setq s (replace-match "" t t s)))
8518 (setq s (org-trim s))
8519 (if (string-match (concat "^\\(" org-quote-string "\\|"
8520 org-comment-string "\\)") s)
8521 (setq s (replace-match "" t t s)))
8522 (while (string-match org-ts-regexp s)
8523 (setq s (replace-match "" t t s))))
20908596 8524 (or string (setq s (concat "*" s))) ; Add * for headlines
acedf35c
CD
8525 (when (and string (integerp lines) (> lines 0))
8526 (let ((slines (org-split-string s "\n")))
8527 (when (< lines (length slines))
01c35094 8528 (setq s (mapconcat
acedf35c 8529 'identity
01c35094 8530 (reverse (nthcdr (- (length slines) lines)
acedf35c 8531 (reverse slines))) "\n")))))
20908596 8532 (mapconcat 'identity (org-split-string s "[ \t]+") " ")))
891f4676 8533
20908596
CD
8534(defun org-make-link (&rest strings)
8535 "Concatenate STRINGS."
8536 (apply 'concat strings))
ab27a4a0 8537
20908596
CD
8538(defun org-make-link-string (link &optional description)
8539 "Make a link with brackets, consisting of LINK and DESCRIPTION."
8540 (unless (string-match "\\S-" link)
8541 (error "Empty link"))
5dec9555
CD
8542 (when (and description
8543 (stringp description)
8544 (not (string-match "\\S-" description)))
8545 (setq description nil))
20908596
CD
8546 (when (stringp description)
8547 ;; Remove brackets from the description, they are fatal.
8548 (while (string-match "\\[" description)
8549 (setq description (replace-match "{" t t description)))
8550 (while (string-match "\\]" description)
8551 (setq description (replace-match "}" t t description))))
8552 (when (equal (org-link-escape link) description)
8553 ;; No description needed, it is identical
8554 (setq description nil))
8555 (when (and (not description)
8556 (not (equal link (org-link-escape link))))
2c3ad40d 8557 (setq description (org-extract-attributes link)))
afe98dfa
CD
8558 (setq link (if (string-match org-link-types-re link)
8559 (concat (match-string 1 link)
8560 (org-link-escape (substring link (match-end 1))))
8561 (org-link-escape link)))
8562 (concat "[[" link "]"
20908596
CD
8563 (if description (concat "[" description "]") "")
8564 "]"))
8565
8566(defconst org-link-escape-chars
8567 '((?\ . "%20")
8568 (?\[ . "%5B")
8569 (?\] . "%5D")
8570 (?\340 . "%E0") ; `a
8571 (?\342 . "%E2") ; ^a
8572 (?\347 . "%E7") ; ,c
8573 (?\350 . "%E8") ; `e
8574 (?\351 . "%E9") ; 'e
8575 (?\352 . "%EA") ; ^e
8576 (?\356 . "%EE") ; ^i
8577 (?\364 . "%F4") ; ^o
8578 (?\371 . "%F9") ; `u
8579 (?\373 . "%FB") ; ^u
8580 (?\; . "%3B")
ed21c5c8 8581;; (?? . "%3F")
20908596
CD
8582 (?= . "%3D")
8583 (?+ . "%2B")
8584 )
8585 "Association list of escapes for some characters problematic in links.
8586This is the list that is used for internal purposes.")
8587
c8d0cf5c
CD
8588(defvar org-url-encoding-use-url-hexify nil)
8589
20908596
CD
8590(defconst org-link-escape-chars-browser
8591 '((?\ . "%20")) ; 32 for the SPC char
8592 "Association list of escapes for some characters problematic in links.
8593This is the list that is used before handing over to the browser.")
8594
8595(defun org-link-escape (text &optional table)
d60b1ba1 8596 "Escape characters in TEXT that are problematic for links."
ed21c5c8 8597 (if (and org-url-encoding-use-url-hexify (not table))
c8d0cf5c
CD
8598 (url-hexify-string text)
8599 (setq table (or table org-link-escape-chars))
8600 (when text
8601 (let ((re (mapconcat (lambda (x) (regexp-quote
8602 (char-to-string (car x))))
8603 table "\\|")))
8604 (while (string-match re text)
8605 (setq text
8606 (replace-match
8607 (cdr (assoc (string-to-char (match-string 0 text))
8608 table))
20908596 8609 t t text)))
c8d0cf5c 8610 text))))
20908596
CD
8611
8612(defun org-link-unescape (text &optional table)
8613 "Reverse the action of `org-link-escape'."
ed21c5c8 8614 (if (and org-url-encoding-use-url-hexify (not table))
c8d0cf5c
CD
8615 (url-unhex-string text)
8616 (setq table (or table org-link-escape-chars))
8617 (when text
ed21c5c8
CD
8618 (let ((case-fold-search t)
8619 (re (mapconcat (lambda (x) (regexp-quote (downcase (cdr x))))
c8d0cf5c
CD
8620 table "\\|")))
8621 (while (string-match re text)
8622 (setq text
8623 (replace-match
ed21c5c8
CD
8624 (char-to-string (car (rassoc (upcase (match-string 0 text))
8625 table)))
c8d0cf5c
CD
8626 t t text)))
8627 text))))
20908596
CD
8628
8629(defun org-xor (a b)
8630 "Exclusive or."
8631 (if a (not b) b))
8632
20908596
CD
8633(defun org-fixup-message-id-for-http (s)
8634 "Replace special characters in a message id, so it can be used in an http query."
86fbb8ca
CD
8635 (when (string-match "%" s)
8636 (setq s (mapconcat (lambda (c)
8637 (if (eq c ?%)
8638 "%25"
8639 (char-to-string c)))
8640 s "")))
20908596
CD
8641 (while (string-match "<" s)
8642 (setq s (replace-match "%3C" t t s)))
8643 (while (string-match ">" s)
8644 (setq s (replace-match "%3E" t t s)))
8645 (while (string-match "@" s)
8646 (setq s (replace-match "%40" t t s)))
8647 s)
8648
8649;;;###autoload
8650(defun org-insert-link-global ()
8651 "Insert a link like Org-mode does.
8652This command can be called in any mode to insert a link in Org-mode syntax."
8653 (interactive)
8654 (org-load-modules-maybe)
8655 (org-run-like-in-org-mode 'org-insert-link))
8656
8657(defun org-insert-link (&optional complete-file link-location)
8658 "Insert a link. At the prompt, enter the link.
8659
93b62de8
CD
8660Completion can be used to insert any of the link protocol prefixes like
8661http or ftp in use.
8662
8663The history can be used to select a link previously stored with
20908596
CD
8664`org-store-link'. When the empty string is entered (i.e. if you just
8665press RET at the prompt), the link defaults to the most recently
8666stored link. As SPC triggers completion in the minibuffer, you need to
8667use M-SPC or C-q SPC to force the insertion of a space character.
8668
8669You will also be prompted for a description, and if one is given, it will
8670be displayed in the buffer instead of the link.
8671
8672If there is already a link at point, this command will allow you to edit link
8673and description parts.
8674
01c35094
JB
8675With a \\[universal-argument] prefix, prompts for a file to link to. The file name can
8676be selected using completion. The path to the file will be relative to the
20908596
CD
8677current directory if the file is in the current directory or a subdirectory.
8678Otherwise, the link will be the absolute path as completed in the minibuffer
93b62de8
CD
8679\(i.e. normally ~/path/to/file). You can configure this behavior using the
8680option `org-link-file-path-type'.
20908596
CD
8681
8682With two \\[universal-argument] prefixes, enforce an absolute path even if the file is in
93b62de8
CD
8683the current directory or below.
8684
8685With three \\[universal-argument] prefixes, negate the meaning of
8686`org-keep-stored-link-after-insertion'.
20908596
CD
8687
8688If `org-make-link-description-function' is non-nil, this function will be
8689called with the link target, and the result will be the default
8690link description.
8691
8692If the LINK-LOCATION parameter is non-nil, this value will be
8693used as the link location instead of reading one interactively."
8694 (interactive "P")
8695 (let* ((wcf (current-window-configuration))
8696 (region (if (org-region-active-p)
8697 (buffer-substring (region-beginning) (region-end))))
8698 (remove (and region (list (region-beginning) (region-end))))
8699 (desc region)
8700 tmphist ; byte-compile incorrectly complains about this
8701 (link link-location)
c8d0cf5c 8702 entry file all-prefixes)
20908596
CD
8703 (cond
8704 (link-location) ; specified by arg, just use it.
8705 ((org-in-regexp org-bracket-link-regexp 1)
8706 ;; We do have a link at point, and we are going to edit it.
8707 (setq remove (list (match-beginning 0) (match-end 0)))
8708 (setq desc (if (match-end 3) (org-match-string-no-properties 3)))
8709 (setq link (read-string "Link: "
8710 (org-link-unescape
8711 (org-match-string-no-properties 1)))))
8712 ((or (org-in-regexp org-angle-link-re)
8713 (org-in-regexp org-plain-link-re))
8714 ;; Convert to bracket link
8715 (setq remove (list (match-beginning 0) (match-end 0))
8716 link (read-string "Link: "
8717 (org-remove-angle-brackets (match-string 0)))))
93b62de8 8718 ((member complete-file '((4) (16)))
20908596 8719 ;; Completing read for file names.
c8d0cf5c 8720 (setq link (org-file-complete-link complete-file)))
20908596
CD
8721 (t
8722 ;; Read link, with completion for stored links.
8723 (with-output-to-temp-buffer "*Org Links*"
c8d0cf5c
CD
8724 (princ "Insert a link.
8725Use TAB to complete link prefixes, then RET for type-specific completion support\n")
20908596
CD
8726 (when org-stored-links
8727 (princ "\nStored links are available with <up>/<down> or M-p/n (most recent with RET):\n\n")
8728 (princ (mapconcat
8729 (lambda (x)
8730 (if (nth 1 x) (concat (car x) " (" (nth 1 x) ")") (car x)))
8731 (reverse org-stored-links) "\n"))))
8732 (let ((cw (selected-window)))
ed21c5c8 8733 (select-window (get-buffer-window "*Org Links*" 'visible))
20908596 8734 (setq truncate-lines t)
c8d0cf5c
CD
8735 (unless (pos-visible-in-window-p (point-max))
8736 (org-fit-window-to-buffer))
8737 (and (window-live-p cw) (select-window cw)))
20908596
CD
8738 ;; Fake a link history, containing the stored links.
8739 (setq tmphist (append (mapcar 'car org-stored-links)
8740 org-insert-link-history))
c8d0cf5c
CD
8741 (setq all-prefixes (append (mapcar 'car org-link-abbrev-alist-local)
8742 (mapcar 'car org-link-abbrev-alist)
8743 org-link-types))
20908596 8744 (unwind-protect
c8d0cf5c
CD
8745 (progn
8746 (setq link
54a0dee5
CD
8747 (let ((org-completion-use-ido nil)
8748 (org-completion-use-iswitchb nil))
c8d0cf5c
CD
8749 (org-completing-read
8750 "Link: "
8751 (append
8752 (mapcar (lambda (x) (list (concat x ":")))
8753 all-prefixes)
8754 (mapcar 'car org-stored-links))
8755 nil nil nil
8756 'tmphist
8757 (car (car org-stored-links)))))
ed21c5c8
CD
8758 (if (not (string-match "\\S-" link))
8759 (error "No link selected"))
c8d0cf5c
CD
8760 (if (or (member link all-prefixes)
8761 (and (equal ":" (substring link -1))
8762 (member (substring link 0 -1) all-prefixes)
8763 (setq link (substring link 0 -1))))
8764 (setq link (org-link-try-special-completion link))))
20908596
CD
8765 (set-window-configuration wcf)
8766 (kill-buffer "*Org Links*"))
8767 (setq entry (assoc link org-stored-links))
8768 (or entry (push link org-insert-link-history))
8769 (if (funcall (if (equal complete-file '(64)) 'not 'identity)
8770 (not org-keep-stored-link-after-insertion))
8771 (setq org-stored-links (delq (assoc link org-stored-links)
8772 org-stored-links)))
8773 (setq desc (or desc (nth 1 entry)))))
8774
8775 (if (string-match org-plain-link-re link)
8776 ;; URL-like link, normalize the use of angular brackets.
8777 (setq link (org-make-link (org-remove-angle-brackets link))))
891f4676 8778
20908596
CD
8779 ;; Check if we are linking to the current file with a search option
8780 ;; If yes, simplify the link by using only the search option.
8781 (when (and buffer-file-name
ce4fdcb9 8782 (string-match "^file:\\(.+?\\)::\\([^>]+\\)" link))
20908596
CD
8783 (let* ((path (match-string 1 link))
8784 (case-fold-search nil)
8785 (search (match-string 2 link)))
8786 (save-match-data
8787 (if (equal (file-truename buffer-file-name) (file-truename path))
8788 ;; We are linking to this same file, with a search option
8789 (setq link search)))))
38f8646b 8790
20908596 8791 ;; Check if we can/should use a relative path. If yes, simplify the link
ed21c5c8
CD
8792 (when (string-match "^\\(file:\\|docview:\\)\\(.*\\)" link)
8793 (let* ((type (match-string 1 link))
8794 (path (match-string 2 link))
20908596
CD
8795 (origpath path)
8796 (case-fold-search nil))
8797 (cond
93b62de8
CD
8798 ((or (eq org-link-file-path-type 'absolute)
8799 (equal complete-file '(16)))
20908596
CD
8800 (setq path (abbreviate-file-name (expand-file-name path))))
8801 ((eq org-link-file-path-type 'noabbrev)
8802 (setq path (expand-file-name path)))
8803 ((eq org-link-file-path-type 'relative)
8804 (setq path (file-relative-name path)))
8805 (t
8806 (save-match-data
8807 (if (string-match (concat "^" (regexp-quote
86fbb8ca
CD
8808 (expand-file-name
8809 (file-name-as-directory
8810 default-directory))))
20908596
CD
8811 (expand-file-name path))
8812 ;; We are linking a file with relative path name.
8813 (setq path (substring (expand-file-name path)
93b62de8
CD
8814 (match-end 0)))
8815 (setq path (abbreviate-file-name (expand-file-name path)))))))
ed21c5c8 8816 (setq link (concat type path))
20908596
CD
8817 (if (equal desc origpath)
8818 (setq desc path))))
38f8646b 8819
20908596
CD
8820 (if org-make-link-description-function
8821 (setq desc (funcall org-make-link-description-function link desc)))
38f8646b 8822
20908596
CD
8823 (setq desc (read-string "Description: " desc))
8824 (unless (string-match "\\S-" desc) (setq desc nil))
8825 (if remove (apply 'delete-region remove))
8826 (insert (org-make-link-string link desc))))
38f8646b 8827
c8d0cf5c
CD
8828(defun org-link-try-special-completion (type)
8829 "If there is completion support for link type TYPE, offer it."
8830 (let ((fun (intern (concat "org-" type "-complete-link"))))
8831 (if (functionp fun)
8832 (funcall fun)
8833 (read-string "Link (no completion support): " (concat type ":")))))
8834
8835(defun org-file-complete-link (&optional arg)
8836 "Create a file link using completion."
8837 (let (file link)
8838 (setq file (read-file-name "File: "))
8839 (let ((pwd (file-name-as-directory (expand-file-name ".")))
8840 (pwd1 (file-name-as-directory (abbreviate-file-name
86fbb8ca 8841 (expand-file-name ".")))))
c8d0cf5c
CD
8842 (cond
8843 ((equal arg '(16))
8844 (setq link (org-make-link
8845 "file:"
8846 (abbreviate-file-name (expand-file-name file)))))
8847 ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
8848 (setq link (org-make-link "file:" (match-string 1 file))))
8849 ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
8850 (expand-file-name file))
8851 (setq link (org-make-link
8852 "file:" (match-string 1 (expand-file-name file)))))
8853 (t (setq link (org-make-link "file:" file)))))
8854 link))
8855
20908596 8856(defun org-completing-read (&rest args)
93b62de8 8857 "Completing-read with SPACE being a normal character."
20908596
CD
8858 (let ((minibuffer-local-completion-map
8859 (copy-keymap minibuffer-local-completion-map)))
8860 (org-defkey minibuffer-local-completion-map " " 'self-insert-command)
0bd48b37 8861 (org-defkey minibuffer-local-completion-map "?" 'self-insert-command)
54a0dee5 8862 (apply 'org-icompleting-read args)))
ce4fdcb9 8863
54a0dee5
CD
8864(defun org-completing-read-no-i (&rest args)
8865 (let (org-completion-use-ido org-completion-use-iswitchb)
9148fdd0
CD
8866 (apply 'org-completing-read args)))
8867
54a0dee5
CD
8868(defun org-iswitchb-completing-read (prompt choices &rest args)
8869 "Use iswitch as a completing-read replacement to choose from choices.
8870PROMPT is a string to prompt with. CHOICES is a list of strings to choose
8871from."
8d642074
CD
8872 (let* ((iswitchb-use-virtual-buffers nil)
8873 (iswitchb-make-buflist-hook
8874 (lambda ()
8875 (setq iswitchb-temp-buflist choices))))
54a0dee5
CD
8876 (iswitchb-read-buffer prompt)))
8877
8878(defun org-icompleting-read (&rest args)
8bfe682a
CD
8879 "Completing-read using `ido-mode' or `iswitchb' speedups if available."
8880 (org-without-partial-completion
8881 (if (and org-completion-use-ido
8882 (fboundp 'ido-completing-read)
8883 (boundp 'ido-mode) ido-mode
8884 (listp (second args)))
8885 (let ((ido-enter-matching-directory nil))
8886 (apply 'ido-completing-read (concat (car args))
8887 (if (consp (car (nth 1 args)))
8888 (mapcar (lambda (x) (car x)) (nth 1 args))
8889 (nth 1 args))
8890 (cddr args)))
8891 (if (and org-completion-use-iswitchb
8892 (boundp 'iswitchb-mode) iswitchb-mode
8893 (listp (second args)))
8894 (apply 'org-iswitchb-completing-read (concat (car args))
8895 (if (consp (car (nth 1 args)))
8896 (mapcar (lambda (x) (car x)) (nth 1 args))
8897 (nth 1 args))
8898 (cddr args))
8899 (apply 'completing-read args)))))
38f8646b 8900
2c3ad40d
CD
8901(defun org-extract-attributes (s)
8902 "Extract the attributes cookie from a string and set as text property."
621f83e4 8903 (let (a attr (start 0) key value)
2c3ad40d
CD
8904 (save-match-data
8905 (when (string-match "{{\\([^}]+\\)}}$" s)
8906 (setq a (match-string 1 s) s (substring s 0 (match-beginning 0)))
8907 (while (string-match "\\([a-zA-Z]+\\)=\"\\([^\"]*\\)\"" a start)
8908 (setq key (match-string 1 a) value (match-string 2 a)
8909 start (match-end 0)
8910 attr (plist-put attr (intern key) value))))
db55f368 8911 (org-add-props s nil 'org-attr attr))
2c3ad40d
CD
8912 s))
8913
c8d0cf5c
CD
8914(defun org-extract-attributes-from-string (tag)
8915 (let (key value attr)
8916 (while (string-match "\\([a-zA-Z]+\\)=\"\\([^\"]*\\)\"\\s-?" tag)
8917 (setq key (match-string 1 tag) value (match-string 2 tag)
8918 tag (replace-match "" t t tag)
8919 attr (plist-put attr (intern key) value)))
8920 (cons tag attr)))
8921
2c3ad40d
CD
8922(defun org-attributes-to-string (plist)
8923 "Format a property list into an HTML attribute list."
8924 (let ((s "") key value)
8925 (while plist
8926 (setq key (pop plist) value (pop plist))
db55f368
CD
8927 (and value
8928 (setq s (concat s " " (symbol-name key) "=\"" value "\""))))
2c3ad40d
CD
8929 s))
8930
20908596 8931;;; Opening/following a link
03f3cf35 8932
20908596 8933(defvar org-link-search-failed nil)
38f8646b 8934
ed21c5c8
CD
8935(defvar org-open-link-functions nil
8936 "Hook for functions finding a plain text link.
8937These functions must take a single argument, the link content.
8938They will be called for links that look like [[link text][description]]
8939when LINK TEXT does not have a protocol like \"http:\" and does not look
8940like a filename (e.g. \"./blue.png\").
8941
8942These functions will be called *before* Org attempts to resolve the
8943link by doing text searches in the current buffer - so if you want a
8944link \"[[target]]\" to still find \"<<target>>\", your function should
8945handle this as a special case.
8946
8947When the function does handle the link, it must return a non-nil value.
8948If it decides that it is not responsible for this link, it must return
8949nil to indicate that that Org-mode can continue with other options
8950like exact and fuzzy text search.")
8951
20908596
CD
8952(defun org-next-link ()
8953 "Move forward to the next link.
8954If the link is in hidden text, expose it."
8955 (interactive)
8956 (when (and org-link-search-failed (eq this-command last-command))
8957 (goto-char (point-min))
8958 (message "Link search wrapped back to beginning of buffer"))
8959 (setq org-link-search-failed nil)
8960 (let* ((pos (point))
8961 (ct (org-context))
8962 (a (assoc :link ct)))
8963 (if a (goto-char (nth 2 a)))
8964 (if (re-search-forward org-any-link-re nil t)
8965 (progn
8966 (goto-char (match-beginning 0))
8967 (if (org-invisible-p) (org-show-context)))
8968 (goto-char pos)
8969 (setq org-link-search-failed t)
8970 (error "No further link found"))))
38f8646b 8971
20908596
CD
8972(defun org-previous-link ()
8973 "Move backward to the previous link.
8974If the link is in hidden text, expose it."
7d58338e 8975 (interactive)
20908596
CD
8976 (when (and org-link-search-failed (eq this-command last-command))
8977 (goto-char (point-max))
8978 (message "Link search wrapped back to end of buffer"))
8979 (setq org-link-search-failed nil)
8980 (let* ((pos (point))
8981 (ct (org-context))
8982 (a (assoc :link ct)))
8983 (if a (goto-char (nth 1 a)))
8984 (if (re-search-backward org-any-link-re nil t)
8985 (progn
8986 (goto-char (match-beginning 0))
8987 (if (org-invisible-p) (org-show-context)))
8988 (goto-char pos)
8989 (setq org-link-search-failed t)
8990 (error "No further link found"))))
7d58338e 8991
ce4fdcb9
CD
8992(defun org-translate-link (s)
8993 "Translate a link string if a translation function has been defined."
8994 (if (and org-link-translation-function
8995 (fboundp org-link-translation-function)
8996 (string-match "\\([a-zA-Z0-9]+\\):\\(.*\\)" s))
8997 (progn
8998 (setq s (funcall org-link-translation-function
8999 (match-string 1) (match-string 2)))
9000 (concat (car s) ":" (cdr s)))
9001 s))
9002
9003(defun org-translate-link-from-planner (type path)
9004 "Translate a link from Emacs Planner syntax so that Org can follow it.
9005This is still an experimental function, your mileage may vary."
9006 (cond
9007 ((member type '("http" "https" "news" "ftp"))
9008 ;; standard Internet links are the same.
9009 nil)
9010 ((and (equal type "irc") (string-match "^//" path))
9011 ;; Planner has two / at the beginning of an irc link, we have 1.
9012 ;; We should have zero, actually....
9013 (setq path (substring path 1)))
9014 ((and (equal type "lisp") (string-match "^/" path))
9015 ;; Planner has a slash, we do not.
9016 (setq type "elisp" path (substring path 1)))
9017 ((string-match "^//\\(.?*\\)/\\(<.*>\\)$" path)
8bfe682a 9018 ;; A typical message link. Planner has the id after the final slash,
ce4fdcb9
CD
9019 ;; we separate it with a hash mark
9020 (setq path (concat (match-string 1 path) "#"
9021 (org-remove-angle-brackets (match-string 2 path)))))
9022 )
9023 (cons type path))
9024
20908596
CD
9025(defun org-find-file-at-mouse (ev)
9026 "Open file link or URL at mouse."
9027 (interactive "e")
9028 (mouse-set-point ev)
9029 (org-open-at-point 'in-emacs))
7d58338e 9030
20908596
CD
9031(defun org-open-at-mouse (ev)
9032 "Open file link or URL at mouse."
9033 (interactive "e")
9034 (mouse-set-point ev)
ce4fdcb9
CD
9035 (if (eq major-mode 'org-agenda-mode)
9036 (org-agenda-copy-local-variable 'org-link-abbrev-alist-local))
20908596 9037 (org-open-at-point))
38f8646b 9038
20908596
CD
9039(defvar org-window-config-before-follow-link nil
9040 "The window configuration before following a link.
9041This is saved in case the need arises to restore it.")
38f8646b 9042
20908596
CD
9043(defvar org-open-link-marker (make-marker)
9044 "Marker pointing to the location where `org-open-at-point; was called.")
9045
9046;;;###autoload
9047(defun org-open-at-point-global ()
9048 "Follow a link like Org-mode does.
9049This command can be called in any mode to follow a link that has
9050Org-mode syntax."
9051 (interactive)
9052 (org-run-like-in-org-mode 'org-open-at-point))
9053
9054;;;###autoload
54a0dee5 9055(defun org-open-link-from-string (s &optional arg reference-buffer)
20908596
CD
9056 "Open a link in the string S, as if it was in Org-mode."
9057 (interactive "sLink: \nP")
54a0dee5 9058 (let ((reference-buffer (or reference-buffer (current-buffer))))
c8d0cf5c
CD
9059 (with-temp-buffer
9060 (let ((org-inhibit-startup t))
9061 (org-mode)
9062 (insert s)
9063 (goto-char (point-min))
ed21c5c8
CD
9064 (when reference-buffer
9065 (setq org-link-abbrev-alist-local
9066 (with-current-buffer reference-buffer
9067 org-link-abbrev-alist-local)))
c8d0cf5c 9068 (org-open-at-point arg reference-buffer)))))
20908596 9069
afe98dfa
CD
9070(defvar org-open-at-point-functions nil
9071 "Hook that is run when following a link at point.
9072
9073Functions in this hook must return t if they identify and follow
9074a link at point. If they don't find anything interesting at point,
9075they must return nil.")
9076
c8d0cf5c 9077(defun org-open-at-point (&optional in-emacs reference-buffer)
20908596
CD
9078 "Open link at or after point.
9079If there is no link at point, this function will search forward up to
c8d0cf5c 9080the end of the current line.
20908596 9081Normally, files will be opened by an appropriate application. If the
93b62de8
CD
9082optional argument IN-EMACS is non-nil, Emacs will visit the file.
9083With a double prefix argument, try to open outside of Emacs, in the
9084application the system uses for this file type."
20908596 9085 (interactive "P")
86fbb8ca
CD
9086 ;; if in a code block, then open the block's results
9087 (unless (call-interactively #'org-babel-open-src-block-result)
20908596
CD
9088 (org-load-modules-maybe)
9089 (move-marker org-open-link-marker (point))
9090 (setq org-window-config-before-follow-link (current-window-configuration))
9091 (org-remove-occur-highlights nil nil t)
0bd48b37 9092 (cond
54a0dee5
CD
9093 ((and (org-on-heading-p)
9094 (not (org-in-regexp
f924a367 9095 (concat org-plain-link-re "\\|"
54a0dee5
CD
9096 org-bracket-link-regexp "\\|"
9097 org-angle-link-re "\\|"
ed21c5c8
CD
9098 "[ \t]:[^ \t\n]+:[ \t]*$")))
9099 (not (get-text-property (point) 'org-linked-text)))
8bfe682a
CD
9100 (or (org-offer-links-in-entry in-emacs)
9101 (progn (require 'org-attach) (org-attach-reveal 'if-exists))))
afe98dfa 9102 ((run-hook-with-args-until-success 'org-open-at-point-functions))
0bd48b37 9103 ((org-at-timestamp-p t) (org-follow-timestamp-link))
acedf35c
CD
9104 ((and (or (org-footnote-at-reference-p) (org-footnote-at-definition-p))
9105 (not (org-in-regexp org-bracket-link-regexp)))
0bd48b37 9106 (org-footnote-action))
c8d0cf5c 9107 (t
20908596
CD
9108 (let (type path link line search (pos (point)))
9109 (catch 'match
9110 (save-excursion
9111 (skip-chars-forward "^]\n\r")
ed21c5c8 9112 (when (org-in-regexp org-bracket-link-regexp 1)
2c3ad40d
CD
9113 (setq link (org-extract-attributes
9114 (org-link-unescape (org-match-string-no-properties 1))))
20908596
CD
9115 (while (string-match " *\n *" link)
9116 (setq link (replace-match " " t t link)))
9117 (setq link (org-link-expand-abbrev link))
2c3ad40d
CD
9118 (cond
9119 ((or (file-name-absolute-p link)
9120 (string-match "^\\.\\.?/" link))
9121 (setq type "file" path link))
ce4fdcb9 9122 ((string-match org-link-re-with-space3 link)
2c3ad40d
CD
9123 (setq type (match-string 1 link) path (match-string 2 link)))
9124 (t (setq type "thisfile" path link)))
20908596 9125 (throw 'match t)))
8c6fb58b 9126
20908596
CD
9127 (when (get-text-property (point) 'org-linked-text)
9128 (setq type "thisfile"
9129 pos (if (get-text-property (1+ (point)) 'org-linked-text)
9130 (1+ (point)) (point))
9131 path (buffer-substring
9132 (previous-single-property-change pos 'org-linked-text)
9133 (next-single-property-change pos 'org-linked-text)))
9134 (throw 'match t))
8c6fb58b 9135
20908596
CD
9136 (save-excursion
9137 (when (or (org-in-regexp org-angle-link-re)
9138 (org-in-regexp org-plain-link-re))
9139 (setq type (match-string 1) path (match-string 2))
9140 (throw 'match t)))
20908596 9141 (save-excursion
afe98dfa 9142 (when (org-in-regexp (org-re "\\(:[[:alnum:]_@#%:]+\\):[ \t]*$"))
20908596
CD
9143 (setq type "tags"
9144 path (match-string 1))
9145 (while (string-match ":" path)
9146 (setq path (replace-match "+" t t path)))
c8d0cf5c
CD
9147 (throw 'match t)))
9148 (when (org-in-regexp "<\\([^><\n]+\\)>")
9149 (setq type "tree-match"
9150 path (match-string 1))
9151 (throw 'match t)))
20908596
CD
9152 (unless path
9153 (error "No link found"))
c8d0cf5c
CD
9154
9155 ;; switch back to reference buffer
9156 ;; needed when if called in a temporary buffer through
9157 ;; org-open-link-from-string
54a0dee5
CD
9158 (with-current-buffer (or reference-buffer (current-buffer))
9159
9160 ;; Remove any trailing spaces in path
9161 (if (string-match " +\\'" path)
9162 (setq path (replace-match "" t t path)))
9163 (if (and org-link-translation-function
9164 (fboundp org-link-translation-function))
9165 ;; Check if we need to translate the link
9166 (let ((tmp (funcall org-link-translation-function type path)))
9167 (setq type (car tmp) path (cdr tmp))))
f924a367 9168
54a0dee5 9169 (cond
f924a367 9170
54a0dee5
CD
9171 ((assoc type org-link-protocols)
9172 (funcall (nth 1 (assoc type org-link-protocols)) path))
f924a367 9173
54a0dee5
CD
9174 ((equal type "mailto")
9175 (let ((cmd (car org-link-mailto-program))
9176 (args (cdr org-link-mailto-program)) args1
9177 (address path) (subject "") a)
9178 (if (string-match "\\(.*\\)::\\(.*\\)" path)
9179 (setq address (match-string 1 path)
9180 subject (org-link-escape (match-string 2 path))))
9181 (while args
9182 (cond
9183 ((not (stringp (car args))) (push (pop args) args1))
9184 (t (setq a (pop args))
9185 (if (string-match "%a" a)
9186 (setq a (replace-match address t t a)))
9187 (if (string-match "%s" a)
9188 (setq a (replace-match subject t t a)))
9189 (push a args1))))
9190 (apply cmd (nreverse args1))))
f924a367 9191
54a0dee5
CD
9192 ((member type '("http" "https" "ftp" "news"))
9193 (browse-url (concat type ":" (org-link-escape
9194 path org-link-escape-chars-browser))))
f924a367 9195
86fbb8ca
CD
9196 ((string= type "doi")
9197 (browse-url (concat "http://dx.doi.org/"
9198 (org-link-escape
9199 path org-link-escape-chars-browser))))
9200
54a0dee5
CD
9201 ((member type '("message"))
9202 (browse-url (concat type ":" path)))
f924a367 9203
54a0dee5
CD
9204 ((string= type "tags")
9205 (org-tags-view in-emacs path))
f924a367 9206
54a0dee5
CD
9207 ((string= type "tree-match")
9208 (org-occur (concat "\\[" (regexp-quote path) "\\]")))
f924a367 9209
54a0dee5
CD
9210 ((string= type "file")
9211 (if (string-match "::\\([0-9]+\\)\\'" path)
9212 (setq line (string-to-number (match-string 1 path))
9213 path (substring path 0 (match-beginning 0)))
9214 (if (string-match "::\\(.+\\)\\'" path)
9215 (setq search (match-string 1 path)
9216 path (substring path 0 (match-beginning 0)))))
9217 (if (string-match "[*?{]" (file-name-nondirectory path))
9218 (dired path)
9219 (org-open-file path in-emacs line search)))
f924a367 9220
54a0dee5
CD
9221 ((string= type "shell")
9222 (let ((cmd path))
9223 (if (or (not org-confirm-shell-link-function)
9224 (funcall org-confirm-shell-link-function
9225 (format "Execute \"%s\" in shell? "
9226 (org-add-props cmd nil
9227 'face 'org-warning))))
9228 (progn
9229 (message "Executing %s" cmd)
9230 (shell-command cmd))
9231 (error "Abort"))))
f924a367 9232
54a0dee5
CD
9233 ((string= type "elisp")
9234 (let ((cmd path))
9235 (if (or (not org-confirm-elisp-link-function)
9236 (funcall org-confirm-elisp-link-function
9237 (format "Execute \"%s\" as elisp? "
9238 (org-add-props cmd nil
9239 'face 'org-warning))))
9240 (message "%s => %s" cmd
9241 (if (equal (string-to-char cmd) ?\()
9242 (eval (read cmd))
9243 (call-interactively (read cmd))))
9244 (error "Abort"))))
f924a367 9245
ed21c5c8
CD
9246 ((and (string= type "thisfile")
9247 (run-hook-with-args-until-success
9248 'org-open-link-functions path)))
9249
9250 ((string= type "thisfile")
9251 (if in-emacs
9252 (switch-to-buffer-other-window
9253 (org-get-buffer-for-internal-link (current-buffer)))
9254 (org-mark-ring-push))
9255 (let ((cmd `(org-link-search
9256 ,path
9257 ,(cond ((equal in-emacs '(4)) 'occur)
9258 ((equal in-emacs '(16)) 'org-occur)
9259 (t nil))
9260 ,pos)))
9261 (condition-case nil (eval cmd)
9262 (error (progn (widen) (eval cmd))))))
9263
54a0dee5 9264 (t
8d642074
CD
9265 (browse-url-at-point)))))))
9266 (move-marker org-open-link-marker nil)
86fbb8ca 9267 (run-hook-with-args 'org-follow-link-hook)))
54a0dee5 9268
8d642074 9269(defun org-offer-links-in-entry (&optional nth zero)
8bfe682a 9270 "Offer links in the current entry and follow the selected link.
54a0dee5 9271If there is only one link, follow it immediately as well.
8d642074
CD
9272If NTH is an integer, immediately pick the NTH link found.
9273If ZERO is a string, check also this string for a link, and if
9274there is one, offer it as link number zero."
54a0dee5
CD
9275 (let ((re (concat "\\(" org-bracket-link-regexp "\\)\\|"
9276 "\\(" org-angle-link-re "\\)\\|"
9277 "\\(" org-plain-link-re "\\)"))
9278 (cnt ?0)
9279 (in-emacs (if (integerp nth) nil nth))
8d642074
CD
9280 have-zero end links link c)
9281 (when (and (stringp zero) (string-match org-bracket-link-regexp zero))
9282 (push (match-string 0 zero) links)
9283 (setq cnt (1- cnt) have-zero t))
54a0dee5
CD
9284 (save-excursion
9285 (org-back-to-heading t)
9286 (setq end (save-excursion (outline-next-heading) (point)))
9287 (while (re-search-forward re end t)
9288 (push (match-string 0) links))
9289 (setq links (org-uniquify (reverse links))))
03f3cf35 9290
54a0dee5 9291 (cond
8bfe682a
CD
9292 ((null links)
9293 (message "No links"))
54a0dee5 9294 ((equal (length links) 1)
ed21c5c8 9295 (setq link (list (car links))))
8d642074
CD
9296 ((and (integerp nth) (>= (length links) (if have-zero (1+ nth) nth)))
9297 (setq link (nth (if have-zero nth (1- nth)) links)))
54a0dee5
CD
9298 (t ; we have to select a link
9299 (save-excursion
9300 (save-window-excursion
9301 (delete-other-windows)
9302 (with-output-to-temp-buffer "*Select Link*"
54a0dee5
CD
9303 (mapc (lambda (l)
9304 (if (not (string-match org-bracket-link-regexp l))
9305 (princ (format "[%c] %s\n" (incf cnt)
9306 (org-remove-angle-brackets l)))
9307 (if (match-end 3)
9308 (princ (format "[%c] %s (%s)\n" (incf cnt)
9309 (match-string 3 l) (match-string 1 l)))
9310 (princ (format "[%c] %s\n" (incf cnt)
9311 (match-string 1 l))))))
9312 links))
9313 (org-fit-window-to-buffer (get-buffer-window "*Select Link*"))
ed21c5c8 9314 (message "Select link to open, RET to open all:")
54a0dee5
CD
9315 (setq c (read-char-exclusive))
9316 (and (get-buffer "*Select Link*") (kill-buffer "*Select Link*"))))
9317 (when (equal c ?q) (error "Abort"))
ed21c5c8
CD
9318 (if (equal c ?\C-m)
9319 (setq link links)
9320 (setq nth (- c ?0))
9321 (if have-zero (setq nth (1+ nth)))
9322 (unless (and (integerp nth) (>= (length links) nth))
9323 (error "Invalid link selection"))
9324 (setq link (list (nth (1- nth) links))))))
8bfe682a 9325 (if link
ed21c5c8
CD
9326 (let ((buf (current-buffer)))
9327 (dolist (l link)
9328 (org-open-link-from-string l in-emacs buf))
9329 t)
8bfe682a 9330 nil)))
fbe6c10d 9331
ed21c5c8
CD
9332;; Add special file links that specify the way of opening
9333
9334(org-add-link-type "file+sys" 'org-open-file-with-system)
9335(org-add-link-type "file+emacs" 'org-open-file-with-emacs)
9336(defun org-open-file-with-system (path)
86fbb8ca 9337 "Open file at PATH using the system way of opening it."
ed21c5c8
CD
9338 (org-open-file path 'system))
9339(defun org-open-file-with-emacs (path)
86fbb8ca 9340 "Open file at PATH in Emacs."
ed21c5c8
CD
9341 (org-open-file path 'emacs))
9342(defun org-remove-file-link-modifiers ()
9343 "Remove the file link modifiers in `file+sys:' and `file+emacs:' links."
9344 (goto-char (point-min))
9345 (while (re-search-forward "\\<file\\+\\(sys\\|emacs\\):" nil t)
9346 (org-if-unprotected
9347 (replace-match "file:" t t))))
9348(eval-after-load "org-exp"
9349 '(add-hook 'org-export-preprocess-before-normalizing-links-hook
9350 'org-remove-file-link-modifiers))
9351
20908596 9352;;;; Time estimates
fbe6c10d 9353
20908596
CD
9354(defun org-get-effort (&optional pom)
9355 "Get the effort estimate for the current entry."
9356 (org-entry-get pom org-effort-property))
2a57416f 9357
20908596 9358;;; File search
38f8646b 9359
20908596
CD
9360(defvar org-create-file-search-functions nil
9361 "List of functions to construct the right search string for a file link.
9362These functions are called in turn with point at the location to
9363which the link should point.
03f3cf35 9364
20908596 9365A function in the hook should first test if it would like to
86fbb8ca
CD
9366handle this file type, for example by checking the `major-mode'
9367or the file extension. If it decides not to handle this file, it
20908596
CD
9368should just return nil to give other functions a chance. If it
9369does handle the file, it must return the search string to be used
9370when following the link. The search string will be part of the
9371file link, given after a double colon, and `org-open-at-point'
9372will automatically search for it. If special measures must be
9373taken to make the search successful, another function should be
9374added to the companion hook `org-execute-file-search-functions',
9375which see.
7d58338e 9376
20908596
CD
9377A function in this hook may also use `setq' to set the variable
9378`description' to provide a suggestion for the descriptive text to
9379be used for this link when it gets inserted into an Org-mode
9380buffer with \\[org-insert-link].")
9381
9382(defvar org-execute-file-search-functions nil
9383 "List of functions to execute a file search triggered by a link.
9384
9385Functions added to this hook must accept a single argument, the
9386search string that was part of the file link, the part after the
9387double colon. The function must first check if it would like to
86fbb8ca
CD
9388handle this search, for example by checking the `major-mode' or
9389the file extension. If it decides not to handle this search, it
20908596
CD
9390should just return nil to give other functions a chance. If it
9391does handle the search, it must return a non-nil value to keep
9392other functions from trying.
9393
9394Each function can access the current prefix argument through the
9395variable `current-prefix-argument'. Note that a single prefix is
9396used to force opening a link in Emacs, so it may be good to only
9397use a numeric or double prefix to guide the search function.
9398
9399In case this is needed, a function in this hook can also restore
9400the window configuration before `org-open-at-point' was called using:
9401
9402 (set-window-configuration org-window-config-before-follow-link)")
9403
afe98dfa 9404(defvar org-link-search-inhibit-query nil) ;; dynamically scoped
20908596
CD
9405(defun org-link-search (s &optional type avoid-pos)
9406 "Search for a link search option.
9407If S is surrounded by forward slashes, it is interpreted as a
9408regular expression. In org-mode files, this will create an `org-occur'
9409sparse tree. In ordinary files, `occur' will be used to list matches.
9410If the current buffer is in `dired-mode', grep will be used to search
9411in all files. If AVOID-POS is given, ignore matches near that position."
9412 (let ((case-fold-search t)
9413 (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " "))
9414 (markers (concat "\\(?:" (mapconcat (lambda (x) (regexp-quote (car x)))
9415 (append '(("") (" ") ("\t") ("\n"))
9416 org-emphasis-alist)
9417 "\\|") "\\)"))
9418 (pos (point))
9419 (pre nil) (post nil)
9420 words re0 re1 re2 re3 re4_ re4 re5 re2a re2a_ reall)
9421 (cond
afe98dfa 9422 ;; First check if there are any special search functions
20908596
CD
9423 ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
9424 ;; Now try the builtin stuff
c8d0cf5c
CD
9425 ((and (equal (string-to-char s0) ?#)
9426 (> (length s0) 1)
9427 (save-excursion
9428 (goto-char (point-min))
9429 (and
9430 (re-search-forward
9431 (concat "^[ \t]*:CUSTOM_ID:[ \t]+" (regexp-quote (substring s0 1)) "[ \t]*$") nil t)
9432 (setq type 'dedicated
9433 pos (match-beginning 0))))
9434 ;; There is an exact target for this
9435 (goto-char pos)
9436 (org-back-to-heading t)))
20908596
CD
9437 ((save-excursion
9438 (goto-char (point-min))
9439 (and
9440 (re-search-forward
9441 (concat "<<" (regexp-quote s0) ">>") nil t)
9442 (setq type 'dedicated
9443 pos (match-beginning 0))))
9444 ;; There is an exact target for this
9445 (goto-char pos))
0bd48b37
CD
9446 ((and (string-match "^(\\(.*\\))$" s0)
9447 (save-excursion
9448 (goto-char (point-min))
9449 (and
9450 (re-search-forward
9451 (concat "[^[]" (regexp-quote
9452 (format org-coderef-label-format
9453 (match-string 1 s0))))
9454 nil t)
9455 (setq type 'dedicated
9456 pos (1+ (match-beginning 0))))))
9457 ;; There is a coderef target for this
9458 (goto-char pos))
20908596
CD
9459 ((string-match "^/\\(.*\\)/$" s)
9460 ;; A regular expression
9461 (cond
9462 ((org-mode-p)
9463 (org-occur (match-string 1 s)))
9464 ;;((eq major-mode 'dired-mode)
9465 ;; (grep (concat "grep -n -e '" (match-string 1 s) "' *")))
9466 (t (org-do-occur (match-string 1 s)))))
afe98dfa
CD
9467 ((and (org-mode-p) org-link-search-must-match-exact-headline)
9468 (and (equal (string-to-char s) ?*) (setq s (substring s 1)))
9469 (goto-char (point-min))
9470 (cond
9471 ((let (case-fold-search)
9472 (re-search-forward (format org-complex-heading-regexp-format
9473 (regexp-quote s))
9474 nil t))
9475 ;; OK, found a match
9476 (setq type 'dedicated)
9477 (goto-char (match-beginning 0)))
9478 ((and (not org-link-search-inhibit-query)
9479 (eq org-link-search-must-match-exact-headline 'query-to-create)
9480 (y-or-n-p "No match - create this as a new heading? "))
9481 (goto-char (point-max))
9482 (or (bolp) (newline))
9483 (insert "* " s "\n")
9484 (beginning-of-line 0))
9485 (t
9486 (goto-char pos)
9487 (error "No match"))))
20908596 9488 (t
afe98dfa 9489 ;; A normal search string
20908596
CD
9490 (when (equal (string-to-char s) ?*)
9491 ;; Anchor on headlines, post may include tags.
9492 (setq pre "^\\*+[ \t]+\\(?:\\sw+\\)?[ \t]*"
afe98dfa 9493 post (org-re "[ \t]*\\(?:[ \t]+:[[:alnum:]_@#%:+]:[ \t]*\\)?$")
20908596
CD
9494 s (substring s 1)))
9495 (remove-text-properties
9496 0 (length s)
9497 '(face nil mouse-face nil keymap nil fontified nil) s)
9498 ;; Make a series of regular expressions to find a match
9499 (setq words (org-split-string s "[ \n\r\t]+")
9500
9501 re0 (concat "\\(<<" (regexp-quote s0) ">>\\)")
9502 re2 (concat markers "\\(" (mapconcat 'downcase words "[ \t]+")
9503 "\\)" markers)
9504 re2a_ (concat "\\(" (mapconcat 'downcase words "[ \t\r\n]+") "\\)[ \t\r\n]")
9505 re2a (concat "[ \t\r\n]" re2a_)
9506 re4_ (concat "\\(" (mapconcat 'downcase words "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
9507 re4 (concat "[^a-zA-Z_]" re4_)
9508
9509 re1 (concat pre re2 post)
9510 re3 (concat pre (if pre re4_ re4) post)
9511 re5 (concat pre ".*" re4)
9512 re2 (concat pre re2)
9513 re2a (concat pre (if pre re2a_ re2a))
9514 re4 (concat pre (if pre re4_ re4))
9515 reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2
9516 "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\("
9517 re5 "\\)"
9518 ))
9519 (cond
9520 ((eq type 'org-occur) (org-occur reall))
9521 ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
9522 (t (goto-char (point-min))
9523 (setq type 'fuzzy)
9524 (if (or (and (org-search-not-self 1 re0 nil t) (setq type 'dedicated))
9525 (org-search-not-self 1 re1 nil t)
9526 (org-search-not-self 1 re2 nil t)
9527 (org-search-not-self 1 re2a nil t)
9528 (org-search-not-self 1 re3 nil t)
9529 (org-search-not-self 1 re4 nil t)
9530 (org-search-not-self 1 re5 nil t)
9531 )
9532 (goto-char (match-beginning 1))
9533 (goto-char pos)
afe98dfa 9534 (error "No match"))))))
20908596
CD
9535 (and (org-mode-p) (org-show-context 'link-search))
9536 type))
9537
9538(defun org-search-not-self (group &rest args)
9539 "Execute `re-search-forward', but only accept matches that do not
9540enclose the position of `org-open-link-marker'."
9541 (let ((m org-open-link-marker))
9542 (catch 'exit
9543 (while (apply 're-search-forward args)
9544 (unless (get-text-property (match-end group) 'intangible) ; Emacs 21
9545 (goto-char (match-end group))
9546 (if (and (or (not (eq (marker-buffer m) (current-buffer)))
9547 (> (match-beginning 0) (marker-position m))
9548 (< (match-end 0) (marker-position m)))
9549 (save-match-data
9550 (or (not (org-in-regexp
9551 org-bracket-link-analytic-regexp 1))
9552 (not (match-end 4)) ; no description
9553 (and (<= (match-beginning 4) (point))
9554 (>= (match-end 4) (point))))))
9555 (throw 'exit (point))))))))
7d58338e 9556
20908596
CD
9557(defun org-get-buffer-for-internal-link (buffer)
9558 "Return a buffer to be used for displaying the link target of internal links."
9559 (cond
9560 ((not org-display-internal-link-with-indirect-buffer)
9561 buffer)
9562 ((string-match "(Clone)$" (buffer-name buffer))
9563 (message "Buffer is already a clone, not making another one")
9564 ;; we also do not modify visibility in this case
9565 buffer)
9566 (t ; make a new indirect buffer for displaying the link
9567 (let* ((bn (buffer-name buffer))
9568 (ibn (concat bn "(Clone)"))
9569 (ib (or (get-buffer ibn) (make-indirect-buffer buffer ibn 'clone))))
9570 (with-current-buffer ib (org-overview))
9571 ib))))
7d58338e 9572
20908596
CD
9573(defun org-do-occur (regexp &optional cleanup)
9574 "Call the Emacs command `occur'.
9575If CLEANUP is non-nil, remove the printout of the regular expression
9576in the *Occur* buffer. This is useful if the regex is long and not useful
9577to read."
9578 (occur regexp)
9579 (when cleanup
9580 (let ((cwin (selected-window)) win beg end)
9581 (when (setq win (get-buffer-window "*Occur*"))
9582 (select-window win))
7d58338e 9583 (goto-char (point-min))
20908596
CD
9584 (when (re-search-forward "match[a-z]+" nil t)
9585 (setq beg (match-end 0))
9586 (if (re-search-forward "^[ \t]*[0-9]+" nil t)
9587 (setq end (1- (match-beginning 0)))))
9588 (and beg end (let ((inhibit-read-only t)) (delete-region beg end)))
9589 (goto-char (point-min))
9590 (select-window cwin))))
7d58338e 9591
20908596 9592;;; The mark ring for links jumps
48aaad2d 9593
20908596
CD
9594(defvar org-mark-ring nil
9595 "Mark ring for positions before jumps in Org-mode.")
9596(defvar org-mark-ring-last-goto nil
9597 "Last position in the mark ring used to go back.")
9598;; Fill and close the ring
9599(setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is reloaded
9600(loop for i from 1 to org-mark-ring-length do
9601 (push (make-marker) org-mark-ring))
9602(setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring)
9603 org-mark-ring)
9604
9605(defun org-mark-ring-push (&optional pos buffer)
9606 "Put the current position or POS into the mark ring and rotate it."
48aaad2d 9607 (interactive)
20908596
CD
9608 (setq pos (or pos (point)))
9609 (setq org-mark-ring (nthcdr (1- org-mark-ring-length) org-mark-ring))
9610 (move-marker (car org-mark-ring)
9611 (or pos (point))
9612 (or buffer (current-buffer)))
9613 (message "%s"
9614 (substitute-command-keys
9615 "Position saved to mark ring, go back with \\[org-mark-ring-goto].")))
48aaad2d 9616
20908596
CD
9617(defun org-mark-ring-goto (&optional n)
9618 "Jump to the previous position in the mark ring.
9619With prefix arg N, jump back that many stored positions. When
9620called several times in succession, walk through the entire ring.
9621Org-mode commands jumping to a different position in the current file,
9622or to another Org-mode file, automatically push the old position
9623onto the ring."
9624 (interactive "p")
9625 (let (p m)
9626 (if (eq last-command this-command)
9627 (setq p (nthcdr n (or org-mark-ring-last-goto org-mark-ring)))
9628 (setq p org-mark-ring))
9629 (setq org-mark-ring-last-goto p)
9630 (setq m (car p))
9631 (switch-to-buffer (marker-buffer m))
9632 (goto-char m)
9633 (if (or (org-invisible-p) (org-invisible-p2)) (org-show-context 'mark-goto))))
fbe6c10d 9634
20908596
CD
9635(defun org-remove-angle-brackets (s)
9636 (if (equal (substring s 0 1) "<") (setq s (substring s 1)))
9637 (if (equal (substring s -1) ">") (setq s (substring s 0 -1)))
9638 s)
9639(defun org-add-angle-brackets (s)
9640 (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s)))
9641 (if (equal (substring s -1) ">") nil (setq s (concat s ">")))
9642 s)
b349f79f
CD
9643(defun org-remove-double-quotes (s)
9644 (if (equal (substring s 0 1) "\"") (setq s (substring s 1)))
9645 (if (equal (substring s -1) "\"") (setq s (substring s 0 -1)))
9646 s)
7d58338e 9647
20908596 9648;;; Following specific links
48aaad2d 9649
20908596
CD
9650(defun org-follow-timestamp-link ()
9651 (cond
9652 ((org-at-date-range-p t)
9653 (let ((org-agenda-start-on-weekday)
9654 (t1 (match-string 1))
9655 (t2 (match-string 2)))
9656 (setq t1 (time-to-days (org-time-string-to-time t1))
9657 t2 (time-to-days (org-time-string-to-time t2)))
9658 (org-agenda-list nil t1 (1+ (- t2 t1)))))
9659 ((org-at-timestamp-p t)
9660 (org-agenda-list nil (time-to-days (org-time-string-to-time
9661 (substring (match-string 1) 0 10)))
9662 1))
9663 (t (error "This should not happen"))))
48aaad2d 9664
03f3cf35 9665
20908596
CD
9666;;; Following file links
9667(defvar org-wait nil)
9668(defun org-open-file (path &optional in-emacs line search)
9669 "Open the file at PATH.
9670First, this expands any special file name abbreviations. Then the
9671configuration variable `org-file-apps' is checked if it contains an
9672entry for this file type, and if yes, the corresponding command is launched.
93b62de8 9673
20908596 9674If no application is found, Emacs simply visits the file.
93b62de8
CD
9675
9676With optional prefix argument IN-EMACS, Emacs will visit the file.
86fbb8ca
CD
9677With a double \\[universal-argument] \\[universal-argument] \
9678prefix arg, Org tries to avoid opening in Emacs
ed21c5c8 9679and to use an external application to visit the file.
93b62de8 9680
86fbb8ca
CD
9681Optional LINE specifies a line to go to, optional SEARCH a string
9682to search for. If LINE or SEARCH is given, the file will be
9683opened in Emacs, unless an entry from org-file-apps that makes
9684use of groups in a regexp matches.
20908596 9685If the file does not exist, an error is thrown."
20908596
CD
9686 (let* ((file (if (equal path "")
9687 buffer-file-name
9688 (substitute-in-file-name (expand-file-name path))))
86fbb8ca
CD
9689 (file-apps (append org-file-apps (org-default-apps)))
9690 (apps (org-remove-if
9691 'org-file-apps-entry-match-against-dlink-p file-apps))
9692 (apps-dlink (org-remove-if-not
9693 'org-file-apps-entry-match-against-dlink-p file-apps))
20908596
CD
9694 (remp (and (assq 'remote apps) (org-file-remote-p file)))
9695 (dirp (if remp nil (file-directory-p file)))
2c3ad40d
CD
9696 (file (if (and dirp org-open-directory-means-index-dot-org)
9697 (concat (file-name-as-directory file) "index.org")
9698 file))
621f83e4 9699 (a-m-a-p (assq 'auto-mode apps))
20908596 9700 (dfile (downcase file))
ed21c5c8
CD
9701 ;; reconstruct the original file: link from the PATH, LINE and SEARCH args
9702 (link (cond ((and (eq line nil)
9703 (eq search nil))
9704 file)
9705 (line
9706 (concat file "::" (number-to-string line)))
9707 (search
9708 (concat file "::" search))))
9709 (dlink (downcase link))
20908596
CD
9710 (old-buffer (current-buffer))
9711 (old-pos (point))
9712 (old-mode major-mode)
ed21c5c8 9713 ext cmd link-match-data)
20908596
CD
9714 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
9715 (setq ext (match-string 1 dfile))
9716 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
9717 (setq ext (match-string 1 dfile))))
93b62de8 9718 (cond
ed21c5c8 9719 ((member in-emacs '((16) system))
93b62de8
CD
9720 (setq cmd (cdr (assoc 'system apps))))
9721 (in-emacs (setq cmd 'emacs))
9722 (t
20908596
CD
9723 (setq cmd (or (and remp (cdr (assoc 'remote apps)))
9724 (and dirp (cdr (assoc 'directory apps)))
86fbb8ca
CD
9725 ; first, try matching against apps-dlink
9726 ; if we get a match here, store the match data for later
9727 (let ((match (assoc-default dlink apps-dlink
9728 'string-match)))
9729 (if match
ed21c5c8 9730 (progn (setq link-match-data (match-data))
86fbb8ca
CD
9731 match)
9732 (progn (setq in-emacs (or in-emacs line search))
9733 nil))) ; if we have no match in apps-dlink,
9734 ; always open the file in emacs if line or search
9735 ; is given (for backwards compatibility)
9736 (assoc-default dfile (org-apps-regexp-alist apps a-m-a-p)
9737 'string-match)
20908596 9738 (cdr (assoc ext apps))
93b62de8
CD
9739 (cdr (assoc t apps))))))
9740 (when (eq cmd 'system)
9741 (setq cmd (cdr (assoc 'system apps))))
621f83e4
CD
9742 (when (eq cmd 'default)
9743 (setq cmd (cdr (assoc t apps))))
20908596
CD
9744 (when (eq cmd 'mailcap)
9745 (require 'mailcap)
9746 (mailcap-parse-mailcaps)
9747 (let* ((mime-type (mailcap-extension-to-mime (or ext "")))
9748 (command (mailcap-mime-info mime-type)))
9749 (if (stringp command)
9750 (setq cmd command)
9751 (setq cmd 'emacs))))
9752 (if (and (not (eq cmd 'emacs)) ; Emacs has no problems with non-ex files
9753 (not (file-exists-p file))
9754 (not org-open-non-existing-files))
9755 (error "No such file: %s" file))
9756 (cond
9757 ((and (stringp cmd) (not (string-match "^\\s-*$" cmd)))
9758 ;; Remove quotes around the file name - we'll use shell-quote-argument.
9759 (while (string-match "['\"]%s['\"]" cmd)
9760 (setq cmd (replace-match "%s" t t cmd)))
9761 (while (string-match "%s" cmd)
9762 (setq cmd (replace-match
b349f79f
CD
9763 (save-match-data
9764 (shell-quote-argument
9765 (convert-standard-filename file)))
20908596 9766 t t cmd)))
86fbb8ca 9767
ed21c5c8
CD
9768 ;; Replace "%1", "%2" etc. in command with group matches from regex
9769 (save-match-data
9770 (let ((match-index 1)
9771 (number-of-groups (- (/ (length link-match-data) 2) 1)))
9772 (set-match-data link-match-data)
9773 (while (<= match-index number-of-groups)
9774 (let ((regex (concat "%" (number-to-string match-index)))
9775 (replace-with (match-string match-index dlink)))
9776 (while (string-match regex cmd)
9777 (setq cmd (replace-match replace-with t t cmd))))
9778 (setq match-index (+ match-index 1)))))
9779
20908596
CD
9780 (save-window-excursion
9781 (start-process-shell-command cmd nil cmd)
9782 (and (boundp 'org-wait) (numberp org-wait) (sit-for org-wait))
9783 ))
9784 ((or (stringp cmd)
9785 (eq cmd 'emacs))
9786 (funcall (cdr (assq 'file org-link-frame-setup)) file)
9787 (widen)
54a0dee5 9788 (if line (org-goto-line line)
20908596
CD
9789 (if search (org-link-search search))))
9790 ((consp cmd)
b349f79f 9791 (let ((file (convert-standard-filename file)))
ed21c5c8
CD
9792 (save-match-data
9793 (set-match-data link-match-data)
9794 (eval cmd))))
20908596
CD
9795 (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
9796 (and (org-mode-p) (eq old-mode 'org-mode)
9797 (or (not (equal old-buffer (current-buffer)))
9798 (not (equal old-pos (point))))
9799 (org-mark-ring-push old-pos old-buffer))))
38f8646b 9800
86fbb8ca
CD
9801(defun org-file-apps-entry-match-against-dlink-p (entry)
9802 "This function returns non-nil if `entry' uses a regular
9803expression which should be matched against the whole link by
9804org-open-file.
9805
9806It assumes that is the case when the entry uses a regular
9807expression which has at least one grouping construct and the
9808action is either a lisp form or a command string containing
9809'%1', i.e. using at least one subexpression match as a
9810parameter."
9811 (let ((selector (car entry))
9812 (action (cdr entry)))
9813 (if (stringp selector)
9814 (and (> (regexp-opt-depth selector) 0)
9815 (or (and (stringp action)
9816 (string-match "%[0-9]" action))
9817 (consp action)))
9818 nil)))
9819
20908596
CD
9820(defun org-default-apps ()
9821 "Return the default applications for this operating system."
9822 (cond
9823 ((eq system-type 'darwin)
9824 org-file-apps-defaults-macosx)
9825 ((eq system-type 'windows-nt)
9826 org-file-apps-defaults-windowsnt)
9827 (t org-file-apps-defaults-gnu)))
38f8646b 9828
621f83e4
CD
9829(defun org-apps-regexp-alist (list &optional add-auto-mode)
9830 "Convert extensions to regular expressions in the cars of LIST.
9831Also, weed out any non-string entries, because the return value is used
9832only for regexp matching.
9833When ADD-AUTO-MODE is set, make all matches in `auto-mode-alist'
9834point to the symbol `emacs', indicating that the file should
9835be opened in Emacs."
9836 (append
9837 (delq nil
9838 (mapcar (lambda (x)
9839 (if (not (stringp (car x)))
9840 nil
9841 (if (string-match "\\W" (car x))
9842 x
86fbb8ca 9843 (cons (concat "\\." (car x) "\\'") (cdr x)))))
621f83e4
CD
9844 list))
9845 (if add-auto-mode
9846 (mapcar (lambda (x) (cons (car x) 'emacs)) auto-mode-alist))))
9847
20908596
CD
9848(defvar ange-ftp-name-format) ; to silence the XEmacs compiler.
9849(defun org-file-remote-p (file)
9850 "Test whether FILE specifies a location on a remote system.
9851Return non-nil if the location is indeed remote.
38f8646b 9852
20908596
CD
9853For example, the filename \"/user@host:/foo\" specifies a location
9854on the system \"/user@host:\"."
9855 (cond ((fboundp 'file-remote-p)
9856 (file-remote-p file))
9857 ((fboundp 'tramp-handle-file-remote-p)
9858 (tramp-handle-file-remote-p file))
9859 ((and (boundp 'ange-ftp-name-format)
9860 (string-match (car ange-ftp-name-format) file))
9861 t)
9862 (t nil)))
03f3cf35 9863
03f3cf35 9864
20908596 9865;;;; Refiling
7d58338e 9866
20908596
CD
9867(defun org-get-org-file ()
9868 "Read a filename, with default directory `org-directory'."
9869 (let ((default (or org-default-notes-file remember-data-file)))
9870 (read-file-name (format "File name [%s]: " default)
9871 (file-name-as-directory org-directory)
9872 default)))
7d58338e 9873
20908596
CD
9874(defun org-notes-order-reversed-p ()
9875 "Check if the current file should receive notes in reversed order."
7d58338e 9876 (cond
20908596
CD
9877 ((not org-reverse-note-order) nil)
9878 ((eq t org-reverse-note-order) t)
9879 ((not (listp org-reverse-note-order)) nil)
9880 (t (catch 'exit
9881 (let ((all org-reverse-note-order)
9882 entry)
9883 (while (setq entry (pop all))
9884 (if (string-match (car entry) buffer-file-name)
9885 (throw 'exit (cdr entry))))
9886 nil)))))
38f8646b 9887
20908596
CD
9888(defvar org-refile-target-table nil
9889 "The list of refile targets, created by `org-refile'.")
fbe6c10d 9890
20908596
CD
9891(defvar org-agenda-new-buffers nil
9892 "Buffers created to visit agenda files.")
03f3cf35 9893
86fbb8ca
CD
9894(defvar org-refile-cache nil
9895 "Cache for refile targets.")
9896
9897
9898(defvar org-refile-markers nil
9899 "All the markers used for caching refile locations.")
9900
9901(defun org-refile-marker (pos)
9902 "Get a new refile marker, but only if caching is in use."
9903 (if (not org-refile-use-cache)
9904 pos
9905 (let ((m (make-marker)))
9906 (move-marker m pos)
9907 (push m org-refile-markers)
9908 m)))
9909
9910(defun org-refile-cache-clear ()
9911 "Clear the refile cache and disable all the markers."
9912 (mapc (lambda (m) (move-marker m nil)) org-refile-markers)
9913 (setq org-refile-markers nil)
9914 (setq org-refile-cache nil)
9915 (message "Refile cache has been cleared"))
9916
9917(defun org-refile-cache-check-set (set)
9918 "Check if all the markers in the cache still have live buffers."
9919 (let (marker)
9920 (catch 'exit
9921 (while (and set (setq marker (nth 3 (pop set))))
9922 ;; if org-refile-use-outline-path is 'file, marker may be nil
9923 (when (and marker (null (marker-buffer marker)))
9924 (message "not found") (sit-for 3)
9925 (throw 'exit nil)))
9926 t)))
9927
9928(defun org-refile-cache-put (set &rest identifiers)
9929 "Push the refile targets SET into the cache, under IDENTIFIERS."
9930 (let* ((key (sha1 (prin1-to-string identifiers)))
9931 (entry (assoc key org-refile-cache)))
9932 (if entry
9933 (setcdr entry set)
9934 (push (cons key set) org-refile-cache))))
9935
9936(defun org-refile-cache-get (&rest identifiers)
9937 "Retrieve the cached value for refile targets given by IDENTIFIERS."
9938 (cond
9939 ((not org-refile-cache) nil)
9940 ((not org-refile-use-cache) (org-refile-cache-clear) nil)
9941 (t
9942 (let ((set (cdr (assoc (sha1 (prin1-to-string identifiers))
9943 org-refile-cache))))
9944 (and set (org-refile-cache-check-set set) set)))))
9945
20908596
CD
9946(defun org-get-refile-targets (&optional default-buffer)
9947 "Produce a table with refile targets."
c8d0cf5c
CD
9948 (let ((case-fold-search nil)
9949 ;; otherwise org confuses "TODO" as a kw and "Todo" as a word
9950 (entries (or org-refile-targets '((nil . (:level . 1)))))
86fbb8ca 9951 targets tgs txt re files f desc descre fast-path-p level pos0)
db55f368 9952 (message "Getting targets...")
20908596
CD
9953 (with-current-buffer (or default-buffer (current-buffer))
9954 (while (setq entry (pop entries))
9955 (setq files (car entry) desc (cdr entry))
db55f368 9956 (setq fast-path-p nil)
20908596
CD
9957 (cond
9958 ((null files) (setq files (list (current-buffer))))
9959 ((eq files 'org-agenda-files)
9960 (setq files (org-agenda-files 'unrestricted)))
9961 ((and (symbolp files) (fboundp files))
9962 (setq files (funcall files)))
9963 ((and (symbolp files) (boundp files))
9964 (setq files (symbol-value files))))
9965 (if (stringp files) (setq files (list files)))
9966 (cond
9967 ((eq (car desc) :tag)
9968 (setq descre (concat "^\\*+[ \t]+.*?:" (regexp-quote (cdr desc)) ":")))
9969 ((eq (car desc) :todo)
9970 (setq descre (concat "^\\*+[ \t]+" (regexp-quote (cdr desc)) "[ \t]")))
9971 ((eq (car desc) :regexp)
9972 (setq descre (cdr desc)))
9973 ((eq (car desc) :level)
9974 (setq descre (concat "^\\*\\{" (number-to-string
9975 (if org-odd-levels-only
9976 (1- (* 2 (cdr desc)))
9977 (cdr desc)))
9978 "\\}[ \t]")))
9979 ((eq (car desc) :maxlevel)
db55f368 9980 (setq fast-path-p t)
20908596
CD
9981 (setq descre (concat "^\\*\\{1," (number-to-string
9982 (if org-odd-levels-only
9983 (1- (* 2 (cdr desc)))
9984 (cdr desc)))
9985 "\\}[ \t]")))
9986 (t (error "Bad refiling target description %s" desc)))
9987 (while (setq f (pop files))
81ad75af 9988 (with-current-buffer
8bfe682a 9989 (if (bufferp f) f (org-get-agenda-file-buffer f))
86fbb8ca
CD
9990 (or
9991 (setq tgs (org-refile-cache-get (buffer-file-name) descre))
9992 (progn
9993 (if (bufferp f) (setq f (buffer-file-name
9994 (buffer-base-buffer f))))
9995 (setq f (and f (expand-file-name f)))
9996 (if (eq org-refile-use-outline-path 'file)
9997 (push (list (file-name-nondirectory f) f nil nil) tgs))
9998 (save-excursion
9999 (save-restriction
10000 (widen)
10001 (goto-char (point-min))
10002 (while (re-search-forward descre nil t)
10003 (goto-char (setq pos0 (point-at-bol)))
10004 (catch 'next
10005 (when org-refile-target-verify-function
10006 (save-match-data
10007 (or (funcall org-refile-target-verify-function)
10008 (throw 'next t))))
10009 (when (looking-at org-complex-heading-regexp)
10010 (setq level (org-reduced-level
10011 (- (match-end 1) (match-beginning 1)))
10012 txt (org-link-display-format (match-string 4))
afe98dfa
CD
10013 txt (replace-regexp-in-string "\\( *\[[0-9]+/?[0-9]*%?\]\\)+$" "" txt)
10014 re (format org-complex-heading-regexp-format
10015 (regexp-quote (match-string 4))))
86fbb8ca
CD
10016 (when org-refile-use-outline-path
10017 (setq txt (mapconcat
10018 'org-protect-slash
10019 (append
10020 (if (eq org-refile-use-outline-path
10021 'file)
10022 (list (file-name-nondirectory
10023 (buffer-file-name
10024 (buffer-base-buffer))))
10025 (if (eq org-refile-use-outline-path
10026 'full-file-path)
10027 (list (buffer-file-name
10028 (buffer-base-buffer)))))
10029 (org-get-outline-path fast-path-p
10030 level txt)
10031 (list txt))
10032 "/")))
10033 (push (list txt f re (org-refile-marker (point)))
10034 tgs)))
10035 (when (= (point) pos0)
10036 ;; verification function has not moved point
10037 (goto-char (point-at-eol))))))))
10038 (when org-refile-use-cache
10039 (org-refile-cache-put tgs (buffer-file-name) descre))
10040 (setq targets (append tgs targets))
10041 ))))
db55f368 10042 (message "Getting targets...done")
c8d0cf5c 10043 (nreverse targets)))
20908596 10044
621f83e4
CD
10045(defun org-protect-slash (s)
10046 (while (string-match "/" s)
10047 (setq s (replace-match "\\" t t s)))
10048 s)
ce4fdcb9 10049
db55f368
CD
10050(defvar org-olpa (make-vector 20 nil))
10051
10052(defun org-get-outline-path (&optional fastp level heading)
1bcdebed 10053 "Return the outline path to the current entry, as a list.
86fbb8ca
CD
10054
10055The parameters FASTP, LEVEL, and HEADING are for use by a scanner
1bcdebed 10056routine which makes outline path derivations for an entire file,
86fbb8ca 10057avoiding backtracing. Refile target collection makes use of that."
db55f368
CD
10058 (if fastp
10059 (progn
33306645 10060 (if (> level 19)
86fbb8ca 10061 (error "Outline path failure, more than 19 levels"))
db55f368
CD
10062 (loop for i from level upto 19 do
10063 (aset org-olpa i nil))
10064 (prog1
10065 (delq nil (append org-olpa nil))
10066 (aset org-olpa level heading)))
ed21c5c8 10067 (let (rtn case-fold-search)
db55f368 10068 (save-excursion
5dec9555
CD
10069 (save-restriction
10070 (widen)
10071 (while (org-up-heading-safe)
10072 (when (looking-at org-complex-heading-regexp)
10073 (push (org-match-string-no-properties 4) rtn)))
10074 rtn)))))
7d58338e 10075
1bcdebed 10076(defun org-format-outline-path (path &optional width prefix)
86fbb8ca 10077 "Format the outline path PATH for display.
1bcdebed
CD
10078Width is the maximum number of characters that is available.
10079Prefix is a prefix to be included in the returned string,
10080such as the file name."
10081 (setq width (or width 79))
10082 (if prefix (setq width (- width (length prefix))))
10083 (if (not path)
10084 (or prefix "")
10085 (let* ((nsteps (length path))
10086 (total-width (+ nsteps (apply '+ (mapcar 'length path))))
10087 (maxwidth (if (<= total-width width)
10088 10000 ;; everything fits
10089 ;; we need to shorten the level headings
10090 (/ (- width nsteps) nsteps)))
10091 (org-odd-levels-only nil)
10092 (n 0)
10093 (total (1+ (length prefix))))
10094 (setq maxwidth (max maxwidth 10))
10095 (concat prefix
10096 (mapconcat
10097 (lambda (h)
10098 (setq n (1+ n))
10099 (if (and (= n nsteps) (< maxwidth 10000))
10100 (setq maxwidth (- total-width total)))
10101 (if (< (length h) maxwidth)
10102 (progn (setq total (+ total (length h) 1)) h)
10103 (setq h (substring h 0 (- maxwidth 2))
10104 total (+ total maxwidth 1))
10105 (if (string-match "[ \t]+\\'" h)
10106 (setq h (substring h 0 (match-beginning 0))))
10107 (setq h (concat h "..")))
10108 (org-add-props h nil 'face
10109 (nth (% (1- n) org-n-level-faces)
10110 org-level-faces))
10111 h)
10112 path "/")))))
10113
10114(defun org-display-outline-path (&optional file current)
10115 "Display the current outline path in the echo area."
10116 (interactive "P")
ed21c5c8
CD
10117 (let* ((bfn (buffer-file-name (buffer-base-buffer)))
10118 (case-fold-search nil)
10119 (path (and (org-mode-p) (org-get-outline-path))))
1bcdebed
CD
10120 (if current (setq path (append path
10121 (save-excursion
10122 (org-back-to-heading t)
10123 (if (looking-at org-complex-heading-regexp)
10124 (list (match-string 4)))))))
5dec9555
CD
10125 (message "%s"
10126 (org-format-outline-path
1bcdebed
CD
10127 path
10128 (1- (frame-width))
10129 (and file bfn (concat (file-name-nondirectory bfn) "/"))))))
10130
20908596
CD
10131(defvar org-refile-history nil
10132 "History for refiling operations.")
7d58338e 10133
c8d0cf5c
CD
10134(defvar org-after-refile-insert-hook nil
10135 "Hook run after `org-refile' has inserted its stuff at the new location.
10136Note that this is still *before* the stuff will be removed from
10137the *old* location.")
10138
86fbb8ca 10139(defvar org-capture-last-stored-marker)
c8d0cf5c 10140(defun org-refile (&optional goto default-buffer rfloc)
20908596
CD
10141 "Move the entry at point to another heading.
10142The list of target headings is compiled using the information in
10143`org-refile-targets', which see. This list is created before each use
10144and will therefore always be up-to-date.
10145
10146At the target location, the entry is filed as a subitem of the target heading.
10147Depending on `org-reverse-note-order', the new subitem will either be the
71d35b24 10148first or the last subitem.
20908596 10149
93b62de8 10150If there is an active region, all entries in that region will be moved.
86fbb8ca 10151However, the region must fulfill the requirement that the first heading
93b62de8
CD
10152is the first one sets the top-level of the moved text - at most siblings
10153below it are allowed.
10154
20908596
CD
10155With prefix arg GOTO, the command will only visit the target location,
10156not actually move anything.
86fbb8ca
CD
10157With a double prefix arg \\[universal-argument] \\[universal-argument], \
10158go to the location where the last refiling
c8d0cf5c 10159operation has put the subtree.
8bfe682a 10160With a prefix argument of `2', refile to the running clock.
c8d0cf5c
CD
10161
10162RFLOC can be a refile location obtained in a different way.
10163
86fbb8ca
CD
10164See also `org-refile-use-outline-path' and `org-completion-use-ido'.
10165
10166If you are using target caching (see `org-refile-use-cache'),
10167You have to clear the target cache in order to find new targets.
10168This can be done with a 0 prefix: `C-0 C-c C-w'"
20908596 10169 (interactive "P")
86fbb8ca
CD
10170 (if (member goto '(0 (64)))
10171 (org-refile-cache-clear)
10172 (let* ((cbuf (current-buffer))
10173 (regionp (org-region-active-p))
10174 (region-start (and regionp (region-beginning)))
10175 (region-end (and regionp (region-end)))
10176 (region-length (and regionp (- region-end region-start)))
10177 (filename (buffer-file-name (buffer-base-buffer cbuf)))
10178 pos it nbuf file re level reversed)
10179 (setq last-command nil)
10180 (when regionp
10181 (goto-char region-start)
10182 (or (bolp) (goto-char (point-at-bol)))
10183 (setq region-start (point))
10184 (unless (org-kill-is-subtree-p
10185 (buffer-substring region-start region-end))
10186 (error "The region is not a (sequence of) subtree(s)")))
10187 (if (equal goto '(16))
10188 (org-refile-goto-last-stored)
10189 (when (or
10190 (and (equal goto 2)
10191 org-clock-hd-marker (marker-buffer org-clock-hd-marker)
10192 (prog1
10193 (setq it (list (or org-clock-heading "running clock")
10194 (buffer-file-name
10195 (marker-buffer org-clock-hd-marker))
10196 ""
10197 (marker-position org-clock-hd-marker)))
10198 (setq goto nil)))
10199 (setq it (or rfloc
10200 (save-excursion
10201 (org-refile-get-location
10202 (if goto "Goto: " "Refile to: ") default-buffer
10203 org-refile-allow-creating-parent-nodes)))))
10204 (setq file (nth 1 it)
10205 re (nth 2 it)
10206 pos (nth 3 it))
10207 (if (and (not goto)
10208 pos
10209 (equal (buffer-file-name) file)
10210 (if regionp
10211 (and (>= pos region-start)
10212 (<= pos region-end))
10213 (and (>= pos (point))
10214 (< pos (save-excursion
10215 (org-end-of-subtree t t))))))
10216 (error "Cannot refile to position inside the tree or region"))
10217
10218 (setq nbuf (or (find-buffer-visiting file)
10219 (find-file-noselect file)))
10220 (if goto
93b62de8 10221 (progn
86fbb8ca
CD
10222 (switch-to-buffer nbuf)
10223 (goto-char pos)
10224 (org-show-context 'org-goto))
10225 (if regionp
10226 (progn
10227 (org-kill-new (buffer-substring region-start region-end))
10228 (org-save-markers-in-region region-start region-end))
10229 (org-copy-subtree 1 nil t))
10230 (with-current-buffer (setq nbuf (or (find-buffer-visiting file)
10231 (find-file-noselect file)))
10232 (setq reversed (org-notes-order-reversed-p))
10233 (save-excursion
10234 (save-restriction
10235 (widen)
10236 (if pos
10237 (progn
10238 (goto-char pos)
10239 (looking-at outline-regexp)
10240 (setq level (org-get-valid-level (funcall outline-level) 1))
10241 (goto-char
10242 (if reversed
10243 (or (outline-next-heading) (point-max))
10244 (or (save-excursion (org-get-next-sibling))
10245 (org-end-of-subtree t t)
10246 (point-max)))))
10247 (setq level 1)
10248 (if (not reversed)
10249 (goto-char (point-max))
10250 (goto-char (point-min))
10251 (or (outline-next-heading) (goto-char (point-max)))))
10252 (if (not (bolp)) (newline))
10253 (org-paste-subtree level)
10254 (when org-log-refile
10255 (org-add-log-setup 'refile nil nil 'findpos
10256 org-log-refile)
10257 (unless (eq org-log-refile 'note)
10258 (save-excursion (org-add-log-note))))
10259 (and org-auto-align-tags (org-set-tags nil t))
10260 (bookmark-set "org-refile-last-stored")
10261 ;; If we are refiling for capture, make sure that the
10262 ;; last-capture pointers point here
10263 (when (org-bound-and-true-p org-refile-for-capture)
10264 (bookmark-set "org-capture-last-stored-marker")
10265 (move-marker org-capture-last-stored-marker (point)))
10266 (if (fboundp 'deactivate-mark) (deactivate-mark))
10267 (run-hooks 'org-after-refile-insert-hook))))
10268 (if regionp
10269 (delete-region (point) (+ (point) region-length))
10270 (org-cut-subtree))
10271 (when (featurep 'org-inlinetask)
10272 (org-inlinetask-remove-END-maybe))
10273 (setq org-markers-to-move nil)
10274 (message "Refiled to \"%s\" in file %s" (car it) file)))))))
20908596
CD
10275
10276(defun org-refile-goto-last-stored ()
10277 "Go to the location where the last refile was stored."
38f8646b 10278 (interactive)
20908596
CD
10279 (bookmark-jump "org-refile-last-stored")
10280 (message "This is the location of the last refile"))
38f8646b 10281
c8d0cf5c 10282(defun org-refile-get-location (&optional prompt default-buffer new-nodes)
20908596
CD
10283 "Prompt the user for a refile location, using PROMPT."
10284 (let ((org-refile-targets org-refile-targets)
10285 (org-refile-use-outline-path org-refile-use-outline-path))
10286 (setq org-refile-target-table (org-get-refile-targets default-buffer)))
10287 (unless org-refile-target-table
10288 (error "No refile targets"))
10289 (let* ((cbuf (current-buffer))
c8d0cf5c 10290 (partial-completion-mode nil)
bb31cb31 10291 (cfn (buffer-file-name (buffer-base-buffer cbuf)))
d60b1ba1
CD
10292 (cfunc (if (and org-refile-use-outline-path
10293 org-outline-path-complete-in-steps)
b349f79f 10294 'org-olpath-completing-read
54a0dee5 10295 'org-icompleting-read))
b349f79f 10296 (extra (if org-refile-use-outline-path "/" ""))
bb31cb31 10297 (filename (and cfn (expand-file-name cfn)))
20908596
CD
10298 (tbl (mapcar
10299 (lambda (x)
c8d0cf5c
CD
10300 (if (and (not (member org-refile-use-outline-path
10301 '(file full-file-path)))
10302 (not (equal filename (nth 1 x))))
b349f79f
CD
10303 (cons (concat (car x) extra " ("
10304 (file-name-nondirectory (nth 1 x)) ")")
20908596 10305 (cdr x))
b349f79f 10306 (cons (concat (car x) extra) (cdr x))))
20908596 10307 org-refile-target-table))
c8d0cf5c
CD
10308 (completion-ignore-case t)
10309 pa answ parent-target child parent old-hist)
10310 (setq old-hist org-refile-history)
10311 (setq answ (funcall cfunc prompt tbl nil (not new-nodes)
10312 nil 'org-refile-history))
10313 (setq pa (or (assoc answ tbl) (assoc (concat answ "/") tbl)))
afe98dfa 10314 (org-refile-check-position pa)
f924a367 10315 (if pa
c8d0cf5c
CD
10316 (progn
10317 (when (or (not org-refile-history)
10318 (not (eq old-hist org-refile-history))
10319 (not (equal (car pa) (car org-refile-history))))
10320 (setq org-refile-history
10321 (cons (car pa) (if (assoc (car org-refile-history) tbl)
10322 org-refile-history
10323 (cdr org-refile-history))))
10324 (if (equal (car org-refile-history) (nth 1 org-refile-history))
10325 (pop org-refile-history)))
10326 pa)
ed21c5c8
CD
10327 (if (string-match "\\`\\(.*\\)/\\([^/]+\\)\\'" answ)
10328 (progn
10329 (setq parent (match-string 1 answ)
10330 child (match-string 2 answ))
10331 (setq parent-target (or (assoc parent tbl)
10332 (assoc (concat parent "/") tbl)))
10333 (when (and parent-target
10334 (or (eq new-nodes t)
10335 (and (eq new-nodes 'confirm)
10336 (y-or-n-p (format "Create new node \"%s\"? "
10337 child)))))
10338 (org-refile-new-child parent-target child)))
10339 (error "Invalid target location")))))
c8d0cf5c 10340
afe98dfa
CD
10341(defun org-refile-check-position (refile-pointer)
10342 "Check if the refile pointer matches the readline to which it points."
10343 (let* ((file (nth 1 refile-pointer))
10344 (re (nth 2 refile-pointer))
10345 (pos (nth 3 refile-pointer))
10346 buffer)
10347 (when (org-string-nw-p re)
10348 (setq buffer (if (markerp pos)
10349 (marker-buffer pos)
10350 (or (find-buffer-visiting file)
10351 (find-file-noselect file))))
10352 (with-current-buffer buffer
10353 (save-excursion
10354 (save-restriction
10355 (widen)
10356 (goto-char pos)
10357 (beginning-of-line 1)
10358 (unless (org-looking-at-p re)
10359 (error "Invalid refile position, please rebuild the cache"))))))))
10360
c8d0cf5c
CD
10361(defun org-refile-new-child (parent-target child)
10362 "Use refile target PARENT-TARGET to add new CHILD below it."
10363 (unless parent-target
10364 (error "Cannot find parent for new node"))
10365 (let ((file (nth 1 parent-target))
10366 (pos (nth 3 parent-target))
10367 level)
10368 (with-current-buffer (or (find-buffer-visiting file)
10369 (find-file-noselect file))
10370 (save-excursion
10371 (save-restriction
10372 (widen)
10373 (if pos
10374 (goto-char pos)
10375 (goto-char (point-max))
10376 (if (not (bolp)) (newline)))
10377 (when (looking-at outline-regexp)
10378 (setq level (funcall outline-level))
10379 (org-end-of-subtree t t))
10380 (org-back-over-empty-lines)
10381 (insert "\n" (make-string
10382 (if pos (org-get-valid-level level 1) 1) ?*)
10383 " " child "\n")
10384 (beginning-of-line 0)
10385 (list (concat (car parent-target) "/" child) file "" (point)))))))
7d58338e 10386
b349f79f
CD
10387(defun org-olpath-completing-read (prompt collection &rest args)
10388 "Read an outline path like a file name."
c8d0cf5c 10389 (let ((thetable collection)
54a0dee5 10390 (org-completion-use-ido nil) ; does not work with ido.
f924a367 10391 (org-completion-use-iswitchb nil)) ; or iswitchb
ce4fdcb9 10392 (apply
54a0dee5 10393 'org-icompleting-read prompt
b349f79f 10394 (lambda (string predicate &optional flag)
65c439fd 10395 (let (rtn r f (l (length string)))
b349f79f
CD
10396 (cond
10397 ((eq flag nil)
10398 ;; try completion
10399 (try-completion string thetable))
10400 ((eq flag t)
10401 ;; all-completions
10402 (setq rtn (all-completions string thetable predicate))
10403 (mapcar
10404 (lambda (x)
10405 (setq r (substring x l))
10406 (if (string-match " ([^)]*)$" x)
10407 (setq f (match-string 0 x))
10408 (setq f ""))
10409 (if (string-match "/" r)
10410 (concat string (substring r 0 (match-end 0)) f)
10411 x))
10412 rtn))
10413 ((eq flag 'lambda)
10414 ;; exact match?
10415 (assoc string thetable)))
10416 ))
10417 args)))
10418
20908596
CD
10419;;;; Dynamic blocks
10420
10421(defun org-find-dblock (name)
10422 "Find the first dynamic block with name NAME in the buffer.
10423If not found, stay at current position and return nil."
10424 (let (pos)
7d58338e 10425 (save-excursion
03f3cf35 10426 (goto-char (point-min))
20908596
CD
10427 (setq pos (and (re-search-forward (concat "^#\\+BEGIN:[ \t]+" name "\\>")
10428 nil t)
10429 (match-beginning 0))))
10430 (if pos (goto-char pos))
10431 pos))
4b3a9ba7 10432
20908596 10433(defconst org-dblock-start-re
8d642074 10434 "^[ \t]*#\\+BEGIN:[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?"
8bfe682a 10435 "Matches the start line of a dynamic block, with parameters.")
891f4676 10436
8d642074 10437(defconst org-dblock-end-re "^[ \t]*#\\+END\\([: \t\r\n]\\|$\\)"
33306645 10438 "Matches the end of a dynamic block.")
8c6fb58b 10439
20908596
CD
10440(defun org-create-dblock (plist)
10441 "Create a dynamic block section, with parameters taken from PLIST.
33306645 10442PLIST must contain a :name entry which is used as name of the block."
8d642074
CD
10443 (when (string-match "\\S-" (buffer-substring (point-at-bol) (point-at-eol)))
10444 (end-of-line 1)
10445 (newline))
10446 (let ((col (current-column))
10447 (name (plist-get plist :name)))
20908596
CD
10448 (insert "#+BEGIN: " name)
10449 (while plist
10450 (if (eq (car plist) :name)
10451 (setq plist (cddr plist))
10452 (insert " " (prin1-to-string (pop plist)))))
8d642074 10453 (insert "\n\n" (make-string col ?\ ) "#+END:\n")
20908596 10454 (beginning-of-line -2)))
891f4676 10455
20908596
CD
10456(defun org-prepare-dblock ()
10457 "Prepare dynamic block for refresh.
10458This empties the block, puts the cursor at the insert position and returns
10459the property list including an extra property :name with the block name."
10460 (unless (looking-at org-dblock-start-re)
10461 (error "Not at a dynamic block"))
10462 (let* ((begdel (1+ (match-end 0)))
10463 (name (org-no-properties (match-string 1)))
10464 (params (append (list :name name)
10465 (read (concat "(" (match-string 3) ")")))))
8d642074
CD
10466 (save-excursion
10467 (beginning-of-line 1)
10468 (skip-chars-forward " \t")
10469 (setq params (plist-put params :indentation-column (current-column))))
20908596
CD
10470 (unless (re-search-forward org-dblock-end-re nil t)
10471 (error "Dynamic block not terminated"))
10472 (setq params
10473 (append params
10474 (list :content (buffer-substring
10475 begdel (match-beginning 0)))))
10476 (delete-region begdel (match-beginning 0))
10477 (goto-char begdel)
10478 (open-line 1)
10479 params))
891f4676 10480
20908596
CD
10481(defun org-map-dblocks (&optional command)
10482 "Apply COMMAND to all dynamic blocks in the current buffer.
10483If COMMAND is not given, use `org-update-dblock'."
ed21c5c8 10484 (let ((cmd (or command 'org-update-dblock)))
20908596
CD
10485 (save-excursion
10486 (goto-char (point-min))
10487 (while (re-search-forward org-dblock-start-re nil t)
ed21c5c8
CD
10488 (goto-char (match-beginning 0))
10489 (save-excursion
10490 (condition-case nil
10491 (funcall cmd)
10492 (error (message "Error during update of dynamic block"))))
20908596
CD
10493 (unless (re-search-forward org-dblock-end-re nil t)
10494 (error "Dynamic block not terminated"))))))
891f4676 10495
20908596
CD
10496(defun org-dblock-update (&optional arg)
10497 "User command for updating dynamic blocks.
10498Update the dynamic block at point. With prefix ARG, update all dynamic
10499blocks in the buffer."
10500 (interactive "P")
10501 (if arg
10502 (org-update-all-dblocks)
10503 (or (looking-at org-dblock-start-re)
10504 (org-beginning-of-dblock))
10505 (org-update-dblock)))
8c6fb58b 10506
20908596 10507(defun org-update-dblock ()
86fbb8ca 10508 "Update the dynamic block at point.
20908596
CD
10509This means to empty the block, parse for parameters and then call
10510the correct writing function."
acedf35c 10511 (interactive)
20908596
CD
10512 (save-window-excursion
10513 (let* ((pos (point))
10514 (line (org-current-line))
10515 (params (org-prepare-dblock))
10516 (name (plist-get params :name))
8d642074 10517 (indent (plist-get params :indentation-column))
20908596
CD
10518 (cmd (intern (concat "org-dblock-write:" name))))
10519 (message "Updating dynamic block `%s' at line %d..." name line)
10520 (funcall cmd params)
10521 (message "Updating dynamic block `%s' at line %d...done" name line)
8d642074
CD
10522 (goto-char pos)
10523 (when (and indent (> indent 0))
10524 (setq indent (make-string indent ?\ ))
10525 (save-excursion
10526 (org-beginning-of-dblock)
10527 (forward-line 1)
10528 (while (not (looking-at org-dblock-end-re))
10529 (insert indent)
10530 (beginning-of-line 2))
10531 (when (looking-at org-dblock-end-re)
10532 (and (looking-at "[ \t]+")
10533 (replace-match ""))
10534 (insert indent)))))))
8c6fb58b 10535
20908596
CD
10536(defun org-beginning-of-dblock ()
10537 "Find the beginning of the dynamic block at point.
33306645 10538Error if there is no such block at point."
20908596
CD
10539 (let ((pos (point))
10540 beg)
10541 (end-of-line 1)
10542 (if (and (re-search-backward org-dblock-start-re nil t)
10543 (setq beg (match-beginning 0))
10544 (re-search-forward org-dblock-end-re nil t)
10545 (> (match-end 0) pos))
10546 (goto-char beg)
10547 (goto-char pos)
10548 (error "Not in a dynamic block"))))
03f3cf35 10549
20908596
CD
10550(defun org-update-all-dblocks ()
10551 "Update all dynamic blocks in the buffer.
10552This function can be used in a hook."
acedf35c 10553 (interactive)
20908596
CD
10554 (when (org-mode-p)
10555 (org-map-dblocks 'org-update-dblock)))
03f3cf35 10556
891f4676 10557
20908596 10558;;;; Completion
891f4676 10559
20908596 10560(defconst org-additional-option-like-keywords
acedf35c
CD
10561 '("BEGIN_HTML" "END_HTML" "HTML:" "ATTR_HTML:"
10562 "BEGIN_DocBook" "END_DocBook" "DocBook:" "ATTR_DocBook:"
ed21c5c8 10563 "BEGIN_LaTeX" "END_LaTeX" "LaTeX:" "LATEX_HEADER:"
acedf35c 10564 "LATEX_CLASS:" "LATEX_CLASS_OPTIONS:" "ATTR_LaTeX:"
c8d0cf5c
CD
10565 "BEGIN:" "END:"
10566 "ORGTBL" "TBLFM:" "TBLNAME:"
621f83e4
CD
10567 "BEGIN_EXAMPLE" "END_EXAMPLE"
10568 "BEGIN_QUOTE" "END_QUOTE"
10569 "BEGIN_VERSE" "END_VERSE"
c8d0cf5c 10570 "BEGIN_CENTER" "END_CENTER"
db55f368 10571 "BEGIN_SRC" "END_SRC"
acedf35c
CD
10572 "BEGIN_RESULT" "END_RESULT"
10573 "SOURCE:" "SRCNAME:" "FUNCTION:"
10574 "RESULTS:"
10575 "HEADER:" "HEADERS:"
10576 "BABEL:"
10577 "CATEGORY:" "COLUMNS:" "PROPERTY:"
10578 "CAPTION:" "LABEL:"
10579 "SETUPFILE:"
10580 "INCLUDE:"
10581 "BIND:"
10582 "MACRO:"))
891f4676 10583
b349f79f
CD
10584(defcustom org-structure-template-alist
10585 '(
ce4fdcb9 10586 ("s" "#+begin_src ?\n\n#+end_src"
b349f79f
CD
10587 "<src lang=\"?\">\n\n</src>")
10588 ("e" "#+begin_example\n?\n#+end_example"
10589 "<example>\n?\n</example>")
10590 ("q" "#+begin_quote\n?\n#+end_quote"
10591 "<quote>\n?\n</quote>")
10592 ("v" "#+begin_verse\n?\n#+end_verse"
10593 "<verse>\n?\n/verse>")
c8d0cf5c
CD
10594 ("c" "#+begin_center\n?\n#+end_center"
10595 "<center>\n?\n/center>")
b349f79f
CD
10596 ("l" "#+begin_latex\n?\n#+end_latex"
10597 "<literal style=\"latex\">\n?\n</literal>")
10598 ("L" "#+latex: "
10599 "<literal style=\"latex\">?</literal>")
10600 ("h" "#+begin_html\n?\n#+end_html"
10601 "<literal style=\"html\">\n?\n</literal>")
10602 ("H" "#+html: "
10603 "<literal style=\"html\">?</literal>")
10604 ("a" "#+begin_ascii\n?\n#+end_ascii")
10605 ("A" "#+ascii: ")
10606 ("i" "#+include %file ?"
10607 "<include file=%file markup=\"?\">")
10608 )
10609 "Structure completion elements.
10610This is a list of abbreviation keys and values. The value gets inserted
86fbb8ca 10611if you type `<' followed by the key and then press the completion key,
b349f79f 10612usually `M-TAB'. %file will be replaced by a file name after prompting
33306645 10613for the file using completion.
b349f79f
CD
10614There are two templates for each key, the first uses the original Org syntax,
10615the second uses Emacs Muse-like syntax tags. These Muse-like tags become
86fbb8ca 10616the default when the /org-mtags.el/ module has been loaded. See also the
ce4fdcb9 10617variable `org-mtags-prefer-muse-templates'.
b349f79f
CD
10618This is an experimental feature, it is undecided if it is going to stay in."
10619 :group 'org-completion
10620 :type '(repeat
10621 (string :tag "Key")
10622 (string :tag "Template")
10623 (string :tag "Muse Template")))
10624
10625(defun org-try-structure-completion ()
10626 "Try to complete a structure template before point.
10627This looks for strings like \"<e\" on an otherwise empty line and
10628expands them."
10629 (let ((l (buffer-substring (point-at-bol) (point)))
10630 a)
10631 (when (and (looking-at "[ \t]*$")
10632 (string-match "^[ \t]*<\\([a-z]+\\)$"l)
10633 (setq a (assoc (match-string 1 l) org-structure-template-alist)))
10634 (org-complete-expand-structure-template (+ -1 (point-at-bol)
10635 (match-beginning 1)) a)
10636 t)))
10637
10638(defun org-complete-expand-structure-template (start cell)
10639 "Expand a structure template."
ce4fdcb9 10640 (let* ((musep (org-bound-and-true-p org-mtags-prefer-muse-templates))
c8d0cf5c
CD
10641 (rpl (nth (if musep 2 1) cell))
10642 (ind ""))
b349f79f
CD
10643 (delete-region start (point))
10644 (when (string-match "\\`#\\+" rpl)
10645 (cond
10646 ((bolp))
10647 ((not (string-match "\\S-" (buffer-substring (point-at-bol) (point))))
c8d0cf5c 10648 (setq ind (buffer-substring (point-at-bol) (point))))
b349f79f
CD
10649 (t (newline))))
10650 (setq start (point))
10651 (if (string-match "%file" rpl)
ce4fdcb9 10652 (setq rpl (replace-match
b349f79f
CD
10653 (concat
10654 "\""
10655 (save-match-data
10656 (abbreviate-file-name (read-file-name "Include file: ")))
10657 "\"")
10658 t t rpl)))
c8d0cf5c
CD
10659 (setq rpl (mapconcat 'identity (split-string rpl "\n")
10660 (concat "\n" ind)))
b349f79f
CD
10661 (insert rpl)
10662 (if (re-search-backward "\\?" start t) (delete-char 1))))
ce4fdcb9 10663
20908596
CD
10664;;;; TODO, DEADLINE, Comments
10665
10666(defun org-toggle-comment ()
10667 "Change the COMMENT state of an entry."
10668 (interactive)
10669 (save-excursion
10670 (org-back-to-heading)
10671 (let (case-fold-search)
10672 (if (looking-at (concat outline-regexp
10673 "\\( *\\<" org-comment-string "\\>[ \t]*\\)"))
10674 (replace-match "" t t nil 1)
10675 (if (looking-at outline-regexp)
10676 (progn
10677 (goto-char (match-end 0))
10678 (insert org-comment-string " ")))))))
10679
10680(defvar org-last-todo-state-is-todo nil
10681 "This is non-nil when the last TODO state change led to a TODO state.
10682If the last change removed the TODO tag or switched to DONE, then
10683this is nil.")
10684
33306645 10685(defvar org-setting-tags nil) ; dynamically skipped
8c6fb58b 10686
c8d0cf5c
CD
10687(defvar org-todo-setup-filter-hook nil
10688 "Hook for functions that pre-filter todo specs.
86fbb8ca 10689Each function takes a todo spec and returns either nil or the spec
c8d0cf5c
CD
10690transformed into canonical form." )
10691
10692(defvar org-todo-get-default-hook nil
10693 "Hook for functions that get a default item for todo.
c8d0cf5c 10694Each function takes arguments (NEW-MARK OLD-MARK) and returns either
86fbb8ca 10695nil or a string to be used for the todo mark." )
c8d0cf5c 10696
93b62de8 10697(defvar org-agenda-headline-snapshot-before-repeat)
c8d0cf5c 10698
20908596
CD
10699(defun org-todo (&optional arg)
10700 "Change the TODO state of an item.
10701The state of an item is given by a keyword at the start of the heading,
10702like
10703 *** TODO Write paper
10704 *** DONE Call mom
10705
10706The different keywords are specified in the variable `org-todo-keywords'.
10707By default the available states are \"TODO\" and \"DONE\".
10708So for this example: when the item starts with TODO, it is changed to DONE.
10709When it starts with DONE, the DONE is removed. And when neither TODO nor
10710DONE are present, add TODO at the beginning of the heading.
10711
86fbb8ca
CD
10712With \\[universal-argument] prefix arg, use completion to determine the new \
10713state.
20908596 10714With numeric prefix arg, switch to that state.
86fbb8ca
CD
10715With a double \\[universal-argument] prefix, switch to the next set of TODO \
10716keywords (nextset).
10717With a triple \\[universal-argument] prefix, circumvent any state blocking.
20908596
CD
10718
10719For calling through lisp, arg is also interpreted in the following way:
10720'none -> empty state
10721\"\"(empty string) -> switch to empty state
10722'done -> switch to DONE
10723'nextset -> switch to the next set of keywords
10724'previousset -> switch to the previous set of keywords
10725\"WAITING\" -> switch to the specified keyword, but only if it
10726 really is a member of `org-todo-keywords'."
10727 (interactive "P")
65c439fd 10728 (if (equal arg '(16)) (setq arg 'nextset))
c8d0cf5c
CD
10729 (let ((org-blocker-hook org-blocker-hook)
10730 (case-fold-search nil))
6c817206
CD
10731 (when (equal arg '(64))
10732 (setq arg nil org-blocker-hook nil))
c8d0cf5c
CD
10733 (when (and org-blocker-hook
10734 (or org-inhibit-blocking
10735 (org-entry-get nil "NOBLOCKING")))
10736 (setq org-blocker-hook nil))
6c817206
CD
10737 (save-excursion
10738 (catch 'exit
8bfe682a 10739 (org-back-to-heading t)
6c817206 10740 (if (looking-at outline-regexp) (goto-char (1- (match-end 0))))
c8d0cf5c 10741 (or (looking-at (concat " +" org-todo-regexp "\\( +\\|$\\)"))
6c817206
CD
10742 (looking-at " *"))
10743 (let* ((match-data (match-data))
10744 (startpos (point-at-bol))
86fbb8ca 10745 (logging (save-match-data (org-entry-get nil "LOGGING" t t)))
6c817206
CD
10746 (org-log-done org-log-done)
10747 (org-log-repeat org-log-repeat)
10748 (org-todo-log-states org-todo-log-states)
10749 (this (match-string 1))
10750 (hl-pos (match-beginning 0))
10751 (head (org-get-todo-sequence-head this))
10752 (ass (assoc head org-todo-kwd-alist))
10753 (interpret (nth 1 ass))
10754 (done-word (nth 3 ass))
10755 (final-done-word (nth 4 ass))
10756 (last-state (or this ""))
10757 (completion-ignore-case t)
10758 (member (member this org-todo-keywords-1))
10759 (tail (cdr member))
10760 (state (cond
10761 ((and org-todo-key-trigger
10762 (or (and (equal arg '(4))
10763 (eq org-use-fast-todo-selection 'prefix))
10764 (and (not arg) org-use-fast-todo-selection
10765 (not (eq org-use-fast-todo-selection
10766 'prefix)))))
10767 ;; Use fast selection
10768 (org-fast-todo-selection))
10769 ((and (equal arg '(4))
10770 (or (not org-use-fast-todo-selection)
10771 (not org-todo-key-trigger)))
10772 ;; Read a state with completion
54a0dee5 10773 (org-icompleting-read
6c817206
CD
10774 "State: " (mapcar (lambda(x) (list x))
10775 org-todo-keywords-1)
10776 nil t))
10777 ((eq arg 'right)
20908596 10778 (if this
6c817206
CD
10779 (if tail (car tail) nil)
10780 (car org-todo-keywords-1)))
10781 ((eq arg 'left)
10782 (if (equal member org-todo-keywords-1)
10783 nil
10784 (if this
10785 (nth (- (length org-todo-keywords-1)
10786 (length tail) 2)
10787 org-todo-keywords-1)
10788 (org-last org-todo-keywords-1))))
10789 ((and (eq org-use-fast-todo-selection t) (equal arg '(4))
10790 (setq arg nil))) ; hack to fall back to cycling
10791 (arg
10792 ;; user or caller requests a specific state
10793 (cond
10794 ((equal arg "") nil)
10795 ((eq arg 'none) nil)
10796 ((eq arg 'done) (or done-word (car org-done-keywords)))
10797 ((eq arg 'nextset)
20908596 10798 (or (car (cdr (member head org-todo-heads)))
6c817206
CD
10799 (car org-todo-heads)))
10800 ((eq arg 'previousset)
10801 (let ((org-todo-heads (reverse org-todo-heads)))
10802 (or (car (cdr (member head org-todo-heads)))
10803 (car org-todo-heads))))
10804 ((car (member arg org-todo-keywords-1)))
8bfe682a
CD
10805 ((stringp arg)
10806 (error "State `%s' not valid in this file" arg))
6c817206
CD
10807 ((nth (1- (prefix-numeric-value arg))
10808 org-todo-keywords-1))))
10809 ((null member) (or head (car org-todo-keywords-1)))
10810 ((equal this final-done-word) nil) ;; -> make empty
10811 ((null tail) nil) ;; -> first entry
6c817206
CD
10812 ((memq interpret '(type priority))
10813 (if (eq this-command last-command)
10814 (car tail)
10815 (if (> (length tail) 0)
10816 (or done-word (car org-done-keywords))
10817 nil)))
c8d0cf5c
CD
10818 (t
10819 (car tail))))
10820 (state (or
10821 (run-hook-with-args-until-success
10822 'org-todo-get-default-hook state last-state)
10823 state))
6c817206
CD
10824 (next (if state (concat " " state " ") " "))
10825 (change-plist (list :type 'todo-state-change :from this :to state
10826 :position startpos))
10827 dolog now-done-p)
10828 (when org-blocker-hook
10829 (setq org-last-todo-state-is-todo
10830 (not (member this org-done-keywords)))
10831 (unless (save-excursion
10832 (save-match-data
10833 (run-hook-with-args-until-failure
10834 'org-blocker-hook change-plist)))
10835 (if (interactive-p)
10836 (error "TODO state change from %s to %s blocked" this state)
10837 ;; fail silently
10838 (message "TODO state change from %s to %s blocked" this state)
10839 (throw 'exit nil))))
10840 (store-match-data match-data)
10841 (replace-match next t t)
10842 (unless (pos-visible-in-window-p hl-pos)
10843 (message "TODO state changed to %s" (org-trim next)))
10844 (unless head
10845 (setq head (org-get-todo-sequence-head state)
10846 ass (assoc head org-todo-kwd-alist)
10847 interpret (nth 1 ass)
10848 done-word (nth 3 ass)
10849 final-done-word (nth 4 ass)))
10850 (when (memq arg '(nextset previousset))
10851 (message "Keyword-Set %d/%d: %s"
10852 (- (length org-todo-sets) -1
10853 (length (memq (assoc state org-todo-sets) org-todo-sets)))
10854 (length org-todo-sets)
10855 (mapconcat 'identity (assoc state org-todo-sets) " ")))
65c439fd 10856 (setq org-last-todo-state-is-todo
6c817206
CD
10857 (not (member state org-done-keywords)))
10858 (setq now-done-p (and (member state org-done-keywords)
10859 (not (member this org-done-keywords))))
10860 (and logging (org-local-logging logging))
10861 (when (and (or org-todo-log-states org-log-done)
c8d0cf5c 10862 (not (eq org-inhibit-logging t))
6c817206
CD
10863 (not (memq arg '(nextset previousset))))
10864 ;; we need to look at recording a time and note
10865 (setq dolog (or (nth 1 (assoc state org-todo-log-states))
10866 (nth 2 (assoc this org-todo-log-states))))
c8d0cf5c
CD
10867 (if (and (eq dolog 'note) (eq org-inhibit-logging 'note))
10868 (setq dolog 'time))
6c817206
CD
10869 (when (and state
10870 (member state org-not-done-keywords)
10871 (not (member this org-not-done-keywords)))
10872 ;; This is now a todo state and was not one before
10873 ;; If there was a CLOSED time stamp, get rid of it.
10874 (org-add-planning-info nil nil 'closed))
10875 (when (and now-done-p org-log-done)
10876 ;; It is now done, and it was not done before
10877 (org-add-planning-info 'closed (org-current-time))
10878 (if (and (not dolog) (eq 'note org-log-done))
c8d0cf5c 10879 (org-add-log-setup 'done state this 'findpos 'note)))
6c817206
CD
10880 (when (and state dolog)
10881 ;; This is a non-nil state, and we need to log it
c8d0cf5c 10882 (org-add-log-setup 'state state this 'findpos dolog)))
6c817206
CD
10883 ;; Fixup tag positioning
10884 (org-todo-trigger-tag-changes state)
10885 (and org-auto-align-tags (not org-setting-tags) (org-set-tags nil t))
10886 (when org-provide-todo-statistics
10887 (org-update-parent-todo-statistics))
10888 (run-hooks 'org-after-todo-state-change-hook)
10889 (if (and arg (not (member state org-done-keywords)))
10890 (setq head (org-get-todo-sequence-head state)))
10891 (put-text-property (point-at-bol) (point-at-eol) 'org-todo-head head)
10892 ;; Do we need to trigger a repeat?
10893 (when now-done-p
10894 (when (boundp 'org-agenda-headline-snapshot-before-repeat)
10895 ;; This is for the agenda, take a snapshot of the headline.
10896 (save-match-data
10897 (setq org-agenda-headline-snapshot-before-repeat
10898 (org-get-heading))))
10899 (org-auto-repeat-maybe state))
10900 ;; Fixup cursor location if close to the keyword
10901 (if (and (outline-on-heading-p)
10902 (not (bolp))
10903 (save-excursion (beginning-of-line 1)
10904 (looking-at org-todo-line-regexp))
10905 (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
10906 (progn
10907 (goto-char (or (match-end 2) (match-end 1)))
c8d0cf5c 10908 (and (looking-at " ") (just-one-space))))
6c817206
CD
10909 (when org-trigger-hook
10910 (save-excursion
10911 (run-hook-with-args 'org-trigger-hook change-plist))))))))
fbe6c10d 10912
c8d0cf5c 10913(defun org-block-todo-from-children-or-siblings-or-parent (change-plist)
d6685abc
CD
10914 "Block turning an entry into a TODO, using the hierarchy.
10915This checks whether the current task should be blocked from state
10916changes. Such blocking occurs when:
10917
10918 1. The task has children which are not all in a completed state.
10919
10920 2. A task has a parent with the property :ORDERED:, and there
10921 are siblings prior to the current task with incomplete
c8d0cf5c
CD
10922 status.
10923
10924 3. The parent of the task is blocked because it has siblings that should
10925 be done first, or is child of a block grandparent TODO entry."
10926
ed21c5c8
CD
10927 (if (not org-enforce-todo-dependencies)
10928 t ; if locally turned off don't block
10929 (catch 'dont-block
10930 ;; If this is not a todo state change, or if this entry is already DONE,
10931 ;; do not block
10932 (when (or (not (eq (plist-get change-plist :type) 'todo-state-change))
10933 (member (plist-get change-plist :from)
10934 (cons 'done org-done-keywords))
10935 (member (plist-get change-plist :to)
10936 (cons 'todo org-not-done-keywords))
10937 (not (plist-get change-plist :to)))
10938 (throw 'dont-block t))
10939 ;; If this task has children, and any are undone, it's blocked
10940 (save-excursion
10941 (org-back-to-heading t)
10942 (let ((this-level (funcall outline-level)))
10943 (outline-next-heading)
10944 (let ((child-level (funcall outline-level)))
10945 (while (and (not (eobp))
10946 (> child-level this-level))
10947 ;; this todo has children, check whether they are all
10948 ;; completed
10949 (if (and (not (org-entry-is-done-p))
10950 (org-entry-is-todo-p))
10951 (throw 'dont-block nil))
10952 (outline-next-heading)
10953 (setq child-level (funcall outline-level))))))
10954 ;; Otherwise, if the task's parent has the :ORDERED: property, and
10955 ;; any previous siblings are undone, it's blocked
10956 (save-excursion
10957 (org-back-to-heading t)
10958 (let* ((pos (point))
10959 (parent-pos (and (org-up-heading-safe) (point))))
c8d0cf5c 10960 (if (not parent-pos) (throw 'dont-block t)) ; no parent
86fbb8ca 10961 (when (and (org-not-nil (org-entry-get (point) "ORDERED"))
c8d0cf5c
CD
10962 (forward-line 1)
10963 (re-search-forward org-not-done-heading-regexp pos t))
ed21c5c8
CD
10964 (throw 'dont-block nil)) ; block, there is an older sibling not done.
10965 ;; Search further up the hierarchy, to see if an anchestor is blocked
10966 (while t
10967 (goto-char parent-pos)
10968 (if (not (looking-at org-not-done-heading-regexp))
10969 (throw 'dont-block t)) ; do not block, parent is not a TODO
10970 (setq pos (point))
10971 (setq parent-pos (and (org-up-heading-safe) (point)))
10972 (if (not parent-pos) (throw 'dont-block t)) ; no parent
86fbb8ca 10973 (when (and (org-not-nil (org-entry-get (point) "ORDERED"))
ed21c5c8
CD
10974 (forward-line 1)
10975 (re-search-forward org-not-done-heading-regexp pos t))
10976 (throw 'dont-block nil)))))))) ; block, older sibling not done.
c8d0cf5c
CD
10977
10978(defcustom org-track-ordered-property-with-tag nil
10979 "Should the ORDERED property also be shown as a tag?
10980The ORDERED property decides if an entry should require subtasks to be
10981completed in sequence. Since a property is not very visible, setting
10982this option means that toggling the ORDERED property with the command
10983`org-toggle-ordered-property' will also toggle a tag ORDERED. That tag is
10984not relevant for the behavior, but it makes things more visible.
10985
10986Note that toggling the tag with tags commands will not change the property
10987and therefore not influence behavior!
10988
10989This can be t, meaning the tag ORDERED should be used, It can also be a
10990string to select a different tag for this task."
10991 :group 'org-todo
10992 :type '(choice
10993 (const :tag "No tracking" nil)
10994 (const :tag "Track with ORDERED tag" t)
10995 (string :tag "Use other tag")))
d6685abc 10996
a2a2e7fb 10997(defun org-toggle-ordered-property ()
c8d0cf5c
CD
10998 "Toggle the ORDERED property of the current entry.
10999For better visibility, you can track the value of this property with a tag.
11000See variable `org-track-ordered-property-with-tag'."
a2a2e7fb 11001 (interactive)
c8d0cf5c
CD
11002 (let* ((t1 org-track-ordered-property-with-tag)
11003 (tag (and t1 (if (stringp t1) t1 "ORDERED"))))
11004 (save-excursion
11005 (org-back-to-heading)
11006 (if (org-entry-get nil "ORDERED")
11007 (progn
11008 (org-delete-property "ORDERED")
11009 (and tag (org-toggle-tag tag 'off))
11010 (message "Subtasks can be completed in arbitrary order"))
11011 (org-entry-put nil "ORDERED" "t")
11012 (and tag (org-toggle-tag tag 'on))
11013 (message "Subtasks must be completed in sequence")))))
11014
11015(defvar org-blocked-by-checkboxes) ; dynamically scoped
6c817206
CD
11016(defun org-block-todo-from-checkboxes (change-plist)
11017 "Block turning an entry into a TODO, using checkboxes.
11018This checks whether the current task should be blocked from state
8bfe682a 11019changes because there are unchecked boxes in this entry."
ed21c5c8
CD
11020 (if (not org-enforce-todo-checkbox-dependencies)
11021 t ; if locally turned off don't block
11022 (catch 'dont-block
11023 ;; If this is not a todo state change, or if this entry is already DONE,
11024 ;; do not block
11025 (when (or (not (eq (plist-get change-plist :type) 'todo-state-change))
11026 (member (plist-get change-plist :from)
11027 (cons 'done org-done-keywords))
11028 (member (plist-get change-plist :to)
11029 (cons 'todo org-not-done-keywords))
11030 (not (plist-get change-plist :to)))
11031 (throw 'dont-block t))
11032 ;; If this task has checkboxes that are not checked, it's blocked
11033 (save-excursion
11034 (org-back-to-heading t)
11035 (let ((beg (point)) end)
11036 (outline-next-heading)
11037 (setq end (point))
11038 (goto-char beg)
11039 (if (re-search-forward "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\)[ \t]+\\[[- ]\\]"
11040 end t)
11041 (progn
11042 (if (boundp 'org-blocked-by-checkboxes)
11043 (setq org-blocked-by-checkboxes t))
11044 (throw 'dont-block nil)))))
11045 t))) ; do not block
11046
11047(defun org-entry-blocked-p ()
11048 "Is the current entry blocked?"
11049 (if (org-entry-get nil "NOBLOCKING")
11050 nil ;; Never block this entry
11051 (not
11052 (run-hook-with-args-until-failure
11053 'org-blocker-hook
11054 (list :type 'todo-state-change
11055 :position (point)
11056 :from 'todo
11057 :to 'done)))))
6c817206 11058
54a0dee5
CD
11059(defun org-update-statistics-cookies (all)
11060 "Update the statistics cookie, either from TODO or from checkboxes.
11061This should be called with the cursor in a line with a statistics cookie."
11062 (interactive "P")
11063 (if all
11064 (progn
11065 (org-update-checkbox-count 'all)
11066 (org-map-entries 'org-update-parent-todo-statistics))
11067 (if (not (org-on-heading-p))
11068 (org-update-checkbox-count)
11069 (let ((pos (move-marker (make-marker) (point)))
11070 end l1 l2)
11071 (ignore-errors (org-back-to-heading t))
11072 (if (not (org-on-heading-p))
11073 (org-update-checkbox-count)
11074 (setq l1 (org-outline-level))
11075 (setq end (save-excursion
11076 (outline-next-heading)
11077 (if (org-on-heading-p) (setq l2 (org-outline-level)))
11078 (point)))
ed21c5c8
CD
11079 (if (and (save-excursion
11080 (re-search-forward
11081 "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) \\[[- X]\\]" end t))
54a0dee5
CD
11082 (not (save-excursion (re-search-forward
11083 ":COOKIE_DATA:.*\\<todo\\>" end t))))
11084 (org-update-checkbox-count)
11085 (if (and l2 (> l2 l1))
11086 (progn
11087 (goto-char end)
11088 (org-update-parent-todo-statistics))
ed21c5c8
CD
11089 (goto-char pos)
11090 (beginning-of-line 1)
11091 (while (re-search-forward
11092 "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)"
11093 (point-at-eol) t)
11094 (replace-match (if (match-end 2) "[100%]" "[0/0]") t t)))))
54a0dee5
CD
11095 (goto-char pos)
11096 (move-marker pos nil)))))
f924a367 11097
c8d0cf5c 11098(defvar org-entry-property-inherited-from) ;; defined below
b349f79f 11099(defun org-update-parent-todo-statistics ()
c8d0cf5c
CD
11100 "Update any statistics cookie in the parent of the current headline.
11101When `org-hierarchical-todo-statistics' is nil, statistics will cover
11102the entire subtree and this will travel up the hierarchy and update
11103statistics everywhere."
b349f79f 11104 (interactive)
c8d0cf5c
CD
11105 (let* ((lim 0) prop
11106 (recursive (or (not org-hierarchical-todo-statistics)
11107 (string-match
11108 "\\<recursive\\>"
11109 (or (setq prop (org-entry-get
11110 nil "COOKIE_DATA" 'inherit)) ""))))
11111 (lim (or (and prop (marker-position
11112 org-entry-property-inherited-from))
11113 lim))
11114 (first t)
11115 (box-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)")
8d642074 11116 level ltoggle l1 new ndel
c8d0cf5c 11117 (cnt-all 0) (cnt-done 0) is-percent kwd cookie-present)
b349f79f
CD
11118 (catch 'exit
11119 (save-excursion
c8d0cf5c
CD
11120 (beginning-of-line 1)
11121 (if (org-at-heading-p)
11122 (setq ltoggle (funcall outline-level))
11123 (error "This should not happen"))
11124 (while (and (setq level (org-up-heading-safe))
11125 (or recursive first)
11126 (>= (point) lim))
8bfe682a 11127 (setq first nil cookie-present nil)
c8d0cf5c
CD
11128 (unless (and level
11129 (not (string-match
11130 "\\<checkbox\\>"
11131 (downcase
11132 (or (org-entry-get
11133 nil "COOKIE_DATA")
11134 "")))))
11135 (throw 'exit nil))
11136 (while (re-search-forward box-re (point-at-eol) t)
11137 (setq cnt-all 0 cnt-done 0 cookie-present t)
11138 (setq is-percent (match-end 2))
11139 (save-match-data
11140 (unless (outline-next-heading) (throw 'exit nil))
11141 (while (and (looking-at org-complex-heading-regexp)
11142 (> (setq l1 (length (match-string 1))) level))
11143 (setq kwd (and (or recursive (= l1 ltoggle))
11144 (match-string 2)))
11145 (if (or (eq org-provide-todo-statistics 'all-headlines)
11146 (and (listp org-provide-todo-statistics)
11147 (or (member kwd org-provide-todo-statistics)
11148 (member kwd org-done-keywords))))
11149 (setq cnt-all (1+ cnt-all))
11150 (if (eq org-provide-todo-statistics t)
11151 (and kwd (setq cnt-all (1+ cnt-all)))))
11152 (and (member kwd org-done-keywords)
11153 (setq cnt-done (1+ cnt-done)))
11154 (outline-next-heading)))
8d642074
CD
11155 (setq new
11156 (if is-percent
11157 (format "[%d%%]" (/ (* 100 cnt-done) (max 1 cnt-all)))
11158 (format "[%d/%d]" cnt-done cnt-all))
11159 ndel (- (match-end 0) (match-beginning 0)))
11160 (goto-char (match-beginning 0))
11161 (insert new)
8bfe682a
CD
11162 (delete-region (point) (+ (point) ndel)))
11163 (when cookie-present
11164 (run-hook-with-args 'org-after-todo-statistics-hook
11165 cnt-done (- cnt-all cnt-done))))))
c8d0cf5c 11166 (run-hooks 'org-todo-statistics-hook)))
b349f79f
CD
11167
11168(defvar org-after-todo-statistics-hook nil
11169 "Hook that is called after a TODO statistics cookie has been updated.
11170Each function is called with two arguments: the number of not-done entries
11171and the number of done entries.
11172
11173For example, the following function, when added to this hook, will switch
11174an entry to DONE when all children are done, and back to TODO when new
11175entries are set to a TODO status. Note that this hook is only called
11176when there is a statistics cookie in the headline!
11177
11178 (defun org-summary-todo (n-done n-not-done)
11179 \"Switch entry to DONE when all subentries are done, to TODO otherwise.\"
11180 (let (org-log-done org-log-states) ; turn off logging
11181 (org-todo (if (= n-not-done 0) \"DONE\" \"TODO\"))))
11182")
71d35b24 11183
c8d0cf5c
CD
11184(defvar org-todo-statistics-hook nil
11185 "Hook that is run whenever Org thinks TODO statistics should be updated.
8bfe682a 11186This hook runs even if there is no statistics cookie present, in which case
c8d0cf5c
CD
11187`org-after-todo-statistics-hook' would not run.")
11188
71d35b24
CD
11189(defun org-todo-trigger-tag-changes (state)
11190 "Apply the changes defined in `org-todo-state-tags-triggers'."
11191 (let ((l org-todo-state-tags-triggers)
11192 changes)
11193 (when (or (not state) (equal state ""))
11194 (setq changes (append changes (cdr (assoc "" l)))))
11195 (when (and (stringp state) (> (length state) 0))
11196 (setq changes (append changes (cdr (assoc state l)))))
11197 (when (member state org-not-done-keywords)
11198 (setq changes (append changes (cdr (assoc 'todo l)))))
11199 (when (member state org-done-keywords)
11200 (setq changes (append changes (cdr (assoc 'done l)))))
11201 (dolist (c changes)
11202 (org-toggle-tag (car c) (if (cdr c) 'on 'off)))))
ce4fdcb9 11203
20908596
CD
11204(defun org-local-logging (value)
11205 "Get logging settings from a property VALUE."
11206 (let* (words w a)
11207 ;; directly set the variables, they are already local.
11208 (setq org-log-done nil
11209 org-log-repeat nil
11210 org-todo-log-states nil)
11211 (setq words (org-split-string value))
11212 (while (setq w (pop words))
11213 (cond
11214 ((setq a (assoc w org-startup-options))
11215 (and (member (nth 1 a) '(org-log-done org-log-repeat))
11216 (set (nth 1 a) (nth 2 a))))
11217 ((setq a (org-extract-log-state-settings w))
11218 (and (member (car a) org-todo-keywords-1)
11219 (push a org-todo-log-states)))))))
03f3cf35 11220
20908596
CD
11221(defun org-get-todo-sequence-head (kwd)
11222 "Return the head of the TODO sequence to which KWD belongs.
11223If KWD is not set, check if there is a text property remembering the
11224right sequence."
11225 (let (p)
11226 (cond
11227 ((not kwd)
11228 (or (get-text-property (point-at-bol) 'org-todo-head)
03f3cf35 11229 (progn
20908596
CD
11230 (setq p (next-single-property-change (point-at-bol) 'org-todo-head
11231 nil (point-at-eol)))
11232 (get-text-property p 'org-todo-head))))
11233 ((not (member kwd org-todo-keywords-1))
11234 (car org-todo-keywords-1))
11235 (t (nth 2 (assoc kwd org-todo-kwd-alist))))))
891f4676 11236
20908596
CD
11237(defun org-fast-todo-selection ()
11238 "Fast TODO keyword selection with single keys.
11239Returns the new TODO keyword, or nil if no state change should occur."
11240 (let* ((fulltable org-todo-key-alist)
11241 (done-keywords org-done-keywords) ;; needed for the faces.
11242 (maxlen (apply 'max (mapcar
11243 (lambda (x)
11244 (if (stringp (car x)) (string-width (car x)) 0))
11245 fulltable)))
11246 (expert nil)
11247 (fwidth (+ maxlen 3 1 3))
11248 (ncol (/ (- (window-width) 4) fwidth))
11249 tg cnt e c tbl
11250 groups ingroup)
d6685abc
CD
11251 (save-excursion
11252 (save-window-excursion
11253 (if expert
11254 (set-buffer (get-buffer-create " *Org todo*"))
11255 (org-switch-to-buffer-other-window (get-buffer-create " *Org todo*")))
11256 (erase-buffer)
11257 (org-set-local 'org-done-keywords done-keywords)
11258 (setq tbl fulltable cnt 0)
11259 (while (setq e (pop tbl))
11260 (cond
11261 ((equal e '(:startgroup))
11262 (push '() groups) (setq ingroup t)
11263 (when (not (= cnt 0))
11264 (setq cnt 0)
11265 (insert "\n"))
11266 (insert "{ "))
11267 ((equal e '(:endgroup))
11268 (setq ingroup nil cnt 0)
11269 (insert "}\n"))
c8d0cf5c
CD
11270 ((equal e '(:newline))
11271 (when (not (= cnt 0))
11272 (setq cnt 0)
11273 (insert "\n")
11274 (setq e (car tbl))
11275 (while (equal (car tbl) '(:newline))
11276 (insert "\n")
11277 (setq tbl (cdr tbl)))))
d6685abc
CD
11278 (t
11279 (setq tg (car e) c (cdr e))
11280 (if ingroup (push tg (car groups)))
11281 (setq tg (org-add-props tg nil 'face
11282 (org-get-todo-face tg)))
11283 (if (and (= cnt 0) (not ingroup)) (insert " "))
11284 (insert "[" c "] " tg (make-string
11285 (- fwidth 4 (length tg)) ?\ ))
11286 (when (= (setq cnt (1+ cnt)) ncol)
11287 (insert "\n")
11288 (if ingroup (insert " "))
11289 (setq cnt 0)))))
11290 (insert "\n")
11291 (goto-char (point-min))
11292 (if (not expert) (org-fit-window-to-buffer))
11293 (message "[a-z..]:Set [SPC]:clear")
11294 (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
20908596 11295 (cond
d6685abc
CD
11296 ((or (= c ?\C-g)
11297 (and (= c ?q) (not (rassoc c fulltable))))
11298 (setq quit-flag t))
11299 ((= c ?\ ) nil)
11300 ((setq e (rassoc c fulltable) tg (car e))
11301 tg)
11302 (t (setq quit-flag t)))))))
ab27a4a0 11303
20908596
CD
11304(defun org-entry-is-todo-p ()
11305 (member (org-get-todo-state) org-not-done-keywords))
11306
11307(defun org-entry-is-done-p ()
11308 (member (org-get-todo-state) org-done-keywords))
11309
11310(defun org-get-todo-state ()
11311 (save-excursion
11312 (org-back-to-heading t)
11313 (and (looking-at org-todo-line-regexp)
11314 (match-end 2)
11315 (match-string 2))))
11316
11317(defun org-at-date-range-p (&optional inactive-ok)
11318 "Is the cursor inside a date range?"
d3f4dbe8 11319 (interactive)
20908596
CD
11320 (save-excursion
11321 (catch 'exit
11322 (let ((pos (point)))
11323 (skip-chars-backward "^[<\r\n")
11324 (skip-chars-backward "<[")
11325 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
11326 (>= (match-end 0) pos)
11327 (throw 'exit t))
11328 (skip-chars-backward "^<[\r\n")
11329 (skip-chars-backward "<[")
11330 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
11331 (>= (match-end 0) pos)
11332 (throw 'exit t)))
11333 nil)))
891f4676 11334
8bfe682a 11335(defun org-get-repeat (&optional tagline)
2c3ad40d 11336 "Check if there is a deadline/schedule with repeater in this entry."
20908596
CD
11337 (save-match-data
11338 (save-excursion
11339 (org-back-to-heading t)
8bfe682a
CD
11340 (and (re-search-forward (if tagline
11341 (concat tagline "\\s-*" org-repeat-re)
11342 org-repeat-re)
11343 (org-entry-end-position) t)
11344 (match-string-no-properties 1)))))
891f4676 11345
20908596 11346(defvar org-last-changed-timestamp)
b349f79f 11347(defvar org-last-inserted-timestamp)
20908596
CD
11348(defvar org-log-post-message)
11349(defvar org-log-note-purpose)
11350(defvar org-log-note-how)
621f83e4 11351(defvar org-log-note-extra)
20908596
CD
11352(defun org-auto-repeat-maybe (done-word)
11353 "Check if the current headline contains a repeated deadline/schedule.
11354If yes, set TODO state back to what it was and change the base date
11355of repeating deadline/scheduled time stamps to new date.
11356This function is run automatically after each state change to a DONE state."
11357 ;; last-state is dynamically scoped into this function
11358 (let* ((repeat (org-get-repeat))
11359 (aa (assoc last-state org-todo-kwd-alist))
11360 (interpret (nth 1 aa))
11361 (head (nth 2 aa))
11362 (whata '(("d" . day) ("m" . month) ("y" . year)))
11363 (msg "Entry repeats: ")
11364 (org-log-done nil)
11365 (org-todo-log-states nil)
86fbb8ca 11366 re type n what ts time to-state)
20908596
CD
11367 (when repeat
11368 (if (eq org-log-repeat t) (setq org-log-repeat 'state))
86fbb8ca
CD
11369 (setq to-state (or (org-entry-get nil "REPEAT_TO_STATE")
11370 org-todo-repeat-to-state))
11371 (unless (and to-state (member to-state org-todo-keywords-1))
11372 (setq to-state (if (eq interpret 'type) last-state head)))
11373 (org-todo to-state)
11374 (when (or org-log-repeat (org-entry-get nil "CLOCK"))
11375 (org-entry-put nil "LAST_REPEAT" (format-time-string
11376 (org-time-stamp-format t t))))
20908596
CD
11377 (when org-log-repeat
11378 (if (or (memq 'org-add-log-note (default-value 'post-command-hook))
11379 (memq 'org-add-log-note post-command-hook))
11380 ;; OK, we are already setup for some record
11381 (if (eq org-log-repeat 'note)
11382 ;; make sure we take a note, not only a time stamp
11383 (setq org-log-note-how 'note))
11384 ;; Set up for taking a record
11385 (org-add-log-setup 'state (or done-word (car org-done-keywords))
c8d0cf5c 11386 last-state
20908596
CD
11387 'findpos org-log-repeat)))
11388 (org-back-to-heading t)
11389 (org-add-planning-info nil nil 'closed)
11390 (setq re (concat "\\(" org-scheduled-time-regexp "\\)\\|\\("
11391 org-deadline-time-regexp "\\)\\|\\("
11392 org-ts-regexp "\\)"))
11393 (while (re-search-forward
11394 re (save-excursion (outline-next-heading) (point)) t)
11395 (setq type (if (match-end 1) org-scheduled-string
11396 (if (match-end 3) org-deadline-string "Plain:"))
65c439fd 11397 ts (match-string (if (match-end 2) 2 (if (match-end 4) 4 0))))
20908596
CD
11398 (when (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([dwmy]\\)" ts)
11399 (setq n (string-to-number (match-string 2 ts))
11400 what (match-string 3 ts))
11401 (if (equal what "w") (setq n (* n 7) what "d"))
11402 ;; Preparation, see if we need to modify the start date for the change
11403 (when (match-end 1)
11404 (setq time (save-match-data (org-time-string-to-time ts)))
11405 (cond
11406 ((equal (match-string 1 ts) ".")
11407 ;; Shift starting date to today
11408 (org-timestamp-change
11409 (- (time-to-days (current-time)) (time-to-days time))
11410 'day))
11411 ((equal (match-string 1 ts) "+")
afe98dfa
CD
11412 (let ((nshiftmax 10) (nshift 0))
11413 (while (or (= nshift 0)
11414 (<= (time-to-days time)
11415 (time-to-days (current-time))))
11416 (when (= (incf nshift) nshiftmax)
11417 (or (y-or-n-p (message "%d repeater intervals were not enough to shift date past today. Continue? " nshift))
11418 (error "Abort")))
11419 (org-timestamp-change n (cdr (assoc what whata)))
11420 (org-at-timestamp-p t)
11421 (setq ts (match-string 1))
11422 (setq time (save-match-data (org-time-string-to-time ts)))))
20908596
CD
11423 (org-timestamp-change (- n) (cdr (assoc what whata)))
11424 ;; rematch, so that we have everything in place for the real shift
11425 (org-at-timestamp-p t)
11426 (setq ts (match-string 1))
11427 (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([dwmy]\\)" ts))))
11428 (org-timestamp-change n (cdr (assoc what whata)))
621f83e4 11429 (setq msg (concat msg type " " org-last-changed-timestamp " "))))
20908596
CD
11430 (setq org-log-post-message msg)
11431 (message "%s" msg))))
891f4676 11432
20908596
CD
11433(defun org-show-todo-tree (arg)
11434 "Make a compact tree which shows all headlines marked with TODO.
11435The tree will show the lines where the regexp matches, and all higher
11436headlines above the match.
c8d0cf5c 11437With a \\[universal-argument] prefix, prompt for a regexp to match.
20908596
CD
11438With a numeric prefix N, construct a sparse tree for the Nth element
11439of `org-todo-keywords-1'."
11440 (interactive "P")
11441 (let ((case-fold-search nil)
11442 (kwd-re
11443 (cond ((null arg) org-not-done-regexp)
11444 ((equal arg '(4))
54a0dee5 11445 (let ((kwd (org-icompleting-read "Keyword (or KWD1|KWD2|...): "
20908596
CD
11446 (mapcar 'list org-todo-keywords-1))))
11447 (concat "\\("
11448 (mapconcat 'identity (org-split-string kwd "|") "\\|")
11449 "\\)\\>")))
11450 ((<= (prefix-numeric-value arg) (length org-todo-keywords-1))
11451 (regexp-quote (nth (1- (prefix-numeric-value arg))
11452 org-todo-keywords-1)))
11453 (t (error "Invalid prefix argument: %s" arg)))))
11454 (message "%d TODO entries found"
11455 (org-occur (concat "^" outline-regexp " *" kwd-re )))))
891f4676 11456
b349f79f 11457(defun org-deadline (&optional remove time)
20908596 11458 "Insert the \"DEADLINE:\" string with a timestamp to make a deadline.
b349f79f
CD
11459With argument REMOVE, remove any deadline from the item.
11460When TIME is set, it should be an internal time specification, and the
11461scheduling will use the corresponding date."
20908596 11462 (interactive "P")
ed21c5c8
CD
11463 (let* ((old-date (org-entry-get nil "DEADLINE"))
11464 (repeater (and old-date
11465 (string-match "\\([.+]+[0-9]+[dwmy]\\) ?" old-date)
11466 (match-string 1 old-date))))
8bfe682a
CD
11467 (if remove
11468 (progn
ed21c5c8
CD
11469 (when (and old-date org-log-redeadline)
11470 (org-add-log-setup 'deldeadline nil old-date 'findpos
11471 org-log-redeadline))
8bfe682a
CD
11472 (org-remove-timestamp-with-keyword org-deadline-string)
11473 (message "Item no longer has a deadline."))
ed21c5c8
CD
11474 (org-add-planning-info 'deadline time 'closed)
11475 (when (and old-date org-log-redeadline
11476 (not (equal old-date
11477 (substring org-last-inserted-timestamp 1 -1))))
11478 (org-add-log-setup 'redeadline nil old-date 'findpos
11479 org-log-redeadline))
11480 (when repeater
11481 (save-excursion
11482 (org-back-to-heading t)
11483 (when (re-search-forward (concat org-deadline-string " "
11484 org-last-inserted-timestamp)
11485 (save-excursion
11486 (outline-next-heading) (point)) t)
11487 (goto-char (1- (match-end 0)))
11488 (insert " " repeater)
11489 (setq org-last-inserted-timestamp
11490 (concat (substring org-last-inserted-timestamp 0 -1)
11491 " " repeater
11492 (substring org-last-inserted-timestamp -1))))))
11493 (message "Deadline on %s" org-last-inserted-timestamp))))
db4a7382 11494
b349f79f 11495(defun org-schedule (&optional remove time)
20908596 11496 "Insert the SCHEDULED: string with a timestamp to schedule a TODO item.
b349f79f
CD
11497With argument REMOVE, remove any scheduling date from the item.
11498When TIME is set, it should be an internal time specification, and the
11499scheduling will use the corresponding date."
20908596 11500 (interactive "P")
ed21c5c8
CD
11501 (let* ((old-date (org-entry-get nil "SCHEDULED"))
11502 (repeater (and old-date
11503 (string-match "\\([.+]+[0-9]+[dwmy]\\) ?" old-date)
11504 (match-string 1 old-date))))
8bfe682a
CD
11505 (if remove
11506 (progn
ed21c5c8
CD
11507 (when (and old-date org-log-reschedule)
11508 (org-add-log-setup 'delschedule nil old-date 'findpos
11509 org-log-reschedule))
8bfe682a
CD
11510 (org-remove-timestamp-with-keyword org-scheduled-string)
11511 (message "Item is no longer scheduled."))
ed21c5c8
CD
11512 (org-add-planning-info 'scheduled time 'closed)
11513 (when (and old-date org-log-reschedule
11514 (not (equal old-date
11515 (substring org-last-inserted-timestamp 1 -1))))
11516 (org-add-log-setup 'reschedule nil old-date 'findpos
11517 org-log-reschedule))
11518 (when repeater
11519 (save-excursion
11520 (org-back-to-heading t)
11521 (when (re-search-forward (concat org-scheduled-string " "
11522 org-last-inserted-timestamp)
11523 (save-excursion
11524 (outline-next-heading) (point)) t)
11525 (goto-char (1- (match-end 0)))
11526 (insert " " repeater)
11527 (setq org-last-inserted-timestamp
11528 (concat (substring org-last-inserted-timestamp 0 -1)
11529 " " repeater
11530 (substring org-last-inserted-timestamp -1))))))
11531 (message "Scheduled to %s" org-last-inserted-timestamp))))
20908596 11532
c8d0cf5c
CD
11533(defun org-get-scheduled-time (pom &optional inherit)
11534 "Get the scheduled time as a time tuple, of a format suitable
11535for calling org-schedule with, or if there is no scheduling,
11536returns nil."
11537 (let ((time (org-entry-get pom "SCHEDULED" inherit)))
11538 (when time
11539 (apply 'encode-time (org-parse-time-string time)))))
11540
11541(defun org-get-deadline-time (pom &optional inherit)
86fbb8ca 11542 "Get the deadline as a time tuple, of a format suitable for
8bfe682a 11543calling org-deadline with, or if there is no scheduling, returns
c8d0cf5c
CD
11544nil."
11545 (let ((time (org-entry-get pom "DEADLINE" inherit)))
11546 (when time
11547 (apply 'encode-time (org-parse-time-string time)))))
11548
20908596
CD
11549(defun org-remove-timestamp-with-keyword (keyword)
11550 "Remove all time stamps with KEYWORD in the current entry."
11551 (let ((re (concat "\\<" (regexp-quote keyword) " +<[^>\n]+>[ \t]*"))
11552 beg)
11553 (save-excursion
11554 (org-back-to-heading t)
11555 (setq beg (point))
54a0dee5 11556 (outline-next-heading)
20908596
CD
11557 (while (re-search-backward re beg t)
11558 (replace-match "")
b349f79f
CD
11559 (if (and (string-match "\\S-" (buffer-substring (point-at-bol) (point)))
11560 (equal (char-before) ?\ ))
11561 (backward-delete-char 1)
11562 (if (string-match "^[ \t]*$" (buffer-substring
11563 (point-at-bol) (point-at-eol)))
11564 (delete-region (point-at-bol)
11565 (min (point-max) (1+ (point-at-eol))))))))))
3278a016 11566
20908596
CD
11567(defun org-add-planning-info (what &optional time &rest remove)
11568 "Insert new timestamp with keyword in the line directly after the headline.
11569WHAT indicates what kind of time stamp to add. TIME indicated the time to use.
11570If non is given, the user is prompted for a date.
11571REMOVE indicates what kind of entries to remove. An old WHAT entry will also
11572be removed."
11573 (interactive)
11574 (let (org-time-was-given org-end-time-was-given ts
11575 end default-time default-input)
0b8568f5 11576
c8d0cf5c
CD
11577 (catch 'exit
11578 (when (and (not time) (memq what '(scheduled deadline)))
11579 ;; Try to get a default date/time from existing timestamp
11580 (save-excursion
20908596 11581 (org-back-to-heading t)
c8d0cf5c
CD
11582 (setq end (save-excursion (outline-next-heading) (point)))
11583 (when (re-search-forward (if (eq what 'scheduled)
11584 org-scheduled-time-regexp
11585 org-deadline-time-regexp)
11586 end t)
11587 (setq ts (match-string 1)
11588 default-time
11589 (apply 'encode-time (org-parse-time-string ts))
11590 default-input (and ts (org-get-compact-tod ts))))))
11591 (when what
11592 ;; If necessary, get the time from the user
11593 (setq time (or time (org-read-date nil 'to-time nil nil
11594 default-time default-input))))
11595
11596 (when (and org-insert-labeled-timestamps-at-point
11597 (member what '(scheduled deadline)))
11598 (insert
11599 (if (eq what 'scheduled) org-scheduled-string org-deadline-string) " ")
11600 (org-insert-time-stamp time org-time-was-given
11601 nil nil nil (list org-end-time-was-given))
11602 (setq what nil))
11603 (save-excursion
11604 (save-restriction
11605 (let (col list elt ts buffer-invisibility-spec)
11606 (org-back-to-heading t)
11607 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"))
11608 (goto-char (match-end 1))
11609 (setq col (current-column))
11610 (goto-char (match-end 0))
11611 (if (eobp) (insert "\n") (forward-char 1))
11612 (when (and (not what)
11613 (not (looking-at
11614 (concat "[ \t]*"
11615 org-keyword-time-not-clock-regexp))))
11616 ;; Nothing to add, nothing to remove...... :-)
11617 (throw 'exit nil))
11618 (if (and (not (looking-at outline-regexp))
11619 (looking-at (concat "[^\r\n]*?" org-keyword-time-regexp
11620 "[^\r\n]*"))
11621 (not (equal (match-string 1) org-clock-string)))
11622 (narrow-to-region (match-beginning 0) (match-end 0))
11623 (insert-before-markers "\n")
11624 (backward-char 1)
11625 (narrow-to-region (point) (point))
11626 (and org-adapt-indentation (org-indent-to-column col)))
11627 ;; Check if we have to remove something.
11628 (setq list (cons what remove))
11629 (while list
11630 (setq elt (pop list))
11631 (goto-char (point-min))
11632 (when (or (and (eq elt 'scheduled)
11633 (re-search-forward org-scheduled-time-regexp nil t))
11634 (and (eq elt 'deadline)
11635 (re-search-forward org-deadline-time-regexp nil t))
11636 (and (eq elt 'closed)
11637 (re-search-forward org-closed-time-regexp nil t)))
11638 (replace-match "")
11639 (if (looking-at "--+<[^>]+>") (replace-match ""))
8d642074 11640 (skip-chars-backward " ")
c8d0cf5c
CD
11641 (if (looking-at " +") (replace-match ""))))
11642 (goto-char (point-max))
8bfe682a 11643 (and org-adapt-indentation (bolp) (org-indent-to-column col))
c8d0cf5c
CD
11644 (when what
11645 (insert
11646 (if (not (or (bolp) (eq (char-before) ?\ ))) " " "")
11647 (cond ((eq what 'scheduled) org-scheduled-string)
11648 ((eq what 'deadline) org-deadline-string)
11649 ((eq what 'closed) org-closed-string))
11650 " ")
11651 (setq ts (org-insert-time-stamp
11652 time
11653 (or org-time-was-given
11654 (and (eq what 'closed) org-log-done-with-time))
11655 (eq what 'closed)
11656 nil nil (list org-end-time-was-given)))
11657 (end-of-line 1))
20908596 11658 (goto-char (point-min))
c8d0cf5c 11659 (widen)
86fbb8ca 11660 (if (and (looking-at "[ \t]*\n")
c8d0cf5c
CD
11661 (equal (char-before) ?\n))
11662 (delete-region (1- (point)) (point-at-eol)))
11663 ts))))))
ab27a4a0 11664
20908596
CD
11665(defvar org-log-note-marker (make-marker))
11666(defvar org-log-note-purpose nil)
11667(defvar org-log-note-state nil)
c8d0cf5c 11668(defvar org-log-note-previous-state nil)
20908596 11669(defvar org-log-note-how nil)
621f83e4 11670(defvar org-log-note-extra nil)
20908596
CD
11671(defvar org-log-note-window-configuration nil)
11672(defvar org-log-note-return-to (make-marker))
11673(defvar org-log-post-message nil
11674 "Message to be displayed after a log note has been stored.
11675The auto-repeater uses this.")
ab27a4a0 11676
20908596
CD
11677(defun org-add-note ()
11678 "Add a note to the current entry.
11679This is done in the same way as adding a state change note."
11680 (interactive)
c8d0cf5c 11681 (org-add-log-setup 'note nil nil 'findpos nil))
8c6fb58b 11682
621f83e4 11683(defvar org-property-end-re)
c8d0cf5c 11684(defun org-add-log-setup (&optional purpose state prev-state
afe98dfa 11685 findpos how extra)
20908596
CD
11686 "Set up the post command hook to take a note.
11687If this is about to TODO state change, the new state is expected in STATE.
11688When FINDPOS is non-nil, find the correct position for the note in
621f83e4
CD
11689the current entry. If not, assume that it can be inserted at point.
11690HOW is an indicator what kind of note should be created.
11691EXTRA is additional text that will be inserted into the notes buffer."
c8d0cf5c
CD
11692 (let* ((org-log-into-drawer (org-log-into-drawer))
11693 (drawer (cond ((stringp org-log-into-drawer)
11694 org-log-into-drawer)
11695 (org-log-into-drawer "LOGBOOK")
11696 (t nil))))
11697 (save-restriction
11698 (save-excursion
11699 (when findpos
11700 (org-back-to-heading t)
11701 (narrow-to-region (point) (save-excursion
11702 (outline-next-heading) (point)))
11703 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"
11704 "\\(\n[^\r\n]*?" org-keyword-time-not-clock-regexp
11705 "[^\r\n]*\\)?"))
11706 (goto-char (match-end 0))
11707 (cond
11708 (drawer
11709 (if (re-search-forward (concat "^[ \t]*:" drawer ":[ \t]*$")
11710 nil t)
11711 (progn
11712 (goto-char (match-end 0))
11713 (or org-log-states-order-reversed
11714 (and (re-search-forward org-property-end-re nil t)
11715 (goto-char (1- (match-beginning 0))))))
11716 (insert "\n:" drawer ":\n:END:")
11717 (beginning-of-line 0)
11718 (org-indent-line-function)
11719 (beginning-of-line 2)
11720 (org-indent-line-function)
11721 (end-of-line 0)))
11722 ((and org-log-state-notes-insert-after-drawers
11723 (save-excursion
11724 (forward-line) (looking-at org-drawer-regexp)))
11725 (forward-line)
11726 (while (looking-at org-drawer-regexp)
11727 (goto-char (match-end 0))
11728 (re-search-forward org-property-end-re (point-max) t)
11729 (forward-line))
11730 (forward-line -1)))
11731 (unless org-log-states-order-reversed
11732 (and (= (char-after) ?\n) (forward-char 1))
11733 (org-skip-over-state-notes)
11734 (skip-chars-backward " \t\n\r")))
11735 (move-marker org-log-note-marker (point))
11736 (setq org-log-note-purpose purpose
11737 org-log-note-state state
11738 org-log-note-previous-state prev-state
11739 org-log-note-how how
11740 org-log-note-extra extra)
11741 (add-hook 'post-command-hook 'org-add-log-note 'append)))))
ab27a4a0 11742
20908596
CD
11743(defun org-skip-over-state-notes ()
11744 "Skip past the list of State notes in an entry."
11745 (if (looking-at "\n[ \t]*- State") (forward-char 1))
afe98dfa
CD
11746 (when (org-in-item-p)
11747 (let ((limit (org-list-bottom-point)))
11748 (while (looking-at "[ \t]*- State")
11749 (goto-char (or (org-get-next-item (point) limit)
11750 (org-get-end-of-item limit)))))))
891f4676 11751
20908596
CD
11752(defun org-add-log-note (&optional purpose)
11753 "Pop up a window for taking a note, and add this note later at point."
11754 (remove-hook 'post-command-hook 'org-add-log-note)
11755 (setq org-log-note-window-configuration (current-window-configuration))
11756 (delete-other-windows)
11757 (move-marker org-log-note-return-to (point))
11758 (switch-to-buffer (marker-buffer org-log-note-marker))
11759 (goto-char org-log-note-marker)
11760 (org-switch-to-buffer-other-window "*Org Note*")
11761 (erase-buffer)
11762 (if (memq org-log-note-how '(time state))
71d35b24 11763 (let (current-prefix-arg) (org-store-log-note))
20908596
CD
11764 (let ((org-inhibit-startup t)) (org-mode))
11765 (insert (format "# Insert note for %s.
11766# Finish with C-c C-c, or cancel with C-c C-k.\n\n"
11767 (cond
11768 ((eq org-log-note-purpose 'clock-out) "stopped clock")
11769 ((eq org-log-note-purpose 'done) "closed todo item")
11770 ((eq org-log-note-purpose 'state)
c8d0cf5c
CD
11771 (format "state change from \"%s\" to \"%s\""
11772 (or org-log-note-previous-state "")
11773 (or org-log-note-state "")))
8bfe682a
CD
11774 ((eq org-log-note-purpose 'reschedule)
11775 "rescheduling")
ed21c5c8
CD
11776 ((eq org-log-note-purpose 'delschedule)
11777 "no longer scheduled")
8bfe682a
CD
11778 ((eq org-log-note-purpose 'redeadline)
11779 "changing deadline")
ed21c5c8
CD
11780 ((eq org-log-note-purpose 'deldeadline)
11781 "removing deadline")
11782 ((eq org-log-note-purpose 'refile)
11783 "refiling")
20908596
CD
11784 ((eq org-log-note-purpose 'note)
11785 "this entry")
11786 (t (error "This should not happen")))))
621f83e4 11787 (if org-log-note-extra (insert org-log-note-extra))
20908596 11788 (org-set-local 'org-finish-function 'org-store-log-note)))
ab27a4a0 11789
20908596
CD
11790(defvar org-note-abort nil) ; dynamically scoped
11791(defun org-store-log-note ()
11792 "Finish taking a log note, and insert it to where it belongs."
11793 (let ((txt (buffer-string))
11794 (note (cdr (assq org-log-note-purpose org-log-note-headings)))
afe98dfa 11795 lines ind bul)
20908596
CD
11796 (kill-buffer (current-buffer))
11797 (while (string-match "\\`#.*\n[ \t\n]*" txt)
11798 (setq txt (replace-match "" t t txt)))
11799 (if (string-match "\\s-+\\'" txt)
11800 (setq txt (replace-match "" t t txt)))
11801 (setq lines (org-split-string txt "\n"))
11802 (when (and note (string-match "\\S-" note))
11803 (setq note
11804 (org-replace-escapes
11805 note
11806 (list (cons "%u" (user-login-name))
11807 (cons "%U" user-full-name)
11808 (cons "%t" (format-time-string
11809 (org-time-stamp-format 'long 'inactive)
11810 (current-time)))
86fbb8ca
CD
11811 (cons "%T" (format-time-string
11812 (org-time-stamp-format 'long nil)
11813 (current-time)))
20908596
CD
11814 (cons "%s" (if org-log-note-state
11815 (concat "\"" org-log-note-state "\"")
c8d0cf5c
CD
11816 ""))
11817 (cons "%S" (if org-log-note-previous-state
11818 (concat "\"" org-log-note-previous-state "\"")
11819 "\"\"")))))
20908596
CD
11820 (if lines (setq note (concat note " \\\\")))
11821 (push note lines))
c8d0cf5c
CD
11822 (when (or current-prefix-arg org-note-abort)
11823 (when org-log-into-drawer
11824 (org-remove-empty-drawer-at
11825 (if (stringp org-log-into-drawer) org-log-into-drawer "LOGBOOK")
11826 org-log-note-marker))
11827 (setq lines nil))
20908596 11828 (when lines
81ad75af 11829 (with-current-buffer (marker-buffer org-log-note-marker)
20908596
CD
11830 (save-excursion
11831 (goto-char org-log-note-marker)
11832 (move-marker org-log-note-marker nil)
11833 (end-of-line 1)
11834 (if (not (bolp)) (let ((inhibit-read-only t)) (insert "\n")))
afe98dfa
CD
11835 (setq ind (save-excursion
11836 (if (org-in-item-p)
11837 (progn
11838 (goto-char (org-list-top-point))
11839 (org-get-indentation))
11840 (skip-chars-backward " \r\t\n")
11841 (cond
11842 ((and (org-at-heading-p)
11843 org-adapt-indentation)
11844 (1+ (org-current-level)))
11845 ((org-at-heading-p) 0)
11846 (t (org-get-indentation))))))
11847 (setq bul (org-list-bullet-string "-"))
11848 (org-indent-line-to ind)
11849 (insert bul (pop lines))
11850 (let ((ind-body (+ (length bul) ind)))
11851 (while lines
11852 (insert "\n")
11853 (org-indent-line-to ind-body)
11854 (insert (pop lines))))
c8d0cf5c
CD
11855 (message "Note stored")
11856 (org-back-to-heading t)
11857 (org-cycle-hide-drawers 'children)))))
20908596
CD
11858 (set-window-configuration org-log-note-window-configuration)
11859 (with-current-buffer (marker-buffer org-log-note-return-to)
11860 (goto-char org-log-note-return-to))
11861 (move-marker org-log-note-return-to nil)
11862 (and org-log-post-message (message "%s" org-log-post-message)))
a3fbe8c4 11863
c8d0cf5c 11864(defun org-remove-empty-drawer-at (drawer pos)
8bfe682a 11865 "Remove an empty drawer DRAWER at position POS.
c8d0cf5c
CD
11866POS may also be a marker."
11867 (with-current-buffer (if (markerp pos) (marker-buffer pos) (current-buffer))
11868 (save-excursion
11869 (save-restriction
11870 (widen)
11871 (goto-char pos)
11872 (if (org-in-regexp
11873 (concat "^[ \t]*:" drawer ":[ \t]*\n[ \t]*:END:[ \t]*\n?") 2)
11874 (replace-match ""))))))
11875
20908596
CD
11876(defun org-sparse-tree (&optional arg)
11877 "Create a sparse tree, prompt for the details.
11878This command can create sparse trees. You first need to select the type
11879of match used to create the tree:
d5098885 11880
86fbb8ca
CD
11881t Show all TODO entries.
11882T Show entries with a specific TODO keyword.
c8d0cf5c 11883m Show entries selected by a tags/property match.
20908596
CD
11884p Enter a property name and its value (both with completion on existing
11885 names/values) and show entries with that property.
acedf35c 11886r Show entries matching a regular expression (`/' can be used as well)
c8d0cf5c
CD
11887d Show deadlines due within `org-deadline-warning-days'.
11888b Show deadlines and scheduled items before a date.
11889a Show deadlines and scheduled items after a date."
20908596
CD
11890 (interactive "P")
11891 (let (ans kwd value)
acedf35c 11892 (message "Sparse tree: [r]egexp [/]regexp [t]odo [T]odo-kwd [m]atch [p]roperty\n [d]eadlines [b]efore-date [a]fter-date")
20908596
CD
11893 (setq ans (read-char-exclusive))
11894 (cond
11895 ((equal ans ?d)
11896 (call-interactively 'org-check-deadlines))
11897 ((equal ans ?b)
11898 (call-interactively 'org-check-before-date))
c8d0cf5c
CD
11899 ((equal ans ?a)
11900 (call-interactively 'org-check-after-date))
20908596 11901 ((equal ans ?t)
86fbb8ca
CD
11902 (org-show-todo-tree nil))
11903 ((equal ans ?T)
20908596 11904 (org-show-todo-tree '(4)))
c8d0cf5c
CD
11905 ((member ans '(?T ?m))
11906 (call-interactively 'org-match-sparse-tree))
20908596 11907 ((member ans '(?p ?P))
54a0dee5 11908 (setq kwd (org-icompleting-read "Property: "
20908596 11909 (mapcar 'list (org-buffer-property-keys))))
54a0dee5 11910 (setq value (org-icompleting-read "Value: "
20908596
CD
11911 (mapcar 'list (org-property-values kwd))))
11912 (unless (string-match "\\`{.*}\\'" value)
11913 (setq value (concat "\"" value "\"")))
c8d0cf5c 11914 (org-match-sparse-tree arg (concat kwd "=" value)))
20908596
CD
11915 ((member ans '(?r ?R ?/))
11916 (call-interactively 'org-occur))
11917 (t (error "No such sparse tree command \"%c\"" ans)))))
a3fbe8c4 11918
20908596
CD
11919(defvar org-occur-highlights nil
11920 "List of overlays used for occur matches.")
11921(make-variable-buffer-local 'org-occur-highlights)
11922(defvar org-occur-parameters nil
11923 "Parameters of the active org-occur calls.
11924This is a list, each call to org-occur pushes as cons cell,
11925containing the regular expression and the callback, onto the list.
11926The list can contain several entries if `org-occur' has been called
11927several time with the KEEP-PREVIOUS argument. Otherwise, this list
11928will only contain one set of parameters. When the highlights are
11929removed (for example with `C-c C-c', or with the next edit (depending
11930on `org-remove-highlights-with-change'), this variable is emptied
11931as well.")
11932(make-variable-buffer-local 'org-occur-parameters)
a3fbe8c4 11933
20908596
CD
11934(defun org-occur (regexp &optional keep-previous callback)
11935 "Make a compact tree which shows all matches of REGEXP.
11936The tree will show the lines where the regexp matches, and all higher
11937headlines above the match. It will also show the heading after the match,
11938to make sure editing the matching entry is easy.
11939If KEEP-PREVIOUS is non-nil, highlighting and exposing done by a previous
11940call to `org-occur' will be kept, to allow stacking of calls to this
11941command.
11942If CALLBACK is non-nil, it is a function which is called to confirm
11943that the match should indeed be shown."
11944 (interactive "sRegexp: \nP")
c8d0cf5c
CD
11945 (when (equal regexp "")
11946 (error "Regexp cannot be empty"))
20908596
CD
11947 (unless keep-previous
11948 (org-remove-occur-highlights nil nil t))
11949 (push (cons regexp callback) org-occur-parameters)
11950 (let ((cnt 0))
a3fbe8c4 11951 (save-excursion
a3fbe8c4 11952 (goto-char (point-min))
20908596
CD
11953 (if (or (not keep-previous) ; do not want to keep
11954 (not org-occur-highlights)) ; no previous matches
11955 ;; hide everything
11956 (org-overview))
11957 (while (re-search-forward regexp nil t)
11958 (when (or (not callback)
11959 (save-match-data (funcall callback)))
11960 (setq cnt (1+ cnt))
11961 (when org-highlight-sparse-tree-matches
11962 (org-highlight-new-match (match-beginning 0) (match-end 0)))
11963 (org-show-context 'occur-tree))))
11964 (when org-remove-highlights-with-change
11965 (org-add-hook 'before-change-functions 'org-remove-occur-highlights
11966 nil 'local))
11967 (unless org-sparse-tree-open-archived-trees
11968 (org-hide-archived-subtrees (point-min) (point-max)))
11969 (run-hooks 'org-occur-hook)
11970 (if (interactive-p)
11971 (message "%d match(es) for regexp %s" cnt regexp))
11972 cnt))
a3fbe8c4 11973
20908596 11974(defun org-show-context (&optional key)
86fbb8ca 11975 "Make sure point and context are visible.
20908596
CD
11976How much context is shown depends upon the variables
11977`org-show-hierarchy-above', `org-show-following-heading'. and
11978`org-show-siblings'."
11979 (let ((heading-p (org-on-heading-p t))
11980 (hierarchy-p (org-get-alist-option org-show-hierarchy-above key))
11981 (following-p (org-get-alist-option org-show-following-heading key))
11982 (entry-p (org-get-alist-option org-show-entry-below key))
11983 (siblings-p (org-get-alist-option org-show-siblings key)))
11984 (catch 'exit
11985 ;; Show heading or entry text
11986 (if (and heading-p (not entry-p))
11987 (org-flag-heading nil) ; only show the heading
11988 (and (or entry-p (org-invisible-p) (org-invisible-p2))
11989 (org-show-hidden-entry))) ; show entire entry
11990 (when following-p
11991 ;; Show next sibling, or heading below text
11992 (save-excursion
11993 (and (if heading-p (org-goto-sibling) (outline-next-heading))
11994 (org-flag-heading nil))))
11995 (when siblings-p (org-show-siblings))
11996 (when hierarchy-p
11997 ;; show all higher headings, possibly with siblings
11998 (save-excursion
11999 (while (and (condition-case nil
12000 (progn (org-up-heading-all 1) t)
12001 (error nil))
12002 (not (bobp)))
12003 (org-flag-heading nil)
12004 (when siblings-p (org-show-siblings))))))))
a3fbe8c4 12005
ed21c5c8
CD
12006(defvar org-reveal-start-hook nil
12007 "Hook run before revealing a location.")
12008
20908596
CD
12009(defun org-reveal (&optional siblings)
12010 "Show current entry, hierarchy above it, and the following headline.
12011This can be used to show a consistent set of context around locations
12012exposed with `org-show-hierarchy-above' or `org-show-following-heading'
12013not t for the search context.
891f4676 12014
20908596
CD
12015With optional argument SIBLINGS, on each level of the hierarchy all
12016siblings are shown. This repairs the tree structure to what it would
ed21c5c8 12017look like when opened with hierarchical calls to `org-cycle'.
86fbb8ca
CD
12018With double optional argument \\[universal-argument] \\[universal-argument], \
12019go to the parent and show the
ed21c5c8 12020entire tree."
20908596 12021 (interactive "P")
ed21c5c8 12022 (run-hooks 'org-reveal-start-hook)
20908596
CD
12023 (let ((org-show-hierarchy-above t)
12024 (org-show-following-heading t)
12025 (org-show-siblings (if siblings t org-show-siblings)))
ed21c5c8
CD
12026 (org-show-context nil))
12027 (when (equal siblings '(16))
12028 (save-excursion
12029 (when (org-up-heading-safe)
12030 (org-show-subtree)
12031 (run-hook-with-args 'org-cycle-hook 'subtree)))))
891f4676 12032
20908596
CD
12033(defun org-highlight-new-match (beg end)
12034 "Highlight from BEG to END and mark the highlight is an occur headline."
86fbb8ca
CD
12035 (let ((ov (make-overlay beg end)))
12036 (overlay-put ov 'face 'secondary-selection)
20908596 12037 (push ov org-occur-highlights)))
791d856f 12038
20908596
CD
12039(defun org-remove-occur-highlights (&optional beg end noremove)
12040 "Remove the occur highlights from the buffer.
12041BEG and END are ignored. If NOREMOVE is nil, remove this function
12042from the `before-change-functions' in the current buffer."
12043 (interactive)
12044 (unless org-inhibit-highlight-removal
86fbb8ca 12045 (mapc 'delete-overlay org-occur-highlights)
20908596
CD
12046 (setq org-occur-highlights nil)
12047 (setq org-occur-parameters nil)
12048 (unless noremove
12049 (remove-hook 'before-change-functions
12050 'org-remove-occur-highlights 'local))))
891f4676 12051
20908596 12052;;;; Priorities
891f4676 12053
20908596
CD
12054(defvar org-priority-regexp ".*?\\(\\[#\\([A-Z0-9]\\)\\] ?\\)"
12055 "Regular expression matching the priority indicator.")
d3f4dbe8 12056
20908596 12057(defvar org-remove-priority-next-time nil)
891f4676 12058
20908596
CD
12059(defun org-priority-up ()
12060 "Increase the priority of the current item."
03f3cf35 12061 (interactive)
20908596 12062 (org-priority 'up))
891f4676 12063
20908596
CD
12064(defun org-priority-down ()
12065 "Decrease the priority of the current item."
12066 (interactive)
12067 (org-priority 'down))
5bf7807a 12068
20908596
CD
12069(defun org-priority (&optional action)
12070 "Change the priority of an item by ARG.
12071ACTION can be `set', `up', `down', or a character."
12072 (interactive)
c8d0cf5c
CD
12073 (unless org-enable-priority-commands
12074 (error "Priority commands are disabled"))
20908596
CD
12075 (setq action (or action 'set))
12076 (let (current new news have remove)
12077 (save-excursion
9148fdd0 12078 (org-back-to-heading t)
20908596
CD
12079 (if (looking-at org-priority-regexp)
12080 (setq current (string-to-char (match-string 2))
12081 have t)
12082 (setq current org-default-priority))
12083 (cond
8bfe682a
CD
12084 ((eq action 'remove)
12085 (setq remove t new ?\ ))
20908596
CD
12086 ((or (eq action 'set)
12087 (if (featurep 'xemacs) (characterp action) (integerp action)))
12088 (if (not (eq action 'set))
12089 (setq new action)
12090 (message "Priority %c-%c, SPC to remove: "
12091 org-highest-priority org-lowest-priority)
afe98dfa
CD
12092 (save-match-data
12093 (setq new (read-char-exclusive))))
20908596
CD
12094 (if (and (= (upcase org-highest-priority) org-highest-priority)
12095 (= (upcase org-lowest-priority) org-lowest-priority))
12096 (setq new (upcase new)))
12097 (cond ((equal new ?\ ) (setq remove t))
12098 ((or (< (upcase new) org-highest-priority) (> (upcase new) org-lowest-priority))
12099 (error "Priority must be between `%c' and `%c'"
12100 org-highest-priority org-lowest-priority))))
12101 ((eq action 'up)
12102 (if (and (not have) (eq last-command this-command))
12103 (setq new org-lowest-priority)
12104 (setq new (if (and org-priority-start-cycle-with-default (not have))
12105 org-default-priority (1- current)))))
12106 ((eq action 'down)
12107 (if (and (not have) (eq last-command this-command))
12108 (setq new org-highest-priority)
12109 (setq new (if (and org-priority-start-cycle-with-default (not have))
12110 org-default-priority (1+ current)))))
12111 (t (error "Invalid action")))
12112 (if (or (< (upcase new) org-highest-priority)
12113 (> (upcase new) org-lowest-priority))
12114 (setq remove t))
12115 (setq news (format "%c" new))
12116 (if have
12117 (if remove
12118 (replace-match "" t t nil 1)
12119 (replace-match news t t nil 2))
12120 (if remove
12121 (error "No priority cookie found in line")
c8d0cf5c
CD
12122 (let ((case-fold-search nil))
12123 (looking-at org-todo-line-regexp))
20908596
CD
12124 (if (match-end 2)
12125 (progn
12126 (goto-char (match-end 2))
12127 (insert " [#" news "]"))
12128 (goto-char (match-beginning 3))
c8d0cf5c
CD
12129 (insert "[#" news "] "))))
12130 (org-preserve-lc (org-set-tags nil 'align)))
20908596
CD
12131 (if remove
12132 (message "Priority removed")
12133 (message "Priority of current item set to %s" news))))
5bf7807a 12134
20908596
CD
12135(defun org-get-priority (s)
12136 "Find priority cookie and return priority."
acedf35c
CD
12137 (if (functionp org-get-priority-function)
12138 (funcall org-get-priority-function)
12139 (save-match-data
12140 (if (not (string-match org-priority-regexp s))
12141 (* 1000 (- org-lowest-priority org-default-priority))
12142 (* 1000 (- org-lowest-priority
12143 (string-to-char (match-string 2 s))))))))
891f4676 12144
20908596 12145;;;; Tags
634a7d0b 12146
2c3ad40d 12147(defvar org-agenda-archives-mode)
c8d0cf5c
CD
12148(defvar org-map-continue-from nil
12149 "Position from where mapping should continue.
8bfe682a 12150Can be set by the action argument to `org-scan-tag's and `org-map-entries'.")
c8d0cf5c
CD
12151
12152(defvar org-scanner-tags nil
12153 "The current tag list while the tags scanner is running.")
12154(defvar org-trust-scanner-tags nil
12155 "Should `org-get-tags-at' use the tags fro the scanner.
12156This is for internal dynamical scoping only.
12157When this is non-nil, the function `org-get-tags-at' will return the value
12158of `org-scanner-tags' instead of building the list by itself. This
12159can lead to large speed-ups when the tags scanner is used in a file with
12160many entries, and when the list of tags is retrieved, for example to
12161obtain a list of properties. Building the tags list for each entry in such
12162a file becomes an N^2 operation - but with this variable set, it scales
12163as N.")
12164
20908596
CD
12165(defun org-scan-tags (action matcher &optional todo-only)
12166 "Scan headline tags with inheritance and produce output ACTION.
b349f79f
CD
12167
12168ACTION can be `sparse-tree' to produce a sparse tree in the current buffer,
12169or `agenda' to produce an entry list for an agenda view. It can also be
12170a Lisp form or a function that should be called at each matched headline, in
12171this case the return value is a list of all return values from these calls.
12172
12173MATCHER is a Lisp form to be evaluated, testing if a given set of tags
12174qualifies a headline for inclusion. When TODO-ONLY is non-nil,
12175only lines with a TODO keyword are included in the output."
0bd48b37 12176 (require 'org-agenda)
c8d0cf5c 12177 (let* ((re (concat "^" outline-regexp " *\\(\\<\\("
20908596
CD
12178 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
12179 (org-re
afe98dfa 12180 "\\>\\)\\)? *\\(.*?\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*$")))
2c3ad40d 12181 (props (list 'face 'default
c8d0cf5c 12182 'done-face 'org-agenda-done
2c3ad40d 12183 'undone-face 'default
20908596
CD
12184 'mouse-face 'highlight
12185 'org-not-done-regexp org-not-done-regexp
12186 'org-todo-regexp org-todo-regexp
20908596
CD
12187 'help-echo
12188 (format "mouse-2 or RET jump to org file %s"
12189 (abbreviate-file-name
12190 (or (buffer-file-name (buffer-base-buffer))
12191 (buffer-name (buffer-base-buffer)))))))
12192 (case-fold-search nil)
c8d0cf5c 12193 (org-map-continue-from nil)
b349f79f 12194 lspos tags tags-list
c8d0cf5c 12195 (tags-alist (list (cons 0 org-file-tags)))
b349f79f 12196 (llast 0) rtn rtn1 level category i txt
20908596 12197 todo marker entry priority)
621f83e4 12198 (when (not (or (member action '(agenda sparse-tree)) (functionp action)))
b349f79f 12199 (setq action (list 'lambda nil action)))
20908596
CD
12200 (save-excursion
12201 (goto-char (point-min))
12202 (when (eq action 'sparse-tree)
12203 (org-overview)
12204 (org-remove-occur-highlights))
12205 (while (re-search-forward re nil t)
12206 (catch :skip
c8d0cf5c
CD
12207 (setq todo (if (match-end 1) (org-match-string-no-properties 2))
12208 tags (if (match-end 4) (org-match-string-no-properties 4)))
12209 (goto-char (setq lspos (match-beginning 0)))
20908596
CD
12210 (setq level (org-reduced-level (funcall outline-level))
12211 category (org-get-category))
12212 (setq i llast llast level)
12213 ;; remove tag lists from same and sublevels
12214 (while (>= i level)
12215 (when (setq entry (assoc i tags-alist))
12216 (setq tags-alist (delete entry tags-alist)))
12217 (setq i (1- i)))
12218 ;; add the next tags
12219 (when tags
c8d0cf5c 12220 (setq tags (org-split-string tags ":")
20908596
CD
12221 tags-alist
12222 (cons (cons level tags) tags-alist)))
12223 ;; compile tags for current headline
12224 (setq tags-list
12225 (if org-use-tag-inheritance
ff4be292 12226 (apply 'append (mapcar 'cdr (reverse tags-alist)))
c8d0cf5c
CD
12227 tags)
12228 org-scanner-tags tags-list)
ff4be292
CD
12229 (when org-use-tag-inheritance
12230 (setcdr (car tags-alist)
12231 (mapcar (lambda (x)
12232 (setq x (copy-sequence x))
12233 (org-add-prop-inherited x))
12234 (cdar tags-alist))))
20908596 12235 (when (and tags org-use-tag-inheritance
c8d0cf5c
CD
12236 (or (not (eq t org-use-tag-inheritance))
12237 org-tags-exclude-from-inheritance))
20908596
CD
12238 ;; selective inheritance, remove uninherited ones
12239 (setcdr (car tags-alist)
12240 (org-remove-uniherited-tags (cdar tags-alist))))
0bd48b37
CD
12241 (when (and (or (not todo-only)
12242 (and (member todo org-not-done-keywords)
12243 (or (not org-agenda-tags-todo-honor-ignore-options)
12244 (not (org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item)))))
621f83e4 12245 (let ((case-fold-search t)) (eval matcher))
2c3ad40d
CD
12246 (or
12247 (not (member org-archive-tag tags-list))
12248 ;; we have an archive tag, should we use this anyway?
12249 (or (not org-agenda-skip-archived-trees)
12250 (and (eq action 'agenda) org-agenda-archives-mode))))
b349f79f 12251 (unless (eq action 'sparse-tree) (org-agenda-skip))
03f3cf35 12252
b349f79f
CD
12253 ;; select this headline
12254
12255 (cond
12256 ((eq action 'sparse-tree)
12257 (and org-highlight-sparse-tree-matches
12258 (org-get-heading) (match-end 0)
12259 (org-highlight-new-match
12260 (match-beginning 0) (match-beginning 1)))
12261 (org-show-context 'tags-tree))
12262 ((eq action 'agenda)
20908596
CD
12263 (setq txt (org-format-agenda-item
12264 ""
12265 (concat
c8d0cf5c 12266 (if (eq org-tags-match-list-sublevels 'indented)
20908596
CD
12267 (make-string (1- level) ?.) "")
12268 (org-get-heading))
c8d0cf5c
CD
12269 category
12270 tags-list
12271 )
20908596
CD
12272 priority (org-get-priority txt))
12273 (goto-char lspos)
12274 (setq marker (org-agenda-new-marker))
12275 (org-add-props txt props
12276 'org-marker marker 'org-hd-marker marker 'org-category category
c8d0cf5c 12277 'todo-state todo
20908596
CD
12278 'priority priority 'type "tagsmatch")
12279 (push txt rtn))
b349f79f 12280 ((functionp action)
c8d0cf5c 12281 (setq org-map-continue-from nil)
b349f79f
CD
12282 (save-excursion
12283 (setq rtn1 (funcall action))
c8d0cf5c 12284 (push rtn1 rtn)))
b349f79f
CD
12285 (t (error "Invalid action")))
12286
20908596 12287 ;; if we are to skip sublevels, jump to end of subtree
c8d0cf5c
CD
12288 (unless org-tags-match-list-sublevels
12289 (org-end-of-subtree t)
12290 (backward-char 1))))
12291 ;; Get the correct position from where to continue
12292 (if org-map-continue-from
12293 (goto-char org-map-continue-from)
12294 (and (= (point) lspos) (end-of-line 1)))))
20908596
CD
12295 (when (and (eq action 'sparse-tree)
12296 (not org-sparse-tree-open-archived-trees))
12297 (org-hide-archived-subtrees (point-min) (point-max)))
12298 (nreverse rtn)))
891f4676 12299
20908596
CD
12300(defun org-remove-uniherited-tags (tags)
12301 "Remove all tags that are not inherited from the list TAGS."
12302 (cond
ff4be292
CD
12303 ((eq org-use-tag-inheritance t)
12304 (if org-tags-exclude-from-inheritance
12305 (org-delete-all org-tags-exclude-from-inheritance tags)
12306 tags))
20908596
CD
12307 ((not org-use-tag-inheritance) nil)
12308 ((stringp org-use-tag-inheritance)
12309 (delq nil (mapcar
ff4be292
CD
12310 (lambda (x)
12311 (if (and (string-match org-use-tag-inheritance x)
12312 (not (member x org-tags-exclude-from-inheritance)))
12313 x nil))
20908596
CD
12314 tags)))
12315 ((listp org-use-tag-inheritance)
621f83e4 12316 (delq nil (mapcar
ff4be292
CD
12317 (lambda (x)
12318 (if (member x org-use-tag-inheritance) x nil))
621f83e4 12319 tags)))))
2a57416f 12320
20908596
CD
12321(defvar todo-only) ;; dynamically scoped
12322
c8d0cf5c 12323(defun org-match-sparse-tree (&optional todo-only match)
d60b1ba1 12324 "Create a sparse tree according to tags string MATCH.
20908596
CD
12325MATCH can contain positive and negative selection of tags, like
12326\"+WORK+URGENT-WITHBOSS\".
d60b1ba1 12327If optional argument TODO-ONLY is non-nil, only select lines that are
20908596
CD
12328also TODO lines."
12329 (interactive "P")
12330 (org-prepare-agenda-buffers (list (current-buffer)))
12331 (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match)) todo-only))
15841868 12332
c8d0cf5c
CD
12333(defalias 'org-tags-sparse-tree 'org-match-sparse-tree)
12334
20908596
CD
12335(defvar org-cached-props nil)
12336(defun org-cached-entry-get (pom property)
12337 (if (or (eq t org-use-property-inheritance)
12338 (and (stringp org-use-property-inheritance)
12339 (string-match org-use-property-inheritance property))
12340 (and (listp org-use-property-inheritance)
12341 (member property org-use-property-inheritance)))
12342 ;; Caching is not possible, check it directly
12343 (org-entry-get pom property 'inherit)
12344 ;; Get all properties, so that we can do complicated checks easily
12345 (cdr (assoc property (or org-cached-props
12346 (setq org-cached-props
12347 (org-entry-properties pom)))))))
15841868 12348
20908596
CD
12349(defun org-global-tags-completion-table (&optional files)
12350 "Return the list of all tags in all agenda buffer/files."
12351 (save-excursion
12352 (org-uniquify
12353 (delq nil
12354 (apply 'append
12355 (mapcar
12356 (lambda (file)
12357 (set-buffer (find-file-noselect file))
12358 (append (org-get-buffer-tags)
12359 (mapcar (lambda (x) (if (stringp (car-safe x))
12360 (list (car-safe x)) nil))
12361 org-tag-alist)))
12362 (if (and files (car files))
12363 files
12364 (org-agenda-files))))))))
2a57416f 12365
20908596
CD
12366(defun org-make-tags-matcher (match)
12367 "Create the TAGS//TODO matcher form for the selection string MATCH."
12368 ;; todo-only is scoped dynamically into this function, and the function
33306645 12369 ;; may change it if the matcher asks for it.
20908596
CD
12370 (unless match
12371 ;; Get a new match request, with completion
12372 (let ((org-last-tags-completion-table
12373 (org-global-tags-completion-table)))
54a0dee5 12374 (setq match (org-completing-read-no-i
20908596
CD
12375 "Match: " 'org-tags-completion-function nil nil nil
12376 'org-tags-history))))
15841868 12377
20908596
CD
12378 ;; Parse the string and create a lisp form
12379 (let ((match0 match)
afe98dfa 12380 (re (org-re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL\\([<=>]\\{1,2\\}\\)\\([0-9]+\\)\\|\\(\\(?:[[:alnum:]_]+\\(?:\\\\-\\)*\\)+\\)\\([<>=]\\{1,2\\}\\)\\({[^}]+}\\|\"[^\"]*\"\\|-?[.0-9]+\\(?:[eE][-+]?[0-9]+\\)?\\)\\|[[:alnum:]_@#%]+\\)"))
20908596
CD
12381 minus tag mm
12382 tagsmatch todomatch tagsmatcher todomatcher kwd matcher
621f83e4 12383 orterms term orlist re-p str-p level-p level-op time-p
acedf35c 12384 prop-p pn pv po gv rest)
20908596
CD
12385 (if (string-match "/+" match)
12386 ;; match contains also a todo-matching request
12387 (progn
12388 (setq tagsmatch (substring match 0 (match-beginning 0))
12389 todomatch (substring match (match-end 0)))
12390 (if (string-match "^!" todomatch)
12391 (setq todo-only t todomatch (substring todomatch 1)))
12392 (if (string-match "^\\s-*$" todomatch)
12393 (setq todomatch nil)))
12394 ;; only matching tags
12395 (setq tagsmatch match todomatch nil))
15841868 12396
20908596
CD
12397 ;; Make the tags matcher
12398 (if (or (not tagsmatch) (not (string-match "\\S-" tagsmatch)))
12399 (setq tagsmatcher t)
12400 (setq orterms (org-split-string tagsmatch "|") orlist nil)
12401 (while (setq term (pop orterms))
12402 (while (and (equal (substring term -1) "\\") orterms)
12403 (setq term (concat term "|" (pop orterms)))) ; repair bad split
12404 (while (string-match re term)
93b62de8
CD
12405 (setq rest (substring term (match-end 0))
12406 minus (and (match-end 1)
20908596 12407 (equal (match-string 1 term) "-"))
afe98dfa
CD
12408 tag (save-match-data (replace-regexp-in-string
12409 "\\\\-" "-"
12410 (match-string 2 term)))
20908596
CD
12411 re-p (equal (string-to-char tag) ?{)
12412 level-p (match-end 4)
12413 prop-p (match-end 5)
12414 mm (cond
12415 (re-p `(org-match-any-p ,(substring tag 1 -1) tags-list))
12416 (level-p
12417 (setq level-op (org-op-to-function (match-string 3 term)))
12418 `(,level-op level ,(string-to-number
12419 (match-string 4 term))))
12420 (prop-p
12421 (setq pn (match-string 5 term)
12422 po (match-string 6 term)
12423 pv (match-string 7 term)
20908596
CD
12424 re-p (equal (string-to-char pv) ?{)
12425 str-p (equal (string-to-char pv) ?\")
93b62de8
CD
12426 time-p (save-match-data
12427 (string-match "^\"[[<].*[]>]\"$" pv))
20908596 12428 pv (if (or re-p str-p) (substring pv 1 -1) pv))
2c3ad40d
CD
12429 (if time-p (setq pv (org-matcher-time pv)))
12430 (setq po (org-op-to-function po (if time-p 'time str-p)))
93b62de8
CD
12431 (cond
12432 ((equal pn "CATEGORY")
12433 (setq gv '(get-text-property (point) 'org-category)))
12434 ((equal pn "TODO")
12435 (setq gv 'todo))
12436 (t
12437 (setq gv `(org-cached-entry-get nil ,pn))))
20908596
CD
12438 (if re-p
12439 (if (eq po 'org<>)
12440 `(not (string-match ,pv (or ,gv "")))
12441 `(string-match ,pv (or ,gv "")))
12442 (if str-p
12443 `(,po (or ,gv "") ,pv)
12444 `(,po (string-to-number (or ,gv ""))
12445 ,(string-to-number pv) ))))
c8d0cf5c 12446 (t `(member ,tag tags-list)))
20908596 12447 mm (if minus (list 'not mm) mm)
93b62de8 12448 term rest)
20908596
CD
12449 (push mm tagsmatcher))
12450 (push (if (> (length tagsmatcher) 1)
12451 (cons 'and tagsmatcher)
12452 (car tagsmatcher))
12453 orlist)
12454 (setq tagsmatcher nil))
12455 (setq tagsmatcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist)))
12456 (setq tagsmatcher
12457 (list 'progn '(setq org-cached-props nil) tagsmatcher)))
12458 ;; Make the todo matcher
12459 (if (or (not todomatch) (not (string-match "\\S-" todomatch)))
12460 (setq todomatcher t)
12461 (setq orterms (org-split-string todomatch "|") orlist nil)
12462 (while (setq term (pop orterms))
12463 (while (string-match re term)
12464 (setq minus (and (match-end 1)
12465 (equal (match-string 1 term) "-"))
12466 kwd (match-string 2 term)
12467 re-p (equal (string-to-char kwd) ?{)
12468 term (substring term (match-end 0))
12469 mm (if re-p
12470 `(string-match ,(substring kwd 1 -1) todo)
12471 (list 'equal 'todo kwd))
12472 mm (if minus (list 'not mm) mm))
12473 (push mm todomatcher))
12474 (push (if (> (length todomatcher) 1)
12475 (cons 'and todomatcher)
12476 (car todomatcher))
12477 orlist)
12478 (setq todomatcher nil))
12479 (setq todomatcher (if (> (length orlist) 1)
12480 (cons 'or orlist) (car orlist))))
a3fbe8c4 12481
20908596
CD
12482 ;; Return the string and lisp forms of the matcher
12483 (setq matcher (if todomatcher
12484 (list 'and tagsmatcher todomatcher)
12485 tagsmatcher))
12486 (cons match0 matcher)))
d3f4dbe8 12487
20908596 12488(defun org-op-to-function (op &optional stringp)
2c3ad40d 12489 "Turn an operator into the appropriate function."
20908596
CD
12490 (setq op
12491 (cond
2c3ad40d
CD
12492 ((equal op "<" ) '(< string< org-time<))
12493 ((equal op ">" ) '(> org-string> org-time>))
12494 ((member op '("<=" "=<")) '(<= org-string<= org-time<=))
12495 ((member op '(">=" "=>")) '(>= org-string>= org-time>=))
12496 ((member op '("=" "==")) '(= string= org-time=))
12497 ((member op '("<>" "!=")) '(org<> org-string<> org-time<>))))
12498 (nth (if (eq stringp 'time) 2 (if stringp 1 0)) op))
20908596
CD
12499
12500(defun org<> (a b) (not (= a b)))
12501(defun org-string<= (a b) (or (string= a b) (string< a b)))
12502(defun org-string>= (a b) (not (string< a b)))
12503(defun org-string> (a b) (and (not (string= a b)) (not (string< a b))))
12504(defun org-string<> (a b) (not (string= a b)))
0bd48b37
CD
12505(defun org-time= (a b) (setq a (org-2ft a) b (org-2ft b)) (and (> a 0) (> b 0) (= a b)))
12506(defun org-time< (a b) (setq a (org-2ft a) b (org-2ft b)) (and (> a 0) (> b 0) (< a b)))
12507(defun org-time<= (a b) (setq a (org-2ft a) b (org-2ft b)) (and (> a 0) (> b 0) (<= a b)))
12508(defun org-time> (a b) (setq a (org-2ft a) b (org-2ft b)) (and (> a 0) (> b 0) (> a b)))
12509(defun org-time>= (a b) (setq a (org-2ft a) b (org-2ft b)) (and (> a 0) (> b 0) (>= a b)))
12510(defun org-time<> (a b) (setq a (org-2ft a) b (org-2ft b)) (and (> a 0) (> b 0) (org<> a b)))
2c3ad40d
CD
12511(defun org-2ft (s)
12512 "Convert S to a floating point time.
12513If S is already a number, just return it. If it is a string, parse
0bd48b37 12514it as a time string and apply `float-time' to it. If S is nil, just return 0."
2c3ad40d
CD
12515 (cond
12516 ((numberp s) s)
12517 ((stringp s)
12518 (condition-case nil
12519 (float-time (apply 'encode-time (org-parse-time-string s)))
12520 (error 0.)))
12521 (t 0.)))
12522
ce4fdcb9
CD
12523(defun org-time-today ()
12524 "Time in seconds today at 0:00.
12525Returns the float number of seconds since the beginning of the
12526epoch to the beginning of today (00:00)."
12527 (float-time (apply 'encode-time
12528 (append '(0 0 0) (nthcdr 3 (decode-time))))))
12529
2c3ad40d 12530(defun org-matcher-time (s)
33306645 12531 "Interpret a time comparison value."
ff4be292
CD
12532 (save-match-data
12533 (cond
12534 ((string= s "<now>") (float-time))
12535 ((string= s "<today>") (org-time-today))
12536 ((string= s "<tomorrow>") (+ 86400.0 (org-time-today)))
12537 ((string= s "<yesterday>") (- (org-time-today) 86400.0))
12538 ((string-match "^<\\([-+][0-9]+\\)\\([dwmy]\\)>$" s)
12539 (+ (org-time-today)
12540 (* (string-to-number (match-string 1 s))
12541 (cdr (assoc (match-string 2 s)
12542 '(("d" . 86400.0) ("w" . 604800.0)
12543 ("m" . 2678400.0) ("y" . 31557600.0)))))))
12544 (t (org-2ft s)))))
15841868 12545
20908596
CD
12546(defun org-match-any-p (re list)
12547 "Does re match any element of list?"
12548 (setq list (mapcar (lambda (x) (string-match re x)) list))
12549 (delq nil list))
15841868 12550
33306645 12551(defvar org-add-colon-after-tag-completion nil) ;; dynamically scoped param
86fbb8ca 12552(defvar org-tags-overlay (make-overlay 1 1))
20908596 12553(org-detach-overlay org-tags-overlay)
e0e66b8e 12554
621f83e4
CD
12555(defun org-get-local-tags-at (&optional pos)
12556 "Get a list of tags defined in the current headline."
12557 (org-get-tags-at pos 'local))
12558
12559(defun org-get-local-tags ()
12560 "Get a list of tags defined in the current headline."
12561 (org-get-tags-at nil 'local))
12562
12563(defun org-get-tags-at (&optional pos local)
20908596
CD
12564 "Get a list of all headline tags applicable at POS.
12565POS defaults to point. If tags are inherited, the list contains
12566the targets in the same sequence as the headlines appear, i.e.
621f83e4
CD
12567the tags of the current headline come last.
12568When LOCAL is non-nil, only return tags from the current headline,
12569ignore inherited ones."
d3f4dbe8 12570 (interactive)
c8d0cf5c
CD
12571 (if (and org-trust-scanner-tags
12572 (or (not pos) (equal pos (point)))
12573 (not local))
12574 org-scanner-tags
12575 (let (tags ltags lastpos parent)
12576 (save-excursion
12577 (save-restriction
12578 (widen)
12579 (goto-char (or pos (point)))
12580 (save-match-data
12581 (catch 'done
12582 (condition-case nil
12583 (progn
12584 (org-back-to-heading t)
12585 (while (not (equal lastpos (point)))
12586 (setq lastpos (point))
12587 (when (looking-at
afe98dfa 12588 (org-re "[^\r\n]+?:\\([[:alnum:]_@#%:]+\\):[ \t]*$"))
c8d0cf5c
CD
12589 (setq ltags (org-split-string
12590 (org-match-string-no-properties 1) ":"))
12591 (when parent
12592 (setq ltags (mapcar 'org-add-prop-inherited ltags)))
12593 (setq tags (append
12594 (if parent
12595 (org-remove-uniherited-tags ltags)
12596 ltags)
12597 tags)))
12598 (or org-use-tag-inheritance (throw 'done t))
12599 (if local (throw 'done t))
12600 (or (org-up-heading-safe) (error nil))
12601 (setq parent t)))
12602 (error nil)))))
12603 (append (org-remove-uniherited-tags org-file-tags) tags)))))
d3f4dbe8 12604
ff4be292
CD
12605(defun org-add-prop-inherited (s)
12606 (add-text-properties 0 (length s) '(inherited t) s)
12607 s)
12608
20908596
CD
12609(defun org-toggle-tag (tag &optional onoff)
12610 "Toggle the tag TAG for the current line.
12611If ONOFF is `on' or `off', don't toggle but set to this state."
20908596 12612 (let (res current)
15841868 12613 (save-excursion
db55f368 12614 (org-back-to-heading t)
afe98dfa 12615 (if (re-search-forward (org-re "[ \t]:\\([[:alnum:]_@#%:]+\\):[ \t]*$")
20908596
CD
12616 (point-at-eol) t)
12617 (progn
12618 (setq current (match-string 1))
12619 (replace-match ""))
12620 (setq current ""))
12621 (setq current (nreverse (org-split-string current ":")))
12622 (cond
12623 ((eq onoff 'on)
12624 (setq res t)
12625 (or (member tag current) (push tag current)))
12626 ((eq onoff 'off)
12627 (or (not (member tag current)) (setq current (delete tag current))))
12628 (t (if (member tag current)
12629 (setq current (delete tag current))
12630 (setq res t)
12631 (push tag current))))
15841868 12632 (end-of-line 1)
20908596
CD
12633 (if current
12634 (progn
12635 (insert " :" (mapconcat 'identity (nreverse current) ":") ":")
12636 (org-set-tags nil t))
12637 (delete-horizontal-space))
12638 (run-hooks 'org-after-tags-change-hook))
12639 res))
15841868 12640
20908596
CD
12641(defun org-align-tags-here (to-col)
12642 ;; Assumes that this is a headline
12643 (let ((pos (point)) (col (current-column)) ncol tags-l p)
891f4676 12644 (beginning-of-line 1)
afe98dfa 12645 (if (and (looking-at (org-re ".*?\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))
20908596
CD
12646 (< pos (match-beginning 2)))
12647 (progn
12648 (setq tags-l (- (match-end 2) (match-beginning 2)))
12649 (goto-char (match-beginning 1))
12650 (insert " ")
12651 (delete-region (point) (1+ (match-beginning 2)))
12652 (setq ncol (max (1+ (current-column))
12653 (1+ col)
12654 (if (> to-col 0)
12655 to-col
12656 (- (abs to-col) tags-l))))
12657 (setq p (point))
12658 (insert (make-string (- ncol (current-column)) ?\ ))
12659 (setq ncol (current-column))
b349f79f 12660 (when indent-tabs-mode (tabify p (point-at-eol)))
20908596
CD
12661 (org-move-to-column (min ncol col) t))
12662 (goto-char pos))))
2a57416f 12663
71d35b24
CD
12664(defun org-set-tags-command (&optional arg just-align)
12665 "Call the set-tags command for the current entry."
12666 (interactive "P")
12667 (if (org-on-heading-p)
12668 (org-set-tags arg just-align)
12669 (save-excursion
12670 (org-back-to-heading t)
12671 (org-set-tags arg just-align))))
12672
8d642074
CD
12673(defun org-set-tags-to (data)
12674 "Set the tags of the current entry to DATA, replacing the current tags.
12675DATA may be a tags string like :aa:bb:cc:, or a list of tags.
12676If DATA is nil or the empty string, any tags will be removed."
12677 (interactive "sTags: ")
12678 (setq data
12679 (cond
12680 ((eq data nil) "")
12681 ((equal data "") "")
12682 ((stringp data)
12683 (concat ":" (mapconcat 'identity (org-split-string data ":+") ":")
12684 ":"))
12685 ((listp data)
12686 (concat ":" (mapconcat 'identity data ":") ":"))
12687 (t nil)))
12688 (when data
12689 (save-excursion
12690 (org-back-to-heading t)
12691 (when (looking-at org-complex-heading-regexp)
12692 (if (match-end 5)
12693 (progn
12694 (goto-char (match-beginning 5))
12695 (insert data)
12696 (delete-region (point) (point-at-eol))
12697 (org-set-tags nil 'align))
12698 (goto-char (point-at-eol))
12699 (insert " " data)
12700 (org-set-tags nil 'align)))
12701 (beginning-of-line 1)
12702 (if (looking-at ".*?\\([ \t]+\\)$")
12703 (delete-region (match-beginning 1) (match-end 1))))))
12704
86fbb8ca
CD
12705(defun org-align-all-tags ()
12706 "Align the tags i all headings."
12707 (interactive)
12708 (save-excursion
12709 (or (ignore-errors (org-back-to-heading t))
12710 (outline-next-heading))
12711 (if (org-on-heading-p)
12712 (org-set-tags t)
12713 (message "No headings"))))
12714
afe98dfa 12715(defvar org-indent-indentation-per-level)
20908596
CD
12716(defun org-set-tags (&optional arg just-align)
12717 "Set the tags for the current headline.
12718With prefix ARG, realign all tags in headings in the current buffer."
12719 (interactive "P")
12720 (let* ((re (concat "^" outline-regexp))
12721 (current (org-get-tags-string))
12722 (col (current-column))
12723 (org-setting-tags t)
12724 table current-tags inherited-tags ; computed below when needed
afe98dfa 12725 tags p0 c0 c1 rpl di tc level)
20908596
CD
12726 (if arg
12727 (save-excursion
2a57416f 12728 (goto-char (point-min))
20908596
CD
12729 (let ((buffer-invisibility-spec (org-inhibit-invisibility)))
12730 (while (re-search-forward re nil t)
12731 (org-set-tags nil t)
12732 (end-of-line 1)))
12733 (message "All tags realigned to column %d" org-tags-column))
12734 (if just-align
12735 (setq tags current)
12736 ;; Get a new set of tags from the user
12737 (save-excursion
c8d0cf5c 12738 (setq table (append org-tag-persistent-alist
ed21c5c8 12739 (or org-tag-alist (org-get-buffer-tags))
afe98dfa
CD
12740 (and
12741 org-complete-tags-always-offer-all-agenda-tags
12742 (org-global-tags-completion-table
12743 (org-agenda-files))))
20908596
CD
12744 org-last-tags-completion-table table
12745 current-tags (org-split-string current ":")
12746 inherited-tags (nreverse
12747 (nthcdr (length current-tags)
12748 (nreverse (org-get-tags-at))))
12749 tags
12750 (if (or (eq t org-use-fast-tag-selection)
12751 (and org-use-fast-tag-selection
12752 (delq nil (mapcar 'cdr table))))
12753 (org-fast-tag-selection
12754 current-tags inherited-tags table
afe98dfa
CD
12755 (if org-fast-tag-selection-include-todo
12756 org-todo-key-alist))
20908596
CD
12757 (let ((org-add-colon-after-tag-completion t))
12758 (org-trim
12759 (org-without-partial-completion
afe98dfa
CD
12760 (org-icompleting-read "Tags: "
12761 'org-tags-completion-function
20908596
CD
12762 nil nil current 'org-tags-history)))))))
12763 (while (string-match "[-+&]+" tags)
12764 ;; No boolean logic, just a list
12765 (setq tags (replace-match ":" t t tags))))
64f72ae1 12766
afe98dfa
CD
12767 (setq tags (replace-regexp-in-string "[ ,]" ":" tags))
12768
c8d0cf5c
CD
12769 (if org-tags-sort-function
12770 (setq tags (mapconcat 'identity
afe98dfa
CD
12771 (sort (org-split-string
12772 tags (org-re "[^[:alnum:]_@#%]+"))
c8d0cf5c
CD
12773 org-tags-sort-function) ":")))
12774
20908596 12775 (if (string-match "\\`[\t ]*\\'" tags)
c8d0cf5c 12776 (setq tags "")
20908596
CD
12777 (unless (string-match ":$" tags) (setq tags (concat tags ":")))
12778 (unless (string-match "^:" tags) (setq tags (concat ":" tags))))
891f4676 12779
20908596
CD
12780 ;; Insert new tags at the correct column
12781 (beginning-of-line 1)
afe98dfa
CD
12782 (setq level (or (and (looking-at org-outline-regexp)
12783 (- (match-end 0) (point) 1))
12784 1))
20908596
CD
12785 (cond
12786 ((and (equal current "") (equal tags "")))
12787 ((re-search-forward
12788 (concat "\\([ \t]*" (regexp-quote current) "\\)[ \t]*$")
12789 (point-at-eol) t)
12790 (if (equal tags "")
12791 (setq rpl "")
12792 (goto-char (match-beginning 0))
afe98dfa
CD
12793 (setq c0 (current-column)
12794 ;; compute offset for the case of org-indent-mode active
12795 di (if org-indent-mode
12796 (* (1- org-indent-indentation-per-level) (1- level))
12797 0)
12798 p0 (if (equal (char-before) ?*) (1+ (point)) (point))
12799 tc (+ org-tags-column (if (> org-tags-column 0) (- di) di))
12800 c1 (max (1+ c0) (if (> tc 0) tc (- (- tc) (length tags))))
20908596
CD
12801 rpl (concat (make-string (max 0 (- c1 c0)) ?\ ) tags)))
12802 (replace-match rpl t t)
12803 (and (not (featurep 'xemacs)) c0 indent-tabs-mode (tabify p0 (point)))
12804 tags)
12805 (t (error "Tags alignment failed")))
12806 (org-move-to-column col)
12807 (unless just-align
12808 (run-hooks 'org-after-tags-change-hook)))))
891f4676 12809
20908596
CD
12810(defun org-change-tag-in-region (beg end tag off)
12811 "Add or remove TAG for each entry in the region.
12812This works in the agenda, and also in an org-mode buffer."
12813 (interactive
12814 (list (region-beginning) (region-end)
12815 (let ((org-last-tags-completion-table
12816 (if (org-mode-p)
12817 (org-get-buffer-tags)
12818 (org-global-tags-completion-table))))
54a0dee5 12819 (org-icompleting-read
20908596
CD
12820 "Tag: " 'org-tags-completion-function nil nil nil
12821 'org-tags-history))
12822 (progn
12823 (message "[s]et or [r]emove? ")
12824 (equal (read-char-exclusive) ?r))))
12825 (if (fboundp 'deactivate-mark) (deactivate-mark))
12826 (let ((agendap (equal major-mode 'org-agenda-mode))
12827 l1 l2 m buf pos newhead (cnt 0))
12828 (goto-char end)
12829 (setq l2 (1- (org-current-line)))
12830 (goto-char beg)
12831 (setq l1 (org-current-line))
12832 (loop for l from l1 to l2 do
54a0dee5 12833 (org-goto-line l)
20908596
CD
12834 (setq m (get-text-property (point) 'org-hd-marker))
12835 (when (or (and (org-mode-p) (org-on-heading-p))
12836 (and agendap m))
12837 (setq buf (if agendap (marker-buffer m) (current-buffer))
12838 pos (if agendap m (point)))
12839 (with-current-buffer buf
12840 (save-excursion
12841 (save-restriction
12842 (goto-char pos)
12843 (setq cnt (1+ cnt))
12844 (org-toggle-tag tag (if off 'off 'on))
12845 (setq newhead (org-get-heading)))))
12846 (and agendap (org-agenda-change-all-lines newhead m))))
12847 (message "Tag :%s: %s in %d headings" tag (if off "removed" "set") cnt)))
891f4676 12848
20908596
CD
12849(defun org-tags-completion-function (string predicate &optional flag)
12850 (let (s1 s2 rtn (ctable org-last-tags-completion-table)
12851 (confirm (lambda (x) (stringp (car x)))))
afe98dfa 12852 (if (string-match "^\\(.*[-+:&,|]\\)\\([^-+:&,|]*\\)$" string)
20908596
CD
12853 (setq s1 (match-string 1 string)
12854 s2 (match-string 2 string))
12855 (setq s1 "" s2 string))
12856 (cond
12857 ((eq flag nil)
12858 ;; try completion
12859 (setq rtn (try-completion s2 ctable confirm))
12860 (if (stringp rtn)
12861 (setq rtn
12862 (concat s1 s2 (substring rtn (length s2))
12863 (if (and org-add-colon-after-tag-completion
12864 (assoc rtn ctable))
12865 ":" ""))))
12866 rtn)
12867 ((eq flag t)
12868 ;; all-completions
12869 (all-completions s2 ctable confirm)
12870 )
12871 ((eq flag 'lambda)
12872 ;; exact match?
12873 (assoc s2 ctable)))
d3f4dbe8 12874 ))
ab27a4a0 12875
20908596 12876(defun org-fast-tag-insert (kwd tags face &optional end)
33306645 12877 "Insert KDW, and the TAGS, the latter with face FACE. Also insert END."
20908596
CD
12878 (insert (format "%-12s" (concat kwd ":"))
12879 (org-add-props (mapconcat 'identity tags " ") nil 'face face)
12880 (or end "")))
891f4676 12881
20908596
CD
12882(defun org-fast-tag-show-exit (flag)
12883 (save-excursion
54a0dee5 12884 (org-goto-line 3)
20908596
CD
12885 (if (re-search-forward "[ \t]+Next change exits" (point-at-eol) t)
12886 (replace-match ""))
12887 (when flag
12888 (end-of-line 1)
12889 (org-move-to-column (- (window-width) 19) t)
12890 (insert (org-add-props " Next change exits" nil 'face 'org-warning)))))
64f72ae1 12891
20908596
CD
12892(defun org-set-current-tags-overlay (current prefix)
12893 (let ((s (concat ":" (mapconcat 'identity current ":") ":")))
12894 (if (featurep 'xemacs)
12895 (org-overlay-display org-tags-overlay (concat prefix s)
12896 'secondary-selection)
12897 (put-text-property 0 (length s) 'face '(secondary-selection org-tag) s)
12898 (org-overlay-display org-tags-overlay (concat prefix s)))))
891f4676 12899
ed21c5c8 12900(defvar org-last-tag-selection-key nil)
20908596
CD
12901(defun org-fast-tag-selection (current inherited table &optional todo-table)
12902 "Fast tag selection with single keys.
12903CURRENT is the current list of tags in the headline, INHERITED is the
12904list of inherited tags, and TABLE is an alist of tags and corresponding keys,
12905possibly with grouping information. TODO-TABLE is a similar table with
12906TODO keywords, should these have keys assigned to them.
12907If the keys are nil, a-z are automatically assigned.
12908Returns the new tags string, or nil to not change the current settings."
12909 (let* ((fulltable (append table todo-table))
12910 (maxlen (apply 'max (mapcar
12911 (lambda (x)
12912 (if (stringp (car x)) (string-width (car x)) 0))
12913 fulltable)))
12914 (buf (current-buffer))
12915 (expert (eq org-fast-tag-selection-single-key 'expert))
12916 (buffer-tags nil)
12917 (fwidth (+ maxlen 3 1 3))
12918 (ncol (/ (- (window-width) 4) fwidth))
12919 (i-face 'org-done)
12920 (c-face 'org-todo)
12921 tg cnt e c char c1 c2 ntable tbl rtn
12922 ov-start ov-end ov-prefix
12923 (exit-after-next org-fast-tag-selection-single-key)
12924 (done-keywords org-done-keywords)
12925 groups ingroup)
12926 (save-excursion
12927 (beginning-of-line 1)
12928 (if (looking-at
afe98dfa 12929 (org-re ".*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))
20908596
CD
12930 (setq ov-start (match-beginning 1)
12931 ov-end (match-end 1)
12932 ov-prefix "")
12933 (setq ov-start (1- (point-at-eol))
12934 ov-end (1+ ov-start))
12935 (skip-chars-forward "^\n\r")
12936 (setq ov-prefix
12937 (concat
12938 (buffer-substring (1- (point)) (point))
12939 (if (> (current-column) org-tags-column)
12940 " "
12941 (make-string (- org-tags-column (current-column)) ?\ ))))))
86fbb8ca 12942 (move-overlay org-tags-overlay ov-start ov-end)
20908596
CD
12943 (save-window-excursion
12944 (if expert
12945 (set-buffer (get-buffer-create " *Org tags*"))
03f3cf35 12946 (delete-other-windows)
20908596
CD
12947 (split-window-vertically)
12948 (org-switch-to-buffer-other-window (get-buffer-create " *Org tags*")))
12949 (erase-buffer)
12950 (org-set-local 'org-done-keywords done-keywords)
12951 (org-fast-tag-insert "Inherited" inherited i-face "\n")
12952 (org-fast-tag-insert "Current" current c-face "\n\n")
12953 (org-fast-tag-show-exit exit-after-next)
12954 (org-set-current-tags-overlay current ov-prefix)
12955 (setq tbl fulltable char ?a cnt 0)
12956 (while (setq e (pop tbl))
12957 (cond
8bfe682a 12958 ((equal (car e) :startgroup)
20908596
CD
12959 (push '() groups) (setq ingroup t)
12960 (when (not (= cnt 0))
12961 (setq cnt 0)
12962 (insert "\n"))
8bfe682a
CD
12963 (insert (if (cdr e) (format "%s: " (cdr e)) "") "{ "))
12964 ((equal (car e) :endgroup)
20908596 12965 (setq ingroup nil cnt 0)
8bfe682a 12966 (insert "}" (if (cdr e) (format " (%s) " (cdr e)) "") "\n"))
c8d0cf5c
CD
12967 ((equal e '(:newline))
12968 (when (not (= cnt 0))
12969 (setq cnt 0)
12970 (insert "\n")
12971 (setq e (car tbl))
12972 (while (equal (car tbl) '(:newline))
12973 (insert "\n")
12974 (setq tbl (cdr tbl)))))
20908596 12975 (t
54a0dee5 12976 (setq tg (copy-sequence (car e)) c2 nil)
20908596
CD
12977 (if (cdr e)
12978 (setq c (cdr e))
12979 ;; automatically assign a character.
12980 (setq c1 (string-to-char
12981 (downcase (substring
12982 tg (if (= (string-to-char tg) ?@) 1 0)))))
12983 (if (or (rassoc c1 ntable) (rassoc c1 table))
12984 (while (or (rassoc char ntable) (rassoc char table))
12985 (setq char (1+ char)))
12986 (setq c2 c1))
12987 (setq c (or c2 char)))
12988 (if ingroup (push tg (car groups)))
12989 (setq tg (org-add-props tg nil 'face
12990 (cond
12991 ((not (assoc tg table))
12992 (org-get-todo-face tg))
12993 ((member tg current) c-face)
12994 ((member tg inherited) i-face)
12995 (t nil))))
12996 (if (and (= cnt 0) (not ingroup)) (insert " "))
12997 (insert "[" c "] " tg (make-string
12998 (- fwidth 4 (length tg)) ?\ ))
12999 (push (cons tg c) ntable)
13000 (when (= (setq cnt (1+ cnt)) ncol)
13001 (insert "\n")
13002 (if ingroup (insert " "))
13003 (setq cnt 0)))))
13004 (setq ntable (nreverse ntable))
13005 (insert "\n")
13006 (goto-char (point-min))
93b62de8 13007 (if (not expert) (org-fit-window-to-buffer))
20908596
CD
13008 (setq rtn
13009 (catch 'exit
13010 (while t
8bfe682a
CD
13011 (message "[a-z..]:Toggle [SPC]:clear [RET]:accept [TAB]:free [!] %sgroups%s"
13012 (if (not groups) "no " "")
20908596
CD
13013 (if expert " [C-c]:window" (if exit-after-next " [C-c]:single" " [C-c]:multi")))
13014 (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
ed21c5c8 13015 (setq org-last-tag-selection-key c)
03f3cf35 13016 (cond
20908596
CD
13017 ((= c ?\r) (throw 'exit t))
13018 ((= c ?!)
13019 (setq groups (not groups))
13020 (goto-char (point-min))
13021 (while (re-search-forward "[{}]" nil t) (replace-match " ")))
13022 ((= c ?\C-c)
13023 (if (not expert)
13024 (org-fast-tag-show-exit
13025 (setq exit-after-next (not exit-after-next)))
13026 (setq expert nil)
13027 (delete-other-windows)
13028 (split-window-vertically)
13029 (org-switch-to-buffer-other-window " *Org tags*")
93b62de8 13030 (org-fit-window-to-buffer)))
20908596
CD
13031 ((or (= c ?\C-g)
13032 (and (= c ?q) (not (rassoc c ntable))))
13033 (org-detach-overlay org-tags-overlay)
13034 (setq quit-flag t))
13035 ((= c ?\ )
13036 (setq current nil)
13037 (if exit-after-next (setq exit-after-next 'now)))
13038 ((= c ?\t)
13039 (condition-case nil
54a0dee5 13040 (setq tg (org-icompleting-read
20908596
CD
13041 "Tag: "
13042 (or buffer-tags
13043 (with-current-buffer buf
13044 (org-get-buffer-tags)))))
13045 (quit (setq tg "")))
13046 (when (string-match "\\S-" tg)
13047 (add-to-list 'buffer-tags (list tg))
13048 (if (member tg current)
13049 (setq current (delete tg current))
13050 (push tg current)))
13051 (if exit-after-next (setq exit-after-next 'now)))
13052 ((setq e (rassoc c todo-table) tg (car e))
13053 (with-current-buffer buf
13054 (save-excursion (org-todo tg)))
13055 (if exit-after-next (setq exit-after-next 'now)))
13056 ((setq e (rassoc c ntable) tg (car e))
13057 (if (member tg current)
13058 (setq current (delete tg current))
13059 (loop for g in groups do
13060 (if (member tg g)
13061 (mapc (lambda (x)
13062 (setq current (delete x current)))
13063 g)))
13064 (push tg current))
13065 (if exit-after-next (setq exit-after-next 'now))))
a3fbe8c4 13066
20908596
CD
13067 ;; Create a sorted list
13068 (setq current
13069 (sort current
13070 (lambda (a b)
13071 (assoc b (cdr (memq (assoc a ntable) ntable))))))
13072 (if (eq exit-after-next 'now) (throw 'exit t))
13073 (goto-char (point-min))
13074 (beginning-of-line 2)
13075 (delete-region (point) (point-at-eol))
13076 (org-fast-tag-insert "Current" current c-face)
13077 (org-set-current-tags-overlay current ov-prefix)
13078 (while (re-search-forward
afe98dfa 13079 (org-re "\\[.\\] \\([[:alnum:]_@#%]+\\)") nil t)
20908596
CD
13080 (setq tg (match-string 1))
13081 (add-text-properties
13082 (match-beginning 1) (match-end 1)
13083 (list 'face
13084 (cond
13085 ((member tg current) c-face)
13086 ((member tg inherited) i-face)
13087 (t (get-text-property (match-beginning 1) 'face))))))
13088 (goto-char (point-min)))))
13089 (org-detach-overlay org-tags-overlay)
13090 (if rtn
13091 (mapconcat 'identity current ":")
13092 nil))))
a3fbe8c4 13093
20908596
CD
13094(defun org-get-tags-string ()
13095 "Get the TAGS string in the current headline."
13096 (unless (org-on-heading-p t)
13097 (error "Not on a heading"))
13098 (save-excursion
13099 (beginning-of-line 1)
afe98dfa 13100 (if (looking-at (org-re ".*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))
20908596
CD
13101 (org-match-string-no-properties 1)
13102 "")))
a3fbe8c4 13103
20908596
CD
13104(defun org-get-tags ()
13105 "Get the list of tags specified in the current headline."
13106 (org-split-string (org-get-tags-string) ":"))
a3fbe8c4 13107
20908596
CD
13108(defun org-get-buffer-tags ()
13109 "Get a table of all tags used in the buffer, for completion."
13110 (let (tags)
2a57416f
CD
13111 (save-excursion
13112 (goto-char (point-min))
20908596 13113 (while (re-search-forward
afe98dfa 13114 (org-re "[ \t]:\\([[:alnum:]_@#%:]+\\):[ \t\r\n]") nil t)
20908596
CD
13115 (when (equal (char-after (point-at-bol 0)) ?*)
13116 (mapc (lambda (x) (add-to-list 'tags x))
13117 (org-split-string (org-match-string-no-properties 1) ":")))))
8bfe682a 13118 (mapc (lambda (s) (add-to-list 'tags s)) org-file-tags)
20908596 13119 (mapcar 'list tags)))
9acdaa21 13120
b349f79f
CD
13121;;;; The mapping API
13122
13123;;;###autoload
13124(defun org-map-entries (func &optional match scope &rest skip)
13125 "Call FUNC at each headline selected by MATCH in SCOPE.
13126
13127FUNC is a function or a lisp form. The function will be called without
13128arguments, with the cursor positioned at the beginning of the headline.
13129The return values of all calls to the function will be collected and
13130returned as a list.
13131
c8d0cf5c
CD
13132The call to FUNC will be wrapped into a save-excursion form, so FUNC
13133does not need to preserve point. After evaluation, the cursor will be
13134moved to the end of the line (presumably of the headline of the
13135processed entry) and search continues from there. Under some
13136circumstances, this may not produce the wanted results. For example,
13137if you have removed (e.g. archived) the current (sub)tree it could
13138mean that the next entry will be skipped entirely. In such cases, you
13139can specify the position from where search should continue by making
13140FUNC set the variable `org-map-continue-from' to the desired buffer
13141position.
13142
b349f79f
CD
13143MATCH is a tags/property/todo match as it is used in the agenda tags view.
13144Only headlines that are matched by this query will be considered during
13145the iteration. When MATCH is nil or t, all headlines will be
13146visited by the iteration.
13147
13148SCOPE determines the scope of this command. It can be any of:
13149
13150nil The current buffer, respecting the restriction if any
13151tree The subtree started with the entry at point
13152file The current buffer, without restriction
13153file-with-archives
13154 The current buffer, and any archives associated with it
13155agenda All agenda files
13156agenda-with-archives
13157 All agenda files with any archive files associated with them
13158\(file1 file2 ...)
13159 If this is a list, all files in the list will be scanned
13160
13161The remaining args are treated as settings for the skipping facilities of
13162the scanner. The following items can be given here:
13163
13164 archive skip trees with the archive tag.
13165 comment skip trees with the COMMENT keyword
13166 function or Emacs Lisp form:
13167 will be used as value for `org-agenda-skip-function', so whenever
04e65fdb 13168 the function returns t, FUNC will not be called for that
b349f79f 13169 entry and search will continue from the point where the
c8d0cf5c
CD
13170 function leaves it.
13171
13172If your function needs to retrieve the tags including inherited tags
13173at the *current* entry, you can use the value of the variable
13174`org-scanner-tags' which will be much faster than getting the value
13175with `org-get-tags-at'. If your function gets properties with
13176`org-entry-properties' at the *current* entry, bind `org-trust-scanner-tags'
13177to t around the call to `org-entry-properties' to get the same speedup.
13178Note that if your function moves around to retrieve tags and properties at
13179a *different* entry, you cannot use these techniques."
2c3ad40d
CD
13180 (let* ((org-agenda-archives-mode nil) ; just to make sure
13181 (org-agenda-skip-archived-trees (memq 'archive skip))
b349f79f
CD
13182 (org-agenda-skip-comment-trees (memq 'comment skip))
13183 (org-agenda-skip-function
13184 (car (org-delete-all '(comment archive) skip)))
13185 (org-tags-match-list-sublevels t)
65c439fd 13186 matcher file res
621f83e4
CD
13187 org-todo-keywords-for-agenda
13188 org-done-keywords-for-agenda
13189 org-todo-keyword-alist-for-agenda
8d642074 13190 org-drawers-for-agenda
621f83e4 13191 org-tag-alist-for-agenda)
b349f79f
CD
13192
13193 (cond
13194 ((eq match t) (setq matcher t))
13195 ((eq match nil) (setq matcher t))
ff4be292 13196 (t (setq matcher (if match (cdr (org-make-tags-matcher match)) t))))
ce4fdcb9 13197
0bd48b37
CD
13198 (save-excursion
13199 (save-restriction
13200 (when (eq scope 'tree)
13201 (org-back-to-heading t)
13202 (org-narrow-to-subtree)
13203 (setq scope nil))
ce4fdcb9 13204
0bd48b37
CD
13205 (if (not scope)
13206 (progn
13207 (org-prepare-agenda-buffers
13208 (list (buffer-file-name (current-buffer))))
13209 (setq res (org-scan-tags func matcher)))
13210 ;; Get the right scope
0bd48b37
CD
13211 (cond
13212 ((and scope (listp scope) (symbolp (car scope)))
13213 (setq scope (eval scope)))
13214 ((eq scope 'agenda)
13215 (setq scope (org-agenda-files t)))
13216 ((eq scope 'agenda-with-archives)
13217 (setq scope (org-agenda-files t))
13218 (setq scope (org-add-archive-files scope)))
13219 ((eq scope 'file)
13220 (setq scope (list (buffer-file-name))))
13221 ((eq scope 'file-with-archives)
13222 (setq scope (org-add-archive-files (list (buffer-file-name))))))
13223 (org-prepare-agenda-buffers scope)
13224 (while (setq file (pop scope))
13225 (with-current-buffer (org-find-base-buffer-visiting file)
13226 (save-excursion
13227 (save-restriction
13228 (widen)
13229 (goto-char (point-min))
13230 (setq res (append res (org-scan-tags func matcher))))))))))
13231 res))
9acdaa21 13232
20908596 13233;;;; Properties
9acdaa21 13234
20908596 13235;;; Setting and retrieving properties
891f4676 13236
20908596 13237(defconst org-special-properties
93b62de8 13238 '("TODO" "TAGS" "ALLTAGS" "DEADLINE" "SCHEDULED" "CLOCK" "CLOSED" "PRIORITY"
ed21c5c8 13239 "TIMESTAMP" "TIMESTAMP_IA" "BLOCKED")
20908596 13240 "The special properties valid in Org-mode.
9acdaa21 13241
20908596
CD
13242These are properties that are not defined in the property drawer,
13243but in some other way.")
9acdaa21 13244
20908596 13245(defconst org-default-properties
c8d0cf5c 13246 '("ARCHIVE" "CATEGORY" "SUMMARY" "DESCRIPTION" "CUSTOM_ID"
b349f79f
CD
13247 "LOCATION" "LOGGING" "COLUMNS" "VISIBILITY"
13248 "TABLE_EXPORT_FORMAT" "TABLE_EXPORT_FILE"
c8d0cf5c 13249 "EXPORT_FILE_NAME" "EXPORT_TITLE" "EXPORT_AUTHOR" "EXPORT_DATE"
86fbb8ca 13250 "ORDERED" "NOBLOCKING" "COOKIE_DATA" "LOG_INTO_DRAWER" "REPEAT_TO_STATE"
ed21c5c8 13251 "CLOCK_MODELINE_TOTAL" "STYLE" "HTML_CONTAINER_CLASS")
20908596
CD
13252 "Some properties that are used by Org-mode for various purposes.
13253Being in this list makes sure that they are offered for completion.")
9acdaa21 13254
20908596
CD
13255(defconst org-property-start-re "^[ \t]*:PROPERTIES:[ \t]*$"
13256 "Regular expression matching the first line of a property drawer.")
9acdaa21 13257
20908596 13258(defconst org-property-end-re "^[ \t]*:END:[ \t]*$"
ed21c5c8 13259 "Regular expression matching the last line of a property drawer.")
9acdaa21 13260
2c3ad40d
CD
13261(defconst org-clock-drawer-start-re "^[ \t]*:CLOCK:[ \t]*$"
13262 "Regular expression matching the first line of a property drawer.")
13263
13264(defconst org-clock-drawer-end-re "^[ \t]*:END:[ \t]*$"
13265 "Regular expression matching the first line of a property drawer.")
13266
13267(defconst org-property-drawer-re
13268 (concat "\\(" org-property-start-re "\\)[^\000]*\\("
13269 org-property-end-re "\\)\n?")
13270 "Matches an entire property drawer.")
13271
13272(defconst org-clock-drawer-re
13273 (concat "\\(" org-clock-drawer-start-re "\\)[^\000]*\\("
13274 org-property-end-re "\\)\n?")
13275 "Matches an entire clock drawer.")
13276
20908596
CD
13277(defun org-property-action ()
13278 "Do an action on properties."
03f3cf35 13279 (interactive)
20908596
CD
13280 (let (c)
13281 (org-at-property-p)
13282 (message "Property Action: [s]et [d]elete [D]elete globally [c]ompute")
13283 (setq c (read-char-exclusive))
13284 (cond
13285 ((equal c ?s)
13286 (call-interactively 'org-set-property))
13287 ((equal c ?d)
13288 (call-interactively 'org-delete-property))
13289 ((equal c ?D)
13290 (call-interactively 'org-delete-property-globally))
13291 ((equal c ?c)
13292 (call-interactively 'org-compute-property-at-point))
13293 (t (error "No such property action %c" c)))))
13294
54a0dee5
CD
13295(defun org-set-effort (&optional value)
13296 "Set the effort property of the current entry.
13297With numerical prefix arg, use the nth allowed value, 0 stands for the 10th
13298allowed value."
13299 (interactive "P")
13300 (if (equal value 0) (setq value 10))
13301 (let* ((completion-ignore-case t)
13302 (prop org-effort-property)
13303 (cur (org-entry-get nil prop))
13304 (allowed (org-property-get-allowed-values nil prop 'table))
13305 (existing (mapcar 'list (org-property-values prop)))
8bfe682a 13306 rpl
54a0dee5
CD
13307 (val (cond
13308 ((stringp value) value)
13309 ((and allowed (integerp value))
13310 (or (car (nth (1- value) allowed))
13311 (car (org-last allowed))))
13312 (allowed
8bfe682a
CD
13313 (message "Select 1-9,0, [RET%s]: %s"
13314 (if cur (concat "=" cur) "")
13315 (mapconcat 'car allowed " "))
13316 (setq rpl (read-char-exclusive))
13317 (if (equal rpl ?\r)
13318 cur
13319 (setq rpl (- rpl ?0))
13320 (if (equal rpl 0) (setq rpl 10))
13321 (if (and (> rpl 0) (<= rpl (length allowed)))
13322 (car (nth (1- rpl) allowed))
5dec9555 13323 (org-completing-read "Effort: " allowed nil))))
54a0dee5
CD
13324 (t
13325 (let (org-completion-use-ido org-completion-use-iswitchb)
13326 (org-completing-read
5dec9555 13327 (concat "Effort " (if (and cur (string-match "\\S-" cur))
54a0dee5
CD
13328 (concat "[" cur "]") "")
13329 ": ")
13330 existing nil nil "" nil cur))))))
13331 (unless (equal (org-entry-get nil prop) val)
13332 (org-entry-put nil prop val))
13333 (message "%s is now %s" prop val)))
13334
20908596 13335(defun org-at-property-p ()
ed21c5c8 13336 "Is cursor inside a property drawer?"
03f3cf35 13337 (save-excursion
20908596 13338 (beginning-of-line 1)
ed21c5c8 13339 (when (looking-at (org-re "^[ \t]*\\(:\\([[:alpha:]][[:alnum:]_-]*\\):\\)[ \t]*\\(.*\\)"))
86fbb8ca
CD
13340 (save-match-data ;; Used by calling procedures
13341 (let ((p (point))
13342 (range (unless (org-before-first-heading-p)
13343 (org-get-property-block))))
13344 (and range (<= (car range) p) (< p (cdr range))))))))
03f3cf35 13345
20908596
CD
13346(defun org-get-property-block (&optional beg end force)
13347 "Return the (beg . end) range of the body of the property drawer.
13348BEG and END can be beginning and end of subtree, if not given
13349they will be found.
13350If the drawer does not exist and FORCE is non-nil, create the drawer."
13351 (catch 'exit
d3f4dbe8 13352 (save-excursion
20908596
CD
13353 (let* ((beg (or beg (progn (org-back-to-heading t) (point))))
13354 (end (or end (progn (outline-next-heading) (point)))))
13355 (goto-char beg)
13356 (if (re-search-forward org-property-start-re end t)
13357 (setq beg (1+ (match-end 0)))
13358 (if force
13359 (save-excursion
13360 (org-insert-property-drawer)
13361 (setq end (progn (outline-next-heading) (point))))
13362 (throw 'exit nil))
13363 (goto-char beg)
13364 (if (re-search-forward org-property-start-re end t)
13365 (setq beg (1+ (match-end 0)))))
13366 (if (re-search-forward org-property-end-re end t)
13367 (setq end (match-beginning 0))
13368 (or force (throw 'exit nil))
13369 (goto-char beg)
13370 (setq end beg)
13371 (org-indent-line-function)
13372 (insert ":END:\n"))
13373 (cons beg end)))))
a3fbe8c4 13374
ed21c5c8 13375(defun org-entry-properties (&optional pom which specific)
20908596
CD
13376 "Get all properties of the entry at point-or-marker POM.
13377This includes the TODO keyword, the tags, time strings for deadline,
13378scheduled, and clocking, and any additional properties defined in the
13379entry. The return value is an alist, keys may occur multiple times
13380if the property key was used several times.
13381POM may also be nil, in which case the current entry is used.
13382If WHICH is nil or `all', get all properties. If WHICH is
ed21c5c8 13383`special' or `standard', only get that subclass. If WHICH
acedf35c 13384is a string only get exactly this property. SPECIFIC can be a string, the
ed21c5c8
CD
13385specific property we are interested in. Specifying it can speed
13386things up because then unnecessary parsing is avoided."
20908596
CD
13387 (setq which (or which 'all))
13388 (org-with-point-at pom
13389 (let ((clockstr (substring org-clock-string 0 -1))
ed21c5c8
CD
13390 (excluded '("TODO" "TAGS" "ALLTAGS" "PRIORITY" "BLOCKED"))
13391 (case-fold-search nil)
86fbb8ca 13392 beg end range props sum-props key key1 value string clocksum)
20908596 13393 (save-excursion
0bd48b37
CD
13394 (when (condition-case nil
13395 (and (org-mode-p) (org-back-to-heading t))
13396 (error nil))
20908596
CD
13397 (setq beg (point))
13398 (setq sum-props (get-text-property (point) 'org-summaries))
13399 (setq clocksum (get-text-property (point) :org-clock-minutes))
13400 (outline-next-heading)
13401 (setq end (point))
13402 (when (memq which '(all special))
13403 ;; Get the special properties, like TODO and tags
13404 (goto-char beg)
ed21c5c8
CD
13405 (when (and (or (not specific) (string= specific "TODO"))
13406 (looking-at org-todo-line-regexp) (match-end 2))
20908596 13407 (push (cons "TODO" (org-match-string-no-properties 2)) props))
ed21c5c8
CD
13408 (when (and (or (not specific) (string= specific "PRIORITY"))
13409 (looking-at org-priority-regexp))
20908596 13410 (push (cons "PRIORITY" (org-match-string-no-properties 2)) props))
ed21c5c8
CD
13411 (when (and (or (not specific) (string= specific "TAGS"))
13412 (setq value (org-get-tags-string))
20908596
CD
13413 (string-match "\\S-" value))
13414 (push (cons "TAGS" value) props))
ed21c5c8
CD
13415 (when (and (or (not specific) (string= specific "ALLTAGS"))
13416 (setq value (org-get-tags-at)))
13417 (push (cons "ALLTAGS" (concat ":" (mapconcat 'identity value ":")
13418 ":"))
20908596 13419 props))
ed21c5c8
CD
13420 (when (or (not specific) (string= specific "BLOCKED"))
13421 (push (cons "BLOCKED" (if (org-entry-blocked-p) "t" "")) props))
13422 (when (or (not specific)
86fbb8ca
CD
13423 (member specific
13424 '("SCHEDULED" "DEADLINE" "CLOCK" "CLOSED"
13425 "TIMESTAMP" "TIMESTAMP_IA")))
ed21c5c8 13426 (while (re-search-forward org-maybe-keyword-time-regexp end t)
86fbb8ca
CD
13427 (setq key (if (match-end 1)
13428 (substring (org-match-string-no-properties 1)
13429 0 -1))
ed21c5c8
CD
13430 string (if (equal key clockstr)
13431 (org-no-properties
13432 (org-trim
86fbb8ca
CD
13433 (buffer-substring
13434 (match-beginning 3) (goto-char
13435 (point-at-eol)))))
13436 (substring (org-match-string-no-properties 3)
13437 1 -1)))
13438 ;; Get the correct property name from the key. This is
13439 ;; necessary if the user has configured time keywords.
13440 (setq key1 (concat key ":"))
13441 (cond
13442 ((not key)
13443 (setq key
13444 (if (= (char-after (match-beginning 3)) ?\[)
13445 "TIMESTAMP_IA" "TIMESTAMP")))
13446 ((equal key1 org-scheduled-string) (setq key "SCHEDULED"))
13447 ((equal key1 org-deadline-string) (setq key "DEADLINE"))
13448 ((equal key1 org-closed-string) (setq key "CLOSED"))
13449 ((equal key1 org-clock-string) (setq key "CLOCK")))
13450 (when (or (equal key "CLOCK") (not (assoc key props)))
ed21c5c8 13451 (push (cons key string) props))))
20908596 13452 )
c4f9780e 13453
20908596 13454 (when (memq which '(all standard))
c8d0cf5c 13455 ;; Get the standard properties, like :PROP: ...
20908596
CD
13456 (setq range (org-get-property-block beg end))
13457 (when range
13458 (goto-char (car range))
13459 (while (re-search-forward
13460 (org-re "^[ \t]*:\\([[:alpha:]][[:alnum:]_-]*\\):[ \t]*\\(\\S-.*\\)?")
13461 (cdr range) t)
13462 (setq key (org-match-string-no-properties 1)
13463 value (org-trim (or (org-match-string-no-properties 2) "")))
13464 (unless (member key excluded)
13465 (push (cons key (or value "")) props)))))
13466 (if clocksum
13467 (push (cons "CLOCKSUM"
13468 (org-columns-number-to-string (/ (float clocksum) 60.)
13469 'add_times))
13470 props))
71d35b24
CD
13471 (unless (assoc "CATEGORY" props)
13472 (setq value (or (org-get-category)
13473 (progn (org-refresh-category-properties)
13474 (org-get-category))))
13475 (push (cons "CATEGORY" value) props))
20908596
CD
13476 (append sum-props (nreverse props)))))))
13477
86fbb8ca 13478(defun org-entry-get (pom property &optional inherit literal-nil)
20908596
CD
13479 "Get value of PROPERTY for entry at point-or-marker POM.
13480If INHERIT is non-nil and the entry does not have the property,
13481then also check higher levels of the hierarchy.
13482If INHERIT is the symbol `selective', use inheritance only if the setting
13483in `org-use-property-inheritance' selects PROPERTY for inheritance.
13484If the property is present but empty, the return value is the empty string.
86fbb8ca
CD
13485If the property is not present at all, nil is returned.
13486
13487If LITERAL-NIL is set, return the string value \"nil\" as a string,
13488do not interpret it as the list atom nil. This is used for inheritance
13489when a \"nil\" value can supersede a non-nil value higher up the hierarchy."
20908596
CD
13490 (org-with-point-at pom
13491 (if (and inherit (if (eq inherit 'selective)
13492 (org-property-inherit-p property)
13493 t))
86fbb8ca 13494 (org-entry-get-with-inheritance property literal-nil)
20908596 13495 (if (member property org-special-properties)
ed21c5c8
CD
13496 ;; We need a special property. Use `org-entry-properties' to
13497 ;; retrieve it, but specify the wanted property
13498 (cdr (assoc property (org-entry-properties nil 'special property)))
20908596
CD
13499 (let ((range (org-get-property-block)))
13500 (if (and range
13501 (goto-char (car range))
13502 (re-search-forward
93b62de8 13503 (concat "^[ \t]*:" property ":[ \t]*\\(.*[^ \t\r\n\f\v]\\)?")
20908596
CD
13504 (cdr range) t))
13505 ;; Found the property, return it.
13506 (if (match-end 1)
86fbb8ca
CD
13507 (if literal-nil
13508 (org-match-string-no-properties 1)
13509 (org-not-nil (org-match-string-no-properties 1)))
20908596
CD
13510 "")))))))
13511
13512(defun org-property-or-variable-value (var &optional inherit)
13513 "Check if there is a property fixing the value of VAR.
13514If yes, return this value. If not, return the current value of the variable."
13515 (let ((prop (org-entry-get nil (symbol-name var) inherit)))
13516 (if (and prop (stringp prop) (string-match "\\S-" prop))
13517 (read prop)
13518 (symbol-value var))))
13519
13520(defun org-entry-delete (pom property)
13521 "Delete the property PROPERTY from entry at point-or-marker POM."
13522 (org-with-point-at pom
13523 (if (member property org-special-properties)
13524 nil ; cannot delete these properties.
13525 (let ((range (org-get-property-block)))
13526 (if (and range
13527 (goto-char (car range))
13528 (re-search-forward
93b62de8 13529 (concat "^[ \t]*:" property ":[ \t]*\\(.*[^ \t\r\n\f\v]\\)")
20908596
CD
13530 (cdr range) t))
13531 (progn
13532 (delete-region (match-beginning 0) (1+ (point-at-eol)))
13533 t)
13534 nil)))))
13535
13536;; Multi-values properties are properties that contain multiple values
13537;; These values are assumed to be single words, separated by whitespace.
13538(defun org-entry-add-to-multivalued-property (pom property value)
13539 "Add VALUE to the words in the PROPERTY in entry at point-or-marker POM."
13540 (let* ((old (org-entry-get pom property))
13541 (values (and old (org-split-string old "[ \t]"))))
621f83e4 13542 (setq value (org-entry-protect-space value))
20908596
CD
13543 (unless (member value values)
13544 (setq values (cons value values))
13545 (org-entry-put pom property
13546 (mapconcat 'identity values " ")))))
13547
13548(defun org-entry-remove-from-multivalued-property (pom property value)
13549 "Remove VALUE from words in the PROPERTY in entry at point-or-marker POM."
13550 (let* ((old (org-entry-get pom property))
13551 (values (and old (org-split-string old "[ \t]"))))
621f83e4 13552 (setq value (org-entry-protect-space value))
20908596
CD
13553 (when (member value values)
13554 (setq values (delete value values))
13555 (org-entry-put pom property
13556 (mapconcat 'identity values " ")))))
9acdaa21 13557
20908596
CD
13558(defun org-entry-member-in-multivalued-property (pom property value)
13559 "Is VALUE one of the words in the PROPERTY in entry at point-or-marker POM?"
13560 (let* ((old (org-entry-get pom property))
13561 (values (and old (org-split-string old "[ \t]"))))
621f83e4 13562 (setq value (org-entry-protect-space value))
20908596 13563 (member value values)))
9acdaa21 13564
621f83e4
CD
13565(defun org-entry-get-multivalued-property (pom property)
13566 "Return a list of values in a multivalued property."
13567 (let* ((value (org-entry-get pom property))
13568 (values (and value (org-split-string value "[ \t]"))))
13569 (mapcar 'org-entry-restore-space values)))
13570
13571(defun org-entry-put-multivalued-property (pom property &rest values)
13572 "Set multivalued PROPERTY at point-or-marker POM to VALUES.
13573VALUES should be a list of strings. Spaces will be protected."
13574 (org-entry-put pom property
13575 (mapconcat 'org-entry-protect-space values " "))
13576 (let* ((value (org-entry-get pom property))
13577 (values (and value (org-split-string value "[ \t]"))))
13578 (mapcar 'org-entry-restore-space values)))
13579
13580(defun org-entry-protect-space (s)
13581 "Protect spaces and newline in string S."
13582 (while (string-match " " s)
13583 (setq s (replace-match "%20" t t s)))
13584 (while (string-match "\n" s)
13585 (setq s (replace-match "%0A" t t s)))
13586 s)
13587
13588(defun org-entry-restore-space (s)
13589 "Restore spaces and newline in string S."
13590 (while (string-match "%20" s)
13591 (setq s (replace-match " " t t s)))
13592 (while (string-match "%0A" s)
13593 (setq s (replace-match "\n" t t s)))
13594 s)
13595
13596(defvar org-entry-property-inherited-from (make-marker)
33306645 13597 "Marker pointing to the entry from where a property was inherited.
621f83e4 13598Each call to `org-entry-get-with-inheritance' will set this marker to the
33306645 13599location of the entry where the inheritance search matched. If there was
621f83e4
CD
13600no match, the marker will point nowhere.
13601Note that also `org-entry-get' calls this function, if the INHERIT flag
13602is set.")
15841868 13603
86fbb8ca
CD
13604(defun org-entry-get-with-inheritance (property &optional literal-nil)
13605 "Get entry property, and search higher levels if not present.
13606The search will stop at the first ancestor which has the property defined.
13607If the value found is \"nil\", return nil to show that the property
13608should be considered as undefined (this is the meaning of nil here).
13609However, if LITERAL-NIL is set, return the string value \"nil\" instead."
621f83e4 13610 (move-marker org-entry-property-inherited-from nil)
20908596
CD
13611 (let (tmp)
13612 (save-excursion
13613 (save-restriction
13614 (widen)
13615 (catch 'ex
13616 (while t
86fbb8ca 13617 (when (setq tmp (org-entry-get nil property nil 'literal-nil))
20908596
CD
13618 (org-back-to-heading t)
13619 (move-marker org-entry-property-inherited-from (point))
13620 (throw 'ex tmp))
13621 (or (org-up-heading-safe) (throw 'ex nil)))))
86fbb8ca
CD
13622 (setq tmp (or tmp
13623 (cdr (assoc property org-file-properties))
13624 (cdr (assoc property org-global-properties))
13625 (cdr (assoc property org-global-properties-fixed))))
13626 (if literal-nil tmp (org-not-nil tmp)))))
c4f9780e 13627
ed21c5c8
CD
13628(defvar org-property-changed-functions nil
13629 "Hook called when the value of a property has changed.
13630Each hook function should accept two arguments, the name of the property
13631and the new value.")
13632
20908596
CD
13633(defun org-entry-put (pom property value)
13634 "Set PROPERTY to VALUE for entry at point-or-marker POM."
13635 (org-with-point-at pom
13636 (org-back-to-heading t)
13637 (let ((beg (point)) (end (save-excursion (outline-next-heading) (point)))
13638 range)
13639 (cond
13640 ((equal property "TODO")
13641 (when (and (stringp value) (string-match "\\S-" value)
13642 (not (member value org-todo-keywords-1)))
13643 (error "\"%s\" is not a valid TODO state" value))
13644 (if (or (not value)
13645 (not (string-match "\\S-" value)))
13646 (setq value 'none))
13647 (org-todo value)
13648 (org-set-tags nil 'align))
13649 ((equal property "PRIORITY")
13650 (org-priority (if (and value (stringp value) (string-match "\\S-" value))
13651 (string-to-char value) ?\ ))
13652 (org-set-tags nil 'align))
13653 ((equal property "SCHEDULED")
13654 (if (re-search-forward org-scheduled-time-regexp end t)
13655 (cond
13656 ((eq value 'earlier) (org-timestamp-change -1 'day))
13657 ((eq value 'later) (org-timestamp-change 1 'day))
13658 (t (call-interactively 'org-schedule)))
13659 (call-interactively 'org-schedule)))
13660 ((equal property "DEADLINE")
13661 (if (re-search-forward org-deadline-time-regexp end t)
13662 (cond
13663 ((eq value 'earlier) (org-timestamp-change -1 'day))
13664 ((eq value 'later) (org-timestamp-change 1 'day))
13665 (t (call-interactively 'org-deadline)))
13666 (call-interactively 'org-deadline)))
13667 ((member property org-special-properties)
13668 (error "The %s property can not yet be set with `org-entry-put'"
13669 property))
13670 (t ; a non-special property
13671 (let ((buffer-invisibility-spec (org-inhibit-invisibility))) ; Emacs 21
13672 (setq range (org-get-property-block beg end 'force))
13673 (goto-char (car range))
13674 (if (re-search-forward
13675 (concat "^[ \t]*:" property ":\\(.*\\)") (cdr range) t)
13676 (progn
13677 (delete-region (match-beginning 1) (match-end 1))
13678 (goto-char (match-beginning 1)))
13679 (goto-char (cdr range))
13680 (insert "\n")
13681 (backward-char 1)
13682 (org-indent-line-function)
13683 (insert ":" property ":"))
13684 (and value (insert " " value))
ed21c5c8
CD
13685 (org-indent-line-function)))))
13686 (run-hook-with-args 'org-property-changed-functions property value)))
03f3cf35 13687
20908596
CD
13688(defun org-buffer-property-keys (&optional include-specials include-defaults include-columns)
13689 "Get all property keys in the current buffer.
33306645 13690With INCLUDE-SPECIALS, also list the special properties that reflect things
20908596
CD
13691like tags and TODO state.
13692With INCLUDE-DEFAULTS, also include properties that has special meaning
13693internally: ARCHIVE, CATEGORY, SUMMARY, DESCRIPTION, LOCATION, and LOGGING.
13694With INCLUDE-COLUMNS, also include property names given in COLUMN
13695formats in the current buffer."
65c439fd 13696 (let (rtn range cfmt s p)
d3f4dbe8 13697 (save-excursion
20908596
CD
13698 (save-restriction
13699 (widen)
13700 (goto-char (point-min))
13701 (while (re-search-forward org-property-start-re nil t)
13702 (setq range (org-get-property-block))
13703 (goto-char (car range))
13704 (while (re-search-forward
13705 (org-re "^[ \t]*:\\([-[:alnum:]_]+\\):")
13706 (cdr range) t)
13707 (add-to-list 'rtn (org-match-string-no-properties 1)))
13708 (outline-next-heading))))
791d856f 13709
20908596
CD
13710 (when include-specials
13711 (setq rtn (append org-special-properties rtn)))
d3f4dbe8 13712
20908596 13713 (when include-defaults
c8d0cf5c
CD
13714 (mapc (lambda (x) (add-to-list 'rtn x)) org-default-properties)
13715 (add-to-list 'rtn org-effort-property))
38f8646b 13716
20908596
CD
13717 (when include-columns
13718 (save-excursion
13719 (save-restriction
13720 (widen)
13721 (goto-char (point-min))
13722 (while (re-search-forward
13723 "^\\(#\\+COLUMNS:\\|[ \t]*:COLUMNS:\\)[ \t]*\\(.*\\)"
13724 nil t)
13725 (setq cfmt (match-string 2) s 0)
13726 (while (string-match (org-re "%[0-9]*\\([-[:alnum:]_]+\\)")
13727 cfmt s)
13728 (setq s (match-end 0)
13729 p (match-string 1 cfmt))
13730 (unless (or (equal p "ITEM")
13731 (member p org-special-properties))
13732 (add-to-list 'rtn (match-string 1 cfmt))))))))
2a57416f 13733
20908596 13734 (sort rtn (lambda (a b) (string< (upcase a) (upcase b))))))
2a57416f 13735
20908596
CD
13736(defun org-property-values (key)
13737 "Return a list of all values of property KEY."
13738 (save-excursion
13739 (save-restriction
13740 (widen)
13741 (goto-char (point-min))
13742 (let ((re (concat "^[ \t]*:" key ":[ \t]*\\(\\S-.*\\)"))
13743 values)
13744 (while (re-search-forward re nil t)
13745 (add-to-list 'values (org-trim (match-string 1))))
13746 (delete "" values)))))
2a57416f 13747
20908596
CD
13748(defun org-insert-property-drawer ()
13749 "Insert a property drawer into the current entry."
13750 (interactive)
13751 (org-back-to-heading t)
13752 (looking-at outline-regexp)
c8d0cf5c
CD
13753 (let ((indent (if org-adapt-indentation
13754 (- (match-end 0)(match-beginning 0))
13755 0))
20908596
CD
13756 (beg (point))
13757 (re (concat "^[ \t]*" org-keyword-time-regexp))
13758 end hiddenp)
13759 (outline-next-heading)
13760 (setq end (point))
13761 (goto-char beg)
13762 (while (re-search-forward re end t))
13763 (setq hiddenp (org-invisible-p))
13764 (end-of-line 1)
13765 (and (equal (char-after) ?\n) (forward-char 1))
c8d0cf5c
CD
13766 (while (looking-at "^[ \t]*\\(:CLOCK:\\|:LOGBOOK:\\|CLOCK:\\|:END:\\)")
13767 (if (member (match-string 1) '("CLOCK:" ":END:"))
13768 ;; just skip this line
13769 (beginning-of-line 2)
13770 ;; Drawer start, find the end
13771 (re-search-forward "^\\*+ \\|^[ \t]*:END:" nil t)
13772 (beginning-of-line 1)))
20908596
CD
13773 (org-skip-over-state-notes)
13774 (skip-chars-backward " \t\n\r")
13775 (if (eq (char-before) ?*) (forward-char 1))
13776 (let ((inhibit-read-only t)) (insert "\n:PROPERTIES:\n:END:"))
13777 (beginning-of-line 0)
13778 (org-indent-to-column indent)
13779 (beginning-of-line 2)
13780 (org-indent-to-column indent)
13781 (beginning-of-line 0)
13782 (if hiddenp
13783 (save-excursion
13784 (org-back-to-heading t)
13785 (hide-entry))
13786 (org-flag-drawer t))))
d3f4dbe8 13787
20908596
CD
13788(defun org-set-property (property value)
13789 "In the current entry, set PROPERTY to VALUE.
13790When called interactively, this will prompt for a property name, offering
13791completion on existing and default properties. And then it will prompt
33306645 13792for a value, offering completion either on allowed values (via an inherited
20908596
CD
13793xxx_ALL property) or on existing values in other instances of this property
13794in the current file."
13795 (interactive
b349f79f
CD
13796 (let* ((completion-ignore-case t)
13797 (keys (org-buffer-property-keys nil t t))
54a0dee5 13798 (prop0 (org-icompleting-read "Property: " (mapcar 'list keys)))
b349f79f
CD
13799 (prop (if (member prop0 keys)
13800 prop0
13801 (or (cdr (assoc (downcase prop0)
13802 (mapcar (lambda (x) (cons (downcase x) x))
13803 keys)))
13804 prop0)))
20908596 13805 (cur (org-entry-get nil prop))
ed21c5c8
CD
13806 (prompt (concat prop " value"
13807 (if (and cur (string-match "\\S-" cur))
13808 (concat " [" cur "]") "") ": "))
20908596
CD
13809 (allowed (org-property-get-allowed-values nil prop 'table))
13810 (existing (mapcar 'list (org-property-values prop)))
13811 (val (if allowed
ed21c5c8
CD
13812 (org-completing-read prompt allowed nil
13813 (not (get-text-property 0 'org-unrestricted
13814 (caar allowed))))
54a0dee5 13815 (let (org-completion-use-ido org-completion-use-iswitchb)
ed21c5c8 13816 (org-completing-read prompt existing nil nil "" nil cur)))))
20908596
CD
13817 (list prop (if (equal val "") cur val))))
13818 (unless (equal (org-entry-get nil property) value)
13819 (org-entry-put nil property value)))
791d856f 13820
20908596
CD
13821(defun org-delete-property (property)
13822 "In the current entry, delete PROPERTY."
13823 (interactive
b349f79f 13824 (let* ((completion-ignore-case t)
86fbb8ca
CD
13825 (prop (org-icompleting-read "Property: "
13826 (org-entry-properties nil 'standard))))
20908596
CD
13827 (list prop)))
13828 (message "Property %s %s" property
13829 (if (org-entry-delete nil property)
13830 "deleted"
13831 "was not present in the entry")))
d3f4dbe8 13832
20908596
CD
13833(defun org-delete-property-globally (property)
13834 "Remove PROPERTY globally, from all entries."
13835 (interactive
b349f79f 13836 (let* ((completion-ignore-case t)
54a0dee5 13837 (prop (org-icompleting-read
20908596
CD
13838 "Globally remove property: "
13839 (mapcar 'list (org-buffer-property-keys)))))
13840 (list prop)))
13841 (save-excursion
13842 (save-restriction
13843 (widen)
13844 (goto-char (point-min))
13845 (let ((cnt 0))
13846 (while (re-search-forward
13847 (concat "^[ \t]*:" (regexp-quote property) ":.*\n?")
13848 nil t)
13849 (setq cnt (1+ cnt))
13850 (replace-match ""))
13851 (message "Property \"%s\" removed from %d entries" property cnt)))))
d3f4dbe8 13852
20908596 13853(defvar org-columns-current-fmt-compiled) ; defined in org-colview.el
d3f4dbe8 13854
20908596
CD
13855(defun org-compute-property-at-point ()
13856 "Compute the property at point.
13857This looks for an enclosing column format, extracts the operator and
33306645 13858then applies it to the property in the column format's scope."
30313b90 13859 (interactive)
20908596
CD
13860 (unless (org-at-property-p)
13861 (error "Not at a property"))
13862 (let ((prop (org-match-string-no-properties 2)))
13863 (org-columns-get-format-and-top-level)
13864 (unless (nth 3 (assoc prop org-columns-current-fmt-compiled))
13865 (error "No operator defined for property %s" prop))
13866 (org-columns-compute prop)))
d3f4dbe8 13867
ed21c5c8
CD
13868(defvar org-property-allowed-value-functions nil
13869 "Hook for functions supplying allowed values for a specific property.
13870The functions must take a single argument, the name of the property, and
13871return a flat list of allowed values. If \":ETC\" is one of
13872the values, this means that these values are intended as defaults for
13873completion, but that other values should be allowed too.
13874The functions must return nil if they are not responsible for this
13875property.")
13876
20908596
CD
13877(defun org-property-get-allowed-values (pom property &optional table)
13878 "Get allowed values for the property PROPERTY.
13879When TABLE is non-nil, return an alist that can directly be used for
13880completion."
13881 (let (vals)
13882 (cond
13883 ((equal property "TODO")
13884 (setq vals (org-with-point-at pom
13885 (append org-todo-keywords-1 '("")))))
13886 ((equal property "PRIORITY")
13887 (let ((n org-lowest-priority))
13888 (while (>= n org-highest-priority)
13889 (push (char-to-string n) vals)
13890 (setq n (1- n)))))
13891 ((member property org-special-properties))
ed21c5c8
CD
13892 ((setq vals (run-hook-with-args-until-success
13893 'org-property-allowed-value-functions property)))
20908596
CD
13894 (t
13895 (setq vals (org-entry-get pom (concat property "_ALL") 'inherit))
20908596
CD
13896 (when (and vals (string-match "\\S-" vals))
13897 (setq vals (car (read-from-string (concat "(" vals ")"))))
13898 (setq vals (mapcar (lambda (x)
13899 (cond ((stringp x) x)
13900 ((numberp x) (number-to-string x))
13901 ((symbolp x) (symbol-name x))
13902 (t "???")))
13903 vals)))))
ed21c5c8
CD
13904 (when (member ":ETC" vals)
13905 (setq vals (remove ":ETC" vals))
13906 (org-add-props (car vals) '(org-unrestricted t)))
20908596 13907 (if table (mapcar 'list vals) vals)))
03f3cf35 13908
20908596
CD
13909(defun org-property-previous-allowed-value (&optional previous)
13910 "Switch to the next allowed value for this property."
13911 (interactive)
13912 (org-property-next-allowed-value t))
d3f4dbe8 13913
20908596
CD
13914(defun org-property-next-allowed-value (&optional previous)
13915 "Switch to the next allowed value for this property."
d3f4dbe8 13916 (interactive)
20908596
CD
13917 (unless (org-at-property-p)
13918 (error "Not at a property"))
13919 (let* ((key (match-string 2))
13920 (value (match-string 3))
13921 (allowed (or (org-property-get-allowed-values (point) key)
13922 (and (member value '("[ ]" "[-]" "[X]"))
13923 '("[ ]" "[X]"))))
13924 nval)
13925 (unless allowed
13926 (error "Allowed values for this property have not been defined"))
13927 (if previous (setq allowed (reverse allowed)))
13928 (if (member value allowed)
13929 (setq nval (car (cdr (member value allowed)))))
13930 (setq nval (or nval (car allowed)))
13931 (if (equal nval value)
13932 (error "Only one allowed value for this property"))
13933 (org-at-property-p)
13934 (replace-match (concat " :" key ": " nval) t t)
13935 (org-indent-line-function)
13936 (beginning-of-line 1)
ed21c5c8
CD
13937 (skip-chars-forward " \t")
13938 (run-hook-with-args 'org-property-changed-functions key nval)))
d3f4dbe8 13939
86fbb8ca
CD
13940(defun org-find-olp (path &optional this-buffer)
13941 "Return a marker pointing to the entry at outline path OLP.
13942If anything goes wrong, throw an error.
13943You can wrap this call to catch the error like this:
13944
13945 (condition-case msg
13946 (org-mobile-locate-entry (match-string 4))
13947 (error (nth 1 msg)))
13948
13949The return value will then be either a string with the error message,
13950or a marker if everything is OK.
13951
13952If THIS-BUFFER is set, the outline path does not contain a file,
13953only headings."
13954 (let* ((file (if this-buffer buffer-file-name (pop path)))
13955 (buffer (if this-buffer (current-buffer) (find-file-noselect file)))
13956 (level 1)
13957 (lmin 1)
13958 (lmax 1)
13959 limit re end found pos heading cnt)
13960 (unless buffer (error "File not found :%s" file))
13961 (with-current-buffer buffer
13962 (save-excursion
13963 (save-restriction
13964 (widen)
13965 (setq limit (point-max))
13966 (goto-char (point-min))
13967 (while (setq heading (pop path))
13968 (setq re (format org-complex-heading-regexp-format
13969 (regexp-quote heading)))
13970 (setq cnt 0 pos (point))
13971 (while (re-search-forward re end t)
13972 (setq level (- (match-end 1) (match-beginning 1)))
13973 (if (and (>= level lmin) (<= level lmax))
13974 (setq found (match-beginning 0) cnt (1+ cnt))))
13975 (when (= cnt 0) (error "Heading not found on level %d: %s"
13976 lmax heading))
13977 (when (> cnt 1) (error "Heading not unique on level %d: %s"
13978 lmax heading))
13979 (goto-char found)
13980 (setq lmin (1+ level) lmax (+ lmin (if org-odd-levels-only 1 0)))
13981 (setq end (save-excursion (org-end-of-subtree t t))))
13982 (when (org-on-heading-p)
13983 (move-marker (make-marker) (point))))))))
13984
afe98dfa
CD
13985(defun org-find-exact-headline-in-buffer (heading &optional buffer pos-only)
13986 "Find node HEADING in BUFFER.
13987Return a marker to the heading if it was found, or nil if not.
13988If POS-ONLY is set, return just the position instead of a marker.
13989
13990The heading text must match exact, but it may have a TODO keyword,
13991a priority cookie and tags in the standard locations."
13992 (with-current-buffer (or buffer (current-buffer))
13993 (save-excursion
13994 (save-restriction
13995 (widen)
13996 (goto-char (point-min))
13997 (let (case-fold-search)
13998 (if (re-search-forward
13999 (format org-complex-heading-regexp-format
14000 (regexp-quote heading)) nil t)
14001 (if pos-only
14002 (match-beginning 0)
14003 (move-marker (make-marker) (match-beginning 0)))))))))
14004
14005(defun org-find-exact-heading-in-directory (heading &optional dir)
14006 "Find Org node headline HEADING in all .org files in directory DIR.
14007When the target headline is found, return a marker to this location."
14008 (let ((files (directory-files (or dir default-directory)
14009 nil "\\`[^.#].*\\.org\\'"))
14010 file visiting m buffer)
14011 (catch 'found
14012 (while (setq file (pop files))
14013 (message "trying %s" file)
14014 (setq visiting (org-find-base-buffer-visiting file))
14015 (setq buffer (or visiting (find-file-noselect file)))
14016 (setq m (org-find-exact-headline-in-buffer
14017 heading buffer))
14018 (when (and (not m) (not visiting)) (kill-buffer buffer))
14019 (and m (throw 'found m))))))
14020
20908596
CD
14021(defun org-find-entry-with-id (ident)
14022 "Locate the entry that contains the ID property with exact value IDENT.
14023IDENT can be a string, a symbol or a number, this function will search for
14024the string representation of it.
14025Return the position where this entry starts, or nil if there is no such entry."
db55f368 14026 (interactive "sID: ")
20908596
CD
14027 (let ((id (cond
14028 ((stringp ident) ident)
14029 ((symbol-name ident) (symbol-name ident))
14030 ((numberp ident) (number-to-string ident))
14031 (t (error "IDENT %s must be a string, symbol or number" ident))))
14032 (case-fold-search nil))
14033 (save-excursion
14034 (save-restriction
14035 (widen)
14036 (goto-char (point-min))
14037 (when (re-search-forward
14038 (concat "^[ \t]*:ID:[ \t]+" (regexp-quote id) "[ \t]*$")
14039 nil t)
c8d0cf5c 14040 (org-back-to-heading t)
20908596 14041 (point))))))
48aaad2d 14042
20908596 14043;;;; Timestamps
d3f4dbe8 14044
20908596 14045(defvar org-last-changed-timestamp nil)
b349f79f
CD
14046(defvar org-last-inserted-timestamp nil
14047 "The last time stamp inserted with `org-insert-time-stamp'.")
20908596
CD
14048(defvar org-time-was-given) ; dynamically scoped parameter
14049(defvar org-end-time-was-given) ; dynamically scoped parameter
14050(defvar org-ts-what) ; dynamically scoped parameter
14051
621f83e4 14052(defun org-time-stamp (arg &optional inactive)
20908596
CD
14053 "Prompt for a date/time and insert a time stamp.
14054If the user specifies a time like HH:MM, or if this command is called
14055with a prefix argument, the time stamp will contain date and time.
14056Otherwise, only the date will be included. All parts of a date not
14057specified by the user will be filled in from the current date/time.
14058So if you press just return without typing anything, the time stamp
14059will represent the current date/time. If there is already a timestamp
14060at the cursor, it will be modified."
14061 (interactive "P")
14062 (let* ((ts nil)
14063 (default-time
14064 ;; Default time is either today, or, when entering a range,
14065 ;; the range start.
14066 (if (or (and (org-at-timestamp-p t) (setq ts (match-string 0)))
14067 (save-excursion
14068 (re-search-backward
14069 (concat org-ts-regexp "--?-?\\=") ; 1-3 minuses
14070 (- (point) 20) t)))
14071 (apply 'encode-time (org-parse-time-string (match-string 1)))
14072 (current-time)))
14073 (default-input (and ts (org-get-compact-tod ts)))
14074 org-time-was-given org-end-time-was-given time)
14075 (cond
621f83e4
CD
14076 ((and (org-at-timestamp-p t)
14077 (memq last-command '(org-time-stamp org-time-stamp-inactive))
14078 (memq this-command '(org-time-stamp org-time-stamp-inactive)))
20908596
CD
14079 (insert "--")
14080 (setq time (let ((this-command this-command))
621f83e4
CD
14081 (org-read-date arg 'totime nil nil
14082 default-time default-input)))
14083 (org-insert-time-stamp time (or org-time-was-given arg) inactive))
14084 ((org-at-timestamp-p t)
20908596
CD
14085 (setq time (let ((this-command this-command))
14086 (org-read-date arg 'totime nil nil default-time default-input)))
621f83e4
CD
14087 (when (org-at-timestamp-p t) ; just to get the match data
14088; (setq inactive (eq (char-after (match-beginning 0)) ?\[))
20908596
CD
14089 (replace-match "")
14090 (setq org-last-changed-timestamp
14091 (org-insert-time-stamp
14092 time (or org-time-was-given arg)
621f83e4 14093 inactive nil nil (list org-end-time-was-given))))
20908596
CD
14094 (message "Timestamp updated"))
14095 (t
14096 (setq time (let ((this-command this-command))
14097 (org-read-date arg 'totime nil nil default-time default-input)))
621f83e4
CD
14098 (org-insert-time-stamp time (or org-time-was-given arg) inactive
14099 nil nil (list org-end-time-was-given))))))
d3f4dbe8 14100
20908596
CD
14101;; FIXME: can we use this for something else, like computing time differences?
14102(defun org-get-compact-tod (s)
14103 (when (string-match "\\(\\([012]?[0-9]\\):\\([0-5][0-9]\\)\\)\\(-\\(\\([012]?[0-9]\\):\\([0-5][0-9]\\)\\)\\)?" s)
14104 (let* ((t1 (match-string 1 s))
14105 (h1 (string-to-number (match-string 2 s)))
14106 (m1 (string-to-number (match-string 3 s)))
14107 (t2 (and (match-end 4) (match-string 5 s)))
14108 (h2 (and t2 (string-to-number (match-string 6 s))))
14109 (m2 (and t2 (string-to-number (match-string 7 s))))
14110 dh dm)
14111 (if (not t2)
14112 t1
14113 (setq dh (- h2 h1) dm (- m2 m1))
14114 (if (< dm 0) (setq dm (+ dm 60) dh (1- dh)))
14115 (concat t1 "+" (number-to-string dh)
14116 (if (/= 0 dm) (concat ":" (number-to-string dm))))))))
d3f4dbe8 14117
20908596
CD
14118(defun org-time-stamp-inactive (&optional arg)
14119 "Insert an inactive time stamp.
14120An inactive time stamp is enclosed in square brackets instead of angle
14121brackets. It is inactive in the sense that it does not trigger agenda entries,
14122does not link to the calendar and cannot be changed with the S-cursor keys.
14123So these are more for recording a certain time/date."
14124 (interactive "P")
621f83e4 14125 (org-time-stamp arg 'inactive))
15841868 14126
86fbb8ca
CD
14127(defvar org-date-ovl (make-overlay 1 1))
14128(overlay-put org-date-ovl 'face 'org-warning)
20908596 14129(org-detach-overlay org-date-ovl)
d3f4dbe8 14130
20908596
CD
14131(defvar org-ans1) ; dynamically scoped parameter
14132(defvar org-ans2) ; dynamically scoped parameter
8c6fb58b 14133
20908596 14134(defvar org-plain-time-of-day-regexp) ; defined below
d3f4dbe8 14135
b349f79f 14136(defvar org-overriding-default-time nil) ; dynamically scoped
20908596
CD
14137(defvar org-read-date-overlay nil)
14138(defvar org-dcst nil) ; dynamically scoped
c8d0cf5c
CD
14139(defvar org-read-date-history nil)
14140(defvar org-read-date-final-answer nil)
d3f4dbe8 14141
20908596
CD
14142(defun org-read-date (&optional with-time to-time from-string prompt
14143 default-time default-input)
14144 "Read a date, possibly a time, and make things smooth for the user.
14145The prompt will suggest to enter an ISO date, but you can also enter anything
14146which will at least partially be understood by `parse-time-string'.
14147Unrecognized parts of the date will default to the current day, month, year,
14148hour and minute. If this command is called to replace a timestamp at point,
86fbb8ca
CD
14149of to enter the second timestamp of a range, the default time is taken
14150from the existing stamp. Furthermore, the command prefers the future,
14151so if you are giving a date where the year is not given, and the day-month
14152combination is already past in the current year, it will assume you
14153mean next year. For details, see the manual. A few examples:
14154
20908596
CD
14155 3-2-5 --> 2003-02-05
14156 feb 15 --> currentyear-02-15
86fbb8ca 14157 2/15 --> currentyear-02-15
20908596
CD
14158 sep 12 9 --> 2009-09-12
14159 12:45 --> today 12:45
14160 22 sept 0:34 --> currentyear-09-22 0:34
14161 12 --> currentyear-currentmonth-12
14162 Fri --> nearest Friday (today or later)
14163 etc.
8c6fb58b 14164
20908596
CD
14165Furthermore you can specify a relative date by giving, as the *first* thing
14166in the input: a plus/minus sign, a number and a letter [dwmy] to indicate
14167change in days weeks, months, years.
14168With a single plus or minus, the date is relative to today. With a double
14169plus or minus, it is relative to the date in DEFAULT-TIME. E.g.
14170 +4d --> four days from today
14171 +4 --> same as above
14172 +2w --> two weeks from today
14173 ++5 --> five days from default date
d3f4dbe8 14174
20908596
CD
14175The function understands only English month and weekday abbreviations,
14176but this can be configured with the variables `parse-time-months' and
14177`parse-time-weekdays'.
d3f4dbe8 14178
20908596
CD
14179While prompting, a calendar is popped up - you can also select the
14180date with the mouse (button 1). The calendar shows a period of three
14181months. To scroll it to other months, use the keys `>' and `<'.
14182If you don't like the calendar, turn it off with
14183 \(setq org-read-date-popup-calendar nil)
48aaad2d 14184
20908596
CD
14185With optional argument TO-TIME, the date will immediately be converted
14186to an internal time.
14187With an optional argument WITH-TIME, the prompt will suggest to also
14188insert a time. Note that when WITH-TIME is not set, you can still
14189enter a time, and this function will inform the calling routine about
14190this change. The calling routine may then choose to change the format
14191used to insert the time stamp into the buffer to include the time.
14192With optional argument FROM-STRING, read from this string instead from
14193the user. PROMPT can overwrite the default prompt. DEFAULT-TIME is
14194the time/date that is used for everything that is not specified by the
14195user."
14196 (require 'parse-time)
14197 (let* ((org-time-stamp-rounding-minutes
14198 (if (equal with-time '(16)) '(0 0) org-time-stamp-rounding-minutes))
14199 (org-dcst org-display-custom-times)
14200 (ct (org-current-time))
b349f79f 14201 (def (or org-overriding-default-time default-time ct))
20908596
CD
14202 (defdecode (decode-time def))
14203 (dummy (progn
14204 (when (< (nth 2 defdecode) org-extend-today-until)
14205 (setcar (nthcdr 2 defdecode) -1)
14206 (setcar (nthcdr 1 defdecode) 59)
14207 (setq def (apply 'encode-time defdecode)
14208 defdecode (decode-time def)))))
c8d0cf5c 14209 (calendar-frame-setup nil)
86fbb8ca 14210 (calendar-setup nil)
20908596
CD
14211 (calendar-move-hook nil)
14212 (calendar-view-diary-initially-flag nil)
20908596 14213 (calendar-view-holidays-initially-flag nil)
20908596
CD
14214 (timestr (format-time-string
14215 (if with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") def))
14216 (prompt (concat (if prompt (concat prompt " ") "")
14217 (format "Date+time [%s]: " timestr)))
14218 ans (org-ans0 "") org-ans1 org-ans2 final)
d3f4dbe8 14219
38f8646b 14220 (cond
20908596
CD
14221 (from-string (setq ans from-string))
14222 (org-read-date-popup-calendar
14223 (save-excursion
14224 (save-window-excursion
14225 (calendar)
14226 (calendar-forward-day (- (time-to-days def)
14227 (calendar-absolute-from-gregorian
14228 (calendar-current-date))))
14229 (org-eval-in-calendar nil t)
14230 (let* ((old-map (current-local-map))
14231 (map (copy-keymap calendar-mode-map))
14232 (minibuffer-local-map (copy-keymap minibuffer-local-map)))
14233 (org-defkey map (kbd "RET") 'org-calendar-select)
86fbb8ca
CD
14234 (org-defkey map [mouse-1] 'org-calendar-select-mouse)
14235 (org-defkey map [mouse-2] 'org-calendar-select-mouse)
20908596 14236 (org-defkey minibuffer-local-map [(meta shift left)]
c8d0cf5c
CD
14237 (lambda () (interactive)
14238 (org-eval-in-calendar '(calendar-backward-month 1))))
20908596 14239 (org-defkey minibuffer-local-map [(meta shift right)]
c8d0cf5c
CD
14240 (lambda () (interactive)
14241 (org-eval-in-calendar '(calendar-forward-month 1))))
20908596 14242 (org-defkey minibuffer-local-map [(meta shift up)]
c8d0cf5c
CD
14243 (lambda () (interactive)
14244 (org-eval-in-calendar '(calendar-backward-year 1))))
20908596 14245 (org-defkey minibuffer-local-map [(meta shift down)]
c8d0cf5c
CD
14246 (lambda () (interactive)
14247 (org-eval-in-calendar '(calendar-forward-year 1))))
14248 (org-defkey minibuffer-local-map [?\e (shift left)]
14249 (lambda () (interactive)
14250 (org-eval-in-calendar '(calendar-backward-month 1))))
14251 (org-defkey minibuffer-local-map [?\e (shift right)]
14252 (lambda () (interactive)
14253 (org-eval-in-calendar '(calendar-forward-month 1))))
14254 (org-defkey minibuffer-local-map [?\e (shift up)]
14255 (lambda () (interactive)
14256 (org-eval-in-calendar '(calendar-backward-year 1))))
14257 (org-defkey minibuffer-local-map [?\e (shift down)]
14258 (lambda () (interactive)
14259 (org-eval-in-calendar '(calendar-forward-year 1))))
20908596 14260 (org-defkey minibuffer-local-map [(shift up)]
c8d0cf5c
CD
14261 (lambda () (interactive)
14262 (org-eval-in-calendar '(calendar-backward-week 1))))
20908596 14263 (org-defkey minibuffer-local-map [(shift down)]
c8d0cf5c
CD
14264 (lambda () (interactive)
14265 (org-eval-in-calendar '(calendar-forward-week 1))))
20908596 14266 (org-defkey minibuffer-local-map [(shift left)]
c8d0cf5c
CD
14267 (lambda () (interactive)
14268 (org-eval-in-calendar '(calendar-backward-day 1))))
20908596 14269 (org-defkey minibuffer-local-map [(shift right)]
c8d0cf5c
CD
14270 (lambda () (interactive)
14271 (org-eval-in-calendar '(calendar-forward-day 1))))
20908596 14272 (org-defkey minibuffer-local-map ">"
c8d0cf5c
CD
14273 (lambda () (interactive)
14274 (org-eval-in-calendar '(scroll-calendar-left 1))))
20908596 14275 (org-defkey minibuffer-local-map "<"
c8d0cf5c
CD
14276 (lambda () (interactive)
14277 (org-eval-in-calendar '(scroll-calendar-right 1))))
86fbb8ca
CD
14278 (org-defkey minibuffer-local-map "\C-v"
14279 (lambda () (interactive)
14280 (org-eval-in-calendar
14281 '(calendar-scroll-left-three-months 1))))
14282 (org-defkey minibuffer-local-map "\M-v"
14283 (lambda () (interactive)
14284 (org-eval-in-calendar
14285 '(calendar-scroll-right-three-months 1))))
c8d0cf5c 14286 (run-hooks 'org-read-date-minibuffer-setup-hook)
20908596
CD
14287 (unwind-protect
14288 (progn
14289 (use-local-map map)
14290 (add-hook 'post-command-hook 'org-read-date-display)
c8d0cf5c
CD
14291 (setq org-ans0 (read-string prompt default-input
14292 'org-read-date-history nil))
20908596
CD
14293 ;; org-ans0: from prompt
14294 ;; org-ans1: from mouse click
14295 ;; org-ans2: from calendar motion
14296 (setq ans (concat org-ans0 " " (or org-ans1 org-ans2))))
14297 (remove-hook 'post-command-hook 'org-read-date-display)
14298 (use-local-map old-map)
14299 (when org-read-date-overlay
86fbb8ca 14300 (delete-overlay org-read-date-overlay)
20908596 14301 (setq org-read-date-overlay nil)))))))
d3f4dbe8 14302
20908596
CD
14303 (t ; Naked prompt only
14304 (unwind-protect
c8d0cf5c
CD
14305 (setq ans (read-string prompt default-input
14306 'org-read-date-history timestr))
20908596 14307 (when org-read-date-overlay
86fbb8ca 14308 (delete-overlay org-read-date-overlay)
20908596 14309 (setq org-read-date-overlay nil)))))
d3f4dbe8 14310
20908596 14311 (setq final (org-read-date-analyze ans def defdecode))
afe98dfa
CD
14312
14313 ;; One round trip to get rid of 34th of August and stuff like that....
14314 (setq final (decode-time (apply 'encode-time final)))
14315
c8d0cf5c 14316 (setq org-read-date-final-answer ans)
d3f4dbe8 14317
20908596
CD
14318 (if to-time
14319 (apply 'encode-time final)
14320 (if (and (boundp 'org-time-was-given) org-time-was-given)
14321 (format "%04d-%02d-%02d %02d:%02d"
14322 (nth 5 final) (nth 4 final) (nth 3 final)
14323 (nth 2 final) (nth 1 final))
14324 (format "%04d-%02d-%02d" (nth 5 final) (nth 4 final) (nth 3 final))))))
c8d0cf5c 14325
20908596
CD
14326(defvar def)
14327(defvar defdecode)
14328(defvar with-time)
8bfe682a 14329(defvar org-read-date-analyze-futurep nil)
20908596 14330(defun org-read-date-display ()
33306645 14331 "Display the current date prompt interpretation in the minibuffer."
20908596
CD
14332 (when org-read-date-display-live
14333 (when org-read-date-overlay
86fbb8ca 14334 (delete-overlay org-read-date-overlay))
20908596
CD
14335 (let ((p (point)))
14336 (end-of-line 1)
14337 (while (not (equal (buffer-substring
14338 (max (point-min) (- (point) 4)) (point))
14339 " "))
14340 (insert " "))
14341 (goto-char p))
14342 (let* ((ans (concat (buffer-substring (point-at-bol) (point-max))
14343 " " (or org-ans1 org-ans2)))
14344 (org-end-time-was-given nil)
14345 (f (org-read-date-analyze ans def defdecode))
14346 (fmts (if org-dcst
14347 org-time-stamp-custom-formats
14348 org-time-stamp-formats))
14349 (fmt (if (or with-time
14350 (and (boundp 'org-time-was-given) org-time-was-given))
14351 (cdr fmts)
14352 (car fmts)))
14353 (txt (concat "=> " (format-time-string fmt (apply 'encode-time f)))))
14354 (when (and org-end-time-was-given
14355 (string-match org-plain-time-of-day-regexp txt))
14356 (setq txt (concat (substring txt 0 (match-end 0)) "-"
14357 org-end-time-was-given
14358 (substring txt (match-end 0)))))
8bfe682a
CD
14359 (when org-read-date-analyze-futurep
14360 (setq txt (concat txt " (=>F)")))
20908596 14361 (setq org-read-date-overlay
86fbb8ca 14362 (make-overlay (1- (point-at-eol)) (point-at-eol)))
20908596 14363 (org-overlay-display org-read-date-overlay txt 'secondary-selection))))
d3f4dbe8 14364
20908596 14365(defun org-read-date-analyze (ans def defdecode)
86fbb8ca 14366 "Analyze the combined answer of the date prompt."
20908596 14367 ;; FIXME: cleanup and comment
ed21c5c8
CD
14368 (let ((nowdecode (decode-time (current-time)))
14369 delta deltan deltaw deltadef year month day
14370 hour minute second wday pm h2 m2 tl wday1
14371 iso-year iso-weekday iso-week iso-year iso-date futurep kill-year)
8bfe682a 14372 (setq org-read-date-analyze-futurep nil)
b349f79f
CD
14373 (when (string-match "\\`[ \t]*\\.[ \t]*\\'" ans)
14374 (setq ans "+0"))
14375
20908596
CD
14376 (when (setq delta (org-read-date-get-relative ans (current-time) def))
14377 (setq ans (replace-match "" t t ans)
14378 deltan (car delta)
14379 deltaw (nth 1 delta)
14380 deltadef (nth 2 delta)))
d3f4dbe8 14381
20908596 14382 ;; Check if there is an iso week date in there
5dec9555 14383 ;; If yes, store the info and postpone interpreting it until the rest
20908596
CD
14384 ;; of the parsing is done
14385 (when (string-match "\\<\\(?:\\([0-9]+\\)-\\)?[wW]\\([0-9]\\{1,2\\}\\)\\(?:-\\([0-6]\\)\\)?\\([ \t]\\|$\\)" ans)
ed21c5c8
CD
14386 (setq iso-year (if (match-end 1)
14387 (org-small-year-to-year
14388 (string-to-number (match-string 1 ans))))
14389 iso-weekday (if (match-end 3)
14390 (string-to-number (match-string 3 ans)))
20908596
CD
14391 iso-week (string-to-number (match-string 2 ans)))
14392 (setq ans (replace-match "" t t ans)))
d3f4dbe8 14393
ed21c5c8 14394 ;; Help matching ISO dates with single digit month or day, like 2006-8-11.
20908596
CD
14395 (when (string-match
14396 "^ *\\(\\([0-9]+\\)-\\)?\\([0-1]?[0-9]\\)-\\([0-3]?[0-9]\\)\\([^-0-9]\\|$\\)" ans)
14397 (setq year (if (match-end 2)
14398 (string-to-number (match-string 2 ans))
ed21c5c8
CD
14399 (progn (setq kill-year t)
14400 (string-to-number (format-time-string "%Y"))))
20908596
CD
14401 month (string-to-number (match-string 3 ans))
14402 day (string-to-number (match-string 4 ans)))
14403 (if (< year 100) (setq year (+ 2000 year)))
14404 (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
14405 t nil ans)))
ed21c5c8
CD
14406 ;; Help matching american dates, like 5/30 or 5/30/7
14407 (when (string-match
86fbb8ca 14408 "^ *\\(0?[1-9]\\|1[012]\\)/\\(0?[1-9]\\|[12][0-9]\\|3[01]\\)\\(/\\([0-9]+\\)\\)?\\([^/0-9]\\|$\\)" ans)
ed21c5c8
CD
14409 (setq year (if (match-end 4)
14410 (string-to-number (match-string 4 ans))
14411 (progn (setq kill-year t)
14412 (string-to-number (format-time-string "%Y"))))
14413 month (string-to-number (match-string 1 ans))
14414 day (string-to-number (match-string 2 ans)))
14415 (if (< year 100) (setq year (+ 2000 year)))
14416 (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
14417 t nil ans)))
20908596
CD
14418 ;; Help matching am/pm times, because `parse-time-string' does not do that.
14419 ;; If there is a time with am/pm, and *no* time without it, we convert
14420 ;; so that matching will be successful.
14421 (loop for i from 1 to 2 do ; twice, for end time as well
14422 (when (and (not (string-match "\\(\\`\\|[^+]\\)[012]?[0-9]:[0-9][0-9]\\([ \t\n]\\|$\\)" ans))
14423 (string-match "\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\(am\\|AM\\|pm\\|PM\\)\\>" ans))
14424 (setq hour (string-to-number (match-string 1 ans))
14425 minute (if (match-end 3)
14426 (string-to-number (match-string 3 ans))
14427 0)
14428 pm (equal ?p
14429 (string-to-char (downcase (match-string 4 ans)))))
14430 (if (and (= hour 12) (not pm))
14431 (setq hour 0)
14432 (if (and pm (< hour 12)) (setq hour (+ 12 hour))))
14433 (setq ans (replace-match (format "%02d:%02d" hour minute)
14434 t t ans))))
d3f4dbe8 14435
20908596
CD
14436 ;; Check if a time range is given as a duration
14437 (when (string-match "\\([012]?[0-9]\\):\\([0-6][0-9]\\)\\+\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?" ans)
14438 (setq hour (string-to-number (match-string 1 ans))
14439 h2 (+ hour (string-to-number (match-string 3 ans)))
14440 minute (string-to-number (match-string 2 ans))
14441 m2 (+ minute (if (match-end 5) (string-to-number
14442 (match-string 5 ans))0)))
14443 (if (>= m2 60) (setq h2 (1+ h2) m2 (- m2 60)))
14444 (setq ans (replace-match (format "%02d:%02d-%02d:%02d" hour minute h2 m2)
14445 t t ans)))
d3f4dbe8 14446
20908596
CD
14447 ;; Check if there is a time range
14448 (when (boundp 'org-end-time-was-given)
14449 (setq org-time-was-given nil)
14450 (when (and (string-match org-plain-time-of-day-regexp ans)
14451 (match-end 8))
14452 (setq org-end-time-was-given (match-string 8 ans))
14453 (setq ans (concat (substring ans 0 (match-beginning 7))
14454 (substring ans (match-end 7))))))
a3fbe8c4 14455
20908596
CD
14456 (setq tl (parse-time-string ans)
14457 day (or (nth 3 tl) (nth 3 defdecode))
14458 month (or (nth 4 tl)
14459 (if (and org-read-date-prefer-future
ed21c5c8
CD
14460 (nth 3 tl) (< (nth 3 tl) (nth 3 nowdecode)))
14461 (prog1 (1+ (nth 4 nowdecode)) (setq futurep t))
20908596 14462 (nth 4 defdecode)))
ed21c5c8 14463 year (or (and (not kill-year) (nth 5 tl))
20908596 14464 (if (and org-read-date-prefer-future
ed21c5c8
CD
14465 (nth 4 tl) (< (nth 4 tl) (nth 4 nowdecode)))
14466 (prog1 (1+ (nth 5 nowdecode)) (setq futurep t))
20908596
CD
14467 (nth 5 defdecode)))
14468 hour (or (nth 2 tl) (nth 2 defdecode))
14469 minute (or (nth 1 tl) (nth 1 defdecode))
14470 second (or (nth 0 tl) 0)
14471 wday (nth 6 tl))
a3fbe8c4 14472
8bfe682a
CD
14473 (when (and (eq org-read-date-prefer-future 'time)
14474 (not (nth 3 tl)) (not (nth 4 tl)) (not (nth 5 tl))
ed21c5c8
CD
14475 (equal day (nth 3 nowdecode))
14476 (equal month (nth 4 nowdecode))
14477 (equal year (nth 5 nowdecode))
8bfe682a 14478 (nth 2 tl)
ed21c5c8
CD
14479 (or (< (nth 2 tl) (nth 2 nowdecode))
14480 (and (= (nth 2 tl) (nth 2 nowdecode))
8bfe682a 14481 (nth 1 tl)
ed21c5c8 14482 (< (nth 1 tl) (nth 1 nowdecode)))))
8bfe682a
CD
14483 (setq day (1+ day)
14484 futurep t))
14485
20908596
CD
14486 ;; Special date definitions below
14487 (cond
14488 (iso-week
14489 ;; There was an iso week
ed21c5c8 14490 (require 'cal-iso)
8bfe682a 14491 (setq futurep nil)
20908596
CD
14492 (setq year (or iso-year year)
14493 day (or iso-weekday wday 1)
14494 wday nil ; to make sure that the trigger below does not match
14495 iso-date (calendar-gregorian-from-absolute
14496 (calendar-absolute-from-iso
14497 (list iso-week day year))))
14498; FIXME: Should we also push ISO weeks into the future?
14499; (when (and org-read-date-prefer-future
14500; (not iso-year)
14501; (< (calendar-absolute-from-gregorian iso-date)
14502; (time-to-days (current-time))))
14503; (setq year (1+ year)
14504; iso-date (calendar-gregorian-from-absolute
14505; (calendar-absolute-from-iso
14506; (list iso-week day year)))))
14507 (setq month (car iso-date)
14508 year (nth 2 iso-date)
14509 day (nth 1 iso-date)))
14510 (deltan
8bfe682a 14511 (setq futurep nil)
20908596
CD
14512 (unless deltadef
14513 (let ((now (decode-time (current-time))))
14514 (setq day (nth 3 now) month (nth 4 now) year (nth 5 now))))
14515 (cond ((member deltaw '("d" "")) (setq day (+ day deltan)))
14516 ((equal deltaw "w") (setq day (+ day (* 7 deltan))))
14517 ((equal deltaw "m") (setq month (+ month deltan)))
14518 ((equal deltaw "y") (setq year (+ year deltan)))))
14519 ((and wday (not (nth 3 tl)))
8bfe682a 14520 (setq futurep nil)
20908596
CD
14521 ;; Weekday was given, but no day, so pick that day in the week
14522 ;; on or after the derived date.
14523 (setq wday1 (nth 6 (decode-time (encode-time 0 0 0 day month year))))
14524 (unless (equal wday wday1)
14525 (setq day (+ day (% (- wday wday1 -7) 7))))))
14526 (if (and (boundp 'org-time-was-given)
14527 (nth 2 tl))
14528 (setq org-time-was-given t))
14529 (if (< year 100) (setq year (+ 2000 year)))
14530 (if (< year 1970) (setq year (nth 5 defdecode))) ; not representable
8bfe682a 14531 (setq org-read-date-analyze-futurep futurep)
20908596 14532 (list second minute hour day month year)))
d3f4dbe8 14533
20908596 14534(defvar parse-time-weekdays)
d3f4dbe8 14535
20908596
CD
14536(defun org-read-date-get-relative (s today default)
14537 "Check string S for special relative date string.
14538TODAY and DEFAULT are internal times, for today and for a default.
14539Return shift list (N what def-flag)
14540WHAT is \"d\", \"w\", \"m\", or \"y\" for day, week, month, year.
14541N is the number of WHATs to shift.
14542DEF-FLAG is t when a double ++ or -- indicates shift relative to
14543 the DEFAULT date rather than TODAY."
7b1019e2
MB
14544 (when (and
14545 (string-match
14546 (concat
14547 "\\`[ \t]*\\([-+]\\{0,2\\}\\)"
14548 "\\([0-9]+\\)?"
14549 "\\([dwmy]\\|\\(" (mapconcat 'car parse-time-weekdays "\\|") "\\)\\)?"
14550 "\\([ \t]\\|$\\)") s)
14551 (or (> (match-end 1) (match-beginning 1)) (match-end 4)))
14552 (let* ((dir (if (> (match-end 1) (match-beginning 1))
20908596
CD
14553 (string-to-char (substring (match-string 1 s) -1))
14554 ?+))
14555 (rel (and (match-end 1) (= 2 (- (match-end 1) (match-beginning 1)))))
14556 (n (if (match-end 2) (string-to-number (match-string 2 s)) 1))
14557 (what (if (match-end 3) (match-string 3 s) "d"))
14558 (wday1 (cdr (assoc (downcase what) parse-time-weekdays)))
14559 (date (if rel default today))
14560 (wday (nth 6 (decode-time date)))
14561 delta)
14562 (if wday1
14563 (progn
14564 (setq delta (mod (+ 7 (- wday1 wday)) 7))
14565 (if (= dir ?-) (setq delta (- delta 7)))
14566 (if (> n 1) (setq delta (+ delta (* (1- n) (if (= dir ?-) -7 7)))))
14567 (list delta "d" rel))
14568 (list (* n (if (= dir ?-) -1 1)) what rel)))))
d3f4dbe8 14569
ed21c5c8
CD
14570(defun org-order-calendar-date-args (arg1 arg2 arg3)
14571 "Turn a user-specified date into the internal representation.
14572The internal representation needed by the calendar is (month day year).
14573This is a wrapper to handle the brain-dead convention in calendar that
14574user function argument order change dependent on argument order."
14575 (if (boundp 'calendar-date-style)
14576 (cond
14577 ((eq calendar-date-style 'american)
14578 (list arg1 arg2 arg3))
14579 ((eq calendar-date-style 'european)
14580 (list arg2 arg1 arg3))
14581 ((eq calendar-date-style 'iso)
14582 (list arg2 arg3 arg1)))
afe98dfa
CD
14583 (with-no-warnings ;; european-calendar-style is obsolete as of version 23.1
14584 (if (org-bound-and-true-p european-calendar-style)
14585 (list arg2 arg1 arg3)
14586 (list arg1 arg2 arg3)))))
ed21c5c8 14587
20908596
CD
14588(defun org-eval-in-calendar (form &optional keepdate)
14589 "Eval FORM in the calendar window and return to current window.
14590Also, store the cursor date in variable org-ans2."
c8d0cf5c
CD
14591 (let ((sf (selected-frame))
14592 (sw (selected-window)))
14593 (select-window (get-buffer-window "*Calendar*" t))
20908596
CD
14594 (eval form)
14595 (when (and (not keepdate) (calendar-cursor-to-date))
14596 (let* ((date (calendar-cursor-to-date))
14597 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
14598 (setq org-ans2 (format-time-string "%Y-%m-%d" time))))
86fbb8ca 14599 (move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer))
c8d0cf5c 14600 (select-window sw)
54a0dee5 14601 (org-select-frame-set-input-focus sf)))
d3f4dbe8 14602
20908596
CD
14603(defun org-calendar-select ()
14604 "Return to `org-read-date' with the date currently selected.
14605This is used by `org-read-date' in a temporary keymap for the calendar buffer."
d3f4dbe8 14606 (interactive)
20908596
CD
14607 (when (calendar-cursor-to-date)
14608 (let* ((date (calendar-cursor-to-date))
14609 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
14610 (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
14611 (if (active-minibuffer-window) (exit-minibuffer))))
14612
14613(defun org-insert-time-stamp (time &optional with-hm inactive pre post extra)
14614 "Insert a date stamp for the date given by the internal TIME.
ed21c5c8 14615WITH-HM means use the stamp format that includes the time of the day.
20908596
CD
14616INACTIVE means use square brackets instead of angular ones, so that the
14617stamp will not contribute to the agenda.
14618PRE and POST are optional strings to be inserted before and after the
14619stamp.
14620The command returns the inserted time stamp."
14621 (let ((fmt (funcall (if with-hm 'cdr 'car) org-time-stamp-formats))
14622 stamp)
14623 (if inactive (setq fmt (concat "[" (substring fmt 1 -1) "]")))
14624 (insert-before-markers (or pre ""))
20908596
CD
14625 (when (listp extra)
14626 (setq extra (car extra))
14627 (if (and (stringp extra)
14628 (string-match "\\([0-9]+\\):\\([0-9]+\\)" extra))
14629 (setq extra (format "-%02d:%02d"
14630 (string-to-number (match-string 1 extra))
14631 (string-to-number (match-string 2 extra))))
14632 (setq extra nil)))
14633 (when extra
afe98dfa
CD
14634 (setq fmt (concat (substring fmt 0 -1) extra (substring fmt -1))))
14635 (insert-before-markers (setq stamp (format-time-string fmt time)))
20908596 14636 (insert-before-markers (or post ""))
b349f79f 14637 (setq org-last-inserted-timestamp stamp)))
d3f4dbe8 14638
20908596
CD
14639(defun org-toggle-time-stamp-overlays ()
14640 "Toggle the use of custom time stamp formats."
d3f4dbe8 14641 (interactive)
20908596
CD
14642 (setq org-display-custom-times (not org-display-custom-times))
14643 (unless org-display-custom-times
14644 (let ((p (point-min)) (bmp (buffer-modified-p)))
14645 (while (setq p (next-single-property-change p 'display))
14646 (if (and (get-text-property p 'display)
14647 (eq (get-text-property p 'face) 'org-date))
14648 (remove-text-properties
14649 p (setq p (next-single-property-change p 'display))
14650 '(display t))))
14651 (set-buffer-modified-p bmp)))
14652 (if (featurep 'xemacs)
14653 (remove-text-properties (point-min) (point-max) '(end-glyph t)))
14654 (org-restart-font-lock)
14655 (setq org-table-may-need-update t)
14656 (if org-display-custom-times
14657 (message "Time stamps are overlayed with custom format")
14658 (message "Time stamp overlays removed")))
d3f4dbe8 14659
20908596 14660(defun org-display-custom-time (beg end)
b349f79f 14661 "Overlay modified time stamp format over timestamp between BEG and END."
20908596
CD
14662 (let* ((ts (buffer-substring beg end))
14663 t1 w1 with-hm tf time str w2 (off 0))
14664 (save-match-data
14665 (setq t1 (org-parse-time-string ts t))
8bfe682a 14666 (if (string-match "\\(-[0-9]+:[0-9]+\\)?\\( [.+]?\\+[0-9]+[dwmy]\\(/[0-9]+[dwmy]\\)?\\)?\\'" ts)
20908596
CD
14667 (setq off (- (match-end 0) (match-beginning 0)))))
14668 (setq end (- end off))
14669 (setq w1 (- end beg)
14670 with-hm (and (nth 1 t1) (nth 2 t1))
14671 tf (funcall (if with-hm 'cdr 'car) org-time-stamp-custom-formats)
14672 time (org-fix-decoded-time t1)
14673 str (org-add-props
14674 (format-time-string
14675 (substring tf 1 -1) (apply 'encode-time time))
14676 nil 'mouse-face 'highlight)
14677 w2 (length str))
14678 (if (not (= w2 w1))
14679 (add-text-properties (1+ beg) (+ 2 beg)
14680 (list 'org-dwidth t 'org-dwidth-n (- w1 w2))))
14681 (if (featurep 'xemacs)
14682 (progn
14683 (put-text-property beg end 'invisible t)
14684 (put-text-property beg end 'end-glyph (make-glyph str)))
14685 (put-text-property beg end 'display str))))
d3f4dbe8 14686
20908596
CD
14687(defun org-translate-time (string)
14688 "Translate all timestamps in STRING to custom format.
14689But do this only if the variable `org-display-custom-times' is set."
14690 (when org-display-custom-times
14691 (save-match-data
14692 (let* ((start 0)
14693 (re org-ts-regexp-both)
14694 t1 with-hm inactive tf time str beg end)
14695 (while (setq start (string-match re string start))
14696 (setq beg (match-beginning 0)
14697 end (match-end 0)
14698 t1 (save-match-data
14699 (org-parse-time-string (substring string beg end) t))
14700 with-hm (and (nth 1 t1) (nth 2 t1))
14701 inactive (equal (substring string beg (1+ beg)) "[")
14702 tf (funcall (if with-hm 'cdr 'car)
14703 org-time-stamp-custom-formats)
14704 time (org-fix-decoded-time t1)
14705 str (format-time-string
14706 (concat
14707 (if inactive "[" "<") (substring tf 1 -1)
14708 (if inactive "]" ">"))
14709 (apply 'encode-time time))
14710 string (replace-match str t t string)
14711 start (+ start (length str)))))))
14712 string)
d3f4dbe8 14713
20908596
CD
14714(defun org-fix-decoded-time (time)
14715 "Set 0 instead of nil for the first 6 elements of time.
14716Don't touch the rest."
14717 (let ((n 0))
14718 (mapcar (lambda (x) (if (< (setq n (1+ n)) 7) (or x 0) x)) time)))
d3f4dbe8 14719
20908596
CD
14720(defun org-days-to-time (timestamp-string)
14721 "Difference between TIMESTAMP-STRING and now in days."
14722 (- (time-to-days (org-time-string-to-time timestamp-string))
14723 (time-to-days (current-time))))
d3f4dbe8 14724
20908596
CD
14725(defun org-deadline-close (timestamp-string &optional ndays)
14726 "Is the time in TIMESTAMP-STRING close to the current date?"
14727 (setq ndays (or ndays (org-get-wdays timestamp-string)))
14728 (and (< (org-days-to-time timestamp-string) ndays)
14729 (not (org-entry-is-done-p))))
d3f4dbe8 14730
20908596
CD
14731(defun org-get-wdays (ts)
14732 "Get the deadline lead time appropriate for timestring TS."
14733 (cond
14734 ((<= org-deadline-warning-days 0)
14735 ;; 0 or negative, enforce this value no matter what
14736 (- org-deadline-warning-days))
c8d0cf5c 14737 ((string-match "-\\([0-9]+\\)\\([dwmy]\\)\\(\\'\\|>\\| \\)" ts)
20908596
CD
14738 ;; lead time is specified.
14739 (floor (* (string-to-number (match-string 1 ts))
14740 (cdr (assoc (match-string 2 ts)
14741 '(("d" . 1) ("w" . 7)
14742 ("m" . 30.4) ("y" . 365.25)))))))
14743 ;; go for the default.
14744 (t org-deadline-warning-days)))
d3f4dbe8 14745
20908596
CD
14746(defun org-calendar-select-mouse (ev)
14747 "Return to `org-read-date' with the date currently selected.
14748This is used by `org-read-date' in a temporary keymap for the calendar buffer."
14749 (interactive "e")
14750 (mouse-set-point ev)
14751 (when (calendar-cursor-to-date)
14752 (let* ((date (calendar-cursor-to-date))
14753 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
14754 (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
14755 (if (active-minibuffer-window) (exit-minibuffer))))
d3f4dbe8 14756
20908596
CD
14757(defun org-check-deadlines (ndays)
14758 "Check if there are any deadlines due or past due.
14759A deadline is considered due if it happens within `org-deadline-warning-days'
14760days from today's date. If the deadline appears in an entry marked DONE,
14761it is not shown. The prefix arg NDAYS can be used to test that many
14762days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are shown."
d3f4dbe8 14763 (interactive "P")
20908596
CD
14764 (let* ((org-warn-days
14765 (cond
14766 ((equal ndays '(4)) 100000)
14767 (ndays (prefix-numeric-value ndays))
14768 (t (abs org-deadline-warning-days))))
14769 (case-fold-search nil)
14770 (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>"))
14771 (callback
14772 (lambda () (org-deadline-close (match-string 1) org-warn-days))))
d3f4dbe8 14773
20908596
CD
14774 (message "%d deadlines past-due or due within %d days"
14775 (org-occur regexp nil callback)
14776 org-warn-days)))
d3f4dbe8 14777
20908596
CD
14778(defun org-check-before-date (date)
14779 "Check if there are deadlines or scheduled entries before DATE."
14780 (interactive (list (org-read-date)))
14781 (let ((case-fold-search nil)
14782 (regexp (concat "\\<\\(" org-deadline-string
14783 "\\|" org-scheduled-string
14784 "\\) *<\\([^>]+\\)>"))
14785 (callback
14786 (lambda () (time-less-p
14787 (org-time-string-to-time (match-string 2))
14788 (org-time-string-to-time date)))))
14789 (message "%d entries before %s"
14790 (org-occur regexp nil callback) date)))
100a4141 14791
c8d0cf5c
CD
14792(defun org-check-after-date (date)
14793 "Check if there are deadlines or scheduled entries after DATE."
14794 (interactive (list (org-read-date)))
14795 (let ((case-fold-search nil)
14796 (regexp (concat "\\<\\(" org-deadline-string
14797 "\\|" org-scheduled-string
14798 "\\) *<\\([^>]+\\)>"))
14799 (callback
14800 (lambda () (not
14801 (time-less-p
14802 (org-time-string-to-time (match-string 2))
14803 (org-time-string-to-time date))))))
14804 (message "%d entries after %s"
14805 (org-occur regexp nil callback) date)))
14806
20908596
CD
14807(defun org-evaluate-time-range (&optional to-buffer)
14808 "Evaluate a time range by computing the difference between start and end.
14809Normally the result is just printed in the echo area, but with prefix arg
14810TO-BUFFER, the result is inserted just after the date stamp into the buffer.
14811If the time range is actually in a table, the result is inserted into the
14812next column.
14813For time difference computation, a year is assumed to be exactly 365
14814days in order to avoid rounding problems."
d3f4dbe8 14815 (interactive "P")
20908596
CD
14816 (or
14817 (org-clock-update-time-maybe)
14818 (save-excursion
14819 (unless (org-at-date-range-p t)
14820 (goto-char (point-at-bol))
14821 (re-search-forward org-tr-regexp-both (point-at-eol) t))
14822 (if (not (org-at-date-range-p t))
14823 (error "Not at a time-stamp range, and none found in current line")))
14824 (let* ((ts1 (match-string 1))
14825 (ts2 (match-string 2))
14826 (havetime (or (> (length ts1) 15) (> (length ts2) 15)))
14827 (match-end (match-end 0))
14828 (time1 (org-time-string-to-time ts1))
14829 (time2 (org-time-string-to-time ts2))
54a0dee5
CD
14830 (t1 (org-float-time time1))
14831 (t2 (org-float-time time2))
20908596
CD
14832 (diff (abs (- t2 t1)))
14833 (negative (< (- t2 t1) 0))
14834 ;; (ys (floor (* 365 24 60 60)))
14835 (ds (* 24 60 60))
14836 (hs (* 60 60))
14837 (fy "%dy %dd %02d:%02d")
14838 (fy1 "%dy %dd")
14839 (fd "%dd %02d:%02d")
14840 (fd1 "%dd")
14841 (fh "%02d:%02d")
14842 y d h m align)
14843 (if havetime
14844 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
14845 y 0
14846 d (floor (/ diff ds)) diff (mod diff ds)
14847 h (floor (/ diff hs)) diff (mod diff hs)
14848 m (floor (/ diff 60)))
14849 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
14850 y 0
14851 d (floor (+ (/ diff ds) 0.5))
14852 h 0 m 0))
14853 (if (not to-buffer)
14854 (message "%s" (org-make-tdiff-string y d h m))
14855 (if (org-at-table-p)
14856 (progn
14857 (goto-char match-end)
14858 (setq align t)
14859 (and (looking-at " *|") (goto-char (match-end 0))))
14860 (goto-char match-end))
14861 (if (looking-at
14862 "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]")
14863 (replace-match ""))
14864 (if negative (insert " -"))
14865 (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m))
14866 (if (> d 0) (insert " " (format (if havetime fd fd1) d h m))
14867 (insert " " (format fh h m))))
14868 (if align (org-table-align))
14869 (message "Time difference inserted")))))
791d856f 14870
20908596
CD
14871(defun org-make-tdiff-string (y d h m)
14872 (let ((fmt "")
14873 (l nil))
14874 (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ")
14875 l (push y l)))
14876 (if (> d 0) (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ")
14877 l (push d l)))
14878 (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ")
14879 l (push h l)))
14880 (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ")
14881 l (push m l)))
14882 (apply 'format fmt (nreverse l))))
ab27a4a0 14883
20908596
CD
14884(defun org-time-string-to-time (s)
14885 (apply 'encode-time (org-parse-time-string s)))
c8d0cf5c 14886(defun org-time-string-to-seconds (s)
54a0dee5 14887 (org-float-time (org-time-string-to-time s)))
791d856f 14888
20908596
CD
14889(defun org-time-string-to-absolute (s &optional daynr prefer show-all)
14890 "Convert a time stamp to an absolute day number.
86fbb8ca 14891If there is a specifier for a cyclic time stamp, get the closest date to
20908596 14892DAYNR.
c8d0cf5c
CD
14893PREFER and SHOW-ALL are passed through to `org-closest-date'.
14894the variable date is bound by the calendar when this is called."
20908596
CD
14895 (cond
14896 ((and daynr (string-match "\\`%%\\((.*)\\)" s))
14897 (if (org-diary-sexp-entry (match-string 1 s) "" date)
14898 daynr
14899 (+ daynr 1000)))
14900 ((and daynr (string-match "\\+[0-9]+[dwmy]" s))
14901 (org-closest-date s (if (and (boundp 'daynr) (integerp daynr)) daynr
14902 (time-to-days (current-time))) (match-string 0 s)
14903 prefer show-all))
14904 (t (time-to-days (apply 'encode-time (org-parse-time-string s))))))
791d856f 14905
20908596
CD
14906(defun org-days-to-iso-week (days)
14907 "Return the iso week number."
14908 (require 'cal-iso)
14909 (car (calendar-iso-from-absolute days)))
14910
14911(defun org-small-year-to-year (year)
14912 "Convert 2-digit years into 4-digit years.
1491338-99 are mapped into 1938-1999. 1-37 are mapped into 2001-2007.
d60b1ba1
CD
14914The year 2000 cannot be abbreviated. Any year larger than 99
14915is returned unchanged."
20908596
CD
14916 (if (< year 38)
14917 (setq year (+ 2000 year))
14918 (if (< year 100)
14919 (setq year (+ 1900 year))))
14920 year)
791d856f 14921
20908596
CD
14922(defun org-time-from-absolute (d)
14923 "Return the time corresponding to date D.
14924D may be an absolute day number, or a calendar-type list (month day year)."
14925 (if (numberp d) (setq d (calendar-gregorian-from-absolute d)))
14926 (encode-time 0 0 0 (nth 1 d) (car d) (nth 2 d)))
d3f4dbe8 14927
20908596
CD
14928(defun org-calendar-holiday ()
14929 "List of holidays, for Diary display in Org-mode."
14930 (require 'holidays)
14931 (let ((hl (funcall
14932 (if (fboundp 'calendar-check-holidays)
14933 'calendar-check-holidays 'check-calendar-holidays) date)))
14934 (if hl (mapconcat 'identity hl "; "))))
d3f4dbe8 14935
20908596
CD
14936(defun org-diary-sexp-entry (sexp entry date)
14937 "Process a SEXP diary ENTRY for DATE."
14938 (require 'diary-lib)
14939 (let ((result (if calendar-debug-sexp
14940 (let ((stack-trace-on-error t))
14941 (eval (car (read-from-string sexp))))
14942 (condition-case nil
14943 (eval (car (read-from-string sexp)))
14944 (error
14945 (beep)
14946 (message "Bad sexp at line %d in %s: %s"
14947 (org-current-line)
14948 (buffer-file-name) sexp)
14949 (sleep-for 2))))))
acedf35c 14950 (cond ((stringp result) (split-string result "; "))
20908596 14951 ((and (consp result)
afe98dfa 14952 (not (consp (cdr result)))
20908596 14953 (stringp (cdr result))) (cdr result))
afe98dfa
CD
14954 ((and (consp result)
14955 (stringp (car result))) result)
20908596
CD
14956 (result entry)
14957 (t nil))))
d3f4dbe8 14958
20908596
CD
14959(defun org-diary-to-ical-string (frombuf)
14960 "Get iCalendar entries from diary entries in buffer FROMBUF.
14961This uses the icalendar.el library."
14962 (let* ((tmpdir (if (featurep 'xemacs)
14963 (temp-directory)
14964 temporary-file-directory))
14965 (tmpfile (make-temp-name
14966 (expand-file-name "orgics" tmpdir)))
14967 buf rtn b e)
81ad75af 14968 (with-current-buffer frombuf
20908596
CD
14969 (icalendar-export-region (point-min) (point-max) tmpfile)
14970 (setq buf (find-buffer-visiting tmpfile))
14971 (set-buffer buf)
14972 (goto-char (point-min))
14973 (if (re-search-forward "^BEGIN:VEVENT" nil t)
14974 (setq b (match-beginning 0)))
14975 (goto-char (point-max))
14976 (if (re-search-backward "^END:VEVENT" nil t)
14977 (setq e (match-end 0)))
14978 (setq rtn (if (and b e) (concat (buffer-substring b e) "\n") "")))
14979 (kill-buffer buf)
20908596
CD
14980 (delete-file tmpfile)
14981 rtn))
d3f4dbe8 14982
20908596
CD
14983(defun org-closest-date (start current change prefer show-all)
14984 "Find the date closest to CURRENT that is consistent with START and CHANGE.
14985When PREFER is `past' return a date that is either CURRENT or past.
14986When PREFER is `future', return a date that is either CURRENT or future.
33306645 14987When SHOW-ALL is nil, only return the current occurrence of a time stamp."
20908596 14988 ;; Make the proper lists from the dates
d3f4dbe8 14989 (catch 'exit
20908596 14990 (let ((a1 '(("d" . day) ("w" . week) ("m" . month) ("y" . year)))
0bd48b37 14991 dn dw sday cday n1 n2 n0
20908596 14992 d m y y1 y2 date1 date2 nmonths nm ny m2)
d3f4dbe8 14993
20908596
CD
14994 (setq start (org-date-to-gregorian start)
14995 current (org-date-to-gregorian
14996 (if show-all
14997 current
14998 (time-to-days (current-time))))
14999 sday (calendar-absolute-from-gregorian start)
15000 cday (calendar-absolute-from-gregorian current))
d3f4dbe8 15001
20908596 15002 (if (<= cday sday) (throw 'exit sday))
791d856f 15003
20908596
CD
15004 (if (string-match "\\(\\+[0-9]+\\)\\([dwmy]\\)" change)
15005 (setq dn (string-to-number (match-string 1 change))
15006 dw (cdr (assoc (match-string 2 change) a1)))
86fbb8ca 15007 (error "Invalid change specifier: %s" change))
20908596
CD
15008 (if (eq dw 'week) (setq dw 'day dn (* 7 dn)))
15009 (cond
15010 ((eq dw 'day)
15011 (setq n1 (+ sday (* dn (floor (/ (- cday sday) dn))))
15012 n2 (+ n1 dn)))
15013 ((eq dw 'year)
15014 (setq d (nth 1 start) m (car start) y1 (nth 2 start) y2 (nth 2 current))
15015 (setq y1 (+ (* (floor (/ (- y2 y1) dn)) dn) y1))
15016 (setq date1 (list m d y1)
15017 n1 (calendar-absolute-from-gregorian date1)
15018 date2 (list m d (+ y1 (* (if (< n1 cday) 1 -1) dn)))
15019 n2 (calendar-absolute-from-gregorian date2)))
15020 ((eq dw 'month)
2c3ad40d 15021 ;; approx number of month between the two dates
20908596
CD
15022 (setq nmonths (floor (/ (- cday sday) 30.436875)))
15023 ;; How often does dn fit in there?
15024 (setq d (nth 1 start) m (car start) y (nth 2 start)
15025 nm (* dn (max 0 (1- (floor (/ nmonths dn)))))
15026 m (+ m nm)
15027 ny (floor (/ m 12))
15028 y (+ y ny)
15029 m (- m (* ny 12)))
15030 (while (> m 12) (setq m (- m 12) y (1+ y)))
15031 (setq n1 (calendar-absolute-from-gregorian (list m d y)))
15032 (setq m2 (+ m dn) y2 y)
15033 (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
15034 (setq n2 (calendar-absolute-from-gregorian (list m2 d y2)))
2c3ad40d 15035 (while (<= n2 cday)
20908596
CD
15036 (setq n1 n2 m m2 y y2)
15037 (setq m2 (+ m dn) y2 y)
15038 (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
15039 (setq n2 (calendar-absolute-from-gregorian (list m2 d y2))))))
0bd48b37
CD
15040 ;; Make sure n1 is the earlier date
15041 (setq n0 n1 n1 (min n1 n2) n2 (max n0 n2))
20908596
CD
15042 (if show-all
15043 (cond
8d642074 15044 ((eq prefer 'past) (if (= cday n2) n2 n1))
20908596
CD
15045 ((eq prefer 'future) (if (= cday n1) n1 n2))
15046 (t (if (> (abs (- cday n1)) (abs (- cday n2))) n2 n1)))
15047 (cond
8d642074 15048 ((eq prefer 'past) (if (= cday n2) n2 n1))
20908596
CD
15049 ((eq prefer 'future) (if (= cday n1) n1 n2))
15050 (t (if (= cday n1) n1 n2)))))))
791d856f 15051
20908596 15052(defun org-date-to-gregorian (date)
86fbb8ca 15053 "Turn any specification of DATE into a Gregorian date for the calendar."
20908596
CD
15054 (cond ((integerp date) (calendar-gregorian-from-absolute date))
15055 ((and (listp date) (= (length date) 3)) date)
15056 ((stringp date)
15057 (setq date (org-parse-time-string date))
15058 (list (nth 4 date) (nth 3 date) (nth 5 date)))
15059 ((listp date)
15060 (list (nth 4 date) (nth 3 date) (nth 5 date)))))
d3f4dbe8 15061
20908596
CD
15062(defun org-parse-time-string (s &optional nodefault)
15063 "Parse the standard Org-mode time string.
15064This should be a lot faster than the normal `parse-time-string'.
15065If time is not given, defaults to 0:00. However, with optional NODEFAULT,
15066hour and minute fields will be nil if not given."
15067 (if (string-match org-ts-regexp0 s)
15068 (list 0
15069 (if (or (match-beginning 8) (not nodefault))
15070 (string-to-number (or (match-string 8 s) "0")))
15071 (if (or (match-beginning 7) (not nodefault))
15072 (string-to-number (or (match-string 7 s) "0")))
15073 (string-to-number (match-string 4 s))
15074 (string-to-number (match-string 3 s))
15075 (string-to-number (match-string 2 s))
15076 nil nil nil)
54a0dee5 15077 (error "Not a standard Org-mode time string: %s" s)))
d3f4dbe8 15078
20908596
CD
15079(defun org-timestamp-up (&optional arg)
15080 "Increase the date item at the cursor by one.
15081If the cursor is on the year, change the year. If it is on the month or
15082the day, change that.
15083With prefix ARG, change by that many units."
15084 (interactive "p")
86fbb8ca 15085 (org-timestamp-change (prefix-numeric-value arg) nil 'updown))
d3f4dbe8 15086
20908596
CD
15087(defun org-timestamp-down (&optional arg)
15088 "Decrease the date item at the cursor by one.
15089If the cursor is on the year, change the year. If it is on the month or
15090the day, change that.
15091With prefix ARG, change by that many units."
15092 (interactive "p")
86fbb8ca 15093 (org-timestamp-change (- (prefix-numeric-value arg)) nil 'updown))
d3f4dbe8 15094
20908596
CD
15095(defun org-timestamp-up-day (&optional arg)
15096 "Increase the date in the time stamp by one day.
15097With prefix ARG, change that many days."
15098 (interactive "p")
15099 (if (and (not (org-at-timestamp-p t))
15100 (org-on-heading-p))
15101 (org-todo 'up)
86fbb8ca 15102 (org-timestamp-change (prefix-numeric-value arg) 'day 'updown)))
d3f4dbe8 15103
20908596
CD
15104(defun org-timestamp-down-day (&optional arg)
15105 "Decrease the date in the time stamp by one day.
15106With prefix ARG, change that many days."
15107 (interactive "p")
15108 (if (and (not (org-at-timestamp-p t))
15109 (org-on-heading-p))
15110 (org-todo 'down)
86fbb8ca 15111 (org-timestamp-change (- (prefix-numeric-value arg)) 'day) 'updown))
d3f4dbe8 15112
20908596
CD
15113(defun org-at-timestamp-p (&optional inactive-ok)
15114 "Determine if the cursor is in or at a timestamp."
15115 (interactive)
15116 (let* ((tsr (if inactive-ok org-ts-regexp3 org-ts-regexp2))
15117 (pos (point))
15118 (ans (or (looking-at tsr)
15119 (save-excursion
15120 (skip-chars-backward "^[<\n\r\t")
15121 (if (> (point) (point-min)) (backward-char 1))
15122 (and (looking-at tsr)
15123 (> (- (match-end 0) pos) -1))))))
15124 (and ans
15125 (boundp 'org-ts-what)
15126 (setq org-ts-what
15127 (cond
15128 ((= pos (match-beginning 0)) 'bracket)
15129 ((= pos (1- (match-end 0))) 'bracket)
15130 ((org-pos-in-match-range pos 2) 'year)
15131 ((org-pos-in-match-range pos 3) 'month)
15132 ((org-pos-in-match-range pos 7) 'hour)
15133 ((org-pos-in-match-range pos 8) 'minute)
15134 ((or (org-pos-in-match-range pos 4)
15135 (org-pos-in-match-range pos 5)) 'day)
15136 ((and (> pos (or (match-end 8) (match-end 5)))
15137 (< pos (match-end 0)))
15138 (- pos (or (match-end 8) (match-end 5))))
15139 (t 'day))))
15140 ans))
a3fbe8c4 15141
20908596
CD
15142(defun org-toggle-timestamp-type ()
15143 "Toggle the type (<active> or [inactive]) of a time stamp."
15144 (interactive)
15145 (when (org-at-timestamp-p t)
93b62de8
CD
15146 (let ((beg (match-beginning 0)) (end (match-end 0))
15147 (map '((?\[ . "<") (?\] . ">") (?< . "[") (?> . "]"))))
15148 (save-excursion
15149 (goto-char beg)
15150 (while (re-search-forward "[][<>]" end t)
15151 (replace-match (cdr (assoc (char-after (match-beginning 0)) map))
15152 t t)))
15153 (message "Timestamp is now %sactive"
15154 (if (equal (char-after beg) ?<) "" "in")))))
a3fbe8c4 15155
86fbb8ca 15156(defun org-timestamp-change (n &optional what updown)
20908596
CD
15157 "Change the date in the time stamp at point.
15158The date will be changed by N times WHAT. WHAT can be `day', `month',
15159`year', `minute', `second'. If WHAT is not given, the cursor position
15160in the timestamp determines what will be changed."
15161 (let ((pos (point))
15162 with-hm inactive
15163 (dm (max (nth 1 org-time-stamp-rounding-minutes) 1))
15164 org-ts-what
15165 extra rem
15166 ts time time0)
15167 (if (not (org-at-timestamp-p t))
15168 (error "Not at a timestamp"))
15169 (if (and (not what) (eq org-ts-what 'bracket))
15170 (org-toggle-timestamp-type)
15171 (if (and (not what) (not (eq org-ts-what 'day))
15172 org-display-custom-times
15173 (get-text-property (point) 'display)
15174 (not (get-text-property (1- (point)) 'display)))
15175 (setq org-ts-what 'day))
15176 (setq org-ts-what (or what org-ts-what)
15177 inactive (= (char-after (match-beginning 0)) ?\[)
15178 ts (match-string 0))
15179 (replace-match "")
15180 (if (string-match
8bfe682a 15181 "\\(\\(-[012][0-9]:[0-5][0-9]\\)?\\( +[.+]?[-+][0-9]+[dwmy]\\(/[0-9]+[dwmy]\\)?\\)*\\)[]>]"
20908596
CD
15182 ts)
15183 (setq extra (match-string 1 ts)))
15184 (if (string-match "^.\\{10\\}.*?[0-9]+:[0-9][0-9]" ts)
15185 (setq with-hm t))
15186 (setq time0 (org-parse-time-string ts))
86fbb8ca
CD
15187 (when (and updown
15188 (eq org-ts-what 'minute)
15189 (not current-prefix-arg))
15190 ;; This looks like s-up and s-down. Change by one rounding step.
20908596
CD
15191 (setq n (* dm (cond ((> n 0) 1) ((< n 0) -1) (t 0))))
15192 (when (not (= 0 (setq rem (% (nth 1 time0) dm))))
15193 (setcar (cdr time0) (+ (nth 1 time0)
15194 (if (> n 0) (- rem) (- dm rem))))))
15195 (setq time
15196 (encode-time (or (car time0) 0)
15197 (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0))
15198 (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0))
15199 (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0))
15200 (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0))
15201 (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0))
15202 (nthcdr 6 time0)))
c8d0cf5c
CD
15203 (when (and (member org-ts-what '(hour minute))
15204 extra
15205 (string-match "-\\([012][0-9]\\):\\([0-5][0-9]\\)" extra))
15206 (setq extra (org-modify-ts-extra
15207 extra
15208 (if (eq org-ts-what 'hour) 2 5)
15209 n dm)))
20908596
CD
15210 (when (integerp org-ts-what)
15211 (setq extra (org-modify-ts-extra extra org-ts-what n dm)))
15212 (if (eq what 'calendar)
15213 (let ((cal-date (org-get-date-from-calendar)))
15214 (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month
15215 (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day
15216 (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year
15217 (setcar time0 (or (car time0) 0))
15218 (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
15219 (setcar (nthcdr 2 time0) (or (nth 2 time0) 0))
15220 (setq time (apply 'encode-time time0))))
15221 (setq org-last-changed-timestamp
15222 (org-insert-time-stamp time with-hm inactive nil nil extra))
15223 (org-clock-update-time-maybe)
15224 (goto-char pos)
15225 ;; Try to recenter the calendar window, if any
15226 (if (and org-calendar-follow-timestamp-change
15227 (get-buffer-window "*Calendar*" t)
15228 (memq org-ts-what '(day month year)))
15229 (org-recenter-calendar (time-to-days time))))))
4b3a9ba7 15230
20908596
CD
15231(defun org-modify-ts-extra (s pos n dm)
15232 "Change the different parts of the lead-time and repeat fields in timestamp."
15233 (let ((idx '(("d" . 0) ("w" . 1) ("m" . 2) ("y" . 3) ("d" . -1) ("y" . 4)))
15234 ng h m new rem)
15235 (when (string-match "\\(-\\([012][0-9]\\):\\([0-5][0-9]\\)\\)?\\( +\\+\\([0-9]+\\)\\([dmwy]\\)\\)?\\( +-\\([0-9]+\\)\\([dmwy]\\)\\)?" s)
891f4676 15236 (cond
20908596
CD
15237 ((or (org-pos-in-match-range pos 2)
15238 (org-pos-in-match-range pos 3))
15239 (setq m (string-to-number (match-string 3 s))
15240 h (string-to-number (match-string 2 s)))
15241 (if (org-pos-in-match-range pos 2)
15242 (setq h (+ h n))
15243 (setq n (* dm (org-no-warnings (signum n))))
15244 (when (not (= 0 (setq rem (% m dm))))
15245 (setq m (+ m (if (> n 0) (- rem) (- dm rem)))))
15246 (setq m (+ m n)))
15247 (if (< m 0) (setq m (+ m 60) h (1- h)))
15248 (if (> m 59) (setq m (- m 60) h (1+ h)))
15249 (setq h (min 24 (max 0 h)))
15250 (setq ng 1 new (format "-%02d:%02d" h m)))
15251 ((org-pos-in-match-range pos 6)
15252 (setq ng 6 new (car (rassoc (+ n (cdr (assoc (match-string 6 s) idx))) idx))))
15253 ((org-pos-in-match-range pos 5)
15254 (setq ng 5 new (format "%d" (max 1 (+ n (string-to-number (match-string 5 s)))))))
891f4676 15255
20908596
CD
15256 ((org-pos-in-match-range pos 9)
15257 (setq ng 9 new (car (rassoc (+ n (cdr (assoc (match-string 9 s) idx))) idx))))
15258 ((org-pos-in-match-range pos 8)
15259 (setq ng 8 new (format "%d" (max 0 (+ n (string-to-number (match-string 8 s))))))))
a3fbe8c4 15260
20908596
CD
15261 (when ng
15262 (setq s (concat
15263 (substring s 0 (match-beginning ng))
15264 new
15265 (substring s (match-end ng))))))
15266 s))
6769c0dc 15267
20908596
CD
15268(defun org-recenter-calendar (date)
15269 "If the calendar is visible, recenter it to DATE."
15270 (let* ((win (selected-window))
15271 (cwin (get-buffer-window "*Calendar*" t))
15272 (calendar-move-hook nil))
15273 (when cwin
15274 (select-window cwin)
15275 (calendar-goto-date (if (listp date) date
15276 (calendar-gregorian-from-absolute date)))
15277 (select-window win))))
2a57416f 15278
20908596
CD
15279(defun org-goto-calendar (&optional arg)
15280 "Go to the Emacs calendar at the current date.
15281If there is a time stamp in the current line, go to that date.
15282A prefix ARG can be used to force the current date."
15283 (interactive "P")
15284 (let ((tsr org-ts-regexp) diff
15285 (calendar-move-hook nil)
15286 (calendar-view-holidays-initially-flag nil)
3820f429 15287 (calendar-view-diary-initially-flag nil))
20908596
CD
15288 (if (or (org-at-timestamp-p)
15289 (save-excursion
15290 (beginning-of-line 1)
15291 (looking-at (concat ".*" tsr))))
15292 (let ((d1 (time-to-days (current-time)))
15293 (d2 (time-to-days
15294 (org-time-string-to-time (match-string 1)))))
15295 (setq diff (- d2 d1))))
15296 (calendar)
15297 (calendar-goto-today)
15298 (if (and diff (not arg)) (calendar-forward-day diff))))
a3fbe8c4 15299
20908596
CD
15300(defun org-get-date-from-calendar ()
15301 "Return a list (month day year) of date at point in calendar."
15302 (with-current-buffer "*Calendar*"
15303 (save-match-data
15304 (calendar-cursor-to-date))))
6769c0dc 15305
20908596
CD
15306(defun org-date-from-calendar ()
15307 "Insert time stamp corresponding to cursor date in *Calendar* buffer.
15308If there is already a time stamp at the cursor position, update it."
15309 (interactive)
15310 (if (org-at-timestamp-p t)
15311 (org-timestamp-change 0 'calendar)
15312 (let ((cal-date (org-get-date-from-calendar)))
15313 (org-insert-time-stamp
15314 (encode-time 0 0 0 (nth 1 cal-date) (car cal-date) (nth 2 cal-date))))))
d3f4dbe8 15315
20908596
CD
15316(defun org-minutes-to-hh:mm-string (m)
15317 "Compute H:MM from a number of minutes."
15318 (let ((h (/ m 60)))
15319 (setq m (- m (* 60 h)))
b349f79f 15320 (format org-time-clocksum-format h m)))
8c6fb58b 15321
20908596 15322(defun org-hh:mm-string-to-minutes (s)
c8d0cf5c 15323 "Convert a string H:MM to a number of minutes.
8bfe682a 15324If the string is just a number, interpret it as minutes.
c8d0cf5c
CD
15325In fact, the first hh:mm or number in the string will be taken,
15326there can be extra stuff in the string.
15327If no number is found, the return value is 0."
15328 (cond
15329 ((string-match "\\([0-9]+\\):\\([0-9]+\\)" s)
15330 (+ (* (string-to-number (match-string 1 s)) 60)
15331 (string-to-number (match-string 2 s))))
15332 ((string-match "\\([0-9]+\\)" s)
15333 (string-to-number (match-string 1 s)))
15334 (t 0)))
15335
15336;;;; Files
15337
15338(defun org-save-all-org-buffers ()
15339 "Save all Org-mode buffers without user confirmation."
15340 (interactive)
15341 (message "Saving all Org-mode buffers...")
15342 (save-some-buffers t 'org-mode-p)
15343 (when (featurep 'org-id) (org-id-locations-save))
15344 (message "Saving all Org-mode buffers... done"))
15345
15346(defun org-revert-all-org-buffers ()
15347 "Revert all Org-mode buffers.
15348Prompt for confirmation when there are unsaved changes.
15349Be sure you know what you are doing before letting this function
15350overwrite your changes.
15351
15352This function is useful in a setup where one tracks org files
15353with a version control system, to revert on one machine after pulling
15354changes from another. I believe the procedure must be like this:
15355
153561. M-x org-save-all-org-buffers
153572. Pull changes from the other machine, resolve conflicts
153583. M-x org-revert-all-org-buffers"
15359 (interactive)
15360 (unless (yes-or-no-p "Revert all Org buffers from their files? ")
15361 (error "Abort"))
15362 (save-excursion
15363 (save-window-excursion
15364 (mapc
15365 (lambda (b)
15366 (when (and (with-current-buffer b (org-mode-p))
15367 (with-current-buffer b buffer-file-name))
15368 (switch-to-buffer b)
15369 (revert-buffer t 'no-confirm)))
15370 (buffer-list))
15371 (when (and (featurep 'org-id) org-id-track-globally)
15372 (org-id-locations-load)))))
6769c0dc 15373
20908596
CD
15374;;;; Agenda files
15375
15376;;;###autoload
86fbb8ca
CD
15377(defun org-switchb (&optional arg)
15378 "Switch between Org buffers.
fdf730ed 15379With a prefix argument, restrict available to files.
86fbb8ca
CD
15380With two prefix arguments, restrict available buffers to agenda files.
15381
15382Defaults to `iswitchb' for buffer name completion.
15383Set `org-completion-use-ido' to make it use ido instead."
fdf730ed
CD
15384 (interactive "P")
15385 (let ((blist (cond ((equal arg '(4)) (org-buffer-list 'files))
15386 ((equal arg '(16)) (org-buffer-list 'agenda))
86fbb8ca
CD
15387 (t (org-buffer-list))))
15388 (org-completion-use-iswitchb org-completion-use-iswitchb)
15389 (org-completion-use-ido org-completion-use-ido))
15390 (unless (or org-completion-use-ido org-completion-use-iswitchb)
15391 (setq org-completion-use-iswitchb t))
fdf730ed 15392 (switch-to-buffer
54a0dee5 15393 (org-icompleting-read "Org buffer: "
86fbb8ca
CD
15394 (mapcar 'list (mapcar 'buffer-name blist))
15395 nil t))))
fdf730ed 15396
86fbb8ca
CD
15397;;; Define some older names previously used for this functionality
15398;;;###autoload
15399(defalias 'org-ido-switchb 'org-switchb)
54a0dee5 15400;;;###autoload
86fbb8ca 15401(defalias 'org-iswitchb 'org-switchb)
54a0dee5 15402
621f83e4 15403(defun org-buffer-list (&optional predicate exclude-tmp)
20908596 15404 "Return a list of Org buffers.
621f83e4
CD
15405PREDICATE can be `export', `files' or `agenda'.
15406
15407export restrict the list to Export buffers.
15408files restrict the list to buffers visiting Org files.
15409agenda restrict the list to buffers visiting agenda files.
15410
15411If EXCLUDE-TMP is non-nil, ignore temporary buffers."
15412 (let* ((bfn nil)
15413 (agenda-files (and (eq predicate 'agenda)
15414 (mapcar 'file-truename (org-agenda-files t))))
15415 (filter
15416 (cond
15417 ((eq predicate 'files)
15418 (lambda (b) (with-current-buffer b (eq major-mode 'org-mode))))
15419 ((eq predicate 'export)
15420 (lambda (b) (string-match "\*Org .*Export" (buffer-name b))))
15421 ((eq predicate 'agenda)
15422 (lambda (b)
ce4fdcb9 15423 (with-current-buffer b
621f83e4
CD
15424 (and (eq major-mode 'org-mode)
15425 (setq bfn (buffer-file-name b))
15426 (member (file-truename bfn) agenda-files)))))
ce4fdcb9 15427 (t (lambda (b) (with-current-buffer b
621f83e4
CD
15428 (or (eq major-mode 'org-mode)
15429 (string-match "\*Org .*Export"
15430 (buffer-name b)))))))))
15431 (delq nil
20908596
CD
15432 (mapcar
15433 (lambda(b)
621f83e4
CD
15434 (if (and (funcall filter b)
15435 (or (not exclude-tmp)
15436 (not (string-match "tmp" (buffer-name b)))))
15437 b
15438 nil))
15439 (buffer-list)))))
20908596 15440
2c3ad40d 15441(defun org-agenda-files (&optional unrestricted archives)
20908596
CD
15442 "Get the list of agenda files.
15443Optional UNRESTRICTED means return the full list even if a restriction
15444is currently in place.
ed21c5c8 15445When ARCHIVES is t, include all archive files that are really being
2c3ad40d
CD
15446used by the agenda files. If ARCHIVE is `ifmode', do this only if
15447`org-agenda-archives-mode' is t."
20908596
CD
15448 (let ((files
15449 (cond
15450 ((and (not unrestricted) (get 'org-agenda-files 'org-restrict)))
15451 ((stringp org-agenda-files) (org-read-agenda-file-list))
15452 ((listp org-agenda-files) org-agenda-files)
15453 (t (error "Invalid value of `org-agenda-files'")))))
15454 (setq files (apply 'append
15455 (mapcar (lambda (f)
15456 (if (file-directory-p f)
15457 (directory-files
15458 f t org-agenda-file-regexp)
15459 (list f)))
15460 files)))
15461 (when org-agenda-skip-unavailable-files
15462 (setq files (delq nil
15463 (mapcar (function
15464 (lambda (file)
15465 (and (file-readable-p file) file)))
15466 files))))
2c3ad40d
CD
15467 (when (or (eq archives t)
15468 (and (eq archives 'ifmode) (eq org-agenda-archives-mode t)))
15469 (setq files (org-add-archive-files files)))
20908596
CD
15470 files))
15471
86fbb8ca
CD
15472(defun org-agenda-file-p (&optional file)
15473 "Return non-nil, if FILE is an agenda file.
15474If FILE is omitted, use the file associated with the current
15475buffer."
15476 (member (or file (buffer-file-name))
15477 (org-agenda-files t)))
15478
20908596
CD
15479(defun org-edit-agenda-file-list ()
15480 "Edit the list of agenda files.
15481Depending on setup, this either uses customize to edit the variable
15482`org-agenda-files', or it visits the file that is holding the list. In the
15483latter case, the buffer is set up in a way that saving it automatically kills
15484the buffer and restores the previous window configuration."
15485 (interactive)
15486 (if (stringp org-agenda-files)
15487 (let ((cw (current-window-configuration)))
15488 (find-file org-agenda-files)
15489 (org-set-local 'org-window-configuration cw)
15490 (org-add-hook 'after-save-hook
15491 (lambda ()
15492 (set-window-configuration
15493 (prog1 org-window-configuration
15494 (kill-buffer (current-buffer))))
15495 (org-install-agenda-files-menu)
15496 (message "New agenda file list installed"))
15497 nil 'local)
15498 (message "%s" (substitute-command-keys
15499 "Edit list and finish with \\[save-buffer]")))
15500 (customize-variable 'org-agenda-files)))
6769c0dc 15501
20908596 15502(defun org-store-new-agenda-file-list (list)
33306645 15503 "Set new value for the agenda file list and save it correctly."
20908596 15504 (if (stringp org-agenda-files)
ed21c5c8
CD
15505 (let ((fe (org-read-agenda-file-list t)) b u)
15506 (while (setq b (find-buffer-visiting org-agenda-files))
15507 (kill-buffer b))
15508 (with-temp-file org-agenda-files
15509 (insert
15510 (mapconcat
15511 (lambda (f) ;; Keep un-expanded entries.
15512 (if (setq u (assoc f fe))
15513 (cdr u)
15514 f))
15515 list "\n")
15516 "\n")))
54a0dee5
CD
15517 (let ((org-mode-hook nil) (org-inhibit-startup t)
15518 (org-insert-mode-line-in-empty-file nil))
20908596
CD
15519 (setq org-agenda-files list)
15520 (customize-save-variable 'org-agenda-files org-agenda-files))))
6769c0dc 15521
ed21c5c8
CD
15522(defun org-read-agenda-file-list (&optional pair-with-expansion)
15523 "Read the list of agenda files from a file.
15524If PAIR-WITH-EXPANSION is t return pairs with un-expanded
15525filenames, used by `org-store-new-agenda-file-list' to write back
15526un-expanded file names."
20908596
CD
15527 (when (file-directory-p org-agenda-files)
15528 (error "`org-agenda-files' cannot be a single directory"))
15529 (when (stringp org-agenda-files)
15530 (with-temp-buffer
15531 (insert-file-contents org-agenda-files)
ed21c5c8
CD
15532 (mapcar
15533 (lambda (f)
15534 (let ((e (expand-file-name (substitute-in-file-name f)
15535 org-directory)))
15536 (if pair-with-expansion
15537 (cons e f)
15538 e)))
15539 (org-split-string (buffer-string) "[ \t\r\n]*?[\r\n][ \t\r\n]*")))))
272dfec2 15540
20908596
CD
15541;;;###autoload
15542(defun org-cycle-agenda-files ()
15543 "Cycle through the files in `org-agenda-files'.
15544If the current buffer visits an agenda file, find the next one in the list.
15545If the current buffer does not, find the first agenda file."
15546 (interactive)
15547 (let* ((fs (org-agenda-files t))
15548 (files (append fs (list (car fs))))
15549 (tcf (if buffer-file-name (file-truename buffer-file-name)))
15550 file)
15551 (unless files (error "No agenda files"))
0b8568f5 15552 (catch 'exit
20908596
CD
15553 (while (setq file (pop files))
15554 (if (equal (file-truename file) tcf)
15555 (when (car files)
15556 (find-file (car files))
15557 (throw 'exit t))))
15558 (find-file (car fs)))
15559 (if (buffer-base-buffer) (switch-to-buffer (buffer-base-buffer)))))
634a7d0b 15560
20908596
CD
15561(defun org-agenda-file-to-front (&optional to-end)
15562 "Move/add the current file to the top of the agenda file list.
15563If the file is not present in the list, it is added to the front. If it is
15564present, it is moved there. With optional argument TO-END, add/move to the
15565end of the list."
891f4676 15566 (interactive "P")
20908596
CD
15567 (let ((org-agenda-skip-unavailable-files nil)
15568 (file-alist (mapcar (lambda (x)
15569 (cons (file-truename x) x))
15570 (org-agenda-files t)))
15571 (ctf (file-truename buffer-file-name))
15572 x had)
15573 (setq x (assoc ctf file-alist) had x)
0b8568f5 15574
20908596
CD
15575 (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name))))
15576 (if to-end
15577 (setq file-alist (append (delq x file-alist) (list x)))
15578 (setq file-alist (cons x (delq x file-alist))))
15579 (org-store-new-agenda-file-list (mapcar 'cdr file-alist))
15580 (org-install-agenda-files-menu)
15581 (message "File %s to %s of agenda file list"
15582 (if had "moved" "added") (if to-end "end" "front"))))
0b8568f5 15583
20908596
CD
15584(defun org-remove-file (&optional file)
15585 "Remove current file from the list of files in variable `org-agenda-files'.
15586These are the files which are being checked for agenda entries.
ed21c5c8 15587Optional argument FILE means use this file instead of the current."
20908596
CD
15588 (interactive)
15589 (let* ((org-agenda-skip-unavailable-files nil)
15590 (file (or file buffer-file-name))
15591 (true-file (file-truename file))
15592 (afile (abbreviate-file-name file))
15593 (files (delq nil (mapcar
15594 (lambda (x)
15595 (if (equal true-file
15596 (file-truename x))
15597 nil x))
15598 (org-agenda-files t)))))
15599 (if (not (= (length files) (length (org-agenda-files t))))
15600 (progn
15601 (org-store-new-agenda-file-list files)
15602 (org-install-agenda-files-menu)
15603 (message "Removed file: %s" afile))
15604 (message "File was not in list: %s (not removed)" afile))))
891f4676 15605
20908596
CD
15606(defun org-file-menu-entry (file)
15607 (vector file (list 'find-file file) t))
891f4676 15608
20908596
CD
15609(defun org-check-agenda-file (file)
15610 "Make sure FILE exists. If not, ask user what to do."
15611 (when (not (file-exists-p file))
8d642074 15612 (message "non-existent agenda file %s. [R]emove from list or [A]bort?"
20908596
CD
15613 (abbreviate-file-name file))
15614 (let ((r (downcase (read-char-exclusive))))
891f4676 15615 (cond
20908596
CD
15616 ((equal r ?r)
15617 (org-remove-file file)
15618 (throw 'nextfile t))
15619 (t (error "Abort"))))))
a3fbe8c4 15620
20908596
CD
15621(defun org-get-agenda-file-buffer (file)
15622 "Get a buffer visiting FILE. If the buffer needs to be created, add
15623it to the list of buffers which might be released later."
15624 (let ((buf (org-find-base-buffer-visiting file)))
15625 (if buf
15626 buf ; just return it
15627 ;; Make a new buffer and remember it
15628 (setq buf (find-file-noselect file))
15629 (if buf (push buf org-agenda-new-buffers))
15630 buf)))
a3fbe8c4 15631
20908596
CD
15632(defun org-release-buffers (blist)
15633 "Release all buffers in list, asking the user for confirmation when needed.
15634When a buffer is unmodified, it is just killed. When modified, it is saved
15635\(if the user agrees) and then killed."
15636 (let (buf file)
15637 (while (setq buf (pop blist))
15638 (setq file (buffer-file-name buf))
15639 (when (and (buffer-modified-p buf)
15640 file
15641 (y-or-n-p (format "Save file %s? " file)))
15642 (with-current-buffer buf (save-buffer)))
15643 (kill-buffer buf))))
03f3cf35 15644
20908596
CD
15645(defun org-prepare-agenda-buffers (files)
15646 "Create buffers for all agenda files, protect archived trees and comments."
15647 (interactive)
15648 (let ((pa '(:org-archived t))
15649 (pc '(:org-comment t))
15650 (pall '(:org-archived t :org-comment t))
15651 (inhibit-read-only t)
15652 (rea (concat ":" org-archive-tag ":"))
15653 bmp file re)
ef943dba 15654 (save-excursion
20908596
CD
15655 (save-restriction
15656 (while (setq file (pop files))
c8d0cf5c
CD
15657 (catch 'nextfile
15658 (if (bufferp file)
15659 (set-buffer file)
15660 (org-check-agenda-file file)
15661 (set-buffer (org-get-agenda-file-buffer file)))
15662 (widen)
15663 (setq bmp (buffer-modified-p))
15664 (org-refresh-category-properties)
15665 (setq org-todo-keywords-for-agenda
15666 (append org-todo-keywords-for-agenda org-todo-keywords-1))
15667 (setq org-done-keywords-for-agenda
15668 (append org-done-keywords-for-agenda org-done-keywords))
15669 (setq org-todo-keyword-alist-for-agenda
15670 (append org-todo-keyword-alist-for-agenda org-todo-key-alist))
8d642074
CD
15671 (setq org-drawers-for-agenda
15672 (append org-drawers-for-agenda org-drawers))
c8d0cf5c
CD
15673 (setq org-tag-alist-for-agenda
15674 (append org-tag-alist-for-agenda org-tag-alist))
621f83e4 15675
c8d0cf5c
CD
15676 (save-excursion
15677 (remove-text-properties (point-min) (point-max) pall)
15678 (when org-agenda-skip-archived-trees
15679 (goto-char (point-min))
15680 (while (re-search-forward rea nil t)
15681 (if (org-on-heading-p t)
15682 (add-text-properties (point-at-bol) (org-end-of-subtree t) pa))))
20908596 15683 (goto-char (point-min))
c8d0cf5c
CD
15684 (setq re (concat "^\\*+ +" org-comment-string "\\>"))
15685 (while (re-search-forward re nil t)
15686 (add-text-properties
15687 (match-beginning 0) (org-end-of-subtree t) pc)))
15688 (set-buffer-modified-p bmp)))))
ed21c5c8
CD
15689 (setq org-todo-keywords-for-agenda
15690 (org-uniquify org-todo-keywords-for-agenda))
621f83e4
CD
15691 (setq org-todo-keyword-alist-for-agenda
15692 (org-uniquify org-todo-keyword-alist-for-agenda)
15693 org-tag-alist-for-agenda (org-uniquify org-tag-alist-for-agenda))))
7d143c25 15694
20908596 15695;;;; Embedded LaTeX
891f4676 15696
20908596
CD
15697(defvar org-cdlatex-mode-map (make-sparse-keymap)
15698 "Keymap for the minor `org-cdlatex-mode'.")
15699
15700(org-defkey org-cdlatex-mode-map "_" 'org-cdlatex-underscore-caret)
15701(org-defkey org-cdlatex-mode-map "^" 'org-cdlatex-underscore-caret)
15702(org-defkey org-cdlatex-mode-map "`" 'cdlatex-math-symbol)
15703(org-defkey org-cdlatex-mode-map "'" 'org-cdlatex-math-modify)
15704(org-defkey org-cdlatex-mode-map "\C-c{" 'cdlatex-environment)
15705
15706(defvar org-cdlatex-texmathp-advice-is-done nil
15707 "Flag remembering if we have applied the advice to texmathp already.")
15708
15709(define-minor-mode org-cdlatex-mode
15710 "Toggle the minor `org-cdlatex-mode'.
15711This mode supports entering LaTeX environment and math in LaTeX fragments
15712in Org-mode.
15713\\{org-cdlatex-mode-map}"
15714 nil " OCDL" nil
15715 (when org-cdlatex-mode (require 'cdlatex))
15716 (unless org-cdlatex-texmathp-advice-is-done
15717 (setq org-cdlatex-texmathp-advice-is-done t)
15718 (defadvice texmathp (around org-math-always-on activate)
15719 "Always return t in org-mode buffers.
15720This is because we want to insert math symbols without dollars even outside
15721the LaTeX math segments. If Orgmode thinks that point is actually inside
33306645 15722an embedded LaTeX fragment, let texmathp do its job.
20908596
CD
15723\\[org-cdlatex-mode-map]"
15724 (interactive)
15725 (let (p)
15726 (cond
15727 ((not (org-mode-p)) ad-do-it)
15728 ((eq this-command 'cdlatex-math-symbol)
15729 (setq ad-return-value t
15730 texmathp-why '("cdlatex-math-symbol in org-mode" . 0)))
15731 (t
15732 (let ((p (org-inside-LaTeX-fragment-p)))
15733 (if (and p (member (car p) (plist-get org-format-latex-options :matchers)))
15734 (setq ad-return-value t
15735 texmathp-why '("Org-mode embedded math" . 0))
15736 (if p ad-do-it)))))))))
891f4676 15737
20908596
CD
15738(defun turn-on-org-cdlatex ()
15739 "Unconditionally turn on `org-cdlatex-mode'."
15740 (org-cdlatex-mode 1))
a3fbe8c4 15741
20908596
CD
15742(defun org-inside-LaTeX-fragment-p ()
15743 "Test if point is inside a LaTeX fragment.
15744I.e. after a \\begin, \\(, \\[, $, or $$, without the corresponding closing
15745sequence appearing also before point.
15746Even though the matchers for math are configurable, this function assumes
15747that \\begin, \\(, \\[, and $$ are always used. Only the single dollar
15748delimiters are skipped when they have been removed by customization.
9b053e76 15749The return value is nil, or a cons cell with the delimiter
20908596
CD
15750and the position of this delimiter.
15751
15752This function does a reasonably good job, but can locally be fooled by
15753for example currency specifications. For example it will assume being in
15754inline math after \"$22.34\". The LaTeX fragment formatter will only format
15755fragments that are properly closed, but during editing, we have to live
15756with the uncertainty caused by missing closing delimiters. This function
15757looks only before point, not after."
15758 (catch 'exit
15759 (let ((pos (point))
15760 (dodollar (member "$" (plist-get org-format-latex-options :matchers)))
15761 (lim (progn
15762 (re-search-backward (concat "^\\(" paragraph-start "\\)") nil t)
15763 (point)))
15764 dd-on str (start 0) m re)
15765 (goto-char pos)
15766 (when dodollar
15767 (setq str (concat (buffer-substring lim (point)) "\000 X$.")
15768 re (nth 1 (assoc "$" org-latex-regexps)))
15769 (while (string-match re str start)
15770 (cond
15771 ((= (match-end 0) (length str))
15772 (throw 'exit (cons "$" (+ lim (match-beginning 0) 1))))
15773 ((= (match-end 0) (- (length str) 5))
15774 (throw 'exit nil))
15775 (t (setq start (match-end 0))))))
15776 (when (setq m (re-search-backward "\\(\\\\begin{[^}]*}\\|\\\\(\\|\\\\\\[\\)\\|\\(\\\\end{[^}]*}\\|\\\\)\\|\\\\\\]\\)\\|\\(\\$\\$\\)" lim t))
15777 (goto-char pos)
15778 (and (match-beginning 1) (throw 'exit (cons (match-string 1) m)))
15779 (and (match-beginning 2) (throw 'exit nil))
15780 ;; count $$
15781 (while (re-search-backward "\\$\\$" lim t)
15782 (setq dd-on (not dd-on)))
15783 (goto-char pos)
15784 (if dd-on (cons "$$" m))))))
a3fbe8c4 15785
ed21c5c8
CD
15786(defun org-inside-latex-macro-p ()
15787 "Is point inside a LaTeX macro or its arguments?"
15788 (save-match-data
15789 (org-in-regexp
15790 "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*")))
15791
20908596
CD
15792(defun org-try-cdlatex-tab ()
15793 "Check if it makes sense to execute `cdlatex-tab', and do it if yes.
15794It makes sense to do so if `org-cdlatex-mode' is active and if the cursor is
15795 - inside a LaTeX fragment, or
15796 - after the first word in a line, where an abbreviation expansion could
15797 insert a LaTeX environment."
15798 (when org-cdlatex-mode
0b8568f5 15799 (cond
20908596
CD
15800 ((save-excursion
15801 (skip-chars-backward "a-zA-Z0-9*")
15802 (skip-chars-backward " \t")
15803 (bolp))
15804 (cdlatex-tab) t)
15805 ((org-inside-LaTeX-fragment-p)
15806 (cdlatex-tab) t)
15807 (t nil))))
c8d16429 15808
20908596
CD
15809(defun org-cdlatex-underscore-caret (&optional arg)
15810 "Execute `cdlatex-sub-superscript' in LaTeX fragments.
15811Revert to the normal definition outside of these fragments."
15812 (interactive "P")
15813 (if (org-inside-LaTeX-fragment-p)
15814 (call-interactively 'cdlatex-sub-superscript)
15815 (let (org-cdlatex-mode)
15816 (call-interactively (key-binding (vector last-input-event))))))
e0e66b8e 15817
20908596
CD
15818(defun org-cdlatex-math-modify (&optional arg)
15819 "Execute `cdlatex-math-modify' in LaTeX fragments.
15820Revert to the normal definition outside of these fragments."
15821 (interactive "P")
15822 (if (org-inside-LaTeX-fragment-p)
15823 (call-interactively 'cdlatex-math-modify)
15824 (let (org-cdlatex-mode)
15825 (call-interactively (key-binding (vector last-input-event))))))
4b3a9ba7 15826
20908596
CD
15827(defvar org-latex-fragment-image-overlays nil
15828 "List of overlays carrying the images of latex fragments.")
15829(make-variable-buffer-local 'org-latex-fragment-image-overlays)
891f4676 15830
20908596
CD
15831(defun org-remove-latex-fragment-image-overlays ()
15832 "Remove all overlays with LaTeX fragment images in current buffer."
86fbb8ca 15833 (mapc 'delete-overlay org-latex-fragment-image-overlays)
20908596 15834 (setq org-latex-fragment-image-overlays nil))
a3fbe8c4 15835
20908596
CD
15836(defun org-preview-latex-fragment (&optional subtree)
15837 "Preview the LaTeX fragment at point, or all locally or globally.
15838If the cursor is in a LaTeX fragment, create the image and overlay
15839it over the source code. If there is no fragment at point, display
15840all fragments in the current text, from one headline to the next. With
15841prefix SUBTREE, display all fragments in the current subtree. With a
86fbb8ca
CD
15842double prefix arg \\[universal-argument] \\[universal-argument], or when \
15843the cursor is before the first headline,
20908596
CD
15844display all fragments in the buffer.
15845The images can be removed again with \\[org-ctrl-c-ctrl-c]."
15846 (interactive "P")
15847 (org-remove-latex-fragment-image-overlays)
15848 (save-excursion
15849 (save-restriction
15850 (let (beg end at msg)
15851 (cond
15852 ((or (equal subtree '(16))
15853 (not (save-excursion
15854 (re-search-backward (concat "^" outline-regexp) nil t))))
15855 (setq beg (point-min) end (point-max)
15856 msg "Creating images for buffer...%s"))
15857 ((equal subtree '(4))
15858 (org-back-to-heading)
15859 (setq beg (point) end (org-end-of-subtree t)
15860 msg "Creating images for subtree...%s"))
15861 (t
15862 (if (setq at (org-inside-LaTeX-fragment-p))
15863 (goto-char (max (point-min) (- (cdr at) 2)))
15864 (org-back-to-heading))
15865 (setq beg (point) end (progn (outline-next-heading) (point))
15866 msg (if at "Creating image...%s"
15867 "Creating images for entry...%s"))))
15868 (message msg "")
15869 (narrow-to-region beg end)
15870 (goto-char beg)
15871 (org-format-latex
15872 (concat "ltxpng/" (file-name-sans-extension
15873 (file-name-nondirectory
15874 buffer-file-name)))
afe98dfa 15875 default-directory 'overlays msg at 'forbuffer 'dvipng)
20908596 15876 (message msg "done. Use `C-c C-c' to remove images.")))))
891f4676 15877
20908596
CD
15878(defvar org-latex-regexps
15879 '(("begin" "^[ \t]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^\000]+?\\\\end{\\2}\\)" 1 t)
15880 ;; ("$" "\\([ (]\\|^\\)\\(\\(\\([$]\\)\\([^ \r\n,.$].*?\\(\n.*?\\)\\{0,5\\}[^ \r\n,.$]\\)\\4\\)\\)\\([ .,?;:'\")]\\|$\\)" 2 nil)
15881 ;; \000 in the following regex is needed for org-inside-LaTeX-fragment-p
0bd48b37
CD
15882 ("$1" "\\([^$]\\)\\(\\$[^ \r\n,;.$]\\$\\)\\([- .,?;:'\")\000]\\|$\\)" 2 nil)
15883 ("$" "\\([^$]\\)\\(\\(\\$\\([^ \r\n,;.$][^$\n\r]*?\\(\n[^$\n\r]*?\\)\\{0,2\\}[^ \r\n,.$]\\)\\$\\)\\)\\([- .,?;:'\")\000]\\|$\\)" 2 nil)
20908596 15884 ("\\(" "\\\\([^\000]*?\\\\)" 0 nil)
54a0dee5
CD
15885 ("\\[" "\\\\\\[[^\000]*?\\\\\\]" 0 nil)
15886 ("$$" "\\$\\$[^\000]*?\\$\\$" 0 nil))
20908596 15887 "Regular expressions for matching embedded LaTeX.")
891f4676 15888
afe98dfa 15889(defvar org-export-have-math nil) ;; dynamic scoping
86fbb8ca 15890(defun org-format-latex (prefix &optional dir overlays msg at
afe98dfa 15891 forbuffer processing-type)
8d642074
CD
15892 "Replace LaTeX fragments with links to an image, and produce images.
15893Some of the options can be changed using the variable
15894`org-format-latex-options'."
20908596
CD
15895 (if (and overlays (fboundp 'clear-image-cache)) (clear-image-cache))
15896 (let* ((prefixnodir (file-name-nondirectory prefix))
15897 (absprefix (expand-file-name prefix dir))
15898 (todir (file-name-directory absprefix))
15899 (opt org-format-latex-options)
15900 (matchers (plist-get opt :matchers))
15901 (re-list org-latex-regexps)
ed21c5c8
CD
15902 (org-format-latex-header-extra
15903 (plist-get (org-infile-export-plist) :latex-header-extra))
5dec9555 15904 (cnt 0) txt hash link beg end re e checkdir
afe98dfa 15905 executables-checked string
20908596 15906 m n block linkfile movefile ov)
20908596
CD
15907 ;; Check the different regular expressions
15908 (while (setq e (pop re-list))
15909 (setq m (car e) re (nth 1 e) n (nth 2 e)
15910 block (if (nth 3 e) "\n\n" ""))
15911 (when (member m matchers)
15912 (goto-char (point-min))
15913 (while (re-search-forward re nil t)
0b91aef0
CD
15914 (when (and (or (not at) (equal (cdr at) (match-beginning n)))
15915 (not (get-text-property (match-beginning n)
54a0dee5
CD
15916 'org-protected))
15917 (or (not overlays)
15918 (not (eq (get-char-property (match-beginning n)
15919 'org-overlay-type)
15920 'org-latex-overlay))))
afe98dfa
CD
15921 (setq org-export-have-math t)
15922 (cond
15923 ((eq processing-type 'verbatim)
15924 ;; Leave the text verbatim, just protect it
15925 (add-text-properties (match-beginning n) (match-end n)
15926 '(org-protected t)))
15927 ((eq processing-type 'mathjax)
15928 ;; Prepare for MathJax processing
15929 (setq string (match-string n))
15930 (if (member m '("$" "$1"))
15931 (save-excursion
15932 (delete-region (match-beginning n) (match-end n))
15933 (goto-char (match-beginning n))
15934 (insert (org-add-props (concat "\\(" (substring string 1 -1)
15935 "\\)")
15936 '(org-protected t))))
86fbb8ca 15937 (add-text-properties (match-beginning n) (match-end n)
afe98dfa
CD
15938 '(org-protected t))))
15939 ((or (eq processing-type 'dvipng) t)
15940 ;; Process to an image
86fbb8ca
CD
15941 (setq txt (match-string n)
15942 beg (match-beginning n) end (match-end n)
15943 cnt (1+ cnt))
15944 (let (print-length print-level) ; make sure full list is printed
15945 (setq hash (sha1 (prin1-to-string
15946 (list org-format-latex-header
15947 org-format-latex-header-extra
15948 org-export-latex-default-packages-alist
15949 org-export-latex-packages-alist
15950 org-format-latex-options
15951 forbuffer txt)))
15952 linkfile (format "%s_%s.png" prefix hash)
15953 movefile (format "%s_%s.png" absprefix hash)))
15954 (setq link (concat block "[[file:" linkfile "]]" block))
15955 (if msg (message msg cnt))
15956 (goto-char beg)
15957 (unless checkdir ; make sure the directory exists
15958 (setq checkdir t)
afe98dfa
CD
15959 (or (file-directory-p todir) (make-directory todir t)))
15960
86fbb8ca
CD
15961 (unless executables-checked
15962 (org-check-external-command
15963 "latex" "needed to convert LaTeX fragments to images")
15964 (org-check-external-command
15965 "dvipng" "needed to convert LaTeX fragments to images")
15966 (setq executables-checked t))
afe98dfa 15967
86fbb8ca
CD
15968 (unless (file-exists-p movefile)
15969 (org-create-formula-image
15970 txt movefile opt forbuffer))
15971 (if overlays
15972 (progn
15973 (mapc (lambda (o)
15974 (if (eq (overlay-get o 'org-overlay-type)
15975 'org-latex-overlay)
15976 (delete-overlay o)))
15977 (overlays-in beg end))
15978 (setq ov (make-overlay beg end))
15979 (overlay-put ov 'org-overlay-type 'org-latex-overlay)
15980 (if (featurep 'xemacs)
15981 (progn
15982 (overlay-put ov 'invisible t)
15983 (overlay-put
15984 ov 'end-glyph
15985 (make-glyph (vector 'png :file movefile))))
15986 (overlay-put
15987 ov 'display
15988 (list 'image :type 'png :file movefile :ascent 'center)))
15989 (push ov org-latex-fragment-image-overlays)
15990 (goto-char end))
15991 (delete-region beg end)
15992 (insert (org-add-props link
15993 (list 'org-latex-src
afe98dfa
CD
15994 (replace-regexp-in-string
15995 "\"" "" txt)))))))))))))
46177585 15996
20908596
CD
15997;; This function borrows from Ganesh Swami's latex2png.el
15998(defun org-create-formula-image (string tofile options buffer)
8d642074 15999 "This calls dvipng."
54a0dee5 16000 (require 'org-latex)
20908596
CD
16001 (let* ((tmpdir (if (featurep 'xemacs)
16002 (temp-directory)
16003 temporary-file-directory))
16004 (texfilebase (make-temp-name
16005 (expand-file-name "orgtex" tmpdir)))
16006 (texfile (concat texfilebase ".tex"))
16007 (dvifile (concat texfilebase ".dvi"))
16008 (pngfile (concat texfilebase ".png"))
16009 (fnh (if (featurep 'xemacs)
16010 (font-height (get-face-font 'default))
16011 (face-attribute 'default :height nil)))
16012 (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0))
16013 (dpi (number-to-string (* scale (floor (* 0.9 (if buffer fnh 140.))))))
16014 (fg (or (plist-get options (if buffer :foreground :html-foreground))
16015 "Black"))
16016 (bg (or (plist-get options (if buffer :background :html-background))
16017 "Transparent")))
16018 (if (eq fg 'default) (setq fg (org-dvipng-color :foreground)))
16019 (if (eq bg 'default) (setq bg (org-dvipng-color :background)))
16020 (with-temp-file texfile
ed21c5c8
CD
16021 (insert (org-splice-latex-header
16022 org-format-latex-header
16023 org-export-latex-default-packages-alist
86fbb8ca 16024 org-export-latex-packages-alist t
ed21c5c8
CD
16025 org-format-latex-header-extra))
16026 (insert "\n\\begin{document}\n" string "\n\\end{document}\n")
16027 (require 'org-latex)
16028 (org-export-latex-fix-inputenc))
20908596
CD
16029 (let ((dir default-directory))
16030 (condition-case nil
16031 (progn
16032 (cd tmpdir)
16033 (call-process "latex" nil nil nil texfile))
16034 (error nil))
16035 (cd dir))
16036 (if (not (file-exists-p dvifile))
16037 (progn (message "Failed to create dvi file from %s" texfile) nil)
2c3ad40d
CD
16038 (condition-case nil
16039 (call-process "dvipng" nil nil nil
c8d0cf5c 16040 "-fg" fg "-bg" bg
2c3ad40d
CD
16041 "-D" dpi
16042 ;;"-x" scale "-y" scale
16043 "-T" "tight"
16044 "-o" pngfile
16045 dvifile)
16046 (error nil))
20908596 16047 (if (not (file-exists-p pngfile))
ed21c5c8
CD
16048 (if org-format-latex-signal-error
16049 (error "Failed to create png file from %s" texfile)
16050 (message "Failed to create png file from %s" texfile)
16051 nil)
20908596
CD
16052 ;; Use the requested file name and clean up
16053 (copy-file pngfile tofile 'replace)
16054 (loop for e in '(".dvi" ".tex" ".aux" ".log" ".png") do
16055 (delete-file (concat texfilebase e)))
16056 pngfile))))
8c6fb58b 16057
86fbb8ca 16058(defun org-splice-latex-header (tpl def-pkg pkg snippets-p &optional extra)
ed21c5c8
CD
16059 "Fill a LaTeX header template TPL.
16060In the template, the following place holders will be recognized:
16061
16062 [DEFAULT-PACKAGES] \\usepackage statements for DEF-PKG
16063 [NO-DEFAULT-PACKAGES] do not include DEF-PKG
86fbb8ca 16064 [PACKAGES] \\usepackage statements for PKG
ed21c5c8
CD
16065 [NO-PACKAGES] do not include PKG
16066 [EXTRA] the string EXTRA
16067 [NO-EXTRA] do not include EXTRA
16068
16069For backward compatibility, if both the positive and the negative place
16070holder is missing, the positive one (without the \"NO-\") will be
16071assumed to be present at the end of the template.
16072DEF-PKG and PKG are assumed to be alists of options/packagename lists.
86fbb8ca
CD
16073EXTRA is a string.
16074SNIPPETS-P indicates if this is run to create snippet images for HTML."
ed21c5c8
CD
16075 (let (rpl (end ""))
16076 (if (string-match "^[ \t]*\\[\\(NO-\\)?DEFAULT-PACKAGES\\][ \t]*\n?" tpl)
16077 (setq rpl (if (or (match-end 1) (not def-pkg))
86fbb8ca 16078 "" (org-latex-packages-to-string def-pkg snippets-p t))
ed21c5c8 16079 tpl (replace-match rpl t t tpl))
86fbb8ca
CD
16080 (if def-pkg (setq end (org-latex-packages-to-string def-pkg snippets-p))))
16081
ed21c5c8
CD
16082 (if (string-match "\\[\\(NO-\\)?PACKAGES\\][ \t]*\n?" tpl)
16083 (setq rpl (if (or (match-end 1) (not pkg))
86fbb8ca 16084 "" (org-latex-packages-to-string pkg snippets-p t))
ed21c5c8 16085 tpl (replace-match rpl t t tpl))
86fbb8ca
CD
16086 (if pkg (setq end
16087 (concat end "\n"
16088 (org-latex-packages-to-string pkg snippets-p)))))
ed21c5c8
CD
16089
16090 (if (string-match "\\[\\(NO-\\)?EXTRA\\][ \t]*\n?" tpl)
16091 (setq rpl (if (or (match-end 1) (not extra))
16092 "" (concat extra "\n"))
16093 tpl (replace-match rpl t t tpl))
16094 (if (and extra (string-match "\\S-" extra))
16095 (setq end (concat end "\n" extra))))
16096
16097 (if (string-match "\\S-" end)
16098 (concat tpl "\n" end)
16099 tpl)))
16100
86fbb8ca 16101(defun org-latex-packages-to-string (pkg &optional snippets-p newline)
ed21c5c8
CD
16102 "Turn an alist of packages into a string with the \\usepackage macros."
16103 (setq pkg (mapconcat (lambda(p)
16104 (cond
16105 ((stringp p) p)
86fbb8ca
CD
16106 ((and snippets-p (>= (length p) 3) (not (nth 2 p)))
16107 (format "%% Package %s omitted" (cadr p)))
ed21c5c8
CD
16108 ((equal "" (car p))
16109 (format "\\usepackage{%s}" (cadr p)))
16110 (t
16111 (format "\\usepackage[%s]{%s}"
16112 (car p) (cadr p)))))
16113 pkg
16114 "\n"))
16115 (if newline (concat pkg "\n") pkg))
16116
20908596
CD
16117(defun org-dvipng-color (attr)
16118 "Return an rgb color specification for dvipng."
16119 (apply 'format "rgb %s %s %s"
16120 (mapcar 'org-normalize-color
16121 (color-values (face-attribute 'default attr nil)))))
c44f0d75 16122
20908596
CD
16123(defun org-normalize-color (value)
16124 "Return string to be used as color value for an RGB component."
16125 (format "%g" (/ value 65535.0)))
6769c0dc 16126
86fbb8ca
CD
16127;; Image display
16128
16129
16130(defvar org-inline-image-overlays nil)
16131(make-variable-buffer-local 'org-inline-image-overlays)
16132
16133(defun org-toggle-inline-images (&optional include-linked)
16134 "Toggle the display of inline images.
16135INCLUDE-LINKED is passed to `org-display-inline-images'."
16136 (interactive "P")
16137 (if org-inline-image-overlays
16138 (progn
16139 (org-remove-inline-images)
16140 (message "Inline image display turned off"))
16141 (org-display-inline-images include-linked)
16142 (if org-inline-image-overlays
16143 (message "%d images displayed inline"
16144 (length org-inline-image-overlays))
16145 (message "No images to display inline"))))
16146
16147(defun org-display-inline-images (&optional include-linked refresh beg end)
16148 "Display inline images.
16149Normally only links without a description part are inlined, because this
16150is how it will work for export. When INCLUDE-LINKED is set, also links
16151with a description part will be inlined. This can be nice for a quick
16152look at those images, but it does not reflect what exported files will look
16153like.
16154When REFRESH is set, refresh existing images between BEG and END.
16155This will create new image displays only if necessary.
16156BEG and END default to the buffer boundaries."
16157 (interactive "P")
16158 (unless refresh
16159 (org-remove-inline-images)
16160 (clear-image-cache))
16161 (save-excursion
16162 (save-restriction
16163 (widen)
16164 (setq beg (or beg (point-min)) end (or end (point-max)))
16165 (goto-char (point-min))
afe98dfa 16166 (let ((re (concat "\\[\\[\\(\\(file:\\)\\|\\([./~]\\)\\)\\([^]\n]+?"
86fbb8ca
CD
16167 (substring (org-image-file-name-regexp) 0 -2)
16168 "\\)\\]" (if include-linked "" "\\]")))
16169 old file ov img)
16170 (while (re-search-forward re end t)
16171 (setq old (get-char-property-and-overlay (match-beginning 1)
16172 'org-image-overlay))
16173 (setq file (expand-file-name
16174 (concat (or (match-string 3) "") (match-string 4))))
16175 (when (file-exists-p file)
16176 (if (and (car-safe old) refresh)
16177 (image-refresh (overlay-get (cdr old) 'display))
afe98dfa 16178 (setq img (save-match-data (create-image file)))
86fbb8ca
CD
16179 (when img
16180 (setq ov (make-overlay (match-beginning 0) (match-end 0)))
16181 (overlay-put ov 'display img)
16182 (overlay-put ov 'face 'default)
16183 (overlay-put ov 'org-image-overlay t)
16184 (overlay-put ov 'modification-hooks
16185 (list 'org-display-inline-modification-hook))
16186 (push ov org-inline-image-overlays)))))))))
16187
16188(defun org-display-inline-modification-hook (ov after beg end &optional len)
16189 "Remove inline-display overlay if a corresponding region is modified."
16190 (let ((inhibit-modification-hooks t))
16191 (when (and ov after)
16192 (delete ov org-inline-image-overlays)
16193 (delete-overlay ov))))
16194
16195(defun org-remove-inline-images ()
16196 "Remove inline display of images."
16197 (interactive)
16198 (mapc 'delete-overlay org-inline-image-overlays)
16199 (setq org-inline-image-overlays nil))
16200
d3f4dbe8 16201;;;; Key bindings
891f4676 16202
1d676e9f 16203;; Make `C-c C-x' a prefix key
a3fbe8c4 16204(org-defkey org-mode-map "\C-c\C-x" (make-sparse-keymap))
1d676e9f 16205
28e5b051 16206;; TAB key with modifiers
a3fbe8c4
CD
16207(org-defkey org-mode-map "\C-i" 'org-cycle)
16208(org-defkey org-mode-map [(tab)] 'org-cycle)
16209(org-defkey org-mode-map [(control tab)] 'org-force-cycle-archived)
acedf35c
CD
16210(org-defkey org-mode-map [(meta tab)] 'pcomplete)
16211(org-defkey org-mode-map "\M-\t" 'pcomplete)
16212(org-defkey org-mode-map "\M-\C-i" 'pcomplete)
28e5b051 16213;; The following line is necessary under Suse GNU/Linux
ab27a4a0 16214(unless (featurep 'xemacs)
a3fbe8c4
CD
16215 (org-defkey org-mode-map [S-iso-lefttab] 'org-shifttab))
16216(org-defkey org-mode-map [(shift tab)] 'org-shifttab)
03f3cf35 16217(define-key org-mode-map [backtab] 'org-shifttab)
28e5b051 16218
a3fbe8c4
CD
16219(org-defkey org-mode-map [(shift return)] 'org-table-copy-down)
16220(org-defkey org-mode-map [(meta shift return)] 'org-insert-todo-heading)
16221(org-defkey org-mode-map [(meta return)] 'org-meta-return)
28e5b051
CD
16222
16223;; Cursor keys with modifiers
a3fbe8c4
CD
16224(org-defkey org-mode-map [(meta left)] 'org-metaleft)
16225(org-defkey org-mode-map [(meta right)] 'org-metaright)
16226(org-defkey org-mode-map [(meta up)] 'org-metaup)
16227(org-defkey org-mode-map [(meta down)] 'org-metadown)
16228
16229(org-defkey org-mode-map [(meta shift left)] 'org-shiftmetaleft)
16230(org-defkey org-mode-map [(meta shift right)] 'org-shiftmetaright)
16231(org-defkey org-mode-map [(meta shift up)] 'org-shiftmetaup)
16232(org-defkey org-mode-map [(meta shift down)] 'org-shiftmetadown)
3278a016 16233
a3fbe8c4
CD
16234(org-defkey org-mode-map [(shift up)] 'org-shiftup)
16235(org-defkey org-mode-map [(shift down)] 'org-shiftdown)
16236(org-defkey org-mode-map [(shift left)] 'org-shiftleft)
16237(org-defkey org-mode-map [(shift right)] 'org-shiftright)
3278a016 16238
a3fbe8c4
CD
16239(org-defkey org-mode-map [(control shift right)] 'org-shiftcontrolright)
16240(org-defkey org-mode-map [(control shift left)] 'org-shiftcontrolleft)
28e5b051 16241
86fbb8ca
CD
16242;; Babel keys
16243(define-key org-mode-map org-babel-key-prefix org-babel-map)
16244(mapc (lambda (pair)
16245 (define-key org-babel-map (car pair) (cdr pair)))
16246 org-babel-key-bindings)
16247
d3f4dbe8
CD
16248;;; Extra keys for tty access.
16249;; We only set them when really needed because otherwise the
16250;; menus don't show the simple keys
3278a016 16251
621f83e4
CD
16252(when (or org-use-extra-keys
16253 (featurep 'xemacs) ;; because XEmacs supports multi-device stuff
3278a016 16254 (not window-system))
a3fbe8c4
CD
16255 (org-defkey org-mode-map "\C-c\C-xc" 'org-table-copy-down)
16256 (org-defkey org-mode-map "\C-c\C-xM" 'org-insert-todo-heading)
16257 (org-defkey org-mode-map "\C-c\C-xm" 'org-meta-return)
16258 (org-defkey org-mode-map [?\e (return)] 'org-meta-return)
16259 (org-defkey org-mode-map [?\e (left)] 'org-metaleft)
16260 (org-defkey org-mode-map "\C-c\C-xl" 'org-metaleft)
16261 (org-defkey org-mode-map [?\e (right)] 'org-metaright)
16262 (org-defkey org-mode-map "\C-c\C-xr" 'org-metaright)
16263 (org-defkey org-mode-map [?\e (up)] 'org-metaup)
16264 (org-defkey org-mode-map "\C-c\C-xu" 'org-metaup)
16265 (org-defkey org-mode-map [?\e (down)] 'org-metadown)
16266 (org-defkey org-mode-map "\C-c\C-xd" 'org-metadown)
16267 (org-defkey org-mode-map "\C-c\C-xL" 'org-shiftmetaleft)
16268 (org-defkey org-mode-map "\C-c\C-xR" 'org-shiftmetaright)
16269 (org-defkey org-mode-map "\C-c\C-xU" 'org-shiftmetaup)
16270 (org-defkey org-mode-map "\C-c\C-xD" 'org-shiftmetadown)
16271 (org-defkey org-mode-map [?\C-c (up)] 'org-shiftup)
16272 (org-defkey org-mode-map [?\C-c (down)] 'org-shiftdown)
16273 (org-defkey org-mode-map [?\C-c (left)] 'org-shiftleft)
16274 (org-defkey org-mode-map [?\C-c (right)] 'org-shiftright)
16275 (org-defkey org-mode-map [?\C-c ?\C-x (right)] 'org-shiftcontrolright)
c8d0cf5c 16276 (org-defkey org-mode-map [?\C-c ?\C-x (left)] 'org-shiftcontrolleft)
acedf35c 16277 (org-defkey org-mode-map [?\e (tab)] 'pcomplete)
c8d0cf5c
CD
16278 (org-defkey org-mode-map [?\e (shift return)] 'org-insert-todo-heading)
16279 (org-defkey org-mode-map [?\e (shift left)] 'org-shiftmetaleft)
16280 (org-defkey org-mode-map [?\e (shift right)] 'org-shiftmetaright)
16281 (org-defkey org-mode-map [?\e (shift up)] 'org-shiftmetaup)
16282 (org-defkey org-mode-map [?\e (shift down)] 'org-shiftmetadown))
d3f4dbe8 16283
3278a016 16284 ;; All the other keys
bea5b1ba 16285
a3fbe8c4
CD
16286(org-defkey org-mode-map "\C-c\C-a" 'show-all) ; in case allout messed up.
16287(org-defkey org-mode-map "\C-c\C-r" 'org-reveal)
2c3ad40d
CD
16288(if (boundp 'narrow-map)
16289 (org-defkey narrow-map "s" 'org-narrow-to-subtree)
16290 (org-defkey org-mode-map "\C-xns" 'org-narrow-to-subtree))
c8d0cf5c
CD
16291(org-defkey org-mode-map "\C-c\C-f" 'org-forward-same-level)
16292(org-defkey org-mode-map "\C-c\C-b" 'org-backward-same-level)
a3fbe8c4
CD
16293(org-defkey org-mode-map "\C-c$" 'org-archive-subtree)
16294(org-defkey org-mode-map "\C-c\C-x\C-s" 'org-advertized-archive-subtree)
8bfe682a 16295(org-defkey org-mode-map "\C-c\C-x\C-a" 'org-archive-subtree-default)
20908596
CD
16296(org-defkey org-mode-map "\C-c\C-xa" 'org-toggle-archive-tag)
16297(org-defkey org-mode-map "\C-c\C-xA" 'org-archive-to-archive-sibling)
a3fbe8c4
CD
16298(org-defkey org-mode-map "\C-c\C-xb" 'org-tree-to-indirect-buffer)
16299(org-defkey org-mode-map "\C-c\C-j" 'org-goto)
16300(org-defkey org-mode-map "\C-c\C-t" 'org-todo)
71d35b24 16301(org-defkey org-mode-map "\C-c\C-q" 'org-set-tags-command)
a3fbe8c4
CD
16302(org-defkey org-mode-map "\C-c\C-s" 'org-schedule)
16303(org-defkey org-mode-map "\C-c\C-d" 'org-deadline)
16304(org-defkey org-mode-map "\C-c;" 'org-toggle-comment)
8c6fb58b 16305(org-defkey org-mode-map "\C-c\C-w" 'org-refile)
03f3cf35 16306(org-defkey org-mode-map "\C-c/" 'org-sparse-tree) ; Minor-mode reserved
c8d0cf5c 16307(org-defkey org-mode-map "\C-c\\" 'org-match-sparse-tree) ; Minor-mode res.
a3fbe8c4
CD
16308(org-defkey org-mode-map "\C-c\C-m" 'org-ctrl-c-ret)
16309(org-defkey org-mode-map "\M-\C-m" 'org-insert-heading)
c8d0cf5c 16310(org-defkey org-mode-map "\C-c\C-xc" 'org-clone-subtree-with-time-shift)
621f83e4
CD
16311(org-defkey org-mode-map [(control return)] 'org-insert-heading-respect-content)
16312(org-defkey org-mode-map [(shift control return)] 'org-insert-todo-heading-respect-content)
a3fbe8c4
CD
16313(org-defkey org-mode-map "\C-c\C-x\C-n" 'org-next-link)
16314(org-defkey org-mode-map "\C-c\C-x\C-p" 'org-previous-link)
16315(org-defkey org-mode-map "\C-c\C-l" 'org-insert-link)
16316(org-defkey org-mode-map "\C-c\C-o" 'org-open-at-point)
16317(org-defkey org-mode-map "\C-c%" 'org-mark-ring-push)
16318(org-defkey org-mode-map "\C-c&" 'org-mark-ring-goto)
20908596 16319(org-defkey org-mode-map "\C-c\C-z" 'org-add-note) ; Alternative binding
a3fbe8c4
CD
16320(org-defkey org-mode-map "\C-c." 'org-time-stamp) ; Minor-mode reserved
16321(org-defkey org-mode-map "\C-c!" 'org-time-stamp-inactive) ; Minor-mode r.
16322(org-defkey org-mode-map "\C-c," 'org-priority) ; Minor-mode reserved
16323(org-defkey org-mode-map "\C-c\C-y" 'org-evaluate-time-range)
16324(org-defkey org-mode-map "\C-c>" 'org-goto-calendar)
16325(org-defkey org-mode-map "\C-c<" 'org-date-from-calendar)
16326(org-defkey org-mode-map [(control ?,)] 'org-cycle-agenda-files)
16327(org-defkey org-mode-map [(control ?\')] 'org-cycle-agenda-files)
16328(org-defkey org-mode-map "\C-c[" 'org-agenda-file-to-front)
16329(org-defkey org-mode-map "\C-c]" 'org-remove-file)
8c6fb58b
CD
16330(org-defkey org-mode-map "\C-c\C-x<" 'org-agenda-set-restriction-lock)
16331(org-defkey org-mode-map "\C-c\C-x>" 'org-agenda-remove-restriction-lock)
38f8646b 16332(org-defkey org-mode-map "\C-c-" 'org-ctrl-c-minus)
2a57416f 16333(org-defkey org-mode-map "\C-c*" 'org-ctrl-c-star)
a3fbe8c4
CD
16334(org-defkey org-mode-map "\C-c^" 'org-sort)
16335(org-defkey org-mode-map "\C-c\C-c" 'org-ctrl-c-ctrl-c)
03f3cf35 16336(org-defkey org-mode-map "\C-c\C-k" 'org-kill-note-or-show-branches)
54a0dee5 16337(org-defkey org-mode-map "\C-c#" 'org-update-statistics-cookies)
a3fbe8c4 16338(org-defkey org-mode-map "\C-m" 'org-return)
8c6fb58b 16339(org-defkey org-mode-map "\C-j" 'org-return-indent)
a3fbe8c4
CD
16340(org-defkey org-mode-map "\C-c?" 'org-table-field-info)
16341(org-defkey org-mode-map "\C-c " 'org-table-blank-field)
16342(org-defkey org-mode-map "\C-c+" 'org-table-sum)
16343(org-defkey org-mode-map "\C-c=" 'org-table-eval-formula)
b349f79f 16344(org-defkey org-mode-map "\C-c'" 'org-edit-special)
a3fbe8c4
CD
16345(org-defkey org-mode-map "\C-c`" 'org-table-edit-field)
16346(org-defkey org-mode-map "\C-c|" 'org-table-create-or-convert-from-region)
a3fbe8c4
CD
16347(org-defkey org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks)
16348(org-defkey org-mode-map "\C-c~" 'org-table-create-with-table.el)
621f83e4 16349(org-defkey org-mode-map "\C-c\C-a" 'org-attach)
a3fbe8c4
CD
16350(org-defkey org-mode-map "\C-c}" 'org-table-toggle-coordinate-overlays)
16351(org-defkey org-mode-map "\C-c{" 'org-table-toggle-formula-debugger)
16352(org-defkey org-mode-map "\C-c\C-e" 'org-export)
16353(org-defkey org-mode-map "\C-c:" 'org-toggle-fixed-width-section)
16354(org-defkey org-mode-map "\C-c\C-x\C-f" 'org-emphasize)
c8d0cf5c 16355(org-defkey org-mode-map "\C-c\C-xf" 'org-footnote-action)
8d642074
CD
16356(org-defkey org-mode-map "\C-c\C-x\C-mg" 'org-mobile-pull)
16357(org-defkey org-mode-map "\C-c\C-x\C-mp" 'org-mobile-push)
acedf35c 16358(org-defkey org-mode-map "\C-c@" 'org-mark-subtree)
c8d0cf5c
CD
16359(org-defkey org-mode-map [?\C-c (control ?*)] 'org-list-make-subtree)
16360;;(org-defkey org-mode-map [?\C-c (control ?-)] 'org-list-make-list-from-subtree)
a3fbe8c4 16361
b349f79f 16362(org-defkey org-mode-map "\C-c\C-x\C-k" 'org-mark-entry-for-agenda-action)
a3fbe8c4
CD
16363(org-defkey org-mode-map "\C-c\C-x\C-w" 'org-cut-special)
16364(org-defkey org-mode-map "\C-c\C-x\M-w" 'org-copy-special)
16365(org-defkey org-mode-map "\C-c\C-x\C-y" 'org-paste-special)
16366
16367(org-defkey org-mode-map "\C-c\C-x\C-t" 'org-toggle-time-stamp-overlays)
16368(org-defkey org-mode-map "\C-c\C-x\C-i" 'org-clock-in)
16369(org-defkey org-mode-map "\C-c\C-x\C-o" 'org-clock-out)
15841868 16370(org-defkey org-mode-map "\C-c\C-x\C-j" 'org-clock-goto)
a3fbe8c4
CD
16371(org-defkey org-mode-map "\C-c\C-x\C-x" 'org-clock-cancel)
16372(org-defkey org-mode-map "\C-c\C-x\C-d" 'org-clock-display)
16373(org-defkey org-mode-map "\C-c\C-x\C-r" 'org-clock-report)
16374(org-defkey org-mode-map "\C-c\C-x\C-u" 'org-dblock-update)
16375(org-defkey org-mode-map "\C-c\C-x\C-l" 'org-preview-latex-fragment)
86fbb8ca
CD
16376(org-defkey org-mode-map "\C-c\C-x\C-v" 'org-toggle-inline-images)
16377(org-defkey org-mode-map "\C-c\C-x\\" 'org-toggle-pretty-entities)
a3fbe8c4 16378(org-defkey org-mode-map "\C-c\C-x\C-b" 'org-toggle-checkbox)
03f3cf35 16379(org-defkey org-mode-map "\C-c\C-xp" 'org-set-property)
54a0dee5 16380(org-defkey org-mode-map "\C-c\C-xe" 'org-set-effort)
a2a2e7fb 16381(org-defkey org-mode-map "\C-c\C-xo" 'org-toggle-ordered-property)
621f83e4 16382(org-defkey org-mode-map "\C-c\C-xi" 'org-insert-columns-dblock)
c8d0cf5c 16383(org-defkey org-mode-map [(control ?c) (control ?x) ?\;] 'org-timer-set-timer)
afe98dfa 16384(org-defkey org-mode-map [(control ?c) (control ?x) ?\:] 'org-timer-cancel-timer)
edd21304 16385
ff4be292
CD
16386(org-defkey org-mode-map "\C-c\C-x." 'org-timer)
16387(org-defkey org-mode-map "\C-c\C-x-" 'org-timer-item)
16388(org-defkey org-mode-map "\C-c\C-x0" 'org-timer-start)
afe98dfa 16389(org-defkey org-mode-map "\C-c\C-x_" 'org-timer-stop)
0bd48b37 16390(org-defkey org-mode-map "\C-c\C-x," 'org-timer-pause-or-continue)
ff4be292 16391
38f8646b
CD
16392(define-key org-mode-map "\C-c\C-x\C-c" 'org-columns)
16393
c8d0cf5c
CD
16394(define-key org-mode-map "\C-c\C-x!" 'org-reload)
16395
16396(define-key org-mode-map "\C-c\C-xg" 'org-feed-update-all)
16397(define-key org-mode-map "\C-c\C-xG" 'org-feed-goto-inbox)
16398
16399(define-key org-mode-map "\C-c\C-x[" 'org-reftex-citation)
16400
16401
edd21304 16402(when (featurep 'xemacs)
a3fbe8c4 16403 (org-defkey org-mode-map 'button3 'popup-mode-menu))
4b3a9ba7 16404
c8d0cf5c 16405
8bfe682a
CD
16406(defconst org-speed-commands-default
16407 '(
1bcdebed
CD
16408 ("Outline Navigation")
16409 ("n" . (org-speed-move-safe 'outline-next-visible-heading))
16410 ("p" . (org-speed-move-safe 'outline-previous-visible-heading))
16411 ("f" . (org-speed-move-safe 'org-forward-same-level))
16412 ("b" . (org-speed-move-safe 'org-backward-same-level))
16413 ("u" . (org-speed-move-safe 'outline-up-heading))
16414 ("j" . org-goto)
16415 ("g" . (org-refile t))
16416 ("Outline Visibility")
8bfe682a
CD
16417 ("c" . org-cycle)
16418 ("C" . org-shifttab)
1bcdebed
CD
16419 (" " . org-display-outline-path)
16420 ("Outline Structure Editing")
8bfe682a
CD
16421 ("U" . org-shiftmetaup)
16422 ("D" . org-shiftmetadown)
16423 ("r" . org-metaright)
16424 ("l" . org-metaleft)
16425 ("R" . org-shiftmetaright)
16426 ("L" . org-shiftmetaleft)
16427 ("i" . (progn (forward-char 1) (call-interactively
16428 'org-insert-heading-respect-content)))
1bcdebed
CD
16429 ("^" . org-sort)
16430 ("w" . org-refile)
16431 ("a" . org-archive-subtree-default-with-confirmation)
acedf35c 16432 ("." . org-mark-subtree)
1bcdebed 16433 ("Clock Commands")
8bfe682a
CD
16434 ("I" . org-clock-in)
16435 ("O" . org-clock-out)
1bcdebed 16436 ("Meta Data Editing")
8bfe682a 16437 ("t" . org-todo)
8bfe682a
CD
16438 ("0" . (org-priority ?\ ))
16439 ("1" . (org-priority ?A))
16440 ("2" . (org-priority ?B))
16441 ("3" . (org-priority ?C))
1bcdebed
CD
16442 (";" . org-set-tags-command)
16443 ("e" . org-set-effort)
16444 ("Agenda Views etc")
16445 ("v" . org-agenda)
16446 ("/" . org-sparse-tree)
1bcdebed
CD
16447 ("Misc")
16448 ("o" . org-open-at-point)
8bfe682a 16449 ("?" . org-speed-command-help)
afe98dfa
CD
16450 ("<" . (org-agenda-set-restriction-lock 'subtree))
16451 (">" . (org-agenda-remove-restriction-lock))
8bfe682a
CD
16452 )
16453 "The default speed commands.")
16454
16455(defun org-print-speed-command (e)
1bcdebed
CD
16456 (if (> (length (car e)) 1)
16457 (progn
16458 (princ "\n")
16459 (princ (car e))
16460 (princ "\n")
16461 (princ (make-string (length (car e)) ?-))
16462 (princ "\n"))
16463 (princ (car e))
16464 (princ " ")
16465 (if (symbolp (cdr e))
16466 (princ (symbol-name (cdr e)))
16467 (prin1 (cdr e)))
16468 (princ "\n")))
8bfe682a
CD
16469
16470(defun org-speed-command-help ()
16471 "Show the available speed commands."
16472 (interactive)
16473 (if (not org-use-speed-commands)
86fbb8ca 16474 (error "Speed commands are not activated, customize `org-use-speed-commands'")
8bfe682a 16475 (with-output-to-temp-buffer "*Help*"
1bcdebed 16476 (princ "User-defined Speed commands\n===========================\n")
8bfe682a
CD
16477 (mapc 'org-print-speed-command org-speed-commands-user)
16478 (princ "\n")
1bcdebed
CD
16479 (princ "Built-in Speed commands\n=======================\n")
16480 (mapc 'org-print-speed-command org-speed-commands-default))
16481 (with-current-buffer "*Help*"
16482 (setq truncate-lines t))))
16483
16484(defun org-speed-move-safe (cmd)
16485 "Execute CMD, but make sure that the cursor always ends up in a headline.
16486If not, return to the original position and throw an error."
16487 (interactive)
16488 (let ((pos (point)))
16489 (call-interactively cmd)
16490 (unless (and (bolp) (org-on-heading-p))
16491 (goto-char pos)
16492 (error "Boundary reached while executing %s" cmd))))
8bfe682a 16493
c8d0cf5c
CD
16494(defvar org-self-insert-command-undo-counter 0)
16495
20908596 16496(defvar org-table-auto-blank-field) ; defined in org-table.el
8bfe682a 16497(defvar org-speed-command nil)
afe98dfa
CD
16498
16499(defun org-speed-command-default-hook (keys)
16500 "Hook for activating single-letter speed commands.
01c35094
JB
16501`org-speed-commands-default' specifies a minimal command set.
16502Use `org-speed-commands-user' for further customization."
afe98dfa
CD
16503 (when (or (and (bolp) (looking-at outline-regexp))
16504 (and (functionp org-use-speed-commands)
16505 (funcall org-use-speed-commands)))
16506 (cdr (assoc keys (append org-speed-commands-user
16507 org-speed-commands-default)))))
16508
16509(defun org-babel-speed-command-hook (keys)
16510 "Hook for activating single-letter code block commands."
16511 (when (and (bolp) (looking-at org-babel-src-block-regexp))
16512 (cdr (assoc keys org-babel-key-bindings))))
16513
16514(defcustom org-speed-command-hook
16515 '(org-speed-command-default-hook org-babel-speed-command-hook)
16516 "Hook for activating speed commands at strategic locations.
16517Hook functions are called in sequence until a valid handler is
16518found.
16519
16520Each hook takes a single argument, a user-pressed command key
16521which is also a `self-insert-command' from the global map.
16522
16523Within the hook, examine the cursor position and the command key
01c35094 16524and return nil or a valid handler as appropriate. Handler could
afe98dfa
CD
16525be one of an interactive command, a function, or a form.
16526
16527Set `org-use-speed-commands' to non-nil value to enable this
01c35094 16528hook. The default setting is `org-speed-command-default-hook'."
afe98dfa
CD
16529 :group 'org-structure
16530 :type 'hook)
16531
791d856f
CD
16532(defun org-self-insert-command (N)
16533 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
16534If the cursor is in a table looking at whitespace, the whitespace is
16535overwritten, and the table is not marked as requiring realignment."
16536 (interactive "p")
8bfe682a
CD
16537 (cond
16538 ((and org-use-speed-commands
afe98dfa
CD
16539 (setq org-speed-command
16540 (run-hook-with-args-until-success
16541 'org-speed-command-hook (this-command-keys))))
8bfe682a
CD
16542 (cond
16543 ((commandp org-speed-command)
16544 (setq this-command org-speed-command)
16545 (call-interactively org-speed-command))
16546 ((functionp org-speed-command)
db4a7382 16547 (funcall org-speed-command))
8bfe682a
CD
16548 ((and org-speed-command (listp org-speed-command))
16549 (eval org-speed-command))
16550 (t (let (org-use-speed-commands)
16551 (call-interactively 'org-self-insert-command)))))
16552 ((and
16553 (org-table-p)
16554 (progn
16555 ;; check if we blank the field, and if that triggers align
16556 (and (featurep 'org-table) org-table-auto-blank-field
16557 (member last-command
16558 '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c yas/expand))
16559 (if (or (equal (char-after) ?\ ) (looking-at "[^|\n]* |"))
16560 ;; got extra space, this field does not determine column width
16561 (let (org-table-may-need-update) (org-table-blank-field))
c8d0cf5c 16562 ;; no extra space, this field may determine column width
8bfe682a
CD
16563 (org-table-blank-field)))
16564 t)
16565 (eq N 1)
16566 (looking-at "[^|\n]* |"))
16567 (let (org-table-may-need-update)
16568 (goto-char (1- (match-end 0)))
16569 (delete-backward-char 1)
16570 (goto-char (match-beginning 0))
16571 (self-insert-command N)))
16572 (t
791d856f 16573 (setq org-table-may-need-update t)
1e8fbb6d 16574 (self-insert-command N)
c8d0cf5c
CD
16575 (org-fix-tags-on-the-fly)
16576 (if org-self-insert-cluster-for-undo
16577 (if (not (eq last-command 'org-self-insert-command))
16578 (setq org-self-insert-command-undo-counter 1)
16579 (if (>= org-self-insert-command-undo-counter 20)
16580 (setq org-self-insert-command-undo-counter 1)
16581 (and (> org-self-insert-command-undo-counter 0)
16582 buffer-undo-list
16583 (not (cadr buffer-undo-list)) ; remove nil entry
16584 (setcdr buffer-undo-list (cddr buffer-undo-list)))
16585 (setq org-self-insert-command-undo-counter
8bfe682a 16586 (1+ org-self-insert-command-undo-counter))))))))
1e8fbb6d
CD
16587
16588(defun org-fix-tags-on-the-fly ()
16589 (when (and (equal (char-after (point-at-bol)) ?*)
16590 (org-on-heading-p))
16591 (org-align-tags-here org-tags-column)))
791d856f 16592
791d856f
CD
16593(defun org-delete-backward-char (N)
16594 "Like `delete-backward-char', insert whitespace at field end in tables.
16595When deleting backwards, in tables this function will insert whitespace in
16596front of the next \"|\" separator, to keep the table aligned. The table will
ab27a4a0
CD
16597still be marked for re-alignment if the field did fill the entire column,
16598because, in this case the deletion might narrow the column."
791d856f
CD
16599 (interactive "p")
16600 (if (and (org-table-p)
c8d16429
CD
16601 (eq N 1)
16602 (string-match "|" (buffer-substring (point-at-bol) (point)))
16603 (looking-at ".*?|"))
edd21304 16604 (let ((pos (point))
ab27a4a0
CD
16605 (noalign (looking-at "[^|\n\r]* |"))
16606 (c org-table-may-need-update))
c8d16429 16607 (backward-delete-char N)
afe98dfa
CD
16608 (if (not overwrite-mode)
16609 (progn
16610 (skip-chars-forward "^|")
16611 (insert " ")
16612 (goto-char (1- pos))))
ab27a4a0
CD
16613 ;; noalign: if there were two spaces at the end, this field
16614 ;; does not determine the width of the column.
16615 (if noalign (setq org-table-may-need-update c)))
1e8fbb6d
CD
16616 (backward-delete-char N)
16617 (org-fix-tags-on-the-fly)))
791d856f
CD
16618
16619(defun org-delete-char (N)
16620 "Like `delete-char', but insert whitespace at field end in tables.
16621When deleting characters, in tables this function will insert whitespace in
ab27a4a0
CD
16622front of the next \"|\" separator, to keep the table aligned. The table will
16623still be marked for re-alignment if the field did fill the entire column,
16624because, in this case the deletion might narrow the column."
791d856f
CD
16625 (interactive "p")
16626 (if (and (org-table-p)
c8d16429
CD
16627 (not (bolp))
16628 (not (= (char-after) ?|))
16629 (eq N 1))
791d856f 16630 (if (looking-at ".*?|")
ab27a4a0
CD
16631 (let ((pos (point))
16632 (noalign (looking-at "[^|\n\r]* |"))
16633 (c org-table-may-need-update))
c8d16429
CD
16634 (replace-match (concat
16635 (substring (match-string 0) 1 -1)
16636 " |"))
ab27a4a0
CD
16637 (goto-char pos)
16638 ;; noalign: if there were two spaces at the end, this field
16639 ;; does not determine the width of the column.
4b3a9ba7
CD
16640 (if noalign (setq org-table-may-need-update c)))
16641 (delete-char N))
1e8fbb6d
CD
16642 (delete-char N)
16643 (org-fix-tags-on-the-fly)))
791d856f 16644
3278a016
CD
16645;; Make `delete-selection-mode' work with org-mode and orgtbl-mode
16646(put 'org-self-insert-command 'delete-selection t)
16647(put 'orgtbl-self-insert-command 'delete-selection t)
16648(put 'org-delete-char 'delete-selection 'supersede)
16649(put 'org-delete-backward-char 'delete-selection 'supersede)
1e4f816a 16650(put 'org-yank 'delete-selection 'yank)
3278a016 16651
7373bc42
CD
16652;; Make `flyspell-mode' delay after some commands
16653(put 'org-self-insert-command 'flyspell-delayed t)
16654(put 'orgtbl-self-insert-command 'flyspell-delayed t)
16655(put 'org-delete-char 'flyspell-delayed t)
16656(put 'org-delete-backward-char 'flyspell-delayed t)
16657
8c6fb58b
CD
16658;; Make pabbrev-mode expand after org-mode commands
16659(put 'org-self-insert-command 'pabbrev-expand-after-command t)
33306645 16660(put 'orgtbl-self-insert-command 'pabbrev-expand-after-command t)
15841868 16661
791d856f
CD
16662;; How to do this: Measure non-white length of current string
16663;; If equal to column width, we should realign.
16664
28e5b051
CD
16665(defun org-remap (map &rest commands)
16666 "In MAP, remap the functions given in COMMANDS.
16667COMMANDS is a list of alternating OLDDEF NEWDEF command names."
16668 (let (new old)
16669 (while commands
16670 (setq old (pop commands) new (pop commands))
16671 (if (fboundp 'command-remapping)
a3fbe8c4 16672 (org-defkey map (vector 'remap old) new)
28e5b051 16673 (substitute-key-definition old new map global-map)))))
e0e66b8e 16674
791d856f
CD
16675(when (eq org-enable-table-editor 'optimized)
16676 ;; If the user wants maximum table support, we need to hijack
16677 ;; some standard editing functions
28e5b051
CD
16678 (org-remap org-mode-map
16679 'self-insert-command 'org-self-insert-command
16680 'delete-char 'org-delete-char
16681 'delete-backward-char 'org-delete-backward-char)
a3fbe8c4 16682 (org-defkey org-mode-map "|" 'org-force-self-insert))
791d856f 16683
c8d0cf5c
CD
16684(defvar org-ctrl-c-ctrl-c-hook nil
16685 "Hook for functions attaching themselves to `C-c C-c'.
16686This can be used to add additional functionality to the C-c C-c key which
16687executes context-dependent commands.
16688Each function will be called with no arguments. The function must check
16689if the context is appropriate for it to act. If yes, it should do its
16690thing and then return a non-nil value. If the context is wrong,
16691just do nothing and return nil.")
16692
16693(defvar org-tab-first-hook nil
16694 "Hook for functions to attach themselves to TAB.
16695See `org-ctrl-c-ctrl-c-hook' for more information.
16696This hook runs as the first action when TAB is pressed, even before
16697`org-cycle' messes around with the `outline-regexp' to cater for
16698inline tasks and plain list item folding.
86fbb8ca
CD
16699If any function in this hook returns t, any other actions that
16700would have been caused by TAB (such as table field motion or visibility
16701cycling) will not occur.")
c8d0cf5c
CD
16702
16703(defvar org-tab-after-check-for-table-hook nil
16704 "Hook for functions to attach themselves to TAB.
16705See `org-ctrl-c-ctrl-c-hook' for more information.
16706This hook runs after it has been established that the cursor is not in a
16707table, but before checking if the cursor is in a headline or if global cycling
16708should be done.
16709If any function in this hook returns t, not other actions like visibility
16710cycling will be done.")
16711
16712(defvar org-tab-after-check-for-cycling-hook nil
16713 "Hook for functions to attach themselves to TAB.
16714See `org-ctrl-c-ctrl-c-hook' for more information.
16715This hook runs after it has been established that not table field motion and
16716not visibility should be done because of current context. This is probably
16717the place where a package like yasnippets can hook in.")
16718
8bfe682a
CD
16719(defvar org-tab-before-tab-emulation-hook nil
16720 "Hook for functions to attach themselves to TAB.
16721See `org-ctrl-c-ctrl-c-hook' for more information.
16722This hook runs after every other options for TAB have been exhausted, but
16723before indentation and \t insertion takes place.")
16724
c8d0cf5c
CD
16725(defvar org-metaleft-hook nil
16726 "Hook for functions attaching themselves to `M-left'.
16727See `org-ctrl-c-ctrl-c-hook' for more information.")
16728(defvar org-metaright-hook nil
16729 "Hook for functions attaching themselves to `M-right'.
16730See `org-ctrl-c-ctrl-c-hook' for more information.")
16731(defvar org-metaup-hook nil
16732 "Hook for functions attaching themselves to `M-up'.
16733See `org-ctrl-c-ctrl-c-hook' for more information.")
16734(defvar org-metadown-hook nil
16735 "Hook for functions attaching themselves to `M-down'.
16736See `org-ctrl-c-ctrl-c-hook' for more information.")
16737(defvar org-shiftmetaleft-hook nil
16738 "Hook for functions attaching themselves to `M-S-left'.
16739See `org-ctrl-c-ctrl-c-hook' for more information.")
16740(defvar org-shiftmetaright-hook nil
16741 "Hook for functions attaching themselves to `M-S-right'.
16742See `org-ctrl-c-ctrl-c-hook' for more information.")
16743(defvar org-shiftmetaup-hook nil
16744 "Hook for functions attaching themselves to `M-S-up'.
16745See `org-ctrl-c-ctrl-c-hook' for more information.")
16746(defvar org-shiftmetadown-hook nil
16747 "Hook for functions attaching themselves to `M-S-down'.
16748See `org-ctrl-c-ctrl-c-hook' for more information.")
16749(defvar org-metareturn-hook nil
16750 "Hook for functions attaching themselves to `M-RET'.
16751See `org-ctrl-c-ctrl-c-hook' for more information.")
86fbb8ca
CD
16752(defvar org-shiftup-hook nil
16753 "Hook for functions attaching themselves to `S-up'.
16754See `org-ctrl-c-ctrl-c-hook' for more information.")
16755(defvar org-shiftup-final-hook nil
16756 "Hook for functions attaching themselves to `S-up'.
16757This one runs after all other options except shift-select have been excluded.
16758See `org-ctrl-c-ctrl-c-hook' for more information.")
16759(defvar org-shiftdown-hook nil
16760 "Hook for functions attaching themselves to `S-down'.
16761See `org-ctrl-c-ctrl-c-hook' for more information.")
16762(defvar org-shiftdown-final-hook nil
16763 "Hook for functions attaching themselves to `S-down'.
16764This one runs after all other options except shift-select have been excluded.
16765See `org-ctrl-c-ctrl-c-hook' for more information.")
16766(defvar org-shiftleft-hook nil
16767 "Hook for functions attaching themselves to `S-left'.
16768See `org-ctrl-c-ctrl-c-hook' for more information.")
16769(defvar org-shiftleft-final-hook nil
16770 "Hook for functions attaching themselves to `S-left'.
16771This one runs after all other options except shift-select have been excluded.
16772See `org-ctrl-c-ctrl-c-hook' for more information.")
16773(defvar org-shiftright-hook nil
16774 "Hook for functions attaching themselves to `S-right'.
16775See `org-ctrl-c-ctrl-c-hook' for more information.")
16776(defvar org-shiftright-final-hook nil
16777 "Hook for functions attaching themselves to `S-right'.
16778This one runs after all other options except shift-select have been excluded.
16779See `org-ctrl-c-ctrl-c-hook' for more information.")
c8d0cf5c 16780
65c439fd
CD
16781(defun org-modifier-cursor-error ()
16782 "Throw an error, a modified cursor command was applied in wrong context."
16783 (error "This command is active in special context like tables, headlines or items"))
16784
16785(defun org-shiftselect-error ()
891f4676 16786 "Throw an error because Shift-Cursor command was applied in wrong context."
65c439fd 16787 (if (and (boundp 'shift-select-mode) shift-select-mode)
f924a367
JB
16788 (error "To use shift-selection with Org-mode, customize `org-support-shift-select'")
16789 (error "This command works only in special context like headlines or timestamps")))
65c439fd
CD
16790
16791(defun org-call-for-shift-select (cmd)
16792 (let ((this-command-keys-shift-translated t))
16793 (call-interactively cmd)))
891f4676 16794
edd21304 16795(defun org-shifttab (&optional arg)
28e5b051 16796 "Global visibility cycling or move to previous table field.
4b3a9ba7
CD
16797Calls `org-cycle' with argument t, or `org-table-previous-field', depending
16798on context.
28e5b051 16799See the individual commands for more information."
edd21304 16800 (interactive "P")
891f4676 16801 (cond
4b3a9ba7 16802 ((org-at-table-p) (call-interactively 'org-table-previous-field))
b349f79f 16803 ((integerp arg)
8d642074
CD
16804 (let ((arg2 (if org-odd-levels-only (1- (* 2 arg)) arg)))
16805 (message "Content view to level: %d" arg)
16806 (org-content (prefix-numeric-value arg2))
16807 (setq org-cycle-global-status 'overview)))
4b3a9ba7 16808 (t (call-interactively 'org-global-cycle))))
891f4676 16809
634a7d0b 16810(defun org-shiftmetaleft ()
28e5b051 16811 "Promote subtree or delete table column.
a3fbe8c4
CD
16812Calls `org-promote-subtree', `org-outdent-item',
16813or `org-table-delete-column', depending on context.
28e5b051 16814See the individual commands for more information."
634a7d0b 16815 (interactive)
891f4676 16816 (cond
c8d0cf5c 16817 ((run-hook-with-args-until-success 'org-shiftmetaleft-hook))
4b3a9ba7
CD
16818 ((org-at-table-p) (call-interactively 'org-table-delete-column))
16819 ((org-on-heading-p) (call-interactively 'org-promote-subtree))
86fbb8ca 16820 ((org-at-item-p) (call-interactively 'org-outdent-item-tree))
65c439fd 16821 (t (org-modifier-cursor-error))))
634a7d0b
CD
16822
16823(defun org-shiftmetaright ()
28e5b051 16824 "Demote subtree or insert table column.
a3fbe8c4
CD
16825Calls `org-demote-subtree', `org-indent-item',
16826or `org-table-insert-column', depending on context.
28e5b051 16827See the individual commands for more information."
634a7d0b 16828 (interactive)
891f4676 16829 (cond
c8d0cf5c 16830 ((run-hook-with-args-until-success 'org-shiftmetaright-hook))
4b3a9ba7
CD
16831 ((org-at-table-p) (call-interactively 'org-table-insert-column))
16832 ((org-on-heading-p) (call-interactively 'org-demote-subtree))
86fbb8ca 16833 ((org-at-item-p) (call-interactively 'org-indent-item-tree))
65c439fd 16834 (t (org-modifier-cursor-error))))
634a7d0b 16835
891f4676 16836(defun org-shiftmetaup (&optional arg)
28e5b051 16837 "Move subtree up or kill table row.
7a368970
CD
16838Calls `org-move-subtree-up' or `org-table-kill-row' or
16839`org-move-item-up' depending on context. See the individual commands
16840for more information."
891f4676
RS
16841 (interactive "P")
16842 (cond
c8d0cf5c 16843 ((run-hook-with-args-until-success 'org-shiftmetaup-hook))
4b3a9ba7
CD
16844 ((org-at-table-p) (call-interactively 'org-table-kill-row))
16845 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
16846 ((org-at-item-p) (call-interactively 'org-move-item-up))
65c439fd 16847 (t (org-modifier-cursor-error))))
c8d0cf5c 16848
891f4676 16849(defun org-shiftmetadown (&optional arg)
28e5b051 16850 "Move subtree down or insert table row.
7a368970
CD
16851Calls `org-move-subtree-down' or `org-table-insert-row' or
16852`org-move-item-down', depending on context. See the individual
16853commands for more information."
891f4676
RS
16854 (interactive "P")
16855 (cond
c8d0cf5c 16856 ((run-hook-with-args-until-success 'org-shiftmetadown-hook))
4b3a9ba7
CD
16857 ((org-at-table-p) (call-interactively 'org-table-insert-row))
16858 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
16859 ((org-at-item-p) (call-interactively 'org-move-item-down))
65c439fd 16860 (t (org-modifier-cursor-error))))
891f4676 16861
86fbb8ca
CD
16862(defsubst org-hidden-tree-error ()
16863 (error
16864 "Hidden subtree, open with TAB or use subtree command M-S-<left>/<right>"))
16865
891f4676 16866(defun org-metaleft (&optional arg)
28e5b051
CD
16867 "Promote heading or move table column to left.
16868Calls `org-do-promote' or `org-table-move-column', depending on context.
7a368970 16869With no specific context, calls the Emacs default `backward-word'.
28e5b051 16870See the individual commands for more information."
891f4676
RS
16871 (interactive "P")
16872 (cond
c8d0cf5c 16873 ((run-hook-with-args-until-success 'org-metaleft-hook))
4b3a9ba7 16874 ((org-at-table-p) (org-call-with-arg 'org-table-move-column 'left))
c8d0cf5c
CD
16875 ((or (org-on-heading-p)
16876 (and (org-region-active-p)
16877 (save-excursion
16878 (goto-char (region-beginning))
16879 (org-on-heading-p))))
86fbb8ca 16880 (when (org-check-for-hidden 'headlines) (org-hidden-tree-error))
4b3a9ba7 16881 (call-interactively 'org-do-promote))
c8d0cf5c
CD
16882 ((or (org-at-item-p)
16883 (and (org-region-active-p)
16884 (save-excursion
16885 (goto-char (region-beginning))
16886 (org-at-item-p))))
86fbb8ca 16887 (when (org-check-for-hidden 'items) (org-hidden-tree-error))
c8d0cf5c 16888 (call-interactively 'org-outdent-item))
4b3a9ba7 16889 (t (call-interactively 'backward-word))))
634a7d0b 16890
891f4676 16891(defun org-metaright (&optional arg)
28e5b051
CD
16892 "Demote subtree or move table column to right.
16893Calls `org-do-demote' or `org-table-move-column', depending on context.
7a368970 16894With no specific context, calls the Emacs default `forward-word'.
28e5b051 16895See the individual commands for more information."
891f4676
RS
16896 (interactive "P")
16897 (cond
c8d0cf5c 16898 ((run-hook-with-args-until-success 'org-metaright-hook))
4b3a9ba7 16899 ((org-at-table-p) (call-interactively 'org-table-move-column))
c8d0cf5c
CD
16900 ((or (org-on-heading-p)
16901 (and (org-region-active-p)
16902 (save-excursion
16903 (goto-char (region-beginning))
16904 (org-on-heading-p))))
86fbb8ca 16905 (when (org-check-for-hidden 'headlines) (org-hidden-tree-error))
4b3a9ba7 16906 (call-interactively 'org-do-demote))
c8d0cf5c
CD
16907 ((or (org-at-item-p)
16908 (and (org-region-active-p)
16909 (save-excursion
16910 (goto-char (region-beginning))
16911 (org-at-item-p))))
86fbb8ca 16912 (when (org-check-for-hidden 'items) (org-hidden-tree-error))
c8d0cf5c 16913 (call-interactively 'org-indent-item))
4b3a9ba7 16914 (t (call-interactively 'forward-word))))
634a7d0b 16915
86fbb8ca
CD
16916(defun org-check-for-hidden (what)
16917 "Check if there are hidden headlines/items in the current visual line.
16918WHAT can be either `headlines' or `items'. If the current line is
16919an outline or item heading and it has a folded subtree below it,
16920this function returns t, nil otherwise."
16921 (let ((re (cond
16922 ((eq what 'headlines) (concat "^" org-outline-regexp))
16923 ((eq what 'items) (concat "^" (org-item-re t)))
16924 (t (error "This should not happen"))))
16925 beg end)
16926 (save-excursion
16927 (catch 'exit
16928 (unless (org-region-active-p)
16929 (setq beg (point-at-bol))
16930 (beginning-of-line 2)
16931 (while (and (not (eobp)) ;; this is like `next-line'
16932 (get-char-property (1- (point)) 'invisible))
16933 (beginning-of-line 2))
16934 (setq end (point))
16935 (goto-char beg)
16936 (goto-char (point-at-eol))
16937 (setq end (max end (point)))
16938 (while (re-search-forward re end t)
16939 (if (get-char-property (match-beginning 0) 'invisible)
16940 (throw 'exit t))))
16941 nil))))
16942
891f4676 16943(defun org-metaup (&optional arg)
28e5b051 16944 "Move subtree up or move table row up.
7a368970
CD
16945Calls `org-move-subtree-up' or `org-table-move-row' or
16946`org-move-item-up', depending on context. See the individual commands
16947for more information."
891f4676
RS
16948 (interactive "P")
16949 (cond
c8d0cf5c 16950 ((run-hook-with-args-until-success 'org-metaup-hook))
4b3a9ba7
CD
16951 ((org-at-table-p) (org-call-with-arg 'org-table-move-row 'up))
16952 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
16953 ((org-at-item-p) (call-interactively 'org-move-item-up))
03f3cf35 16954 (t (transpose-lines 1) (beginning-of-line -1))))
634a7d0b 16955
891f4676 16956(defun org-metadown (&optional arg)
28e5b051 16957 "Move subtree down or move table row down.
7a368970
CD
16958Calls `org-move-subtree-down' or `org-table-move-row' or
16959`org-move-item-down', depending on context. See the individual
16960commands for more information."
891f4676
RS
16961 (interactive "P")
16962 (cond
c8d0cf5c 16963 ((run-hook-with-args-until-success 'org-metadown-hook))
4b3a9ba7
CD
16964 ((org-at-table-p) (call-interactively 'org-table-move-row))
16965 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
16966 ((org-at-item-p) (call-interactively 'org-move-item-down))
03f3cf35 16967 (t (beginning-of-line 2) (transpose-lines 1) (beginning-of-line 0))))
891f4676
RS
16968
16969(defun org-shiftup (&optional arg)
4b3a9ba7 16970 "Increase item in timestamp or increase priority of current headline.
a3fbe8c4
CD
16971Calls `org-timestamp-up' or `org-priority-up', or `org-previous-item',
16972depending on context. See the individual commands for more information."
891f4676
RS
16973 (interactive "P")
16974 (cond
86fbb8ca 16975 ((run-hook-with-args-until-success 'org-shiftup-hook))
65c439fd
CD
16976 ((and org-support-shift-select (org-region-active-p))
16977 (org-call-for-shift-select 'previous-line))
0b8568f5
JW
16978 ((org-at-timestamp-p t)
16979 (call-interactively (if org-edit-timestamp-down-means-later
16980 'org-timestamp-down 'org-timestamp-up)))
65c439fd 16981 ((and (not (eq org-support-shift-select 'always))
c8d0cf5c 16982 org-enable-priority-commands
65c439fd
CD
16983 (org-on-heading-p))
16984 (call-interactively 'org-priority-up))
16985 ((and (not org-support-shift-select) (org-at-item-p))
16986 (call-interactively 'org-previous-item))
20908596 16987 ((org-clocktable-try-shift 'up arg))
86fbb8ca 16988 ((run-hook-with-args-until-success 'org-shiftup-final-hook))
65c439fd
CD
16989 (org-support-shift-select
16990 (org-call-for-shift-select 'previous-line))
16991 (t (org-shiftselect-error))))
891f4676
RS
16992
16993(defun org-shiftdown (&optional arg)
4b3a9ba7 16994 "Decrease item in timestamp or decrease priority of current headline.
a3fbe8c4
CD
16995Calls `org-timestamp-down' or `org-priority-down', or `org-next-item'
16996depending on context. See the individual commands for more information."
891f4676
RS
16997 (interactive "P")
16998 (cond
86fbb8ca 16999 ((run-hook-with-args-until-success 'org-shiftdown-hook))
65c439fd
CD
17000 ((and org-support-shift-select (org-region-active-p))
17001 (org-call-for-shift-select 'next-line))
0b8568f5
JW
17002 ((org-at-timestamp-p t)
17003 (call-interactively (if org-edit-timestamp-down-means-later
17004 'org-timestamp-up 'org-timestamp-down)))
65c439fd 17005 ((and (not (eq org-support-shift-select 'always))
c8d0cf5c 17006 org-enable-priority-commands
65c439fd
CD
17007 (org-on-heading-p))
17008 (call-interactively 'org-priority-down))
17009 ((and (not org-support-shift-select) (org-at-item-p))
17010 (call-interactively 'org-next-item))
20908596 17011 ((org-clocktable-try-shift 'down arg))
86fbb8ca 17012 ((run-hook-with-args-until-success 'org-shiftdown-final-hook))
c8d0cf5c 17013 (org-support-shift-select
65c439fd
CD
17014 (org-call-for-shift-select 'next-line))
17015 (t (org-shiftselect-error))))
891f4676 17016
20908596 17017(defun org-shiftright (&optional arg)
ce4fdcb9
CD
17018 "Cycle the thing at point or in the current line, depending on context.
17019Depending on context, this does one of the following:
17020
17021- switch a timestamp at point one day into the future
17022- on a headline, switch to the next TODO keyword.
17023- on an item, switch entire list to the next bullet type
17024- on a property line, switch to the next allowed value
17025- on a clocktable definition line, move time block into the future"
20908596 17026 (interactive "P")
f425a6ea 17027 (cond
86fbb8ca 17028 ((run-hook-with-args-until-success 'org-shiftright-hook))
65c439fd
CD
17029 ((and org-support-shift-select (org-region-active-p))
17030 (org-call-for-shift-select 'forward-char))
8df0de1c 17031 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-up-day))
65c439fd
CD
17032 ((and (not (eq org-support-shift-select 'always))
17033 (org-on-heading-p))
c8d0cf5c
CD
17034 (let ((org-inhibit-logging
17035 (not org-treat-S-cursor-todo-selection-as-state-change))
17036 (org-inhibit-blocking
17037 (not org-treat-S-cursor-todo-selection-as-state-change)))
17038 (org-call-with-arg 'org-todo 'right)))
65c439fd
CD
17039 ((or (and org-support-shift-select
17040 (not (eq org-support-shift-select 'always))
17041 (org-at-item-bullet-p))
17042 (and (not org-support-shift-select) (org-at-item-p)))
17043 (org-call-with-arg 'org-cycle-list-bullet nil))
17044 ((and (not (eq org-support-shift-select 'always))
17045 (org-at-property-p))
17046 (call-interactively 'org-property-next-allowed-value))
20908596 17047 ((org-clocktable-try-shift 'right arg))
86fbb8ca 17048 ((run-hook-with-args-until-success 'org-shiftright-final-hook))
c8d0cf5c 17049 (org-support-shift-select
65c439fd
CD
17050 (org-call-for-shift-select 'forward-char))
17051 (t (org-shiftselect-error))))
f425a6ea 17052
20908596 17053(defun org-shiftleft (&optional arg)
ce4fdcb9
CD
17054 "Cycle the thing at point or in the current line, depending on context.
17055Depending on context, this does one of the following:
17056
17057- switch a timestamp at point one day into the past
17058- on a headline, switch to the previous TODO keyword.
17059- on an item, switch entire list to the previous bullet type
17060- on a property line, switch to the previous allowed value
17061- on a clocktable definition line, move time block into the past"
20908596 17062 (interactive "P")
f425a6ea 17063 (cond
86fbb8ca 17064 ((run-hook-with-args-until-success 'org-shiftleft-hook))
65c439fd
CD
17065 ((and org-support-shift-select (org-region-active-p))
17066 (org-call-for-shift-select 'backward-char))
8df0de1c 17067 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-down-day))
65c439fd
CD
17068 ((and (not (eq org-support-shift-select 'always))
17069 (org-on-heading-p))
c8d0cf5c
CD
17070 (let ((org-inhibit-logging
17071 (not org-treat-S-cursor-todo-selection-as-state-change))
17072 (org-inhibit-blocking
17073 (not org-treat-S-cursor-todo-selection-as-state-change)))
17074 (org-call-with-arg 'org-todo 'left)))
65c439fd
CD
17075 ((or (and org-support-shift-select
17076 (not (eq org-support-shift-select 'always))
17077 (org-at-item-bullet-p))
17078 (and (not org-support-shift-select) (org-at-item-p)))
17079 (org-call-with-arg 'org-cycle-list-bullet 'previous))
17080 ((and (not (eq org-support-shift-select 'always))
17081 (org-at-property-p))
7d58338e 17082 (call-interactively 'org-property-previous-allowed-value))
20908596 17083 ((org-clocktable-try-shift 'left arg))
86fbb8ca 17084 ((run-hook-with-args-until-success 'org-shiftleft-final-hook))
c8d0cf5c 17085 (org-support-shift-select
65c439fd
CD
17086 (org-call-for-shift-select 'backward-char))
17087 (t (org-shiftselect-error))))
f425a6ea 17088
a3fbe8c4
CD
17089(defun org-shiftcontrolright ()
17090 "Switch to next TODO set."
17091 (interactive)
17092 (cond
65c439fd
CD
17093 ((and org-support-shift-select (org-region-active-p))
17094 (org-call-for-shift-select 'forward-word))
17095 ((and (not (eq org-support-shift-select 'always))
17096 (org-on-heading-p))
17097 (org-call-with-arg 'org-todo 'nextset))
17098 (org-support-shift-select
17099 (org-call-for-shift-select 'forward-word))
17100 (t (org-shiftselect-error))))
a3fbe8c4
CD
17101
17102(defun org-shiftcontrolleft ()
17103 "Switch to previous TODO set."
17104 (interactive)
17105 (cond
65c439fd
CD
17106 ((and org-support-shift-select (org-region-active-p))
17107 (org-call-for-shift-select 'backward-word))
17108 ((and (not (eq org-support-shift-select 'always))
17109 (org-on-heading-p))
17110 (org-call-with-arg 'org-todo 'previousset))
17111 (org-support-shift-select
17112 (org-call-for-shift-select 'backward-word))
17113 (t (org-shiftselect-error))))
a3fbe8c4
CD
17114
17115(defun org-ctrl-c-ret ()
17116 "Call `org-table-hline-and-move' or `org-insert-heading' dep. on context."
17117 (interactive)
17118 (cond
17119 ((org-at-table-p) (call-interactively 'org-table-hline-and-move))
17120 (t (call-interactively 'org-insert-heading))))
17121
634a7d0b 17122(defun org-copy-special ()
28e5b051
CD
17123 "Copy region in table or copy current subtree.
17124Calls `org-table-copy' or `org-copy-subtree', depending on context.
17125See the individual commands for more information."
634a7d0b 17126 (interactive)
64f72ae1 17127 (call-interactively
9acdaa21 17128 (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree)))
891f4676 17129
634a7d0b 17130(defun org-cut-special ()
28e5b051
CD
17131 "Cut region in table or cut current subtree.
17132Calls `org-table-copy' or `org-cut-subtree', depending on context.
17133See the individual commands for more information."
634a7d0b 17134 (interactive)
9acdaa21
CD
17135 (call-interactively
17136 (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree)))
891f4676
RS
17137
17138(defun org-paste-special (arg)
28e5b051
CD
17139 "Paste rectangular region into table, or past subtree relative to level.
17140Calls `org-table-paste-rectangle' or `org-paste-subtree', depending on context.
17141See the individual commands for more information."
891f4676
RS
17142 (interactive "P")
17143 (if (org-at-table-p)
634a7d0b 17144 (org-table-paste-rectangle)
891f4676
RS
17145 (org-paste-subtree arg)))
17146
86fbb8ca 17147(defun org-edit-special (&optional arg)
b349f79f
CD
17148 "Call a special editor for the stuff at point.
17149When at a table, call the formula editor with `org-table-edit-formulas'.
17150When at the first line of an src example, call `org-edit-src-code'.
17151When in an #+include line, visit the include file. Otherwise call
17152`ffap' to visit the file at point."
17153 (interactive)
86fbb8ca
CD
17154 ;; possibly prep session before editing source
17155 (when arg
17156 (let* ((info (org-babel-get-src-block-info))
17157 (lang (nth 0 info))
17158 (params (nth 2 info))
17159 (session (cdr (assoc :session params))))
17160 (when (and info session) ;; we are in a source-code block with a session
17161 (funcall
17162 (intern (concat "org-babel-prep-session:" lang)) session params))))
17163 (cond ;; proceed with `org-edit-special'
b349f79f
CD
17164 ((save-excursion
17165 (beginning-of-line 1)
17166 (looking-at "\\(?:#\\+\\(?:setupfile\\|include\\):?[ \t]+\"?\\|[ \t]*<include\\>.*?file=\"\\)\\([^\"\n>]+\\)"))
17167 (find-file (org-trim (match-string 1))))
17168 ((org-edit-src-code))
621f83e4 17169 ((org-edit-fixed-width-region))
86fbb8ca
CD
17170 ((org-at-table.el-p)
17171 (org-edit-src-code))
acedf35c
CD
17172 ((or (org-at-table-p)
17173 (save-excursion
17174 (beginning-of-line 1)
17175 (looking-at "[ \t]*#\\+TBLFM:")))
86fbb8ca 17176 (call-interactively 'org-table-edit-formulas))
b349f79f
CD
17177 (t (call-interactively 'ffap))))
17178
891f4676 17179(defun org-ctrl-c-ctrl-c (&optional arg)
a4b39e39
CD
17180 "Set tags in headline, or update according to changed information at point.
17181
17182This command does many different things, depending on context:
17183
c8d0cf5c
CD
17184- If a function in `org-ctrl-c-ctrl-c-hook' recognizes this location,
17185 this is what we do.
17186
54a0dee5
CD
17187- If the cursor is on a statistics cookie, update it.
17188
a4b39e39
CD
17189- If the cursor is in a headline, prompt for tags and insert them
17190 into the current line, aligned to `org-tags-column'. When called
17191 with prefix arg, realign all tags in the current buffer.
17192
17193- If the cursor is in one of the special #+KEYWORD lines, this
17194 triggers scanning the buffer for these lines and updating the
edd21304 17195 information.
a4b39e39
CD
17196
17197- If the cursor is inside a table, realign the table. This command
17198 works even if the automatic table editor has been turned off.
17199
17200- If the cursor is on a #+TBLFM line, re-apply the formulas to
17201 the entire table.
17202
0bd48b37
CD
17203- If the cursor is at a footnote reference or definition, jump to
17204 the corresponding definition or references, respectively.
17205
15841868
JW
17206- If the cursor is a the beginning of a dynamic block, update it.
17207
afe98dfa 17208- If the current buffer is a capture buffer, close note and file it.
a4b39e39 17209
afe98dfa
CD
17210- If the cursor is on a <<<target>>>, update radio targets and
17211 corresponding links in this buffer.
a4b39e39
CD
17212
17213- If the cursor is on a numbered item in a plain list, renumber the
8c6fb58b
CD
17214 ordered list.
17215
86fbb8ca
CD
17216- If the cursor is on a checkbox, toggle it.
17217
17218- If the cursor is on a code block, evaluate it. The variable
17219 `org-confirm-babel-evaluate' can be used to control prompting
17220 before code block evaluation, by default every code block
17221 evaluation requires confirmation. Code block evaluation can be
17222 inhibited by setting `org-babel-no-eval-on-ctrl-c-ctrl-c'."
891f4676
RS
17223 (interactive "P")
17224 (let ((org-enable-table-editor t))
17225 (cond
20908596 17226 ((or (and (boundp 'org-clock-overlays) org-clock-overlays)
3278a016 17227 org-occur-highlights
6769c0dc 17228 org-latex-fragment-image-overlays)
0bd48b37 17229 (and (boundp 'org-clock-overlays) (org-clock-remove-overlays))
edd21304 17230 (org-remove-occur-highlights)
6769c0dc
CD
17231 (org-remove-latex-fragment-image-overlays)
17232 (message "Temporary highlights/overlays removed from current buffer"))
ab27a4a0
CD
17233 ((and (local-variable-p 'org-finish-function (current-buffer))
17234 (fboundp org-finish-function))
17235 (funcall org-finish-function))
c8d0cf5c 17236 ((run-hook-with-args-until-success 'org-ctrl-c-ctrl-c-hook))
ed21c5c8
CD
17237 ((or (looking-at org-property-start-re)
17238 (org-at-property-p))
7d58338e 17239 (call-interactively 'org-property-action))
4b3a9ba7 17240 ((org-on-target-p) (call-interactively 'org-update-radio-target-regexp))
54a0dee5
CD
17241 ((and (org-in-regexp "\\[\\([0-9]*%\\|[0-9]*/[0-9]*\\)\\]")
17242 (or (org-on-heading-p) (org-at-item-p)))
17243 (call-interactively 'org-update-statistics-cookies))
4b3a9ba7 17244 ((org-on-heading-p) (call-interactively 'org-set-tags))
891f4676 17245 ((org-at-table.el-p)
ed21c5c8 17246 (message "Use C-c ' to edit table.el tables"))
891f4676 17247 ((org-at-table-p)
9acdaa21
CD
17248 (org-table-maybe-eval-formula)
17249 (if arg
4b3a9ba7 17250 (call-interactively 'org-table-recalculate)
c8d16429 17251 (org-table-maybe-recalculate-line))
acedf35c
CD
17252 (call-interactively 'org-table-align)
17253 (orgtbl-send-table 'maybe))
0bd48b37
CD
17254 ((or (org-footnote-at-reference-p)
17255 (org-footnote-at-definition-p))
17256 (call-interactively 'org-footnote-action))
4b3a9ba7 17257 ((org-at-item-checkbox-p)
afe98dfa 17258 (call-interactively 'org-list-repair)
86fbb8ca
CD
17259 (call-interactively 'org-toggle-checkbox)
17260 (org-list-send-list 'maybe))
7a368970 17261 ((org-at-item-p)
afe98dfa
CD
17262 (call-interactively 'org-list-repair)
17263 (when arg (call-interactively 'org-toggle-checkbox))
86fbb8ca 17264 (org-list-send-list 'maybe))
8d642074 17265 ((save-excursion (beginning-of-line 1) (looking-at org-dblock-start-re))
15841868
JW
17266 ;; Dynamic block
17267 (beginning-of-line 1)
621f83e4 17268 (save-excursion (org-update-dblock)))
c8d0cf5c
CD
17269 ((save-excursion
17270 (beginning-of-line 1)
17271 (looking-at "[ \t]*#\\+\\([A-Z]+\\)"))
9acdaa21
CD
17272 (cond
17273 ((equal (match-string 1) "TBLFM")
c8d16429
CD
17274 ;; Recalculate the table before this line
17275 (save-excursion
17276 (beginning-of-line 1)
17277 (skip-chars-backward " \r\n\t")
4b3a9ba7 17278 (if (org-at-table-p)
8d642074 17279 (org-call-with-arg 'org-table-recalculate (or arg t)))))
9acdaa21 17280 (t
ed21c5c8
CD
17281 (let ((org-inhibit-startup-visibility-stuff t)
17282 (org-startup-align-all-tables nil))
17283 (org-save-outline-visibility 'use-markers (org-mode-restart)))
b349f79f 17284 (message "Local setup has been refreshed"))))
c8d0cf5c 17285 ((org-clock-update-time-maybe))
f924a367 17286 (t (error "C-c C-c can do nothing useful at this location")))))
891f4676 17287
28e5b051
CD
17288(defun org-mode-restart ()
17289 "Restart Org-mode, to scan again for special lines.
17290Also updates the keyword regular expressions."
17291 (interactive)
b349f79f
CD
17292 (org-mode)
17293 (message "Org-mode restarted"))
28e5b051 17294
03f3cf35 17295(defun org-kill-note-or-show-branches ()
a0d892d4 17296 "If this is a Note buffer, abort storing the note. Else call `show-branches'."
03f3cf35
JW
17297 (interactive)
17298 (if (not org-finish-function)
86fbb8ca
CD
17299 (progn
17300 (hide-subtree)
17301 (call-interactively 'show-branches))
03f3cf35
JW
17302 (let ((org-note-abort t))
17303 (funcall org-finish-function))))
17304
8c6fb58b 17305(defun org-return (&optional indent)
28e5b051
CD
17306 "Goto next table row or insert a newline.
17307Calls `org-table-next-row' or `newline', depending on context.
17308See the individual commands for more information."
634a7d0b 17309 (interactive)
891f4676 17310 (cond
8c6fb58b 17311 ((bobp) (if indent (newline-and-indent) (newline)))
c8d0cf5c
CD
17312 ((org-at-table-p)
17313 (org-table-justify-field-maybe)
17314 (call-interactively 'org-table-next-row))
17315 ((and org-return-follows-link
17316 (eq (get-text-property (point) 'face) 'org-link))
17317 (call-interactively 'org-open-at-point))
2a57416f
CD
17318 ((and (org-at-heading-p)
17319 (looking-at
afe98dfa 17320 (org-re "\\([ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)[ \t]*$")))
2a57416f
CD
17321 (org-show-entry)
17322 (end-of-line 1)
17323 (newline))
8c6fb58b 17324 (t (if indent (newline-and-indent) (newline)))))
891f4676 17325
8c6fb58b 17326(defun org-return-indent ()
8c6fb58b
CD
17327 "Goto next table row or insert a newline and indent.
17328Calls `org-table-next-row' or `newline-and-indent', depending on
17329context. See the individual commands for more information."
2a57416f 17330 (interactive)
8c6fb58b 17331 (org-return t))
03f3cf35 17332
2a57416f
CD
17333(defun org-ctrl-c-star ()
17334 "Compute table, or change heading status of lines.
0bd48b37
CD
17335Calls `org-table-recalculate' or `org-toggle-heading',
17336depending on context."
2a57416f
CD
17337 (interactive)
17338 (cond
17339 ((org-at-table-p)
17340 (call-interactively 'org-table-recalculate))
0bd48b37 17341 (t
2a57416f 17342 ;; Convert all lines in region to list items
0bd48b37 17343 (call-interactively 'org-toggle-heading))))
2a57416f 17344
38f8646b 17345(defun org-ctrl-c-minus ()
2a57416f
CD
17346 "Insert separator line in table or modify bullet status of line.
17347Also turns a plain line or a region of lines into list items.
0bd48b37 17348Calls `org-table-insert-hline', `org-toggle-item', or
2a57416f 17349`org-cycle-list-bullet', depending on context."
38f8646b
CD
17350 (interactive)
17351 (cond
17352 ((org-at-table-p)
17353 (call-interactively 'org-table-insert-hline))
2a57416f 17354 ((org-region-active-p)
0bd48b37 17355 (call-interactively 'org-toggle-item))
38f8646b
CD
17356 ((org-in-item-p)
17357 (call-interactively 'org-cycle-list-bullet))
0bd48b37
CD
17358 (t
17359 (call-interactively 'org-toggle-item))))
17360
17361(defun org-toggle-item ()
17362 "Convert headings or normal lines to items, items to normal lines.
17363If there is no active region, only the current line is considered.
17364
17365If the first line in the region is a headline, convert all headlines to items.
17366
17367If the first line in the region is an item, convert all items to normal lines.
17368
17369If the first line is normal text, add an item bullet to each line."
17370 (interactive)
17371 (let (l2 l beg end)
17372 (if (org-region-active-p)
17373 (setq beg (region-beginning) end (region-end))
17374 (setq beg (point-at-bol)
17375 end (min (1+ (point-at-eol)) (point-max))))
2a57416f
CD
17376 (save-excursion
17377 (goto-char end)
17378 (setq l2 (org-current-line))
17379 (goto-char beg)
17380 (beginning-of-line 1)
17381 (setq l (1- (org-current-line)))
17382 (if (org-at-item-p)
17383 ;; We already have items, de-itemize
17384 (while (< (setq l (1+ l)) l2)
17385 (when (org-at-item-p)
afe98dfa
CD
17386 (skip-chars-forward " \t")
17387 (delete-region (point) (match-end 0)))
2a57416f 17388 (beginning-of-line 2))
0bd48b37
CD
17389 (if (org-on-heading-p)
17390 ;; Headings, convert to items
17391 (while (< (setq l (1+ l)) l2)
17392 (if (looking-at org-outline-regexp)
afe98dfa 17393 (replace-match (org-list-bullet-string "-") t t))
0bd48b37
CD
17394 (beginning-of-line 2))
17395 ;; normal lines, turn them into items
17396 (while (< (setq l (1+ l)) l2)
17397 (unless (org-at-item-p)
17398 (if (looking-at "\\([ \t]*\\)\\(\\S-\\)")
afe98dfa
CD
17399 (replace-match
17400 (concat "\\1" (org-list-bullet-string "-") "\\2"))))
0bd48b37
CD
17401 (beginning-of-line 2)))))))
17402
17403(defun org-toggle-heading (&optional nstars)
17404 "Convert headings to normal text, or items or text to headings.
17405If there is no active region, only the current line is considered.
17406
17407If the first line is a heading, remove the stars from all headlines
17408in the region.
17409
c8d0cf5c
CD
17410If the first line is a plain list item, turn all plain list items
17411into headings.
0bd48b37 17412
c8d0cf5c
CD
17413If the first line is a normal line, turn each and every line in the
17414region into a heading.
0bd48b37
CD
17415
17416When converting a line into a heading, the number of stars is chosen
c8d0cf5c
CD
17417such that the lines become children of the current entry. However,
17418when a prefix argument is given, its value determines the number of
17419stars to add."
0bd48b37
CD
17420 (interactive "P")
17421 (let (l2 l itemp beg end)
17422 (if (org-region-active-p)
17423 (setq beg (region-beginning) end (region-end))
17424 (setq beg (point-at-bol)
17425 end (min (1+ (point-at-eol)) (point-max))))
2a57416f
CD
17426 (save-excursion
17427 (goto-char end)
17428 (setq l2 (org-current-line))
17429 (goto-char beg)
17430 (beginning-of-line 1)
17431 (setq l (1- (org-current-line)))
17432 (if (org-on-heading-p)
17433 ;; We already have headlines, de-star them
17434 (while (< (setq l (1+ l)) l2)
17435 (when (org-on-heading-p t)
17436 (and (looking-at outline-regexp) (replace-match "")))
17437 (beginning-of-line 2))
0bd48b37
CD
17438 (setq itemp (org-at-item-p))
17439 (let* ((stars
17440 (if nstars
17441 (make-string (prefix-numeric-value current-prefix-arg)
17442 ?*)
17443 (save-excursion
c8d0cf5c
CD
17444 (if (re-search-backward org-complex-heading-regexp nil t)
17445 (match-string 1) ""))))
17446 (add-stars (cond (nstars "")
17447 ((equal stars "") "*")
17448 (org-odd-levels-only "**")
17449 (t "*")))
0bd48b37 17450 (rpl (concat stars add-stars " ")))
2a57416f 17451 (while (< (setq l (1+ l)) l2)
0bd48b37
CD
17452 (if itemp
17453 (and (org-at-item-p) (replace-match rpl t t))
17454 (unless (org-on-heading-p)
17455 (if (looking-at "\\([ \t]*\\)\\(\\S-\\)")
17456 (replace-match (concat rpl (match-string 2))))))
2a57416f 17457 (beginning-of-line 2)))))))
5bf7807a 17458
791d856f 17459(defun org-meta-return (&optional arg)
28e5b051
CD
17460 "Insert a new heading or wrap a region in a table.
17461Calls `org-insert-heading' or `org-table-wrap-region', depending on context.
17462See the individual commands for more information."
791d856f
CD
17463 (interactive "P")
17464 (cond
c8d0cf5c 17465 ((run-hook-with-args-until-success 'org-metareturn-hook))
791d856f 17466 ((org-at-table-p)
4b3a9ba7
CD
17467 (call-interactively 'org-table-wrap-region))
17468 (t (call-interactively 'org-insert-heading))))
891f4676
RS
17469
17470;;; Menu entries
17471
891f4676 17472;; Define the Org-mode menus
9acdaa21
CD
17473(easy-menu-define org-tbl-menu org-mode-map "Tbl menu"
17474 '("Tbl"
20908596 17475 ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p)]
9acdaa21
CD
17476 ["Next Field" org-cycle (org-at-table-p)]
17477 ["Previous Field" org-shifttab (org-at-table-p)]
17478 ["Next Row" org-return (org-at-table-p)]
17479 "--"
17480 ["Blank Field" org-table-blank-field (org-at-table-p)]
ab27a4a0 17481 ["Edit Field" org-table-edit-field (org-at-table-p)]
9acdaa21
CD
17482 ["Copy Field from Above" org-table-copy-down (org-at-table-p)]
17483 "--"
17484 ("Column"
17485 ["Move Column Left" org-metaleft (org-at-table-p)]
17486 ["Move Column Right" org-metaright (org-at-table-p)]
17487 ["Delete Column" org-shiftmetaleft (org-at-table-p)]
d3f4dbe8 17488 ["Insert Column" org-shiftmetaright (org-at-table-p)])
9acdaa21
CD
17489 ("Row"
17490 ["Move Row Up" org-metaup (org-at-table-p)]
17491 ["Move Row Down" org-metadown (org-at-table-p)]
17492 ["Delete Row" org-shiftmetaup (org-at-table-p)]
17493 ["Insert Row" org-shiftmetadown (org-at-table-p)]
e0e66b8e 17494 ["Sort lines in region" org-table-sort-lines (org-at-table-p)]
9acdaa21 17495 "--"
38f8646b 17496 ["Insert Hline" org-ctrl-c-minus (org-at-table-p)])
9acdaa21
CD
17497 ("Rectangle"
17498 ["Copy Rectangle" org-copy-special (org-at-table-p)]
17499 ["Cut Rectangle" org-cut-special (org-at-table-p)]
17500 ["Paste Rectangle" org-paste-special (org-at-table-p)]
17501 ["Fill Rectangle" org-table-wrap-region (org-at-table-p)])
17502 "--"
17503 ("Calculate"
c4f9780e 17504 ["Set Column Formula" org-table-eval-formula (org-at-table-p)]
d3f4dbe8 17505 ["Set Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
b349f79f 17506 ["Edit Formulas" org-edit-special (org-at-table-p)]
c4f9780e 17507 "--"
9acdaa21
CD
17508 ["Recalculate line" org-table-recalculate (org-at-table-p)]
17509 ["Recalculate all" (lambda () (interactive) (org-table-recalculate '(4))) :active (org-at-table-p) :keys "C-u C-c *"]
d3f4dbe8
CD
17510 ["Iterate all" (lambda () (interactive) (org-table-recalculate '(16))) :active (org-at-table-p) :keys "C-u C-u C-c *"]
17511 "--"
9acdaa21 17512 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks (org-at-table-p)]
c4f9780e 17513 "--"
64f72ae1 17514 ["Sum Column/Rectangle" org-table-sum
9acdaa21
CD
17515 (or (org-at-table-p) (org-region-active-p))]
17516 ["Which Column?" org-table-current-column (org-at-table-p)])
17517 ["Debug Formulas"
d3f4dbe8 17518 org-table-toggle-formula-debugger
20908596 17519 :style toggle :selected (org-bound-and-true-p org-table-formula-debug)]
d3f4dbe8
CD
17520 ["Show Col/Row Numbers"
17521 org-table-toggle-coordinate-overlays
20908596
CD
17522 :style toggle
17523 :selected (org-bound-and-true-p org-table-overlay-coordinates)]
9acdaa21 17524 "--"
9acdaa21 17525 ["Create" org-table-create (and (not (org-at-table-p))
c8d16429 17526 org-enable-table-editor)]
ab27a4a0 17527 ["Convert Region" org-table-convert-region (not (org-at-table-p 'any))]
9acdaa21
CD
17528 ["Import from File" org-table-import (not (org-at-table-p))]
17529 ["Export to File" org-table-export (org-at-table-p)]
17530 "--"
17531 ["Create/Convert from/to table.el" org-table-create-with-table.el t]))
17532
891f4676
RS
17533(easy-menu-define org-org-menu org-mode-map "Org menu"
17534 '("Org"
3278a016 17535 ("Show/Hide"
20908596
CD
17536 ["Cycle Visibility" org-cycle :active (or (bobp) (outline-on-heading-p))]
17537 ["Cycle Global Visibility" org-shifttab :active (not (org-at-table-p))]
17538 ["Sparse Tree..." org-sparse-tree t]
3278a016 17539 ["Reveal Context" org-reveal t]
d3f4dbe8
CD
17540 ["Show All" show-all t]
17541 "--"
17542 ["Subtree to indirect buffer" org-tree-to-indirect-buffer t])
891f4676
RS
17543 "--"
17544 ["New Heading" org-insert-heading t]
17545 ("Navigate Headings"
17546 ["Up" outline-up-heading t]
17547 ["Next" outline-next-visible-heading t]
17548 ["Previous" outline-previous-visible-heading t]
17549 ["Next Same Level" outline-forward-same-level t]
17550 ["Previous Same Level" outline-backward-same-level t]
17551 "--"
374585c9 17552 ["Jump" org-goto t])
891f4676 17553 ("Edit Structure"
35fb9989
CD
17554 ["Move Subtree Up" org-shiftmetaup (not (org-at-table-p))]
17555 ["Move Subtree Down" org-shiftmetadown (not (org-at-table-p))]
891f4676
RS
17556 "--"
17557 ["Copy Subtree" org-copy-special (not (org-at-table-p))]
17558 ["Cut Subtree" org-cut-special (not (org-at-table-p))]
17559 ["Paste Subtree" org-paste-special (not (org-at-table-p))]
17560 "--"
c8d0cf5c
CD
17561 ["Clone subtree, shift time" org-clone-subtree-with-time-shift t]
17562 "--"
891f4676
RS
17563 ["Promote Heading" org-metaleft (not (org-at-table-p))]
17564 ["Promote Subtree" org-shiftmetaleft (not (org-at-table-p))]
17565 ["Demote Heading" org-metaright (not (org-at-table-p))]
30313b90
CD
17566 ["Demote Subtree" org-shiftmetaright (not (org-at-table-p))]
17567 "--"
d3f4dbe8
CD
17568 ["Sort Region/Children" org-sort (not (org-at-table-p))]
17569 "--"
4ed31842
CD
17570 ["Convert to odd levels" org-convert-to-odd-levels t]
17571 ["Convert to odd/even levels" org-convert-to-oddeven-levels t])
a3fbe8c4 17572 ("Editing"
b349f79f 17573 ["Emphasis..." org-emphasize t]
0bd48b37
CD
17574 ["Edit Source Example" org-edit-special t]
17575 "--"
17576 ["Footnote new/jump" org-footnote-action t]
17577 ["Footnote extra" (org-footnote-action t) :active t :keys "C-u C-c C-x f"])
6769c0dc 17578 ("Archive"
8bfe682a 17579 ["Archive (default method)" org-archive-subtree-default t]
6769c0dc 17580 "--"
8bfe682a
CD
17581 ["Move Subtree to Archive file" org-advertized-archive-subtree t]
17582 ["Toggle ARCHIVE tag" org-toggle-archive-tag t]
17583 ["Move subtree to Archive sibling" org-archive-to-archive-sibling t]
d3f4dbe8 17584 )
891f4676 17585 "--"
c8d0cf5c
CD
17586 ("Hyperlinks"
17587 ["Store Link (Global)" org-store-link t]
17588 ["Find existing link to here" org-occur-link-in-agenda-files t]
17589 ["Insert Link" org-insert-link t]
17590 ["Follow Link" org-open-at-point t]
17591 "--"
17592 ["Next link" org-next-link t]
17593 ["Previous link" org-previous-link t]
17594 "--"
17595 ["Descriptive Links"
86fbb8ca 17596 (progn (add-to-invisibility-spec '(org-link)) (org-restart-font-lock))
c8d0cf5c
CD
17597 :style radio
17598 :selected (member '(org-link) buffer-invisibility-spec)]
17599 ["Literal Links"
17600 (progn
17601 (org-remove-from-invisibility-spec '(org-link)) (org-restart-font-lock))
17602 :style radio
17603 :selected (not (member '(org-link) buffer-invisibility-spec))])
17604 "--"
35fb9989 17605 ("TODO Lists"
891f4676 17606 ["TODO/DONE/-" org-todo t]
5137195a
CD
17607 ("Select keyword"
17608 ["Next keyword" org-shiftright (org-on-heading-p)]
17609 ["Previous keyword" org-shiftleft (org-on-heading-p)]
acedf35c 17610 ["Complete Keyword" pcomplete (assq :todo-keyword (org-context))]
a3fbe8c4
CD
17611 ["Next keyword set" org-shiftcontrolright (and (> (length org-todo-sets) 1) (org-on-heading-p))]
17612 ["Previous keyword set" org-shiftcontrolright (and (> (length org-todo-sets) 1) (org-on-heading-p))])
86fbb8ca
CD
17613 ["Show TODO Tree" org-show-todo-tree :active t :keys "C-c / t"]
17614 ["Global TODO list" org-todo-list :active t :keys "C-c a t"]
891f4676 17615 "--"
a2a2e7fb
CD
17616 ["Enforce dependencies" (customize-variable 'org-enforce-todo-dependencies)
17617 :selected org-enforce-todo-dependencies :style toggle :active t]
17618 "Settings for tree at point"
17619 ["Do Children sequentially" org-toggle-ordered-property :style radio
17620 :selected (ignore-errors (org-entry-get nil "ORDERED"))
17621 :active org-enforce-todo-dependencies :keys "C-c C-x o"]
17622 ["Do Children parallel" org-toggle-ordered-property :style radio
17623 :selected (ignore-errors (not (org-entry-get nil "ORDERED")))
17624 :active org-enforce-todo-dependencies :keys "C-c C-x o"]
17625 "--"
35fb9989
CD
17626 ["Set Priority" org-priority t]
17627 ["Priority Up" org-shiftup t]
c8d0cf5c
CD
17628 ["Priority Down" org-shiftdown t]
17629 "--"
17630 ["Get news from all feeds" org-feed-update-all t]
17631 ["Go to the inbox of a feed..." org-feed-goto-inbox t]
17632 ["Customize feeds" (customize-variable 'org-feed-alist) t])
38f8646b 17633 ("TAGS and Properties"
579d2d62 17634 ["Set Tags" org-set-tags-command t]
fd8d5da9 17635 ["Change tag in region" org-change-tag-in-region (org-region-active-p)]
03f3cf35 17636 "--"
fd8d5da9 17637 ["Set property" org-set-property t]
03f3cf35
JW
17638 ["Column view of properties" org-columns t]
17639 ["Insert Column View DBlock" org-insert-columns-dblock t])
891f4676
RS
17640 ("Dates and Scheduling"
17641 ["Timestamp" org-time-stamp t]
28e5b051 17642 ["Timestamp (inactive)" org-time-stamp-inactive t]
891f4676 17643 ("Change Date"
3278a016
CD
17644 ["1 Day Later" org-shiftright t]
17645 ["1 Day Earlier" org-shiftleft t]
35fb9989
CD
17646 ["1 ... Later" org-shiftup t]
17647 ["1 ... Earlier" org-shiftdown t])
891f4676
RS
17648 ["Compute Time Range" org-evaluate-time-range t]
17649 ["Schedule Item" org-schedule t]
17650 ["Deadline" org-deadline t]
17651 "--"
3278a016
CD
17652 ["Custom time format" org-toggle-time-stamp-overlays
17653 :style radio :selected org-display-custom-times]
17654 "--"
891f4676 17655 ["Goto Calendar" org-goto-calendar t]
ff4be292
CD
17656 ["Date from Calendar" org-date-from-calendar t]
17657 "--"
0bd48b37
CD
17658 ["Start/Restart Timer" org-timer-start t]
17659 ["Pause/Continue Timer" org-timer-pause-or-continue t]
17660 ["Stop Timer" org-timer-pause-or-continue :active t :keys "C-u C-c C-x ,"]
17661 ["Insert Timer String" org-timer t]
17662 ["Insert Timer Item" org-timer-item t])
edd21304 17663 ("Logging work"
c8d0cf5c
CD
17664 ["Clock in" org-clock-in :active t :keys "C-c C-x C-i"]
17665 ["Switch task" (lambda () (interactive) (org-clock-in '(4))) :active t :keys "C-u C-c C-x C-i"]
edd21304
CD
17666 ["Clock out" org-clock-out t]
17667 ["Clock cancel" org-clock-cancel t]
c8d0cf5c
CD
17668 "--"
17669 ["Mark as default task" org-clock-mark-default-task t]
17670 ["Clock in, mark as default" (lambda () (interactive) (org-clock-in '(16))) :active t :keys "C-u C-u C-c C-x C-i"]
15841868 17671 ["Goto running clock" org-clock-goto t]
c8d0cf5c 17672 "--"
edd21304 17673 ["Display times" org-clock-display t]
0fee8d6e 17674 ["Create clock table" org-clock-report t]
edd21304
CD
17675 "--"
17676 ["Record DONE time"
17677 (progn (setq org-log-done (not org-log-done))
17678 (message "Switching to %s will %s record a timestamp"
a3fbe8c4 17679 (car org-done-keywords)
edd21304
CD
17680 (if org-log-done "automatically" "not")))
17681 :style toggle :selected org-log-done])
891f4676 17682 "--"
3278a016 17683 ["Agenda Command..." org-agenda t]
8c6fb58b 17684 ["Set Restriction Lock" org-agenda-set-restriction-lock t]
d924f2e5
CD
17685 ("File List for Agenda")
17686 ("Special views current file"
4da1a99d
CD
17687 ["TODO Tree" org-show-todo-tree t]
17688 ["Check Deadlines" org-check-deadlines t]
17689 ["Timeline" org-timeline t]
c8d0cf5c 17690 ["Tags/Property tree" org-match-sparse-tree t])
891f4676 17691 "--"
3278a016 17692 ["Export/Publish..." org-export t]
6769c0dc 17693 ("LaTeX"
c44f0d75 17694 ["Org CDLaTeX mode" org-cdlatex-mode :style toggle
6769c0dc
CD
17695 :selected org-cdlatex-mode]
17696 ["Insert Environment" cdlatex-environment (fboundp 'cdlatex-environment)]
17697 ["Insert math symbol" cdlatex-math-symbol (fboundp 'cdlatex-math-symbol)]
17698 ["Modify math symbol" org-cdlatex-math-modify
17699 (org-inside-LaTeX-fragment-p)]
c8d0cf5c
CD
17700 ["Insert citation" org-reftex-citation t]
17701 "--"
86fbb8ca 17702 ["Template for BEAMER" org-insert-beamer-options-template t])
891f4676 17703 "--"
8d642074
CD
17704 ("MobileOrg"
17705 ["Push Files and Views" org-mobile-push t]
17706 ["Get Captured and Flagged" org-mobile-pull t]
17707 ["Find FLAGGED Tasks" (org-agenda nil "?") :active t :keys "C-c a ?"]
17708 "--"
17709 ["Setup" (progn (require 'org-mobile) (customize-group 'org-mobile)) t])
17710 "--"
891f4676
RS
17711 ("Documentation"
17712 ["Show Version" org-version t]
17713 ["Info Documentation" org-info t])
17714 ("Customize"
17715 ["Browse Org Group" org-customize t]
17716 "--"
ab27a4a0 17717 ["Expand This Menu" org-create-customize-menu
891f4676 17718 (fboundp 'customize-menu-create)])
54a0dee5 17719 ["Send bug report" org-submit-bug-report t]
28e5b051 17720 "--"
c8d0cf5c
CD
17721 ("Refresh/Reload"
17722 ["Refresh setup current buffer" org-mode-restart t]
17723 ["Reload Org (after update)" org-reload t]
17724 ["Reload Org uncompiled" (org-reload t) :active t :keys "C-u C-c C-x r"])
891f4676
RS
17725 ))
17726
891f4676
RS
17727(defun org-info (&optional node)
17728 "Read documentation for Org-mode in the info system.
17729With optional NODE, go directly to that node."
17730 (interactive)
74c52de1 17731 (info (format "(org)%s" (or node ""))))
891f4676 17732
54a0dee5
CD
17733;;;###autoload
17734(defun org-submit-bug-report ()
17735 "Submit a bug report on Org-mode via mail.
17736
17737Don't hesitate to report any problems or inaccurate documentation.
17738
17739If you don't have setup sending mail from (X)Emacs, please copy the
17740output buffer into your mail program, as it gives us important
17741information about your Org-mode version and configuration."
17742 (interactive)
17743 (require 'reporter)
17744 (org-load-modules-maybe)
17745 (org-require-autoloaded-modules)
17746 (let ((reporter-prompt-for-summary-p "Bug report subject: "))
17747 (reporter-submit-bug-report
17748 "emacs-orgmode@gnu.org"
17749 (org-version)
17750 (let (list)
17751 (save-window-excursion
17752 (switch-to-buffer (get-buffer-create "*Warn about privacy*"))
17753 (delete-other-windows)
17754 (erase-buffer)
17755 (insert "You are about to submit a bug report to the Org-mode mailing list.
17756
17757We would like to add your full Org-mode and Outline configuration to the
17758bug report. This greatly simplifies the work of the maintainer and
17759other experts on the mailing list.
17760
17761HOWEVER, some variables you have customized may contain private
17762information. The names of customers, colleagues, or friends, might
17763appear in the form of file names, tags, todo states, or search strings.
17764If you answer yes to the prompt, you might want to check and remove
17765such private information before sending the email.")
17766 (add-text-properties (point-min) (point-max) '(face org-warning))
17767 (when (yes-or-no-p "Include your Org-mode configuration ")
17768 (mapatoms
17769 (lambda (v)
17770 (and (boundp v)
17771 (string-match "\\`\\(org-\\|outline-\\)" (symbol-name v))
17772 (or (and (symbol-value v)
17773 (string-match "\\(-hook\\|-function\\)\\'" (symbol-name v)))
17774 (and
17775 (get v 'custom-type) (get v 'standard-value)
17776 (not (equal (symbol-value v) (eval (car (get v 'standard-value)))))))
17777 (push v list)))))
17778 (kill-buffer (get-buffer "*Warn about privacy*"))
17779 list))
17780 nil nil
17781 "Remember to cover the basics, that is, what you expected to happen and
17782what in fact did happen. You don't know how to make a good report? See
17783
17784 http://orgmode.org/manual/Feedback.html#Feedback
17785
17786Your bug report will be posted to the Org-mode mailing list.
1bcdebed
CD
17787------------------------------------------------------------------------")
17788 (save-excursion
17789 (if (re-search-backward "^\\(Subject: \\)Org-mode version \\(.*?\\);[ \t]*\\(.*\\)" nil t)
17790 (replace-match "\\1Bug: \\3 [\\2]")))))
db4a7382 17791
54a0dee5 17792
891f4676 17793(defun org-install-agenda-files-menu ()
ab27a4a0
CD
17794 (let ((bl (buffer-list)))
17795 (save-excursion
17796 (while bl
17797 (set-buffer (pop bl))
b928f99a
CD
17798 (if (org-mode-p) (setq bl nil)))
17799 (when (org-mode-p)
ab27a4a0
CD
17800 (easy-menu-change
17801 '("Org") "File List for Agenda"
17802 (append
17803 (list
17804 ["Edit File List" (org-edit-agenda-file-list) t]
17805 ["Add/Move Current File to Front of List" org-agenda-file-to-front t]
17806 ["Remove Current File from List" org-remove-file t]
17807 ["Cycle through agenda files" org-cycle-agenda-files t]
15841868 17808 ["Occur in all agenda files" org-occur-in-agenda-files t]
ab27a4a0
CD
17809 "--")
17810 (mapcar 'org-file-menu-entry (org-agenda-files t))))))))
891f4676 17811
d3f4dbe8 17812;;;; Documentation
891f4676 17813
b349f79f 17814;;;###autoload
20908596
CD
17815(defun org-require-autoloaded-modules ()
17816 (interactive)
17817 (mapc 'require
c8d0cf5c
CD
17818 '(org-agenda org-archive org-ascii org-attach org-clock org-colview
17819 org-docbook org-exp org-html org-icalendar
17820 org-id org-latex
17821 org-publish org-remember org-table
17822 org-timer org-xoxo)))
17823
17824;;;###autoload
17825(defun org-reload (&optional uncompiled)
17826 "Reload all org lisp files.
17827With prefix arg UNCOMPILED, load the uncompiled versions."
17828 (interactive "P")
17829 (require 'find-func)
17830 (let* ((file-re "^\\(org\\|orgtbl\\)\\(\\.el\\|-.*\\.el\\)")
17831 (dir-org (file-name-directory (org-find-library-name "org")))
17832 (dir-org-contrib (ignore-errors
17833 (file-name-directory
17834 (org-find-library-name "org-contribdir"))))
86fbb8ca
CD
17835 (babel-files
17836 (mapcar (lambda (el) (concat "ob" (when el (format "-%s" el)) ".el"))
17837 (append (list nil "comint" "eval" "exp" "keys"
17838 "lob" "ref" "table" "tangle")
17839 (delq nil
17840 (mapcar
17841 (lambda (lang)
17842 (when (cdr lang) (symbol-name (car lang))))
17843 org-babel-load-languages)))))
c8d0cf5c
CD
17844 (files
17845 (append (directory-files dir-org t file-re)
86fbb8ca 17846 babel-files
c8d0cf5c
CD
17847 (and dir-org-contrib
17848 (directory-files dir-org-contrib t file-re))))
17849 (remove-re (concat (if (featurep 'xemacs)
17850 "org-colview" "org-colview-xemacs")
17851 "\\'")))
17852 (setq files (mapcar 'file-name-sans-extension files))
17853 (setq files (mapcar
17854 (lambda (x) (if (string-match remove-re x) nil x))
17855 files))
17856 (setq files (delq nil files))
17857 (mapc
17858 (lambda (f)
17859 (when (featurep (intern (file-name-nondirectory f)))
17860 (if (and (not uncompiled)
17861 (file-exists-p (concat f ".elc")))
17862 (load (concat f ".elc") nil nil t)
17863 (load (concat f ".el") nil nil t))))
17864 files))
17865 (org-version))
20908596 17866
b349f79f 17867;;;###autoload
891f4676 17868(defun org-customize ()
c8d16429 17869 "Call the customize function with org as argument."
891f4676 17870 (interactive)
20908596
CD
17871 (org-load-modules-maybe)
17872 (org-require-autoloaded-modules)
891f4676
RS
17873 (customize-browse 'org))
17874
17875(defun org-create-customize-menu ()
17876 "Create a full customization menu for Org-mode, insert it into the menu."
17877 (interactive)
20908596
CD
17878 (org-load-modules-maybe)
17879 (org-require-autoloaded-modules)
891f4676
RS
17880 (if (fboundp 'customize-menu-create)
17881 (progn
17882 (easy-menu-change
17883 '("Org") "Customize"
17884 `(["Browse Org group" org-customize t]
17885 "--"
17886 ,(customize-menu-create 'org)
17887 ["Set" Custom-set t]
17888 ["Save" Custom-save t]
17889 ["Reset to Current" Custom-reset-current t]
17890 ["Reset to Saved" Custom-reset-saved t]
17891 ["Reset to Standard Settings" Custom-reset-standard t]))
17892 (message "\"Org\"-menu now contains full customization menu"))
17893 (error "Cannot expand menu (outdated version of cus-edit.el)")))
17894
d3f4dbe8
CD
17895;;;; Miscellaneous stuff
17896
d3f4dbe8 17897;;; Generally useful functions
891f4676 17898
8d642074
CD
17899(defun org-get-at-bol (property)
17900 "Get text property PROPERTY at beginning of line."
17901 (get-text-property (point-at-bol) property))
17902
db55f368
CD
17903(defun org-find-text-property-in-string (prop s)
17904 "Return the first non-nil value of property PROP in string S."
17905 (or (get-text-property 0 prop s)
17906 (get-text-property (or (next-single-property-change 0 prop s) 0)
17907 prop s)))
17908
b349f79f
CD
17909(defun org-display-warning (message) ;; Copied from Emacs-Muse
17910 "Display the given MESSAGE as a warning."
17911 (if (fboundp 'display-warning)
17912 (display-warning 'org message
86fbb8ca 17913 (if (featurep 'xemacs) 'warning :warning))
b349f79f
CD
17914 (let ((buf (get-buffer-create "*Org warnings*")))
17915 (with-current-buffer buf
17916 (goto-char (point-max))
17917 (insert "Warning (Org): " message)
17918 (unless (bolp)
17919 (newline)))
17920 (display-buffer buf)
17921 (sit-for 0))))
17922
54a0dee5
CD
17923(defun org-in-commented-line ()
17924 "Is point in a line starting with `#'?"
17925 (equal (char-after (point-at-bol)) ?#))
17926
86fbb8ca
CD
17927(defun org-in-indented-comment-line ()
17928 "Is point in a line starting with `#' after some white space?"
17929 (save-excursion
17930 (save-match-data
17931 (goto-char (point-at-bol))
17932 (looking-at "[ \t]*#"))))
17933
8bfe682a
CD
17934(defun org-in-verbatim-emphasis ()
17935 (save-match-data
17936 (and (org-in-regexp org-emph-re 2) (member (match-string 3) '("=" "~")))))
17937
b349f79f 17938(defun org-goto-marker-or-bmk (marker &optional bookmark)
621f83e4 17939 "Go to MARKER, widen if necessary. When marker is not live, try BOOKMARK."
b349f79f
CD
17940 (if (and marker (marker-buffer marker)
17941 (buffer-live-p (marker-buffer marker)))
17942 (progn
17943 (switch-to-buffer (marker-buffer marker))
17944 (if (or (> marker (point-max)) (< marker (point-min)))
17945 (widen))
0bd48b37
CD
17946 (goto-char marker)
17947 (org-show-context 'org-goto))
b349f79f
CD
17948 (if bookmark
17949 (bookmark-jump bookmark)
17950 (error "Cannot find location"))))
17951
17952(defun org-quote-csv-field (s)
17953 "Quote field for inclusion in CSV material."
17954 (if (string-match "[\",]" s)
17955 (concat "\"" (mapconcat 'identity (split-string s "\"") "\"\"") "\"")
17956 s))
17957
20908596
CD
17958(defun org-plist-delete (plist property)
17959 "Delete PROPERTY from PLIST.
17960This is in contrast to merely setting it to 0."
17961 (let (p)
17962 (while plist
17963 (if (not (eq property (car plist)))
17964 (setq p (plist-put p (car plist) (nth 1 plist))))
17965 (setq plist (cddr plist)))
17966 p))
17967
17968(defun org-force-self-insert (N)
17969 "Needed to enforce self-insert under remapping."
17970 (interactive "p")
17971 (self-insert-command N))
17972
17973(defun org-string-width (s)
17974 "Compute width of string, ignoring invisible characters.
17975This ignores character with invisibility property `org-link', and also
17976characters with property `org-cwidth', because these will become invisible
17977upon the next fontification round."
17978 (let (b l)
17979 (when (or (eq t buffer-invisibility-spec)
17980 (assq 'org-link buffer-invisibility-spec))
17981 (while (setq b (text-property-any 0 (length s)
17982 'invisible 'org-link s))
17983 (setq s (concat (substring s 0 b)
17984 (substring s (or (next-single-property-change
17985 b 'invisible s) (length s)))))))
17986 (while (setq b (text-property-any 0 (length s) 'org-cwidth t s))
17987 (setq s (concat (substring s 0 b)
17988 (substring s (or (next-single-property-change
17989 b 'org-cwidth s) (length s))))))
17990 (setq l (string-width s) b -1)
17991 (while (setq b (text-property-any (1+ b) (length s) 'org-dwidth t s))
17992 (setq l (- l (get-text-property b 'org-dwidth-n s))))
17993 l))
17994
acedf35c
CD
17995(defun org-shorten-string (s maxlength)
17996 "Shorten string S so tht it is no longer than MAXLENGTH characters.
17997If the string is shorter or has length MAXLENGTH, just return the
17998original string. If it is longer, the functions finds a space in the
17999string, breaks this string off at that locations and adds three dots
18000as ellipsis. Including the ellipsis, the string will not be longer
18001than MAXLENGTH. If finding a good breaking point in the string does
18002not work, the string is just chopped off in the middle of a word
18003if necessary."
18004 (if (<= (length s) maxlength)
18005 s
18006 (let* ((n (max (- maxlength 4) 1))
18007 (re (concat "\\`\\(.\\{1," (int-to-string n) "\\}[^ ]\\)\\([ ]\\|\\'\\)")))
18008 (if (string-match re s)
18009 (concat (match-string 1 s) "...")
18010 (concat (substring s 0 (max (- maxlength 3) 0)) "...")))))
18011
621f83e4
CD
18012(defun org-get-indentation (&optional line)
18013 "Get the indentation of the current line, interpreting tabs.
18014When LINE is given, assume it represents a line and compute its indentation."
18015 (if line
18016 (if (string-match "^ *" (org-remove-tabs line))
18017 (match-end 0))
18018 (save-excursion
18019 (beginning-of-line 1)
18020 (skip-chars-forward " \t")
18021 (current-column))))
18022
18023(defun org-remove-tabs (s &optional width)
18024 "Replace tabulators in S with spaces.
18025Assumes that s is a single line, starting in column 0."
18026 (setq width (or width tab-width))
18027 (while (string-match "\t" s)
18028 (setq s (replace-match
18029 (make-string
18030 (- (* width (/ (+ (match-beginning 0) width) width))
18031 (match-beginning 0)) ?\ )
18032 t t s)))
18033 s)
18034
18035(defun org-fix-indentation (line ind)
18036 "Fix indentation in LINE.
18037IND is a cons cell with target and minimum indentation.
33306645 18038If the current indentation in LINE is smaller than the minimum,
621f83e4
CD
18039leave it alone. If it is larger than ind, set it to the target."
18040 (let* ((l (org-remove-tabs line))
18041 (i (org-get-indentation l))
18042 (i1 (car ind)) (i2 (cdr ind)))
18043 (if (>= i i2) (setq l (substring line i2)))
18044 (if (> i1 0)
18045 (concat (make-string i1 ?\ ) l)
18046 l)))
18047
c8d0cf5c
CD
18048(defun org-remove-indentation (code &optional n)
18049 "Remove the maximum common indentation from the lines in CODE.
18050N may optionally be the number of spaces to remove."
18051 (with-temp-buffer
18052 (insert code)
18053 (org-do-remove-indentation n)
18054 (buffer-string)))
18055
18056(defun org-do-remove-indentation (&optional n)
18057 "Remove the maximum common indentation from the buffer."
18058 (untabify (point-min) (point-max))
18059 (let ((min 10000) re)
18060 (if n
18061 (setq min n)
18062 (goto-char (point-min))
18063 (while (re-search-forward "^ *[^ \n]" nil t)
18064 (setq min (min min (1- (- (match-end 0) (match-beginning 0)))))))
18065 (unless (or (= min 0) (= min 10000))
18066 (setq re (format "^ \\{%d\\}" min))
18067 (goto-char (point-min))
18068 (while (re-search-forward re nil t)
18069 (replace-match "")
18070 (end-of-line 1))
18071 min)))
18072
8bfe682a
CD
18073(defun org-fill-template (template alist)
18074 "Find each %key of ALIST in TEMPLATE and replace it."
ed21c5c8
CD
18075 (let ((case-fold-search nil)
18076 entry key value)
8bfe682a
CD
18077 (setq alist (sort (copy-sequence alist)
18078 (lambda (a b) (< (length (car a)) (length (car b))))))
18079 (while (setq entry (pop alist))
18080 (setq template
18081 (replace-regexp-in-string
18082 (concat "%" (regexp-quote (car entry)))
18083 (cdr entry) template t t)))
18084 template))
18085
b349f79f
CD
18086(defun org-base-buffer (buffer)
18087 "Return the base buffer of BUFFER, if it has one. Else return the buffer."
18088 (if (not buffer)
18089 buffer
18090 (or (buffer-base-buffer buffer)
18091 buffer)))
20908596
CD
18092
18093(defun org-trim (s)
18094 "Remove whitespace at beginning and end of string."
18095 (if (string-match "\\`[ \t\n\r]+" s) (setq s (replace-match "" t t s)))
18096 (if (string-match "[ \t\n\r]+\\'" s) (setq s (replace-match "" t t s)))
18097 s)
18098
18099(defun org-wrap (string &optional width lines)
18100 "Wrap string to either a number of lines, or a width in characters.
18101If WIDTH is non-nil, the string is wrapped to that width, however many lines
18102that costs. If there is a word longer than WIDTH, the text is actually
18103wrapped to the length of that word.
18104IF WIDTH is nil and LINES is non-nil, the string is forced into at most that
18105many lines, whatever width that takes.
18106The return value is a list of lines, without newlines at the end."
18107 (let* ((words (org-split-string string "[ \t\n]+"))
18108 (maxword (apply 'max (mapcar 'org-string-width words)))
18109 w ll)
18110 (cond (width
18111 (org-do-wrap words (max maxword width)))
18112 (lines
18113 (setq w maxword)
18114 (setq ll (org-do-wrap words maxword))
18115 (if (<= (length ll) lines)
18116 ll
18117 (setq ll words)
18118 (while (> (length ll) lines)
18119 (setq w (1+ w))
18120 (setq ll (org-do-wrap words w)))
18121 ll))
18122 (t (error "Cannot wrap this")))))
18123
18124(defun org-do-wrap (words width)
18125 "Create lines of maximum width WIDTH (in characters) from word list WORDS."
18126 (let (lines line)
18127 (while words
18128 (setq line (pop words))
18129 (while (and words (< (+ (length line) (length (car words))) width))
18130 (setq line (concat line " " (pop words))))
18131 (setq lines (push line lines)))
18132 (nreverse lines)))
18133
18134(defun org-split-string (string &optional separators)
18135 "Splits STRING into substrings at SEPARATORS.
18136No empty strings are returned if there are matches at the beginning
18137and end of string."
18138 (let ((rexp (or separators "[ \f\t\n\r\v]+"))
18139 (start 0)
18140 notfirst
18141 (list nil))
18142 (while (and (string-match rexp string
18143 (if (and notfirst
18144 (= start (match-beginning 0))
18145 (< start (length string)))
18146 (1+ start) start))
18147 (< (match-beginning 0) (length string)))
18148 (setq notfirst t)
18149 (or (eq (match-beginning 0) 0)
18150 (and (eq (match-beginning 0) (match-end 0))
18151 (eq (match-beginning 0) start))
18152 (setq list
18153 (cons (substring string start (match-beginning 0))
18154 list)))
18155 (setq start (match-end 0)))
18156 (or (eq start (length string))
18157 (setq list
18158 (cons (substring string start)
18159 list)))
18160 (nreverse list)))
18161
c8d0cf5c
CD
18162(defun org-quote-vert (s)
18163 "Replace \"|\" with \"\\vert\"."
18164 (while (string-match "|" s)
18165 (setq s (replace-match "\\vert" t t s)))
18166 s)
18167
18168(defun org-uuidgen-p (s)
18169 "Is S an ID created by UUIDGEN?"
18170 (string-match "\\`[0-9a-f]\\{8\\}-[0-9a-f]\\{4\\}-[0-9a-f]\\{4\\}-[0-9a-f]\\{4\\}-[0-9a-f]\\{12\\}\\'" (downcase s)))
18171
c4b5acde
CD
18172(defun org-context ()
18173 "Return a list of contexts of the current cursor position.
18174If several contexts apply, all are returned.
18175Each context entry is a list with a symbol naming the context, and
18176two positions indicating start and end of the context. Possible
18177contexts are:
18178
18179:headline anywhere in a headline
18180:headline-stars on the leading stars in a headline
18181:todo-keyword on a TODO keyword (including DONE) in a headline
18182:tags on the TAGS in a headline
18183:priority on the priority cookie in a headline
18184:item on the first line of a plain list item
e39856be 18185:item-bullet on the bullet/number of a plain list item
c4b5acde
CD
18186:checkbox on the checkbox in a plain list item
18187:table in an org-mode table
18188:table-special on a special filed in a table
18189:table-table in a table.el table
d3f4dbe8 18190:link on a hyperlink
c4b5acde
CD
18191:keyword on a keyword: SCHEDULED, DEADLINE, CLOSE,COMMENT, QUOTE.
18192:target on a <<target>>
18193:radio-target on a <<<radio-target>>>
e39856be
CD
18194:latex-fragment on a LaTeX fragment
18195:latex-preview on a LaTeX fragment with overlayed preview image
c4b5acde
CD
18196
18197This function expects the position to be visible because it uses font-lock
18198faces as a help to recognize the following contexts: :table-special, :link,
18199and :keyword."
18200 (let* ((f (get-text-property (point) 'face))
18201 (faces (if (listp f) f (list f)))
e39856be 18202 (p (point)) clist o)
c4b5acde
CD
18203 ;; First the large context
18204 (cond
a3fbe8c4 18205 ((org-on-heading-p t)
c4b5acde
CD
18206 (push (list :headline (point-at-bol) (point-at-eol)) clist)
18207 (when (progn
18208 (beginning-of-line 1)
18209 (looking-at org-todo-line-tags-regexp))
18210 (push (org-point-in-group p 1 :headline-stars) clist)
18211 (push (org-point-in-group p 2 :todo-keyword) clist)
18212 (push (org-point-in-group p 4 :tags) clist))
18213 (goto-char p)
8bfe682a 18214 (skip-chars-backward "^[\n\r \t") (or (bobp) (backward-char 1))
a3fbe8c4 18215 (if (looking-at "\\[#[A-Z0-9]\\]")
c4b5acde
CD
18216 (push (org-point-in-group p 0 :priority) clist)))
18217
18218 ((org-at-item-p)
e39856be 18219 (push (org-point-in-group p 2 :item-bullet) clist)
c4b5acde
CD
18220 (push (list :item (point-at-bol)
18221 (save-excursion (org-end-of-item) (point)))
18222 clist)
18223 (and (org-at-item-checkbox-p)
18224 (push (org-point-in-group p 0 :checkbox) clist)))
18225
18226 ((org-at-table-p)
18227 (push (list :table (org-table-begin) (org-table-end)) clist)
18228 (if (memq 'org-formula faces)
18229 (push (list :table-special
18230 (previous-single-property-change p 'face)
18231 (next-single-property-change p 'face)) clist)))
18232 ((org-at-table-p 'any)
18233 (push (list :table-table) clist)))
18234 (goto-char p)
18235
18236 ;; Now the small context
18237 (cond
18238 ((org-at-timestamp-p)
18239 (push (org-point-in-group p 0 :timestamp) clist))
18240 ((memq 'org-link faces)
18241 (push (list :link
18242 (previous-single-property-change p 'face)
18243 (next-single-property-change p 'face)) clist))
18244 ((memq 'org-special-keyword faces)
18245 (push (list :keyword
18246 (previous-single-property-change p 'face)
18247 (next-single-property-change p 'face)) clist))
18248 ((org-on-target-p)
18249 (push (org-point-in-group p 0 :target) clist)
18250 (goto-char (1- (match-beginning 0)))
18251 (if (looking-at org-radio-target-regexp)
18252 (push (org-point-in-group p 0 :radio-target) clist))
e39856be
CD
18253 (goto-char p))
18254 ((setq o (car (delq nil
c44f0d75 18255 (mapcar
e39856be
CD
18256 (lambda (x)
18257 (if (memq x org-latex-fragment-image-overlays) x))
86fbb8ca 18258 (overlays-at (point))))))
c44f0d75 18259 (push (list :latex-fragment
86fbb8ca 18260 (overlay-start o) (overlay-end o)) clist)
c44f0d75 18261 (push (list :latex-preview
86fbb8ca 18262 (overlay-start o) (overlay-end o)) clist))
e39856be 18263 ((org-inside-LaTeX-fragment-p)
3278a016 18264 ;; FIXME: positions wrong.
e39856be 18265 (push (list :latex-fragment (point) (point)) clist)))
c4b5acde
CD
18266
18267 (setq clist (nreverse (delq nil clist)))
18268 clist))
18269
15841868 18270;; FIXME: Compare with at-regexp-p Do we need both?
d3f4dbe8
CD
18271(defun org-in-regexp (re &optional nlines visually)
18272 "Check if point is inside a match of regexp.
18273Normally only the current line is checked, but you can include NLINES extra
18274lines both before and after point into the search.
18275If VISUALLY is set, require that the cursor is not after the match but
18276really on, so that the block visually is on the match."
18277 (catch 'exit
18278 (let ((pos (point))
18279 (eol (point-at-eol (+ 1 (or nlines 0))))
18280 (inc (if visually 1 0)))
18281 (save-excursion
18282 (beginning-of-line (- 1 (or nlines 0)))
18283 (while (re-search-forward re eol t)
a3fbe8c4 18284 (if (and (<= (match-beginning 0) pos)
d3f4dbe8
CD
18285 (>= (+ inc (match-end 0)) pos))
18286 (throw 'exit (cons (match-beginning 0) (match-end 0)))))))))
18287
a3fbe8c4
CD
18288(defun org-at-regexp-p (regexp)
18289 "Is point inside a match of REGEXP in the current line?"
18290 (catch 'exit
18291 (save-excursion
18292 (let ((pos (point)) (end (point-at-eol)))
18293 (beginning-of-line 1)
18294 (while (re-search-forward regexp end t)
18295 (if (and (<= (match-beginning 0) pos)
18296 (>= (match-end 0) pos))
18297 (throw 'exit t)))
18298 nil))))
18299
afe98dfa 18300(defun org-in-regexps-block-p (start-re end-re &optional bound)
86fbb8ca 18301 "Return t if the current point is between matches of START-RE and END-RE.
afe98dfa 18302This will also return t if point is on one of the two matches or
01c35094 18303in an unfinished block. END-RE can be a string or a form
afe98dfa
CD
18304returning a string.
18305
01c35094
JB
18306An optional third argument bounds the search for START-RE.
18307It defaults to previous heading or `point-min'."
afe98dfa
CD
18308 (let ((pos (point))
18309 (limit (or bound (save-excursion (outline-previous-heading)))))
ed21c5c8 18310 (save-excursion
afe98dfa
CD
18311 ;; we're on a block when point is on start-re...
18312 (or (org-at-regexp-p start-re)
18313 ;; ... or start-re can be found above...
18314 (and (re-search-backward start-re limit t)
18315 ;; ... but no end-re between start-re and point.
18316 (not (re-search-forward (eval end-re) pos t)))))))
ed21c5c8 18317
03f3cf35 18318(defun org-occur-in-agenda-files (regexp &optional nlines)
15841868 18319 "Call `multi-occur' with buffers for all agenda files."
03f3cf35
JW
18320 (interactive "sOrg-files matching: \np")
18321 (let* ((files (org-agenda-files))
18322 (tnames (mapcar 'file-truename files))
2a57416f 18323 (extra org-agenda-text-search-extra-files)
03f3cf35 18324 f)
20908596
CD
18325 (when (eq (car extra) 'agenda-archives)
18326 (setq extra (cdr extra))
18327 (setq files (org-add-archive-files files)))
03f3cf35
JW
18328 (while (setq f (pop extra))
18329 (unless (member (file-truename f) tnames)
18330 (add-to-list 'files f 'append)
18331 (add-to-list 'tnames (file-truename f) 'append)))
18332 (multi-occur
5dec9555
CD
18333 (mapcar (lambda (x)
18334 (with-current-buffer
18335 (or (get-file-buffer x) (find-file-noselect x))
18336 (widen)
18337 (current-buffer)))
18338 files)
03f3cf35 18339 regexp)))
15841868 18340
2a57416f
CD
18341(if (boundp 'occur-mode-find-occurrence-hook)
18342 ;; Emacs 23
18343 (add-hook 'occur-mode-find-occurrence-hook
18344 (lambda ()
18345 (when (org-mode-p)
18346 (org-reveal))))
18347 ;; Emacs 22
18348 (defadvice occur-mode-goto-occurrence
18349 (after org-occur-reveal activate)
18350 (and (org-mode-p) (org-reveal)))
18351 (defadvice occur-mode-goto-occurrence-other-window
18352 (after org-occur-reveal activate)
18353 (and (org-mode-p) (org-reveal)))
18354 (defadvice occur-mode-display-occurrence
18355 (after org-occur-reveal activate)
18356 (when (org-mode-p)
18357 (let ((pos (occur-mode-find-occurrence)))
18358 (with-current-buffer (marker-buffer pos)
18359 (save-excursion
18360 (goto-char pos)
18361 (org-reveal)))))))
18362
c8d0cf5c
CD
18363(defun org-occur-link-in-agenda-files ()
18364 "Create a link and search for it in the agendas.
18365The link is not stored in `org-stored-links', it is just created
18366for the search purpose."
18367 (interactive)
18368 (let ((link (condition-case nil
18369 (org-store-link nil)
18370 (error "Unable to create a link to here"))))
18371 (org-occur-in-agenda-files (regexp-quote link))))
18372
a3fbe8c4
CD
18373(defun org-uniquify (list)
18374 "Remove duplicate elements from LIST."
18375 (let (res)
18376 (mapc (lambda (x) (add-to-list 'res x 'append)) list)
18377 res))
18378
18379(defun org-delete-all (elts list)
18380 "Remove all elements in ELTS from LIST."
18381 (while elts
18382 (setq list (delete (pop elts) list)))
18383 list)
18384
86fbb8ca
CD
18385(defun org-count (cl-item cl-seq)
18386 "Count the number of occurrences of ITEM in SEQ.
18387Taken from `count' in cl-seq.el with all keyword arguments removed."
18388 (let ((cl-end (length cl-seq)) (cl-start 0) (cl-count 0) cl-x)
18389 (when (consp cl-seq) (setq cl-seq (nthcdr cl-start cl-seq)))
18390 (while (< cl-start cl-end)
18391 (setq cl-x (if (consp cl-seq) (pop cl-seq) (aref cl-seq cl-start)))
18392 (if (equal cl-item cl-x) (setq cl-count (1+ cl-count)))
18393 (setq cl-start (1+ cl-start)))
18394 cl-count))
18395
18396(defun org-remove-if (predicate seq)
18397 "Remove everything from SEQ that fulfills PREDICATE."
18398 (let (res e)
18399 (while seq
18400 (setq e (pop seq))
18401 (if (not (funcall predicate e)) (push e res)))
18402 (nreverse res)))
18403
18404(defun org-remove-if-not (predicate seq)
18405 "Remove everything from SEQ that does not fulfill PREDICATE."
18406 (let (res e)
18407 (while seq
18408 (setq e (pop seq))
18409 (if (funcall predicate e) (push e res)))
18410 (nreverse res)))
18411
8c6fb58b 18412(defun org-back-over-empty-lines ()
33306645 18413 "Move backwards over whitespace, to the beginning of the first empty line.
5bf7807a 18414Returns the number of empty lines passed."
8c6fb58b
CD
18415 (let ((pos (point)))
18416 (skip-chars-backward " \t\n\r")
18417 (beginning-of-line 2)
18418 (goto-char (min (point) pos))
18419 (count-lines (point) pos)))
18420
18421(defun org-skip-whitespace ()
18422 (skip-chars-forward " \t\n\r"))
18423
c4b5acde
CD
18424(defun org-point-in-group (point group &optional context)
18425 "Check if POINT is in match-group GROUP.
18426If CONTEXT is non-nil, return a list with CONTEXT and the boundaries of the
86fbb8ca 18427match. If the match group does not exist or point is not inside it,
c4b5acde
CD
18428return nil."
18429 (and (match-beginning group)
18430 (>= point (match-beginning group))
18431 (<= point (match-end group))
18432 (if context
18433 (list context (match-beginning group) (match-end group))
18434 t)))
18435
374585c9
CD
18436(defun org-switch-to-buffer-other-window (&rest args)
18437 "Switch to buffer in a second window on the current frame.
86fbb8ca
CD
18438In particular, do not allow pop-up frames.
18439Returns the newly created buffer."
374585c9
CD
18440 (let (pop-up-frames special-display-buffer-names special-display-regexps
18441 special-display-function)
18442 (apply 'switch-to-buffer-other-window args)))
18443
d3f4dbe8
CD
18444(defun org-combine-plists (&rest plists)
18445 "Create a single property list from all plists in PLISTS.
18446The process starts by copying the first list, and then setting properties
18447from the other lists. Settings in the last list are the most significant
18448ones and overrule settings in the other lists."
18449 (let ((rtn (copy-sequence (pop plists)))
18450 p v ls)
18451 (while plists
18452 (setq ls (pop plists))
18453 (while ls
18454 (setq p (pop ls) v (pop ls))
18455 (setq rtn (plist-put rtn p v))))
18456 rtn))
18457
891f4676 18458(defun org-move-line-down (arg)
634a7d0b 18459 "Move the current line down. With prefix argument, move it past ARG lines."
891f4676
RS
18460 (interactive "p")
18461 (let ((col (current-column))
18462 beg end pos)
18463 (beginning-of-line 1) (setq beg (point))
18464 (beginning-of-line 2) (setq end (point))
18465 (beginning-of-line (+ 1 arg))
18466 (setq pos (move-marker (make-marker) (point)))
18467 (insert (delete-and-extract-region beg end))
18468 (goto-char pos)
20908596 18469 (org-move-to-column col)))
891f4676
RS
18470
18471(defun org-move-line-up (arg)
634a7d0b 18472 "Move the current line up. With prefix argument, move it past ARG lines."
891f4676
RS
18473 (interactive "p")
18474 (let ((col (current-column))
18475 beg end pos)
18476 (beginning-of-line 1) (setq beg (point))
18477 (beginning-of-line 2) (setq end (point))
634a7d0b 18478 (beginning-of-line (- arg))
891f4676
RS
18479 (setq pos (move-marker (make-marker) (point)))
18480 (insert (delete-and-extract-region beg end))
18481 (goto-char pos)
20908596 18482 (org-move-to-column col)))
891f4676 18483
d3f4dbe8
CD
18484(defun org-replace-escapes (string table)
18485 "Replace %-escapes in STRING with values in TABLE.
15841868 18486TABLE is an association list with keys like \"%a\" and string values.
d3f4dbe8
CD
18487The sequences in STRING may contain normal field width and padding information,
18488for example \"%-5s\". Replacements happen in the sequence given by TABLE,
18489so values can contain further %-escapes if they are define later in TABLE."
86fbb8ca
CD
18490 (let ((tbl (copy-alist table))
18491 (case-fold-search nil)
18492 (pchg 0)
18493 e re rpl)
18494 (while (setq e (pop tbl))
d3f4dbe8 18495 (setq re (concat "%-?[0-9.]*" (substring (car e) 1)))
86fbb8ca
CD
18496 (when (and (cdr e) (string-match re (cdr e)))
18497 (let ((sref (substring (cdr e) (match-beginning 0) (match-end 0)))
18498 (safe "SREF"))
18499 (add-text-properties 0 3 (list 'sref sref) safe)
18500 (setcdr e (replace-match safe t t (cdr e)))))
d3f4dbe8 18501 (while (string-match re string)
86fbb8ca
CD
18502 (setq rpl (format (concat (substring (match-string 0 string) 0 -1) "s")
18503 (cdr e)))
18504 (setq string (replace-match rpl t t string))))
18505 (while (setq pchg (next-property-change pchg string))
18506 (let ((sref (get-text-property pchg 'sref string)))
18507 (when (and sref (string-match "SREF" string pchg))
18508 (setq string (replace-match sref t t string)))))
d3f4dbe8
CD
18509 string))
18510
d3f4dbe8
CD
18511(defun org-sublist (list start end)
18512 "Return a section of LIST, from START to END.
18513Counting starts at 1."
18514 (let (rtn (c start))
18515 (setq list (nthcdr (1- start) list))
18516 (while (and list (<= c end))
18517 (push (pop list) rtn)
18518 (setq c (1+ c)))
18519 (nreverse rtn)))
18520
d3f4dbe8 18521(defun org-find-base-buffer-visiting (file)
c8d0cf5c 18522 "Like `find-buffer-visiting' but always return the base buffer and
5bf7807a 18523not an indirect buffer."
c8d0cf5c
CD
18524 (let ((buf (or (get-file-buffer file)
18525 (find-buffer-visiting file))))
15841868
JW
18526 (if buf
18527 (or (buffer-base-buffer buf) buf)
18528 nil)))
d3f4dbe8 18529
0bd48b37
CD
18530(defun org-image-file-name-regexp (&optional extensions)
18531 "Return regexp matching the file names of images.
18532If EXTENSIONS is given, only match these."
18533 (if (and (not extensions) (fboundp 'image-file-name-regexp))
a3fbe8c4
CD
18534 (image-file-name-regexp)
18535 (let ((image-file-name-extensions
0bd48b37
CD
18536 (or extensions
18537 '("png" "jpeg" "jpg" "gif" "tiff" "tif"
18538 "xbm" "xpm" "pbm" "pgm" "ppm"))))
a3fbe8c4
CD
18539 (concat "\\."
18540 (regexp-opt (nconc (mapcar 'upcase
18541 image-file-name-extensions)
18542 image-file-name-extensions)
18543 t)
18544 "\\'"))))
18545
0bd48b37 18546(defun org-file-image-p (file &optional extensions)
a3fbe8c4
CD
18547 "Return non-nil if FILE is an image."
18548 (save-match-data
0bd48b37 18549 (string-match (org-image-file-name-regexp extensions) file)))
a3fbe8c4 18550
b349f79f
CD
18551(defun org-get-cursor-date ()
18552 "Return the date at cursor in as a time.
18553This works in the calendar and in the agenda, anywhere else it just
18554returns the current time."
18555 (let (date day defd)
18556 (cond
18557 ((eq major-mode 'calendar-mode)
18558 (setq date (calendar-cursor-to-date)
18559 defd (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
18560 ((eq major-mode 'org-agenda-mode)
18561 (setq day (get-text-property (point) 'day))
18562 (if day
18563 (setq date (calendar-gregorian-from-absolute day)
18564 defd (encode-time 0 0 0 (nth 1 date) (nth 0 date)
18565 (nth 2 date))))))
18566 (or defd (current-time))))
18567
18568(defvar org-agenda-action-marker (make-marker)
18569 "Marker pointing to the entry for the next agenda action.")
18570
18571(defun org-mark-entry-for-agenda-action ()
18572 "Mark the current entry as target of an agenda action.
18573Agenda actions are actions executed from the agenda with the key `k',
18574which make use of the date at the cursor."
18575 (interactive)
18576 (move-marker org-agenda-action-marker
18577 (save-excursion (org-back-to-heading t) (point))
18578 (current-buffer))
18579 (message
18580 "Entry marked for action; press `k' at desired date in agenda or calendar"))
18581
acedf35c
CD
18582(defun org-mark-subtree ()
18583 "Mark the current subtree.
18584This puts point at the start of the current subtree, and mark at the end.
18585
18586If point is in an inline task, mark that task instead."
18587 (interactive)
18588 (let ((inline-task-p
18589 (and (featurep 'org-inlinetask)
18590 (org-inlinetask-in-task-p)))
18591 (beg))
18592 ;; Get beginning of subtree
18593 (cond
18594 (inline-task-p (org-inlinetask-goto-beginning))
18595 ((org-at-heading-p) (beginning-of-line))
18596 (t (let ((outline-regexp (org-get-limited-outline-regexp)))
18597 (outline-previous-visible-heading 1))))
18598 (setq beg (point))
18599 ;; Get end of it
18600 (if inline-task-p
18601 (org-inlinetask-goto-end)
18602 (org-end-of-subtree))
18603 ;; Mark zone
18604 (push-mark (point) nil t)
18605 (goto-char beg)))
18606
d3f4dbe8 18607;;; Paragraph filling stuff.
e0e66b8e 18608;; We want this to be just right, so use the full arsenal.
a3fbe8c4
CD
18609
18610(defun org-indent-line-function ()
acedf35c 18611 "Indent line depending on context."
a3fbe8c4 18612 (interactive)
b38c6895
CD
18613 (let* ((pos (point))
18614 (itemp (org-at-item-p))
c8d0cf5c
CD
18615 (case-fold-search t)
18616 (org-drawer-regexp (or org-drawer-regexp "\000"))
afe98dfa
CD
18617 (inline-task-p (and (featurep 'org-inlinetask)
18618 (org-inlinetask-in-task-p)))
acedf35c 18619 column bpos bcol tpos tcol)
b38c6895
CD
18620 (beginning-of-line 1)
18621 (cond
afe98dfa 18622 ;; Comments
acedf35c 18623 ((looking-at "# ") (setq column 0))
afe98dfa 18624 ;; Headings
5152b597 18625 ((looking-at "\\*+ ") (setq column 0))
acedf35c
CD
18626 ;; Literal examples
18627 ((looking-at "[ \t]*:[ \t]")
18628 (setq column (org-get-indentation))) ; do nothing
afe98dfa 18629 ;; Drawers
c8d0cf5c
CD
18630 ((and (looking-at "[ \t]*:END:")
18631 (save-excursion (re-search-backward org-drawer-regexp nil t)))
18632 (save-excursion
18633 (goto-char (1- (match-beginning 1)))
18634 (setq column (current-column))))
afe98dfa
CD
18635 ;; Special blocks
18636 ((and (looking-at "[ \t]*#\\+end_\\([a-z]+\\)")
c8d0cf5c
CD
18637 (save-excursion
18638 (re-search-backward
18639 (concat "^[ \t]*#\\+begin_" (downcase (match-string 1))) nil t)))
18640 (setq column (org-get-indentation (match-string 0))))
afe98dfa
CD
18641 ((and (not (looking-at "[ \t]*#\\+begin_"))
18642 (org-in-regexps-block-p "^[ \t]*#\\+begin_" "[ \t]*#\\+end_"))
18643 (save-excursion
18644 (re-search-backward "^[ \t]*#\\+begin_\\([a-z]+\\)" nil t))
18645 (setq column
18646 (if (equal (downcase (match-string 1)) "src")
18647 ;; src blocks: let `org-edit-src-exit' handle them
18648 (org-get-indentation)
18649 (org-get-indentation (match-string 0)))))
18650 ;; Lists
18651 ((org-in-item-p)
18652 (org-beginning-of-item)
18653 (looking-at "[ \t]*\\(\\S-+\\)[ \t]*\\(\\(:?\\[@\\(:?start:\\)?[0-9]+\\][ \t]*\\)?\\[[- X]\\][ \t]*\\|.*? :: \\)?")
18654 (setq bpos (match-beginning 1) tpos (match-end 0)
18655 bcol (progn (goto-char bpos) (current-column))
acedf35c 18656 tcol (progn (goto-char tpos) (current-column)))
afe98dfa
CD
18657 (if (> tcol (+ bcol org-description-max-indent))
18658 (setq tcol (+ bcol 5)))
acedf35c
CD
18659 (goto-char pos)
18660 (setq column (if itemp (org-get-indentation) tcol)))
18661 ;; This line has nothing special, look at the previous relevant
18662 ;; line to compute indentation
b38c6895
CD
18663 (t
18664 (beginning-of-line 0)
afe98dfa 18665 (while (and (not (bobp))
acedf35c 18666 (not (looking-at org-drawer-regexp))
afe98dfa 18667 ;; skip comments, verbatim, empty lines, tables,
acedf35c
CD
18668 ;; inline tasks, lists, drawers and blocks
18669 (or (and (looking-at "[ \t]*:END:")
18670 (re-search-backward org-drawer-regexp nil t))
18671 (and (looking-at "[ \t]*#\\+end_")
18672 (re-search-backward "[ \t]*#\\+begin_"nil t))
18673 (looking-at "[ \t]*[\n:#|]")
afe98dfa
CD
18674 (and (org-in-item-p) (goto-char (org-list-top-point)))
18675 (and (not inline-task-p)
18676 (featurep 'org-inlinetask)
acedf35c
CD
18677 (org-inlinetask-in-task-p)
18678 (or (org-inlinetask-goto-beginning) t))))
afe98dfa 18679 (beginning-of-line 0))
b38c6895 18680 (cond
afe98dfa 18681 ;; There was an heading above.
b38c6895 18682 ((looking-at "\\*+[ \t]+")
b349f79f
CD
18683 (if (not org-adapt-indentation)
18684 (setq column 0)
18685 (goto-char (match-end 0))
18686 (setq column (current-column))))
acedf35c 18687 ;; A drawer had started and is unfinished
c8d0cf5c 18688 ((looking-at org-drawer-regexp)
afe98dfa
CD
18689 (goto-char (1- (match-beginning 1)))
18690 (setq column (current-column)))
afe98dfa 18691 ;; Else, nothing noticeable found: get indentation and go on.
b38c6895 18692 (t (setq column (org-get-indentation))))))
acedf35c 18693 ;; Now apply indentation and move cursor accordingly
b38c6895 18694 (goto-char pos)
a3fbe8c4 18695 (if (<= (current-column) (current-indentation))
20908596
CD
18696 (org-indent-line-to column)
18697 (save-excursion (org-indent-line-to column)))
acedf35c 18698 ;; Special polishing for properties, see `org-property-format'
38f8646b
CD
18699 (setq column (current-column))
18700 (beginning-of-line 1)
18701 (if (looking-at
8c6fb58b 18702 "\\([ \t]+\\)\\(:[-_0-9a-zA-Z]+:\\)[ \t]*\\(\\S-.*\\(\\S-\\|$\\)\\)")
8bfe682a
CD
18703 (replace-match (concat (match-string 1)
18704 (format org-property-format
18705 (match-string 2) (match-string 3)))
18706 t t))
20908596 18707 (org-move-to-column column)))
e0e66b8e 18708
ed21c5c8
CD
18709(defvar org-adaptive-fill-regexp-backup adaptive-fill-regexp
18710 "Variable to store copy of `adaptive-fill-regexp'.
18711Since `adaptive-fill-regexp' is set to never match, we need to
18712store a backup of its value before entering `org-mode' so that
18713the functionality can be provided as a fall-back.")
18714
e0e66b8e
CD
18715(defun org-set-autofill-regexps ()
18716 (interactive)
18717 ;; In the paragraph separator we include headlines, because filling
18718 ;; text in a line directly attached to a headline would otherwise
18719 ;; fill the headline as well.
5137195a 18720 (org-set-local 'comment-start-skip "^#+[ \t]*")
8d642074 18721 (org-set-local 'paragraph-separate "\f\\|\\*+ \\|[ ]*$\\|[ \t]*[:|#]")
e0e66b8e 18722 ;; The paragraph starter includes hand-formatted lists.
c8d0cf5c
CD
18723 (org-set-local
18724 'paragraph-start
18725 (concat
18726 "\f" "\\|"
18727 "[ ]*$" "\\|"
18728 "\\*+ " "\\|"
8d642074 18729 "[ \t]*#" "\\|"
c8d0cf5c
CD
18730 "[ \t]*\\([-+*][ \t]+\\|[0-9]+[.)][ \t]+\\)" "\\|"
18731 "[ \t]*[:|]" "\\|"
18732 "\\$\\$" "\\|"
18733 "\\\\\\(begin\\|end\\|[][]\\)"))
e0e66b8e
CD
18734 ;; Inhibit auto-fill for headers, tables and fixed-width lines.
18735 ;; But only if the user has not turned off tables or fixed-width regions
5137195a
CD
18736 (org-set-local
18737 'auto-fill-inhibit-regexp
7d58338e 18738 (concat "\\*+ \\|#\\+"
5137195a
CD
18739 "\\|[ \t]*" org-keyword-time-regexp
18740 (if (or org-enable-table-editor org-enable-fixed-width-editor)
18741 (concat
18742 "\\|[ \t]*["
18743 (if org-enable-table-editor "|" "")
18744 (if org-enable-fixed-width-editor ":" "")
18745 "]"))))
e0e66b8e
CD
18746 ;; We use our own fill-paragraph function, to make sure that tables
18747 ;; and fixed-width regions are not wrapped. That function will pass
18748 ;; through to `fill-paragraph' when appropriate.
5137195a 18749 (org-set-local 'fill-paragraph-function 'org-fill-paragraph)
ed21c5c8 18750 ;; Adaptive filling: To get full control, first make sure that
6eff18ef 18751 ;; `adaptive-fill-regexp' never matches. Then install our own matcher.
86fbb8ca 18752 (unless (local-variable-p 'adaptive-fill-regexp (current-buffer))
ed21c5c8
CD
18753 (org-set-local 'org-adaptive-fill-regexp-backup
18754 adaptive-fill-regexp))
5137195a
CD
18755 (org-set-local 'adaptive-fill-regexp "\000")
18756 (org-set-local 'adaptive-fill-function
2a57416f
CD
18757 'org-adaptive-fill-function)
18758 (org-set-local
18759 'align-mode-rules-list
18760 '((org-in-buffer-settings
18761 (regexp . "^#\\+[A-Z_]+:\\(\\s-*\\)\\S-+")
18762 (modes . '(org-mode))))))
e0e66b8e
CD
18763
18764(defun org-fill-paragraph (&optional justify)
18765 "Re-align a table, pass through to fill-paragraph if no table."
18766 (let ((table-p (org-at-table-p))
18767 (table.el-p (org-at-table.el-p)))
8c6fb58b
CD
18768 (cond ((and (equal (char-after (point-at-bol)) ?*)
18769 (save-excursion (goto-char (point-at-bol))
18770 (looking-at outline-regexp)))
18771 t) ; skip headlines
18772 (table.el-p t) ; skip table.el tables
18773 (table-p (org-table-align) t) ; align org-mode tables
18774 (t nil)))) ; call paragraph-fill
e0e66b8e
CD
18775
18776;; For reference, this is the default value of adaptive-fill-regexp
18777;; "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*"
18778
18779(defun org-adaptive-fill-function ()
18780 "Return a fill prefix for org-mode files.
18781In particular, this makes sure hanging paragraphs for hand-formatted lists
18782work correctly."
ed21c5c8
CD
18783 (cond
18784 ;; Comment line
18785 ((looking-at "#[ \t]+")
18786 (match-string-no-properties 0))
18787 ;; Description list
b349f79f
CD
18788 ((looking-at "[ \t]*\\([-*+] .*? :: \\)")
18789 (save-excursion
18790 (if (> (match-end 1) (+ (match-beginning 1)
18791 org-description-max-indent))
18792 (goto-char (+ (match-beginning 1) 5))
18793 (goto-char (match-end 0)))
18794 (make-string (current-column) ?\ )))
ed21c5c8
CD
18795 ;; Ordered or unordered list
18796 ((looking-at "[ \t]*\\([-*+] \\|[0-9]+[.)] ?\\)")
a3fbe8c4
CD
18797 (save-excursion
18798 (goto-char (match-end 0))
18799 (make-string (current-column) ?\ )))
ed21c5c8
CD
18800 ;; Other text
18801 ((looking-at org-adaptive-fill-regexp-backup)
18802 (match-string-no-properties 0))))
891f4676 18803
20908596
CD
18804;;; Other stuff.
18805
18806(defun org-toggle-fixed-width-section (arg)
18807 "Toggle the fixed-width export.
18808If there is no active region, the QUOTE keyword at the current headline is
18809inserted or removed. When present, it causes the text between this headline
18810and the next to be exported as fixed-width text, and unmodified.
18811If there is an active region, this command adds or removes a colon as the
18812first character of this line. If the first character of a line is a colon,
18813this line is also exported in fixed-width font."
18814 (interactive "P")
18815 (let* ((cc 0)
18816 (regionp (org-region-active-p))
18817 (beg (if regionp (region-beginning) (point)))
18818 (end (if regionp (region-end)))
18819 (nlines (or arg (if (and beg end) (count-lines beg end) 1)))
18820 (case-fold-search nil)
c8d0cf5c 18821 (re "[ \t]*\\(: \\)")
20908596
CD
18822 off)
18823 (if regionp
18824 (save-excursion
18825 (goto-char beg)
18826 (setq cc (current-column))
18827 (beginning-of-line 1)
18828 (setq off (looking-at re))
18829 (while (> nlines 0)
18830 (setq nlines (1- nlines))
18831 (beginning-of-line 1)
18832 (cond
18833 (arg
18834 (org-move-to-column cc t)
c8d0cf5c 18835 (insert ": \n")
20908596
CD
18836 (forward-line -1))
18837 ((and off (looking-at re))
18838 (replace-match "" t t nil 1))
c8d0cf5c 18839 ((not off) (org-move-to-column cc t) (insert ": ")))
20908596
CD
18840 (forward-line 1)))
18841 (save-excursion
18842 (org-back-to-heading)
18843 (if (looking-at (concat outline-regexp
18844 "\\( *\\<" org-quote-string "\\>[ \t]*\\)"))
18845 (replace-match "" t t nil 1)
18846 (if (looking-at outline-regexp)
18847 (progn
18848 (goto-char (match-end 0))
18849 (insert org-quote-string " "))))))))
891f4676 18850
c8d0cf5c
CD
18851(defun org-reftex-citation ()
18852 "Use reftex-citation to insert a citation into the buffer.
18853This looks for a line like
18854
18855#+BIBLIOGRAPHY: foo plain option:-d
18856
8bfe682a 18857and derives from it that foo.bib is the bibliography file relevant
c8d0cf5c
CD
18858for this document. It then installs the necessary environment for RefTeX
18859to work in this buffer and calls `reftex-citation' to insert a citation
18860into the buffer.
18861
18862Export of such citations to both LaTeX and HTML is handled by the contributed
18863package org-exp-bibtex by Taru Karttunen."
18864 (interactive)
18865 (let ((reftex-docstruct-symbol 'rds)
18866 (reftex-cite-format "\\cite{%l}")
18867 rds bib)
18868 (save-excursion
18869 (save-restriction
18870 (widen)
18871 (let ((case-fold-search t)
18872 (re "^#\\+bibliography:[ \t]+\\([^ \t\n]+\\)"))
18873 (if (not (save-excursion
18874 (or (re-search-forward re nil t)
18875 (re-search-backward re nil t))))
18876 (error "No bibliography defined in file")
18877 (setq bib (concat (match-string 1) ".bib")
18878 rds (list (list 'bib bib)))))))
18879 (call-interactively 'reftex-citation)))
18880
20908596 18881;;;; Functions extending outline functionality
2a57416f 18882
1e8fbb6d 18883(defun org-beginning-of-line (&optional arg)
891f4676 18884 "Go to the beginning of the current line. If that is invisible, continue
1e8fbb6d
CD
18885to a visible line beginning. This makes the function of C-a more intuitive.
18886If this is a headline, and `org-special-ctrl-a/e' is set, ignore tags on the
18887first attempt, and only move to after the tags when the cursor is already
18888beyond the end of the headline."
18889 (interactive "P")
c8d0cf5c
CD
18890 (let ((pos (point))
18891 (special (if (consp org-special-ctrl-a/e)
18892 (car org-special-ctrl-a/e)
18893 org-special-ctrl-a/e))
18894 refpos)
18895 (if (org-bound-and-true-p line-move-visual)
18896 (beginning-of-visual-line 1)
18897 (beginning-of-line 1))
7b96ff9a
CD
18898 (if (and arg (fboundp 'move-beginning-of-line))
18899 (call-interactively 'move-beginning-of-line)
18900 (if (bobp)
18901 nil
18902 (backward-char 1)
86fbb8ca
CD
18903 (if (org-truely-invisible-p)
18904 (while (and (not (bobp)) (org-truely-invisible-p))
7b96ff9a
CD
18905 (backward-char 1)
18906 (beginning-of-line 1))
18907 (forward-char 1))))
c8d0cf5c 18908 (when special
48aaad2d 18909 (cond
b349f79f 18910 ((and (looking-at org-complex-heading-regexp)
48aaad2d 18911 (= (char-after (match-end 1)) ?\ ))
b349f79f
CD
18912 (setq refpos (min (1+ (or (match-end 3) (match-end 2) (match-end 1)))
18913 (point-at-eol)))
48aaad2d 18914 (goto-char
c8d0cf5c 18915 (if (eq special t)
b349f79f
CD
18916 (cond ((> pos refpos) refpos)
18917 ((= pos (point)) refpos)
374585c9
CD
18918 (t (point)))
18919 (cond ((> pos (point)) (point))
18920 ((not (eq last-command this-command)) (point))
b349f79f 18921 (t refpos)))))
48aaad2d
CD
18922 ((org-at-item-p)
18923 (goto-char
c8d0cf5c 18924 (if (eq special t)
374585c9
CD
18925 (cond ((> pos (match-end 4)) (match-end 4))
18926 ((= pos (point)) (match-end 4))
18927 (t (point)))
18928 (cond ((> pos (point)) (point))
18929 ((not (eq last-command this-command)) (point))
b349f79f
CD
18930 (t (match-end 4))))))))
18931 (org-no-warnings
18932 (and (featurep 'xemacs) (setq zmacs-region-stays t)))))
04d18304 18933
1e8fbb6d
CD
18934(defun org-end-of-line (&optional arg)
18935 "Go to the end of the line.
18936If this is a headline, and `org-special-ctrl-a/e' is set, ignore tags on the
18937first attempt, and only move to after the tags when the cursor is already
18938beyond the end of the headline."
18939 (interactive "P")
c8d0cf5c
CD
18940 (let ((special (if (consp org-special-ctrl-a/e)
18941 (cdr org-special-ctrl-a/e)
18942 org-special-ctrl-a/e)))
18943 (if (or (not special)
18944 (not (org-on-heading-p))
18945 arg)
18946 (call-interactively
18947 (cond ((org-bound-and-true-p line-move-visual) 'end-of-visual-line)
18948 ((fboundp 'move-end-of-line) 'move-end-of-line)
18949 (t 'end-of-line)))
18950 (let ((pos (point)))
18951 (beginning-of-line 1)
afe98dfa 18952 (if (looking-at (org-re ".*?\\(?:\\([ \t]*\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*\\)?$"))
c8d0cf5c
CD
18953 (if (eq special t)
18954 (if (or (< pos (match-beginning 1))
18955 (= pos (match-end 0)))
18956 (goto-char (match-beginning 1))
18957 (goto-char (match-end 0)))
18958 (if (or (< pos (match-end 0)) (not (eq this-command last-command)))
18959 (goto-char (match-end 0))
18960 (goto-char (match-beginning 1))))
18961 (call-interactively (if (fboundp 'move-end-of-line)
18962 'move-end-of-line
18963 'end-of-line)))))
18964 (org-no-warnings
18965 (and (featurep 'xemacs) (setq zmacs-region-stays t)))))
b349f79f 18966
5137195a 18967(define-key org-mode-map "\C-a" 'org-beginning-of-line)
1e8fbb6d 18968(define-key org-mode-map "\C-e" 'org-end-of-line)
891f4676 18969
c8d0cf5c
CD
18970(defun org-backward-sentence (&optional arg)
18971 "Go to beginning of sentence, or beginning of table field.
18972This will call `backward-sentence' or `org-table-beginning-of-field',
18973depending on context."
18974 (interactive "P")
18975 (cond
18976 ((org-at-table-p) (call-interactively 'org-table-beginning-of-field))
18977 (t (call-interactively 'backward-sentence))))
18978
18979(defun org-forward-sentence (&optional arg)
18980 "Go to end of sentence, or end of table field.
18981This will call `forward-sentence' or `org-table-end-of-field',
18982depending on context."
18983 (interactive "P")
18984 (cond
18985 ((org-at-table-p) (call-interactively 'org-table-end-of-field))
18986 (t (call-interactively 'forward-sentence))))
18987
18988(define-key org-mode-map "\M-a" 'org-backward-sentence)
18989(define-key org-mode-map "\M-e" 'org-forward-sentence)
18990
2a57416f
CD
18991(defun org-kill-line (&optional arg)
18992 "Kill line, to tags or end of line."
18993 (interactive "P")
18994 (cond
18995 ((or (not org-special-ctrl-k)
18996 (bolp)
18997 (not (org-on-heading-p)))
86fbb8ca
CD
18998 (if (and (get-char-property (min (point-max) (point-at-eol)) 'invisible)
18999 org-ctrl-k-protect-subtree)
19000 (if (or (eq org-ctrl-k-protect-subtree 'error)
19001 (not (y-or-n-p "Kill hidden subtree along with headline? ")))
19002 (error "C-k aborted - would kill hidden subtree")))
2a57416f 19003 (call-interactively 'kill-line))
afe98dfa 19004 ((looking-at (org-re ".*?\\S-\\([ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)[ \t]*$"))
2a57416f
CD
19005 (kill-region (point) (match-beginning 1))
19006 (org-set-tags nil t))
19007 (t (kill-region (point) (point-at-eol)))))
19008
19009(define-key org-mode-map "\C-k" 'org-kill-line)
19010
93b62de8
CD
19011(defun org-yank (&optional arg)
19012 "Yank. If the kill is a subtree, treat it specially.
19013This command will look at the current kill and check if is a single
19014subtree, or a series of subtrees[1]. If it passes the test, and if the
19015cursor is at the beginning of a line or after the stars of a currently
33306645 19016empty headline, then the yank is handled specially. How exactly depends
93b62de8
CD
19017on the value of the following variables, both set by default.
19018
19019org-yank-folded-subtrees
33306645 19020 When set, the subtree(s) will be folded after insertion, but only
93b62de8
CD
19021 if doing so would now swallow text after the yanked text.
19022
19023org-yank-adjusted-subtrees
19024 When set, the subtree will be promoted or demoted in order to
19025 fit into the local outline tree structure, which means that the level
19026 will be adjusted so that it becomes the smaller one of the two
19027 *visible* surrounding headings.
19028
19029Any prefix to this command will cause `yank' to be called directly with
86fbb8ca
CD
19030no special treatment. In particular, a simple \\[universal-argument] prefix \
19031will just
93b62de8
CD
19032plainly yank the text as it is.
19033
c8d0cf5c 19034\[1] The test checks if the first non-white line is a heading
93b62de8
CD
19035 and if there are no other headings with fewer stars."
19036 (interactive "P")
c8d0cf5c
CD
19037 (org-yank-generic 'yank arg))
19038
19039(defun org-yank-generic (command arg)
19040 "Perform some yank-like command.
19041
19042This function implements the behavior described in the `org-yank'
01c35094 19043documentation. However, it has been generalized to work for any
c8d0cf5c
CD
19044interactive command with similar behavior."
19045
19046 ;; pretend to be command COMMAND
19047 (setq this-command command)
19048
93b62de8 19049 (if arg
c8d0cf5c
CD
19050 (call-interactively command)
19051
93b62de8
CD
19052 (let ((subtreep ; is kill a subtree, and the yank position appropriate?
19053 (and (org-kill-is-subtree-p)
19054 (or (bolp)
19055 (and (looking-at "[ \t]*$")
ce4fdcb9 19056 (string-match
93b62de8
CD
19057 "\\`\\*+\\'"
19058 (buffer-substring (point-at-bol) (point)))))))
19059 swallowp)
19060 (cond
19061 ((and subtreep org-yank-folded-subtrees)
19062 (let ((beg (point))
19063 end)
19064 (if (and subtreep org-yank-adjusted-subtrees)
19065 (org-paste-subtree nil nil 'for-yank)
c8d0cf5c
CD
19066 (call-interactively command))
19067
93b62de8
CD
19068 (setq end (point))
19069 (goto-char beg)
19070 (when (and (bolp) subtreep
19071 (not (setq swallowp
19072 (org-yank-folding-would-swallow-text beg end))))
19073 (or (looking-at outline-regexp)
19074 (re-search-forward (concat "^" outline-regexp) end t))
19075 (while (and (< (point) end) (looking-at outline-regexp))
19076 (hide-subtree)
19077 (org-cycle-show-empty-lines 'folded)
19078 (condition-case nil
19079 (outline-forward-same-level 1)
19080 (error (goto-char end)))))
19081 (when swallowp
19082 (message
c8d0cf5c
CD
19083 "Inserted text not folded because that would swallow text"))
19084
93b62de8
CD
19085 (goto-char end)
19086 (skip-chars-forward " \t\n\r")
ce4fdcb9
CD
19087 (beginning-of-line 1)
19088 (push-mark beg 'nomsg)))
93b62de8 19089 ((and subtreep org-yank-adjusted-subtrees)
ce4fdcb9
CD
19090 (let ((beg (point-at-bol)))
19091 (org-paste-subtree nil nil 'for-yank)
19092 (push-mark beg 'nomsg)))
93b62de8 19093 (t
c8d0cf5c 19094 (call-interactively command))))))
ce4fdcb9 19095
93b62de8
CD
19096(defun org-yank-folding-would-swallow-text (beg end)
19097 "Would hide-subtree at BEG swallow any text after END?"
19098 (let (level)
19099 (save-excursion
19100 (goto-char beg)
19101 (when (or (looking-at outline-regexp)
19102 (re-search-forward (concat "^" outline-regexp) end t))
19103 (setq level (org-outline-level)))
19104 (goto-char end)
19105 (skip-chars-forward " \t\r\n\v\f")
19106 (if (or (eobp)
19107 (and (bolp) (looking-at org-outline-regexp)
19108 (<= (org-outline-level) level)))
19109 nil ; Nothing would be swallowed
19110 t)))) ; something would swallow
621f83e4
CD
19111
19112(define-key org-mode-map "\C-y" 'org-yank)
19113
891f4676
RS
19114(defun org-invisible-p ()
19115 "Check if point is at a character currently not visible."
5137195a
CD
19116 ;; Early versions of noutline don't have `outline-invisible-p'.
19117 (if (fboundp 'outline-invisible-p)
19118 (outline-invisible-p)
19119 (get-char-property (point) 'invisible)))
891f4676 19120
86fbb8ca
CD
19121(defun org-truely-invisible-p ()
19122 "Check if point is at a character currently not visible.
19123This version does not only check the character property, but also
19124`visible-mode'."
19125 ;; Early versions of noutline don't have `outline-invisible-p'.
19126 (if (org-bound-and-true-p visible-mode)
19127 nil
19128 (if (fboundp 'outline-invisible-p)
19129 (outline-invisible-p)
19130 (get-char-property (point) 'invisible))))
19131
a96ee7df
CD
19132(defun org-invisible-p2 ()
19133 "Check if point is at a character currently not visible."
19134 (save-excursion
5137195a
CD
19135 (if (and (eolp) (not (bobp))) (backward-char 1))
19136 ;; Early versions of noutline don't have `outline-invisible-p'.
19137 (if (fboundp 'outline-invisible-p)
19138 (outline-invisible-p)
19139 (get-char-property (point) 'invisible))))
19140
ce4fdcb9
CD
19141(defun org-back-to-heading (&optional invisible-ok)
19142 "Call `outline-back-to-heading', but provide a better error message."
19143 (condition-case nil
19144 (outline-back-to-heading invisible-ok)
19145 (error (error "Before first headline at position %d in buffer %s"
19146 (point) (current-buffer)))))
19147
86fbb8ca
CD
19148(defun org-beginning-of-defun ()
19149 "Go to the beginning of the subtree, i.e. back to the heading."
19150 (org-back-to-heading))
19151(defun org-end-of-defun ()
19152 "Go to the end of the subtree."
19153 (org-end-of-subtree nil t))
19154
db55f368
CD
19155(defun org-before-first-heading-p ()
19156 "Before first heading?"
19157 (save-excursion
19158 (null (re-search-backward "^\\*+ " nil t))))
19159
8d642074
CD
19160(defun org-on-heading-p (&optional ignored)
19161 (outline-on-heading-p t))
19162(defun org-at-heading-p (&optional ignored)
19163 (outline-on-heading-p t))
19164
ed21c5c8
CD
19165(defun org-point-at-end-of-empty-headline ()
19166 "If point is at the end of an empty headline, return t, else nil.
19167If the heading only contains a TODO keyword, it is still still considered
19168empty."
19169 (and (looking-at "[ \t]*$")
19170 (save-excursion
19171 (beginning-of-line 1)
19172 (looking-at (concat "^\\(\\*+\\)[ \t]+\\(" org-todo-regexp
19173 "\\)?[ \t]*$")))))
a3fbe8c4
CD
19174(defun org-at-heading-or-item-p ()
19175 (or (org-on-heading-p) (org-at-item-p)))
891f4676 19176
a96ee7df 19177(defun org-on-target-p ()
d3f4dbe8
CD
19178 (or (org-in-regexp org-radio-target-regexp)
19179 (org-in-regexp org-target-regexp)))
a96ee7df 19180
891f4676
RS
19181(defun org-up-heading-all (arg)
19182 "Move to the heading line of which the present line is a subheading.
19183This function considers both visible and invisible heading lines.
19184With argument, move up ARG levels."
5137195a
CD
19185 (if (fboundp 'outline-up-heading-all)
19186 (outline-up-heading-all arg) ; emacs 21 version of outline.el
19187 (outline-up-heading arg t))) ; emacs 22 version of outline.el
891f4676 19188
d5098885
JW
19189(defun org-up-heading-safe ()
19190 "Move to the heading line of which the present line is a subheading.
19191This version will not throw an error. It will return the level of the
c8d0cf5c
CD
19192headline found, or nil if no higher level is found.
19193
19194Also, this function will be a lot faster than `outline-up-heading',
19195because it relies on stars being the outline starters. This can really
19196make a significant difference in outlines with very many siblings."
db55f368
CD
19197 (let (start-level re)
19198 (org-back-to-heading t)
19199 (setq start-level (funcall outline-level))
19200 (if (equal start-level 1)
19201 nil
19202 (setq re (concat "^\\*\\{1," (number-to-string (1- start-level)) "\\} "))
19203 (if (re-search-backward re nil t)
19204 (funcall outline-level)))))
d5098885 19205
8c6fb58b
CD
19206(defun org-first-sibling-p ()
19207 "Is this heading the first child of its parents?"
19208 (interactive)
19209 (let ((re (concat "^" outline-regexp))
19210 level l)
19211 (unless (org-at-heading-p t)
19212 (error "Not at a heading"))
19213 (setq level (funcall outline-level))
19214 (save-excursion
19215 (if (not (re-search-backward re nil t))
19216 t
19217 (setq l (funcall outline-level))
19218 (< l level)))))
19219
3278a016
CD
19220(defun org-goto-sibling (&optional previous)
19221 "Goto the next sibling, even if it is invisible.
19222When PREVIOUS is set, go to the previous sibling instead. Returns t
19223when a sibling was found. When none is found, return nil and don't
19224move point."
19225 (let ((fun (if previous 're-search-backward 're-search-forward))
19226 (pos (point))
19227 (re (concat "^" outline-regexp))
19228 level l)
5152b597
CD
19229 (when (condition-case nil (org-back-to-heading t) (error nil))
19230 (setq level (funcall outline-level))
19231 (catch 'exit
19232 (or previous (forward-char 1))
19233 (while (funcall fun re nil t)
19234 (setq l (funcall outline-level))
19235 (when (< l level) (goto-char pos) (throw 'exit nil))
19236 (when (= l level) (goto-char (match-beginning 0)) (throw 'exit t)))
19237 (goto-char pos)
19238 nil))))
3278a016 19239
d3f4dbe8
CD
19240(defun org-show-siblings ()
19241 "Show all siblings of the current headline."
19242 (save-excursion
19243 (while (org-goto-sibling) (org-flag-heading nil)))
19244 (save-excursion
19245 (while (org-goto-sibling 'previous)
19246 (org-flag-heading nil))))
19247
afe98dfa
CD
19248(defun org-goto-first-child ()
19249 "Goto the first child, even if it is invisible.
01c35094 19250Return t when a child was found. Otherwise don't move point and
afe98dfa
CD
19251return nil."
19252 (let (level (pos (point)) (re (concat "^" outline-regexp)))
19253 (when (condition-case nil (org-back-to-heading t) (error nil))
19254 (setq level (outline-level))
19255 (forward-char 1)
19256 (if (and (re-search-forward re nil t) (> (outline-level) level))
19257 (progn (goto-char (match-beginning 0)) t)
19258 (goto-char pos) nil))))
19259
891f4676
RS
19260(defun org-show-hidden-entry ()
19261 "Show an entry where even the heading is hidden."
19262 (save-excursion
634a7d0b 19263 (org-show-entry)))
891f4676 19264
891f4676 19265(defun org-flag-heading (flag &optional entry)
2dd9129f 19266 "Flag the current heading. FLAG non-nil means make invisible.
891f4676
RS
19267When ENTRY is non-nil, show the entire entry."
19268 (save-excursion
19269 (org-back-to-heading t)
891f4676
RS
19270 ;; Check if we should show the entire entry
19271 (if entry
c8d16429
CD
19272 (progn
19273 (org-show-entry)
4b3a9ba7
CD
19274 (save-excursion
19275 (and (outline-next-heading)
19276 (org-flag-heading nil))))
48aaad2d 19277 (outline-flag-region (max (point-min) (1- (point)))
c8d16429 19278 (save-excursion (outline-end-of-heading) (point))
5137195a 19279 flag))))
891f4676 19280
621f83e4
CD
19281(defun org-get-next-sibling ()
19282 "Move to next heading of the same level, and return point.
19283If there is no such heading, return nil.
19284This is like outline-next-sibling, but invisible headings are ok."
19285 (let ((level (funcall outline-level)))
19286 (outline-next-heading)
19287 (while (and (not (eobp)) (> (funcall outline-level) level))
19288 (outline-next-heading))
19289 (if (or (eobp) (< (funcall outline-level) level))
19290 nil
19291 (point))))
19292
54a0dee5
CD
19293(defun org-get-last-sibling ()
19294 "Move to previous heading of the same level, and return point.
19295If there is no such heading, return nil."
19296 (let ((opoint (point))
19297 (level (funcall outline-level)))
19298 (outline-previous-heading)
19299 (when (and (/= (point) opoint) (outline-on-heading-p t))
19300 (while (and (> (funcall outline-level) level)
19301 (not (bobp)))
19302 (outline-previous-heading))
19303 (if (< (funcall outline-level) level)
19304 nil
19305 (point)))))
19306
a3fbe8c4 19307(defun org-end-of-subtree (&optional invisible-OK to-heading)
c8d0cf5c 19308 ;; This contains an exact copy of the original function, but it uses
04d18304
CD
19309 ;; `org-back-to-heading', to make it work also in invisible
19310 ;; trees. And is uses an invisible-OK argument.
19311 ;; Under Emacs this is not needed, but the old outline.el needs this fix.
c8d0cf5c
CD
19312 ;; Furthermore, when used inside Org, finding the end of a large subtree
19313 ;; with many children and grandchildren etc, this can be much faster
19314 ;; than the outline version.
04d18304 19315 (org-back-to-heading invisible-OK)
f462ee2c 19316 (let ((first t)
04d18304 19317 (level (funcall outline-level)))
c8d0cf5c
CD
19318 (if (and (org-mode-p) (< level 1000))
19319 ;; A true heading (not a plain list item), in Org-mode
19320 ;; This means we can easily find the end by looking
19321 ;; only for the right number of stars. Using a regexp to do
19322 ;; this is so much faster than using a Lisp loop.
19323 (let ((re (concat "^\\*\\{1," (int-to-string level) "\\} ")))
19324 (forward-char 1)
19325 (and (re-search-forward re nil 'move) (beginning-of-line 1)))
19326 ;; something else, do it the slow way
19327 (while (and (not (eobp))
19328 (or first (> (funcall outline-level) level)))
19329 (setq first nil)
19330 (outline-next-heading)))
a3fbe8c4
CD
19331 (unless to-heading
19332 (if (memq (preceding-char) '(?\n ?\^M))
c8d0cf5c
CD
19333 (progn
19334 ;; Go to end of line before heading
19335 (forward-char -1)
19336 (if (memq (preceding-char) '(?\n ?\^M))
19337 ;; leave blank line before heading
19338 (forward-char -1))))))
0fee8d6e 19339 (point))
04d18304 19340
c8d0cf5c
CD
19341(defadvice outline-end-of-subtree (around prefer-org-version activate compile)
19342 "Use Org version in org-mode, for dramatic speed-up."
19343 (if (eq major-mode 'org-mode)
19344 (progn
19345 (org-end-of-subtree nil t)
8d642074 19346 (unless (eobp) (backward-char 1)))
c8d0cf5c
CD
19347 ad-do-it))
19348
19349(defun org-forward-same-level (arg &optional invisible-ok)
19350 "Move forward to the arg'th subheading at same level as this one.
afe98dfa
CD
19351Stop at the first and last subheadings of a superior heading.
19352Normally this only looks at visible headings, but when INVISIBLE-OK is non-nil
19353it wil also look at invisible ones."
c8d0cf5c
CD
19354 (interactive "p")
19355 (org-back-to-heading invisible-ok)
19356 (org-on-heading-p)
19357 (let* ((level (- (match-end 0) (match-beginning 0) 1))
19358 (re (format "^\\*\\{1,%d\\} " level))
19359 l)
19360 (forward-char 1)
19361 (while (> arg 0)
19362 (while (and (re-search-forward re nil 'move)
19363 (setq l (- (match-end 0) (match-beginning 0) 1))
19364 (= l level)
19365 (not invisible-ok)
ed21c5c8 19366 (progn (backward-char 1) (org-invisible-p)))
c8d0cf5c
CD
19367 (if (< l level) (setq arg 1)))
19368 (setq arg (1- arg)))
19369 (beginning-of-line 1)))
19370
19371(defun org-backward-same-level (arg &optional invisible-ok)
19372 "Move backward to the arg'th subheading at same level as this one.
19373Stop at the first and last subheadings of a superior heading."
19374 (interactive "p")
19375 (org-back-to-heading)
19376 (org-on-heading-p)
19377 (let* ((level (- (match-end 0) (match-beginning 0) 1))
19378 (re (format "^\\*\\{1,%d\\} " level))
19379 l)
19380 (while (> arg 0)
19381 (while (and (re-search-backward re nil 'move)
19382 (setq l (- (match-end 0) (match-beginning 0) 1))
19383 (= l level)
19384 (not invisible-ok)
19385 (org-invisible-p))
19386 (if (< l level) (setq arg 1)))
19387 (setq arg (1- arg)))))
19388
634a7d0b
CD
19389(defun org-show-subtree ()
19390 "Show everything after this heading at deeper levels."
64f72ae1
JB
19391 (outline-flag-region
19392 (point)
634a7d0b 19393 (save-excursion
54a0dee5 19394 (org-end-of-subtree t t))
5137195a 19395 nil))
634a7d0b
CD
19396
19397(defun org-show-entry ()
19398 "Show the body directly following this heading.
19399Show the heading too, if it is currently invisible."
19400 (interactive)
19401 (save-excursion
15841868
JW
19402 (condition-case nil
19403 (progn
19404 (org-back-to-heading t)
19405 (outline-flag-region
19406 (max (point-min) (1- (point)))
19407 (save-excursion
c8d0cf5c
CD
19408 (if (re-search-forward
19409 (concat "[\r\n]\\(" outline-regexp "\\)") nil t)
19410 (match-beginning 1)
19411 (point-max)))
19412 nil)
19413 (org-cycle-hide-drawers 'children))
15841868 19414 (error nil))))
634a7d0b 19415
c8d0cf5c 19416(defun org-make-options-regexp (kwds &optional extra)
891f4676
RS
19417 "Make a regular expression for keyword lines."
19418 (concat
5137195a 19419 "^"
891f4676
RS
19420 "#?[ \t]*\\+\\("
19421 (mapconcat 'regexp-quote kwds "\\|")
c8d0cf5c 19422 (if extra (concat "\\|" extra))
891f4676 19423 "\\):[ \t]*"
c8d0cf5c 19424 "\\(.*\\)"))
891f4676 19425
d3f4dbe8
CD
19426;; Make isearch reveal the necessary context
19427(defun org-isearch-end ()
19428 "Reveal context after isearch exits."
19429 (when isearch-success ; only if search was successful
19430 (if (featurep 'xemacs)
19431 ;; Under XEmacs, the hook is run in the correct place,
19432 ;; we directly show the context.
19433 (org-show-context 'isearch)
19434 ;; In Emacs the hook runs *before* restoring the overlays.
19435 ;; So we have to use a one-time post-command-hook to do this.
19436 ;; (Emacs 22 has a special variable, see function `org-mode')
19437 (unless (and (boundp 'isearch-mode-end-hook-quit)
19438 isearch-mode-end-hook-quit)
19439 ;; Only when the isearch was not quitted.
19440 (org-add-hook 'post-command-hook 'org-isearch-post-command
19441 'append 'local)))))
19442
19443(defun org-isearch-post-command ()
19444 "Remove self from hook, and show context."
19445 (remove-hook 'post-command-hook 'org-isearch-post-command 'local)
19446 (org-show-context 'isearch))
19447
a3fbe8c4 19448
8c6fb58b
CD
19449;;;; Integration with and fixes for other packages
19450
19451;;; Imenu support
19452
19453(defvar org-imenu-markers nil
19454 "All markers currently used by Imenu.")
19455(make-variable-buffer-local 'org-imenu-markers)
19456
19457(defun org-imenu-new-marker (&optional pos)
19458 "Return a new marker for use by Imenu, and remember the marker."
19459 (let ((m (make-marker)))
19460 (move-marker m (or pos (point)))
19461 (push m org-imenu-markers)
19462 m))
19463
19464(defun org-imenu-get-tree ()
19465 "Produce the index for Imenu."
19466 (mapc (lambda (x) (move-marker x nil)) org-imenu-markers)
19467 (setq org-imenu-markers nil)
19468 (let* ((n org-imenu-depth)
19469 (re (concat "^" outline-regexp))
19470 (subs (make-vector (1+ n) nil))
19471 (last-level 0)
65c439fd 19472 m level head)
8c6fb58b
CD
19473 (save-excursion
19474 (save-restriction
19475 (widen)
19476 (goto-char (point-max))
19477 (while (re-search-backward re nil t)
19478 (setq level (org-reduced-level (funcall outline-level)))
19479 (when (<= level n)
19480 (looking-at org-complex-heading-regexp)
621f83e4
CD
19481 (setq head (org-link-display-format
19482 (org-match-string-no-properties 4))
8c6fb58b
CD
19483 m (org-imenu-new-marker))
19484 (org-add-props head nil 'org-imenu-marker m 'org-imenu t)
19485 (if (>= level last-level)
19486 (push (cons head m) (aref subs level))
19487 (push (cons head (aref subs (1+ level))) (aref subs level))
19488 (loop for i from (1+ level) to n do (aset subs i nil)))
19489 (setq last-level level)))))
19490 (aref subs 1)))
19491
19492(eval-after-load "imenu"
19493 '(progn
19494 (add-hook 'imenu-after-jump-hook
2c3ad40d
CD
19495 (lambda ()
19496 (if (eq major-mode 'org-mode)
19497 (org-show-context 'org-goto))))))
8c6fb58b 19498
621f83e4
CD
19499(defun org-link-display-format (link)
19500 "Replace a link with either the description, or the link target
19501if no description is present"
19502 (save-match-data
19503 (if (string-match org-bracket-link-analytic-regexp link)
8bfe682a
CD
19504 (replace-match (if (match-end 5)
19505 (match-string 5 link)
19506 (concat (match-string 1 link)
19507 (match-string 3 link)))
19508 nil t link)
621f83e4
CD
19509 link)))
19510
8c6fb58b
CD
19511;; Speedbar support
19512
86fbb8ca 19513(defvar org-speedbar-restriction-lock-overlay (make-overlay 1 1)
20908596 19514 "Overlay marking the agenda restriction line in speedbar.")
86fbb8ca 19515(overlay-put org-speedbar-restriction-lock-overlay
20908596 19516 'face 'org-agenda-restriction-lock)
86fbb8ca 19517(overlay-put org-speedbar-restriction-lock-overlay
20908596
CD
19518 'help-echo "Agendas are currently limited to this item.")
19519(org-detach-overlay org-speedbar-restriction-lock-overlay)
19520
8c6fb58b
CD
19521(defun org-speedbar-set-agenda-restriction ()
19522 "Restrict future agenda commands to the location at point in speedbar.
19523To get rid of the restriction, use \\[org-agenda-remove-restriction-lock]."
19524 (interactive)
20908596 19525 (require 'org-agenda)
65c439fd 19526 (let (p m tp np dir txt)
8c6fb58b
CD
19527 (cond
19528 ((setq p (text-property-any (point-at-bol) (point-at-eol)
19529 'org-imenu t))
19530 (setq m (get-text-property p 'org-imenu-marker))
8bfe682a
CD
19531 (with-current-buffer (marker-buffer m)
19532 (goto-char m)
19533 (org-agenda-set-restriction-lock 'subtree)))
8c6fb58b
CD
19534 ((setq p (text-property-any (point-at-bol) (point-at-eol)
19535 'speedbar-function 'speedbar-find-file))
19536 (setq tp (previous-single-property-change
19537 (1+ p) 'speedbar-function)
19538 np (next-single-property-change
19539 tp 'speedbar-function)
19540 dir (speedbar-line-directory)
19541 txt (buffer-substring-no-properties (or tp (point-min))
19542 (or np (point-max))))
8bfe682a
CD
19543 (with-current-buffer (find-file-noselect
19544 (let ((default-directory dir))
19545 (expand-file-name txt)))
19546 (unless (org-mode-p)
19547 (error "Cannot restrict to non-Org-mode file"))
19548 (org-agenda-set-restriction-lock 'file)))
8c6fb58b 19549 (t (error "Don't know how to restrict Org-mode's agenda")))
86fbb8ca
CD
19550 (move-overlay org-speedbar-restriction-lock-overlay
19551 (point-at-bol) (point-at-eol))
8c6fb58b
CD
19552 (setq current-prefix-arg nil)
19553 (org-agenda-maybe-redo)))
19554
19555(eval-after-load "speedbar"
19556 '(progn
19557 (speedbar-add-supported-extension ".org")
19558 (define-key speedbar-file-key-map "<" 'org-speedbar-set-agenda-restriction)
19559 (define-key speedbar-file-key-map "\C-c\C-x<" 'org-speedbar-set-agenda-restriction)
19560 (define-key speedbar-file-key-map ">" 'org-agenda-remove-restriction-lock)
19561 (define-key speedbar-file-key-map "\C-c\C-x>" 'org-agenda-remove-restriction-lock)
19562 (add-hook 'speedbar-visiting-tag-hook
1ba1f458 19563 (lambda () (and (org-mode-p) (org-show-context 'org-goto))))))
8c6fb58b 19564
20908596 19565;;; Fixes and Hacks for problems with other packages
a3fbe8c4
CD
19566
19567;; Make flyspell not check words in links, to not mess up our keymap
19568(defun org-mode-flyspell-verify ()
19569 "Don't let flyspell put overlays at active buttons."
afe98dfa
CD
19570 (and (not (get-text-property (max (1- (point)) (point-min)) 'keymap))
19571 (not (get-text-property (max (1- (point)) (point-min)) 'org-no-flyspell))))
c8d0cf5c
CD
19572
19573(defun org-remove-flyspell-overlays-in (beg end)
19574 "Remove flyspell overlays in region."
19575 (and (org-bound-and-true-p flyspell-mode)
19576 (fboundp 'flyspell-delete-region-overlays)
19577 (flyspell-delete-region-overlays beg end))
19578 (add-text-properties beg end '(org-no-flyspell t)))
d3f4dbe8 19579
8bfe682a 19580;; Make `bookmark-jump' shows the jump location if it was hidden.
891f4676 19581(eval-after-load "bookmark"
b9661543
CD
19582 '(if (boundp 'bookmark-after-jump-hook)
19583 ;; We can use the hook
19584 (add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide)
19585 ;; Hook not available, use advice
19586 (defadvice bookmark-jump (after org-make-visible activate)
19587 "Make the position visible."
19588 (org-bookmark-jump-unhide))))
19589
8bfe682a 19590;; Make sure saveplace shows the location if it was hidden
93b62de8
CD
19591(eval-after-load "saveplace"
19592 '(defadvice save-place-find-file-hook (after org-make-visible activate)
19593 "Make the position visible."
19594 (org-bookmark-jump-unhide)))
19595
8bfe682a
CD
19596;; Make sure ecb shows the location if it was hidden
19597(eval-after-load "ecb"
19598 '(defadvice ecb-method-clicked (after esf/org-show-context activate)
19599 "Make hierarchy visible when jumping into location from ECB tree buffer."
19600 (if (eq major-mode 'org-mode)
19601 (org-show-context))))
19602
b9661543
CD
19603(defun org-bookmark-jump-unhide ()
19604 "Unhide the current position, to show the bookmark location."
b928f99a 19605 (and (org-mode-p)
b9661543
CD
19606 (or (org-invisible-p)
19607 (save-excursion (goto-char (max (point-min) (1- (point))))
19608 (org-invisible-p)))
3278a016 19609 (org-show-context 'bookmark-jump)))
891f4676 19610
3278a016
CD
19611;; Make session.el ignore our circular variable
19612(eval-after-load "session"
19613 '(add-to-list 'session-globals-exclude 'org-mark-ring))
0fee8d6e 19614
d3f4dbe8 19615;;;; Experimental code
b928f99a 19616
a3fbe8c4
CD
19617(defun org-closed-in-range ()
19618 "Sparse tree of items closed in a certain time range.
8c6fb58b 19619Still experimental, may disappear in the future."
a3fbe8c4
CD
19620 (interactive)
19621 ;; Get the time interval from the user.
54a0dee5 19622 (let* ((time1 (org-float-time
a3fbe8c4 19623 (org-read-date nil 'to-time nil "Starting date: ")))
54a0dee5 19624 (time2 (org-float-time
a3fbe8c4
CD
19625 (org-read-date nil 'to-time nil "End date:")))
19626 ;; callback function
19627 (callback (lambda ()
19628 (let ((time
54a0dee5 19629 (org-float-time
a3fbe8c4
CD
19630 (apply 'encode-time
19631 (org-parse-time-string
19632 (match-string 1))))))
19633 ;; check if time in interval
19634 (and (>= time time1) (<= time time2))))))
19635 ;; make tree, check each match with the callback
19636 (org-occur "CLOSED: +\\[\\(.*?\\)\\]" nil callback)))
d3f4dbe8
CD
19637
19638;;;; Finish up
c44f0d75 19639
f462ee2c
SM
19640(provide 'org)
19641
19642(run-hooks 'org-load-hook)
19643
7d58338e 19644
b349f79f 19645;;; org.el ends here