summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Egli <christian.egli@sbszh.ch>2011-04-28 12:12:53 +0200
committerChristian Egli <christian.egli@sbszh.ch>2011-04-28 12:12:53 +0200
commit2a8ce137f489ceff11c7ee5f40b00adeb813a7ba (patch)
tree99e5877c6267bab0fb43a5b7a9ab29d860e6cfa7
parent2e21cd424a8a14c93bd2c88cacc58d3e760bb396 (diff)
parentaa903a749d449e57ab42ea68b471636753299d82 (diff)
downloadorg-mode-2a8ce137f489ceff11c7ee5f40b00adeb813a7ba.tar.gz
Merge branch 'master' of orgmode.org:org-mode
-rw-r--r--contrib/babel/langs/ob-oz.el74
-rw-r--r--contrib/babel/library-of-babel.org41
-rw-r--r--contrib/lisp/org-contacts.el20
-rw-r--r--doc/org.texi89
-rw-r--r--doc/orgcard.tex2
-rw-r--r--lisp/ob-R.el6
-rw-r--r--lisp/ob-ditaa.el5
-rw-r--r--lisp/ob-emacs-lisp.el5
-rw-r--r--lisp/ob-lisp.el126
-rw-r--r--lisp/ob-ocaml.el25
-rw-r--r--lisp/ob-octave.el2
-rw-r--r--lisp/ob-plantuml.el2
-rw-r--r--lisp/ob-python.el85
-rw-r--r--lisp/ob-tangle.el11
-rw-r--r--lisp/ob.el38
-rw-r--r--lisp/org-agenda.el257
-rw-r--r--lisp/org-ascii.el1
-rw-r--r--lisp/org-beamer.el1
-rw-r--r--lisp/org-bibtex.el360
-rw-r--r--lisp/org-capture.el69
-rw-r--r--lisp/org-clock.el2
-rw-r--r--lisp/org-docbook.el3
-rw-r--r--lisp/org-exp.el126
-rw-r--r--lisp/org-html.el36
-rw-r--r--lisp/org-latex.el29
-rw-r--r--lisp/org-list.el118
-rw-r--r--lisp/org-mobile.el2
-rw-r--r--lisp/org-protocol.el8
-rw-r--r--lisp/org-src.el8
-rw-r--r--lisp/org-table.el6
-rw-r--r--lisp/org.el97
31 files changed, 1193 insertions, 461 deletions
diff --git a/contrib/babel/langs/ob-oz.el b/contrib/babel/langs/ob-oz.el
index e1e6e35..f92733e 100644
--- a/contrib/babel/langs/ob-oz.el
+++ b/contrib/babel/langs/ob-oz.el
@@ -5,7 +5,7 @@
;; Author: Torsten Anders and Eric Schulte
;; Keywords: literate programming, reproducible research
;; Homepage: http://orgmode.org
-;; Version: 0.01
+;; Version: 0.02
;;; License:
@@ -120,7 +120,7 @@
(defvar org-babel-oz-server-dir
(file-name-as-directory
(expand-file-name
- "scripts"
+ "contrib/scripts"
(file-name-as-directory
(expand-file-name
"../../.."
@@ -196,53 +196,41 @@ StartOzServer.oz is located.")
(setq org-babel-oz-collected-result nil))))
result))
-(defun org-babel-expand-body:oz (body params &optional processed-params)
- (let ((vars (second (or processed-params (org-babel-process-params params))))))
- (if vars
- ;; only add var declarations if any variables are there
- (concat
- ;; prepend code to define all arguments passed to the code block
- "local\n"
- (mapconcat
- (lambda (pair)
- (format "%s=%s"
- (car pair)
- (org-babel-oz-var-to-oz (cdr pair))))
- vars "\n") "\n"
- "in\n"
- body
- "end\n")
- body))
+(defun org-babel-expand-body:oz (body params)
+ (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+ (if vars
+ ;; prepend code to define all arguments passed to the code block
+ (let ((var-string (mapcar (lambda (pair)
+ (format "%s=%s"
+ (car pair)
+ (org-babel-oz-var-to-oz (cdr pair))))
+ vars)))
+ ;; only add var declarations if any variables are there
+ (mapconcat #'identity
+ (append (list "local") var-string (list "in" body "end"))
+ "\n"))
+ body)))
(defun org-babel-execute:oz (body params)
"Execute a block of Oz code with org-babel. This function is
called by `org-babel-execute-src-block' via multiple-value-bind."
- (let* ((processed-params (org-babel-process-params params))
-;; (session (org-babel-ruby-initiate-session (first processed-params)))
- (vars (second processed-params))
-;; (result-params (third processed-params))
- (result-type (fourth processed-params))
- (full-body (org-babel-expand-body:oz body params processed-params))
- (wait-time (plist-get params :wait-time))
- ;; set the session if the session variable is non-nil
-;; (session-buffer (org-babel-oz-initiate-session session))
-;; (session (org-babel-prep-session:oz session params))
- )
+ (let* ((result-params (cdr (assoc :result-params params)))
+ (full-body (org-babel-expand-body:oz body params))
+ (wait-time (plist-get params :wait-time)))
;; actually execute the source-code block
(org-babel-reassemble-table
- (case result-type
- (output
- (progn
- (message "Org-babel: executing Oz statement")
- (oz-send-string full-body)))
- (value
- (progn
- (message "Org-babel: executing Oz expression")
- (oz-send-string-expression full-body (if wait-time
- wait-time
- 1)))))
- (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
- (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params))))))
+ (cond
+ ((member "output" result-params)
+ (message "Org-babel: executing Oz statement")
+ (oz-send-string full-body))
+ ((member "value" result-params)
+ (message "Org-babel: executing Oz expression")
+ (oz-send-string-expression full-body (or wait-time 1)))
+ (t (error "either 'output' or 'results' must be members of :results.")))
+ (org-babel-pick-name (cdr (assoc :colname-names params))
+ (cdr (assoc :colnames params)))
+ (org-babel-pick-name (cdr (assoc :roname-names params))
+ (cdr (assoc :rownames params))))))
;; This function should be used to assign any variables in params in
;; the context of the session environment.
diff --git a/contrib/babel/library-of-babel.org b/contrib/babel/library-of-babel.org
index abc15a9..fea5b3f 100644
--- a/contrib/babel/library-of-babel.org
+++ b/contrib/babel/library-of-babel.org
@@ -282,14 +282,55 @@ are optional.
| 3 | 6 |
* Misc
+
+** File-specific Version Control logging
+ :PROPERTIES:
+ :AUTHOR: Luke Crook
+ :END:
+
+This function will attempt to retrieve the entire commit log for the
+file associated with the current buffer and insert this log into the
+export. The function uses the Emacs VC commands to interface to the
+local version control system, but has only been tested to work with
+Git. 'limit' is currently unsupported.
+
+#+source: vc-log
+#+headers: :var limit=-1
+#+headers: :var buf=(buffer-name (current-buffer))
+#+begin_src emacs-lisp
+ ;; Most of this code is copied from vc.el vc-print-log
+ (require 'vc)
+ (when (vc-find-backend-function
+ (vc-backend (buffer-file-name (get-buffer buf))) 'print-log)
+ (let ((limit -1)
+ (vc-fileset nil)
+ (backend nil)
+ (files nil))
+ (with-current-buffer (get-buffer buf)
+ (setq vc-fileset (vc-deduce-fileset t)) ; FIXME: Why t? --Stef
+ (setq backend (car vc-fileset))
+ (setq files (cadr vc-fileset)))
+ (with-temp-buffer
+ (let ((status (vc-call-backend
+ backend 'print-log files (current-buffer))))
+ (when (and (processp status) ; Make sure status is a process
+ (= 0 (process-exit-status status))) ; which has not terminated
+ (while (not (eq 'exit (process-status status)))
+ (sit-for 1 t)))
+ (buffer-string)))))
+#+end_src
+
+** Trivial python code blocks
#+srcname: python-identity(a=1)
#+begin_src python
a
#+end_src
+
#+srcname: python-add(a=1, b=2)
#+begin_src python
a + b
#+end_src
+
* GANTT Charts
The =elispgantt= source block was sent to the mailing list by Eric
diff --git a/contrib/lisp/org-contacts.el b/contrib/lisp/org-contacts.el
index 86b1741..e8c4807 100644
--- a/contrib/lisp/org-contacts.el
+++ b/contrib/lisp/org-contacts.el
@@ -37,9 +37,7 @@
;;; Code:
(eval-and-compile
- (require 'org)
- (require 'gnus)
- (require 'gnus-art))
+ (require 'org))
(defgroup org-contacts nil
"Options concerning contacts management."
@@ -253,8 +251,6 @@ If both match values are nil, return all contacts."
;; show the next heading
(org-flag-heading nil)))))))
-(define-key gnus-summary-mode-map ";" 'org-contacts-gnus-article-from-goto)
-
(defun org-contacts-anniversaries (&optional field format)
"Compute FIELD anniversary for each contact, returning FORMAT.
Default FIELD value is \"BIRTHDAY\".
@@ -323,8 +319,6 @@ This function should be called from `gnus-article-prepare-hook'."
(link (gnus-with-article-buffer (org-store-link nil))))
(org-set-property org-contacts-last-read-mail-property link)))))))
-(add-hook 'gnus-article-prepare-hook 'org-contacts-gnus-store-last-mail)
-
(defun org-contacts-icon-as-string ()
(let ((image (org-contacts-get-icon)))
(concat
@@ -386,7 +380,17 @@ This function should be called from `gnus-article-prepare-hook'."
(org-with-point-at marker
(org-contacts-check-mail-address (cadr (org-contacts-gnus-get-name-email)))))))
-(add-hook 'gnus-article-prepare-hook 'org-contacts-gnus-check-mail-address)
+(defun org-contacts-gnus-insinuate ()
+ "Add some hooks for Gnus user.
+This adds `org-contacts-gnus-check-mail-address' and
+`org-contacts-gnus-store-last-mail' to
+`gnus-article-prepare-hook'. It also adds a binding on `;' in
+`gnus-summary-mode-map' to `org-contacts-gnus-article-from-goto'"
+ (require 'gnus)
+ (require 'gnus-art)
+ (define-key gnus-summary-mode-map ";" 'org-contacts-gnus-article-from-goto)
+ (add-hook 'gnus-article-prepare-hook 'org-contacts-gnus-check-mail-address)
+ (add-hook 'gnus-article-prepare-hook 'org-contacts-gnus-store-last-mail))
(defun org-contacts-view-send-email (&optional ask)
"Send email to the contact at point.
diff --git a/doc/org.texi b/doc/org.texi
index 6fc848b..7142ce0 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -1895,10 +1895,11 @@ calculator).
@section The built-in table editor
@cindex table editor, built-in
-Org makes it easy to format tables in plain ASCII. Any line with
-@samp{|} as the first non-whitespace character is considered part of a
-table. @samp{|} is also the column separator. A table might look like
-this:
+Org makes it easy to format tables in plain ASCII. Any line with @samp{|} as
+the first non-whitespace character is considered part of a table. @samp{|}
+is also the column separator@footnote{To insert a vertical bar into a table
+field, use @code{\vert} or, inside a word @code{abc\vert@{@}def}.}. A table
+might look like this:
@example
| Name | Phone | Age |
@@ -4274,7 +4275,7 @@ be placed into a headline or into (the first line of) a plain list item.
Each cookie covers checkboxes of direct children structurally below the
headline/item on which the cookie appears@footnote{Set the variable
@code{org-hierarchical-checkbox-statistics} if you want such cookies to
-represent the all checkboxes below the cookie, not just the direct
+count all checkboxes below the cookie, not just those belonging to direct
children.}. You have to insert the cookie yourself by typing either
@samp{[/]} or @samp{[%]}. With @samp{[/]} you get an @samp{n out of m}
result, as in the examples above. With @samp{[%]} you get information about
@@ -4331,8 +4332,7 @@ a @kbd{C-u} prefix, update the entire file. Checkbox statistic cookies are
updated automatically if you toggle checkboxes with @kbd{C-c C-c} and make
new ones with @kbd{M-S-@key{RET}}. TODO statistics cookies update when
changing TODO states. If you delete boxes/entries or add/change them by
-hand, use this command to get things back into sync. Or simply toggle any
-entry twice (checkboxes with @kbd{C-c C-c}).
+hand, use this command to get things back into sync.
@end table
@node Tags, Properties and Columns, TODO Items, Top
@@ -6457,6 +6457,7 @@ dynamic insertion of content:
%u, %U @r{like the above, but inactive timestamps}
%^t @r{like @code{%t}, but prompt for date. Similarly @code{%^T}, @code{%^u}, @code{%^U}}
@r{You may define a prompt like @code{%^@{Birthday@}t}}
+%<...> @r{the result of format-time-string on the ... format specification}
%n @r{user name (taken from @code{user-full-name})}
%c @r{Current kill ring head.}
%x @r{Content of the X clipboard.}
@@ -7692,6 +7693,10 @@ will be followed without a selection prompt.
@tsubheading{Change display}
@cindex display changing, in agenda
+@kindex A
+@item A
+Interactively select another agenda view and append it to the current view.
+@c
@kindex o
@item o
Delete other windows.
@@ -7769,6 +7774,15 @@ when toggling this mode (i.e.@: @kbd{C-u R}), the clock table will not show
contributions from entries that are hidden by agenda filtering@footnote{Only
tags filtering will be respected here, effort filtering is ignored.}.
@c
+@orgkey{v c}
+@vindex org-agenda-clock-consistency-checks
+Show overlapping clock entries, clocking gaps, and other clocking problems in
+the current agenda range. You can then visit clocking lines and fix them
+manually. See the variable @code{org-agenda-clock-consistency-checks} for
+information on how to customize the definition of what constituted a clocking
+problem. To return to normal agenda display, press @kbd{l} to exit Logbook
+mode.
+@c
@orgcmdkskc{v E,E,org-agenda-entry-text-mode}
@vindex org-agenda-start-with-entry-text-mode
@vindex org-agenda-entry-text-maxlines
@@ -7883,7 +7897,7 @@ Internet, and outside of business hours, with something like this:
@end group
@end lisp
-@orgcmd{\,org-agenda-filter-by-tag-refine}
+@orgcmd{\\,org-agenda-filter-by-tag-refine}
Narrow the current agenda filter by an additional condition. When called with
prefix arg, remove the entries that @emph{do} have the tag, or that do match
the effort criterion. You can achieve the same effect by pressing @kbd{+} or
@@ -8048,6 +8062,9 @@ Jump to the running clock in another window.
Mark the entry at point for bulk action. With prefix arg, mark that many
successive entries.
@c
+@orgcmd{%,org-agenda-bulk-mark-regexp}
+Mark entries matching a regular expression for bulk action.
+@c
@orgcmd{u,org-agenda-bulk-unmark}
Unmark entry for bulk action.
@c
@@ -8072,9 +8089,24 @@ t @r{Change TODO state. This prompts for a single TODO keyword and}
s @r{Schedule all items to a new date. To shift existing schedule dates}
@r{by a fixed number of days, use something starting with double plus}
@r{at the prompt, for example @samp{++8d} or @samp{++2w}.}
-S @r{Reschedule randomly by N days. N will be prompted for. With prefix}
- @r{arg (@kbd{C-u B S}), scatter only accross weekdays.}
+S @r{Reschedule randomly into the coming N days. N will be prompted for.}
+ @r{With prefix arg (@kbd{C-u B S}), scatter only across weekdays.}
d @r{Set deadline to a specific date.}
+f @r{Apply a function to marked entries.}
+ @r{For example, the function below sets the CATEGORY property of the}
+ @r{entries to web.}
+ @r{(defun set-category ()}
+ @r{ (interactive "P")}
+ @r{ (let* ((marker (or (org-get-at-bol 'org-hd-marker)}
+ @r{ (org-agenda-error)))}
+ @r{ (buffer (marker-buffer marker)))}
+ @r{ (with-current-buffer buffer}
+ @r{ (save-excursion}
+ @r{ (save-restriction}
+ @r{ (widen)}
+ @r{ (goto-char marker)}
+ @r{ (org-back-to-heading t)}
+ @r{ (org-set-property "CATEGORY" "web"))))))}
@end example
@@ -8507,7 +8539,7 @@ This causes the following issues:
Org needs to make a decision which @code{COLUMNS} format to use. Since the
entries in the agenda are collected from different files, and different files
may have different @code{COLUMNS} formats, this is a non-trivial problem.
-Org first checks if the variable @code{org-overriding-columns-format} is
+Org first checks if the variable @code{org-agenda-overriding-columns-format} is
currently set, and if so, takes the format from there. Otherwise it takes
the format associated with the first item in the agenda, or, if that item
does not have a specific format (defined in a property, or in its file), it
@@ -8845,7 +8877,9 @@ package is included by the LaTeX header, and ensuring that the
@code{org-export-latex-listings} and @code{org-export-latex-minted} for
further details.}. This is done with the @samp{src} block, where you also
need to specify the name of the major mode that should be used to fontify the
-example:
+example@footnote{Code in @samp{src} blocks may also be evaluated either
+interactively or on export. See @pxref{Working With Source Code} for more
+information on evaluating code blocks.}:
@cindex #+BEGIN_SRC
@example
@@ -9307,26 +9341,34 @@ enabled (default in Emacs 23).
@node Selective export, Export options, Exporting, Exporting
@section Selective export
-@cindex export, selective by tags
+@cindex export, selective by tags or TODO keyword
@vindex org-export-select-tags
@vindex org-export-exclude-tags
+@cindex org-export-with-tasks
You may use tags to select the parts of a document that should be exported,
or to exclude parts from export. This behavior is governed by two variables:
@code{org-export-select-tags} and @code{org-export-exclude-tags}.
-Org first checks if any of the @emph{select} tags is present in the buffer.
-If yes, all trees that do not carry one of these tags will be excluded. If a
-selected tree is a subtree, the heading hierarchy above it will also be
-selected for export, but not the text below those headings.
+@enumerate
+@item
+Org first checks if any of the @emph{select} tags is present in the
+buffer. If yes, all trees that do not carry one of these tags will be
+excluded. If a selected tree is a subtree, the heading hierarchy above it
+will also be selected for export, but not the text below those headings.
-@noindent
+@item
If none of the select tags is found, the whole buffer will be selected for
export.
-@noindent
+@item
Finally, all subtrees that are marked by any of the @emph{exclude} tags will
be removed from the export buffer.
+@end enumerate
+
+The variable @code{org-export-with-tasks} can be configured to select which
+kind of tasks should be included for export. See the docstring of the
+variable for more information.
@node Export options, The export dispatcher, Selective export, Exporting
@section Export options
@@ -9426,6 +9468,8 @@ toc: @r{turn on/off table of contents, or set level limit (integer)}
-: @r{turn on/off conversion of special strings.}
f: @r{turn on/off footnotes like this[1].}
todo: @r{turn on/off inclusion of TODO keywords into exported text}
+tasks: @r{turn on/off inclusion of tasks (TODO items), can be nil to remove}
+ @r{all tasks, @code{todo} to remove DONE tasks, or list of kwds to keep}
pri: @r{turn on/off priority cookies}
tags: @r{turn on/off inclusion of tags, may also be @code{not-in-toc}}
<: @r{turn on/off inclusion of any time/date stamps like DEADLINES}
@@ -10905,6 +10949,8 @@ respective variable for details.
@vindex org-export-with-drawers
@vindex org-export-with-tags
@vindex org-export-with-todo-keywords
+@vindex org-export-with-tasks
+@vindex org-export-with-done-tasks
@vindex org-export-with-priority
@vindex org-export-with-TeX-macros
@vindex org-export-with-LaTeX-fragments
@@ -10953,6 +10999,7 @@ respective variable for details.
@item @code{:drawers} @tab @code{org-export-with-drawers}
@item @code{:tags} @tab @code{org-export-with-tags}
@item @code{:todo-keywords} @tab @code{org-export-with-todo-keywords}
+@item @code{:tasks} @tab @code{org-export-with-tasks}
@item @code{:priority} @tab @code{org-export-with-priority}
@item @code{:TeX-macros} @tab @code{org-export-with-TeX-macros}
@item @code{:LaTeX-fragments} @tab @code{org-export-with-LaTeX-fragments}
@@ -12030,8 +12077,8 @@ org-mode file, while there is no such guarantee for evaluation of the code
block body.
@example
-#+begin_src sh :var file-name=(buffer-file-name) :exports both
- wc -w $file
+#+begin_src sh :var filename=(buffer-file-name) :exports both
+ wc -w $filename
#+end_src
@end example
diff --git a/doc/orgcard.tex b/doc/orgcard.tex
index 45266ab..16460e3 100644
--- a/doc/orgcard.tex
+++ b/doc/orgcard.tex
@@ -589,7 +589,7 @@ after ``{\tt :}'', and dictionary words elsewhere.
\key{switch to day/week/month/year/def view}{d w vm vy vSP}
\key{toggle diary entries / time grid / habits}{D / G / K}
\key{toggle entry text / clock report}{E / R}
-\key{toggle display of logbook entries}{l / v l/L}
+\key{toggle display of logbook entries}{l / v l/L/c}
\key{toggle inclusion of archived trees/files}{v a/A}
\key{refresh agenda buffer with any changes}{r / g}
\key{filter with respect to a tag}{/}
diff --git a/lisp/ob-R.el b/lisp/ob-R.el
index b72effc..713d59f 100644
--- a/lisp/ob-R.el
+++ b/lisp/ob-R.el
@@ -51,6 +51,12 @@
(defvar org-babel-R-command "R --slave --no-save"
"Name of command to use for executing R code.")
+(defun org-babel-edit-prep:R (info)
+ (let ((session (cdr (assoc :session (nth 2 info)))))
+ (when (and session (string-match "^\\*\\(.+?\\)\\*$" session))
+ (save-match-data (org-babel-R-initiate-session session nil))
+ (setq ess-local-process-name (match-string 1 session)))))
+
(defun org-babel-expand-body:R (body params &optional graphics-file)
"Expand BODY according to PARAMS, return the expanded body."
(let ((graphics-file
diff --git a/lisp/ob-ditaa.el b/lisp/ob-ditaa.el
index 20b5c42..68ad795 100644
--- a/lisp/ob-ditaa.el
+++ b/lisp/ob-ditaa.el
@@ -40,7 +40,7 @@
(require 'ob)
(defvar org-babel-default-header-args:ditaa
- '((:results . "file") (:exports . "results"))
+ '((:results . "file") (:exports . "results") (:java . "-Dfile.encoding=UTF-8"))
"Default arguments for evaluating a ditaa source block.")
(defvar org-ditaa-jar-path)
@@ -54,8 +54,9 @@ This function is called by `org-babel-execute-src-block'."
"ditaa code block requires :file header argument")))
(cdr (assoc :file params))))
(cmdline (cdr (assoc :cmdline params)))
+ (java (cdr (assoc :java params)))
(in-file (org-babel-temp-file "ditaa-"))
- (cmd (concat "java -jar "
+ (cmd (concat "java " java " -jar "
(shell-quote-argument
(expand-file-name org-ditaa-jar-path))
" " cmdline
diff --git a/lisp/ob-emacs-lisp.el b/lisp/ob-emacs-lisp.el
index 4b855e6..9e7dc72 100644
--- a/lisp/ob-emacs-lisp.el
+++ b/lisp/ob-emacs-lisp.el
@@ -57,7 +57,10 @@
"Execute a block of emacs-lisp code with Babel."
(save-window-excursion
(org-babel-reassemble-table
- (eval (read (format "(progn %s)"
+ (eval (read (format (if (member "output"
+ (cdr (assoc :result-params params)))
+ "(with-output-to-string %s)"
+ "(progn %s)")
(org-babel-expand-body:emacs-lisp body params))))
(org-babel-pick-name (cdr (assoc :colname-names params))
(cdr (assoc :colnames params)))
diff --git a/lisp/ob-lisp.el b/lisp/ob-lisp.el
index f009e18..a810d86 100644
--- a/lisp/ob-lisp.el
+++ b/lisp/ob-lisp.el
@@ -1,35 +1,30 @@
-;;; ob-lisp.el --- org-babel functions for Common Lisp
+;;; ob-lisp.el --- org-babel functions for common lisp evaluation
-;; Copyright (C) 2010 Free Software Foundation
+;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
-;; Author: David T. O'Toole <dto@gnu.org>, Eric Schulte
-;; Keywords: literate programming, reproducible research, lisp
+;; Author: Joel Boehland, Eric Schulte, David T. O'Toole <dto@gnu.org>
+;; Keywords: literate programming, reproducible research
;; Homepage: http://orgmode.org
;; Version: 7.5
-;;; License:
+;; This file is part of GNU Emacs.
-;; This program is free software; you can redistribute it and/or modify
+;; 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, or (at your option)
-;; any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
+;; 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; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
-;; Now working with SBCL for both session and external evaluation.
-;;
-;; This certainly isn't optimally robust, but it seems to be working
-;; for the basic use cases.
+;;; support for evaluating common lisp code, relies on slime for all eval
;;; Requirements:
@@ -38,73 +33,56 @@
;;; Code:
(require 'ob)
-(require 'ob-ref)
-(require 'ob-comint)
-(require 'ob-eval)
(declare-function slime-eval "ext:slime" (sexp &optional package))
-(declare-function slime-process "ext:slime" (&optional connection))
-(declare-function slime-connected-p "ext:slime" ())
-(defvar org-babel-default-header-args:lisp '()
- "Default header arguments for lisp code blocks.")
+(add-to-list 'org-babel-tangle-lang-exts '("lisp" . "lisp"))
-(defcustom org-babel-lisp-cmd "sbcl --script"
- "Name of command used to evaluate lisp blocks."
- :group 'org-babel
- :type 'string)
+(defvar org-babel-default-header-args:lisp '())
+(defvar org-babel-header-arg-names:lisp '(package))
(defun org-babel-expand-body:lisp (body params)
"Expand BODY according to PARAMS, return the expanded body."
- (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
- (if (> (length vars) 0)
- (concat "(let ("
- (mapconcat
- (lambda (var) (format "%S" (print `(,(car var) ',(cdr var)))))
- vars "\n ")
- ")\n" body ")")
+ (let* ((vars (mapcar #'cdr (org-babel-get-header params :var)))
+ (result-params (cdr (assoc :result-params params)))
+ (print-level nil) (print-length nil)
+ (body (org-babel-trim
+ (if (> (length vars) 0)
+ (concat "(let ("
+ (mapconcat
+ (lambda (var)
+ (format "(%S (quote %S))" (car var) (cdr var)))
+ vars "\n ")
+ ")\n" body ")")
+ (format "(progn %s)" body)))))
+ (if (or (member "code" result-params)
+ (member "pp" result-params))
+ (format "(pprint %s)" body)
body)))
(defun org-babel-execute:lisp (body params)
- "Execute a block of Lisp code with org-babel.
-This function is called by `org-babel-execute-src-block'"
- (require 'slime)
- (message "executing Lisp source code block")
- (let* ((session (org-babel-lisp-initiate-session
- (cdr (assoc :session params))))
- (result-type (cdr (assoc :result-type params)))
- (full-body (org-babel-expand-body:lisp body params)))
- (read
- (if session
- ;; session evaluation
- (save-window-excursion
- (cadr (slime-eval `(swank:eval-and-grab-output ,full-body))))
- ;; external evaluation
- (let ((script-file (org-babel-temp-file "lisp-script-")))
- (with-temp-file script-file
- (insert
- ;; return the value or the output
- (if (string= result-type "value")
- (format "(print %s)" full-body)
- full-body)))
- (org-babel-eval
- (format "%s %s" org-babel-lisp-cmd
- (org-babel-process-file-name script-file)) ""))))))
-
-;; This function should be used to assign any variables in params in
-;; the context of the session environment.
-(defun org-babel-prep-session:lisp (session params)
- "Prepare SESSION according to the header arguments specified in PARAMS."
- (error "not yet implemented"))
-
-(defun org-babel-lisp-initiate-session (&optional session)
- "If there is not a current inferior-process-buffer in SESSION
-then create. Return the initialized session."
+ "Execute a block of Common Lisp code with Babel."
(require 'slime)
- (unless (string= session "none")
- (save-window-excursion
- (or (slime-connected-p)
- (slime-process)))))
+ (org-babel-reassemble-table
+ (with-temp-buffer
+ (insert (org-babel-expand-body:lisp body params))
+ ((lambda (result)
+ (if (member "output" (cdr (assoc :result-params params)))
+ (car result)
+ (condition-case nil
+ (read (org-bable-lisp-vector-to-list (cadr result)))
+ (error (cadr result)))))
+ (slime-eval `(swank:eval-and-grab-output
+ ,(buffer-substring-no-properties (point-min) (point-max)))
+ (cdr (assoc :package params)))))
+ (org-babel-pick-name (cdr (assoc :colname-names params))
+ (cdr (assoc :colnames params)))
+ (org-babel-pick-name (cdr (assoc :rowname-names params))
+ (cdr (assoc :rownames params)))))
+
+(defun org-bable-lisp-vector-to-list (results)
+ ;; TODO: better would be to replace #(...) with [...]
+ (replace-regexp-in-string "#(" "(" results))
(provide 'ob-lisp)
diff --git a/lisp/ob-ocaml.el b/lisp/ob-ocaml.el
index 4d366e7..1a21d15 100644
--- a/lisp/ob-ocaml.el
+++ b/lisp/ob-ocaml.el
@@ -125,30 +125,17 @@ OUTPUT is string output from an ocaml process."
"Convert RESULTS into an elisp table or string.
If the results look like a table, then convert them into an
Emacs-lisp table, otherwise return the results as a string."
- (org-babel-read
- (if (and (stringp results) (string-match "^\\[.+\\]$" results))
- (org-babel-read
- (replace-regexp-in-string
- "\\[" "(" (replace-regexp-in-string
- "\\]" ")" (replace-regexp-in-string
- "; " " " (replace-regexp-in-string
- "'" "\"" results)))))
- results)))
+ (org-babel-script-escape (replace-regexp-in-string ";" "," results)))
(defun org-babel-ocaml-read-array (results)
"Convert RESULTS into an elisp table or string.
If the results look like a table, then convert them into an
Emacs-lisp table, otherwise return the results as a string."
- (org-babel-read
- (if (and (stringp results) (string-match "^\\[.+\\]$" results))
- (org-babel-read
- (concat
- "'" (replace-regexp-in-string
- "\\[|" "(" (replace-regexp-in-string
- "|\\]" ")" (replace-regexp-in-string
- "; " " " (replace-regexp-in-string
- "'" "\"" results))))))
- results)))
+ (org-babel-script-escape
+ (replace-regexp-in-string
+ "\\[|" "[" (replace-regexp-in-string
+ "|\\]" "]" (replace-regexp-in-string
+ "; " "," results)))))
(provide 'ob-ocaml)
diff --git a/lisp/ob-octave.el b/lisp/ob-octave.el
index 31e53c8..3430dea 100644
--- a/lisp/ob-octave.el
+++ b/lisp/ob-octave.el
@@ -103,7 +103,7 @@ end")
"Return list of octave statements assigning the block's variables"
(mapcar
(lambda (pair)
- (format "%s=%s"
+ (format "%s=%s;"
(car pair)
(org-babel-octave-var-to-octave (cdr pair))))
(mapcar #'cdr (org-babel-get-header params :var))))
diff --git a/lisp/ob-plantuml.el b/lisp/ob-plantuml.el
index fbebd35..b57aad6 100644
--- a/lisp/ob-plantuml.el
+++ b/lisp/ob-plantuml.el
@@ -62,6 +62,8 @@ This function is called by `org-babel-execute-src-block'."
(expand-file-name org-plantuml-jar-path))
(if (string= (file-name-extension out-file) "svg")
" -tsvg" "")
+ (if (string= (file-name-extension out-file) "eps")
+ " -teps" "")
" -p " cmdline " < "
(org-babel-process-file-name in-file)
" > "
diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index a5ce25a..f3f4a03 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -202,29 +202,33 @@ open('%s', 'w').write( pprint.pformat(main()) )")
If RESULT-TYPE equals 'output then return standard output as a
string. If RESULT-TYPE equals 'value then return the value of the
last statement in BODY, as elisp."
- (case result-type
- (output (org-babel-eval org-babel-python-command
- (concat (if preamble (concat preamble "\n") "") body)))
- (value (let ((tmp-file (org-babel-temp-file "python-")))
- (org-babel-eval org-babel-python-command
- (concat
- (if preamble (concat preamble "\n") "")
- (format
- (if (member "pp" result-params)
- org-babel-python-pp-wrapper-method
- org-babel-python-wrapper-method)
- (mapconcat
- (lambda (line) (format "\t%s" line))
- (split-string
- (org-remove-indentation
- (org-babel-trim body))
- "[\r\n]") "\n")
- (org-babel-process-file-name tmp-file 'noquote))))
- ((lambda (raw)
- (if (or (member "code" result-params)
- (member "pp" result-params))
- raw
- (org-babel-python-table-or-string raw)))
+ ((lambda (raw)
+ (if (or (member "code" result-params)
+ (member "pp" result-params)
+ (and (member "output" result-params)
+ (not (member "table" result-params))))
+ raw
+ (org-babel-python-table-or-string (org-babel-trim raw))))
+ (case result-type
+ (output (org-babel-eval org-babel-python-command
+ (concat (if preamble (concat preamble "\n") "")
+ body)))
+ (value (let ((tmp-file (org-babel-temp-file "python-")))
+ (org-babel-eval
+ org-babel-python-command
+ (concat
+ (if preamble (concat preamble "\n") "")
+ (format
+ (if (member "pp" result-params)
+ org-babel-python-pp-wrapper-method
+ org-babel-python-wrapper-method)
+ (mapconcat
+ (lambda (line) (format "\t%s" line))
+ (split-string
+ (org-remove-indentation
+ (org-babel-trim body))
+ "[\r\n]") "\n")
+ (org-babel-process-file-name tmp-file 'noquote))))
(org-babel-eval-read-file tmp-file))))))
(defun org-babel-python-evaluate-session
@@ -248,22 +252,25 @@ last statement in BODY, as elisp."
(mapc (lambda (statement) (insert statement) (comint-send-input))
(split-string (org-babel-trim body) "[\r\n]+"))
(comint-send-input) (comint-send-input)))
- (case result-type
- (output
- (mapconcat
- #'org-babel-trim
- (butlast
- (org-babel-comint-with-output
- (session org-babel-python-eoe-indicator t body)
- (let ((comint-process-echoes nil))
- (input-body body)
- (insert org-babel-python-eoe-indicator)
- (comint-send-input))) 2) "\n"))
- (value
- ((lambda (results)
- (if (or (member "code" result-params) (member "pp" result-params))
- results
- (org-babel-python-table-or-string results)))
+ ((lambda (results)
+ (if (or (member "code" result-params)
+ (member "pp" result-params)
+ (and (member "output" result-params)
+ (not (member "table" result-params))))
+ results
+ (org-babel-python-table-or-string results)))
+ (case result-type
+ (output
+ (mapconcat
+ #'org-babel-trim
+ (butlast
+ (org-babel-comint-with-output
+ (session org-babel-python-eoe-indicator t body)
+ (let ((comint-process-echoes nil))
+ (input-body body)
+ (insert org-babel-python-eoe-indicator)
+ (comint-send-input))) 2) "\n"))
+ (value
(let ((tmp-file (org-babel-temp-file "python-")))
(org-babel-comint-with-output
(session org-babel-python-eoe-indicator nil body)
diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index afbef81..5a81f73 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -243,7 +243,8 @@ exported source code blocks by language."
(org-babel-tangle-collect-blocks lang))
(message "tangled %d code block%s from %s" block-counter
(if (= block-counter 1) "" "s")
- (file-name-nondirectory (buffer-file-name (current-buffer))))
+ (file-name-nondirectory
+ (buffer-file-name (or (buffer-base-buffer) (current-buffer)))))
;; run `org-babel-post-tangle-hook' in all tangled files
(when org-babel-post-tangle-hook
(mapc
@@ -295,9 +296,11 @@ code blocks by language."
(unless (and language (not (string= language src-lang)))
(let* ((info (org-babel-get-src-block-info))
(params (nth 2 info))
- (link (progn (org-store-link nil)
- (org-babel-clean-text-properties
- (car (pop org-stored-links)))))
+ (link ((lambda (link)
+ (and (string-match org-bracket-link-regexp link)
+ (match-string 1 link)))
+ (org-babel-clean-text-properties
+ (org-store-link nil))))
(source-name
(intern (or (nth 4 info)
(format "%s:%d"
diff --git a/lisp/ob.el b/lisp/ob.el
index 6b4a766..82722f9 100644
--- a/lisp/ob.el
+++ b/lisp/ob.el
@@ -306,10 +306,6 @@ specific header arguments as well.")
'((:session . "none") (:results . "replace") (:exports . "results"))
"Default arguments to use when evaluating an inline source block.")
-(defvar org-babel-current-buffer-properties nil
- "Local cache for buffer properties.")
-(make-variable-buffer-local 'org-babel-current-buffer-properties)
-
(defvar org-babel-result-regexp
"^[ \t]*#\\+res\\(ults\\|name\\)\\(\\[\\([[:alnum:]]+\\)\\]\\)?\\:[ \t]*"
"Regular expression used to match result lines.
@@ -892,20 +888,20 @@ may be specified in the properties of the current outline entry."
"Retrieve per-buffer parameters.
Return an association list of any source block params which
may be specified in the current buffer."
- (or org-babel-current-buffer-properties
- (save-match-data
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (while (re-search-forward
- (org-make-options-regexp (list "BABEL")) nil t)
- (setq org-babel-current-buffer-properties
- (org-babel-merge-params
- org-babel-current-buffer-properties
- (org-babel-parse-header-arguments
- (org-match-string-no-properties 2)))))
- org-babel-current-buffer-properties)))))
+ (let (local-properties)
+ (save-match-data
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (while (re-search-forward
+ (org-make-options-regexp (list "BABEL" "PROPERTIES")) nil t)
+ (setq local-properties
+ (org-babel-merge-params
+ local-properties
+ (org-babel-parse-header-arguments
+ (org-match-string-no-properties 2)))))
+ local-properties)))))
(defvar org-src-preserve-indentation)
(defun org-babel-parse-src-block-match ()
@@ -996,8 +992,10 @@ may be specified in the current buffer."
(append
(mapcar (lambda (var) (cons :var var)) (car vars-and-names))
(list
- (cons :colname-names (cadr vars-and-names))
- (cons :rowname-names (caddr vars-and-names))
+ (cons :colname-names (or (cdr (assoc :colname-names params))
+ (cadr vars-and-names)))
+ (cons :rowname-names (or (cdr (assoc :rowname-names params))
+ (caddr vars-and-names)))
(cons :result-params result-params)
(cons :result-type (cond ((member "output" result-params) 'output)
((member "value" result-params) 'value)
diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index 1f046f2..d11fdf1 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -1096,6 +1096,49 @@ the agenda to display all available LOG items temporarily."
:group 'org-agenda-daily/weekly
:type '(set :greedy t (const closed) (const clock) (const state)))
+(defcustom org-agenda-clock-consistency-checks
+ '(:max-duration "10:00" :min-duration 0 :max-gap "0:05"
+ :gap-ok-around ("4:00")
+ :default-face ((:background "DarkRed") (:foreground "white"))
+ :overlap-face nil :gap-face nil :no-end-time-face nil
+ :long-face nil :short-face nil)
+ "This is a property list, with the following keys:
+
+:max-duration Mark clocking chunks that are longer than this time.
+ This is a time string like \"HH:MM\", or the number
+ of minutes as an integer.
+
+:min-duration Mark clocking chunks that are shorter that this.
+ This is a time string like \"HH:MM\", or the number
+ of minutes as an integer.
+
+:max-gap Mark gaps between clocking chunks that are longer than
+ this duration. A number of minutes, or a string
+ like \"HH:MM\".
+
+:gap-ok-around List of times during the day which are usually not working
+ times. When a gap is detected, but the gap contains any
+ of these times, the gap is *not* reported. For example,
+ if this is (\"4:00\" \"13:00\") then gaps that contain
+ 4:00 in the morning (i.e. the night) and 13:00
+ (i.e. a typical lunch time) do not cause a warning.
+ You should have at least one time during the night in this
+ list, or otherwise the first task each morning will trigger
+ a warning because it follows a long gap.
+
+Furthermore, the following properties can be used to define faces for
+issue display.
+
+:default-face the default face, if the specific face is undefined
+:overlap-face face for overlapping clocks
+:gap-face face for gaps between clocks
+:no-end-time-face face for incomplete clocks
+:long-face face for clock intervals that are too long
+:short-face face for clock intervals that are too short"
+ :group 'org-agenda-daily/weekly
+ :group 'org-clock
+ :type 'plist)
+
(defcustom org-agenda-log-mode-add-notes t
"Non-nil means add first line of notes to log entries in agenda views.
If a log item like a state change or a clock entry is associated with
@@ -3412,7 +3455,8 @@ When EMPTY is non-nil, also include days without any entries."
;;; Agenda Daily/Weekly
(defvar org-agenda-start-day nil ; dynamically scoped parameter
-"Custom commands can set this variable in the options section.")
+"Start day for the agenda view.
+Custom commands can set this variable in the options section.")
(defvar org-starting-day nil) ; local variable in the agenda buffer
(defvar org-agenda-current-span nil
"The current span used in the agenda view.") ; local variable in the agenda buffer
@@ -3457,11 +3501,6 @@ the daily/weekly agenda, see `org-agenda-skip-function'.")
The view will be for the current day or week, but from the overview buffer
you will be able to go to other days/weeks.
-With one \\[universal-argument] prefix argument INCLUDE-ALL,
-all unfinished TODO items will also be shown, before the agenda.
-This feature is considered obsolete, please use the TODO list or a block
-agenda instead.
-
With a numeric prefix argument in an interactive call, the agenda will
span INCLUDE-ALL days. Lisp programs should instead specify SPAN to change
the number of days. SPAN defaults to `org-agenda-span'.
@@ -3516,24 +3555,6 @@ given in `org-agenda-start-on-weekday'."
(org-set-local 'org-starting-day (car day-numbers))
(org-set-local 'org-include-all-loc include-all)
(org-set-local 'org-agenda-current-span (org-agenda-ndays-to-span span))
- (when (and (or include-all org-agenda-include-all-todo)
- (member today day-numbers))
- (setq files thefiles
- rtnall nil)
- (while (setq file (pop files))
- (catch 'nextfile
- (org-check-agenda-file file)
- (setq date (calendar-gregorian-from-absolute today)
- rtn (org-agenda-get-day-entries
- file date :todo))
- (setq rtnall (append rtnall rtn))))
- (when rtnall
- (insert "All currently open TODO items:\n")
- (add-text-properties (point-min) (1- (point))
- (list 'face 'org-agenda-structure
- 'short-heading "All TODO items"))
- (org-agenda-mark-header-line (point-min))
- (insert (org-finalize-agenda-entries rtnall) "\n")))
(unless org-agenda-compact-blocks
(let* ((d1 (car day-numbers))
(d2 (org-last day-numbers))
@@ -3572,7 +3593,7 @@ given in `org-agenda-start-on-weekday'."
(setq org-agenda-entry-types
(delq :deadline org-agenda-entry-types)))
(cond
- ((eq org-agenda-show-log 'only)
+ ((memq org-agenda-show-log '(only clockcheck))
(setq rtn (org-agenda-get-day-entries
file date :closed)))
(org-agenda-show-log
@@ -3643,6 +3664,8 @@ given in `org-agenda-start-on-weekday'."
(recenter 1))))
(goto-char (or start-pos 1))
(add-text-properties (point-min) (point-max) '(org-agenda-type agenda))
+ (if (eq org-agenda-show-log 'clockcheck)
+ (org-agenda-show-clocking-issues))
(org-finalize-agenda)
(setq buffer-read-only t)
(message "")))
@@ -4732,7 +4755,7 @@ This function is invoked if `org-agenda-todo-ignore-deadlines',
(setq hdmarker (org-agenda-new-marker)
tags (org-get-tags-at))
(looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
- (setq head (match-string 1))
+ (setq head (or (match-string 1) ""))
(setq txt (org-format-agenda-item
(if inactivep org-agenda-inactive-leader nil)
head category tags timestr
@@ -4830,7 +4853,9 @@ be skipped."
(abbreviate-file-name buffer-file-name))))
(items (if (consp org-agenda-show-log)
org-agenda-show-log
- org-agenda-log-mode-items))
+ (if (eq org-agenda-show-log 'clockcheck)
+ '(clock)
+ org-agenda-log-mode-items)))
(parts
(delq nil
(list
@@ -4912,6 +4937,125 @@ be skipped."
(goto-char (point-at-eol))))
(nreverse ee)))
+(defun org-agenda-show-clocking-issues ()
+ "Add overlays, showing issues with clocking.
+See also the user option `org-agenda-clock-consistency-checks'."
+ (interactive)
+ (let* ((pl org-agenda-clock-consistency-checks)
+ (re (concat "^[ \t]*"
+ org-clock-string
+ "[ \t]+"
+ "\\(\\[.*?\\]\\)" ; group 1 is first stamp
+ "\\(-\\{1,3\\}\\(\\[.*?\\]\\)\\)?")) ; group 3 is second
+ (tlstart 0.)
+ (tlend 0.)
+ (maxtime (org-hh:mm-string-to-minutes
+ (or (plist-get pl :max-duration) "24:00")))
+ (mintime (org-hh:mm-string-to-minutes
+ (or (plist-get pl :min-duration) 0)))
+ (maxgap (org-hh:mm-string-to-minutes
+ ;; default 30:00 means never complain
+ (or (plist-get pl :max-gap) "30:00")))
+ (gapok (mapcar 'org-hh:mm-string-to-minutes
+ (plist-get pl :gap-ok-around)))
+ (def-face (or (plist-get pl :default-face)
+ '((:background "DarkRed") (:foreground "white"))))
+ issue)
+ (goto-char (point-min))
+ (while (re-search-forward " Clocked: +(-\\|\\([0-9]+:[0-9]+\\))" nil t)
+ (setq issue nil face def-face)
+ (catch 'next
+ (setq m (org-get-at-bol 'org-marker)
+ te nil ts nil)
+ (unless (and m (markerp m))
+ (setq issue "No valid clock line") (throw 'next t))
+ (org-with-point-at m
+ (save-excursion
+ (goto-char (point-at-bol))
+ (unless (looking-at re)
+ (error "No valid Clock line")
+ (throw 'next t))
+ (unless (match-end 3)
+ (setq issue "No end time"
+ face (or (plist-get pl :no-end-time-face) face))
+ (throw 'next t))
+ (setq ts (match-string 1)
+ te (match-string 3)
+ ts (org-float-time
+ (apply 'encode-time (org-parse-time-string ts)))
+ te (org-float-time
+ (apply 'encode-time (org-parse-time-string te)))
+ dt (- te ts))))
+ (cond
+ ((> dt (* 60 maxtime))
+ ;; a very long clocking chunk
+ (setq issue (format "Clocking interval is very long: %s"
+ (org-minutes-to-hh:mm-string
+ (floor (/ (float dt) 60.))))
+ face (or (plist-get pl :long-face) face)))
+ ((< dt (* 60 mintime))
+ ;; a very short clocking chunk
+ (setq issue (format "Clocking interval is very short: %s"
+ (org-minutes-to-hh:mm-string
+ (floor (/ (float dt) 60.))))
+ face (or (plist-get pl :short-face) face)))
+ ((and (> tlend 0) (< ts tlend))
+ ;; Two clock entries are overlapping
+ (setq issue (format "Clocking overlap: %d minutes"
+ (/ (- tlend ts) 60))
+ face (or (plist-get pl :overlap-face) face)))
+ ((and (> tlend 0) (> ts (+ tlend (* 60 maxgap))))
+ ;; There is a gap, lets see if we need to report it
+ (unless (org-agenda-check-clock-gap tlend ts gapok)
+ (setq issue (format "Clocking gap: %d minutes"
+ (/ (- ts tlend) 60))
+ face (or (plist-get pl :gap-face) face))))
+ (t nil)))
+ (setq tlend (or te tlend) tlstart (or ts tlstart))
+ (when issue
+ ;; OK, there was some issue, add an overlay to show the issue
+ (setq ov (make-overlay (point-at-bol) (point-at-eol)))
+ (overlay-put ov 'before-string
+ (concat
+ (org-add-props
+ (format "%-43s" (concat " " issue))
+ nil
+ 'face face)
+ "\n"))
+ (overlay-put ov 'evaporate t)))))
+
+(defun org-agenda-check-clock-gap (t1 t2 ok-list)
+ "Check if gap T1 -> T2 contains one of the OK-LIST time-of-day values."
+ (catch 'exit
+ (unless ok-list
+ ;; there are no OK times for gaps...
+ (throw 'exit nil))
+ (if (> (- (/ t2 36000) (/ t1 36000)) 24)
+ ;; This is more than 24 hours, so it is OK.
+ ;; because we have at least one OK time, that must be in the
+ ;; 24 hour interval.
+ (throw 'exit t))
+ ;; We have a shorter gap.
+ ;; Now we have to get the minute of the day when these times are
+ (let* ((t1dec (decode-time (seconds-to-time t1)))
+ (t2dec (decode-time (seconds-to-time t2)))
+ ;; compute the minute on the day
+ (min1 (+ (nth 1 t1dec) (* 60 (nth 2 t1dec))))
+ (min2 (+ (nth 1 t2dec) (* 60 (nth 2 t2dec)))))
+ (when (< min2 min1)
+ ;; if min2 is smaller than min1, this means it is on the next day.
+ ;; Wrap it to after midnight.
+ (setq min2 (+ min2 1440)))
+ ;; Now check if any of the OK times is in the gap
+ (mapcar (lambda (x)
+ ;; Wrap the time to after midnight if necessary
+ (if (< x min1) (setq x (+ x 1440)))
+ ;; Check if in interval
+ (and (<= min1 x) (>= min2 x) (throw 'exit t)))
+ ok-list)
+ ;; Nope, this gap is not OK
+ nil)))
+
(defun org-agenda-get-deadlines ()
"Return the deadline information for agenda display."
(let* ((props (list 'mouse-face 'highlight
@@ -5921,12 +6065,13 @@ to switch to narrowing."
(efforts (org-split-string
(or (cdr (assoc (concat org-effort-property "_ALL")
org-global-properties))
- "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00 8:00" "")))
+ "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00 8:00"
+ "")))
(effort-op org-agenda-filter-effort-default-operator)
(effort-prompt "")
(inhibit-read-only t)
(current org-agenda-filter)
- maybe-reftresh a n tag)
+ maybe-refresh a n tag)
(unless char
(message
"%s by tag [%s ], [TAB], %s[/]:off, [+-]:narrow, [>=<?]:effort: "
@@ -5973,12 +6118,12 @@ to switch to narrowing."
(push modifier org-agenda-filter))))
(if (not (null org-agenda-filter))
(org-agenda-filter-apply org-agenda-filter)))
- (setq maybe-reftresh t))
+ (setq maybe-refresh t))
((equal char ?/)
(org-agenda-filter-by-tag-show-all)
(when (get 'org-agenda-filter :preset-filter)
(org-agenda-filter-apply org-agenda-filter))
- (setq maybe-reftresh t))
+ (setq maybe-refresh t))
((or (equal char ?\ )
(setq a (rassoc char alist))
(and (>= char ?0) (<= char ?9)
@@ -5995,9 +6140,9 @@ to switch to narrowing."
(cons (concat (if strip "-" "+") tag)
(if narrow current nil)))
(org-agenda-filter-apply org-agenda-filter)
- (setq maybe-reftresh t))
+ (setq maybe-refresh t))
(t (error "Invalid tag selection character %c" char)))
- (when (and maybe-reftresh
+ (when (and maybe-refresh
(eq org-agenda-clockreport-mode 'with-filter))
(org-agenda-redo))))
@@ -6215,9 +6360,10 @@ With prefix ARG, go backward that many times the current span."
(defun org-agenda-view-mode-dispatch ()
"Call one of the view mode commands."
(interactive)
- (message "View: [d]ay [w]eek [m]onth [y]ear [SPC]reset [q]uit/abort
- time[G]rid [[]inactive [f]ollow [l]og [L]og-all [E]ntryText
- [a]rch-trees [A]rch-files clock[R]eport include[D]iary")
+ (message "View: [d]ay [w]eek [m]onth [y]ear [SPC]reset [q]uit/abort
+ time[G]rid [[]inactive [f]ollow [l]og [L]og-all [c]lockcheck
+ [a]rch-trees [A]rch-files clock[R]eport include[D]iary
+ [E]ntryText")
(let ((a (read-char-exclusive)))
(case a
(?\ (call-interactively 'org-agenda-reset-view))
@@ -6227,6 +6373,7 @@ With prefix ARG, go backward that many times the current span."
(?y (call-interactively 'org-agenda-year-view))
(?l (call-interactively 'org-agenda-log-mode))
(?L (org-agenda-log-mode '(4)))
+ (?c (org-agenda-log-mode 'clockcheck))
((?F ?f) (call-interactively 'org-agenda-follow-mode))
(?a (call-interactively 'org-agenda-archives-mode))
(?A (org-agenda-archives-mode 'files))
@@ -6430,10 +6577,13 @@ With a double `C-u' prefix arg, show *only* log items, nothing else."
(interactive "P")
(org-agenda-check-type t 'agenda 'timeline)
(setq org-agenda-show-log
- (if (equal special '(16))
- 'only
- (if special '(closed clock state)
- (not org-agenda-show-log))))
+ (cond
+ ((equal special '(16)) 'only)
+ ((eq special 'clockcheck)
+ (if (eq org-agenda-show-log 'clockcheck)
+ nil 'clockcheck))
+ (special '(closed clock state))
+ (t (not org-agenda-show-log))))
(org-agenda-set-mode-name)
(org-agenda-redo)
(message "Log mode is %s"
@@ -6502,8 +6652,11 @@ When called with a prefix argument, include all archive files as well."
(if org-agenda-use-time-grid " Grid" "")
(if (and (boundp 'org-habit-show-habits)
org-habit-show-habits) " Habit" "")
- (if (consp org-agenda-show-log) " LogAll"
- (if org-agenda-show-log " Log" ""))
+ (cond
+ ((consp org-agenda-show-log) " LogAll")
+ ((eq org-agenda-show-log 'clockcheck) " ClkCk")
+ (org-agenda-show-log " Log")
+ (t ""))
(if (or org-agenda-filter (get 'org-agenda-filter
:preset-filter))
(concat " {" (mapconcat
@@ -7954,8 +8107,18 @@ This will remove the markers, and the overlays."
"Execute an remote-editing action on all marked entries.
The prefix arg is passed through to the command if possible."
(interactive "P")
- (unless org-agenda-bulk-marked-entries
- (error "No entries are marked"))
+ ;; Make sure we have markers, and only valid ones
+ (unless org-agenda-bulk-marked-entries (error "No entries are marked"))
+ (mapc
+ (lambda (m)
+ (unless (and (markerp m)
+ (marker-buffer m)
+ (buffer-live-p (marker-buffer m))
+ (marker-position m))
+ (error "Marker %s for bulk command is invalid" m)))
+ org-agenda-bulk-marked-entries)
+
+ ;; Prompt for the bulk command
(message "Bulk: [r]efile [$]arch [A]rch->sib [t]odo [+/-]tag [s]chd [S]catter [d]eadline [f]unction")
(let* ((action (read-char-exclusive))
(org-log-refile (if org-log-refile 'time nil))
@@ -8020,7 +8183,7 @@ The prefix arg is passed through to the command if possible."
(fmakunbound 'read-string)))))))
((equal action ?S)
- (if (not (org-agenda-check-type nil 'agenda 'timeline))
+ (if (not (org-agenda-check-type nil 'agenda 'timeline 'todo))
(error "Can't scatter tasks in \"%s\" agenda view" org-agenda-type)
(let ((days (read-number
(format "Scatter tasks across how many %sdays: "
@@ -8043,7 +8206,9 @@ The prefix arg is passed through to the command if possible."
(setq day-of-week 0)))))
;; silently fail when try to replan a sexp entry
(condition-case nil
- (org-agenda-date-later distance)
+ (org-agenda-schedule nil
+ (days-to-time
+ (+ (org-today) distance)))
(error nil)))))))
((equal action ?f)
diff --git a/lisp/org-ascii.el b/lisp/org-ascii.el
index 5727f04..a2bbb0f 100644
--- a/lisp/org-ascii.el
+++ b/lisp/org-ascii.el
@@ -303,6 +303,7 @@ publishing directory."
:footnotes (plist-get opt-plist :footnotes)
:timestamps (plist-get opt-plist :timestamps)
:todo-keywords (plist-get opt-plist :todo-keywords)
+ :tasks (plist-get opt-plist :tasks)
:verbatim-multiline t
:select-tags (plist-get opt-plist :select-tags)
:exclude-tags (plist-get opt-plist :exclude-tags)
diff --git a/lisp/org-beamer.el b/lisp/org-beamer.el
index d27f91f..dc0535e 100644
--- a/lisp/org-beamer.el
+++ b/lisp/org-beamer.el
@@ -139,6 +139,7 @@ open The opening template for the environment, with the following escapes
%h the headline text
%H if there is headline text, that text in {} braces
%U if there is headline text, that text in [] brackets
+ %x the content of the BEAMER_extra property
close The closing string of the environment."
:group 'org-beamer
diff --git a/lisp/org-bibtex.el b/lisp/org-bibtex.el
index b7b7416..bb8994a 100644
--- a/lisp/org-bibtex.el
+++ b/lisp/org-bibtex.el
@@ -1,9 +1,10 @@
;;; org-bibtex.el --- Org links to BibTeX entries
;;
-;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
;;
;; Author: Bastien Guerry <bzg at altern dot org>
;; Carsten Dominik <carsten dot dominik at gmail dot com>
+;; Eric Schulte <schulte dot eric at gmail dot com>
;; Keywords: org, wp, remember
;; Version: 7.5
;;
@@ -66,12 +67,30 @@
;; =====================================================================
;; * READ <== [point here]
;;
-;; [[file:/file.bib::dolev83][Dolev & Yao 1983: security of public key protocols]]
+;; [[file:file.bib::dolev83][Dolev & Yao 1983: security of public key protocols]]
;;
;; Danny Dolev and Andrew C. Yao (1983): On the security of public-key protocols
;; In IEEE Transaction on Information Theory, 198--208.
;; =====================================================================
;;
+;; Additionally, the following functions are now available for storing
+;; bibtex entries within Org-mode documents.
+;;
+;; - Run `org-bibtex' to export the current file to a .bib.
+;;
+;; - Run `org-bibtex-check' or `org-bibtex-check-all' to check and
+;; fill in missing field of either the current, or all headlines
+;;
+;; - Run `org-bibtex-create' to add a bibtex entry
+;;
+;; - Use `org-bibtex-read' to read a bibtex entry after `point' or in
+;; the active region, then call `org-bibtex-write' in a .org file to
+;; insert a heading for the read bibtex entry
+;;
+;; - All Bibtex information is taken from the document compiled by
+;; Andrew Roberts from the Bibtex manual, available at
+;; http://www.andy-roberts.net/misc/latex/sessions/bibtex/bibentries.pdf
+;;
;;; History:
;;
;; The link creation part has been part of Org-mode for a long time.
@@ -80,12 +99,17 @@
;; of Austin Frank: http://article.gmane.org/gmane.emacs.orgmode/4112
;; and then implemented by Bastien Guerry.
;;
+;; Eric Schulte eventually added the functions for translating between
+;; Org-mode headlines and Bibtex entries, and for fleshing out the Bibtex
+;; fields of existing Org-mode headlines.
+;;
;; Org-mode loads this module by default - if this is not what you want,
;; configure the variable `org-modules'.
;;; Code:
(require 'org)
+(require 'bibtex)
(defvar description nil) ; dynamically scoped from org.el
@@ -93,21 +117,238 @@
(declare-function bibtex-generate-autokey "bibtex" ())
(declare-function bibtex-parse-entry "bibtex" (&optional content))
(declare-function bibtex-url "bibtex" (&optional pos no-browse))
+(declare-function longlines-mode "longlines" (&optional arg))
+
+
+;;; Bibtex data
+(defvar org-bibtex-types
+ '((:article
+ (:description . "An article from a journal or magazine")
+ (:required :author :title :journal :year)
+ (:optional :volume :number :pages :month :note))
+ (:book
+ (:description . "A book with an explicit publisher")
+ (:required (:editor :author) :title :publisher :year)
+ (:optional (:volume :number) :series :address :edition :month :note))
+ (:booklet
+ (:description . "A work that is printed and bound, but without a named publisher or sponsoring institution.")
+ (:required :title)
+ (:optional :author :howpublished :address :month :year :note))
+ (:conference
+ (:description . "")
+ (:required :author :title :booktitle :year)
+ (:optional :editor :pages :organization :publisher :address :month :note))
+ (:inbook
+ (:description . "A part of a book, which may be a chapter (or section or whatever) and/or a range of pages.")
+ (:required (:author :editor) :title (:chapter :pages) :publisher :year)
+ (:optional (:volume :number) :series :type :address :edition :month :note))
+ (:incollection
+ (:description . "A part of a book having its own title.")
+ (:required :author :title :booktitle :publisher :year)
+ (:optional :editor (:volume :number) :series :type :chapter :pages :address :edition :month :note))
+ (:inproceedings
+ (:description . "An article in a conference proceedings")
+ (:required :author :title :booktitle :year)
+ (:optional :editor (:volume :number) :series :pages :address :month :organization :publisher :note))
+ (:manual
+ (:description . "Technical documentation.")
+ (:required :title)
+ (:optional :author :organization :address :edition :month :year :note))
+ (:mastersthesis
+ (:description . "A Master’s thesis.")
+ (:required :author :title :school :year)
+ (:optional :type :address :month :note))
+ (:misc
+ (:description . "Use this type when nothing else fits.")
+ (:required)
+ (:optional :author :title :howpublished :month :year :note))
+ (:phdthesis
+ (:description . "A PhD thesis.")
+ (:required :author :title :school :year)
+ (:optional :type :address :month :note))
+ (:proceedings
+ (:description . "The proceedings of a conference.")
+ (:required :title :year)
+ (:optional :editor (:volume :number) :series :address :month :organization :publisher :note))
+ (:techreport
+ (:description . "A report published by a school or other institution.")
+ (:required :author :title :institution :year)
+ (:optional :type :address :month :note))
+ (:unpublished
+ (:description . "A document having an author and title, but not formally published.")
+ (:required :author :title :note)
+ (:optional :month :year)))
+ "Bibtex entry types with required and optional parameters.")
+
+(defvar org-bibtex-fields
+ '((:address . "Usually the address of the publisher or other type of institution. For major publishing houses, van Leunen recommends omitting the information entirely. For small publishers, on the other hand, you can help the reader by giving the complete address.")
+ (:annote . "An annotation. It is not used by the standard bibliography styles, but may be used by others that produce an annotated bibliography.")
+ (:author . "The name(s) of the author(s), in the format described in the LaTeX book. Remember, all names are separated with the and keyword, and not commas.")
+ (:booktitle . "Title of a book, part of which is being cited. See the LaTeX book for how to type titles. For book entries, use the title field instead.")
+ (:chapter . "A chapter (or section or whatever) number.")
+ (:crossref . "The database key of the entry being cross referenced.")
+ (:edition . "The edition of a book for example, 'Second'. This should be an ordinal, and should have the first letter capitalized, as shown here; the standard styles convert to lower case when necessary.")
+ (:editor . "Name(s) of editor(s), typed as indicated in the LaTeX book. If there is also an author field, then the editor field gives the editor of the book or collection in which the reference appears.")
+ (:howpublished . "How something strange has been published. The first word should be capitalized.")
+ (:institution . "The sponsoring institution of a technical report.")
+ (:journal . "A journal name.")
+ (:key . "Used for alphabetizing, cross-referencing, and creating a label when the author information is missing. This field should not be confused with the key that appears in the \cite command and at the beginning of the database entry.")
+ (:month . "The month in which the work was published or, for an unpublished work, in which it was written. You should use the standard three-letter abbreviation,")
+ (:note . "Any additional information that can help the reader. The first word should be capitalized.")
+ (:number . "Any additional information that can help the reader. The first word should be capitalized.")
+ (:organization . "The organization that sponsors a conference or that publishes a manual.")
+ (:pages . "One or more page numbers or range of numbers, such as 42-111 or 7,41,73-97 or 43+ (the ‘+’ in this last example indicates pages following that don’t form simple range). BibTEX requires double dashes for page ranges (--).")
+ (:publisher . "The publisher’s name.")
+ (:school . "The name of the school where a thesis was written.")
+ (:series . "The name of a series or set of books. When citing an entire book, the the title field gives its title and an optional series field gives the name of a series or multi-volume set in which the book is published.")
+ (:title . "The work’s title, typed as explained in the LaTeX book.")
+ (:type . "The type of a technical report for example, 'Research Note'.")
+ (:volume . "The volume of a journal or multi-volume book.")
+ (:year . "The year of publication or, for an unpublished work, the year it was written. Generally it should consist of four numerals, such as 1984, although the standard styles can handle any year whose last four nonpunctuation characters are numerals, such as '(about 1984)'"))
+ "Bibtex fields with descriptions.")
+
+(defvar *org-bibtex-entries* nil
+ "List to hold parsed bibtex entries.")
+
+(defcustom org-bibtex-autogen-keys nil
+ "Set to a truthy value to use `bibtex-generate-autokey' to generate keys."
+ :group 'org-bibtex
+ :type 'boolean)
+
+(defcustom org-bibtex-prefix nil
+ "Optional prefix for all bibtex property names.
+For example setting to 'BIB_' would allow interoperability with fireforg."
+ :group 'org-bibtex
+ :type 'string)
+
+(defcustom org-bibtex-export-arbitrary-fields nil
+ "When converting to bibtex allow fields not defined in `org-bibtex-fields'.
+This only has effect if org-bibtex-prefix is defined, so as to
+ensure that other org-properties, such as CATEGORY or LOGGING are
+not placed in the exported bibtex entry."
+ :group 'org-bibtex
+ :type 'boolean)
+
+;; TODO if ID, test to make sure ID is unique
+(defcustom org-bibtex-key-property "CUSTOM_ID"
+ "Property that holds the bibtex key.
+By default, this is CUSTOM_ID, which enables easy linking to
+bibtex headlines from within an org file. This can be set to ID
+to enable global links, but only with great caution, as global
+IDs must be unique."
+ :group 'org-bibtex
+ :type 'string)
+
+;;; Utility functions
+(defun org-bibtex-get (property)
+ (or (org-entry-get (point) (upcase property))
+ (org-entry-get (point) (concat org-bibtex-prefix (upcase property)))))
+
+(defun org-bibtex-put (property value)
+ (let ((prop (upcase (if (keywordp property)
+ (substring (symbol-name property) 1)
+ property))))
+ (org-set-property
+ (concat (unless (string= org-bibtex-key-property prop) org-bibtex-prefix)
+ prop)
+ value)))
+
+(defun org-bibtex-headline ()
+ "Return a bibtex entry of the given headline as a string."
+ (flet ((get (key lst) (cdr (assoc key lst)))
+ (to (string) (intern (concat ":" string)))
+ (from (key) (substring (symbol-name key) 1))
+ (flatten (&rest lsts)
+ (apply #'append (mapcar
+ (lambda (e)
+ (if (listp e) (apply #'flatten e) (list e)))
+ lsts))))
+ (let ((notes (buffer-string))
+ (id (org-bibtex-get org-bibtex-key-property))
+ (type (org-bibtex-get "type")))
+ (when type
+ (let ((entry (format
+ "@%s{%s,\n%s\n}\n" type id
+ (mapconcat
+ (lambda (pair) (format " %s={%s}" (car pair) (cdr pair)))
+ (remove nil
+ (if (and org-bibtex-export-arbitrary-fields
+ org-bibtex-prefix)
+ (mapcar
+ (lambda (kv)
+ (when (string-match org-bibtex-prefix (car kv))
+ (cons (downcase (replace-regexp-in-string
+ org-bibtex-prefix ""
+ (car kv)))
+ (cdr kv))))
+ (org-entry-properties nil 'standard))
+ (mapcar
+ (lambda (field)
+ (let ((value (or (org-bibtex-get (from field))
+ (and (equal :title field)
+ (org-get-heading)))))
+ (when value (cons (from field) value))))
+ (flatten
+ (get :required (get (to type) org-bibtex-types))
+ (get :optional (get (to type) org-bibtex-types))))))
+ ",\n"))))
+ (with-temp-buffer
+ (insert entry)
+ (bibtex-reformat) (buffer-string)))))))
+
+(defun org-bibtex-ask (field)
+ (unless (assoc field org-bibtex-fields)
+ (error "field:%s is not known" field))
+ (save-window-excursion
+ (let* ((name (substring (symbol-name field) 1))
+ (buf-name (format "*Bibtex Help %s*" name)))
+ (with-output-to-temp-buffer buf-name
+ (princ (cdr (assoc field org-bibtex-fields))))
+ (with-current-buffer buf-name (longlines-mode t))
+ (org-fit-window-to-buffer (get-buffer-window buf-name))
+ ((lambda (result) (when (> (length result) 0) result))
+ (read-from-minibuffer (format "%s: " name))))))
+
+(defun org-bibtex-autokey ()
+ "Generate an autokey for the current headline"
+ (org-bibtex-put org-bibtex-key-property
+ (if org-bibtex-autogen-keys
+ (let ((entry (org-bibtex-headline)))
+ (with-temp-buffer
+ (insert entry)
+ (bibtex-generate-autokey)))
+ (read-from-minibuffer "id: "))))
+
+(defun org-bibtex-fleshout (type &optional optional)
+ "Fleshout the current heading, ensuring that all required fields are present.
+With optional argument OPTIONAL, also prompt for optional fields."
+ (flet ((get (key lst) (cdr (assoc key lst)))
+ (keyword (name) (intern (concat ":" (downcase name))))
+ (name (keyword) (upcase (substring (symbol-name keyword) 1))))
+ (dolist (field (append
+ (remove :title (get :required (get type org-bibtex-types)))
+ (when optional (get :optional (get type org-bibtex-types)))))
+ (when (consp field) ; or'd pair of fields e.g., (:editor :author)
+ (let ((present (first (remove nil
+ (mapcar
+ (lambda (f) (when (org-bibtex-get (name f)) f))
+ field)))))
+ (setf field (or present (keyword (org-icompleting-read
+ "Field: " (mapcar #'name field)))))))
+ (let ((name (name field)))
+ (unless (org-bibtex-get name)
+ (let ((prop (org-bibtex-ask field)))
+ (when prop (org-bibtex-put name prop)))))))
+ (when (and type (assoc type org-bibtex-types)
+ (not (org-bibtex-get org-bibtex-key-property)))
+ (org-bibtex-autokey)))
+
+
+;;; Bibtex link functions
(org-add-link-type "bibtex" 'org-bibtex-open)
(add-hook 'org-store-link-functions 'org-bibtex-store-link)
-;; (defun org-bibtex-publish (path)
-;; "Build the description of the BibTeX entry for publishing."
-;; (let* ((search (when (string-match "::\\(.+\\)\\'" path)
-;; (match-string 1 path)))
-;; (path (substring path 0 (match-beginning 0)))
-;; key)
-;; (with-temp-buffer
-;; (org-open-file path t nil search)
-;; (setq key (org-create-file-search-functions)))
-;; (or description key)))
-
(defun org-bibtex-open (path)
"Visit the bibliography entry on PATH."
(let* ((search (when (string-match "::\\(.+\\)\\'" path)
@@ -192,12 +433,103 @@
(goto-char p)
(bibtex-url)))
(recenter 0)) ; Move entry start to beginning of window
- ;; return t to indicate that the search is done.
+ ;; return t to indicate that the search is done.
t))
;; Finally add the link search function to the right hook.
(add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-bibtex)
+
+;;; Bibtex <-> Org-mode headline translation functions
+(defun org-bibtex ()
+ "Export each headline in the current file to a bibtex entry.
+Headlines are exported using `org-bibtex-export-headline'."
+ (interactive)
+ (let ((bibtex-entries (remove nil (org-map-entries #'org-bibtex-headline))))
+ (with-temp-file (concat (file-name-sans-extension (buffer-file-name)) ".bib")
+ (insert (mapconcat #'identity bibtex-entries "\n")))))
+
+(defun org-bibtex-check (&optional optional)
+ "Check the current headline for required fields.
+With prefix argument OPTIONAL also prompt for optional fields."
+ (interactive "P")
+ (save-restriction
+ (org-narrow-to-subtree)
+ (let ((type ((lambda (name) (when name (intern (concat ":" name))))
+ (org-bibtex-get "TYPE"))))
+ (when type (org-bibtex-fleshout type optional)))))
+
+(defun org-bibtex-check-all (&optional optional)
+ "Check all headlines in the current file.
+With prefix argument OPTIONAL also prompt for optional fields."
+ (interactive) (org-map-entries (lambda () (org-bibtex-check optional))))
+
+(defun org-bibtex-create (type)
+ "Create a new entry at the given level."
+ (interactive
+ (list (org-icompleting-read
+ "Type: "
+ (mapcar (lambda (type) (symbol-name (car type))) org-bibtex-types))))
+ (let ((type (if (keywordp type) type (intern type))))
+ (unless (assoc type org-bibtex-types)
+ (error "type:%s is not known" type))
+ (org-insert-heading)
+ (let ((title (org-bibtex-ask :title)))
+ (insert title) (org-bibtex-put "TITLE" title))
+ (org-bibtex-put "TYPE" (substring (symbol-name type) 1))
+ (org-bibtex-fleshout type)))
+
+(defun org-bibtex-read ()
+ "Read a bibtex entry and save to `*org-bibtex-entries*'.
+This uses `bibtex-parse-entry'."
+ (interactive)
+ (flet ((keyword (str) (intern (concat ":" (downcase str))))
+ (clean-space (str) (replace-regexp-in-string
+ "[[:space:]\n\r]+" " " str))
+ (strip-delim (str) ; strip enclosing "..." and {...}
+ (dolist (pair '((34 . 34) (123 . 125) (123 . 125)))
+ (when (and (= (aref str 0) (car pair))
+ (= (aref str (1- (length str))) (cdr pair)))
+ (setf str (subseq str 1 (1- (length str)))))) str))
+ (push (mapcar
+ (lambda (pair)
+ (cons (let ((field (keyword (car pair))))
+ (case field
+ (:=type= :type)
+ (:=key= :key)
+ (otherwise field)))
+ (clean-space (strip-delim (cdr pair)))))
+ (save-excursion (bibtex-beginning-of-entry) (bibtex-parse-entry)))
+ *org-bibtex-entries*)))
+
+(defun org-bibtex-write ()
+ "Insert a heading built from the first element of `*org-bibtex-entries*'."
+ (interactive)
+ (when (= (length *org-bibtex-entries*) 0)
+ (error "No entries in `*org-bibtex-entries*'."))
+ (let ((entry (pop *org-bibtex-entries*))
+ (org-special-properties nil)) ; avoids errors with `org-entry-put'
+ (flet ((get (field) (cdr (assoc field entry))))
+ (org-insert-heading)
+ (insert (get :title))
+ (org-bibtex-put "TITLE" (get :title))
+ (org-bibtex-put "TYPE" (downcase (get :type)))
+ (dolist (pair entry)
+ (case (car pair)
+ (:title nil)
+ (:type nil)
+ (:key (org-bibtex-put org-bibtex-key-property (cdr pair)))
+ (otherwise (org-bibtex-put (car pair) (cdr pair))))))))
+
+(defun org-bibtex-yank ()
+ "If kill ring holds a bibtex entry yank it as an Org-mode headline."
+ (interactive)
+ (let (entry)
+ (with-temp-buffer (yank 1) (setf entry (org-bibtex-read)))
+ (if entry
+ (org-bibtex-write)
+ (error "yanked text does not appear to contain a bibtex entry"))))
+
(provide 'org-bibtex)
;; arch-tag: 83987d5a-01b8-41c7-85bc-77700f1285f5
diff --git a/lisp/org-capture.el b/lisp/org-capture.el
index eb7430b..8beea68 100644
--- a/lisp/org-capture.el
+++ b/lisp/org-capture.el
@@ -215,6 +215,7 @@ Furthermore, the following %-escapes will be replaced with content:
%u, %U like the above, but inactive time stamps
%^t like %t, but prompt for date. Similarly %^T, %^u, %^U.
You may define a prompt like %^{Please specify birthday
+ %<...> the result of format-time-string on the ... format specification
%n user name (taken from `user-full-name')
%a annotation, normally the link created with `org-store-link'
%i initial content, copied from the active region. If %i is
@@ -346,6 +347,9 @@ The remember buffer is still current when this hook runs."
"Local variable holding the plist in a capture buffer.
This is used to store the plist for use when finishing a capture process.
Another such process might have changed the global variable by then.")
+(defvar org-capture-clock-keep nil
+ "Local variable to store the value of the :clock-keep parameter.
+This is needed in case org-capture-finalize is called interactively.")
(defun org-capture-put (&rest stuff)
(while stuff
@@ -446,6 +450,7 @@ bypassed."
(if (get-buffer "*Capture*") (kill-buffer "*Capture*"))
(error "Capture abort: %s" error)))
+ (setq org-capture-clock-keep (org-capture-get :clock-keep))
(if (equal goto 0)
;;insert at point
(org-capture-insert-template-here)
@@ -459,19 +464,19 @@ bypassed."
(error "Capture template `%s': %s"
(org-capture-get :key)
(nth 1 error))))
+ (if (and (org-mode-p)
+ (org-capture-get :clock-in))
+ (condition-case nil
+ (progn
+ (if (org-clock-is-active)
+ (org-capture-put :interrupted-clock
+ (copy-marker org-clock-marker)))
+ (org-clock-in)
+ (org-set-local 'org-capture-clock-was-started t))
+ (error
+ "Could not start the clock in this capture buffer")))
(if (org-capture-get :immediate-finish)
- (org-capture-finalize nil (org-capture-get :clock-keep))
- (if (and (org-mode-p)
- (org-capture-get :clock-in))
- (condition-case nil
- (progn
- (if (org-clock-is-active)
- (org-capture-put :interrupted-clock
- (copy-marker org-clock-marker)))
- (org-clock-in)
- (org-set-local 'org-capture-clock-was-started t))
- (error
- "Could not start the clock in this capture buffer")))))))))))
+ (org-capture-finalize nil)))))))))
(defun org-capture-get-template ()
"Get the template from a file or a function if necessary."
@@ -491,12 +496,10 @@ bypassed."
(t (setq txt "* Invalid capture template")))
(org-capture-put :template txt)))
-(defun org-capture-finalize (&optional stay-with-capture clock-keep)
+(defun org-capture-finalize (&optional stay-with-capture)
"Finalize the capture process.
With prefix argument STAY-WITH-CAPTURE, jump to the location of the
-captured item after finalizing.
-A second optional argument tells whether finalizing the capture
-process should keep the clock running in the filed entry."
+captured item after finalizing."
(interactive "P")
(unless (and org-capture-mode
(buffer-base-buffer (current-buffer)))
@@ -509,8 +512,8 @@ process should keep the clock running in the filed entry."
(> org-clock-marker (point-min))
(< org-clock-marker (point-max)))
;; Looks like the clock we started is still running. Clock out.
- (when (not clock-keep) (let (org-log-note-clock-out) (org-clock-out)))
- (when (and (not clock-keep)
+ (when (not org-capture-clock-keep) (let (org-log-note-clock-out) (org-clock-out)))
+ (when (and (not org-capture-clock-keep)
(org-capture-get :clock-resume 'local)
(markerp (org-capture-get :interrupted-clock 'local))
(buffer-live-p (marker-buffer
@@ -1011,13 +1014,28 @@ it. When it is a variable, retrieve the value. Return whatever we get."
(org-table-align)))
(defun org-capture-place-plain-text ()
- "Place the template plainly."
+ "Place the template plainly.
+If the target locator points at an Org node, place the template into
+the text of the entry, before the first child. If not, place the
+template at the beginning or end of the file.
+Of course, if exact position has been required, just put it there."
(let* ((txt (org-capture-get :template))
beg end)
- (goto-char (cond
- ((org-capture-get :exact-position))
- ((org-capture-get :prepend) (point-min))
- (t (point-max))))
+ (cond
+ ((org-capture-get :exact-position)
+ (goto-char (org-capture-get :exact-position)))
+ ((and (org-capture-get :target-entry-p)
+ (bolp)
+ (looking-at org-outline-regexp))
+ ;; we should place the text into this entry
+ (if (org-capture-get :prepend)
+ ;; Skip meta data and drawers
+ (org-end-of-meta-data-and-drawers)
+ ;; go to ent of the entry text, before the next headline
+ (outline-next-heading)))
+ (t
+ ;; beginning or end of file
+ (goto-char (if (org-capture-get :prepend) (point-min) (point-max)))))
(or (bolp) (newline))
(org-capture-empty-lines-before)
(setq beg (point))
@@ -1299,6 +1317,11 @@ The template may still contain \"%?\" for cursor positioning."
(delete-region template-start (point))
(insert result)))))
+ ;; The current time
+ (goto-char (point-min))
+ (while (re-search-forward "%<\\([^>\n]+\\)>" nil t)
+ (replace-match (format-time-string (match-string 1)) t t))
+
;; Simple %-escapes
(goto-char (point-min))
(while (re-search-forward "%\\([tTuUaiAcxkKInfF]\\)" nil t)
diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index 87b175c..efeb72f 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -2424,6 +2424,8 @@ This function is made for clock tables."
tot))))
0))))
+;; Saving and loading the clock
+
(defvar org-clock-loaded nil
"Was the clock file loaded?")
diff --git a/lisp/org-docbook.el b/lisp/org-docbook.el
index 02704c4..124e1dc 100644
--- a/lisp/org-docbook.el
+++ b/lisp/org-docbook.el
@@ -529,6 +529,7 @@ publishing directory."
(plist-get opt-plist :skip-before-1st-heading)
:drawers (plist-get opt-plist :drawers)
:todo-keywords (plist-get opt-plist :todo-keywords)
+ :tasks (plist-get opt-plist :tasks)
:tags (plist-get opt-plist :tags)
:priority (plist-get opt-plist :priority)
:footnotes (plist-get opt-plist :footnotes)
@@ -1381,7 +1382,7 @@ the alist of previous items."
(string-match (concat "[ \t]*\\(\\S-+[ \t]*\\)"
"\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[a-zA-Z]\\)\\]\\)?"
"\\(?:\\(\\[[ X-]\\]\\)[ \t]+\\)?"
- "\\(?:\\(.*\\)[ \t]+::[ \t]+\\)?"
+ "\\(?:\\(.*\\)[ \t]+::\\(?:[ \t]+\\|$\\)\\)?"
"\\(.*\\)")
line)
(let* ((checkbox (match-string 3 line))
diff --git a/lisp/org-exp.el b/lisp/org-exp.el
index 3e84314..2ed989e 100644
--- a/lisp/org-exp.el
+++ b/lisp/org-exp.el
@@ -296,6 +296,23 @@ When nil, remove all these keywords from the export."
:group 'org-export-general
:type 'boolean)
+(defcustom org-export-with-tasks t
+ "Non-nil means include TODO items for export.
+This may have the following values:
+t include tasks independent of state.
+todo include only tasks that are not yet done.
+done include only tasks that are already done.
+nil remove all tasks before export
+list of TODO kwds keep only tasks with these keywords"
+ :group 'org-export-general
+ :type '(choice
+ (const :tag "All tasks" t)
+ (const :tag "No tasks" nil)
+ (const :tag "Not-done tasks" todo)
+ (const :tag "Only done tasks" done)
+ (repeat :tag "Specific TODO keywords"
+ (string :tag "Keyword"))))
+
(defcustom org-export-with-priority nil
"Non-nil means include priority cookies in export.
When nil, remove priority cookies for export."
@@ -621,6 +638,7 @@ table.el tables."
(:drawers "d" org-export-with-drawers)
(:tags "tags" org-export-with-tags)
(:todo-keywords "todo" org-export-with-todo-keywords)
+ (:tasks "tasks" org-export-with-tasks)
(:priority "pri" org-export-with-priority)
(:TeX-macros "TeX" org-export-with-TeX-macros)
(:LaTeX-fragments "LaTeX" org-export-with-LaTeX-fragments)
@@ -841,7 +859,7 @@ security risks."
(while (setq o (pop op))
(if (and (nth 1 o)
(string-match (concat "\\<" (regexp-quote (nth 1 o))
- ":\\([^ \t\n\r;,.]*\\)")
+ ":\\(([^)\n]+)\\|[^ \t\n\r;,.]*\\)")
options))
(setq p (plist-put p (car o)
(car (read-from-string
@@ -976,17 +994,19 @@ Pressing `1' will switch between these two options."
(setq subtree-p t)
(message "Export subtree: "))))
(when (eq r1 ?\ )
- (let ((case-fold-search t))
+ (let ((case-fold-search t)
+ (end (save-excursion (while (org-up-heading-safe)) (point))))
+ (outline-next-heading)
(if (re-search-backward
- "^[ \t]+\\(:latex_class:\\|:export_title:\\)[ \t]+\\S-"
- nil t)
+ "^[ \t]+\\(:latex_class:\\|:export_title:\\|:export_file_name:\\)[ \t]+\\S-"
+ end t)
(progn
(org-back-to-heading t)
(setq subtree-p t)
(setq bpos (point))
(message "Select command (for subtree): ")
(setq r1 (read-char-exclusive)))
- (error "No enclosing node with LaTeX_CLASS or EXPORT_FILE_NAME")
+ (error "No enclosing node with LaTeX_CLASS or EXPORT_TITLE or EXPORT_FILE_NAME")
)))))
(redisplay)
(and bpos (goto-char bpos))
@@ -1077,16 +1097,20 @@ on this string to produce the exported version."
;; Call the hook
(run-hooks 'org-export-preprocess-hook)
- ;; Process the macros
- (org-export-preprocess-apply-macros)
- (run-hooks 'org-export-preprocess-after-macros-hook)
-
(untabify (point-min) (point-max))
;; Handle include files, and call a hook
(org-export-handle-include-files-recurse)
(run-hooks 'org-export-preprocess-after-include-files-hook)
+ ;; Change lists ending. Other parts of export may insert blank
+ ;; lines and lists' structure could be altered.
+ (org-export-mark-list-end)
+
+ ;; Process the macros
+ (org-export-preprocess-apply-macros)
+ (run-hooks 'org-export-preprocess-after-macros-hook)
+
;; Get rid of archived trees
(org-export-remove-archived-trees archived-trees)
@@ -1098,9 +1122,8 @@ on this string to produce the exported version."
(plist-get parameters :exclude-tags))
(run-hooks 'org-export-preprocess-after-tree-selection-hook)
- ;; Change lists ending. Other parts of export may insert blank
- ;; lines and lists' structure could be altered.
- (org-export-mark-list-end)
+ ;; Get rid of tasks, depending on configuration
+ (org-export-remove-tasks (plist-get parameters :tasks))
;; Export code blocks
(org-export-blocks-preprocess)
@@ -1488,6 +1511,36 @@ removed as well."
(point-max)))
(delete-region beg end))))
+(defun org-export-remove-tasks (keep)
+ "Remove tasks depending on configuration.
+When KEEP is nil, remove all tasks.
+When KEEP is `todo', remove the tasks that are DONE.
+When KEEP is `done', remove the tasks that are not yet done.
+When it is a list of strings, keep only tasks with these TODO keywords."
+ (when (or (listp keep) (memq keep '(todo done nil)))
+ (let ((re (concat "^\\*+[ \t]+\\("
+ (mapconcat
+ 'regexp-quote
+ (cond ((not keep) org-todo-keywords-1)
+ ((eq keep 'todo) org-done-keywords)
+ ((eq keep 'done) org-not-done-keywords)
+ ((listp keep)
+ (org-delete-all keep (copy-sequence
+ org-todo-keywords-1))))
+ "\\|")
+ "\\)\\($\\|[ \t]\\)"))
+ (case-fold-search nil)
+ beg)
+ (goto-char (point-min))
+ (while (re-search-forward re nil t)
+ (org-if-unprotected
+ (setq beg (match-beginning 0))
+ (org-end-of-subtree t t)
+ (if (looking-at "^\\*+[ \t]+END[ \t]*$")
+ ;; Kill the END line of the inline task
+ (goto-char (min (point-max) (1+ (match-end 0)))))
+ (delete-region beg (point)))))))
+
(defun org-export-remove-archived-trees (export-archived-trees)
"Remove archived trees.
When EXPORT-ARCHIVED-TREES is `headline;, only the headline will be exported.
@@ -1828,7 +1881,7 @@ table line. If it is a link, add it to the line containing the link."
(goto-char (point-min))
(setq case-fold-search t)
(while (re-search-forward
- "^#\\+begin_comment[ \t]*\n[^\000]*?^#\\+end_comment\\>.*" nil t)
+ "^#\\+begin_comment[ \t]*\n[^\000]*?\n#\\+end_comment\\>.*" nil t)
(replace-match "" t t))
;; Remove subtrees that are commented
(goto-char (point-min))
@@ -1853,7 +1906,10 @@ When it is nil, all comments will be removed."
(not (equal (char-before (match-end 1)) ?+)))
(progn (add-text-properties
(match-beginning 0) (match-end 0) '(org-protected t))
- (replace-match (format commentsp (match-string 2)) t t))
+ (replace-match (org-add-props
+ (format commentsp (match-string 2))
+ nil 'org-protected t)
+ t t))
(goto-char (1+ pos))
(replace-match "")
(goto-char (max (point-min) (1- pos))))))))
@@ -2163,26 +2219,35 @@ TYPE must be a string, any of:
(defun org-export-preprocess-apply-macros ()
"Replace macro references."
(goto-char (point-min))
- (let (sy val key args args2 s n)
+ (let (sy val key args args2 ind-str s n)
(while (re-search-forward
"{{{\\([a-zA-Z][-a-zA-Z0-9_]*\\)\\(([ \t\n]*\\([^\000]*?\\))\\)?}}}"
nil t)
- (unless (save-match-data
- (save-excursion
- (goto-char (point-at-bol))
- (looking-at "[ \t]*#\\+macro")))
+ (unless (save-match-data (save-excursion
+ (goto-char (point-at-bol))
+ (looking-at "[ \t]*#\\+macro")))
+ ;; Get macro name (KEY), arguments (ARGS), and indentation of
+ ;; current line (IND-STR) as strings.
(setq key (downcase (match-string 1))
- args (match-string 3))
+ args (match-string 3)
+ ind-str (save-match-data (save-excursion
+ (beginning-of-line)
+ (looking-at "^\\([ \t]*\\).*")
+ (match-string 1))))
+ ;; When macro is defined, retrieve replacement text in VAL,
+ ;; and proceed with expansion.
(when (setq val (or (plist-get org-export-opt-plist
(intern (concat ":macro-" key)))
(plist-get org-export-opt-plist
(intern (concat ":" key)))))
(save-match-data
+ ;; If arguments are provided, first retreive them properly
+ ;; (in ARGS, as a list), then replace them in VAL.
(when args
(setq args (org-split-string args ",") args2 nil)
(while args
(while (string-match "\\\\\\'" (car args))
- ;; repair bad splits
+ ;; Repair bad splits.
(setcar (cdr args) (concat (substring (car args) 0 -1)
"," (nth 1 args)))
(pop args))
@@ -2194,13 +2259,22 @@ TYPE must be a string, any of:
n (string-to-number (match-string 1 val)))
(and (>= (length args) n)
(setq val (replace-match (nth (1- n) args) t t val)))))
+ ;; VAL starts with "(eval": it is a sexp, `eval' it.
(when (string-match "\\`(eval\\>" val)
(setq val (eval (read val))))
- (if (and val (not (stringp val)))
- (setq val (format "%s" val))))
- (and (stringp val)
- (prog1 (replace-match val t t)
- (goto-char (match-beginning 0)))))))))
+ ;; Ensure VAL is a string (or nil) and that each new line
+ ;; is indented as the first one.
+ (setq val (and val
+ (mapconcat 'identity
+ (org-split-string
+ (if (stringp val) val (format "%s" val))
+ "\n")
+ (concat "\n" ind-str)))))
+ ;; Eventually do the replacement, if VAL isn't nil. Move
+ ;; point at beginning of macro for recursive expansions.
+ (when val
+ (replace-match val t t)
+ (goto-char (match-beginning 0))))))))
(defun org-export-apply-macros-in-string (s)
"Apply the macros in string S."
diff --git a/lisp/org-html.el b/lisp/org-html.el
index 62fce1b..7a4564d 100644
--- a/lisp/org-html.el
+++ b/lisp/org-html.el
@@ -826,7 +826,8 @@ MAY-INLINE-P allows inlining it as an image."
(not type)
(string= type "http")
(string= type "https")
- (string= type "file"))
+ (string= type "file")
+ (string= type "coderef"))
(if fragment
(setq thefile (concat thefile "#" fragment))))
@@ -836,7 +837,8 @@ MAY-INLINE-P allows inlining it as an image."
(setq thefile
(let
((str (org-export-html-format-href thefile)))
- (if (and type (not (string= "file" type)))
+ (if (and type (not (or (string= "file" type)
+ (string= "coderef" type))))
(concat type ":" str)
str)))
@@ -886,7 +888,8 @@ OPT-PLIST is the export options list."
(if (string-match "^file:" desc)
(setq desc (substring desc (match-end 0)))))
(setq desc (org-add-props
- (concat "<img src=\"" desc "\"/>")
+ (concat "<img src=\"" desc "\" alt=\""
+ (file-name-nondirectory desc) "\"/>")
'(org-protected t))))
(cond
((equal type "internal")
@@ -1179,6 +1182,7 @@ PUB-DIR is set, use this as the publishing directory."
(plist-get opt-plist :skip-before-1st-heading)
:drawers (plist-get opt-plist :drawers)
:todo-keywords (plist-get opt-plist :todo-keywords)
+ :tasks (plist-get opt-plist :tasks)
:tags (plist-get opt-plist :tags)
:priority (plist-get opt-plist :priority)
:footnotes (plist-get opt-plist :footnotes)
@@ -1356,7 +1360,9 @@ lang=\"%s\" xml:lang=\"%s\">
(if (string-match quote-re0 txt)
(setq txt (replace-match "" t t txt)))
(setq snumber (org-section-number level))
- (if (and num (integerp num) (>= num level))
+ (if (and num (if (integerp num)
+ (>= num level)
+ num))
(setq txt (concat snumber " " txt)))
(if (<= level (max umax umax-toc))
(setq head-count (+ head-count 1)))
@@ -2404,16 +2410,16 @@ When TITLE is nil, just close all open levels."
(setq title (concat
(format "<span class=\"section-number-%d\">%s</span>"
level
- (if (and (integerp num)
- ;; fix up num to take into
- ;; account the top-level
- ;; heading value
- (>= (+ num
- org-export-html-toplevel-hlevel
- -1)
- level))
- snumber
- ""))
+ (if (and num
+ (if (integerp num)
+ ;; fix up num to take into
+ ;; account the top-level
+ ;; heading value
+ (>= (+ num org-export-html-toplevel-hlevel -1)
+ level)
+ num))
+ snumber
+ ""))
" " title)))
(unless (= head-count 1) (insert "\n</div>\n"))
(setq href (cdr (assoc (concat "sec-" snu) org-export-preferred-target-alist)))
@@ -2500,7 +2506,7 @@ the alist of previous items."
(concat "[ \t]*\\(\\S-+[ \t]*\\)"
"\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\]\\)?"
"\\(?:\\(\\[[ X-]\\]\\)[ \t]+\\)?"
- "\\(?:\\(.*\\)[ \t]+::[ \t]+\\)?"
+ "\\(?:\\(.*\\)[ \t]+::\\(?:[ \t]+\\|$\\)\\)?"
"\\(.*\\)") line)
(let* ((checkbox (match-string 3 line))
(desc-tag (or (match-string 4 line) "???"))
diff --git a/lisp/org-latex.el b/lisp/org-latex.el
index 605795c..e7307ef 100644
--- a/lisp/org-latex.el
+++ b/lisp/org-latex.el
@@ -869,6 +869,7 @@ when PUB-DIR is set, use this as the publishing directory."
:drawers (plist-get opt-plist :drawers)
:timestamps (plist-get opt-plist :timestamps)
:todo-keywords (plist-get opt-plist :todo-keywords)
+ :tasks (plist-get opt-plist :tasks)
:add-text nil
:skip-before-1st-heading skip
:select-tags nil
@@ -886,6 +887,7 @@ when PUB-DIR is set, use this as the publishing directory."
:drawers (plist-get opt-plist :drawers)
:timestamps (plist-get opt-plist :timestamps)
:todo-keywords (plist-get opt-plist :todo-keywords)
+ :tasks (plist-get opt-plist :tasks)
:add-text (if (eq to-buffer 'string) nil text)
:skip-before-1st-heading skip
:select-tags (plist-get opt-plist :select-tags)
@@ -1524,7 +1526,7 @@ links, keywords, lists, tables, fixed-width"
(format org-export-latex-tag-markup
(save-match-data
(replace-regexp-in-string
- "_" "\\\\_" (match-string 0)))))
+ "\\([_#]\\)" "\\\\\\1" (match-string 0)))))
t t)))))
(defun org-export-latex-fontify-headline (string)
@@ -1684,13 +1686,7 @@ See the `org-export-latex.el' code for a complete conversion table."
"\\(\\(\\\\?\\$\\)\\)"
"\\([a-zA-Z0-9()]+\\|[ \t\n]\\|\\b\\|\\\\\\)\\(_\\|\\^\\)\\({[^{}]+}\\|[a-zA-Z0-9]+\\|[ \t\n]\\|[:punct:]\\|)\\|{[a-zA-Z0-9]+}\\|([a-zA-Z0-9]+)\\)"
"\\(.\\|^\\)\\(\\\\\\)\\([ \t\n]\\|\\([&#%{}\"]\\|[a-zA-Z][a-zA-Z0-9]*\\)\\)"
- "\\(.\\|^\\)\\(&\\)"
- "\\(.\\|^\\)\\(#\\)"
- "\\(.\\|^\\)\\(%\\)"
- "\\(.\\|^\\)\\({\\)"
- "\\(.\\|^\\)\\(}\\)"
- "\\(.\\|^\\)\\(~\\)"
- "\\(.\\|^\\)\\(\\.\\.\\.\\)"
+ "\\(^\\|.\\)\\([&#%{}~]\\|\\.\\.\\.\\)"
;; (?\< . "\\textless{}")
;; (?\> . "\\textgreater{}")
)))
@@ -1994,7 +1990,7 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
(setq tbl (concat "\\begin{center}\n" tbl "\\end{center}")))
(when floatp
(setq tbl (concat "\\begin{table}\n"
- (format "\\caption%s{%s}%s\n"
+ (format "\\caption%s{%s%s}\n"
(if shortn (format "[%s]" shortn) "")
(if label (format "\\label{%s}" label) "")
(or caption ""))
@@ -2416,12 +2412,15 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
(replace-match (org-export-latex-protect-string
(concat "$^{" (match-string 1) "}$")))
(replace-match "")
- (let ((end (save-excursion
- (if (re-search-forward "^$\\|^#.*$\\|\\[[0-9]+\\]" nil t)
- (match-beginning 0) (point-max)))))
- (setq footnote (concat (org-trim (buffer-substring (point) end))
- ; last } won't be part of a link or list.
- "\n"))
+ (let* ((end (save-excursion
+ (if (re-search-forward "^$\\|^#.*$\\|\\[[0-9]+\\]" nil t)
+ (match-beginning 0) (point-max))))
+ (body (org-trim (buffer-substring (point) end))))
+ ;; Fix for footnotes ending on a link or a list.
+ (setq footnote
+ (concat body
+ (if (string-match "ORG-LIST-END-MARKER\\'" body)
+ "\n" " ")))
(delete-region (point) end))
(goto-char foot-beg)
(delete-region foot-beg foot-end)
diff --git a/lisp/org-list.el b/lisp/org-list.el
index 7787706..9c178e1 100644
--- a/lisp/org-list.el
+++ b/lisp/org-list.el
@@ -396,12 +396,16 @@ group 4: description tag")
(and (org-at-item-p)
(save-excursion
(goto-char (match-end 0))
- ;; Ignore counter if any
- (when (looking-at "\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?")
- (goto-char (match-end 0)))
+ (let ((counter-re (concat "\\(?:\\[@\\(?:start:\\)?"
+ (if org-alphabetical-lists
+ "\\([0-9]+\\|[A-Za-z]\\)"
+ "[0-9]+")
+ "\\][ \t]*\\)")))
+ ;; Ignore counter if any
+ (when (looking-at counter-re) (goto-char (match-end 0))))
(looking-at regexp))))
-(defun org-list-in-valid-block-p ()
+(defun org-list-in-valid-context-p ()
"Non-nil if point is in a valid block.
Invalid blocks are referring to `org-list-forbidden-blocks'."
(save-match-data
@@ -491,7 +495,7 @@ This checks `org-list-ending-method'."
"Is point in a line starting a hand-formatted item?"
(save-excursion
(beginning-of-line)
- (and (looking-at (org-item-re)) (org-list-in-valid-block-p))))
+ (and (looking-at (org-item-re)) (org-list-in-valid-context-p))))
(defun org-at-item-bullet-p ()
"Is point at the bullet of a plain list item?"
@@ -599,8 +603,8 @@ values are:
2. bullet with trailing whitespace,
3. bullet counter, if any,
4. checkbox, if any,
-5. position at item end,
-6. description tag, if any.
+5. description tag, if any,
+6. position at item end.
Thus the following list, where numbers in parens are
point-at-bol:
@@ -688,8 +692,20 @@ Assume point is at an item."
(throw 'exit
(setq itm-lst
(memq (assq (car beg-cell) itm-lst) itm-lst))))
- ;; Skip blocks, drawers, inline tasks, blank lines
- ;; along the way.
+ ;; Point is at an item. Add data to ITM-LST. It may
+ ;; also end a previous item: save it in END-LST. If ind
+ ;; is less or equal than BEG-CELL and there is no end
+ ;; at this ind or lesser, this item becomes the new
+ ;; BEG-CELL.
+ ((looking-at item-re)
+ (push (funcall assoc-at-point ind) itm-lst)
+ (push (cons ind (point)) end-lst)
+ (when (or (and (eq org-list-ending-method 'regexp)
+ (<= ind (cdr beg-cell)))
+ (< ind text-min-ind))
+ (setq beg-cell (cons (point) ind)))
+ (forward-line -1))
+ ;; Skip blocks, drawers, inline tasks, blank lines.
((and (looking-at "^[ \t]*#\\+end_")
(re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
((and (looking-at "^[ \t]*:END:")
@@ -700,26 +716,13 @@ Assume point is at an item."
(forward-line -1))
((looking-at "^[ \t]*$")
(forward-line -1))
- ((looking-at item-re)
- ;; Point is at an item. Add data to ITM-LST. It may
- ;; also end a previous item: save it in END-LST. If
- ;; ind is less or equal than BEG-CELL and there is no
- ;; end at this ind or lesser, this item becomes the
- ;; new BEG-CELL.
- (push (funcall assoc-at-point ind) itm-lst)
- (push (cons ind (point)) end-lst)
- (when (or (and (eq org-list-ending-method 'regexp)
- (<= ind (cdr beg-cell)))
- (< ind text-min-ind))
- (setq beg-cell (cons (point) ind)))
- (forward-line -1))
;; From there, point is not at an item. Unless ending
;; method is `regexp', interpret line's indentation:
;; - text at column 0 is necessarily out of any list.
;; Dismiss data recorded above BEG-CELL. Jump to
;; part 2.
- ;; - any other case, it can possibly be an ending
- ;; position for an item above. Save it and proceed.
+ ;; - any other case may be an ending position for an
+ ;; hypothetical item above. Store it and proceed.
((eq org-list-ending-method 'regexp) (forward-line -1))
((zerop ind)
(throw 'exit
@@ -730,9 +733,9 @@ Assume point is at an item."
(push (cons ind (point)) end-lst)
(forward-line -1)))))))
;; 2. Read list from starting point to its end, that is until we
- ;; get out of context, or a non-item line is less or equally
- ;; indented that BEG-CELL's cdr. Also store ending position
- ;; of items in END-LST-2.
+ ;; get out of context, or that a non-item line is less or
+ ;; equally indented than BEG-CELL's cdr. Also, store ending
+ ;; position of items in END-LST-2.
(catch 'exit
(while t
(let ((ind (+ (or (get-text-property (point) 'original-indentation) 0)
@@ -755,41 +758,39 @@ Assume point is at an item."
((and (not (eq org-list-ending-method 'indent))
(looking-at org-list-end-re))
(throw 'exit (push (cons 0 (point)) end-lst-2)))
- ;; Skip blocks, drawers, inline tasks and blank lines
- ;; along the way
- ((and (looking-at "^[ \t]*#\\+begin_")
- (re-search-forward "^[ \t]*#\\+end_" lim-down t))
- (forward-line 1))
- ((and (looking-at drawers-re)
- (re-search-forward "^[ \t]*:END:" lim-down t))
- (forward-line 1))
- ((and inlinetask-re (looking-at inlinetask-re))
- (org-inlinetask-goto-end))
- ((looking-at "^[ \t]*$")
- (forward-line 1))
((looking-at item-re)
;; Point is at an item. Add data to ITM-LST-2. It may also
;; end a previous item, so save it in END-LST-2.
(push (funcall assoc-at-point ind) itm-lst-2)
(push (cons ind (point)) end-lst-2)
(forward-line 1))
- ;; From there, point is not at an item. If ending method
- ;; is not `regexp', two situations are of interest:
- ;; - ind is lesser or equal than BEG-CELL's. The list is
- ;; over. Store point as an ending position and jump to
- ;; part 3.
- ;; - ind is lesser or equal than previous item's. This
- ;; is an ending position. Store it and proceed.
- ((eq org-list-ending-method 'regexp) (forward-line 1))
- ((<= ind (cdr beg-cell))
+ ;; Skip inline tasks and blank lines along the way
+ ((and inlinetask-re (looking-at inlinetask-re))
+ (org-inlinetask-goto-end))
+ ((looking-at "^[ \t]*$")
+ (forward-line 1))
+ ;; Ind is lesser or equal than BEG-CELL's. The list is
+ ;; over: store point as an ending position and jump to
+ ;; part 3.
+ ((and (not (eq org-list-ending-method 'regexp))
+ (<= ind (cdr beg-cell)))
(throw 'exit
(push (cons 0 (funcall end-before-blank)) end-lst-2)))
- ((<= ind (nth 1 (car itm-lst-2)))
- (push (cons ind (point)) end-lst-2)
- (forward-line 1))
- (t (forward-line 1))))))
- (setq struct (append itm-lst (cdr (nreverse itm-lst-2))))
- (setq end-lst (append end-lst (cdr (nreverse end-lst-2))))
+ ;; Else, if ind is lesser or equal than previous item's,
+ ;; this is an ending position: store it. In any case,
+ ;; skip block or drawer at point, and move to next line.
+ (t
+ (when (and (not (eq org-list-ending-method 'regexp))
+ (<= ind (nth 1 (car itm-lst-2))))
+ (push (cons ind (point)) end-lst-2))
+ (cond
+ ((and (looking-at "^[ \t]*#\\+begin_")
+ (re-search-forward "^[ \t]*#\\+end_" lim-down t)))
+ ((and (looking-at drawers-re)
+ (re-search-forward "^[ \t]*:END:" lim-down t))))
+ (forward-line 1))))))
+ (setq struct (append itm-lst (cdr (nreverse itm-lst-2)))
+ end-lst (append end-lst (cdr (nreverse end-lst-2))))
;; 3. Correct ill-formed lists by ensuring top item is the least
;; indented.
(let ((min-ind (nth 1 (car struct))))
@@ -798,7 +799,8 @@ Assume point is at an item."
(bul (nth 2 item)))
(when (< ind min-ind)
(setcar (cdr item) min-ind)
- ;; Modify bullet to be sure item will be modified
+ ;; Trim bullet so item will be seen as different
+ ;; when compared with repaired version.
(setcar (nthcdr 2 item) (org-trim bul)))))
struct))
;; 4. Associate each item to its end pos.
@@ -1053,7 +1055,7 @@ in `re-search-forward'."
nil)))
;; 2. Match in valid context: return point. Else, continue
;; searching.
- (when (org-list-in-valid-block-p) (throw 'exit (point)))))))
+ (when (org-list-in-valid-context-p) (throw 'exit (point)))))))
(defun org-list-search-backward (regexp &optional bound noerror)
"Like `re-search-backward' but stop only where lists are recognized.
@@ -2164,8 +2166,8 @@ in subtree, ignoring drawers."
"Checkboxes were removed due to unchecked box at line %d"
(org-current-line block-item))))
(goto-char bottom)
- (org-list-struct-apply-struct struct struct-copy))))
- (org-update-checkbox-count-maybe)))
+ (org-list-struct-apply-struct struct struct-copy)))))
+ (org-update-checkbox-count-maybe))
(defun org-reset-checkbox-state-subtree ()
"Reset all checkboxes in an entry subtree."
diff --git a/lisp/org-mobile.el b/lisp/org-mobile.el
index 83462f0..332ec18 100644
--- a/lisp/org-mobile.el
+++ b/lisp/org-mobile.el
@@ -305,9 +305,9 @@ create all custom agenda views, for upload to the mobile phone."
(org-agenda-redo-command org-agenda-redo-command))
(save-excursion
(save-window-excursion
+ (run-hooks 'org-mobile-pre-push-hook)
(org-mobile-check-setup)
(org-mobile-prepare-file-lists)
- (run-hooks 'org-mobile-pre-push-hook)
(message "Creating agendas...")
(let ((inhibit-redisplay t)) (org-mobile-create-sumo-agenda))
(message "Creating agendas...done")
diff --git a/lisp/org-protocol.el b/lisp/org-protocol.el
index 0bbef03..bedfaa3 100644
--- a/lisp/org-protocol.el
+++ b/lisp/org-protocol.el
@@ -400,9 +400,9 @@ The location for a browser's bookmark has to look like this:
See the docs for `org-protocol-capture' for more information."
(if (and (boundp 'org-stored-links)
- (or (fboundp 'org-capture))
+ (fboundp 'org-capture)
(org-protocol-do-capture info 'org-remember))
- (message "Org-mode not loaded."))
+ (message "Item remembered."))
nil)
(defun org-protocol-capture (info)
@@ -427,9 +427,9 @@ But you may prepend the encoded URL with a character and a slash like so:
Now template ?b will be used."
(if (and (boundp 'org-stored-links)
- (or (fboundp 'org-capture))
+ (fboundp 'org-capture)
(org-protocol-do-capture info 'org-capture))
- (message "Org-mode not loaded."))
+ (message "Item captured."))
nil)
(defun org-protocol-do-capture (info capture-func)
diff --git a/lisp/org-src.el b/lisp/org-src.el
index f72579a..4ec457c 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -153,7 +153,7 @@ but which mess up the display of a snippet in Org exported files.")
(defcustom org-src-lang-modes
'(("ocaml" . tuareg) ("elisp" . emacs-lisp) ("ditaa" . artist)
("asymptote" . asy) ("dot" . fundamental) ("sqlite" . sql)
- ("calc" . fundamental))
+ ("calc" . fundamental) ("C" . c))
"Alist mapping languages to their major mode.
The key is the language name, the value is the string that should
be inserted as the name of the major mode. For many languages this is
@@ -214,6 +214,7 @@ buffer."
(let ((mark (and (org-region-active-p) (mark)))
(case-fold-search t)
(info (org-edit-src-find-region-and-lang))
+ (full-info (org-babel-get-src-block-info))
(org-mode-p (or (org-mode-p) (derived-mode-p 'org-mode)))
(beg (make-marker))
(end (make-marker))
@@ -323,7 +324,10 @@ buffer."
(org-src-mode)
(set-buffer-modified-p nil)
(and org-edit-src-persistent-message
- (org-set-local 'header-line-format msg)))
+ (org-set-local 'header-line-format msg))
+ (let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang))))
+ (when (fboundp edit-prep-func)
+ (funcall edit-prep-func full-info))))
t)))
(defun org-edit-src-continue (e)
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 3573032..58aa835 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -3702,14 +3702,14 @@ Use COMMAND to do the motion, repeat if necessary to end up in a data line."
(defun org-table-cleanup-narrow-column-properties ()
"Remove all properties related to narrow-column invisibility."
- (let ((s 1))
+ (let ((s (point-min)))
(while (setq s (text-property-any s (point-max)
'display org-narrow-column-arrow))
(remove-text-properties s (1+ s) '(display t)))
- (setq s 1)
+ (setq s (point-min))
(while (setq s (text-property-any s (point-max) 'org-cwidth 1))
(remove-text-properties s (1+ s) '(org-cwidth t)))
- (setq s 1)
+ (setq s (point-min))
(while (setq s (text-property-any s (point-max) 'invisible 'org-cwidth))
(remove-text-properties s (1+ s) '(invisible t)))))
diff --git a/lisp/org.el b/lisp/org.el
index 27a3949..e17c90f 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5003,13 +5003,13 @@ This should be called after the variable `org-link-types' has changed."
(defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)>"
"Regular expression for fast time stamp matching.")
-(defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)[]>]"
+(defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^]\r\n>]*?\\)[]>]"
"Regular expression for fast time stamp matching.")
-(defconst org-ts-regexp0 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) *\\([^]-+0-9>\r\n ]*\\)\\( \\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
+(defconst org-ts-regexp0 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) *\\([^]+0-9>\r\n -]*\\)\\( \\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
"Regular expression matching time strings for analysis.
This one does not require the space after the date, so it can be used
on a string that terminates immediately after the date.")
-(defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) +\\([^]-+0-9>\r\n ]*\\)\\( \\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
+(defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) +\\([^]+0-9>\r\n -]*\\)\\( \\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
"Regular expression matching time strings for analysis.")
(defconst org-ts-regexp2 (concat "<" org-ts-regexp1 "[^>\n]\\{0,16\\}>")
"Regular expression matching time stamps, with groups.")
@@ -5593,8 +5593,8 @@ needs to be inserted at a specific position in the font-lock sequence.")
'("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
(0 (org-get-checkbox-statistics-face) t)))
;; Description list items
- '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\)[ \t]+\\(.*? ::\\)"
- 2 'bold prepend)
+ '("^[ \t]*[-+*][ \t]+\\(.*?[ \t]+::\\)\\([ \t]+\\|$\\)"
+ 1 'bold prepend)
;; ARCHIVEd headings
(list (concat "^\\*+ \\(.*:" org-archive-tag ":.*\\)")
'(1 'org-archived prepend))
@@ -7145,6 +7145,8 @@ If the region is active in `transient-mark-mode', promote all headings
in the region."
(org-back-to-heading t)
(let* ((level (save-match-data (funcall outline-level)))
+ (after-change-functions (remove 'flyspell-after-change-function
+ after-change-functions))
(up-head (concat (make-string (org-get-valid-level level -1) ?*) " "))
(diff (abs (- level (length up-head) -1))))
(if (= level 1) (error "Cannot promote to level 0. UNDO to recover if necessary"))
@@ -7160,6 +7162,8 @@ If the region is active in `transient-mark-mode', demote all headings
in the region."
(org-back-to-heading t)
(let* ((level (save-match-data (funcall outline-level)))
+ (after-change-functions (remove 'flyspell-after-change-function
+ after-change-functions))
(down-head (concat (make-string (org-get-valid-level level 1) ?*) " "))
(diff (abs (- level (length down-head) -1))))
(replace-match down-head nil t)
@@ -13694,7 +13698,7 @@ when a \"nil\" value can supersede a non-nil value higher up the hierarchy."
(if (and range
(goto-char (car range))
(re-search-forward
- (concat "^[ \t]*:" property ":[ \t]*\\(.*[^ \t\r\n\f\v]\\)?")
+ (org-re-property property)
(cdr range) t))
;; Found the property, return it.
(if (match-end 1)
@@ -13720,7 +13724,7 @@ If yes, return this value. If not, return the current value of the variable."
(if (and range
(goto-char (car range))
(re-search-forward
- (concat "^[ \t]*:" property ":[ \t]*\\(.*[^ \t\r\n\f\v]\\)")
+ (org-re-property property)
(cdr range) t))
(progn
(delete-region (match-beginning 0) (1+ (point-at-eol)))
@@ -13867,7 +13871,7 @@ and the new value.")
(setq range (org-get-property-block beg end 'force))
(goto-char (car range))
(if (re-search-forward
- (concat "^[ \t]*:" property ":\\(.*\\)") (cdr range) t)
+ (org-re-property property) (cdr range) t)
(progn
(delete-region (match-beginning 1) (match-end 1))
(goto-char (match-beginning 1)))
@@ -13929,13 +13933,18 @@ formats in the current buffer."
(sort rtn (lambda (a b) (string< (upcase a) (upcase b))))))
+(defsubst org-re-property (property)
+ "Return a regexp matching PROPERTY.
+Match group 1 will be set to the value "
+ (concat "^[ \t]*:" (regexp-quote property) ":[ \t]*\\(\\S-.*\\)"))
+
(defun org-property-values (key)
- "Return a list of all values of property KEY."
+ "Return a list of all values of property KEY in the current buffer."
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
- (let ((re (concat "^[ \t]*:" key ":[ \t]*\\(\\S-.*\\)"))
+ (let ((re (org-re-property key))
values)
(while (re-search-forward re nil t)
(add-to-list 'values (org-trim (match-string 1))))
@@ -14068,7 +14077,7 @@ in the current file."
(goto-char (point-min))
(let ((cnt 0))
(while (re-search-forward
- (concat "^[ \t]*:" (regexp-quote property) ":.*\n?")
+ (org-re-property property)
nil t)
(setq cnt (1+ cnt))
(replace-match ""))
@@ -14180,7 +14189,7 @@ only headings."
(level 1)
(lmin 1)
(lmax 1)
- limit re end found pos heading cnt)
+ limit re end found pos heading cnt flevel)
(unless buffer (error "File not found :%s" file))
(with-current-buffer buffer
(save-excursion
@@ -14195,13 +14204,13 @@ only headings."
(while (re-search-forward re end t)
(setq level (- (match-end 1) (match-beginning 1)))
(if (and (>= level lmin) (<= level lmax))
- (setq found (match-beginning 0) cnt (1+ cnt))))
+ (setq found (match-beginning 0) flevel level cnt (1+ cnt))))
(when (= cnt 0) (error "Heading not found on level %d: %s"
lmax heading))
(when (> cnt 1) (error "Heading not unique on level %d: %s"
lmax heading))
(goto-char found)
- (setq lmin (1+ level) lmax (+ lmin (if org-odd-levels-only 1 0)))
+ (setq lmin (1+ flevel) lmax (+ lmin (if org-odd-levels-only 1 0)))
(setq end (save-excursion (org-end-of-subtree t t))))
(when (org-on-heading-p)
(move-marker (make-marker) (point))))))))
@@ -14636,6 +14645,19 @@ user."
(if (< year 100) (setq year (+ 2000 year)))
(setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
t nil ans)))
+
+ ;; Help matching dottet european dates
+ (when (string-match
+ "^ *\\(3[01]\\|0?[1-9]\\|[12][0-9]\\)\\. ?\\(0?[1-9]\\|1[012]\\)\\. ?\\([1-9][0-9][0-9][0-9]\\)?" ans)
+ (setq year (if (match-end 3)
+ (string-to-number (match-string 3 ans))
+ (progn (setq kill-year t)
+ (string-to-number (format-time-string "%Y"))))
+ day (string-to-number (match-string 1 ans))
+ month (string-to-number (match-string 2 ans))
+ ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
+ t nil ans)))
+
;; Help matching american dates, like 5/30 or 5/30/7
(when (string-match
"^ *\\(0?[1-9]\\|1[012]\\)/\\(0?[1-9]\\|[12][0-9]\\|3[01]\\)\\(/\\([0-9]+\\)\\)?\\([^/0-9]\\|$\\)" ans)
@@ -15570,6 +15592,7 @@ In fact, the first hh:mm or number in the string will be taken,
there can be extra stuff in the string.
If no number is found, the return value is 0."
(cond
+ ((integerp s) s)
((string-match "\\([0-9]+\\):\\([0-9]+\\)" s)
(+ (* (string-to-number (match-string 1 s)) 60)
(string-to-number (match-string 2 s))))
@@ -19039,6 +19062,8 @@ If point is in an inline task, mark that task instead."
((looking-at "# ") (setq column 0))
;; Headings
((looking-at "\\*+ ") (setq column 0))
+ ;; Footnote definition
+ ((looking-at org-footnote-definition-re) (setq column 0))
;; Literal examples
((looking-at "[ \t]*:[ \t]")
(setq column (org-get-indentation))) ; do nothing
@@ -19077,15 +19102,16 @@ If point is in an inline task, mark that task instead."
(not (looking-at org-drawer-regexp))
;; When point started in an inline task, do not move
;; above task starting line.
- (not (and inline-task-p
- (looking-at inline-re)))
- ;; Skip comments, verbatim, empty lines, tables,
- ;; inline tasks, lists, drawers and blocks.
+ (not (and inline-task-p (looking-at inline-re)))
+ ;; Skip drawers, blocks, empty lines, verbatim,
+ ;; comments, tables, footnotes definitions, lists,
+ ;; inline tasks.
(or (and (looking-at "[ \t]*:END:")
(re-search-backward org-drawer-regexp nil t))
(and (looking-at "[ \t]*#\\+end_")
(re-search-backward "[ \t]*#\\+begin_"nil t))
(looking-at "[ \t]*[\n:#|]")
+ (looking-at org-footnote-definition-re)
(and (ignore-errors (goto-char (org-in-item-p)))
(goto-char
(org-list-get-top-point (org-list-struct))))
@@ -19164,6 +19190,11 @@ the functionality can be provided as a fall-back.")
;; and fixed-width regions are not wrapped. That function will pass
;; through to `fill-paragraph' when appropriate.
(org-set-local 'fill-paragraph-function 'org-fill-paragraph)
+ ;; Prevent auto-fill from inserting unwanted new items.
+ (org-set-local 'fill-nobreak-predicate
+ (if (memq 'org-fill-item-nobreak-p fill-nobreak-predicate)
+ fill-nobreak-predicate
+ (cons 'org-fill-item-nobreak-p fill-nobreak-predicate)))
;; Adaptive filling: To get full control, first make sure that
;; `adaptive-fill-regexp' never matches. Then install our own matcher.
(unless (local-variable-p 'adaptive-fill-regexp (current-buffer))
@@ -19179,6 +19210,10 @@ the functionality can be provided as a fall-back.")
(regexp . "^#\\+[A-Z_]+:\\(\\s-*\\)\\S-+")
(modes . '(org-mode))))))
+(defun org-fill-item-nobreak-p ()
+ "Non-nil when a line break at point would insert a new item."
+ (and (looking-at (org-item-re)) (org-list-in-valid-context-p)))
+
(defun org-fill-paragraph (&optional justify)
"Re-align a table, pass through to fill-paragraph if no table."
(let ((table-p (org-at-table-p))
@@ -19649,8 +19684,9 @@ empty."
(and (looking-at "[ \t]*$")
(save-excursion
(beginning-of-line 1)
- (looking-at (concat "^\\(\\*+\\)[ \t]+\\(" org-todo-regexp
- "\\)?[ \t]*$")))))
+ (let ((case-fold-search nil))
+ (looking-at (concat "^\\(\\*+\\)[ \t]+\\(" org-todo-regexp
+ "\\)?[ \t]*$"))))))
(defun org-at-heading-or-item-p ()
(or (org-on-heading-p) (org-at-item-p)))
@@ -19826,6 +19862,27 @@ If there is no such heading, return nil."
(unless (eobp) (backward-char 1)))
ad-do-it))
+(defun org-end-of-meta-data-and-drawers ()
+ "Jump to the first text after meta data and drawers in the current entry.
+This will move over empty lines, lines with planning time stamps,
+clocking lines, and drawers."
+ (org-back-to-heading t)
+ (let ((end (save-excursion (outline-next-heading) (point)))
+ (re (concat "[ \t]*$"
+ "\\|"
+ "\\(" org-drawer-regexp "\\)" ; group 1 are drawers
+ "\\|"
+ "\\([ \t]*\\(" org-keyword-time-regexp "\\)\\)")))
+ (forward-line 1)
+ (while (looking-at (concat "[ \t]*\\(" org-keyword-time-regexp "\\)"))
+ (if (not (match-end 1))
+ ;; empty or planning line
+ (forward-line 1)
+ ;; a drawer, find the end
+ (re-search-forward "^[ \t]*:END:" end 'move)
+ (forward-line 1)))
+ (point)))
+
(defun org-forward-same-level (arg &optional invisible-ok)
"Move forward to the arg'th subheading at same level as this one.
Stop at the first and last subheadings of a superior heading.