;;; org.el --- Outline-based notes management and organizer
;; Carstens outline-mode for keeping track of everything.
;; Copyright (C) 2004-2015 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Maintainer: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
;; Homepage: http://orgmode.org
;;
;; This file is part of GNU Emacs.
;;
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;
;;; Commentary:
;;
;; Org-mode is a mode for keeping notes, maintaining ToDo lists, and doing
;; project planning with a fast and effective plain-text system.
;;
;; Org-mode develops organizational tasks around NOTES files that contain
;; information about projects as plain text. Org-mode is implemented on
;; top of outline-mode, which makes it possible to keep the content of
;; large files well structured. Visibility cycling and structure editing
;; help to work with the tree. Tables are easily created with a built-in
;; table editor. Org-mode supports ToDo items, deadlines, time stamps,
;; and scheduling. It dynamically compiles entries into an agenda that
;; utilizes and smoothly integrates much of the Emacs calendar and diary.
;; Plain text URL-like links connect to websites, emails, Usenet
;; messages, BBDB entries, and any files related to the projects. For
;; printing and sharing of notes, an Org-mode file can be exported as a
;; structured ASCII file, as HTML, or (todo and agenda items only) as an
;; iCalendar file. It can also serve as a publishing tool for a set of
;; linked webpages.
;;
;; Installation and Activation
;; ---------------------------
;; See the corresponding sections in the manual at
;;
;; http://orgmode.org/org.html#Installation
;;
;; Documentation
;; -------------
;; The documentation of Org-mode can be found in the TeXInfo file. The
;; distribution also contains a PDF version of it. At the homepage of
;; Org-mode, you can read the same text online as HTML. There is also an
;; excellent reference card made by Philip Rooke. This card can be found
;; in the etc/ directory of Emacs 22.
;;
;; A list of recent changes can be found at
;; http://orgmode.org/Changes.html
;;
;;; Code:
(defvar org-inhibit-highlight-removal nil) ; dynamically scoped param
(defvar org-table-formula-constants-local nil
"Local version of `org-table-formula-constants'.")
(make-variable-buffer-local 'org-table-formula-constants-local)
;;;; Require other packages
(eval-when-compile
(require 'cl)
(require 'gnus-sum))
(require 'calendar)
(require 'find-func)
(require 'format-spec)
(or (equal this-command 'eval-buffer)
(condition-case nil
(load (concat (file-name-directory load-file-name)
"org-loaddefs.el")
nil t t t)
(error
(message "WARNING: No org-loaddefs.el file could be found from where org.el is loaded.")
(sit-for 3)
(message "You need to run \"make\" or \"make autoloads\" from Org lisp directory")
(sit-for 3))))
(require 'org-macs)
(require 'org-compat)
;; `org-outline-regexp' ought to be a defconst but is let-bound in
;; some places -- e.g. see the macro `org-with-limited-levels'.
;;
;; In Org buffers, the value of `outline-regexp' is that of
;; `org-outline-regexp'. The only function still directly relying on
;; `outline-regexp' is `org-overview' so that `org-cycle' can do its
;; job when `orgstruct-mode' is active.
(defvar org-outline-regexp "\\*+ "
"Regexp to match Org headlines.")
(defvar org-outline-regexp-bol "^\\*+ "
"Regexp to match Org headlines.
This is similar to `org-outline-regexp' but additionally makes
sure that we are at the beginning of the line.")
(defvar org-heading-regexp "^\\(\\*+\\)\\(?: +\\(.*?\\)\\)?[ \t]*$"
"Matches a headline, putting stars and text into groups.
Stars are put in group 1 and the trimmed body in group 2.")
;; Emacs 22 calendar compatibility: Make sure the new variables are available
(unless (boundp 'calendar-view-holidays-initially-flag)
(org-defvaralias 'calendar-view-holidays-initially-flag
'view-calendar-holidays-initially))
(unless (boundp 'calendar-view-diary-initially-flag)
(org-defvaralias 'calendar-view-diary-initially-flag
'view-diary-entries-initially))
(unless (boundp 'diary-fancy-buffer)
(org-defvaralias 'diary-fancy-buffer 'fancy-diary-buffer))
(declare-function cdlatex-environment "ext:cdlatex" (environment item))
(declare-function org-add-archive-files "org-archive" (files))
(declare-function org-agenda-entry-get-agenda-timestamp "org-agenda" (pom))
(declare-function org-agenda-list "org-agenda" (&optional arg start-day span))
(declare-function org-agenda-redo "org-agenda" (&optional all))
(declare-function org-babel-do-in-edit-buffer "ob-core" (&rest body))
(declare-function org-babel-tangle-file "ob-tangle" (file &optional target-file lang))
(declare-function org-beamer-mode "ox-beamer" ())
(declare-function org-clock-get-last-clock-out-time "org-clock" ())
(declare-function org-clock-out "org-clock" (&optional switch-to-state fail-quietly at-time))
(declare-function org-clock-remove-overlays "org-clock" (&optional beg end noremove))
(declare-function org-clock-sum "org-clock" (&optional tstart tend headline-filter propname))
(declare-function org-clock-sum-current-item "org-clock" (&optional tstart))
(declare-function org-clock-timestamps-down "org-clock" (&optional n))
(declare-function org-clock-timestamps-up "org-clock" (&optional n))
(declare-function org-clock-update-time-maybe "org-clock" ())
(declare-function org-clocktable-shift "org-clock" (dir n))
(declare-function org-element-at-point "org-element" ())
(declare-function org-element-cache-refresh "org-element" (pos))
(declare-function org-element-cache-reset "org-element" (&optional all))
(declare-function org-element-contents "org-element" (element))
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-copy "org-element" (datum))
(declare-function org-element-interpret-data "org-element" (data &optional parent))
(declare-function org-element-lineage "org-element" (blob &optional types with-self))
(declare-function org-element-nested-p "org-element" (elem-a elem-b))
(declare-function org-element-parse-buffer "org-element" (&optional granularity visible-only))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-put-property "org-element" (element property value))
(declare-function org-element-swap-A-B "org-element" (elem-a elem-b))
(declare-function org-element-type "org-element" (element))
(declare-function org-element-update-syntax "org-element" ())
(declare-function org-id-find-id-file "org-id" (id))
(declare-function org-id-get-create "org-id" (&optional force))
(declare-function org-inlinetask-at-task-p "org-inlinetask" ())
(declare-function org-inlinetask-outline-regexp "org-inlinetask" ())
(declare-function org-inlinetask-toggle-visibility "org-inlinetask" ())
(declare-function org-plot/gnuplot "org-plot" (&optional params))
(declare-function org-pop-to-buffer-same-window "org-compat" (&optional buffer-or-name norecord label))
(declare-function org-table-align "org-table" ())
(declare-function org-table-begin "org-table" (&optional table-type))
(declare-function org-table-beginning-of-field "org-table" (&optional n))
(declare-function org-table-blank-field "org-table" ())
(declare-function org-table-calc-current-TBLFM "org-table" (&optional arg))
(declare-function org-table-edit-field "org-table" (arg))
(declare-function org-table-end "org-table" (&optional table-type))
(declare-function org-table-end-of-field "org-table" (&optional n))
(declare-function org-table-insert-row "org-table" (&optional arg))
(declare-function org-table-justify-field-maybe "org-table" (&optional new))
(declare-function org-table-maybe-eval-formula "org-table" ())
(declare-function org-table-maybe-recalculate-line "org-table" ())
(declare-function org-table-next-row "org-table" ())
(declare-function org-table-paste-rectangle "org-table" ())
(declare-function org-table-wrap-region "org-table" (arg))
(declare-function org-tags-view "org-agenda" (&optional todo-only match))
(declare-function orgtbl-ascii-plot "org-table" (&optional ask))
(declare-function orgtbl-mode "org-table" (&optional arg))
(defsubst org-uniquify (list)
"Non-destructively remove duplicate elements from LIST."
(let ((res (copy-sequence list))) (delete-dups res)))
(defsubst org-get-at-bol (property)
"Get text property PROPERTY at the beginning of line."
(get-text-property (point-at-bol) property))
(defsubst org-trim (s)
"Remove whitespace at the beginning and the end of string S."
(replace-regexp-in-string
"\\`[ \t\n\r]+" ""
(replace-regexp-in-string "[ \t\n\r]+\\'" "" s)))
;; load languages based on value of `org-babel-load-languages'
(defvar org-babel-load-languages)
;;;###autoload
(defun org-babel-do-load-languages (sym value)
"Load the languages defined in `org-babel-load-languages'."
(set-default sym value)
(mapc (lambda (pair)
(let ((active (cdr pair)) (lang (symbol-name (car pair))))
(if active
(progn
(require (intern (concat "ob-" lang))))
(progn
(funcall 'fmakunbound
(intern (concat "org-babel-execute:" lang)))
(funcall 'fmakunbound
(intern (concat "org-babel-expand-body:" lang)))))))
org-babel-load-languages))
(declare-function org-babel-tangle-file "ob-tangle" (file &optional target-file lang))
;;;###autoload
(defun org-babel-load-file (file &optional compile)
"Load Emacs Lisp source code blocks in the Org-mode FILE.
This function exports the source code using `org-babel-tangle'
and then loads the resulting file using `load-file'. With prefix
arg (noninteractively: 2nd arg) COMPILE the tangled Emacs Lisp
file to byte-code before it is loaded."
(interactive "fFile to load: \nP")
(let* ((age (lambda (file)
(float-time
(time-subtract (current-time)
(nth 5 (or (file-attributes (file-truename file))
(file-attributes file)))))))
(base-name (file-name-sans-extension file))
(exported-file (concat base-name ".el")))
;; tangle if the org-mode file is newer than the elisp file
(unless (and (file-exists-p exported-file)
(> (funcall age file) (funcall age exported-file)))
;; Tangle-file traversal returns reversed list of tangled files
;; and we want to evaluate the first target.
(setq exported-file
(car (last (org-babel-tangle-file file exported-file "emacs-lisp")))))
(message "%s %s"
(if compile
(progn (byte-compile-file exported-file 'load)
"Compiled and loaded")
(progn (load-file exported-file) "Loaded"))
exported-file)))
(defcustom org-babel-load-languages '((emacs-lisp . t))
"Languages which can be evaluated in Org-mode buffers.
This list can be used to load support for any of the languages
below, note that each language will depend on a different set of
system executables and/or Emacs modes. When a language is
\"loaded\", then code blocks in that language can be evaluated
with `org-babel-execute-src-block' bound by default to C-c
C-c (note the `org-babel-no-eval-on-ctrl-c-ctrl-c' variable can
be set to remove code block evaluation from the C-c C-c
keybinding. By default only Emacs Lisp (which has no
requirements) is loaded."
:group 'org-babel
:set 'org-babel-do-load-languages
:version "24.1"
:type '(alist :tag "Babel Languages"
:key-type
(choice
(const :tag "Awk" awk)
(const :tag "C" C)
(const :tag "R" R)
(const :tag "Asymptote" asymptote)
(const :tag "Calc" calc)
(const :tag "Clojure" clojure)
(const :tag "CSS" css)
(const :tag "Ditaa" ditaa)
(const :tag "Dot" dot)
(const :tag "Emacs Lisp" emacs-lisp)
(const :tag "Forth" forth)
(const :tag "Fortran" fortran)
(const :tag "Gnuplot" gnuplot)
(const :tag "Haskell" haskell)
(const :tag "IO" io)
(const :tag "J" J)
(const :tag "Java" java)
(const :tag "Javascript" js)
(const :tag "LaTeX" latex)
(const :tag "Ledger" ledger)
(const :tag "Lilypond" lilypond)
(const :tag "Lisp" lisp)
(const :tag "Makefile" makefile)
(const :tag "Maxima" maxima)
(const :tag "Matlab" matlab)
(const :tag "Mscgen" mscgen)
(const :tag "Ocaml" ocaml)
(const :tag "Octave" octave)
(const :tag "Org" org)
(const :tag "Perl" perl)
(const :tag "Pico Lisp" picolisp)
(const :tag "PlantUML" plantuml)
(const :tag "Python" python)
(const :tag "Ruby" ruby)
(const :tag "Sass" sass)
(const :tag "Scala" scala)
(const :tag "Scheme" scheme)
(const :tag "Screen" screen)
(const :tag "Shell Script" shell)
(const :tag "Shen" shen)
(const :tag "Sql" sql)
(const :tag "Sqlite" sqlite)
(const :tag "ebnf2ps" ebnf2ps))
:value-type (boolean :tag "Activate" :value t)))
;;;; Customization variables
(defcustom org-clone-delete-id nil
"Remove ID property of clones of a subtree.
When non-nil, clones of a subtree don't inherit the ID property.
Otherwise they inherit the ID property with a new unique
identifier."
:type 'boolean
:version "24.1"
:group 'org-id)
;;; Version
(org-check-version)
;;;###autoload
(defun org-version (&optional here full message)
"Show the org-mode version.
Interactively, or when MESSAGE is non-nil, show it in echo area.
With prefix argument, or when HERE is non-nil, insert it at point.
In non-interactive uses, a reduced version string is output unless
FULL is given."
(interactive (list current-prefix-arg t (not current-prefix-arg)))
(let* ((org-dir (ignore-errors (org-find-library-dir "org")))
(save-load-suffixes (when (boundp 'load-suffixes) load-suffixes))
(load-suffixes (list ".el"))
(org-install-dir (ignore-errors (org-find-library-dir "org-loaddefs")))
(org-trash (or
(and (fboundp 'org-release) (fboundp 'org-git-version))
(org-load-noerror-mustsuffix (concat org-dir "org-version"))))
(load-suffixes save-load-suffixes)
(org-version (org-release))
(git-version (org-git-version))
(version (format "Org-mode version %s (%s @ %s)"
org-version
git-version
(if org-install-dir
(if (string= org-dir org-install-dir)
org-install-dir
(concat "mixed installation! " org-install-dir " and " org-dir))
"org-loaddefs.el can not be found!")))
(version1 (if full version org-version)))
(when here (insert version1))
(when message (message "%s" version1))
version1))
(defconst org-version (org-version))
;;; Syntax Constants
;;;; Block
(defconst org-block-regexp
"^[ \t]*#\\+begin_?\\([^ \n]+\\)\\(\\([^\n]+\\)\\)?\n\\([^\000]+?\\)#\\+end_?\\1[ \t]*$"
"Regular expression for hiding blocks.")
(defconst org-dblock-start-re
"^[ \t]*#\\+\\(?:BEGIN\\|begin\\):[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?"
"Matches the start line of a dynamic block, with parameters.")
(defconst org-dblock-end-re "^[ \t]*#\\+\\(?:END\\|end\\)\\([: \t\r\n]\\|$\\)"
"Matches the end of a dynamic block.")
;;;; Clock and Planning
(defconst org-clock-string "CLOCK:"
"String used as prefix for timestamps clocking work hours on an item.")
(defvar org-closed-string "CLOSED:"
"String used as the prefix for timestamps logging closing a TODO entry.")
(defvar org-deadline-string "DEADLINE:"
"String to mark deadline entries.
A deadline is this string, followed by a time stamp. Should be a word,
terminated by a colon. You can insert a schedule keyword and
a timestamp with \\[org-deadline].")
(defvar org-scheduled-string "SCHEDULED:"
"String to mark scheduled TODO entries.
A schedule is this string, followed by a time stamp. Should be a word,
terminated by a colon. You can insert a schedule keyword and
a timestamp with \\[org-schedule].")
(defconst org-ds-keyword-length
(+ 2
(apply #'max
(mapcar #'length
(list org-deadline-string org-scheduled-string
org-clock-string org-closed-string))))
"Maximum length of the DEADLINE and SCHEDULED keywords.")
(defconst org-planning-line-re
(concat "^[ \t]*"
(regexp-opt
(list org-closed-string org-deadline-string org-scheduled-string)
t))
"Matches a line with planning info.
Matched keyword is in group 1.")
(defconst org-clock-line-re
(concat "^[ \t]*" org-clock-string)
"Matches a line with clock info.")
(defconst org-deadline-regexp (concat "\\<" org-deadline-string)
"Matches the DEADLINE keyword.")
(defconst org-deadline-time-regexp
(concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
"Matches the DEADLINE keyword together with a time stamp.")
(defconst org-deadline-time-hour-regexp
(concat "\\<" org-deadline-string
" *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy \t.]*\\)>")
"Matches the DEADLINE keyword together with a time-and-hour stamp.")
(defconst org-deadline-line-regexp
(concat "\\<\\(" org-deadline-string "\\).*")
"Matches the DEADLINE keyword and the rest of the line.")
(defconst org-scheduled-regexp (concat "\\<" org-scheduled-string)
"Matches the SCHEDULED keyword.")
(defconst org-scheduled-time-regexp
(concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
"Matches the SCHEDULED keyword together with a time stamp.")
(defconst org-scheduled-time-hour-regexp
(concat "\\<" org-scheduled-string
" *<\\([^>]+[0-9]\\{1,2\\}:[0-9]\\{2\\}[0-9-+:hdwmy \t.]*\\)>")
"Matches the SCHEDULED keyword together with a time-and-hour stamp.")
(defconst org-closed-time-regexp
(concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
"Matches the CLOSED keyword together with a time stamp.")
(defconst org-keyword-time-regexp
(concat "\\<"
(regexp-opt
(list org-scheduled-string org-deadline-string org-closed-string
org-clock-string)
t)
" *[[<]\\([^]>]+\\)[]>]")
"Matches any of the 4 keywords, together with the time stamp.")
(defconst org-keyword-time-not-clock-regexp
(concat
"\\<"
(regexp-opt
(list org-scheduled-string org-deadline-string org-closed-string) t)
" *[[<]\\([^]>]+\\)[]>]")
"Matches any of the 3 keywords, together with the time stamp.")
(defconst org-maybe-keyword-time-regexp
(concat "\\(\\<"
(regexp-opt
(list org-scheduled-string org-deadline-string org-closed-string
org-clock-string)
t)
"\\)?"
" *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^]\r\n>]*?[]>]"
"\\|"
"<%%([^\r\n>]*>\\)")
"Matches a timestamp, possibly preceded by a keyword.")
(defconst org-all-time-keywords
(mapcar (lambda (w) (substring w 0 -1))
(list org-scheduled-string org-deadline-string
org-clock-string org-closed-string))
"List of time keywords.")
;;;; Drawer
(defconst org-drawer-regexp "^[ \t]*:\\(\\(?:\\w\\|[-_]\\)+\\):[ \t]*$"
"Matches first or last line of a hidden block.
Group 1 contains drawer's name or \"END\".")
(defconst org-property-start-re "^[ \t]*:PROPERTIES:[ \t]*$"
"Regular expression matching the first line of a property drawer.")
(defconst org-property-end-re "^[ \t]*:END:[ \t]*$"
"Regular expression matching the last line of a property drawer.")
(defconst org-clock-drawer-start-re "^[ \t]*:CLOCK:[ \t]*$"
"Regular expression matching the first line of a clock drawer.")
(defconst org-clock-drawer-end-re "^[ \t]*:END:[ \t]*$"
"Regular expression matching the last line of a clock drawer.")
(defconst org-property-drawer-re
(concat "^[ \t]*:PROPERTIES:[ \t]*\n"
"\\(?:[ \t]*:\\S-+:\\(?: .*\\)?[ \t]*\n\\)*"
"[ \t]*:END:[ \t]*$")
"Matches an entire property drawer.")
(defconst org-clock-drawer-re
(concat "\\(" org-clock-drawer-start-re "\\)[^\000]*?\\("
org-clock-drawer-end-re "\\)\n?")
"Matches an entire clock drawer.")
;;;; Headline
(defconst org-heading-keyword-regexp-format
"^\\(\\*+\\)\\(?: +%s\\)\\(?: +\\(.*?\\)\\)?[ \t]*$"
"Printf format for a regexp matching a headline with some keyword.
This regexp will match the headline of any node which has the
exact keyword that is put into the format. The keyword isn't in
any group by default, but the stars and the body are.")
(defconst org-heading-keyword-maybe-regexp-format
"^\\(\\*+\\)\\(?: +%s\\)?\\(?: +\\(.*?\\)\\)?[ \t]*$"
"Printf format for a regexp matching a headline, possibly with some keyword.
This regexp can match any headline with the specified keyword, or
without a keyword. The keyword isn't in any group by default,
but the stars and the body are.")
(defconst org-archive-tag "ARCHIVE"
"The tag that marks a subtree as archived.
An archived subtree does not open during visibility cycling, and does
not contribute to the agenda listings.")
(defconst org-comment-string "COMMENT"
"Entries starting with this keyword will never be exported.
An entry can be toggled between COMMENT and normal with
\\[org-toggle-comment].")
;;;; LaTeX Environments and Fragments
(