summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile2
-rw-r--r--README_maintainer7
-rw-r--r--contrib/README8
-rw-r--r--contrib/lisp/ob-eukleides.el2
-rw-r--r--contrib/lisp/ob-fomus.el2
-rw-r--r--contrib/lisp/ob-julia.el2
-rw-r--r--contrib/lisp/ob-mathomatic.el2
-rw-r--r--contrib/lisp/ob-oz.el4
-rw-r--r--contrib/lisp/ob-stata.el313
-rw-r--r--contrib/lisp/ob-tcl.el2
-rw-r--r--contrib/lisp/org-annotate-file.el116
-rw-r--r--contrib/lisp/org-bibtex-extras.el26
-rw-r--r--contrib/lisp/org-bookmark.el2
-rw-r--r--contrib/lisp/org-checklist.el2
-rw-r--r--contrib/lisp/org-choose.el2
-rw-r--r--contrib/lisp/org-collector.el10
-rw-r--r--contrib/lisp/org-colview-xemacs.el6
-rw-r--r--contrib/lisp/org-contacts.el126
-rw-r--r--contrib/lisp/org-contribdir.el2
-rw-r--r--contrib/lisp/org-depend.el2
-rw-r--r--contrib/lisp/org-download.el336
-rw-r--r--contrib/lisp/org-drill.el601
-rw-r--r--contrib/lisp/org-ebib.el47
-rw-r--r--contrib/lisp/org-effectiveness.el288
-rw-r--r--contrib/lisp/org-elisp-symbol.el2
-rw-r--r--contrib/lisp/org-eval-light.el2
-rw-r--r--contrib/lisp/org-eval.el2
-rw-r--r--contrib/lisp/org-expiry.el7
-rwxr-xr-xcontrib/lisp/org-favtable.el1701
-rw-r--r--contrib/lisp/org-git-link.el29
-rw-r--r--contrib/lisp/org-index.el2217
-rw-r--r--contrib/lisp/org-interactive-query.el2
-rw-r--r--contrib/lisp/org-invoice.el2
-rw-r--r--contrib/lisp/org-jira.el2
-rw-r--r--contrib/lisp/org-learn.el2
-rw-r--r--contrib/lisp/org-license.el540
-rw-r--r--contrib/lisp/org-mac-iCal.el2
-rw-r--r--contrib/lisp/org-mac-link.el606
-rw-r--r--contrib/lisp/org-mairix.el2
-rw-r--r--contrib/lisp/org-mew.el2
-rw-r--r--contrib/lisp/org-mime.el19
-rw-r--r--contrib/lisp/org-mtags.el255
-rw-r--r--contrib/lisp/org-notify.el2
-rw-r--r--contrib/lisp/org-notmuch.el36
-rw-r--r--contrib/lisp/org-passwords.el342
-rw-r--r--contrib/lisp/org-registry.el6
-rw-r--r--contrib/lisp/org-screen.el2
-rw-r--r--contrib/lisp/org-screenshot.el2
-rw-r--r--contrib/lisp/org-secretary.el2
-rw-r--r--contrib/lisp/org-sudoku.el2
-rw-r--r--contrib/lisp/org-toc.el4
-rw-r--r--contrib/lisp/org-track.el4
-rw-r--r--contrib/lisp/org-velocity.el2
-rw-r--r--contrib/lisp/org-vm.el2
-rw-r--r--contrib/lisp/org-wikinodes.el11
-rw-r--r--contrib/lisp/org-wl.el2
-rw-r--r--contrib/lisp/orgtbl-sqlinsert.el2
-rw-r--r--contrib/lisp/ox-bibtex.el358
-rw-r--r--contrib/lisp/ox-confluence.el32
-rw-r--r--contrib/lisp/ox-deck.el10
-rw-r--r--contrib/lisp/ox-extra.el190
-rw-r--r--contrib/lisp/ox-freemind.el4
-rw-r--r--contrib/lisp/ox-gfm.el193
-rw-r--r--contrib/lisp/ox-groff.el48
-rw-r--r--contrib/lisp/ox-koma-letter.el614
-rw-r--r--contrib/lisp/ox-rss.el66
-rw-r--r--contrib/lisp/ox-s5.el8
-rw-r--r--contrib/lisp/ox-taskjuggler.el58
-rw-r--r--doc/Makefile5
-rw-r--r--doc/doclicense.texi2
-rw-r--r--doc/htmlxref.cnf2
-rw-r--r--doc/org.texi2616
-rw-r--r--doc/orgcard.tex8
-rw-r--r--doc/orgguide.texi162
-rw-r--r--doc/texinfo.tex3161
-rw-r--r--etc/ORG-NEWS130
-rw-r--r--etc/styles/README2
-rw-r--r--lisp/ob-C.el386
-rw-r--r--lisp/ob-J.el179
-rw-r--r--lisp/ob-R.el153
-rw-r--r--lisp/ob-abc.el94
-rw-r--r--lisp/ob-asymptote.el2
-rw-r--r--lisp/ob-awk.el53
-rw-r--r--lisp/ob-calc.el45
-rw-r--r--lisp/ob-clojure.el107
-rw-r--r--lisp/ob-comint.el85
-rw-r--r--lisp/ob-coq.el77
-rw-r--r--lisp/ob-core.el748
-rw-r--r--lisp/ob-css.el2
-rw-r--r--lisp/ob-ditaa.el29
-rw-r--r--lisp/ob-dot.el6
-rw-r--r--lisp/ob-ebnf.el85
-rw-r--r--lisp/ob-emacs-lisp.el44
-rw-r--r--lisp/ob-eval.el9
-rw-r--r--lisp/ob-exp.el390
-rw-r--r--lisp/ob-forth.el86
-rw-r--r--lisp/ob-fortran.el32
-rw-r--r--lisp/ob-gnuplot.el38
-rw-r--r--lisp/ob-groovy.el126
-rw-r--r--lisp/ob-haskell.el16
-rw-r--r--lisp/ob-io.el13
-rw-r--r--lisp/ob-java.el49
-rw-r--r--lisp/ob-js.el9
-rw-r--r--lisp/ob-keys.el3
-rw-r--r--lisp/ob-latex.el23
-rw-r--r--lisp/ob-ledger.el2
-rw-r--r--lisp/ob-lilypond.el289
-rw-r--r--lisp/ob-lisp.el41
-rw-r--r--lisp/ob-lob.el33
-rw-r--r--lisp/ob-makefile.el5
-rw-r--r--lisp/ob-matlab.el2
-rw-r--r--lisp/ob-maxima.el42
-rw-r--r--lisp/ob-mscgen.el2
-rw-r--r--lisp/ob-ocaml.el61
-rw-r--r--lisp/ob-octave.el14
-rw-r--r--lisp/ob-org.el2
-rw-r--r--lisp/ob-perl.el32
-rw-r--r--lisp/ob-picolisp.el107
-rw-r--r--lisp/ob-plantuml.el6
-rw-r--r--lisp/ob-python.el151
-rw-r--r--lisp/ob-ref.el185
-rw-r--r--lisp/ob-ruby.el32
-rw-r--r--lisp/ob-sass.el2
-rw-r--r--lisp/ob-scala.el13
-rw-r--r--lisp/ob-scheme.el28
-rw-r--r--lisp/ob-screen.el6
-rw-r--r--lisp/ob-sh.el211
-rw-r--r--lisp/ob-shell.el264
-rw-r--r--lisp/ob-shen.el18
-rw-r--r--lisp/ob-sql.el29
-rw-r--r--lisp/ob-sqlite.el27
-rw-r--r--lisp/ob-table.el85
-rw-r--r--lisp/ob-tangle.el200
-rw-r--r--lisp/ob.el2
-rw-r--r--lisp/org-agenda.el1045
-rw-r--r--lisp/org-archive.el7
-rw-r--r--lisp/org-attach.el17
-rw-r--r--lisp/org-bbdb.el9
-rw-r--r--lisp/org-bibtex.el108
-rw-r--r--lisp/org-capture.el56
-rw-r--r--lisp/org-clock.el219
-rw-r--r--lisp/org-colview.el44
-rw-r--r--lisp/org-compat.el36
-rw-r--r--lisp/org-crypt.el12
-rw-r--r--lisp/org-ctags.el2
-rw-r--r--lisp/org-datetree.el2
-rw-r--r--lisp/org-docview.el25
-rw-r--r--lisp/org-element.el4380
-rw-r--r--lisp/org-entities.el16
-rw-r--r--lisp/org-eshell.el2
-rw-r--r--lisp/org-faces.el17
-rw-r--r--lisp/org-feed.el14
-rw-r--r--lisp/org-footnote.el84
-rw-r--r--lisp/org-gnus.el16
-rw-r--r--lisp/org-habit.el19
-rw-r--r--lisp/org-id.el6
-rw-r--r--lisp/org-indent.el2
-rw-r--r--lisp/org-info.el2
-rw-r--r--lisp/org-inlinetask.el9
-rw-r--r--lisp/org-irc.el6
-rw-r--r--lisp/org-list.el41
-rw-r--r--lisp/org-macro.el6
-rw-r--r--lisp/org-macs.el31
-rw-r--r--lisp/org-mhe.el2
-rw-r--r--lisp/org-mobile.el9
-rw-r--r--lisp/org-mouse.el17
-rw-r--r--lisp/org-pcomplete.el21
-rw-r--r--lisp/org-plot.el2
-rw-r--r--lisp/org-protocol.el4
-rw-r--r--lisp/org-rmail.el12
-rw-r--r--lisp/org-src.el119
-rw-r--r--lisp/org-table.el1368
-rw-r--r--lisp/org-timer.el45
-rw-r--r--lisp/org-w3m.el2
-rwxr-xr-x[-rw-r--r--]lisp/org.el5306
-rw-r--r--lisp/ox-ascii.el896
-rw-r--r--lisp/ox-beamer.el205
-rw-r--r--lisp/ox-html.el971
-rw-r--r--lisp/ox-icalendar.el362
-rw-r--r--lisp/ox-latex.el1155
-rw-r--r--lisp/ox-man.el113
-rw-r--r--lisp/ox-md.el278
-rw-r--r--lisp/ox-odt.el458
-rw-r--r--lisp/ox-org.el143
-rw-r--r--lisp/ox-publish.el105
-rw-r--r--lisp/ox-texinfo.el1528
-rw-r--r--lisp/ox.el966
-rw-r--r--mk/default.mk51
-rw-r--r--mk/eldo.el4
-rw-r--r--mk/org-fixup.el16
-rw-r--r--mk/server.mk2
-rw-r--r--mk/targets.mk15
-rw-r--r--request-assign-future.txt2
-rw-r--r--testing/README26
-rw-r--r--testing/examples/babel.org64
-rw-r--r--testing/examples/include.html1
-rw-r--r--testing/examples/ob-C-test.org88
-rw-r--r--testing/examples/ob-awk-test.org7
-rw-r--r--testing/examples/ob-shell-test.org88
-rw-r--r--testing/examples/open-at-point.org8
-rw-r--r--testing/lisp/test-ob-C.el161
-rw-r--r--testing/lisp/test-ob-R.el2
-rw-r--r--testing/lisp/test-ob-awk.el11
-rw-r--r--testing/lisp/test-ob-emacs-lisp.el2
-rw-r--r--testing/lisp/test-ob-exp.el226
-rw-r--r--testing/lisp/test-ob-fortran.el2
-rw-r--r--testing/lisp/test-ob-header-arg-defaults.el2
-rw-r--r--testing/lisp/test-ob-lilypond.el367
-rw-r--r--testing/lisp/test-ob-lob.el52
-rw-r--r--testing/lisp/test-ob-maxima.el2
-rw-r--r--testing/lisp/test-ob-octave.el2
-rw-r--r--testing/lisp/test-ob-perl.el2
-rw-r--r--testing/lisp/test-ob-python.el2
-rw-r--r--testing/lisp/test-ob-ruby.el49
-rw-r--r--testing/lisp/test-ob-sh.el52
-rw-r--r--testing/lisp/test-ob-shell.el92
-rw-r--r--testing/lisp/test-ob-table.el2
-rw-r--r--testing/lisp/test-ob-tangle.el2
-rw-r--r--testing/lisp/test-ob.el157
-rw-r--r--testing/lisp/test-org-clock.el2
-rw-r--r--testing/lisp/test-org-element.el1485
-rw-r--r--testing/lisp/test-org-footnote.el2
-rw-r--r--testing/lisp/test-org-list.el6
-rw-r--r--testing/lisp/test-org-macro.el2
-rw-r--r--testing/lisp/test-org-open-at-point.el61
-rw-r--r--testing/lisp/test-org-src.el2
-rw-r--r--testing/lisp/test-org-table.el588
-rw-r--r--testing/lisp/test-org.el823
-rw-r--r--testing/lisp/test-ox.el538
-rw-r--r--testing/lisp/test-property-inheritance.el2
-rw-r--r--testing/org-batch-test-init.el20
-rw-r--r--testing/org-test.el40
233 files changed, 28724 insertions, 16901 deletions
diff --git a/.gitignore b/.gitignore
index a9d73ad..70980ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@ ORGWEBPAGE/Changes.txt
local*.mk
.gitattributes
mk/x11idle
+ChangeLog
# texi2pdf --tidy
diff --git a/Makefile b/Makefile
index f95bcb2..f6312f2 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,6 @@ help helpall::
$(info )
$(info Getting Help)
$(info ============)
- $(info )
$(info make help - show brief help)
$(info make targets - ditto)
$(info make helpall - show extended help)
@@ -30,6 +29,7 @@ help helpall::
$(info make single - build Org ELisp files, single Emacs per source)
$(info make autoloads - create org-loaddefs.el to load Org in-place)
$(info make test - build Org ELisp files and run test suite)
+ $(info make vanilla - run Emacs with this Org-mode and no personal config)
helpall::
$(info make test-dirty - check without building first)
$(info make compile-dirty - build only stale Org ELisp files)
diff --git a/README_maintainer b/README_maintainer
index fed9867..6b162aa 100644
--- a/README_maintainer
+++ b/README_maintainer
@@ -2,6 +2,7 @@
#+TITLE: Org maintainer tasks
#+STARTUP: noindent
+#+OPTIONS: ^:nil
This document describes the tasks the Org-mode maintainer has to do
and how they are performed.
@@ -136,10 +137,8 @@ So the way I have been doing things with Emacs is this:
version in Emacs starts diverging from my own.
Careful: Copy /org.texi/ and /orgcard.tex/ into the right places,
- and also copy the lisp files with *two exceptions*: Do *not* copy
- /org-colview-xemacs.el/ and /org-loaddefs.el/. The former does not
- belong in Emacs. And the latter would actually be harmful because
- Emacs generates its own autoloads.
+ and also copy the lisp files with *one exception*: Do *not* copy
+ /org-loaddefs.el/, Emacs generates its own autoloads.
4. Generate the ChangeLog entries
diff --git a/contrib/README b/contrib/README
index bdbdb47..e92da14 100644
--- a/contrib/README
+++ b/contrib/README
@@ -24,21 +24,22 @@ org-contacts.el --- Contacts management
org-contribdir.el --- Dummy file to mark the org contrib Lisp directory
org-depend.el --- TODO dependencies for Org-mode
org-drill.el --- Self-testing with org-learn
+org-effectiveness.el --- Measuring your personal effectiveness
org-element.el --- Parser and applications for Org syntax
org-elisp-symbol.el --- Org links to emacs-lisp symbols
org-eval-light.el --- Evaluate in-buffer code on demand
org-eval.el --- The <lisp> tag, adapted from Muse
org-expiry.el --- Expiry mechanism for Org entries
org-export-generic.el --- Export framework for configurable backends
-org-favtable.el --- Lookup table of favorite references and links
org-git-link.el --- Provide org links to specific file version
+org-index.el --- A personal index for org and beyond
org-interactive-query.el --- Interactive modification of tags query
org-invoice.el --- Help manage client invoices in OrgMode
org-jira.el --- Add a jira:ticket protocol to Org
org-learn.el --- SuperMemo's incremental learning algorithm
+org-license.el --- Insert free licenses to your org documents
org-mac-iCal.el --- Imports events from iCal.app to the Emacs diary
-org-mac-link-grabber.el --- Grab links and URLs from various Mac applications
-org-mac-message.el --- Links to Apple Mail.app messages from within Org-mode
+org-mac-link.el --- Grab links and URLs from various Mac applications
org-mairix.el --- Hook mairix search into Org for different MUAs
org-man.el --- Support for links to manpages in Org-mode
org-mew.el --- Support for links to Mew messages
@@ -79,6 +80,7 @@ ob-fomus.el --- Org-babel functions for fomus evaluation
ob-julia.el --- Org-babel functions for julia evaluation
ob-mathomatic.el --- Org-babel functions for mathomatic evaluation
ob-oz.el --- Org-babel functions for Oz evaluation
+ob-stata.el --- Org-babel functions for Stata evaluation
ob-tcl.el --- Org-babel functions for tcl evaluation
External libraries
diff --git a/contrib/lisp/ob-eukleides.el b/contrib/lisp/ob-eukleides.el
index e25ed1c..c8ce881 100644
--- a/contrib/lisp/ob-eukleides.el
+++ b/contrib/lisp/ob-eukleides.el
@@ -1,6 +1,6 @@
;;; ob-eukleides.el --- Org-babel functions for eukleides evaluation
-;; Copyright (C) 2010-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2014 Free Software Foundation, Inc.
;; Author: Luis Anaya
;; Keywords: literate programming, reproducible research
diff --git a/contrib/lisp/ob-fomus.el b/contrib/lisp/ob-fomus.el
index 58183fb..1db32e4 100644
--- a/contrib/lisp/ob-fomus.el
+++ b/contrib/lisp/ob-fomus.el
@@ -1,6 +1,6 @@
;;; ob-fomus.el --- Org-babel functions for fomus evaluation
-;; Copyright (C) 2011-2013 Torsten Anders
+;; Copyright (C) 2011-2014 Torsten Anders
;; Author: Torsten Anders
;; Keywords: literate programming, reproducible research
diff --git a/contrib/lisp/ob-julia.el b/contrib/lisp/ob-julia.el
index 3aed818..4d8deb2 100644
--- a/contrib/lisp/ob-julia.el
+++ b/contrib/lisp/ob-julia.el
@@ -1,6 +1,6 @@
;;; ob-julia.el --- org-babel functions for julia code evaluation
-;; Copyright (C) 2013 G. Jay Kerns
+;; Copyright (C) 2013, 2014 G. Jay Kerns
;; Author: G. Jay Kerns, based on ob-R.el by Eric Schulte and Dan Davison
;; This file is not part of GNU Emacs.
diff --git a/contrib/lisp/ob-mathomatic.el b/contrib/lisp/ob-mathomatic.el
index 585604e..bfd8ecf 100644
--- a/contrib/lisp/ob-mathomatic.el
+++ b/contrib/lisp/ob-mathomatic.el
@@ -1,6 +1,6 @@
;;; ob-mathomatic.el --- Org-babel functions for mathomatic evaluation
-;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2014 Free Software Foundation, Inc.
;; Author: Eric S Fraga
;; Eric Schulte
diff --git a/contrib/lisp/ob-oz.el b/contrib/lisp/ob-oz.el
index ce8e8a6..3531d95 100644
--- a/contrib/lisp/ob-oz.el
+++ b/contrib/lisp/ob-oz.el
@@ -1,6 +1,6 @@
;;; ob-oz.el --- Org-babel functions for Oz evaluation
-;; Copyright (C) 2009-2013 Torsten Anders and Eric Schulte
+;; Copyright (C) 2009-2014 Torsten Anders and Eric Schulte
;; Author: Torsten Anders and Eric Schulte
;; Keywords: literate programming, reproducible research
@@ -90,7 +90,7 @@
(require 'ob)
;;; major mode for editing Oz programs
-(require 'mozart)
+(require 'mozart nil t)
;;
;; Interface to communicate with Oz.
diff --git a/contrib/lisp/ob-stata.el b/contrib/lisp/ob-stata.el
new file mode 100644
index 0000000..29aa88d
--- a/dev/null
+++ b/contrib/lisp/ob-stata.el
@@ -0,0 +1,313 @@
+;;; ob-stata.el --- org-babel functions for stata code evaluation
+
+;; Copyright (C) 2014 Ista Zahn
+;; Author: Ista Zahn istazahn@gmail.com
+;; G. Jay Kerns
+;; Eric Schulte
+;; Dan Davison
+
+
+;; This file is not part of GNU Emacs.
+
+;; This program 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,
+;; 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.
+
+;;; Commentary:
+
+;; The file provides Org-Babel support for evaluating stata code.
+;; It is basically result of find-and-replace "stata" for "julia"
+;; in ob-julia.el by G. Jay Kerns. Only ":results output" works: the
+;; header args must include ":results output" (this is the default).
+;; Note that I'm not sure ':results value' makes sense or is useful
+;; but I have left all the value-processing stuff inherited from
+;; ob-julia and ob-R. ':results graphics' would be nice, but I have
+;; not tried to implement it.
+;; --Ista, 07/30/2014
+
+;;; Requirements:
+;; Stata: http://stata.com
+;; ESS: http://ess.r-project.org
+
+;;; Code:
+(require 'ob)
+(eval-when-compile (require 'cl))
+
+(declare-function orgtbl-to-csv "org-table" (table params))
+(declare-function stata "ext:ess-stata" (&optional start-args))
+(declare-function inferior-ess-send-input "ext:ess-inf" ())
+(declare-function ess-make-buffer-current "ext:ess-inf" ())
+(declare-function ess-eval-buffer "ext:ess-inf" (vis))
+(declare-function org-number-sequence "org-compat" (from &optional to inc))
+(declare-function org-remove-if-not "org" (predicate seq))
+
+(defconst org-babel-header-args:stata
+ '((width . :any)
+ (horizontal . :any)
+ (results . ((file list vector table scalar verbatim)
+ (raw org html latex code pp wrap)
+ (replace silent append prepend)
+ ;; NOTE: not sure 'value' makes sense in stata
+ ;; we may want to remove it from the list
+ (output value graphics))))
+ "stata-specific header arguments.")
+
+(add-to-list 'org-babel-tangle-lang-exts '("stata" . "do"))
+
+;; only ':results output' currently works, so make that the default
+(defvar org-babel-default-header-args:stata '((:results . "output")))
+
+(defcustom org-babel-stata-command inferior-STA-program-name
+ "Name of command to use for executing stata code."
+ :group 'org-babel
+ :version "24.4"
+ :package-version '(Org . "8.3")
+ :type 'string)
+
+(defvar ess-local-process-name) ; dynamically scoped
+(defun org-babel-edit-prep:stata (info)
+ (let ((session (cdr (assoc :session (nth 2 info)))))
+ (when (and session (string-match "^\\*\\(.+?\\)\\*$" session))
+ (save-match-data (org-babel-stata-initiate-session session nil)))))
+
+(defun org-babel-expand-body:stata (body params &optional graphics-file)
+ "Expand BODY according to PARAMS, return the expanded body."
+ (let ((graphics-file
+ (or graphics-file (org-babel-stata-graphical-output-file params))))
+ (mapconcat
+ #'identity
+ ((lambda (inside)
+ (if graphics-file
+ inside
+ inside))
+ (append (org-babel-variable-assignments:stata params)
+ (list body))) "\n")))
+
+(defun org-babel-execute:stata (body params)
+ "Execute a block of stata code.
+This function is called by `org-babel-execute-src-block'."
+ (save-excursion
+ (let* ((result-params (cdr (assoc :result-params params)))
+ (result-type (cdr (assoc :result-type params)))
+ (session (org-babel-stata-initiate-session
+ (cdr (assoc :session params)) params))
+ (colnames-p (cdr (assoc :colnames params)))
+ (rownames-p (cdr (assoc :rownames params)))
+ (graphics-file (org-babel-stata-graphical-output-file params))
+ (full-body (org-babel-expand-body:stata body params graphics-file))
+ (result
+ (org-babel-stata-evaluate
+ session full-body result-type result-params
+ (or (equal "yes" colnames-p)
+ (org-babel-pick-name
+ (cdr (assoc :colname-names params)) colnames-p))
+ (or (equal "yes" rownames-p)
+ (org-babel-pick-name
+ (cdr (assoc :rowname-names params)) rownames-p)))))
+ (if graphics-file nil result))))
+
+(defun org-babel-prep-session:stata (session params)
+ "Prepare SESSION according to the header arguments specified in PARAMS."
+ (let* ((session (org-babel-stata-initiate-session session params))
+ (var-lines (org-babel-variable-assignments:stata params)))
+ (org-babel-comint-in-buffer session
+ (mapc (lambda (var)
+ (end-of-line 1) (insert var) (comint-send-input nil t)
+ (org-babel-comint-wait-for-output session)) var-lines))
+ session))
+
+(defun org-babel-load-session:stata (session body params)
+ "Load BODY into SESSION."
+ (save-window-excursion
+ (let ((buffer (org-babel-prep-session:stata session params)))
+ (with-current-buffer buffer
+ (goto-char (process-mark (get-buffer-process (current-buffer))))
+ (insert (org-babel-chomp body)))
+ buffer)))
+
+;; helper functions
+
+(defun org-babel-variable-assignments:stata (params)
+ "Return list of stata statements assigning the block's variables."
+ (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+ (mapcar
+ (lambda (pair)
+ (org-babel-stata-assign-elisp
+ (car pair) (cdr pair)
+ (equal "yes" (cdr (assoc :colnames params)))
+ (equal "yes" (cdr (assoc :rownames params)))))
+ (mapcar
+ (lambda (i)
+ (cons (car (nth i vars))
+ (org-babel-reassemble-table
+ (cdr (nth i vars))
+ (cdr (nth i (cdr (assoc :colname-names params))))
+ (cdr (nth i (cdr (assoc :rowname-names params)))))))
+ (org-number-sequence 0 (1- (length vars)))))))
+
+(defun org-babel-stata-quote-csv-field (s)
+ "Quote field S for export to stata."
+ (if (stringp s)
+ (concat "\"" (mapconcat 'identity (split-string s "\"") "\"\"") "\"")
+ (format "%S" s)))
+
+(defun org-babel-stata-assign-elisp (name value colnames-p rownames-p)
+ "Construct stata code assigning the elisp VALUE to a variable named NAME."
+ (if (listp value)
+ (let ((max (apply #'max (mapcar #'length (org-remove-if-not
+ #'sequencep value))))
+ (min (apply #'min (mapcar #'length (org-remove-if-not
+ #'sequencep value))))
+ (transition-file (org-babel-temp-file "stata-import-")))
+ ;; ensure VALUE has an orgtbl structure (depth of at least 2)
+ (unless (listp (car value)) (setq value (list value)))
+ (with-temp-file transition-file
+ (insert
+ (orgtbl-to-csv value '(:fmt org-babel-stata-quote-csv-field))
+ "\n"))
+ (let ((file (org-babel-process-file-name transition-file 'noquote))
+ (header (if (or (eq (nth 1 value) 'hline) colnames-p)
+ "TRUE" "FALSE"))
+ (row-names (if rownames-p "1" "NULL")))
+ (if (= max min)
+ (format "%s = insheet using \"%s\"" name file)
+ (format "%s = insheet using \"%s\""
+ name file))))
+ (format "%s = %s" name (org-babel-stata-quote-csv-field value))))
+
+(defvar ess-ask-for-ess-directory) ; dynamically scoped
+
+(defun org-babel-stata-initiate-session (session params)
+ "If there is not a current stata process then create one."
+ (unless (string= session "none")
+ (let ((session (or session "*stata*"))
+ (ess-ask-for-ess-directory
+ (and (and (boundp 'ess-ask-for-ess-directory) ess-ask-for-ess-directory)
+ (not (cdr (assoc :dir params))))))
+ (if (org-babel-comint-buffer-livep session)
+ session
+ (save-window-excursion
+ (require 'ess) (stata)
+ (rename-buffer
+ (if (bufferp session)
+ (buffer-name session)
+ (if (stringp session)
+ session
+ (buffer-name))))
+ (current-buffer))))))
+
+(defun org-babel-stata-associate-session (session)
+ "Associate stata code buffer with a stata session.
+Make SESSION be the inferior ESS process associated with the
+current code buffer."
+ (setq ess-local-process-name
+ (process-name (get-buffer-process session)))
+ (ess-make-buffer-current))
+
+(defun org-babel-stata-graphical-output-file (params)
+ "Name of file to which stata should send graphical output."
+ (and (member "graphics" (cdr (assq :result-params params)))
+ (cdr (assq :file params))))
+
+(defvar org-babel-stata-eoe-indicator "display \"org_babel_stata_eoe\"")
+(defvar org-babel-stata-eoe-output "org_babel_stata_eoe")
+
+(defvar org-babel-stata-write-object-command "outsheet using \"%s\"")
+
+(defun org-babel-stata-evaluate
+ (session body result-type result-params column-names-p row-names-p)
+ "Evaluate stata code in BODY."
+ (if session
+ (org-babel-stata-evaluate-session
+ session body result-type result-params column-names-p row-names-p)
+ (org-babel-stata-evaluate-external-process
+ body result-type result-params column-names-p row-names-p)))
+
+(defun org-babel-stata-evaluate-external-process
+ (body result-type result-params column-names-p row-names-p)
+ "Evaluate BODY in external stata process.
+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
+ (value
+ (let ((tmp-file (org-babel-temp-file "stata-")))
+ (org-babel-eval org-babel-stata-command
+ (format org-babel-stata-write-object-command
+ (org-babel-process-file-name tmp-file 'noquote)
+ (format "begin\n%s\nend" body)))
+ (org-babel-stata-process-value-result
+ (org-babel-result-cond result-params
+ (with-temp-buffer
+ (insert-file-contents tmp-file)
+ (buffer-string))
+ (org-babel-import-elisp-from-file tmp-file '(4)))
+ column-names-p)))
+ (output (org-babel-eval org-babel-stata-command body))))
+
+(defun org-babel-stata-evaluate-session
+ (session body result-type result-params column-names-p row-names-p)
+ "Evaluate BODY in SESSION.
+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
+ (value
+ (with-temp-buffer
+ (insert (org-babel-chomp body))
+ (let ((ess-local-process-name
+ (process-name (get-buffer-process session)))
+ (ess-eval-visibly-p nil))
+ (ess-eval-buffer nil)))
+ (let ((tmp-file (org-babel-temp-file "stata-")))
+ (org-babel-comint-eval-invisibly-and-wait-for-file
+ session tmp-file
+ (format org-babel-stata-write-object-command
+ (org-babel-process-file-name tmp-file 'noquote) "ans"))
+ (org-babel-stata-process-value-result
+ (org-babel-result-cond result-params
+ (with-temp-buffer
+ (insert-file-contents tmp-file)
+ (buffer-string))
+ (org-babel-import-elisp-from-file tmp-file '(4)))
+ column-names-p)))
+ (output
+ (mapconcat
+ #'org-babel-chomp
+ (butlast
+ (delq nil
+ (mapcar
+ (lambda (line) (when (> (length line) 0) line))
+ (mapcar
+ (lambda (line) ;; cleanup extra prompts left in output
+ (if (string-match
+ "^\\([ ]*[>+\\.][ ]?\\)+\\([[0-9]+\\|[ ]\\)" line)
+ (substring line (match-end 1))
+ line))
+ (org-babel-comint-with-output (session org-babel-stata-eoe-output)
+ (insert (mapconcat #'org-babel-chomp
+ (list body org-babel-stata-eoe-indicator)
+ "\n"))
+ (inferior-ess-send-input)))))) "\n"))))
+
+(defun org-babel-stata-process-value-result (result column-names-p)
+ "stata-specific processing of return value.
+Insert hline if column names in output have been requested."
+ (if column-names-p
+ (cons (car result) (cons 'hline (cdr result)))
+ result))
+
+(provide 'ob-stata)
+
+;;; ob-stata.el ends here
diff --git a/contrib/lisp/ob-tcl.el b/contrib/lisp/ob-tcl.el
index e8d735b..50afe5a 100644
--- a/contrib/lisp/ob-tcl.el
+++ b/contrib/lisp/ob-tcl.el
@@ -1,6 +1,6 @@
;;; ob-tcl.el --- Org-babel functions for tcl evaluation
-;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2014 Free Software Foundation, Inc.
;; Authors: Dan Davison
;; Eric Schulte
diff --git a/contrib/lisp/org-annotate-file.el b/contrib/lisp/org-annotate-file.el
index bdb9acb..b8e8bd9 100644
--- a/contrib/lisp/org-annotate-file.el
+++ b/contrib/lisp/org-annotate-file.el
@@ -1,6 +1,6 @@
;;; org-annotate-file.el --- Annotate a file with org syntax
-;; Copyright (C) 2008-2013 Philip Jackson
+;; Copyright (C) 2008-2014 Philip Jackson
;; Author: Philip Jackson <phil@shellarchive.co.uk>
;; Version: 0.2
@@ -25,7 +25,7 @@
;;; Commentary:
;; This is yet another implementation to allow the annotation of a
-;; file without modification of the file itself. The annotation is in
+;; file without modification of the file itself. The annotation is in
;; org syntax so you can use all of the org features you are used to.
;; To use you might put the following in your .emacs:
@@ -47,30 +47,41 @@
;; and next time you hit C-c C-l you will hit those notes again.
;;
;; To put a subheading with a text search for the current line set
-;; `org-annotate-file-add-search` to non-nil value. Then when you hit
+;; `org-annotate-file-add-search` to non-nil value. Then when you hit
;; C-c C-l (on the above line for example) you will get:
;; * ~/org-annotate-file.el
-;; ** `org-annotate-file-add-search` to non-nil value. Then whe...
+;; ** `org-annotate-file-add-search` to non-nil value. Then whe...
;; Note that both of the above will be links.
-(require 'org)
-
-(defvar org-annotate-file-storage-file "~/.org-annotate-file.org"
- "File in which to keep annotations.")
+;;; Code:
-(defvar org-annotate-file-add-search nil
- "If non-nil then add a link as a second level to the actual
-location in the file")
-
-(defvar org-annotate-file-always-open t
- "non-nil means always expand the full tree when you visit
-`org-annotate-file-storage-file'.")
+(require 'org)
-(defun org-annotate-file-elipsify-desc (string &optional after)
- "Strip starting and ending whitespace and replace any chars
-that appear after the value in `after' with '...'"
+(defgroup org-annotate-file nil
+ "Org Annotate"
+ :group 'org)
+
+(defcustom org-annotate-file-storage-file "~/.org-annotate-file.org"
+ "File in which to keep annotations."
+ :group 'org-annotate-file
+ :type 'file)
+
+(defcustom org-annotate-file-add-search nil
+ "If non-nil, add a link as a second level to the actual file location."
+ :group 'org-annotate-file
+ :type 'boolean)
+
+(defcustom org-annotate-file-always-open t
+ "If non-nil, always expand the full tree when visiting the annotation file."
+ :group 'org-annotate-file
+ :type 'boolean)
+
+(defun org-annotate-file-ellipsify-desc (string &optional after)
+ "Return shortened STRING with appended ellipsis.
+Trim whitespace at beginning and end of STRING and replace any
+ characters that appear after the occurrence of AFTER with '...'"
(let* ((after (number-to-string (or after 30)))
(replace-map (list (cons "^[ \t]*" "")
(cons "[ \t]*$" "")
@@ -82,46 +93,61 @@ that appear after the value in `after' with '...'"
replace-map)
string))
+;;;###autoload
(defun org-annotate-file ()
- "Put a section for the current file into your annotation file"
+ "Visit `org-annotate-file-storage-file` and add a new annotation section.
+The annotation is opened at the new section which will be referencing
+the point in the current file."
(interactive)
(unless (buffer-file-name)
- (error "This buffer has no associated file"))
- (org-annotate-file-show-section))
-
-(defun org-annotate-file-show-section (&optional buffer)
- "Visit the buffer named `org-annotate-file-storage-file' and
-show the relevant section"
- (let* ((filename (abbreviate-file-name (or buffer (buffer-file-name))))
- (line (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
- (link (org-make-link-string (concat "file:" filename) filename))
+ (error "This buffer has no associated file!"))
+ (switch-to-buffer
+ (org-annotate-file-show-section org-annotate-file-storage-file)))
+
+;;;###autoload
+(defun org-annotate-file-show-section (storage-file &optional annotated-buffer)
+ "Add or show annotation entry in STORAGE-FILE and return the buffer.
+The annotation will link to ANNOTATED-BUFFER if specified,
+ otherwise the current buffer is used."
+ (let ((filename (abbreviate-file-name (or annotated-buffer
+ (buffer-file-name))))
+ (line (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
+ (annotation-buffer (find-file-noselect storage-file)))
+ (with-current-buffer annotation-buffer
+ (org-annotate-file-annotate filename line))
+ annotation-buffer))
+
+(defun org-annotate-file-annotate (filename line)
+ "Add annotation for FILENAME at LINE using current buffer."
+ (let* ((link (org-make-link-string (concat "file:" filename) filename))
(search-link (org-make-link-string
(concat "file:" filename "::" line)
- (org-annotate-file-elipsify-desc line))))
- (with-current-buffer (find-file org-annotate-file-storage-file)
- (unless (eq major-mode 'org-mode)
- (org-mode))
- (goto-char (point-min))
- (widen)
- (when org-annotate-file-always-open
- (show-all))
+ (org-annotate-file-ellipsify-desc line))))
+ (unless (eq major-mode 'org-mode)
+ (org-mode))
+ (goto-char (point-min))
+ (widen)
+ (when org-annotate-file-always-open
+ (show-all))
+ (unless (search-forward-regexp
+ (concat "^* " (regexp-quote link)) nil t)
+ (org-annotate-file-add-upper-level link))
+ (beginning-of-line)
+ (org-narrow-to-subtree)
+ ;; deal with a '::' search if need be
+ (when org-annotate-file-add-search
(unless (search-forward-regexp
- (concat "^* " (regexp-quote link)) nil t)
- (org-annotate-file-add-upper-level link))
- (beginning-of-line)
- (org-narrow-to-subtree)
- ;; deal with a '::' search if need be
- (when org-annotate-file-add-search
- (unless (search-forward-regexp
- (concat "^** " (regexp-quote search-link)) nil t)
- (org-annotate-file-add-second-level search-link))))))
+ (concat "^** " (regexp-quote search-link)) nil t)
+ (org-annotate-file-add-second-level search-link)))))
(defun org-annotate-file-add-upper-level (link)
+ "Add and link heading to LINK."
(goto-char (point-min))
(call-interactively 'org-insert-heading)
(insert link))
(defun org-annotate-file-add-second-level (link)
+ "Add and link subheading to LINK."
(goto-char (point-at-eol))
(call-interactively 'org-insert-subheading)
(insert link))
diff --git a/contrib/lisp/org-bibtex-extras.el b/contrib/lisp/org-bibtex-extras.el
index 93c97a9..5f05039 100644
--- a/contrib/lisp/org-bibtex-extras.el
+++ b/contrib/lisp/org-bibtex-extras.el
@@ -1,6 +1,6 @@
;;; org-bibtex-extras --- extras for working with org-bibtex entries
-;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;; Author: Eric Schulte <eric dot schulte at gmx dot com>
;; Keywords: outlines, hypermedia, bibtex, d3
@@ -75,25 +75,14 @@ For example, to point to your `obe-bibtex-file' use the following.
"Return all citations from `obe-bibtex-file'."
(or obe-citations
(save-window-excursion
- (find-file obe-bibtex-file)
+ (find-file (or obe-bibtex-file
+ (error "`obe-bibtex-file' has not been configured")))
(goto-char (point-min))
(while (re-search-forward " :CUSTOM_ID: \\(.+\\)$" nil t)
(push (org-no-properties (match-string 1))
obe-citations))
obe-citations)))
-(defun obe-goto-citation (&optional citation)
- "Visit a citation given its ID."
- (interactive)
- (let ((citation (or citation
- (org-icompleting-read "Citation: "
- (obe-citations)))))
- (find-file obe-bibtex-file)
- (goto-char (point-min))
- (when (re-search-forward (format " :CUSTOM_ID: %s" citation) nil t)
- (outline-previous-visible-heading 1)
- t)))
-
(defun obe-html-export-citations ()
"Convert all \\cite{...} citations in the current file into HTML links."
(save-excursion
@@ -105,15 +94,6 @@ For example, to point to your `obe-bibtex-file' use the following.
(mapcar #'org-babel-trim
(split-string (match-string 1) ",")) ", "))))))
-(defun obe-get-meta-data (citation)
- "Collect meta-data for CITATION."
- (save-excursion
- (when (obe-goto-citation citation)
- (let ((pt (point)))
- `((:authors . ,(split-string (org-entry-get pt "AUTHOR") " and " t))
- (:title . ,(org-no-properties (org-get-heading 1 1)))
- (:journal . ,(org-entry-get pt "JOURNAL")))))))
-
(defun obe-meta-to-json (meta &optional fields)
"Turn a list of META data from citations into a string of json."
(let ((counter 1) nodes links)
diff --git a/contrib/lisp/org-bookmark.el b/contrib/lisp/org-bookmark.el
index 44588b6..9a69bbb 100644
--- a/contrib/lisp/org-bookmark.el
+++ b/contrib/lisp/org-bookmark.el
@@ -1,5 +1,5 @@
;;; org-bookmark.el - Support for links to bookmark
-;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;;
;; Author: Tokuya Kameshima <kames AT fa2.so-net.ne.jp>
;; Version: 1.0
diff --git a/contrib/lisp/org-checklist.el b/contrib/lisp/org-checklist.el
index faa5998..2bc00c0 100644
--- a/contrib/lisp/org-checklist.el
+++ b/contrib/lisp/org-checklist.el
@@ -1,6 +1,6 @@
;;; org-checklist.el --- org functions for checklist handling
-;; Copyright (C) 2008-2013 James TD Smith
+;; Copyright (C) 2008-2014 James TD Smith
;; Author: James TD Smith (@ ahktenzero (. mohorovi cc))
;; Version: 1.0
diff --git a/contrib/lisp/org-choose.el b/contrib/lisp/org-choose.el
index 8e5935d..c1006d0 100644
--- a/contrib/lisp/org-choose.el
+++ b/contrib/lisp/org-choose.el
@@ -1,6 +1,6 @@
;;; org-choose.el --- decision management for org-mode
-;; Copyright (C) 2009-2013 Tom Breton (Tehom)
+;; Copyright (C) 2009-2014 Tom Breton (Tehom)
;; This file is not part of GNU Emacs.
diff --git a/contrib/lisp/org-collector.el b/contrib/lisp/org-collector.el
index 60b9069..5894707 100644
--- a/contrib/lisp/org-collector.el
+++ b/contrib/lisp/org-collector.el
@@ -1,6 +1,6 @@
;;; org-collector --- collect properties into tables
-;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;; Author: Eric Schulte <schulte dot eric at gmail dot com>
;; Keywords: outlines, hypermedia, calendar, wp, experimentation,
@@ -121,6 +121,7 @@ preceeding the dblock, then update the contents of the dblock."
(scope (plist-get params :scope))
(noquote (plist-get params :noquote))
(colnames (plist-get params :colnames))
+ (defaultval (plist-get params :defaultval))
(content-lines (org-split-string (plist-get params :content) "\n"))
id table line pos)
(save-excursion
@@ -133,9 +134,10 @@ preceeding the dblock, then update the contents of the dblock."
(t (error "Cannot find entry with :ID: %s" id))))
(unless (eq id 'global) (org-narrow-to-subtree))
(setq stringformat (if noquote "%s" "%S"))
- (setq table (org-propview-to-table
- (org-propview-collect cols stringformat conds match scope inherit
- (if colnames colnames cols)) stringformat))
+ (let ((org-propview-default-value (if defaultval defaultval org-propview-default-value)))
+ (setq table (org-propview-to-table
+ (org-propview-collect cols stringformat conds match scope inherit
+ (if colnames colnames cols)) stringformat)))
(widen))
(setq pos (point))
(when content-lines
diff --git a/contrib/lisp/org-colview-xemacs.el b/contrib/lisp/org-colview-xemacs.el
index 63c0238..67a2aad 100644
--- a/contrib/lisp/org-colview-xemacs.el
+++ b/contrib/lisp/org-colview-xemacs.el
@@ -1,6 +1,6 @@
;;; org-colview-xemacs.el --- Column View in Org-mode, XEmacs-specific version
-;; Copyright (C) 2004-2013
+;; Copyright (C) 2004-2014
;; Carsten Dominik
;; Author: Carsten Dominik <carsten at orgmode dot org>
@@ -477,6 +477,7 @@ This is the compiled version of the format.")
(defvar org-colview-initial-truncate-line-value nil
"Remember the value of `truncate-lines' across colview.")
+;;;###autoload
(defun org-columns-remove-overlays ()
"Remove all currently active column overlays."
(interactive)
@@ -820,6 +821,7 @@ around it."
(let ((value (get-char-property (point) 'org-columns-value)))
(org-open-link-from-string value arg)))
+;;;###autoload
(defun org-columns-get-format-and-top-level ()
(let (fmt)
(when (condition-case nil (org-back-to-heading) (error nil))
@@ -1091,6 +1093,7 @@ Don't set this, this is meant for dynamic scoping.")
(org-overlay-display ov (format fmt val))))))
org-columns-overlays))))
+;;;###autoload
(defun org-columns-compute (property)
"Sum the values of property PROPERTY hierarchically, for the entire buffer."
(interactive)
@@ -1187,6 +1190,7 @@ Don't set this, this is meant for dynamic scoping.")
(setq sum (+ (string-to-number (pop l)) (/ sum 60))))
sum)))
+;;;###autoload
(defun org-columns-number-to-string (n fmt &optional printf)
"Convert a computed column number to a string value, according to FMT."
(cond
diff --git a/contrib/lisp/org-contacts.el b/contrib/lisp/org-contacts.el
index 97171d0..88aef9d 100644
--- a/contrib/lisp/org-contacts.el
+++ b/contrib/lisp/org-contacts.el
@@ -1,6 +1,6 @@
;;; org-contacts.el --- Contacts management
-;; Copyright (C) 2010-2013 Julien Danjou <julien@danjou.info>
+;; Copyright (C) 2010-2014 Julien Danjou <julien@danjou.info>
;; Author: Julien Danjou <julien@danjou.info>
;; Keywords: outlines, hypermedia, calendar
@@ -155,6 +155,11 @@ The following replacements are available:
:type 'string
:group 'org-contacts)
+(defcustom org-contacts-tags-props-prefix "#"
+ "Tags and properties prefix."
+ :type 'string
+ :group 'org-contacts)
+
(defcustom org-contacts-matcher
(mapconcat 'identity (list org-contacts-email-property
org-contacts-alias-property
@@ -183,6 +188,12 @@ This overrides `org-email-link-description-format' if set."
:group 'org-contacts
:type 'boolean)
+(defcustom org-contacts-complete-functions
+ '(org-contacts-complete-group org-contacts-complete-tags-props org-contacts-complete-name)
+ "List of functions used to complete contacts in `message-mode'."
+ :group 'org-contacts
+ :type 'hook)
+
;; Decalre external functions and variables
(declare-function org-reverse-string "org")
(declare-function diary-ordinal-suffix "ext:diary-lib")
@@ -244,7 +255,7 @@ to dead or no buffer."
(let* (todo-only
(contacts-matcher
(cdr (org-make-tags-matcher org-contacts-matcher)))
- markers result)
+ result)
(when (org-contacts-db-need-update-p)
(let ((progress-reporter
(make-progress-reporter "Updating Org Contacts Database..." 0 (length org-contacts-files)))
@@ -253,21 +264,26 @@ to dead or no buffer."
(org-check-agenda-file file)
(with-current-buffer (org-get-agenda-file-buffer file)
(unless (eq major-mode 'org-mode)
- (error "File %s is no in `org-mode'" file))
- (org-scan-tags
- '(add-to-list 'markers (set-marker (make-marker) (point)))
- contacts-matcher
- todo-only))
+ (error "File %s is not in `org-mode'" file))
+ (setf result
+ (append result
+ (org-scan-tags
+ 'org-contacts-at-point
+ contacts-matcher
+ todo-only))))
(progress-reporter-update progress-reporter (setq i (1+ i))))
- (dolist (marker markers result)
- (org-with-point-at marker
- (add-to-list 'result
- (list (org-get-heading t) marker (org-entry-properties marker 'all)))))
(setf org-contacts-db result
org-contacts-last-update (current-time))
- (progress-reporter-done progress-reporter)))
+ (progress-reporter-done progress-reporter)))
org-contacts-db))
+(defun org-contacts-at-point (&optional pom)
+ "Return the contacts at point-or-marker POM or current position
+if nil."
+ (setq pom (or pom (point)))
+ (org-with-point-at pom
+ (list (org-get-heading t) (set-marker (make-marker) pom) (org-entry-properties pom 'all))))
+
(defun org-contacts-filter (&optional name-match tags-match prop-match)
"Search for a contact matching any of NAME-MATCH, TAGS-MATCH, PROP-MATCH.
If all match values are nil, return all contacts.
@@ -500,11 +516,12 @@ A group FOO is composed of contacts with the tag FOO."
;; returned by `org-contacts-filter'.
for contact-name = (car contact)
;; Grab the first email of the contact
- for email = (org-contacts-strip-link (car (org-contacts-split-property
- (or
- (cdr (assoc-string org-contacts-email-property
- (caddr contact)))
- ""))))
+ for email = (org-contacts-strip-link
+ (or (car (org-contacts-split-property
+ (or
+ (cdr (assoc-string org-contacts-email-property
+ (caddr contact)))
+ ""))) ""))
;; If the user has an email address, append USER <EMAIL>.
if email collect (org-contacts-format-email contact-name email))
", ")))
@@ -512,6 +529,45 @@ A group FOO is composed of contacts with the tag FOO."
(completion-table-case-fold completion-list
(not org-contacts-completion-ignore-case))))))))
+(defun org-contacts-complete-tags-props (start end string)
+ "Insert emails that match the tags expression.
+
+For example: FOO-BAR will match entries tagged with FOO but not
+with BAR.
+
+See (org) Matching tags and properties for a complete
+description."
+ (let* ((completion-ignore-case org-contacts-completion-ignore-case)
+ (completion-p (org-string-match-p
+ (concat "^" org-contacts-tags-props-prefix) string)))
+ (when completion-p
+ (let ((result
+ (mapconcat
+ 'identity
+ (loop for contact in (org-contacts-db)
+ for contact-name = (car contact)
+ for email = (org-contacts-strip-link (or (car (org-contacts-split-property
+ (or
+ (cdr (assoc-string org-contacts-email-property
+ (caddr contact)))
+ ""))) ""))
+ for tags = (cdr (assoc "TAGS" (nth 2 contact)))
+ for tags-list = (if tags
+ (split-string (substring (cdr (assoc "TAGS" (nth 2 contact))) 1 -1) ":")
+ '())
+ for marker = (second contact)
+ if (with-current-buffer (marker-buffer marker)
+ (save-excursion
+ (goto-char marker)
+ (let (todo-only)
+ (eval (cdr (org-make-tags-matcher (subseq string 1)))))))
+ collect (org-contacts-format-email contact-name email))
+ ",")))
+ (when (not (string= "" result))
+ ;; return (start end function)
+ (lexical-let* ((to-return result))
+ (list start end
+ (lambda (string pred &optional to-ignore) to-return))))))))
(defun org-contacts-remove-ignored-property-values (ignore-list list)
"Remove all ignore-list's elements from list and you can use
@@ -570,8 +626,8 @@ A group FOO is composed of contacts with the tag FOO."
(goto-char (match-end 0))
(point))))
(string (buffer-substring start end)))
- (or (org-contacts-complete-group start end string)
- (org-contacts-complete-name start end string))))))
+ (run-hook-with-args-until-success
+ 'org-contacts-complete-functions start end string)))))
(defun org-contacts-gnus-get-name-email ()
"Get name and email address from Gnus message."
@@ -946,7 +1002,7 @@ to do our best."
(setq phones-list (org-contacts-remove-ignored-property-values ignore-list (org-contacts-split-property tel)))
(setq result "")
(while phones-list
- (setq result (concat result "TEL:" (org-contacts-strip-link (car phones-list)) "\n"))
+ (setq result (concat result "TEL:" (org-link-unescape (org-contacts-strip-link (car phones-list))) "\n"))
(setq phones-list (cdr phones-list)))
result))
(when bday
@@ -960,11 +1016,39 @@ to do our best."
"END:VCARD\n\n")))
(defun org-contacts-export-as-vcard (&optional name file to-buffer)
+ "Export org contacts to V-Card 3.0.
+
+By default, all contacts are exported to `org-contacts-vcard-file'.
+
+When NAME is \\[universal-argument], prompts for a contact name.
+
+When NAME is \\[universal-argument] \\[universal-argument],
+prompts for a contact name and a file name where to export.
+
+When NAME is \\[universal-argument] \\[universal-argument]
+\\[universal-argument], prompts for a contact name and a buffer where to export.
+
+If the function is not called interactively, all parameters are
+passed to `org-contacts-export-as-vcard-internal'."
+ (interactive "P")
+ (when (called-interactively-p 'any)
+ (cl-psetf name
+ (when name
+ (read-string "Contact name: "
+ (first (org-contacts-at-point))))
+ file
+ (when (equal name '(16))
+ (read-file-name "File: " nil org-contacts-vcard-file))
+ to-buffer
+ (when (equal name '(64))
+ (read-buffer "Buffer: "))))
+ (org-contacts-export-as-vcard-internal name file to-buffer))
+
+(defun org-contacts-export-as-vcard-internal (&optional name file to-buffer)
"Export all contacts matching NAME as VCard 3.0.
If TO-BUFFER is nil, the content is written to FILE or
`org-contacts-vcard-file'. If TO-BUFFER is non-nil, the buffer
is created and the VCard is written into that buffer."
- (interactive) ; TODO ask for name?
(let* ((filename (or file org-contacts-vcard-file))
(buffer (if to-buffer
(get-buffer-create to-buffer)
diff --git a/contrib/lisp/org-contribdir.el b/contrib/lisp/org-contribdir.el
index 8132750..d94e7a0 100644
--- a/contrib/lisp/org-contribdir.el
+++ b/contrib/lisp/org-contribdir.el
@@ -1,5 +1,5 @@
;;; org-contribdir.el --- Mark the location of the contrib directory
-;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2014 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
diff --git a/contrib/lisp/org-depend.el b/contrib/lisp/org-depend.el
index dc99a1d..1cd4130 100644
--- a/contrib/lisp/org-depend.el
+++ b/contrib/lisp/org-depend.el
@@ -1,5 +1,5 @@
;;; org-depend.el --- TODO dependencies for Org-mode
-;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
diff --git a/contrib/lisp/org-download.el b/contrib/lisp/org-download.el
new file mode 100644
index 0000000..39312cf
--- a/dev/null
+++ b/contrib/lisp/org-download.el
@@ -0,0 +1,336 @@
+;;; org-download.el --- Image drag-and-drop for Emacs org-mode
+
+;; Copyright (C) 2014 Free Software Foundation, Inc.
+
+;; Author: Oleh Krehel
+;; Keywords: images, screenshots, download
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; This extension facilitates moving images from point A to point B.
+;;
+;; Point A (the source) can be:
+;; 1. An image inside your browser that you can drag to Emacs.
+;; 2. An image on your file system that you can drag to Emacs.
+;; 3. A local or remote image address in kill-ring.
+;; Use the `org-download-yank' command for this.
+;; Remember that you can use "0 w" in `dired' to get an address.
+;; 4. An screenshot taken using `gnome-screenshot' or `scrot' or `gm'.
+;; Use the `org-download-screenshot' command for this.
+;; Customize the backend with `org-download-screenshot-method'.
+;;
+;; Point B (the target) is an Emacs `org-mode' buffer where the inline
+;; link will be inserted. Several customization options will determine
+;; where exactly on the file system the file will be stored.
+;;
+;; They are:
+;; `org-download-method':
+;; a. 'attach => use `org-mode' attachment machinery
+;; b. 'directory => construct the directory in two stages:
+;; 1. first part of the folder name is:
+;; * either "." (current folder)
+;; * or `org-download-image-dir' (if it's not nil).
+;; `org-download-image-dir' becomes buffer-local when set,
+;; so each file can customize this value, e.g with:
+;; # -*- mode: Org; org-download-image-dir: ~/Pictures/foo; -*-
+;; 2. second part is:
+;; * `org-download-heading-lvl' is nil => ""
+;; * `org-download-heading-lvl' is n => the name of current
+;; heading with level n. Level count starts with 0,
+;; i.e. * is 0, ** is 1, *** is 2 etc.
+;; `org-download-heading-lvl' becomes buffer-local when set,
+;; so each file can customize this value, e.g with:
+;; # -*- mode: Org; org-download-heading-lvl: nil; -*-
+;;
+;; `org-download-timestamp':
+;; optionally add a timestamp to the file name.
+;;
+;; Customize `org-download-backend' to choose between `url-retrieve'
+;; (the default) or `wget' or `curl'.
+;;
+;;; Code:
+
+
+(eval-when-compile
+ (require 'cl))
+(require 'url-parse)
+(require 'url-http)
+
+(defgroup org-download nil
+ "Image drag-and-drop for org-mode."
+ :group 'org
+ :prefix "org-download-")
+
+(defcustom org-download-method 'directory
+ "The way images should be stored."
+ :type '(choice
+ (const :tag "Directory" directory)
+ (const :tag "Attachment" attach))
+ :group 'org-download)
+
+(defcustom org-download-image-dir nil
+ "If set, images will be stored in this directory instead of \".\".
+See `org-download--dir-1' for more info."
+ :type '(choice
+ (const :tag "Default" nil)
+ (string :tag "Directory"))
+ :group 'org-download)
+(make-variable-buffer-local 'org-download-image-dir)
+
+(defcustom org-download-heading-lvl 0
+ "Heading level to be used in `org-download--dir-2'."
+ :group 'org-download)
+(make-variable-buffer-local 'org-download-heading-lvl)
+
+(defcustom org-download-backend t
+ "Method to use for downloading."
+ :type '(choice
+ (const :tag "wget" "wget \"%s\" -O \"%s\"")
+ (const :tag "curl" "curl \"%s\" -o \"%s\"")
+ (const :tag "url-retrieve" t))
+ :group 'org-download)
+
+(defcustom org-download-timestamp "_%Y-%m-%d_%H:%M:%S"
+ "This `format-time-string'-style string will be appended to the file name.
+Set this to \"\" if you don't want time stamps."
+ :type 'string
+ :group 'org-download)
+
+(defcustom org-download-screenshot-method "gnome-screenshot -a -f %s"
+ "The tool to capture screenshots."
+ :type '(choice
+ (const :tag "gnome-screenshot" "gnome-screenshot -a -f %s")
+ (const :tag "scrot" "scrot -s %s")
+ (const :tag "gm" "gm import %s"))
+ :group 'org-download)
+
+(defcustom org-download-image-width 0
+ "When non-zero add #+attr_html: :width tag to the image."
+ :type 'integer
+ :group 'org-download)
+
+(defun org-download-get-heading (lvl)
+ "Return the heading of the current entry's LVL level parent."
+ (save-excursion
+ (let ((cur-lvl (org-current-level)))
+ (unless (= cur-lvl 1)
+ (org-up-heading-all (- (1- (org-current-level)) lvl)))
+ (substring-no-properties
+ (org-get-heading)))))
+
+(defun org-download--dir-1 ()
+ "Return the first part of the directory path for `org-download--dir'.
+It's `org-download-image-dir', unless it's nil. Then it's \".\"."
+ (or org-download-image-dir "."))
+
+(defun org-download--dir-2 ()
+ "Return the second part of the directory path for `org-download--dir'.
+Unless `org-download-heading-lvl' is nil, it's the name of the current
+`org-download-heading-lvl'-leveled heading. Otherwise it's \"\"."
+ (and org-download-heading-lvl
+ (org-download-get-heading
+ org-download-heading-lvl)))
+
+(defun org-download--dir ()
+ "Return the directory path for image storage.
+
+The path is composed from `org-download--dir-1' and `org-download--dir-2'.
+The directory is created if it didn't exist before."
+ (let* ((part1 (org-download--dir-1))
+ (part2 (org-download--dir-2))
+ (dir (if part2
+ (format "%s/%s" part1 part2)
+ part1)))
+ (unless (file-exists-p dir)
+ (make-directory dir t))
+ dir))
+
+(defun org-download--fullname (link)
+ "Return the file name where LINK will be saved to.
+
+It's affected by `org-download-timestamp' and `org-download--dir'."
+ (let ((filename
+ (file-name-nondirectory
+ (car (url-path-and-query
+ (url-generic-parse-url link)))))
+ (dir (org-download--dir)))
+ (format "%s/%s%s.%s"
+ dir
+ (file-name-sans-extension filename)
+ (format-time-string org-download-timestamp)
+ (file-name-extension filename))))
+
+(defun org-download--image (link filename)
+ "Save LINK to FILENAME asynchronously and show inline images in current buffer."
+ (when (string-match "^file://\\(.*\\)" link)
+ (setq link (url-unhex-string (match-string 1 link))))
+ (cond ((file-exists-p link)
+ (org-download--image/command "cp \"%s\" \"%s\"" link filename))
+ ((eq org-download-backend t)
+ (org-download--image/url-retrieve link filename))
+ (t
+ (org-download--image/command org-download-backend link filename))))
+
+(defun org-download--image/command (command link filename)
+ "Using COMMAND, save LINK to FILENAME.
+COMMAND is a format-style string with two slots for LINK and FILENAME."
+ (require 'async)
+ (async-start
+ `(lambda() (shell-command
+ ,(format command link
+ (expand-file-name filename))))
+ (lexical-let ((cur-buf (current-buffer)))
+ (lambda(x)
+ (with-current-buffer cur-buf
+ (org-display-inline-images))))))
+
+(defun org-download--image/url-retrieve (link filename)
+ "Save LINK to FILENAME using `url-retrieve'."
+ (url-retrieve
+ link
+ (lambda (status filename buffer)
+ ;; Write current buffer to FILENAME
+ ;; and update inline images in BUFFER
+ (let ((err (plist-get status :error)))
+ (if err (error
+ "\"%s\" %s" link
+ (downcase (nth 2 (assq (nth 2 err) url-http-codes))))))
+ (delete-region
+ (point-min)
+ (progn
+ (re-search-forward "\n\n" nil 'move)
+ (point)))
+ (let ((coding-system-for-write 'no-conversion))
+ (write-region nil nil filename nil nil nil 'confirm))
+ (with-current-buffer buffer
+ (org-display-inline-images)))
+ (list
+ (expand-file-name filename)
+ (current-buffer))
+ nil t))
+
+(defun org-download-yank ()
+ "Call `org-download-image' with current kill."
+ (interactive)
+ (org-download-image (current-kill 0)))
+
+(defun org-download-screenshot ()
+ "Capture screenshot and insert the resulting file.
+The screenshot tool is determined by `org-download-screenshot-method'."
+ (interactive)
+ (let ((link "/tmp/screenshot.png"))
+ (shell-command (format org-download-screenshot-method link))
+ (org-download-image link)))
+
+(defun org-download-image (link)
+ "Save image at address LINK to `org-download--dir'."
+ (interactive "sUrl: ")
+ (let ((filename
+ (if (eq org-download-method 'attach)
+ (let ((org-download-image-dir (progn (require 'org-attach)
+ (org-attach-dir t)))
+ org-download-heading-lvl)
+ (org-download--fullname link))
+ (org-download--fullname link))))
+ (when (image-type-from-file-name filename)
+ (org-download--image link filename)
+ (when (eq org-download-method 'attach)
+ (org-attach-attach filename nil 'none))
+ (if (looking-back "^[ \t]+")
+ (delete-region (match-beginning 0) (match-end 0))
+ (newline))
+ (insert (format "#+DOWNLOADED: %s @ %s\n%s [[%s]]"
+ link
+ (format-time-string "%Y-%m-%d %H:%M:%S")
+ (if (= org-download-image-width 0)
+ ""
+ (format "#+attr_html: :width %dpx\n" org-download-image-width))
+ filename))
+ (org-display-inline-images))))
+
+(defun org-download--at-comment-p ()
+ "Check if current line begins with #+DOWLOADED:."
+ (save-excursion
+ (move-beginning-of-line nil)
+ (looking-at "#\\+DOWNLOADED:")))
+
+(defun org-download-delete ()
+ "Delete inline image link on current line, and the file that it points to."
+ (interactive)
+ (cond ((org-download--at-comment-p)
+ (delete-region (line-beginning-position)
+ (line-end-position))
+ (org-download--delete (line-beginning-position)
+ nil
+ 1))
+ ((region-active-p)
+ (org-download--delete (region-beginning)
+ (region-end))
+ (delete-region (region-beginning)
+ (region-end)))
+
+ (t (org-download--delete (line-beginning-position)
+ (line-end-position)))))
+
+(defun org-download--delete (beg end &optional times)
+ "Delete inline image links and the files they point to between BEG and END.
+
+When TIMES isn't nil, delete only TIMES links."
+ (unless times
+ (setq times most-positive-fixnum))
+ (save-excursion
+ (goto-char beg)
+ (while (and (>= (decf times) 0)
+ (re-search-forward "\\[\\[\\([^]]*\\)\\]\\]" end t))
+ (let ((str (match-string-no-properties 1)))
+ (delete-region (match-beginning 0)
+ (match-end 0))
+ (when (file-exists-p str)
+ (delete-file str))))))
+
+(defun org-download-dnd (uri action)
+ "When in `org-mode' and URI points to image, download it.
+Otherwise, pass URI and ACTION back to dnd dispatch."
+ (if (eq major-mode 'org-mode)
+ ;; probably shouldn't redirect
+ (unless (org-download-image uri)
+ (message "not an image URL"))
+ ;; redirect to someone else
+ (let ((dnd-protocol-alist
+ (rassq-delete-all
+ 'org-download-dnd
+ (copy-alist dnd-protocol-alist))))
+ (dnd-handle-one-url nil action uri))))
+
+(defun org-download-enable ()
+ "Enable org-download."
+ (unless (eq (cdr (assoc "^\\(https?\\|ftp\\|file\\|nfs\\)://" dnd-protocol-alist))
+ 'org-download-dnd)
+ (setq dnd-protocol-alist
+ `(("^\\(https?\\|ftp\\|file\\|nfs\\)://" . org-download-dnd) ,@dnd-protocol-alist))))
+
+(defun org-download-disable ()
+ "Disable org-download."
+ (rassq-delete-all 'org-download-dnd dnd-protocol-alist))
+
+(org-download-enable)
+
+(provide 'org-download)
+
+;;; org-download.el ends here
diff --git a/contrib/lisp/org-drill.el b/contrib/lisp/org-drill.el
index 5bf6dd4..e5b0d49 100644
--- a/contrib/lisp/org-drill.el
+++ b/contrib/lisp/org-drill.el
@@ -1,73 +1,72 @@
-;; -*- coding: utf-8-unix -*-
+;;; -*- coding: utf-8-unix -*-
;;; org-drill.el - Self-testing using spaced repetition
;;;
-;; Author: Paul Sexton <eeeickythump@gmail.com>
-;; Version: 2.3.7
-;; Repository at http://bitbucket.org/eeeickythump/org-drill/
-;;
-;; This file is not part of GNU Emacs.
-;;
-;; This program 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,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary and synopsis:
+;;; Author: Paul Sexton <eeeickythump@gmail.com>
+;;; Version: 2.4.1
+;;; Repository at http://bitbucket.org/eeeickythump/org-drill/
;;;
-;; Uses the SuperMemo spaced repetition algorithms to conduct interactive
-;; "drill sessions", where the material to be remembered is presented to the
-;; student in random order. The student rates his or her recall of each item,
-;; and this information is used to schedule the item for later revision.
-;;
-;; Each drill session can be restricted to topics in the current buffer
-;; (default), one or several files, all agenda files, or a subtree. A single
-;; topic can also be drilled.
-;;
-;; Different "card types" can be defined, which present their information to
-;; the student in different ways.
-;;
-;; See the file README.org for more detailed documentation.
-;;
-;;; Code:
+;;;
+;;; Synopsis
+;;; ========
+;;;
+;;; Uses the SuperMemo spaced repetition algorithms to conduct interactive
+;;; "drill sessions", where the material to be remembered is presented to the
+;;; student in random order. The student rates his or her recall of each item,
+;;; and this information is used to schedule the item for later revision.
+;;;
+;;; Each drill session can be restricted to topics in the current buffer
+;;; (default), one or several files, all agenda files, or a subtree. A single
+;;; topic can also be drilled.
+;;;
+;;; Different "card types" can be defined, which present their information to
+;;; the student in different ways.
+;;;
+;;; See the file README.org for more detailed documentation.
+
(eval-when-compile (require 'cl))
(eval-when-compile (require 'hi-lock))
+(require 'cl-lib)
+(require 'hi-lock)
(require 'org)
(require 'org-id)
(require 'org-learn)
+
(defgroup org-drill nil
"Options concerning interactive drill sessions in Org mode (org-drill)."
:tag "Org-Drill"
:group 'org-link)
-(defcustom org-drill-question-tag "drill"
+
+
+(defcustom org-drill-question-tag
+ "drill"
"Tag which topics must possess in order to be identified as review topics
by `org-drill'."
:group 'org-drill
:type 'string)
-(defcustom org-drill-maximum-items-per-session 30
+
+(defcustom org-drill-maximum-items-per-session
+ 30
"Each drill session will present at most this many topics for review.
Nil means unlimited."
:group 'org-drill
:type '(choice integer (const nil)))
-(defcustom org-drill-maximum-duration 20
+
+
+(defcustom org-drill-maximum-duration
+ 20
"Maximum duration of a drill session, in minutes.
Nil means unlimited."
:group 'org-drill
:type '(choice integer (const nil)))
-(defcustom org-drill-failure-quality 2
+
+(defcustom org-drill-failure-quality
+ 2
"If the quality of recall for an item is this number or lower,
it is regarded as an unambiguous failure, and the repetition
interval for the card is reset to 0 days. If the quality is higher
@@ -81,7 +80,9 @@ really sensible."
:group 'org-drill
:type '(choice (const 2) (const 1)))
-(defcustom org-drill-forgetting-index 10
+
+(defcustom org-drill-forgetting-index
+ 10
"What percentage of items do you consider it is 'acceptable' to
forget each drill session? The default is 10%. A warning message
is displayed at the end of the session if the percentage forgotten
@@ -89,13 +90,17 @@ climbs above this number."
:group 'org-drill
:type 'integer)
-(defcustom org-drill-leech-failure-threshold 15
+
+(defcustom org-drill-leech-failure-threshold
+ 15
"If an item is forgotten more than this many times, it is tagged
as a 'leech' item."
:group 'org-drill
:type '(choice integer (const nil)))
-(defcustom org-drill-leech-method 'skip
+
+(defcustom org-drill-leech-method
+ 'skip
"How should 'leech items' be handled during drill sessions?
Possible values:
- nil :: Leech items are treated the same as normal items.
@@ -104,62 +109,89 @@ Possible values:
but a warning message is printed when each leech item is
presented."
:group 'org-drill
- :type '(choice (const 'warn) (const 'skip) (const nil)))
+ :type '(choice (const warn) (const skip) (const nil)))
+
(defface org-drill-visible-cloze-face
'((t (:foreground "darkseagreen")))
"The face used to hide the contents of cloze phrases."
:group 'org-drill)
+
(defface org-drill-visible-cloze-hint-face
'((t (:foreground "dark slate blue")))
"The face used to hide the contents of cloze phrases."
:group 'org-drill)
+
(defface org-drill-hidden-cloze-face
'((t (:foreground "deep sky blue" :background "blue")))
"The face used to hide the contents of cloze phrases."
:group 'org-drill)
-(defcustom org-drill-use-visible-cloze-face-p nil
+
+(defcustom org-drill-use-visible-cloze-face-p
+ nil
"Use a special face to highlight cloze-deleted text in org mode
buffers?"
:group 'org-drill
:type 'boolean)
-(defcustom org-drill-hide-item-headings-p nil
+
+(defcustom org-drill-hide-item-headings-p
+ nil
"Conceal the contents of the main heading of each item during drill
sessions? You may want to enable this behaviour if item headings or tags
contain information that could 'give away' the answer."
:group 'org-drill
:type 'boolean)
-(defcustom org-drill-new-count-color "royal blue"
+
+(defcustom org-drill-new-count-color
+ "royal blue"
"Foreground colour used to display the count of remaining new items
during a drill session."
:group 'org-drill
:type 'color)
-(defcustom org-drill-mature-count-color "green"
+(defcustom org-drill-mature-count-color
+ "green"
"Foreground colour used to display the count of remaining mature items
during a drill session. Mature items are due for review, but are not new."
:group 'org-drill
:type 'color)
-(defcustom org-drill-failed-count-color "red"
+(defcustom org-drill-failed-count-color
+ "red"
"Foreground colour used to display the count of remaining failed items
during a drill session."
:group 'org-drill
:type 'color)
-(defcustom org-drill-done-count-color "sienna"
+(defcustom org-drill-done-count-color
+ "sienna"
"Foreground colour used to display the count of reviewed items
during a drill session."
:group 'org-drill
:type 'color)
+(defcustom org-drill-left-cloze-delimiter
+ "["
+ "String used within org buffers to delimit cloze deletions."
+ :group 'org-drill
+ :type 'string)
+
+(defcustom org-drill-right-cloze-delimiter
+ "]"
+ "String used within org buffers to delimit cloze deletions."
+ :group 'org-drill
+ :type 'string)
+
+
(setplist 'org-drill-cloze-overlay-defaults
- '(display "[...]"
+ `(display ,(format "%s...%s"
+ org-drill-left-cloze-delimiter
+ org-drill-right-cloze-delimiter)
face org-drill-hidden-cloze-face
window t))
@@ -171,21 +203,35 @@ during a drill session."
face default
window t))
+
(defvar org-drill-hint-separator "||"
"String which, if it occurs within a cloze expression, signifies that the
rest of the expression after the string is a `hint', to be displayed instead of
the hidden cloze during a test.")
-(defvar org-drill-cloze-regexp
- (concat "\\(\\[[[:cntrl:][:graph:][:space:]]+?\\)\\(\\|"
+(defun org-drill--compute-cloze-regexp ()
+ (concat "\\("
+ (regexp-quote org-drill-left-cloze-delimiter)
+ "[[:cntrl:][:graph:][:space:]]+?\\)\\(\\|"
(regexp-quote org-drill-hint-separator)
- ".+?\\)\\(\\]\\)"))
+ ".+?\\)\\("
+ (regexp-quote org-drill-right-cloze-delimiter)
+ "\\)"))
+
+(defun org-drill--compute-cloze-keywords ()
+ (list (list (org-drill--compute-cloze-regexp)
+ (copy-list '(1 'org-drill-visible-cloze-face nil))
+ (copy-list '(2 'org-drill-visible-cloze-hint-face t))
+ (copy-list '(3 'org-drill-visible-cloze-face nil))
+ )))
+
+(defvar-local org-drill-cloze-regexp
+ (org-drill--compute-cloze-regexp))
+
+
+(defvar-local org-drill-cloze-keywords
+ (org-drill--compute-cloze-keywords))
-(defvar org-drill-cloze-keywords
- `((,org-drill-cloze-regexp
- (1 'org-drill-visible-cloze-face nil)
- (2 'org-drill-visible-cloze-hint-face t)
- (3 'org-drill-visible-cloze-face nil))))
(defcustom org-drill-card-type-alist
'((nil org-drill-present-simple-card)
@@ -234,7 +280,9 @@ even if their bodies are empty."
:type '(alist :key-type (choice string (const nil))
:value-type function))
-(defcustom org-drill-scope 'file
+
+(defcustom org-drill-scope
+ 'file
"The scope in which to search for drill items when conducting a
drill session. This can be any of:
@@ -256,18 +304,34 @@ directory All files with the extension '.org' in the same
;; 'file-no-restriction' means current file/buffer, ignoring restrictions
;; 'directory' means all *.org files in current directory
:group 'org-drill
- :type '(choice (const 'file) (const 'tree) (const 'file-no-restriction)
- (const 'file-with-archives) (const 'agenda)
- (const 'agenda-with-archives) (const 'directory)
- list))
+ :type '(choice (const :tag "The current buffer, respecting the restriction if any." file)
+ (const :tag "The subtree started with the entry at point" tree)
+ (const :tag "The current buffer, without restriction" file-no-restriction)
+ (const :tag "The current buffer, and any archives associated with it." file-with-archives)
+ (const :tag "All agenda files" agenda)
+ (const :tag "All agenda files with any archive files associated with them." agenda-with-archives)
+ (const :tag "All files with the extension '.org' in the same directory as the current file (includes the current file if it is an .org file.)" directory)
+ (repeat :tag "List of files to scan for drill items." file)))
+
+
+(defcustom org-drill-match
+ nil
+ "If non-nil, a string specifying a tags/property/TODO query. During
+drill sessions, only items that match this query will be considered."
+ :group 'org-drill
+ :type '(choice (const nil) string))
+
-(defcustom org-drill-save-buffers-after-drill-sessions-p t
+(defcustom org-drill-save-buffers-after-drill-sessions-p
+ t
"If non-nil, prompt to save all modified buffers after a drill session
finishes."
:group 'org-drill
:type 'boolean)
-(defcustom org-drill-spaced-repetition-algorithm 'sm5
+
+(defcustom org-drill-spaced-repetition-algorithm
+ 'sm5
"Which SuperMemo spaced repetition algorithm to use for scheduling items.
Available choices are:
- SM2 :: the SM2 algorithm, used in SuperMemo 2.0
@@ -280,9 +344,11 @@ Available choices are:
adjusting intervals when items are reviewed early or late has been taken
from SM11, a later version of the algorithm, and included in Simple8."
:group 'org-drill
- :type '(choice (const 'sm2) (const 'sm5) (const 'simple8)))
+ :type '(choice (const sm2) (const sm5) (const simple8)))
+
-(defcustom org-drill-optimal-factor-matrix nil
+(defcustom org-drill-optimal-factor-matrix
+ nil
"DO NOT CHANGE THE VALUE OF THIS VARIABLE.
Persistent matrix of optimal factors, used by the SuperMemo SM5 algorithm.
@@ -294,14 +360,18 @@ pace of learning."
:group 'org-drill
:type 'sexp)
-(defcustom org-drill-sm5-initial-interval 4.0
+
+(defcustom org-drill-sm5-initial-interval
+ 4.0
"In the SM5 algorithm, the initial interval after the first
successful presentation of an item is always 4 days. If you wish to change
this, you can do so here."
:group 'org-drill
:type 'float)
-(defcustom org-drill-add-random-noise-to-intervals-p nil
+
+(defcustom org-drill-add-random-noise-to-intervals-p
+ nil
"If true, the number of days until an item's next repetition
will vary slightly from the interval calculated by the SM2
algorithm. The variation is very small when the interval is
@@ -309,7 +379,9 @@ small, but scales up with the interval."
:group 'org-drill
:type 'boolean)
-(defcustom org-drill-adjust-intervals-for-early-and-late-repetitions-p nil
+
+(defcustom org-drill-adjust-intervals-for-early-and-late-repetitions-p
+ nil
"If true, when the student successfully reviews an item 1 or more days
before or after the scheduled review date, this will affect that date of
the item's next scheduled review, according to the algorithm presented at
@@ -324,7 +396,9 @@ is used."
:group 'org-drill
:type 'boolean)
-(defcustom org-drill-cloze-text-weight 4
+
+(defcustom org-drill-cloze-text-weight
+ 4
"For card types 'hide1_firstmore', 'show1_lastmore' and 'show1_firstless',
this number determines how often the 'less favoured' situation
should arise. It will occur 1 in every N trials, where N is the
@@ -343,12 +417,15 @@ all weighted card types are treated as their unweighted equivalents."
:group 'org-drill
:type '(choice integer (const nil)))
-(defcustom org-drill-cram-hours 12
+
+(defcustom org-drill-cram-hours
+ 12
"When in cram mode, items are considered due for review if
they were reviewed at least this many hours ago."
:group 'org-drill
:type 'integer)
+
;;; NEW items have never been presented in a drill session before.
;;; MATURE items HAVE been presented at least once before.
;;; - YOUNG mature items were scheduled no more than
@@ -361,13 +438,17 @@ they were reviewed at least this many hours ago."
;;; LAST-INTERVAL * (ORG-DRILL-OVERDUE-INTERVAL-FACTOR - 1) days,
;;; regardless of young/old status.
-(defcustom org-drill-days-before-old 10
+
+(defcustom org-drill-days-before-old
+ 10
"When an item's inter-repetition interval rises above this value in days,
it is no longer considered a 'young' (recently learned) item."
:group 'org-drill
:type 'integer)
-(defcustom org-drill-overdue-interval-factor 1.2
+
+(defcustom org-drill-overdue-interval-factor
+ 1.2
"An item is considered overdue if its scheduled review date is
more than (ORG-DRILL-OVERDUE-INTERVAL-FACTOR - 1) * LAST-INTERVAL
days in the past. For example, a value of 1.2 means an additional
@@ -379,7 +460,9 @@ should never be less than 1.0."
:group 'org-drill
:type 'float)
-(defcustom org-drill-learn-fraction 0.5
+
+(defcustom org-drill-learn-fraction
+ 0.5
"Fraction between 0 and 1 that governs how quickly the spaces
between successive repetitions increase, for all items. The
default value is 0.5. Higher values make spaces increase more
@@ -389,6 +472,7 @@ exponential effect on inter-repetition spacing."
:group 'org-drill
:type 'float)
+
(defvar drill-answer nil
"Global variable that can be bound to a correct answer when an
item is being presented. If this variable is non-nil, the default
@@ -399,6 +483,7 @@ This variable is useful for card types that compute their answers
-- for example, a card type that asks the student to translate a
random number to another language. ")
+
(defvar *org-drill-session-qualities* nil)
(defvar *org-drill-start-time* 0)
(defvar *org-drill-new-entries* nil)
@@ -428,8 +513,10 @@ for review unless they were already reviewed in the recent past?")
"DRILL_TOTAL_REPEATS" "DRILL_FAILURE_COUNT" "DRILL_AVERAGE_QUALITY"
"DRILL_EASE" "DRILL_LAST_QUALITY" "DRILL_LAST_REVIEWED"))
+
;;; Make the above settings safe as file-local variables.
+
(put 'org-drill-question-tag 'safe-local-variable 'stringp)
(put 'org-drill-maximum-items-per-session 'safe-local-variable
'(lambda (val) (or (integerp val) (null val))))
@@ -454,15 +541,22 @@ for review unless they were already reviewed in the recent past?")
(put 'org-drill-overdue-interval-factor 'safe-local-variable 'floatp)
(put 'org-drill-scope 'safe-local-variable
'(lambda (val) (or (symbolp val) (listp val))))
+(put 'org-drill-match 'safe-local-variable
+ '(lambda (val) (or (stringp val) (null val))))
(put 'org-drill-save-buffers-after-drill-sessions-p 'safe-local-variable 'booleanp)
(put 'org-drill-cloze-text-weight 'safe-local-variable
'(lambda (val) (or (null val) (integerp val))))
+(put 'org-drill-left-cloze-delimiter 'safe-local-variable 'stringp)
+(put 'org-drill-right-cloze-delimiter 'safe-local-variable 'stringp)
+
;;;; Utilities ================================================================
+
(defun free-marker (m)
(set-marker m nil))
+
(defmacro pop-random (place)
(let ((idx (gensym)))
`(if (null ,place)
@@ -472,18 +566,20 @@ for review unless they were already reviewed in the recent past?")
(setq ,place (append (subseq ,place 0 ,idx)
(subseq ,place (1+ ,idx)))))))))
+
(defmacro push-end (val place)
"Add VAL to the end of the sequence stored in PLACE. Return the new
value."
`(setq ,place (append ,place (list ,val))))
+
(defun shuffle-list (list)
"Randomly permute the elements of LIST (all permutations equally likely)."
;; Adapted from 'shuffle-vector' in cookie1.el
(let ((i 0)
- j
- temp
- (len (length list)))
+ j
+ temp
+ (len (length list)))
(while (< i len)
(setq j (+ i (random* (- len i))))
(setq temp (nth i list))
@@ -492,28 +588,43 @@ value."
(setq i (1+ i))))
list)
+
(defun round-float (floatnum fix)
"Round the floating point number FLOATNUM to FIX decimal places.
Example: (round-float 3.56755765 3) -> 3.568"
(let ((n (expt 10 fix)))
(/ (float (round (* floatnum n))) n)))
+
(defun command-keybinding-to-string (cmd)
"Return a human-readable description of the key/keys to which the command
CMD is bound, or nil if it is not bound to a key."
(let ((key (where-is-internal cmd overriding-local-map t)))
(if key (key-description key))))
+
(defun time-to-inactive-org-timestamp (time)
(format-time-string
(concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")
time))
-(defun org-map-drill-entries (func &optional scope &rest skip)
+
+(defun time-to-active-org-timestamp (time)
+ (format-time-string
+ (concat "<" (substring (cdr org-time-stamp-formats) 1 -1) ">")
+ time))
+
+
+(defun org-map-drill-entries (func &optional scope drill-match &rest skip)
"Like `org-map-entries', but only drill entries are processed."
- (let ((org-drill-scope (or scope org-drill-scope)))
+ (let ((org-drill-scope (or scope org-drill-scope))
+ (org-drill-match (or drill-match org-drill-match)))
(apply 'org-map-entries func
- (concat "+" org-drill-question-tag)
+ (concat "+" org-drill-question-tag
+ (if (and (stringp org-drill-match)
+ (not (member '(?+ ?- ?|) (elt org-drill-match 0))))
+ "+" "")
+ (or org-drill-match ""))
(case org-drill-scope
(file nil)
(file-no-restriction 'file)
@@ -523,6 +634,7 @@ CMD is bound, or nil if it is not bound to a key."
(t org-drill-scope))
skip)))
+
(defmacro with-hidden-cloze-text (&rest body)
`(progn
(org-drill-hide-clozed-text)
@@ -531,6 +643,7 @@ CMD is bound, or nil if it is not bound to a key."
,@body)
(org-drill-unhide-clozed-text))))
+
(defmacro with-hidden-cloze-hints (&rest body)
`(progn
(org-drill-hide-cloze-hints)
@@ -539,6 +652,7 @@ CMD is bound, or nil if it is not bound to a key."
,@body)
(org-drill-unhide-text))))
+
(defmacro with-hidden-comments (&rest body)
`(progn
(if org-drill-hide-item-headings-p
@@ -549,6 +663,7 @@ CMD is bound, or nil if it is not bound to a key."
,@body)
(org-drill-unhide-text))))
+
(defun org-drill-days-since-last-review ()
"Nil means a last review date has not yet been stored for
the item.
@@ -562,6 +677,7 @@ this should never happen."
(time-to-days (apply 'encode-time
(org-parse-time-string datestr)))))))
+
(defun org-drill-hours-since-last-review ()
"Like `org-drill-days-since-last-review', but return value is
in hours rather than days."
@@ -573,6 +689,7 @@ in hours rather than days."
(org-parse-time-string datestr))))
(* 60 60))))))
+
(defun org-drill-entry-p (&optional marker)
"Is MARKER, or the point, in a 'drill item'? This will return nil if
the point is inside a subheading of a drill item -- to handle that
@@ -582,10 +699,12 @@ situation use `org-part-of-drill-entry-p'."
(org-drill-goto-entry marker))
(member org-drill-question-tag (org-get-local-tags))))
+
(defun org-drill-goto-entry (marker)
(switch-to-buffer (marker-buffer marker))
(goto-char marker))
+
(defun org-part-of-drill-entry-p ()
"Is the current entry either the main heading of a 'drill item',
or a subheading within a drill item?"
@@ -593,6 +712,7 @@ or a subheading within a drill item?"
;; Does this heading INHERIT the drill tag
(member org-drill-question-tag (org-get-tags-at))))
+
(defun org-drill-goto-drill-entry-heading ()
"Move the point to the heading which holds the :drill: tag for this
drill entry."
@@ -604,11 +724,14 @@ drill entry."
(unless (org-up-heading-safe)
(error "Cannot find a parent heading that is marked as a drill entry"))))
+
+
(defun org-drill-entry-leech-p ()
"Is the current entry a 'leech item'?"
(and (org-drill-entry-p)
(member "leech" (org-get-local-tags))))
+
;; (defun org-drill-entry-due-p ()
;; (cond
;; (*org-drill-cram-mode*
@@ -626,6 +749,7 @@ drill entry."
;; (- (time-to-days (current-time))
;; (time-to-days item-time))))))))))
+
(defun org-drill-entry-days-overdue ()
"Returns:
- NIL if the item is not to be regarded as scheduled for review at all.
@@ -655,6 +779,7 @@ drill entry."
(- (time-to-days (current-time))
(time-to-days item-time))))))))
+
(defun org-drill-entry-overdue-p (&optional days-overdue last-interval)
"Returns true if entry that is scheduled DAYS-OVERDUE dasy in the past,
and whose last inter-repetition interval was LAST-INTERVAL, should be
@@ -670,28 +795,34 @@ from the entry at point."
(> (/ (+ days-overdue last-interval 1.0) last-interval)
org-drill-overdue-interval-factor)))
+
+
(defun org-drill-entry-due-p ()
(let ((due (org-drill-entry-days-overdue)))
(and (not (null due))
(not (minusp due)))))
+
(defun org-drill-entry-new-p ()
(and (org-drill-entry-p)
(let ((item-time (org-get-scheduled-time (point))))
(null item-time))))
+
(defun org-drill-entry-last-quality (&optional default)
(let ((quality (org-entry-get (point) "DRILL_LAST_QUALITY")))
(if quality
(string-to-number quality)
default)))
+
(defun org-drill-entry-failure-count ()
(let ((quality (org-entry-get (point) "DRILL_FAILURE_COUNT")))
(if quality
(string-to-number quality)
0)))
+
(defun org-drill-entry-average-quality (&optional default)
(let ((val (org-entry-get (point) "DRILL_AVERAGE_QUALITY")))
(if val
@@ -722,16 +853,17 @@ from the entry at point."
(string-to-number val)
default)))
+
;;; From http://www.supermemo.com/english/ol/sm5.htm
(defun org-drill-random-dispersal-factor ()
"Returns a random number between 0.5 and 1.5."
(let ((a 0.047)
(b 0.092)
(p (- (random* 1.0) 0.5)))
- (flet ((sign (n)
- (cond ((zerop n) 0)
- ((plusp n) 1)
- (t -1))))
+ (cl-flet ((sign (n)
+ (cond ((zerop n) 0)
+ ((plusp n) 1)
+ (t -1))))
(/ (+ 100 (* (* (/ -1 b) (log (- 1 (* (/ b a ) (abs p)))))
(sign p)))
100.0))))
@@ -744,9 +876,10 @@ from the entry at point."
(- variation)
mean))
+
(defun org-drill-early-interval-factor (optimal-factor
- optimal-interval
- days-ahead)
+ optimal-interval
+ days-ahead)
"Arguments:
- OPTIMAL-FACTOR: interval-factor if the item had been tested
exactly when it was supposed to be.
@@ -763,6 +896,7 @@ in the matrix."
(- optimal-factor
(* delta-ofmax (/ days-ahead (+ days-ahead (* 0.6 optimal-interval)))))))
+
(defun org-drill-get-item-data ()
"Returns a list of 6 items, containing all the stored recall
data for the item at point:
@@ -800,6 +934,7 @@ in the matrix."
(t ; virgin item
(list 0 0 0 0 nil nil)))))
+
(defun org-drill-store-item-data (last-interval repeats failures
total-repeats meanq
ease)
@@ -815,8 +950,11 @@ in the matrix."
(org-set-property "DRILL_EASE"
(number-to-string (round-float ease 3))))
+
+
;;; SM2 Algorithm =============================================================
+
(defun determine-next-interval-sm2 (last-interval n ef quality
failures meanq total-repeats)
"Arguments:
@@ -865,6 +1003,8 @@ Returns a list: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS OFMATRIX), wher
;;; SM5 Algorithm =============================================================
+
+
(defun initial-optimal-factor-sm5 (n ef)
(if (= 1 n)
org-drill-sm5-initial-interval
@@ -873,17 +1013,19 @@ Returns a list: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS OFMATRIX), wher
(defun get-optimal-factor-sm5 (n ef of-matrix)
(let ((factors (assoc n of-matrix)))
(or (and factors
- (let ((ef-of (assoc ef (cdr factors))))
- (and ef-of (cdr ef-of))))
- (initial-optimal-factor-sm5 n ef))))
+ (let ((ef-of (assoc ef (cdr factors))))
+ (and ef-of (cdr ef-of))))
+ (initial-optimal-factor-sm5 n ef))))
+
(defun inter-repetition-interval-sm5 (last-interval n ef &optional of-matrix)
(let ((of (get-optimal-factor-sm5 n ef (or of-matrix
org-drill-optimal-factor-matrix))))
(if (= 1 n)
- of
+ of
(* of last-interval))))
+
(defun determine-next-interval-sm5 (last-interval n ef quality
failures meanq total-repeats
of-matrix &optional delta-days)
@@ -894,10 +1036,12 @@ Returns a list: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS OFMATRIX), wher
(unless of-matrix
(setq of-matrix org-drill-optimal-factor-matrix))
(setq of-matrix (cl-copy-tree of-matrix))
+
(setq meanq (if meanq
(/ (+ quality (* meanq total-repeats 1.0))
(1+ total-repeats))
quality))
+
(let ((next-ef (modify-e-factor ef quality))
(old-ef ef)
(new-of (modify-of (get-optimal-factor-sm5 n ef of-matrix)
@@ -910,10 +1054,13 @@ Returns a list: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS OFMATRIX), wher
(inter-repetition-interval-sm5
last-interval n ef of-matrix)
delta-days)))
+
(setq of-matrix
(set-optimal-factor n next-ef of-matrix
(round-float new-of 3))) ; round OF to 3 d.p.
+
(setq ef next-ef)
+
(cond
;; "Failed" -- reset repetitions to 0,
((<= quality org-drill-failure-quality)
@@ -938,8 +1085,10 @@ Returns a list: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS OFMATRIX), wher
(1+ total-repeats)
of-matrix)))))
+
;;; Simple8 Algorithm =========================================================
+
(defun org-drill-simple8-first-interval (failures)
"Arguments:
- FAILURES: integer >= 0. The total number of times the item has
@@ -949,6 +1098,7 @@ Returns the optimal FIRST interval for an item which has previously been
forgotten on FAILURES occasions."
(* 2.4849 (exp (* -0.057 failures))))
+
(defun org-drill-simple8-interval-factor (ease repetition)
"Arguments:
- EASE: floating point number >= 1.2. Corresponds to `AF' in SM8 algorithm.
@@ -959,6 +1109,7 @@ The factor by which the last interval should be
multiplied to give the next interval. Corresponds to `RF' or `OF'."
(+ 1.2 (* (- ease 1.2) (expt org-drill-learn-fraction (log repetition 2)))))
+
(defun org-drill-simple8-quality->ease (quality)
"Returns the ease (`AF' in the SM8 algorithm) which corresponds
to a mean item quality of QUALITY."
@@ -968,6 +1119,7 @@ to a mean item quality of QUALITY."
(* -1.2403 quality)
1.4515))
+
(defun determine-next-interval-simple8 (last-interval repeats quality
failures meanq totaln
&optional delta-days)
@@ -1034,7 +1186,11 @@ See the documentation for `org-drill-get-item-data' for a description of these."
(org-drill-simple8-quality->ease meanq)
failures
meanq
- totaln)))
+ totaln
+ )))
+
+
+
;;; Essentially copied from `org-learn.el', but modified to
;;; optionally call the SM2 or simple8 functions.
@@ -1087,7 +1243,7 @@ item will be scheduled exactly this many days into the future."
(cond
((= 0 days-ahead)
- (org-schedule t))
+ (org-schedule '(4)))
((minusp days-ahead)
(org-schedule nil (current-time)))
(t
@@ -1207,13 +1363,14 @@ How well did you do? (0-5, ?=help, e=edit, t=tags, q=quit)"
(sit-for 0.5)))))
(org-set-property "DRILL_LAST_QUALITY" (format "%d" quality))
(org-set-property "DRILL_LAST_REVIEWED"
- (time-to-inactive-org-timestamp (current-time))))
+ (time-to-active-org-timestamp (current-time))))
quality))
((= ch ?e)
'edit)
(t
nil))))
+
;; (defun org-drill-hide-all-subheadings-except (heading-list)
;; "Returns a list containing the position of each immediate subheading of
;; the current topic."
@@ -1234,6 +1391,8 @@ How well did you do? (0-5, ?=help, e=edit, t=tags, q=quit)"
;; "" 'tree))
;; (reverse drill-sections)))
+
+
(defun org-drill-hide-subheadings-if (test)
"TEST is a function taking no arguments. TEST will be called for each
of the immediate subheadings of the current drill item, with the point
@@ -1256,11 +1415,13 @@ the current topic."
"" 'tree))
(reverse drill-sections)))
+
(defun org-drill-hide-all-subheadings-except (heading-list)
(org-drill-hide-subheadings-if
(lambda () (let ((drill-heading (org-get-heading t)))
(not (member drill-heading heading-list))))))
+
(defun org-drill-presentation-prompt (&rest fmt-and-args)
(let* ((item-start-time (current-time))
(input nil)
@@ -1341,22 +1502,26 @@ Consider reformulating the item to make it easier to remember.\n"
(?s 'skip)
(otherwise t))))
+
(defun org-pos-in-regexp (pos regexp &optional nlines)
(save-excursion
(goto-char pos)
(org-in-regexp regexp nlines)))
+
(defun org-drill-hide-region (beg end &optional text)
"Hide the buffer region between BEG and END with an 'invisible text'
visual overlay, or with the string TEXT if it is supplied."
(let ((ovl (make-overlay beg end)))
(overlay-put ovl 'category
'org-drill-hidden-text-overlay)
+ (overlay-put ovl 'priority 9999)
(when (stringp text)
(overlay-put ovl 'invisible nil)
(overlay-put ovl 'face 'default)
(overlay-put ovl 'display text))))
+
(defun org-drill-hide-heading-at-point (&optional text)
(unless (org-at-heading-p)
(error "Point is not on a heading."))
@@ -1365,11 +1530,13 @@ visual overlay, or with the string TEXT if it is supplied."
(end-of-line)
(org-drill-hide-region beg (point) text))))
+
(defun org-drill-hide-comments ()
(save-excursion
(while (re-search-forward "^#.*$" nil t)
(org-drill-hide-region (match-beginning 0) (match-end 0)))))
+
(defun org-drill-unhide-text ()
;; This will also unhide the item's heading.
(save-excursion
@@ -1377,16 +1544,20 @@ visual overlay, or with the string TEXT if it is supplied."
(when (eql 'org-drill-hidden-text-overlay (overlay-get ovl 'category))
(delete-overlay ovl)))))
+
(defun org-drill-hide-clozed-text ()
(save-excursion
(while (re-search-forward org-drill-cloze-regexp nil t)
;; Don't hide org links, partly because they might contain inline
- ;; images which we want to keep visible
+ ;; images which we want to keep visible.
+ ;; And don't hide LaTeX math fragments.
(unless (save-match-data
- (org-pos-in-regexp (match-beginning 0)
- org-bracket-link-regexp 1))
+ (or (org-pos-in-regexp (match-beginning 0)
+ org-bracket-link-regexp 1)
+ (org-inside-LaTeX-fragment-p)))
(org-drill-hide-matched-cloze-text)))))
+
(defun org-drill-hide-matched-cloze-text ()
"Hide the current match with a 'cloze' visual overlay."
(let ((ovl (make-overlay (match-beginning 0) (match-end 0)))
@@ -1394,6 +1565,7 @@ visual overlay, or with the string TEXT if it is supplied."
(match-string 0))))
(overlay-put ovl 'category
'org-drill-cloze-overlay-defaults)
+ (overlay-put ovl 'priority 9999)
(when (and hint-sep-pos
(> hint-sep-pos 1))
(let ((hint (substring-no-properties
@@ -1407,6 +1579,7 @@ visual overlay, or with the string TEXT if it is supplied."
(format (if (string-match-p (regexp-quote "...") hint) "[%s]" "[%s...]")
hint))))))
+
(defun org-drill-hide-cloze-hints ()
(save-excursion
(while (re-search-forward org-drill-cloze-regexp nil t)
@@ -1416,6 +1589,7 @@ visual overlay, or with the string TEXT if it is supplied."
(null (match-beginning 2))) ; hint subexpression matched
(org-drill-hide-region (match-beginning 2) (match-end 2))))))
+
(defmacro with-replaced-entry-text (text &rest body)
"During the execution of BODY, the entire text of the current entry is
concealed by an overlay that displays the string TEXT."
@@ -1426,6 +1600,7 @@ concealed by an overlay that displays the string TEXT."
,@body)
(org-drill-unreplace-entry-text))))
+
(defmacro with-replaced-entry-text-multi (replacements &rest body)
"During the execution of BODY, the entire text of the current entry is
concealed by an overlay that displays the overlays in REPLACEMENTS."
@@ -1436,6 +1611,7 @@ concealed by an overlay that displays the overlays in REPLACEMENTS."
,@body)
(org-drill-unreplace-entry-text))))
+
(defun org-drill-replace-entry-text (text &optional multi-p)
"Make an overlay that conceals the entire text of the item, not
including properties or the contents of subheadings. The overlay shows
@@ -1454,16 +1630,19 @@ Note: does not actually alter the item."
(save-excursion
(outline-next-heading)
(point)))))
+ (overlay-put ovl 'priority 9999)
(overlay-put ovl 'category
'org-drill-replaced-text-overlay)
(overlay-put ovl 'display text)))))
+
(defun org-drill-unreplace-entry-text ()
(save-excursion
(dolist (ovl (overlays-in (point-min) (point-max)))
(when (eql 'org-drill-replaced-text-overlay (overlay-get ovl 'category))
(delete-overlay ovl)))))
+
(defun org-drill-replace-entry-text-multi (replacements)
"Make overlays that conceal the entire text of the item, not
including properties or the contents of subheadings. The overlay shows
@@ -1480,10 +1659,12 @@ Note: does not actually alter the item."
(if (= i (1- (length replacements)))
p-max
(+ p-min (* 2 i) 1))))
+ (overlay-put ovl 'priority 9999)
(overlay-put ovl 'category
'org-drill-replaced-text-overlay)
(overlay-put ovl 'display (nth i replacements)))))
+
(defmacro with-replaced-entry-heading (heading &rest body)
`(progn
(org-drill-replace-entry-heading ,heading)
@@ -1492,18 +1673,21 @@ Note: does not actually alter the item."
,@body)
(org-drill-unhide-text))))
+
(defun org-drill-replace-entry-heading (heading)
"Make an overlay that conceals the heading of the item. The overlay shows
the string TEXT.
Note: does not actually alter the item."
(org-drill-hide-heading-at-point heading))
+
(defun org-drill-unhide-clozed-text ()
(save-excursion
(dolist (ovl (overlays-in (point-min) (point-max)))
(when (eql 'org-drill-cloze-overlay-defaults (overlay-get ovl 'category))
(delete-overlay ovl)))))
+
(defun org-drill-get-entry-text (&optional keep-properties-p)
(let ((text (org-agenda-get-some-entry-text (point-marker) 100)))
(if keep-properties-p
@@ -1526,6 +1710,7 @@ Note: does not actually alter the item."
(defun org-drill-entry-empty-p () (org-entry-empty-p))
+
;;; Presentation functions ====================================================
;;
;; Each of these is called with point on topic heading. Each needs to show the
@@ -1540,12 +1725,14 @@ Note: does not actually alter the item."
(with-hidden-cloze-hints
(with-hidden-cloze-text
(org-drill-hide-all-subheadings-except nil)
+ (org-preview-latex-fragment) ; overlay all LaTeX fragments with images
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
(prog1 (org-drill-presentation-prompt)
(org-drill-hide-subheadings-if 'org-drill-entry-p))))))
+
(defun org-drill-present-default-answer (reschedule-fn)
(cond
(drill-answer
@@ -1557,12 +1744,14 @@ Note: does not actually alter the item."
(t
(org-drill-hide-subheadings-if 'org-drill-entry-p)
(org-drill-unhide-clozed-text)
+ (org-preview-latex-fragment)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
(with-hidden-cloze-hints
(funcall reschedule-fn)))))
+
(defun org-drill-present-two-sided-card ()
(with-hidden-comments
(with-hidden-cloze-hints
@@ -1573,12 +1762,15 @@ Note: does not actually alter the item."
(goto-char (nth (random* (min 2 (length drill-sections)))
drill-sections))
(org-show-subtree)))
+ (org-preview-latex-fragment)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
(prog1 (org-drill-presentation-prompt)
(org-drill-hide-subheadings-if 'org-drill-entry-p)))))))
+
+
(defun org-drill-present-multi-sided-card ()
(with-hidden-comments
(with-hidden-cloze-hints
@@ -1588,12 +1780,14 @@ Note: does not actually alter the item."
(save-excursion
(goto-char (nth (random* (length drill-sections)) drill-sections))
(org-show-subtree)))
+ (org-preview-latex-fragment)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
(prog1 (org-drill-presentation-prompt)
(org-drill-hide-subheadings-if 'org-drill-entry-p)))))))
+
(defun org-drill-present-multicloze-hide-n (number-to-hide
&optional
force-show-first
@@ -1628,7 +1822,8 @@ items if FORCE-SHOW-FIRST or FORCE-SHOW-LAST is non-nil)."
(let ((in-regexp? (save-match-data
(org-pos-in-regexp (match-beginning 0)
org-bracket-link-regexp 1))))
- (unless in-regexp?
+ (unless (or in-regexp?
+ (org-inside-LaTeX-fragment-p))
(incf match-count)))))
(if (minusp number-to-hide)
(setq number-to-hide (+ match-count number-to-hide)))
@@ -1655,8 +1850,9 @@ items if FORCE-SHOW-FIRST or FORCE-SHOW-LAST is non-nil)."
(setq cnt 0)
(while (re-search-forward org-drill-cloze-regexp item-end t)
(unless (save-match-data
- (org-pos-in-regexp (match-beginning 0)
- org-bracket-link-regexp 1))
+ (or (org-pos-in-regexp (match-beginning 0)
+ org-bracket-link-regexp 1)
+ (org-inside-LaTeX-fragment-p)))
(incf cnt)
(if (memq cnt match-nums)
(org-drill-hide-matched-cloze-text)))))))
@@ -1666,6 +1862,7 @@ items if FORCE-SHOW-FIRST or FORCE-SHOW-LAST is non-nil)."
;; while (org-pos-in-regexp (match-beginning 0)
;; org-bracket-link-regexp 1))
;; (org-drill-hide-matched-cloze-text)))))
+ (org-preview-latex-fragment)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
@@ -1673,6 +1870,7 @@ items if FORCE-SHOW-FIRST or FORCE-SHOW-LAST is non-nil)."
(org-drill-hide-subheadings-if 'org-drill-entry-p)
(org-drill-unhide-clozed-text))))))
+
(defun org-drill-present-multicloze-hide-nth (to-hide)
"Hide the TO-HIDE'th piece of clozed text. 1 is the first piece. If
TO-HIDE is negative, count backwards, so -1 means the last item, -2
@@ -1694,7 +1892,8 @@ the second to last, etc."
(let ((in-regexp? (save-match-data
(org-pos-in-regexp (match-beginning 0)
org-bracket-link-regexp 1))))
- (unless in-regexp?
+ (unless (or in-regexp?
+ (org-inside-LaTeX-fragment-p))
(incf match-count)))))
(if (minusp to-hide)
(setq to-hide (+ 1 to-hide match-count)))
@@ -1708,11 +1907,16 @@ the second to last, etc."
(setq cnt 0)
(while (re-search-forward org-drill-cloze-regexp item-end t)
(unless (save-match-data
- (org-pos-in-regexp (match-beginning 0)
- org-bracket-link-regexp 1))
+ ;; Don't consider this a cloze region if it is part of an
+ ;; org link, or if it occurs inside a LaTeX math
+ ;; fragment
+ (or (org-pos-in-regexp (match-beginning 0)
+ org-bracket-link-regexp 1)
+ (org-inside-LaTeX-fragment-p)))
(incf cnt)
(if (= cnt to-hide)
(org-drill-hide-matched-cloze-text)))))))
+ (org-preview-latex-fragment)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
@@ -1720,24 +1924,29 @@ the second to last, etc."
(org-drill-hide-subheadings-if 'org-drill-entry-p)
(org-drill-unhide-clozed-text))))))
+
(defun org-drill-present-multicloze-hide1 ()
"Hides one of the pieces of text that are marked for cloze deletion,
chosen at random."
(org-drill-present-multicloze-hide-n 1))
+
(defun org-drill-present-multicloze-hide2 ()
"Hides two of the pieces of text that are marked for cloze deletion,
chosen at random."
(org-drill-present-multicloze-hide-n 2))
+
(defun org-drill-present-multicloze-hide-first ()
"Hides the first piece of text that is marked for cloze deletion."
(org-drill-present-multicloze-hide-nth 1))
+
(defun org-drill-present-multicloze-hide-last ()
"Hides the last piece of text that is marked for cloze deletion."
(org-drill-present-multicloze-hide-nth -1))
+
(defun org-drill-present-multicloze-hide1-firstmore ()
"Commonly, hides the FIRST piece of text that is marked for
cloze deletion. Uncommonly, hide one of the other pieces of text,
@@ -1767,6 +1976,7 @@ the value of `org-drill-cloze-text-weight'."
;; Commonly, hide first item
(org-drill-present-multicloze-hide-first))))
+
(defun org-drill-present-multicloze-show1-lastmore ()
"Commonly, hides all pieces except the last. Uncommonly, shows
any random piece. The effect is similar to 'show1cloze' except
@@ -1791,6 +2001,7 @@ the value of `org-drill-cloze-text-weight'."
;; Commonly, show the LAST item
(org-drill-present-multicloze-hide-n -1 nil t))))
+
(defun org-drill-present-multicloze-show1-firstless ()
"Commonly, hides all pieces except one, where the shown piece
is guaranteed NOT to be the first piece. Uncommonly, shows any
@@ -1816,49 +2027,19 @@ the value of `org-drill-cloze-text-weight'."
;; Commonly, show any item, except the first
(org-drill-present-multicloze-hide-n -1 nil nil t))))
+
(defun org-drill-present-multicloze-show1 ()
"Similar to `org-drill-present-multicloze-hide1', but hides all
the pieces of text that are marked for cloze deletion, except for one
piece which is chosen at random."
(org-drill-present-multicloze-hide-n -1))
+
(defun org-drill-present-multicloze-show2 ()
"Similar to `org-drill-present-multicloze-show1', but reveals two
pieces rather than one."
(org-drill-present-multicloze-hide-n -2))
-;; (defun org-drill-present-multicloze-show1 ()
-;; "Similar to `org-drill-present-multicloze-hide1', but hides all
-;; the pieces of text that are marked for cloze deletion, except for one
-;; piece which is chosen at random."
-;; (with-hidden-comments
-;; (with-hidden-cloze-hints
-;; (let ((item-end nil)
-;; (match-count 0)
-;; (body-start (or (cdr (org-get-property-block))
-;; (point))))
-;; (org-drill-hide-all-subheadings-except nil)
-;; (save-excursion
-;; (outline-next-heading)
-;; (setq item-end (point)))
-;; (save-excursion
-;; (goto-char body-start)
-;; (while (re-search-forward org-drill-cloze-regexp item-end t)
-;; (incf match-count)))
-;; (when (plusp match-count)
-;; (let ((match-to-hide (random* match-count)))
-;; (save-excursion
-;; (goto-char body-start)
-;; (dotimes (n match-count)
-;; (re-search-forward org-drill-cloze-regexp
-;; item-end t)
-;; (unless (= n match-to-hide)
-;; (org-drill-hide-matched-cloze-text))))))
-;; (org-display-inline-images t)
-;; (org-cycle-hide-drawers 'all)
-;; (prog1 (org-drill-presentation-prompt)
-;; (org-drill-hide-subheadings-if 'org-drill-entry-p)
-;; (org-drill-unhide-clozed-text))))))
(defun org-drill-present-card-using-text (question &optional answer)
"Present the string QUESTION as the only visible content of the card.
@@ -1874,6 +2055,7 @@ If ANSWER is supplied, set the global variable `drill-answer' to its value."
(prog1 (org-drill-presentation-prompt)
(org-drill-hide-subheadings-if 'org-drill-entry-p)))))
+
(defun org-drill-present-card-using-multiple-overlays (replacements &optional answer)
"TEXTS is a list of valid values for the 'display' text property.
Present these overlays, in sequence, as the only
@@ -1890,6 +2072,7 @@ If ANSWER is supplied, set the global variable `drill-answer' to its value."
(prog1 (org-drill-presentation-prompt)
(org-drill-hide-subheadings-if 'org-drill-entry-p)))))
+
(defun org-drill-entry ()
"Present the current topic for interactive review, as in `org-drill'.
Review will occur regardless of whether the topic is due for review or whether
@@ -1907,7 +2090,7 @@ See `org-drill' for more details."
;; (error "Point is not inside a drill entry"))
;;(unless (org-at-heading-p)
;; (org-back-to-heading))
- (let ((card-type (org-entry-get (point) "DRILL_CARD_TYPE"))
+ (let ((card-type (org-entry-get (point) "DRILL_CARD_TYPE" t))
(answer-fn 'org-drill-present-default-answer)
(present-empty-cards nil)
(cont nil)
@@ -1949,6 +2132,7 @@ See `org-drill' for more details."
(funcall answer-fn
(lambda () (org-drill-reschedule)))))))))))))
+
(defun org-drill-entries-pending-p ()
(or *org-drill-again-entries*
*org-drill-current-item*
@@ -1961,6 +2145,7 @@ See `org-drill' for more details."
*org-drill-overdue-entries*
*org-drill-again-entries*))))
+
(defun org-drill-pending-entry-count ()
(+ (if (markerp *org-drill-current-item*) 1 0)
(length *org-drill-new-entries*)
@@ -1970,6 +2155,7 @@ See `org-drill' for more details."
(length *org-drill-overdue-entries*)
(length *org-drill-again-entries*)))
+
(defun org-drill-maximum-duration-reached-p ()
"Returns true if the current drill session has continued past its
maximum duration."
@@ -1979,6 +2165,7 @@ maximum duration."
(> (- (float-time (current-time)) *org-drill-start-time*)
(* org-drill-maximum-duration 60))))
+
(defun org-drill-maximum-item-count-reached-p ()
"Returns true if the current drill session has reached the
maximum number of items."
@@ -1987,6 +2174,7 @@ maximum number of items."
(>= (length *org-drill-done-entries*)
org-drill-maximum-items-per-session)))
+
(defun org-drill-pop-next-pending-entry ()
(block org-drill-pop-next-pending-entry
(let ((m nil))
@@ -2034,6 +2222,7 @@ maximum number of items."
(return-from org-drill-pop-next-pending-entry nil)))))
m)))
+
(defun org-drill-entries (&optional resuming-p)
"Returns nil, t, or a list of markers representing entries that were
'failed' and need to be presented again before the session ends.
@@ -2086,6 +2275,8 @@ RESUMING-P is true if we are resuming a suspended drill session."
(push m *org-drill-done-entries*)))
(setq *org-drill-current-item* nil))))))))))
+
+
(defun org-drill-final-report ()
(let ((pass-percent
(round (* 100 (count-if (lambda (qual)
@@ -2172,7 +2363,10 @@ order to make items appear more frequently over time."
*org-drill-overdue-entry-count*
(round (* 100 *org-drill-overdue-entry-count*)
(+ *org-drill-dormant-entry-count*
- *org-drill-due-entry-count*)))))))
+ *org-drill-due-entry-count*)))
+ ))))
+
+
(defun org-drill-free-markers (markers)
"MARKERS is a list of markers, all of which will be freed (set to
@@ -2268,7 +2462,7 @@ one of the following values:
sym1)))))
-(defun org-drill (&optional scope resume-p)
+(defun org-drill (&optional scope drill-match resume-p)
"Begin an interactive 'drill session'. The user is asked to
review a series of topics (headers). Each topic is initially
presented as a 'question', often with part of the topic content
@@ -2296,10 +2490,24 @@ SCOPE determines the scope in which to search for
questions. It accepts the same values as `org-drill-scope',
which see.
+DRILL-MATCH, if supplied, is a string specifying a tags/property/
+todo query. Only items matching the query will be considered.
+It accepts the same values as `org-drill-match', which see.
+
If RESUME-P is non-nil, resume a suspended drill session rather
than starting a new one."
(interactive)
+ ;; Check org version. Org 7.9.3f introduced a backwards-incompatible change
+ ;; to the arguments accepted by `org-schedule'. At the time of writing there
+ ;; are still lots of people using versions of org older than this.
+ (let ((majorv (first (mapcar 'string-to-number (split-string (org-release) "[.]")))))
+ (if (and (< majorv 8)
+ (not (string-match-p "universal prefix argument" (documentation 'org-schedule))))
+ (read-char-exclusive
+ (format "Warning: org-drill requires org mode 7.9.3f or newer. Scheduling of failed cards will not
+work correctly with older versions of org mode. Your org mode version (%s) appears to be older than
+7.9.3f. Please consider installing a more recent version of org mode." (org-release)))))
(let ((end-pos nil)
(overdue-data nil)
(cnt 0))
@@ -2368,7 +2576,7 @@ than starting a new one."
(:old
(push (point-marker) *org-drill-old-mature-entries*))
)))))
- scope)
+ scope drill-match)
(org-drill-order-overdue-entries overdue-data)
(setq *org-drill-overdue-entry-count*
(length *org-drill-overdue-entries*))))
@@ -2405,7 +2613,8 @@ than starting a new one."
(org-drill-save-optimal-factor-matrix))
(if org-drill-save-buffers-after-drill-sessions-p
(save-some-buffers))
- (message "Drill session finished!")))))
+ (message "Drill session finished!")
+ ))))
(defun org-drill-save-optimal-factor-matrix ()
@@ -2414,14 +2623,14 @@ than starting a new one."
org-drill-optimal-factor-matrix))
-(defun org-drill-cram (&optional scope)
+(defun org-drill-cram (&optional scope drill-match)
"Run an interactive drill session in 'cram mode'. In cram mode,
all drill items are considered to be due for review, unless they
have been reviewed within the last `org-drill-cram-hours'
hours."
(interactive)
(setq *org-drill-cram-mode* t)
- (org-drill scope))
+ (org-drill scope drill-match))
(defun org-drill-tree ()
@@ -2438,7 +2647,7 @@ files in the same directory as the current file."
(org-drill 'directory))
-(defun org-drill-again (&optional scope)
+(defun org-drill-again (&optional scope drill-match)
"Run a new drill session, but try to use leftover due items that
were not reviewed during the last session, rather than scanning for
unreviewed items. If there are no leftover items in memory, a full
@@ -2453,9 +2662,9 @@ scan will be performed."
(setq *org-drill-start-time* (float-time (current-time))
*org-drill-done-entries* nil
*org-drill-current-item* nil)
- (org-drill scope t))
+ (org-drill scope drill-match t))
(t
- (org-drill scope))))
+ (org-drill scope drill-match))))
@@ -2465,7 +2674,7 @@ exiting them with the `edit' or `quit' options."
(interactive)
(cond
((org-drill-entries-pending-p)
- (org-drill nil t))
+ (org-drill nil nil t))
((and (plusp (org-drill-pending-entry-count))
;; Current drill session is finished, but there are still
;; more items which need to be reviewed.
@@ -2478,10 +2687,18 @@ need reviewing. Start a new drill session? "
(message "You have finished the drill session."))))
+(defun org-drill-relearn-item ()
+ "Make the current item due for revision, and set its last interval to 0.
+Makes the item behave as if it has been failed, without actually recording a
+failure. This command can be used to 'reset' repetitions for an item."
+ (interactive)
+ (org-drill-smart-reschedule 4 0))
+
+
(defun org-drill-strip-entry-data ()
(dolist (prop org-drill-scheduling-properties)
(org-delete-property prop))
- (org-schedule t))
+ (org-schedule '(4)))
(defun org-drill-strip-all-data (&optional scope)
@@ -2499,22 +2716,42 @@ values as `org-drill-scope'."
;; `org-delete-property-globally', which is faster.
(dolist (prop org-drill-scheduling-properties)
(org-delete-property-globally prop))
- (org-map-drill-entries (lambda () (org-schedule t)) scope))
+ (org-map-drill-entries (lambda () (org-schedule '(4))) scope))
(t
(org-map-drill-entries 'org-drill-strip-entry-data scope)))
(message "Done.")))
-
(defun org-drill-add-cloze-fontification ()
+ ;; Compute local versions of the regexp for cloze deletions, in case
+ ;; the left and right delimiters are redefined locally.
+ (setq-local org-drill-cloze-regexp (org-drill--compute-cloze-regexp))
+ (setq-local org-drill-cloze-keywords (org-drill--compute-cloze-keywords))
(when org-drill-use-visible-cloze-face-p
- (font-lock-add-keywords 'org-mode
- org-drill-cloze-keywords
- nil)))
-
-(add-hook 'org-mode-hook 'org-drill-add-cloze-fontification)
-
-(org-drill-add-cloze-fontification)
+ (add-to-list 'org-font-lock-extra-keywords
+ (first org-drill-cloze-keywords))))
+
+(add-hook 'org-font-lock-set-keywords-hook 'org-drill-add-cloze-fontification)
+
+;; Can't add to org-mode-hook, because local variables won't have been loaded
+;; yet.
+
+;; (defun org-drill-add-cloze-fontification ()
+;; (when (eql major-mode 'org-mode)
+;; ;; Compute local versions of the regexp for cloze deletions, in case
+;; ;; the left and right delimiters are redefined locally.
+;; (setq-local org-drill-cloze-regexp (org-drill--compute-cloze-regexp))
+;; (setq-local org-drill-cloze-keywords (org-drill--compute-cloze-keywords))
+;; (when org-drill-use-visible-cloze-face-p
+;; (font-lock-add-keywords nil ;'org-mode
+;; org-drill-cloze-keywords
+;; nil))))
+
+;; XXX
+;; (add-hook 'hack-local-variables-hook
+;; 'org-drill-add-cloze-fontification)
+;;
+;; (org-drill-add-cloze-fontification)
;;; Synching card collections =================================================
@@ -2530,18 +2767,18 @@ the tag 'imported'."
(save-excursion
(let ((src (current-buffer))
(m nil))
- (flet ((paste-tree-here (&optional level)
- (org-paste-subtree level)
- (org-drill-strip-entry-data)
- (org-toggle-tag "imported" 'on)
- (org-map-drill-entries
- (lambda ()
- (let ((id (org-id-get)))
- (org-drill-strip-entry-data)
- (unless (gethash id *org-drill-dest-id-table*)
- (puthash id (point-marker)
- *org-drill-dest-id-table*))))
- 'tree)))
+ (cl-flet ((paste-tree-here (&optional level)
+ (org-paste-subtree level)
+ (org-drill-strip-entry-data)
+ (org-toggle-tag "imported" 'on)
+ (org-map-drill-entries
+ (lambda ()
+ (let ((id (org-id-get)))
+ (org-drill-strip-entry-data)
+ (unless (gethash id *org-drill-dest-id-table*)
+ (puthash id (point-marker)
+ *org-drill-dest-id-table*))))
+ 'tree)))
(unless path
(setq path (org-get-outline-path)))
(org-copy-subtree)
@@ -2565,7 +2802,9 @@ the tag 'imported'."
(outline-next-heading)
(newline)
(forward-line -1)
- (paste-tree-here (1+ (or (org-current-level) 0))))))))
+ (paste-tree-here (1+ (or (org-current-level) 0)))
+ )))))
+
(defun org-drill-merge-buffers (src &optional dest ignore-new-items-p)
@@ -2658,12 +2897,15 @@ copy them across."
(free-marker m))
*org-drill-dest-id-table*))))
+
+
;;; Card types for learning languages =========================================
;;; Get spell-number.el from:
;;; http://www.emacswiki.org/emacs/spell-number.el
(autoload 'spelln-integer-in-words "spell-number")
+
;;; `conjugate' card type =====================================================
;;; See spanish.org for usage
@@ -2726,15 +2968,15 @@ the name of the tense.")
(defun org-drill-present-verb-conjugation ()
"Present a drill entry whose card type is 'conjugate'."
- (flet ((tense-and-mood-to-string
- (tense mood)
- (cond
- ((and tense mood)
- (format "%s tense, %s mood" tense mood))
- (tense
- (format "%s tense" tense))
- (mood
- (format "%s mood" mood)))))
+ (cl-flet ((tense-and-mood-to-string
+ (tense mood)
+ (cond
+ ((and tense mood)
+ (format "%s tense, %s mood" tense mood))
+ (tense
+ (format "%s tense" tense))
+ (mood
+ (format "%s mood" mood)))))
(destructuring-bind (infinitive inf-hint translation tense mood)
(org-drill-get-verb-conjugation-info)
(org-drill-present-card-using-text
@@ -2915,6 +3157,7 @@ returns its return value."
'face highlight-face))
(spelln-integer-in-language drilled-number language))))))))
+
;; (defun org-drill-show-answer-translate-number (reschedule-fn)
;; (let* ((language (read (org-entry-get (point) "DRILL_LANGUAGE" t)))
;; (highlight-face 'font-lock-warning-face)
diff --git a/contrib/lisp/org-ebib.el b/contrib/lisp/org-ebib.el
new file mode 100644
index 0000000..2136a13
--- a/dev/null
+++ b/contrib/lisp/org-ebib.el
@@ -0,0 +1,47 @@
+;;; org-ebib.el - Support for links to Ebib's entries in Org
+;;
+;; Author: Grégoire Jadi <daimrod@gmail.com>
+;;
+;; This file is not yet part of GNU Emacs.
+;;
+;; This program 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,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+
+(require 'org)
+
+(org-add-link-type "ebib" 'org-ebib-open)
+
+(add-hook 'org-store-link-functions 'org-ebib-store-link)
+
+(defun org-ebib-open (key)
+ "Open Ebib and jump to KEY."
+ (ebib nil key))
+
+(defun org-ebib-store-link ()
+ "Store a key to an Ebib entry."
+ (when (memq major-mode '(ebib-index-mode ebib-entry-mode))
+ ;; This is an Ebib entry
+ (let* ((key (ebib-cur-entry-key))
+ (link (concat "ebib:" key))
+ (description (ignore-errors (ebib-db-get-field-value 'title key ebib-cur-db))))
+ (org-store-link-props
+ :type "ebib"
+ :link link
+ :description description))))
+
+(provide 'org-ebib)
+
+;;; org-ebib.el ends here
diff --git a/contrib/lisp/org-effectiveness.el b/contrib/lisp/org-effectiveness.el
new file mode 100644
index 0000000..1e80d1f
--- a/dev/null
+++ b/contrib/lisp/org-effectiveness.el
@@ -0,0 +1,288 @@
+;;; org-effectiveness.el --- Measuring the personal effectiveness
+
+;; Copyright (C) 2013 Free Software Foundation, Inc.
+
+;; Author: David Arroyo Menéndez <davidam@es.gnu.org>
+;; Keywords: effectiveness, plot
+;; Homepage: http://orgmode.org
+;;
+;; This file is not part of GNU Emacs, yet.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+
+;; This file implements functions to measure the effectiveness in org.
+;; Org-mode doesn't load this module by default - if this is not what
+;; you want, configure the variable `org-modules'. Thanks to #emacs-es
+;; irc channel for your support.
+
+;;; Code:
+
+(require 'org)
+
+(defcustom org-effectiveness-max-todo 50
+ "This variable is useful to advice to the user about
+many TODO pending"
+ :type 'integer
+ :group 'org-effectiveness)
+
+(defun org-effectiveness-advice()
+ "Advicing about a possible excess of TODOS"
+ (interactive)
+ (goto-char (point-min))
+ (if (< org-effectiveness-max-todo (count-matches "* TODO"))
+ (message "An excess of TODOS!")))
+
+;; Check advice starting an org file
+(add-hook 'org-mode-hook 'org-effectiveness-advice)
+
+(defun org-effectiveness-count-keyword(keyword)
+ "Print a message with the number of keyword outline in the current buffer"
+ (interactive "sKeyword: ")
+ (save-excursion
+ (goto-char (point-min))
+ (message "Number of %s: %d" keyword (count-matches (concat "* " keyword)))))
+
+(defun org-effectiveness-count-todo()
+ "Print a message with the number of todo tasks in the current buffer"
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (message "Number of TODO: %d" (count-matches "* TODO"))))
+
+(defun org-effectiveness-count-done()
+ "Print a message with the number of done tasks in the current buffer"
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (message "Number of DONE: %d" (count-matches "* DONE"))))
+
+(defun org-effectiveness-count-canceled()
+ "Print a message with the number of canceled tasks in the current buffer"
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (message "Number of Canceled: %d" (count-matches "* CANCEL+ED"))))
+
+(defun org-effectiveness()
+ "Returns the effectiveness in the current org buffer"
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (let ((done (float (count-matches "* DONE.*\n.*")))
+ (canc (float (count-matches "* CANCEL+ED.*\n.*"))))
+ (if (and (= done canc) (zerop done))
+ (setq effectiveness 0)
+ (setq effectiveness (* 100 (/ done (+ done canc)))))
+ (message "Effectiveness: %f" effectiveness))))
+
+(defun org-effectiveness-keywords-in-date(keyword date)
+ (interactive "sKeyword: \nsDate: " keyword date)
+ (setq count (count-matches (concat keyword ".*\n.*" date)))
+ (message (concat "%sS: %d" keyword count)))
+
+(defun org-effectiveness-dones-in-date(date)
+ (interactive "sGive me a date: " date)
+ (setq count (count-matches (concat "DONE.*\n.*" date)))
+ (message "DONES: %d" count))
+
+(defun org-effectivenes-todos-in-date(date)
+ (interactive "sGive me a date: " date)
+ (setq count (count-matches (concat "TODO.*\n.*" date)))
+ (message "TODOS: %d" count))
+
+(defun org-effectiveness-canceled-in-date(date)
+ (interactive "sGive me a date: " date)
+ (setq count (count-matches (concat "CANCEL+ED.*\n.*" date)))
+ (message "CANCELEDS: %d" count))
+
+(defun org-effectiveness-in-date(date &optional notmessage)
+ (interactive "sGive me a date: " date)
+ (save-excursion
+ (goto-char (point-min))
+ (let ((done (float (count-matches (concat "* DONE.*\n.*" date))))
+ (canc (float (count-matches (concat "* CANCEL+ED.*\n.*" date)))))
+ (if (and (= done canc) (zerop done))
+ (setq effectiveness 0)
+ (setq effectiveness (* 100 (/ done (+ done canc)))))
+ (if (eq notmessage 1)
+ (message "%d" effectiveness)
+ (message "Effectiveness: %d " effectiveness)))))
+
+(defun org-effectiveness-month-to-string (m)
+ (if (< m 10)
+ (concat "0" (number-to-string m))
+ (number-to-string m)))
+
+(defun org-effectiveness-plot(startdate enddate)
+ (interactive "sGive me the start date: \nsGive me the end date: " startdate enddate)
+ (setq dates (org-effectiveness-check-dates startdate enddate))
+ (setq syear (cadr (assoc 'startyear dates)))
+ (setq smonth (cadr (assoc 'startmonth dates)))
+ (setq eyear (cadr (assoc 'endyear dates)))
+ (setq emonth (assoc 'endmonth dates))
+;; Checking the format of the dates
+ (if (not (string-match "[0-9][0-9][0-9][0-9]-[0-9][0-9]" startdate))
+ (message "The start date must have the next format YYYY-MM"))
+ (if (not (string-match "[0-9][0-9][0-9][0-9]-[0-9][0-9]" enddate))
+ (message "The end date must have the next format YYYY-MM"))
+;; Checking if startdate < enddate
+ (if (string-match "^[0-9][0-9][0-9][0-9]" startdate)
+ (setq startyear (string-to-number (match-string 0 startdate))))
+ (if (string-match "[0-9][0-9]$" startdate)
+ (setq startmonth (string-to-number (match-string 0 startdate))))
+ (if (string-match "^[0-9][0-9][0-9][0-9]" enddate)
+ (setq endyear (string-to-number (match-string 0 enddate))))
+ (if (string-match "[0-9][0-9]$" enddate)
+ (setq endmonth (string-to-number (match-string 0 enddate))))
+ (if (> startyear endyear)
+ (message "The start date must be before that end date"))
+ (if (and (= startyear endyear) (> startmonth endmonth))
+ (message "The start date must be before that end date"))
+;; Create a file
+ (let ((month startmonth)
+ (year startyear)
+ (str ""))
+ (while (or (> endyear year) (and (= endyear year) (>= endmonth month)))
+ (setq str (concat str (number-to-string year) "-" (org-effectiveness-month-to-string month) " " (org-effectiveness-in-date (concat (number-to-string year) "-" (org-effectiveness-month-to-string month)) 1) "\n"))
+ (if (= month 12)
+ (progn
+ (setq year (+ 1 year))
+ (setq month 1))
+ (setq month (+ 1 month))))
+ (write-region str nil "/tmp/org-effectiveness"))
+;; Create the bar graph
+ (if (file-exists-p "/usr/bin/gnuplot")
+ (call-process "/bin/bash" nil t nil "-c" "/usr/bin/gnuplot -e 'plot \"/tmp/org-effectiveness\" using 2:xticlabels(1) with histograms' -p")
+ (message "gnuplot is not installed")))
+
+(defun org-effectiveness-ascii-bar(n &optional label)
+ "Print a bar with the percentage from 0 to 100 printed in ascii"
+ (interactive "nPercentage: \nsLabel: ")
+ (if (or (< n 0) (> n 100))
+ (message "The percentage must be between 0 to 100")
+ (let ((x 0)
+ (y 0)
+ (z 0))
+ (insert (format "\n### %s ###" label))
+ (insert "\n-")
+ (while (< x n)
+ (insert "-")
+ (setq x (+ x 1)))
+ (insert "+\n")
+ (insert (format "%d" n))
+ (if (> n 10)
+ (setq y (+ y 1)))
+ (while (< y n)
+ (insert " ")
+ (setq y (+ y 1)))
+ (insert "|\n")
+ (insert "-")
+ (while (< z n)
+ (insert "-")
+ (setq z (+ z 1)))
+ (insert "+"))))
+
+(defun org-effectiveness-html-bar(n &optional label)
+ "Print a bar with the percentage from 0 to 100 printed in html"
+ (interactive "nPercentage: \nsLabel: ")
+ (if (or (< n 0) (> n 100))
+ (message "The percentage must be between 0 to 100")
+ (let ((x 0)
+ (y 0)
+ (z 0))
+ (insert (format "\n<div class='percentage-%d'>%d</div>" n n))
+)))
+
+
+(defun org-effectiveness-check-dates (startdate enddate)
+ "Generate a list with ((startyear startmonth) (endyear endmonth))"
+ (setq str nil)
+ (if (not (string-match "[0-9][0-9][0-9][0-9]-[0-9][0-9]" startdate))
+ (setq str "The start date must have the next format YYYY-MM"))
+ (if (not (string-match "[0-9][0-9][0-9][0-9]-[0-9][0-9]" enddate))
+ (setq str "The end date must have the next format YYYY-MM"))
+;; Checking if startdate < enddate
+ (if (string-match "^[0-9][0-9][0-9][0-9]" startdate)
+ (setq startyear (string-to-number (match-string 0 startdate))))
+ (if (string-match "[0-9][0-9]$" startdate)
+ (setq startmonth (string-to-number (match-string 0 startdate))))
+ (if (string-match "^[0-9][0-9][0-9][0-9]" enddate)
+ (setq endyear (string-to-number (match-string 0 enddate))))
+ (if (string-match "[0-9][0-9]$" enddate)
+ (setq endmonth (string-to-number (match-string 0 enddate))))
+ (if (> startyear endyear)
+ (setq str "The start date must be before that end date"))
+ (if (and (= startyear endyear) (> startmonth endmonth))
+ (setq str "The start date must be before that end date"))
+ (if str
+ (message str)
+;; (list (list startyear startmonth) (list endyear endmonth))))
+ (list (list 'startyear startyear) (list 'startmonth startmonth) (list 'endyear endyear) (list 'endmonth endmonth))))
+
+(defun org-effectiveness-plot-ascii (startdate enddate)
+ (interactive "sGive me the start date: \nsGive me the end date: " startdate enddate)
+ (setq dates (org-effectiveness-check-dates startdate enddate))
+ (let ((syear (cadr (assoc 'startyear dates)))
+ (smonth (cadr (assoc 'startmonth dates)))
+ (year (cadr (assoc 'startyear dates)))
+ (month (cadr (assoc 'startmonth dates)))
+ (emonth (cadr (assoc 'endmonth dates)))
+ (eyear (cadr (assoc 'endyear dates)))
+ (buffer (current-buffer))
+ (str ""))
+ (while (or (> eyear year) (and (= eyear year) (>= emonth month)))
+ (setq str (org-effectiveness-in-date (concat (number-to-string year) "-" (org-effectiveness-month-to-string month)) 1))
+ (switch-to-buffer "*org-effectiveness*")
+ (org-effectiveness-ascii-bar (string-to-number str) (format "%s-%s" year month))
+ (switch-to-buffer buffer)
+ (if (eq month 12)
+ (progn
+ (setq year (+ 1 year))
+ (setq month 1))
+ (setq month (+ 1 month)))))
+ (switch-to-buffer "*org-effectiveness*"))
+
+(defun org-effectiveness-plot-html (startdate enddate)
+ "Print html bars about the effectiveness in a buffer"
+ (interactive "sGive me the start date: \nsGive me the end date: " startdate enddate)
+ (setq dates (org-effectiveness-check-dates startdate enddate))
+ (let ((syear (cadr (assoc 'startyear dates)))
+ (smonth (cadr (assoc 'startmonth dates)))
+ (year (cadr (assoc 'startyear dates)))
+ (month (cadr (assoc 'startmonth dates)))
+ (emonth (cadr (assoc 'endmonth dates)))
+ (eyear (cadr (assoc 'endyear dates)))
+ (buffer (current-buffer))
+ (str ""))
+ (switch-to-buffer "*org-effectiveness-html*")
+ (insert "<html><head><title>Graphbar</title><meta http-equiv='Content-type' content='text/html; charset=utf-8'><link rel='stylesheet' type='text/css' href='graphbar.css' title='graphbar'></head><body>")
+ (while (or (> eyear year) (and (= eyear year) (>= emonth month)))
+ (setq str (org-effectiveness-in-date (concat (number-to-string year) "-" (org-effectiveness-month-to-string month)) 1))
+ (switch-to-buffer "*org-effectiveness-html*")
+ (org-effectiveness-html-bar (string-to-number str) (format "%s-%s" year month))
+ (switch-to-buffer buffer)
+ (format "%s-%s" year month)
+ (if (eq month 12)
+ (progn
+ (setq year (+ 1 year))
+ (setq month 1))
+ (setq month (+ 1 month))))
+ (switch-to-buffer "*org-effectiveness-html*")
+ (insert "</body></html>")))
+
+(provide 'org-effectiveness)
+
diff --git a/contrib/lisp/org-elisp-symbol.el b/contrib/lisp/org-elisp-symbol.el
index e0bc284..167731e 100644
--- a/contrib/lisp/org-elisp-symbol.el
+++ b/contrib/lisp/org-elisp-symbol.el
@@ -1,6 +1,6 @@
;;; org-elisp-symbol.el --- Org links to emacs-lisp symbols
;;
-;; Copyright 2007-2013 Free Software Foundation, Inc.
+;; Copyright 2007-2014 Free Software Foundation, Inc.
;;
;; Author: Bastien Guerry
;; Version: 0.2
diff --git a/contrib/lisp/org-eval-light.el b/contrib/lisp/org-eval-light.el
index 34a2e99..872f3a4 100644
--- a/contrib/lisp/org-eval-light.el
+++ b/contrib/lisp/org-eval-light.el
@@ -1,6 +1,6 @@
;;; org-eval-light.el --- Display result of evaluating code in various languages (light)
-;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten at orgmode dot org>,
;; Eric Schulte <schulte dot eric at gmail dot com>
diff --git a/contrib/lisp/org-eval.el b/contrib/lisp/org-eval.el
index 6cd7f78..cb5620c 100644
--- a/contrib/lisp/org-eval.el
+++ b/contrib/lisp/org-eval.el
@@ -1,5 +1,5 @@
;;; org-eval.el --- Display result of evaluating code in various languages
-;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
diff --git a/contrib/lisp/org-expiry.el b/contrib/lisp/org-expiry.el
index 363bebe..1506c3b 100644
--- a/contrib/lisp/org-expiry.el
+++ b/contrib/lisp/org-expiry.el
@@ -1,6 +1,6 @@
;;; org-expiry.el --- expiry mechanism for Org entries
;;
-;; Copyright 2007-2013 Free Software Foundation, Inc.
+;; Copyright 2007-2014 Free Software Foundation, Inc.
;;
;; Author: Bastien Guerry
;; Version: 0.2
@@ -218,11 +218,12 @@ Return nil if the entry is not expired. Otherwise return the
amount of time between today and the expiry date.
If there is no creation date, use `org-expiry-created-date'.
-If there is no expiry date, use `org-expiry-expiry-date'."
+If there is no expiry date, use `org-expiry-wait'."
(let* ((ex-prop org-expiry-expiry-property-name)
(cr-prop org-expiry-created-property-name)
(ct (current-time))
- (cr (org-read-date nil t (or (org-entry-get (point) cr-prop t) "+0d")))
+ (cr (org-read-date nil t (or (org-entry-get (point) cr-prop t)
+ org-expiry-created-date)))
(ex-field (or (org-entry-get (point) ex-prop t) org-expiry-wait))
(ex (if (string-match "^[ \t]?[+-]" ex-field)
(time-add cr (time-subtract (org-read-date nil t ex-field) ct))
diff --git a/contrib/lisp/org-favtable.el b/contrib/lisp/org-favtable.el
deleted file mode 100755
index 51f75a5..0000000
--- a/contrib/lisp/org-favtable.el
+++ b/dev/null
@@ -1,1701 +0,0 @@
-;;; org-favtable.el --- Lookup table of favorite references and links
-
-;; Copyright (C) 2011-2013 Free Software Foundation, Inc.
-
-;; Author: Marc-Oliver Ihm <org-favtable@ferntreffer.de>
-;; Keywords: hypermedia, matching
-;; Requires: org
-;; Download: http://orgmode.org/worg/code/elisp/org-favtable.el
-;; Version: 2.2.0
-
-;; This file is not part of GNU Emacs.
-
-;;; License:
-
-;; This program 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,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Purpose:
-;;
-;; Mark and find your favorite things and locations in org easily: Create
-;; and update a lookup table of your references and links. Often used
-;; entries bubble to the top and entering some keywords displays only the
-;; matching entries. That way the right entry one can be picked easily.
-;;
-;; References are essentially small numbers (e.g. "R237" or "-455-"),
-;; which are created by this package; they are well suited to be used
-;; outside of org. Links are just normal org-mode links.
-;;
-;;
-;; Setup:
-;;
-;; - Add these lines to your .emacs:
-;;
-;; (require 'org-favtable)
-;; ;; Good enough to start, but later you should probably
-;; ;; change this id, as will be explained below
-;; (setq org-favtable-id "00e26bef-1929-4110-b8b4-7eb9c9ab1fd4")
-;; ;; Optionally assign a key. Pick your own favorite.
-;; (global-set-key (kbd "C-+") 'org-favtable)
-;;
-;; - Just invoke `org-favtable', which will explain how to complete your
-;; setup by creating the necessary table of favorites.
-;;
-;;
-;; Further reading:
-;;
-;; Invoke `org-favtable' and pick one of its help options. You may also
-;; read the documentation of `org-favtable-id' for setup instructions, of
-;; `org-favtable' for regular usage and of `org-favtable--commands' for a
-;; list of available commands.
-;;
-
-;;; Change Log:
-
-;; [2013-02-28 Th] Version 2.2.0:
-;; - Allowed shortcuts like "h237" for command "head" with argument "237"
-;; - Integrated with org-mark-ring-goto
-;;
-;; [2013-01-25 Fr] Version 2.1.0:
-;; - Added full support for links
-;; - New commands "missing" and "statistics"
-;; - Renamed the package from "org-reftable" to "org-favtable"
-;; - Additional columns are required (e.g. "link"). Error messages will
-;; guide you
-;;
-;; [2012-12-07 Fr] Version 2.0.0:
-;; - The format of the table of favorites has changed ! You need to bring
-;; your existing table into the new format by hand (which however is
-;; easy and explained below)
-;; - Reference table can be sorted after usage count or date of last access
-;; - Ask user explicitly, which command to invoke
-;; - Renamed the package from "org-refer-by-number" to "org-reftable"
-
-;; [2012-09-22 Sa] Version 1.5.0:
-;; - New command "sort" to sort a buffer or region by reference number
-;; - New commands "highlight" and "unhighlight" to mark references
-
-;; [2012-07-13 Fr] Version 1.4.0:
-;; - New command "head" to find a headline with a reference number
-
-;; [2012-04-28 Sa] Version 1.3.0:
-;; - New commands occur and multi-occur
-;; - All commands can now be invoked explicitly
-;; - New documentation
-;; - Many bugfixes
-
-;; [2011-12-10 Sa] Version 1.2.0:
-;; - Fixed a bug, which lead to a loss of newly created reference numbers
-;; - Introduced single and double prefix arguments
-;; - Started this Change Log
-
-;;; Code:
-
-(require 'org-table)
-(require 'cl)
-
-(defvar org-favtable--version "2.2.0")
-(defvar org-favtable--preferred-command nil)
-
-(defvar org-favtable--commands '(occur head ref link enter leave goto + help reorder fill sort update highlight unhighlight missing statistics)
- "List of commands known to org-favtable:
-
-Commands known:
-
- occur: If you supply a keyword (text): Apply emacs standard
- occur operation on the table of favorites; ask for a
- string (keyword) to select lines. Occur will only show you
- lines which contain the given keyword, so you can easily find
- the right one. You may supply a list of words seperated by
- comma (\",\"), to select lines that contain any or all of the
- given words.
-
- If you supply a reference number: Apply emacs standard
- multi-occur operation all org-mode buffers to search for a
- specific reference.
-
- You may also read the note at the end of this help on saving
- the keystroke RET to accept this frequent default command.
-
- head: If invoked outside the table of favorites, ask for a
- reference number and search for a heading containing it. If
- invoked within favtable dont ask; rather use the reference or
- link from the current line.
-
- ref: Create a new reference, copy any previously selected text.
- If already within reftable, fill in ref-column.
-
- link: Create a new line in reftable with a link to the current node.
- Do not populate the ref column; this can later be populated by
- calling the \"fill\" command from within the reftable.
-
- leave: Leave the table of favorites. If the last command has
- been \"ref\", the new reference is copied and ready to yank.
- This \"org-mark-ring-goto\" and can be called several times
- in succession.
-
- enter: Just enter the node with the table of favorites.
-
- goto: Search for a specific reference within the table of
- favorites.
-
- help: Show this list of commands.
-
- +: Show all commands including the less frequently used ones
- given below. If \"+\" is followd by enough letters of such a
- command (e.g. \"+fi\"), then this command is invoked
- directly.
-
- reorder: Temporarily reorder the table of favorites, e.g. by
- count, reference or last access.
-
- fill: If either ref or link is missing, fill it.
-
- sort: Sort a set of lines (either the active region or the
- whole buffer) by the references found in each line.
-
- update: For the given reference, update the line in the
- favtable.
-
- highlight: Highlight references in region or buffer.
-
- unhighlight: Remove highlights.
-
- missing : Search for missing reference numbers (which do not
- appear in the reference table). If requested, add additional
- lines for them, so that the command \"new\" is able to reuse
- them.
-
- statistics : Show some statistics (e.g. minimum and maximum
- reference) about favtable.
-
-
-
-Two ways to save keystrokes:
-
-When prompting for a command, org-favtable puts the most likely
-one (e.g. \"occur\" or \"ref\") at the front of the list, so that
-you may just type RET.
-
-If this command needs additional input (like e.g. \"occur\"), you
-may supply this input right away, although you are still beeing
-prompted for the command. So do an occur for the string \"foo\",
-you can just enter \"foo\" without even entering \"occur\".
-
-
-Another way to save keystrokes applies if you want to choose a
-command, that requrires a reference number (and would normally
-prompt for it): In that case you may just enter enough characters
-from your command, so that it appears first in the list of
-matches; then immediately enter the number of the reference you
-are searching for. So the input \"h237\" would execute the
-command \"head\" for reference \"237\" right away.
-
-")
-
-(defvar org-favtable--commands-some '(occur head ref link leave enter goto + help))
-
-(defvar org-favtable--columns nil)
-
-(defvar org-favtable-id nil
- "Id of the Org-mode node, which contains the favorite table.
-
-Read below, on how to set up things. See the help options
-\"usage\" and \"commands\" for normal usage after setup.
-
-Setup requires two steps:
-
- - Adjust your .emacs initialization file
-
- - Create a suitable org-mode node
-
-
-Here are the lines, you need to add to your .emacs:
-
- (require 'org-favtable)
- ;; Good enough to start, but later you should probably
- ;; change this id, as will be explained below
- (setq org-favtable-id \"00e26bef-1929-4110-b8b4-7eb9c9ab1fd4\")
- ;; Optionally assign a key. Pick your own favorite.
- (global-set-key (kbd \"C-+\") 'org-favtable)
-
-Do not forget to restart emacs to make these lines effective.
-
-
-As a second step you need to create the org-mode node, where your
-reference numbers and links will be stored. It may look like
-this:
-
- * org-favtable
- :PROPERTIES:
- :ID: 00e26bef-1929-4110-b8b4-7eb9c9ab1fd4
- :END:
-
-
- | | | Comment, description, details | | | |
- | ref | link | ;c | count;s | created | last-accessed |
- | | <4> | <30> | | | |
- |-----+------+--------------------------------+---------+---------+---------------|
- | R1 | | My first reference | | | |
-
-
-You may just copy this node into one of your org-files. Many
-things however can or should be adjusted:
-
- - The node needs not be a top level node.
-
- - Its name is completely at you choice. The node is found
- through its ID.
-
- - There are three lines of headings above the first hline. The
- first one is ignored by org-favtable, and you can use them to
- give meaningful names to columns; the second line contains
- configuration information for org-favtable; please read
- further below for its format. The third line is optional and
- may contain width-informations (e.g. <30>) only.
-
- - The sequence of columns does not matter. You may reorder them
- any way you like; e.g. make the comment-column the last
- columns within the table. Columns ar found by their name,
- which appears in the second heading-line.
-
- - You can add further columns or even remove the
- \"Comment\"-column. All other columns from the
- example (e.g. \"ref\", \"link\", \"count\", \"created\" and
- \"last-accessed\") are required.
-
- - Your references need not start at \"R1\"; However, having an
- initial row is required (it serves as a template for subsequent
- references).
-
- - Your reference need not have the form \"R1\"; you may just as
- well choose any text, that contains a single number,
- e.g. \"reference-{1}\" or \"#7\" or \"++17++\" or \"-344-\". The
- function `org-favtable' will inspect your first reference and
- create all subsequent references in the same way.
-
- - You may want to change the ID-Property of the node above and
- create a new one, which is unique (and not just a copy of
- mine). You need to change it in the lines copied to your .emacs
- too. However, this is not strictly required to make things
- work, so you may do this later, after trying out this package.
-
-
-Optionally you may tweak the second header line to adjust
-`org-favtable' a bit. In the example above it looks like this
- (with spaces collapsed):
-
-
- | ref | link | ;c | count;s | created | last-accessed |
-
-
-The different fields have different meanings:
-
- - ref : This denotes the column which contains you references
-
- - link : Column for org-mode links, which can be used to access
- locations within your files.
-
- - ;c : The flag \"c\" (\"c\" for \"copy\") denotes this column
- as the one beeing copied on command \"leave\". In the example
- above, it is also the comment-column.
-
- - count;s : this is the column which counts, how many time this
- line has been accessed (which is the key-feature of this
- package). The flag \"s\" stands for \"sort\", so the table is
- sorted after this column. You may also sort after columns
- \"ref\" or \"last-accessed\".
-
- - created : Date when this line was created.
-
- - last-accessed : Date and time, when this line was last accessed.
-
-
-After this two-step setup process you may invoke `org-favtable'
-to create a new favorite. Read the help option \"usage\" for
-instructions on normal usage, read the help option \"commands\"
-for help on single commands.
-
-")
-
-
-(defvar org-favtable--text-to-yank nil)
-(defvar org-favtable--last-action nil)
-(defvar org-favtable--occur-buffer nil)
-(defvar org-favtable--ref-regex nil)
-(defvar org-favtable--ref-format nil)
-
-
-
-(defun org-favtable (&optional what search search-is-link)
- "Mark and find your favorite items and org-locations easily:
-Create and update a lookup table of your favorite references and
-links. Often used entries automatically bubble to the top of the
-table; entering some keywords narrows it to just the matching
-entries; that way the right one can be picked easily.
-
-References are essentially small numbers (e.g. \"R237\" or
-\"-455-\"), as created by this package; links are normal org-mode
-links. Within org-favtable, both are denoted as favorites.
-
-
-Read below for a detailed description of this function. See the
-help option \"setup\" or read the documentation of
-`org-favtable-id' for setup instructions.
-
-The function `org-favtable' operates on a dedicated table (called
-the table or favorites or favtable, for short) within a special
-Org-mode node. The node has to be created as part of your initial
-setup. Each line of the favorite table contains:
-
- - A reference (optional)
-
- - A link (optional)
-
- - A number; counting, how often each reference has been
- used. This number is updated automatically and the table can
- be sorted according to it, so that most frequently used
- references appear at the top of the table and can be spotted
- easily.
-
- - Its respective creation date
-
- - Date and time of last access. This column can alternatively be
- used to sort the table.
-
-To be useful, your table of favorites should probably contain a
-column with comments too, which allows lines to be selected by
-keywords.
-
-The table of favorites is found through the id of the containing
-node; this id should be stored within `org-favtable-id' (see there
-for details).
-
-
-The function `org-favtable' is the only interactive function of
-this package and its sole entry point; it offers several commands
-to create, find and look up these favorites (references and
-links). All of them are explained within org-favtable's help.
-
-
-Finally, org-favtable can also be invoked from elisp; the two
-optional arguments accepted are:
-
- search : string to search for
- what : symbol of the command to invoke
- search-is-link : t, if argument search is actually a link
-
-An example would be:
-
- (org-favtable \"237\" 'head) ;; find heading with ref 237
-
-"
-
- (interactive "P")
-
- (let (within-node ; True, if we are within node with favtable
- result-is-visible ; True, if node or occur is visible in any window
- ref-node-buffer-and-point ; cons with buffer and point of favorites node
- below-cursor ; word below cursor
- active-region ; active region (if any)
- link-id ; link of starting node, if required
- guarded-search ; with guard against additional digits
- search-is-ref ; true, if search is a reference
- commands ; currently active set of selectable commands
- what-adjusted ; True, if we had to adjust what
- what-input ; Input on what question (need not necessary be "what")
- reorder-once ; Column to use for single time sorting
- parts ; Parts of a typical reference number (which
- ; need not be a plain number); these are:
- head ; Any header before number (e.g. "R")
- maxref ; Maximum number from reference table (e.g. "153")
- tail ; Tail after number (e.g. "}" or "")
- ref-regex ; Regular expression to match a reference
- has-reuse ; True, if table contains a line for reuse
- numcols ; Number of columns in favtable
- kill-new-text ; Text that will be appended to kill ring
- message-text ; Text that will be issued as an explanation,
- ; what we have done
- initial-ref-or-link ; Initial position in reftable
- )
-
- ;;
- ;; Examine current buffer and location, before turning to favtable
- ;;
-
- ;; Get the content of the active region or the word under cursor
- (if (and transient-mark-mode
- mark-active)
- (setq active-region (buffer-substring (region-beginning) (region-end))))
- (setq below-cursor (thing-at-point 'symbol))
-
-
- ;; Find out, if we are within favable or not
- (setq within-node (string= (org-id-get) org-favtable-id))
-
- ;; Find out, if point in any window is within node with favtable
- (mapc (lambda (x) (with-current-buffer (window-buffer x)
- (when (or
- (string= (org-id-get) org-favtable-id)
- (eq (window-buffer x)
- org-favtable--occur-buffer))
- (setq result-is-visible t))))
- (window-list))
-
-
-
- ;;
- ;; Get decoration of references and highest reference from favtable
- ;;
-
-
- ;; Save initial ref or link
- (if (and within-node
- (org-at-table-p))
- (setq initial-ref-or-link
- (or (org-favtable--get-field 'ref)
- (org-favtable--get-field 'link))))
-
- ;; Find node
- (setq ref-node-buffer-and-point (org-favtable--id-find))
- (unless ref-node-buffer-and-point
- (org-favtable--report-setup-error
- (format "Cannot find node with id \"%s\"" org-favtable-id)))
-
- ;; Get configuration of reftable; catch errors
- (let ((error-message
- (catch 'content-error
-
- (with-current-buffer (car ref-node-buffer-and-point)
- (save-excursion
- (unless (string= (org-id-get) org-favtable-id)
- (goto-char (cdr ref-node-buffer-and-point)))
-
- ;; parse table while still within buffer
- (setq parts (org-favtable--parse-and-adjust-table)))
-
- nil))))
- (when error-message
- (org-pop-to-buffer-same-window (car ref-node-buffer-and-point))
- (org-reveal)
- (error error-message)))
-
- ;; Give names to parts of configuration
- (setq head (nth 0 parts))
- (setq maxref (nth 1 parts))
- (setq tail (nth 2 parts))
- (setq numcols (nth 3 parts))
- (setq ref-regex (nth 4 parts))
- (setq has-reuse (nth 5 parts))
- (setq org-favtable--ref-regex ref-regex)
- (setq org-favtable--ref-format (concat head "%d" tail))
-
- ;;
- ;; Find out, what we are supposed to do
- ;;
-
- (if (equal what '(4)) (setq what 'leave))
-
- ;; Set preferred action, that will be the default choice
- (setq org-favtable--preferred-command
- (if within-node
- (if (memq org-favtable--last-action '(ref link))
- 'leave
- 'occur)
- (if active-region
- 'ref
- (if (and below-cursor (string-match ref-regex below-cursor))
- 'occur
- nil))))
-
- ;; Ask user, what to do
- (unless what
- (setq commands (copy-list org-favtable--commands-some))
- (while (progn
- (setq what-input
- (org-icompleting-read
- "Please choose: "
- (mapcar 'symbol-name
- ;; Construct unique list of commands with
- ;; preferred one at front
- (delq nil (delete-dups
- (append
- (list org-favtable--preferred-command)
- commands))))
- nil nil))
-
-
- ;; if input starts with "+", any command (not only some) may follow
- ;; this allows input like "+sort" to be accepted
- (when (string= (substring what-input 0 1) "+")
- ;; make all commands available for selection
- (setq commands (copy-list org-favtable--commands))
- (unless (string= what-input "+")
- ;; not just "+", use following string
- (setq what-input (substring what-input 1))
-
- (let ((completions
- ;; get list of possible completions for what-input
- (all-completions what-input (mapcar 'symbol-name commands))))
- ;; use it, if unambigously
- (if (= (length completions) 1)
- (setq what-input (car completions))))))
-
-
- ;; if input ends in digits, save them away and do completions on head of input
- ;; this allows input like "h224" to be accepted
- (when (string-match "^\\([^0-9+]\\)\\([0-9]+\\)\\s *$" what-input)
- ;; use first match as input, even if ambigously
- (setq org-favtable--preferred-command
- (intern (first (all-completions (match-string 1 what-input)
- (mapcar 'symbol-name commands)))))
- ;; use digits as argument to commands
- (setq what-input (format org-favtable--ref-format
- (string-to-number (match-string 2 what-input)))))
-
- (setq what (intern what-input))
-
- ;; user is not required to input one of the commands; if
- ;; not, take the first one and use the original input for
- ;; next question
- (if (memq what commands)
- ;; input matched one element of list, dont need original
- ;; input any more
- (setq what-input nil)
- ;; what-input will be used for next question, use first
- ;; command for what
- (setq what (or org-favtable--preferred-command
- (first commands)))
- ;; remove any trailing dot, that user might have added to
- ;; disambiguate his input
- (if (equal (substring what-input -1) ".")
- ;; but do this only, if dot was really necessary to
- ;; disambiguate
- (let ((shortened-what-input (substring what-input 0 -1)))
- (unless (test-completion shortened-what-input
- (mapcar 'symbol-name
- commands))
- (setq what-input shortened-what-input)))))
-
- ;; ask for reorder in loop, because we have to ask for
- ;; what right again
- (if (eq what 'reorder)
- (setq reorder-once
- (intern
- (org-icompleting-read
- "Please choose column to reorder reftable once: "
- (mapcar 'symbol-name '(ref count last-accessed))
- nil t))))
-
- ;; maybe ask initial question again
- (memq what '(reorder +)))))
-
-
- ;;
- ;; Get search, if required
- ;;
-
- ;; These actions need a search string:
- (when (memq what '(goto occur head update))
-
- ;; Maybe we've got a search string from the arguments
- (unless search
- (let (search-from-table
- search-from-cursor)
-
- ;; Search string can come from several sources:
- ;; From ref column of table
- (when within-node
- (setq search-from-table (org-favtable--get-field 'ref)))
- ;; From string below cursor
- (when (and (not within-node)
- below-cursor
- (string-match (concat "\\(" ref-regex "\\)")
- below-cursor))
- (setq search-from-cursor (match-string 1 below-cursor)))
-
- ;; Depending on requested action, get search from one of the sources above
- (cond ((eq what 'goto)
- (setq search (or what-input search-from-cursor)))
- ((memq what '(head occur))
- (setq search (or what-input search-from-table search-from-cursor))))))
-
-
- ;; If we still do not have a search string, ask user explicitly
- (unless search
-
- (if what-input
- (setq search what-input)
- (setq search (read-from-minibuffer
- (cond ((memq what '(occur head))
- "Text or reference number to search for: ")
- ((eq what 'goto)
- "Reference number to search for, or enter \".\" for id of current node: ")
- ((eq what 'update)
- "Reference number to update: ")))))
-
- (if (string-match "^\\s *[0-9]+\\s *$" search)
- (setq search (format "%s%s%s" head (org-trim search) tail))))
-
- ;; Clean up and examine search string
- (if search (setq search (org-trim search)))
- (if (string= search "") (setq search nil))
- (setq search-is-ref (string-match ref-regex search))
-
- ;; Check for special case
- (when (and (memq what '(head goto))
- (string= search "."))
- (setq search (org-id-get))
- (setq search-is-link t))
-
- (when search-is-ref
- (setq guarded-search (org-favtable--make-guarded-search search)))
-
- ;;
- ;; Do some sanity checking before really starting
- ;;
-
- ;; Correct requested action, if nothing to search
- (when (and (not search)
- (memq what '(search occur head)))
- (setq what 'enter)
- (setq what-adjusted t))
-
- ;; For a proper reference as input, we do multi-occur
- (if (and (string-match ref-regex search)
- (eq what 'occur))
- (setq what 'multi-occur))
-
- ;; Check for invalid combinations of arguments; try to be helpful
- (when (and (memq what '(head goto))
- (not search-is-link)
- (not search-is-ref))
- (error "Can do '%s' only for a reference or link (not '%s'), try 'occur' to search for text" what search)))
-
-
- ;;
- ;; Prepare
- ;;
-
- ;; Get link if required before moving in
- (if (eq what 'link)
- (setq link-id (org-id-get-create)))
-
- ;; Move into table, if outside
- (when (memq what '(enter ref link goto occur multi-occur missing statistics))
-
- ;; Support orgmode-standard of going back (buffer and position)
- (org-mark-ring-push)
-
- ;; Switch to favtable
- (org-pop-to-buffer-same-window (car ref-node-buffer-and-point))
- (goto-char (cdr ref-node-buffer-and-point))
- (show-subtree)
- (org-show-context)
-
- ;; sort favtable
- (org-favtable--sort-table reorder-once))
-
- ;; Goto back to initial ref, because reformatting of table above might
- ;; have moved point
- (when initial-ref-or-link
- (while (and (org-at-table-p)
- (not (or
- (string= initial-ref-or-link (org-favtable--get-field 'ref))
- (string= initial-ref-or-link (org-favtable--get-field 'link)))))
- (forward-line))
- ;; did not find ref, go back to top
- (if (not (org-at-table-p)) (goto-char top)))
-
-
- ;;
- ;; Actually do, what is requested
- ;;
-
- (cond
-
-
- ((eq what 'help)
-
- (let ((help-what
- ;; which sort of help ?
- (intern
- (concat
- "help-"
- (org-icompleting-read
- "Help on: "
- (mapcar 'symbol-name '(commands usage setup version example))
- nil t)))))
-
- ;; help is taken from docstring of functions or variables
- (cond ((eq help-what 'help-commands)
- (org-favtable--show-help 'org-favtable--commands))
- ((eq help-what 'help-usage)
- (org-favtable--show-help 'org-favtable))
- ((eq help-what 'help-setup)
- (org-favtable--show-help 'org-favtable-id))
- ((eq help-what 'help-version)
- (org-favtable-version)))))
-
-
- ((eq what 'multi-occur)
-
- ;; Conveniently position cursor on number to search for
- (org-favtable--goto-top)
- (let (found (initial (point)))
- (while (and (not found)
- (forward-line)
- (org-at-table-p))
- (save-excursion
- (setq found (string= search
- (org-favtable--get-field 'ref)))))
- (if found
- (org-favtable--update-line nil)
- (goto-char initial)))
-
- ;; Construct list of all org-buffers
- (let (buff org-buffers)
- (dolist (buff (buffer-list))
- (set-buffer buff)
- (if (string= major-mode "org-mode")
- (setq org-buffers (cons buff org-buffers))))
-
- ;; Do multi-occur
- (multi-occur org-buffers guarded-search)
- (if (get-buffer "*Occur*")
- (progn
- (setq message-text (format "multi-occur for '%s'" search))
- (setq org-favtable--occur-buffer (get-buffer "*Occur*"))
- (other-window 1)
- (toggle-truncate-lines 1))
- (setq message-text (format "Did not find '%s'" search)))))
-
-
- ((eq what 'head)
-
- (let (link)
- ;; link either from table or passed in as argument
-
- ;; try to get link
- (if search-is-link
- (setq link (org-trim search))
- (if (and within-node
- (org-at-table-p))
- (setq link (org-favtable--get-field 'link))))
-
- ;; use link if available
- (if (and link
- (not (string= link "")))
- (progn
- (org-id-goto link)
- (org-favtable--update-line search)
- (setq message-text "Followed link"))
-
- (message (format "Scanning headlines for '%s' ..." search))
- (let (buffer point)
- (if (catch 'found
- (progn
- ;; loop over all headlines, stop on first match
- (org-map-entries
- (lambda ()
- (when (looking-at (concat ".*" guarded-search))
- ;; remember location and bail out
- (setq buffer (current-buffer))
- (setq point (point))
- (throw 'found t)))
- nil 'agenda)
- nil))
-
- (progn
- (org-favtable--update-line search)
- (setq message-text (format "Found '%s'" search))
- (org-pop-to-buffer-same-window buffer)
- (goto-char point)
- (org-reveal))
- (setq message-text (format "Did not find '%s'" search)))))))
-
-
- ((eq what 'leave)
-
- (when result-is-visible
-
- ;; If we are within the occur-buffer, switch over to get current line
- (if (and (string= (buffer-name) "*Occur*")
- (eq org-favtable--last-action 'occur))
- (occur-mode-goto-occurrence)))
-
- (setq kill-new-text org-favtable--text-to-yank)
- (setq org-favtable--text-to-yank nil)
-
- ;; If "leave" has been called two times in succession, make
- ;; org-mark-ring-goto believe it has been called two times too
- (if (eq org-favtable--last-action 'leave)
- (let ((this-command nil) (last-command nil))
- (org-mark-ring-goto 1))
- (org-mark-ring-goto 0)))
-
-
- ((eq what 'goto)
-
- ;; Go downward in table to requested reference
- (let (found (initial (point)))
- (org-favtable--goto-top)
- (while (and (not found)
- (forward-line)
- (org-at-table-p))
- (save-excursion
- (setq found
- (string= search
- (org-favtable--get-field
- (if search-is-link 'link 'ref))))))
- (if found
- (progn
- (setq message-text (format "Found '%s'" search))
- (org-favtable--update-line nil)
- (org-table-goto-column (org-favtable--column-num 'ref))
- (if (looking-back " ") (backward-char))
- ;; remember string to copy
- (setq org-favtable--text-to-yank
- (org-trim (org-table-get-field (org-favtable--column-num 'copy)))))
- (setq message-text (format "Did not find '%s'" search))
- (goto-char initial)
- (forward-line)
- (setq what 'missed))))
-
-
- ((eq what 'occur)
-
- ;; search for string: occur
- (let (search-regexp
- all-or-any
- (search-words (split-string search "," t)))
-
- (if (< (length search-words) 2)
- ;; only one word to search; use it as is
- (setq search-regexp search)
- ;; construct regexp to match any of the words (maybe throw out some matches later)
- (setq search-regexp
- (mapconcat (lambda (x) (concat "\\(" x "\\)")) search-words "\\|"))
- (setq all-or-any
- (intern
- (org-icompleting-read
- "Two or more words have been specified; show lines, that match: " '("all" "any")))))
-
- (save-restriction
- (org-narrow-to-subtree)
- (occur search-regexp)
- (widen)
- (if (get-buffer "*Occur*")
- (with-current-buffer "*Occur*"
-
- ;; install helpful keyboard-shortcuts within occur-buffer
- (let ((keymap (make-sparse-keymap)))
- (set-keymap-parent keymap occur-mode-map)
-
- (define-key keymap (kbd "RET")
- (lambda () (interactive)
- (org-favtable--occur-helper 'head)))
-
- (define-key keymap (kbd "<C-return>")
- (lambda () (interactive)
- (org-favtable--occur-helper 'multi-occur)))
-
- (define-key keymap (kbd "<M-return>")
- (lambda () (interactive)
- (org-favtable--occur-helper 'goto)))
-
- (define-key keymap (kbd "<C-M-return>")
- (lambda () (interactive)
- (org-favtable--occur-helper 'update)))
-
- (use-local-map keymap))
-
- ;; Brush up occur buffer
- (other-window 1)
- (toggle-truncate-lines 1)
- (let ((inhibit-read-only t))
- ;; insert some help text
- (insert (substitute-command-keys
- "Type RET to find heading, C-RET for multi-occur, M-RET to go to occurence and C-M-RET to update line in reftable.\n\n"))
- (forward-line 1)
-
- ;; when matching all of multiple words, remove all lines that do not match one of the words
- (when (eq all-or-any 'all)
- (mapc (lambda (x) (keep-lines x)) search-words))
-
- ;; replace description from occur
- (when all-or-any
- (forward-line -1)
- (kill-line)
- (let ((count (- (count-lines (point) (point-max)) 1)))
- (insert (format "%d %s for %s of %s"
- count
- (if (= count 1) "match" "matches")
- all-or-any
- search)))
- (forward-line)
- (beginning-of-line))
-
- ;; Record link or reference for each line in
- ;; occur-buffer, that is linked into reftable. Because if
- ;; we later realign the reftable and then reuse the occur
- ;; buffer, the original links might point nowehere.
- (save-excursion
- (while (not (eq (point) (point-max)))
- (let ((beg (line-beginning-position))
- (end (line-end-position))
- pos ref link)
-
- ;; occur has saved the position into a special property
- (setq pos (get-text-property (point) 'occur-target))
- (when pos
- ;; but this property might soon point nowhere; so retrieve ref-or-link instead
- (with-current-buffer (marker-buffer pos)
- (goto-char pos)
- (setq ref (org-favtable--get-field 'ref))
- (setq link (org-favtable--get-field 'link))))
- ;; save as text property
- (put-text-property beg end 'org-favtable--ref ref)
- (put-text-property beg end 'org-favtable--link link))
- (forward-line))))
-
- (setq message-text
- (format "Occur for '%s'" search)))
- (setq message-text
- (format "Did not find any matches for '%s'" search))))))
-
-
- ((memq what '(ref link))
-
- ;; add a new row (or reuse existing one)
- (let (new)
-
- (when (eq what 'ref)
- ;; go through table to find first entry to be reused
- (when has-reuse
- (org-favtable--goto-top)
- ;; go through table
- (while (and (org-at-table-p)
- (not new))
- (when (string=
- (org-favtable--get-field 'count)
- ":reuse:")
- (setq new (org-favtable--get-field 'ref))
- (if new (org-table-kill-row)))
- (forward-line)))
-
- ;; no ref to reuse; construct new reference
- (unless new
- (setq new (format "%s%d%s" head (1+ maxref) tail)))
-
- ;; remember for org-mark-ring-goto
- (setq org-favtable--text-to-yank new))
-
- ;; insert ref or link as very first row
- (org-favtable--goto-top)
- (org-table-insert-row)
-
- ;; fill special columns with standard values
- (when (eq what 'ref)
- (org-table-goto-column (org-favtable--column-num 'ref))
- (insert new))
- (when (eq what 'link)
- (org-table-goto-column (org-favtable--column-num 'link))
- (insert link-id))
- (org-table-goto-column (org-favtable--column-num 'created))
- (org-insert-time-stamp nil nil t)
-
- ;; goto first empty field
- (unless (catch 'empty
- (dotimes (col numcols)
- (org-table-goto-column (+ col 1))
- (if (string= (org-trim (org-table-get-field)) "")
- (throw 'empty t))))
- ;; none found, goto first
- (org-table-goto-column 1))
-
- (org-table-align)
- (if active-region (setq kill-new-text active-region))
- (if (eq what 'ref)
- (setq message-text (format "Adding a new row with ref '%s'" new))
- (setq message-text (format "Adding a new row linked to '%s'" link-id)))))
-
-
- ((eq what 'enter)
-
- ;; simply go into table
- (org-favtable--goto-top)
- (show-subtree)
- (recenter)
- (if what-adjusted
- (setq message-text "Nothing to search for; at favtable")
- (setq message-text "At favtable")))
-
-
- ((eq what 'fill)
-
- ;; check, if within reftable
- (unless (and within-node
- (org-at-table-p))
- (error "Not within table of favorites"))
-
- ;; applies to missing refs and missing links alike
- (let ((ref (org-favtable--get-field 'ref))
- (link (org-favtable--get-field 'link)))
-
- (if (and (not ref)
- (not link))
- ;; have already checked this during parse, check here anyway
- (error "Columns ref and link are both empty in this line"))
-
- ;; fill in new ref
- (if (not ref)
- (progn
- (setq kill-new-text (format "%s%d%s" head (1+ maxref) tail))
- (org-favtable--get-field 'ref kill-new-text)
- ;; remember for org-mark-ring-goto
- (setq org-favtable--text-to-yank kill-new-text)
- (org-id-goto link)
- (setq message-text "Filled reftable field with new reference"))
-
- ;; fill in new link
- (if (not link)
- (progn
- (setq guarded-search (org-favtable--make-guarded-search ref))
- (message (format "Scanning headlines for '%s' ..." ref))
- (let (link)
- (if (catch 'found
- (org-map-entries
- (lambda ()
- (when (looking-at (concat ".*" guarded-search))
- (setq link (org-id-get-create))
- (throw 'found t)))
- nil 'agenda)
- nil)
-
- (progn
- (org-favtable--get-field 'link link)
- (setq message-text "Inserted link"))
-
- (setq message-text (format "Did not find reference '%s'" ref)))))
-
- ;; nothing is missing
- (setq message-text "Columns 'ref' and 'link' are already filled; nothing to do")))))
-
-
- ((eq what 'sort)
-
- ;; sort lines according to contained reference
- (let (begin end where)
- (catch 'aborted
- ;; either active region or whole buffer
- (if (and transient-mark-mode
- mark-active)
- ;; sort only region
- (progn
- (setq begin (region-beginning))
- (setq end (region-end))
- (setq where "region"))
- ;; sort whole buffer
- (setq begin (point-min))
- (setq end (point-max))
- (setq where "whole buffer")
- ;; make sure
- (unless (y-or-n-p "Sort whole buffer ")
- (setq message-text "Sort aborted")
- (throw 'aborted nil)))
-
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (narrow-to-region begin end)
- (sort-subr nil 'forward-line 'end-of-line
- (lambda ()
- (if (looking-at (concat ".*"
- (org-favtable--make-guarded-search ref-regex 'dont-quote)))
- (string-to-number (match-string 1))
- 0))))
- (highlight-regexp ref-regex)
- (setq message-text (format "Sorted %s from character %d to %d, %d lines"
- where begin end
- (count-lines begin end)))))))
-
-
- ((eq what 'update)
-
- ;; simply update line in reftable
- (save-excursion
- (let ((ref-or-link (if search-is-link "link" "reference")))
- (beginning-of-line)
- (if (org-favtable--update-line search)
- (setq message-text (format "Updated %s '%s'" ref-or-link search))
- (setq message-text (format "Did not find %s '%s'" ref-or-link search))))))
-
-
- ((eq what 'parse)
-
- ;; Just parse the reftable, which is already done, so nothing to do
- )
-
-
- ((memq what '(highlight unhighlight))
-
- (let ((where "buffer"))
- (save-excursion
- (save-restriction
- (when (and transient-mark-mode
- mark-active)
- (narrow-to-region (region-beginning) (region-end))
- (setq where "region"))
-
- (if (eq what 'highlight)
- (progn
- (highlight-regexp ref-regex)
- (setq message-text (format "Highlighted references in %s" where)))
- (unhighlight-regexp ref-regex)
- (setq message-text (format "Removed highlights for references in %s" where)))))))
-
-
- ((memq what '(missing statistics))
-
- (org-favtable--goto-top)
- (let (missing
- ref-field
- ref
- min
- max
- (total 0))
-
- ;; start with list of all references
- (setq missing (mapcar (lambda (x) (format "%s%d%s" head x tail))
- (number-sequence 1 maxref)))
-
- ;; go through table and remove all refs, that we see
- (while (and (forward-line)
- (org-at-table-p))
-
- ;; get ref-field and number
- (setq ref-field (org-favtable--get-field 'ref))
- (if (and ref-field
- (string-match ref-regex ref-field))
- (setq ref (string-to-number (match-string 1 ref-field))))
-
- ;; remove existing refs from list
- (if ref-field (setq missing (delete ref-field missing)))
-
- ;; record min and max
- (if (or (not min) (< ref min)) (setq min ref))
- (if (or (not max) (> ref max)) (setq max ref))
-
- ;; count
- (setq total (1+ total)))
-
- ;; insert them, if requested
- (forward-line -1)
- (if (eq what 'statistics)
-
- (setq message-text (format "Found %d references from %s to %s. %d references below highest do not appear in table. "
- total
- (format org-favtable--format min)
- (format org-favtable--format max)
- (length missing)))
-
- (if (y-or-n-p (format "Found %d missing references; do you wish to append them to the table of favorites"
- (length missing)))
- (let (type)
- (setq type (org-icompleting-read
- "Insert new lines for reuse by command \"new\" or just as missing ? " '("reuse" "missing")))
- (mapc (lambda (x)
- (let (org-table-may-need-update) (org-table-insert-row t))
- (org-favtable--get-field 'ref x)
- (org-favtable--get-field 'count (format ":%s:" type)))
- missing)
- (org-table-align)
- (setq message-text (format "Inserted %d new lines for missing refernces" (length missing))))
- (setq message-text (format "%d missing references." (length missing)))))))
-
-
- (t (error "This is a bug: unmatched case '%s'" what)))
-
-
- ;; remember what we have done for next time
- (setq org-favtable--last-action what)
-
- ;; tell, what we have done and what can be yanked
- (if kill-new-text (setq kill-new-text
- (substring-no-properties kill-new-text)))
- (if (string= kill-new-text "") (setq kill-new-text nil))
- (let ((m (concat
- message-text
- (if (and message-text kill-new-text)
- " and r"
- (if kill-new-text "R" ""))
- (if kill-new-text (format "eady to yank '%s'" kill-new-text) ""))))
- (unless (string= m "") (message m)))
- (if kill-new-text (kill-new kill-new-text))))
-
-
-
-(defun org-favtable--parse-and-adjust-table ()
-
- (let ((maxref 0)
- top
- bottom
- ref-field
- link-field
- parts
- numcols
- head
- tail
- ref-regex
- has-reuse
- initial-point)
-
- (setq initial-point (point))
- (org-favtable--goto-top)
- (setq top (point))
-
- (goto-char top)
-
- ;; count columns
- (org-table-goto-column 100)
- (setq numcols (- (org-table-current-column) 1))
-
- ;; get contents of columns
- (forward-line -2)
- (unless (org-at-table-p)
- (org-favtable--report-setup-error
- "Table of favorites starts with a hline" t))
-
- ;; check for optional line consisting solely of width specifications
- (beginning-of-line)
- (if (looking-at "\\s *|\\(\\(\\s *|\\)\\|\\(\\s *<[0-9]+>\\s *|\\)\\)+\\s *$")
- (forward-line -1))
- (org-table-goto-column 1)
-
- (setq org-favtable--columns (org-favtable--parse-headings numcols))
-
- ;; Go beyond end of table
- (while (org-at-table-p) (forward-line 1))
-
- ;; Kill all empty rows at bottom
- (while (progn
- (forward-line -1)
- (org-table-goto-column 1)
- (and
- (not (org-favtable--get-field 'ref))
- (not (org-favtable--get-field 'link))))
- (org-table-kill-row))
- (forward-line)
- (setq bottom (point))
- (forward-line -1)
-
- ;; Retrieve any decorations around the number within the first nonempty ref-field
- (goto-char top)
- (while (and (org-at-table-p)
- (not (setq ref-field (org-favtable--get-field 'ref))))
- (forward-line))
-
- ;; Some Checking
- (unless ref-field
- (org-favtable--report-setup-error
- "No line of reference column contains a number" t))
-
- (unless (string-match "^\\([^0-9]*\\)\\([0-9]+\\)\\([^0-9]*\\)$" ref-field)
- (org-favtable--report-setup-error
- (format "First reference in table table of favorites ('%s') does not contain a number" ref-field) t))
-
-
- ;; These are the decorations used within the first ref of favtable
- (setq head (match-string 1 ref-field))
- (setq tail (match-string 3 ref-field))
- (setq ref-regex (concat (regexp-quote head)
- "\\([0-9]+\\)"
- (regexp-quote tail)))
-
- ;; Go through table to find maximum number and do some checking
- (let ((ref 0))
-
- (while (org-at-table-p)
-
- (setq ref-field (org-favtable--get-field 'ref))
- (setq link-field (org-favtable--get-field 'link))
-
- (if (and (not ref-field)
- (not link-field))
- (throw 'content-error "Columns ref and link are both empty in this line"))
-
- (if ref-field
- (if (string-match ref-regex ref-field)
- ;; grab number
- (setq ref (string-to-number (match-string 1 ref-field)))
- (throw 'content-error "Column ref does not contain a number")))
-
- ;; check, if higher ref
- (if (> ref maxref) (setq maxref ref))
-
- ;; check if ref is ment for reuse
- (if (string= (org-favtable--get-field 'count) ":reuse:")
- (setq has-reuse 1))
-
- (forward-line 1)))
-
- ;; sort used to be here
-
- (setq parts (list head maxref tail numcols ref-regex has-reuse))
-
- ;; go back to top of table
- (goto-char top)
-
- parts))
-
-
-
-(defun org-favtable--sort-table (sort-column)
-
- (unless sort-column (setq sort-column (org-favtable--column-num 'sort)))
-
- (let (top
- bottom
- ref-field
- count-field
- count-special)
-
-
- ;; get boundaries of table
- (org-favtable--goto-top)
- (forward-line 0)
- (setq top (point))
- (while (org-at-table-p) (forward-line))
- (setq bottom (point))
-
- (save-restriction
- (narrow-to-region top bottom)
- (goto-char top)
- (sort-subr t
- 'forward-line
- 'end-of-line
- (lambda ()
- (let (ref
- (ref-field (or (org-favtable--get-field 'ref) ""))
- (count-field (or (org-favtable--get-field 'count) ""))
- (count-special 0))
-
- ;; get reference with leading zeroes, so it can be
- ;; sorted as text
- (string-match org-favtable--ref-regex ref-field)
- (setq ref (format
- "%06d"
- (string-to-number
- (or (match-string 1 ref-field)
- "0"))))
-
- ;; find out, if special token in count-column
- (setq count-special (format "%d"
- (- 2
- (length (member count-field '(":missing:" ":reuse:"))))))
-
- ;; Construct different sort-keys according to
- ;; requested sort column; prepend count-special to
- ;; sort special entries at bottom of table, append ref
- ;; as a secondary sort key
- (cond
-
- ((eq sort-column 'count)
- (concat count-special
- (format
- "%08d"
- (string-to-number (or (org-favtable--get-field 'count)
- "")))
- ref))
-
- ((eq sort-column 'last-accessed)
- (concat count-special
- (org-favtable--get-field 'last-accessed)
- " "
- ref))
-
- ((eq sort-column 'ref)
- (concat count-special
- ref))
-
- (t (error "This is a bug: unmatched case '%s'" sort-column)))))
-
- nil 'string<)))
-
- ;; align table
- (org-table-align))
-
-
-(defun org-favtable--goto-top ()
-
- ;; go to heading of node
- (while (not (org-at-heading-p)) (forward-line -1))
- (forward-line 1)
- ;; go to table within node, but make sure we do not get into another node
- (while (and (not (org-at-heading-p))
- (not (org-at-table-p))
- (not (eq (point) (point-max))))
- (forward-line 1))
-
- ;; check, if there really is a table
- (unless (org-at-table-p)
- (org-favtable--report-setup-error
- (format "Cannot find favtable within node %s" org-favtable-id) t))
-
- ;; go to first hline
- (while (and (not (org-at-table-hline-p))
- (org-at-table-p))
- (forward-line 1))
-
- ;; and check
- (unless (org-at-table-hline-p)
- (org-favtable--report-setup-error
- "Cannot find hline within table of favorites" t))
-
- (forward-line 1)
- (org-table-goto-column 1))
-
-
-
-(defun org-favtable--id-find ()
- "Find org-favtable-id"
- (let ((marker (org-id-find org-favtable-id 'marker))
- marker-and-buffer)
-
- (if marker
- (progn
- (setq marker-and-buffer (cons (marker-buffer marker) (marker-position marker)))
- (move-marker marker nil)
- marker-and-buffer)
- nil)))
-
-
-
-(defun org-favtable--parse-headings (numcols)
-
- (let (columns)
-
- ;; Associate names of special columns with column-numbers
- (setq columns (copy-tree '((ref . 0) (link . 0) (created . 0) (last-accessed . 0)
- (count . 0) (sort . nil) (copy . nil))))
-
- ;; For each column
- (dotimes (col numcols)
- (let* (field-flags ;; raw heading, consisting of file name and maybe
- ;; flags (seperated by ";")
- field ;; field name only
- field-symbol ;; and as a symbol
- flags ;; flags from field-flags
- found)
-
- ;; parse field-flags into field and flags
- (setq field-flags (org-trim (org-table-get-field (+ col 1))))
- (if (string-match "^\\([^;]*\\);\\([a-z]+\\)$" field-flags)
- (progn
- (setq field (downcase (or (match-string 1 field-flags) "")))
- ;; get flags as list of characters
- (setq flags (mapcar 'string-to-char
- (split-string
- (downcase (match-string 2 field-flags))
- "" t))))
- ;; no flags
- (setq field field-flags))
-
- (unless (string= field "") (setq field-symbol (intern (downcase field))))
-
- ;; Check, that no flags appear twice
- (mapc (lambda (x)
- (when (memq (car x) flags)
- (if (cdr (assoc (cdr x) columns))
- (org-favtable--report-setup-error
- (format "More than one heading is marked with flag '%c'" (car x)) t))))
- '((?s . sort)
- (?c . copy)))
-
- ;; Process flags
- (if (memq ?s flags)
- (setcdr (assoc 'sort columns) field-symbol))
- (if (memq ?c flags)
- (setcdr (assoc 'copy columns) (+ col 1)))
-
- ;; Store columns in alist
- (setq found (assoc field-symbol columns))
- (when found
- (if (> (cdr found) 0)
- (org-favtable--report-setup-error
- (format "'%s' appears two times as column heading" (downcase field)) t))
- (setcdr found (+ col 1)))))
-
- ;; check if all necessary informations have been specified
- (mapc (lambda (col)
- (unless (> (cdr (assoc col columns)) 0)
- (org-favtable--report-setup-error
- (format "column '%s' has not been set" col) t)))
- '(ref link count created last-accessed))
-
- ;; use ref as a default sort-column
- (unless (cdr (assoc 'sort columns))
- (setcdr (assoc 'sort columns) 'ref))
- columns))
-
-
-
-(defun org-favtable--report-setup-error (text &optional switch-to-node)
-
- (when switch-to-node
- (org-id-goto org-favtable-id)
- (delete-other-windows))
-
- (when (y-or-n-p (concat
- text
- ";\n"
- "the correct setup is explained in the documentation of 'org-favtable-id'.\n"
- "Do you want to read it ? "))
- (org-favtable--show-help 'org-favtable-id))
-
- (error "")
- (setq org-favtable--last-action 'leave))
-
-
-
-(defun org-favtable--show-help (function-or-variable)
-
- (let ((isfun (functionp function-or-variable)))
- ;; bring up help-buffer for function or variable
- (if isfun
- (describe-function function-or-variable)
- (describe-variable function-or-variable))
-
-
- ;; clean up help-buffer
- (pop-to-buffer "*Help*")
- (let ((inhibit-read-only t))
- (goto-char (point-min))
- (while (progn
- (kill-line 1)
- (not (looking-at
- (if isfun
- "("
- "Documentation:")))))
- (kill-line (if isfun 2 3))
- (goto-char (point-max))
- (kill-line -2)
- (goto-char (point-min)))))
-
-
-
-(defun org-favtable--update-line (ref-or-link)
-
- (let (initial
- found
- count-field
- (ref-node-buffer-and-point (org-favtable--id-find)))
-
- (with-current-buffer (car ref-node-buffer-and-point)
-
- ;; search reference or link, if given (or assume, that we are already positioned right)
- (when ref-or-link
- (setq initial (point))
- (goto-char (cdr ref-node-buffer-and-point))
- (org-favtable--goto-top)
- (while (and (org-at-table-p)
- (not (or (string= ref-or-link (org-favtable--get-field 'ref))
- (string= ref-or-link (org-favtable--get-field 'link)))))
- (forward-line)))
-
- (if (not (org-at-table-p))
- (error "Did not find reference or link '%s'" ref-or-link)
- (setq count-field (org-favtable--get-field 'count))
-
- ;; update count field only if number or empty; leave :missing: and :reuse: as is
- (if (or (not count-field)
- (string-match "^[0-9]+$" count-field))
- (org-favtable--get-field 'count
- (number-to-string
- (+ 1 (string-to-number (or count-field "0"))))))
-
- ;; update timestamp
- (org-table-goto-column (org-favtable--column-num 'last-accessed))
- (org-table-blank-field)
- (org-insert-time-stamp nil t t)
-
- (setq found t))
-
- (if initial (goto-char initial))
-
- found)))
-
-
-
-(defun org-favtable--occur-helper (action)
- (let ((line-beg (line-beginning-position))
- key search link ref)
-
- ;; extract reference or link from text property (as put there before)
- (setq ref (get-text-property line-beg 'org-favtable--ref))
- (if (string= ref "") (setq ref nil))
- (setq link (get-text-property line-beg 'org-favtable--link))
- (if (string= link "") (setq link nil))
-
- (org-favtable action
- (or link ref) ;; prefer link
- (if link t nil))))
-
-
-(defun org-favtable--get-field (key &optional value)
- (let (field)
- (setq field (org-trim (org-table-get-field (cdr (assoc key org-favtable--columns)) value)))
- (if (string= field "") (setq field nil))
-
- field))
-
-
-(defun org-favtable--column-num (key)
- (cdr (assoc key org-favtable--columns)))
-
-
-(defun org-favtable-version ()
- "Show version of org-favtable" (interactive)
- (message "org-favtable %s" org-favtable--version))
-
-
-(defun org-favtable--make-guarded-search (ref &optional dont-quote)
- (concat "\\b" (if dont-quote ref (regexp-quote ref)) "\\b"))
-
-
-(defun org-favtable-get-ref-regex-format ()
- "return cons-cell with regular expression and format for references"
- (unless org-favtable--ref-regex
- (org-favtable 'parse))
- (cons (org-favtable--make-guarded-search org-favtable--ref-regex 'dont-quote) org-favtable--ref-format))
-
-
-(defadvice org-mark-ring-goto (after org-favtable--advice-text-to-yank activate)
- "Make text from the favtable available for yank."
- (when org-favtable--text-to-yank
- (kill-new org-favtable--text-to-yank)
- (message (format "Ready to yank '%s'" org-favtable--text-to-yank))
- (setq org-favtable--text-to-yank nil)))
-
-
-(provide 'org-favtable)
-
-;; Local Variables:
-;; fill-column: 75
-;; comment-column: 50
-;; End:
-
-;;; org-favtable.el ends here
diff --git a/contrib/lisp/org-git-link.el b/contrib/lisp/org-git-link.el
index b9e6a4e..ad0ce71 100644
--- a/contrib/lisp/org-git-link.el
+++ b/contrib/lisp/org-git-link.el
@@ -1,6 +1,6 @@
;;; org-git-link.el --- Provide org links to specific file version
-;; Copyright (C) 2009-2013 Reimar Finken
+;; Copyright (C) 2009-2014 Reimar Finken
;; Author: Reimar Finken <reimar.finken@gmx.de>
;; Keywords: files, calendar, hypermedia
@@ -98,10 +98,12 @@
(let* ((strlist (org-git-split-string str))
(filepath (first strlist))
(commit (second strlist))
+ (line (third strlist))
(dirlist (org-git-find-gitdir (file-truename filepath)))
(gitdir (first dirlist))
(relpath (second dirlist)))
- (org-git-open-file-internal gitdir (concat commit ":" relpath))))
+ (org-git-open-file-internal gitdir (concat commit ":" relpath))
+ (when line (goto-line (string-to-int line)))))
;; Utility functions (file names etc)
@@ -141,16 +143,19 @@
;; splitting the link string
;; Both link open functions are called with a string of
-;; consisting of two parts separated by a double colon (::).
+;; consisting of three parts separated by a double colon (::).
(defun org-git-split-string (str)
- "Given a string of the form \"str1::str2\", return a list of
- two substrings \'(\"str1\" \"str2\"). If the double colon is mising, take str2 to be the empty string."
+ "Given a string of the form \"str1::str2::str3\", return a list of
+ three substrings \'(\"str1\" \"str2\" \"str3\"). If there are less
+than two double colons, str2 and/or str3 may be set the empty string."
(let ((strlist (split-string str "::")))
(cond ((= 1 (length strlist))
- (list (car strlist) ""))
+ (list (car strlist) "" ""))
((= 2 (length strlist))
+ (append strlist (list "")))
+ ((= 3 (length strlist))
strlist)
- (t (error "org-git-split-string: only one :: allowed: %s" str)))))
+ (t (error "org-git-split-string: only one or two :: allowed: %s" str)))))
;; finding the file name part of a commit
(defun org-git-link-filename (str)
@@ -168,22 +173,24 @@
(concat branch "@{" timestring "}"))
-(defun org-git-create-git-link (file)
+(defun org-git-create-git-link (file &optional line)
"Create git link part to file at specific time"
(interactive "FFile: ")
(let* ((gitdir (first (org-git-find-gitdir (file-truename file))))
(branchname (org-git-get-current-branch gitdir))
(timestring (format-time-string "%Y-%m-%d" (current-time))))
- (concat "git:" file "::" (org-git-create-searchstring branchname timestring))))
+ (concat "git:" file "::" (org-git-create-searchstring branchname timestring)
+ (if line (format "::%s" line) ""))))
(defun org-git-store-link ()
"Store git link to current file."
(when (buffer-file-name)
- (let ((file (abbreviate-file-name (buffer-file-name))))
+ (let ((file (abbreviate-file-name (buffer-file-name)))
+ (line (line-number-at-pos)))
(when (org-git-gitrepos-p file)
(org-store-link-props
:type "git"
- :link (org-git-create-git-link file))))))
+ :link (org-git-create-git-link file line))))))
(add-hook 'org-store-link-functions 'org-git-store-link)
diff --git a/contrib/lisp/org-index.el b/contrib/lisp/org-index.el
new file mode 100644
index 0000000..64974eb
--- a/dev/null
+++ b/contrib/lisp/org-index.el
@@ -0,0 +1,2217 @@
+;;; org-index.el --- A personal index for org and beyond
+
+;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
+
+;; Author: Marc Ihm <org-index@2484.de>
+;; Keywords: outlines, hypermedia, matching
+;; Requires: org
+;; Version: 2.4.3
+
+;; This file is not part of GNU Emacs.
+
+;;; License:
+
+;; This program 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,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Purpose:
+;;
+;; Mark and find your favorite org-locations and other points of interest
+;; easily; create and update a lookup table of references and links. When
+;; searching, frequently used entries appear at the the top and entering
+;; some keywords narrows down to matching entries only, so that the
+;; right one can be spotted easily.
+;;
+;; References are essentially small numbers (e.g. "R237" or "-455-"),
+;; which are created by this package; they are well suited to be used
+;; outside org. Links are normal org-mode links.
+;;
+;;
+;; Setup:
+;;
+;; - Add these lines to your .emacs:
+;;
+;; ;; use the real path from your org-installation
+;; (add-to-list 'load-path "~/path/to/orgdir/contrib/lisp" t)
+;; (require 'org-index)
+;;
+;; - Restart your emacs to make these lines effective
+;;
+;; - Invoke `org-index', which will assist in creating your index
+;; table. The variable org-index-id will be persisted within your
+;; customization file (typically .emacs).
+;;
+;;
+;; Further reading:
+;;
+;; See the documentation of `org-index', which can also be read
+;; by invoking `org-index' and and choosing the help-command.
+;;
+;; For more documentation and working examples, see:
+;;
+;; http://orgmode.org/worg/org-contrib/org-index.html
+;;
+;;
+;; Updates:
+;;
+;; The latest tested version of this file can always be found at:
+;;
+;; http://orgmode.org/w/org-mode.git?p=org-mode.git;a=blob_plain;f=contrib/lisp/org-index.el;hb=HEAD
+
+;;; Change Log:
+
+;; [2014-04-26 Sa] Version 2.4.3:
+;; - Some Bugfixes and enhancements for occur-command
+;; - Fixes for assistant to create index table
+;;
+;; [2014-02-01 Sa] Version 2.4.2:
+;; - Follow mode in occur-buffer
+;; - Reorder for x-columns
+;;
+;; [2014-01-02 Th] Version 2.4.0:
+;; - New command "put" to store a nodes reference in a property
+;; - New functions org-index-new-line and org-index-get-line
+;; offer access to org-index from other lisp programs
+;; - New flag p, new columns x1,x2 and x3
+;; - Major Code refactoring
+;; - Regression tests with ert
+;; - Lots of bugfixes
+;;
+;; [2013-10-04 Fr] Version 2.3.2:
+;; - Bugfix: index-table created by assistant is found after
+;; restart of emacs instead of invoking assistent again
+;;
+;; [2013-07-20 Sa] Version 2.3.0:
+;; - Renamed from "org-favtable" to "org-index"
+;; - Added an assistent to set up the index table
+;; - occur is now incremental, searching as you type
+;; - simplified the documentation and help-system
+;; - Saving keystrokes, as "+g237" is now valid input
+;; - Many bugfixes
+;;
+;; [2013-02-28 Th] Version 2.2.0:
+;; - Allowed shortcuts like "h237" for command "head" with argument "237"
+;; - Integrated with org-mark-ring-goto
+;;
+;; [2013-01-25 Fr] Version 2.1.0:
+;; - Added full support for links
+;; - New commands "missing" and "statistics"
+;; - Renamed the package from "org-reftable" to "org-favtable"
+;; - Additional columns are required (e.g. "link"). Error messages will
+;; guide you
+;;
+;; [2012-12-07 Fr] Version 2.0.0:
+;; - The format of the table of favorites has changed ! You need to bring
+;; your existing table into the new format by hand (which however is
+;; easy and explained below)
+;; - Reference table can be sorted after usage count or date of last access
+;; - Ask user explicitly, which command to invoke
+;; - Renamed the package from "org-refer-by-number" to "org-reftable"
+;;
+;; [2012-09-22 Sa] Version 1.5.0:
+;; - New command "sort" to sort a buffer or region by reference number
+;; - New commands "highlight" and "unhighlight" to mark references
+;;
+;; [2012-07-13 Fr] Version 1.4.0:
+;; - New command "head" to find a headline with a reference number
+;;
+;; [2012-04-28 Sa] Version 1.3.0:
+;; - New commands occur and multi-occur
+;; - All commands can now be invoked explicitly
+;; - New documentation
+;; - Many bugfixes
+;;
+;; [2011-12-10 Sa] Version 1.2.0:
+;; - Fixed a bug, which lead to a loss of newly created reference numbers
+;; - Introduced single and double prefix arguments
+;; - Started this Change Log
+
+;;; Code:
+
+(require 'org-table)
+(require 'cl)
+
+(defcustom org-index-id nil
+ "Id of the Org-mode node, which contains the index table."
+ :group 'org
+ :group 'org-index)
+
+;; Variables to hold the configuration of the index table
+(defvar org-index--maxref) ; Maximum number from reference table (e.g. "153")
+(defvar org-index--head) ; Any header before number (e.g. "R")
+(defvar org-index--tail) ; Tail after number (e.g. "}" or "")
+(defvar org-index--numcols) ; Number of columns in index table
+(defvar org-index--ref-regex) ; Regular expression to match a reference
+(defvar org-index--has-reuse nil) ; True, if table contains a line for reuse
+(defvar org-index--ref-format) ; Format, that can print a reference
+(defvar org-index--columns nil) ; Columns of index-table
+(defvar org-index--special-columns nil) ; Columns with flags
+(defvar org-index--buffer) ; Buffer of index table
+(defvar org-index--point) ; Position at start of headline of index table
+(defvar org-index--below-hline) ; Position of first cell in first line below hline
+(defvar org-index--headings) ; Headlines of index-table as a string
+
+;; Variables to hold context and state
+(defvar org-index--last-action nil) ; Last action performed by org-index
+(defvar org-index--text-to-yank nil) ; Text, that can be yanked after call (mostly a reference)
+(defvar org-index--last-ref) ; Last reference created or visited
+(defvar org-index--point-before nil) ; Point in buffer with index table
+(defvar org-index--point-saved nil) ; Saved point if we want to return
+(defvar org-index--silent nil) ; t, if user should not be queried
+(defvar org-index--preferred-command) ; command, that is presented first
+(defvar org-index--active-region) ; Active region, initially. I.e. what has been marked
+(defvar org-index--below-cursor) ; Word below cursor
+(defvar org-index--within-node) ; True, if we are within node of the index table
+(defvar org-index--active-window-index nil) ; Active window with index table (if any)
+(defvar org-index--occur-follow-mode nil) ; True, if follow mode in occur-buffer is on
+
+
+(setq org-index--commands '(occur head ref link leave put enter goto help + reorder fill sort update multi-occur highlight unhighlight missing statistics)) ; list of commands available
+
+(defun org-index (&optional ARG)
+ "Mark and find your favorite things and org-locations easily:
+Create and update a lookup table of references and links. Often
+used entries bubble to the top; entering some keywords narrows
+down to matching entries only, so that the right one can be
+spotted easily.
+
+References are essentially small numbers (e.g. \"R237\" or \"-455-\"),
+which are created by this package; they are well suited to be used
+outside of org. Links are normal org-mode links.
+
+This is version 2.4.3 of org-index.
+
+The function `org-index' operates on a dedicated table, the index
+table, which lives within its own Org-mode node. The table and
+its node will be created, when you first invoke org-index.
+
+Each line in the index table contains:
+
+ - A reference (e.g. \"R237\")
+
+ - An optional link to another location in org
+
+ - A number, counting, how often each reference has been
+ used. This number is updated automatically and the table can
+ be sorted after it, so that most frequently used references
+ appear at the top of the table and can be spotted easily.
+
+ - The creation date of the line
+
+ - Date and time of last access. This column can alternatively be
+ used to sort the table.
+
+ - A column for your own comments
+
+The index table is found through the id of the containing
+node; this id is stored within the variable `org-index-id'.
+
+
+The function `org-index' is the only interactive function of this
+package and its main entry point; it offers several commands to
+create, find and look up line within the index table.
+
+Commands known:
+
+ occur: Incremental search, that shows matching lines from the
+ index table, updated after every keystroke. You may enter a
+ list of words seperated by space or comma (\",\"), to select
+ lines that contain all of the given words.
+
+ You may also read the note at the end of this help on saving
+ the keystroke RET with this frequent default command.
+
+ head: If invoked outside the index table, ask for a reference
+ number and search for an entry, which either has this
+ reference contained in its heading or within its property
+ org-index-ref. If invoked from within the index table dont
+ ask; rather use the reference or link from the current line.
+
+ ref: Create a new reference, copy any previously selected text.
+ If already within index table, fill in ref-column.
+
+ link: Create a new line in index table with a link to the
+ current node. Do not populate the ref column; this can later
+ be populated by calling the \"fill\" command from within the
+ index table.
+
+ leave: Leave the index table. If the last command has been
+ \"ref\", the new reference is copied and ready to yank. This
+ \"org-mark-ring-goto\" and can be called several times in
+ succession. If you invoke org-index with a prefix argument,
+ this command \"leave\" is executed without further questions.
+
+ put: Put the reference, that was created last, as the value of
+ property org-index-ref into the current node. That way it can
+ be found by a later call to \"head\".
+
+ enter: Just enter the node with the index table.
+
+ goto: Enter index table and go to a specific reference.
+
+ help: Show this text.
+
+ +: Show all commands including the less frequently used ones
+ given below. If \"+\" is followd by enough letters of such a
+ command (e.g. \"+fi\"), then this command (e.g. \"fill\") is
+ invoked directly.
+
+ reorder: Temporarily reorder the index table, e.g. by count,
+ reference or last access.
+
+ fill: If either ref or link is missing in current line of index
+ table, fill in the missing value.
+
+ sort: Sort a set of lines (either from the active region or the
+ whole buffer) by references found in each line.
+
+ update: For the given reference, update the line in the
+ index table, i.e. increment its count.
+
+ multi-occur: Apply emacs standard multi-occur operation on all
+ org-mode buffers to search for the given reference.
+
+ highlight: Highlight references in active region or buffer.
+
+ unhighlight: Remove those highlights.
+
+ missing : Search for missing reference numbers (which do not
+ appear in the reference table). If requested, add additional
+ lines for them, so that the command \"ref\" is able to reuse
+ them.
+
+ statistics : Show some statistics (e.g. minimum and maximum
+ reference) about index table.
+
+
+
+Two ways to save keystrokes:
+
+When prompting for a command, org-index puts the most likely
+one (e.g. \"occur\" or \"ref\") in front of the list, so that
+you may just type RET.
+
+If this first command in the list of commands needs additional
+input (like e.g. \"occur\"), you may supply this input right
+away, although you are still beeing prompted for the command. So,
+to do an occur for the string \"foo\", you can just enter \"foo\"
+RET, without even typing \"occur\".
+
+
+Another way to save keystrokes applies if you want to choose a
+command, that requrires a reference number and would normally
+prompt for it: In that case you may just enter enough characters
+from your command, so that it appears first in the list of
+matches; then immediately enter the number of the reference you
+are searching for. So the input \"h237\" would execute the
+command \"head\" for reference \"237\".
+
+"
+
+ (interactive "P")
+
+ (let ((org-index--silent nil) ; t, if user can be asked
+ link-id ; link of starting node, if required
+ what ; what to do
+ search ; what to search for
+ guarded-search ; with guard against additional digits
+ search-ref ; search, if search is a reference
+ search-link ; search, if search is a link
+ what-adjusted ; true, if we had to adjust what
+ what-input ; Input on what question (need not necessary be "what")
+ reorder-once ; column to use for single time sorting
+ kill-new-text ; text that will be appended to kill ring
+ message-text ; text that will be issued as an explanation
+ initial-ref-or-link ; initial position in index table
+ )
+
+
+ ;;
+ ;; Initialize and parse
+ ;;
+
+ ;; creates index table, if necessary
+ (org-index--verify-id)
+
+ ;; store context information
+ (org-index--retrieve-context)
+
+ ;; Get configuration of index table
+ (org-index--parse-table)
+
+
+ ;;
+ ;; Find out, what we are supposed to do
+ ;;
+
+ (if ARG
+ (if (equal ARG '(4))
+ (setq what 'leave)
+ (if (and (symbolp ARG)
+ (memq ARG org-index--commands))
+ (setq what ARG)
+ (error "Unknown command '%s' passed as argument, valid choices are a prefix argument or any of these symbols: %s"
+ ARG (mapconcat 'symbol-name org-index--commands ","))))
+
+ (let ((r (org-index--read-what what))) ; query user if not from argument
+ (setq what (nth 0 r))
+ (setq what-input (nth 1 r))
+ (setq reorder-once (nth 2 r))))
+
+
+ ;;
+ ;; Get search, if required
+ ;;
+
+ ;; These actions need a search string:
+ (when (memq what '(goto occur head update))
+ ;; Maybe we've got a search string from the arguments
+ (setq search (org-index--get-or-read-search search what what-input))
+
+ (when search
+ (when (string-match org-index--ref-regex search)
+ (setq search-ref search)
+ (setq guarded-search (org-index--make-guarded-search search)))
+ (when (string-match "^[a-fA-F0-9]\\{8\\}-[a-fA-F0-9]\\{4\\}-[a-fA-F0-9]\\{4\\}-[a-fA-F0-9]\\{4\\}-[a-fA-F0-9]\\{12\\}$" search)
+ (setq search-link search))))
+
+
+ ;;
+ ;; Do some sanity checking before really starting
+ ;;
+
+ ;; Correct requested action, if nothing to search
+ (when (and (not search)
+ (memq what '(search head)))
+ (setq what 'enter)
+ (setq what-adjusted t))
+
+ ;; Check for invalid combinations of arguments; try to be helpful
+ (when (and (memq what '(head goto))
+ (not search-ref)
+ (not search-link))
+ (error "Can do '%s' only for a reference or link (not '%s'), try 'occur' to search for text" what search))
+
+
+ ;;
+ ;; Sort and enter table
+ ;;
+
+ ;; Get link if required before moving in
+ (if (eq what 'link)
+ (let ((org-id-link-to-org-use-id t))
+ (setq link-id (org-id-get-create))))
+
+ ;; Save initial ref or link for later return
+ (if (and org-index--within-node
+ (org-at-table-p))
+ (setq initial-ref-or-link
+ (or (org-index--get-field :ref)
+ (org-index--get-field :link))))
+
+ ;; These commands enter index table only temporarily
+ (when (memq what '(occur multi-occur statistics))
+
+ (set-buffer org-index--buffer)
+ (goto-char org-index--point)
+
+ ;; Sort and align
+ (org-index--sort reorder-once)
+ (org-index--align))
+
+ ;; These commands will leave user in index table after they are finished
+ (when (memq what '(enter ref link goto missing))
+
+ ;; Support orgmode-standard of going back (buffer and position)
+ (org-mark-ring-push)
+
+ (org-pop-to-buffer-same-window org-index--buffer)
+ (goto-char org-index--point)
+ (show-subtree)
+ (org-show-context)
+
+ ;; Sort and align
+ (org-index--sort reorder-once)
+ (org-index--align)
+
+ ;; Remember position for leave
+ (if org-index--point-before
+ (setq org-index--point-saved org-index--point-before)))
+
+ ;; prepare to return to initial position in index table
+ (when initial-ref-or-link
+ (while (and (org-at-table-p)
+ (not (or
+ (string= initial-ref-or-link (org-index--get-field :ref))
+ (string= initial-ref-or-link (org-index--get-field :link)))))
+ (forward-line))
+ ;; did not find ref, go back to top
+ (if (not (org-at-table-p)) (goto-char org-index--point)))
+
+
+ ;;
+ ;; Actually do, what is requested
+ ;;
+
+ (cond
+
+
+ ((eq what 'help)
+
+ ;; bring up help-buffer for this function
+ (describe-function 'org-index))
+
+
+ ((eq what 'multi-occur)
+
+ ;; Position point in index buffer on reference to search for
+ (goto-char org-index--below-hline)
+ (let (found (initial (point)))
+ (while (and (not found)
+ (forward-line)
+ (org-at-table-p))
+ (save-excursion
+ (setq found (string= search
+ (org-index--get-field :ref)))))
+ (if found
+ (org-index--update-line nil)
+ (goto-char initial)))
+
+ ;; Construct list of all org-buffers
+ (let (buff org-buffers)
+ (dolist (buff (buffer-list))
+ (set-buffer buff)
+ (if (string= major-mode "org-mode")
+ (setq org-buffers (cons buff org-buffers))))
+
+ ;; Do multi-occur
+ (multi-occur org-buffers guarded-search)
+
+ ;; Present results
+ (if (get-buffer "*Occur*")
+ (progn
+ (setq message-text (format "multi-occur for '%s'" search))
+ (other-window 1)
+ (toggle-truncate-lines 1))
+ (setq message-text (format "Did not find '%s'" search)))))
+
+
+ ((eq what 'head)
+
+ (let (link)
+ (if (and org-index--within-node
+ (org-at-table-p))
+ (setq link (org-index--get-field :link))))
+
+ (setq message-text (org-index--do-head search-ref search-link)))
+
+
+ ((eq what 'leave)
+
+ (setq kill-new-text org-index--text-to-yank)
+ (setq org-index--text-to-yank nil)
+
+ ;; If "leave" has been called two times in succession, make
+ ;; org-mark-ring-goto believe it has been called two times too
+ (if (eq org-index--last-action 'leave)
+ (let ((this-command nil) (last-command nil))
+ (org-mark-ring-goto 1))
+ (org-mark-ring-goto))
+
+ ;; Return to saved position in index buffer
+ (when org-index--point-saved
+ ;; buffer displayed in window need to set point there first
+ (if (eq (window-buffer org-index--active-window-index)
+ org-index--buffer)
+ (set-window-point org-index--active-window-index (marker-position org-index--point-saved)))
+ ;; set position in buffer in any case and second
+ (with-current-buffer org-index--buffer
+ (goto-char org-index--point-saved)))
+ (setq org-index--point-saved nil))
+
+
+ ((eq what 'goto)
+
+ ;; Go downward in table to requested reference
+ (let (found (initial (point)))
+ (goto-char org-index--below-hline)
+ (while (and (not found)
+ (forward-line)
+ (org-at-table-p))
+ (save-excursion
+ (setq found
+ (string= search
+ (org-index--get-field
+ (if search-link :link :ref))))))
+ (if found
+ (progn
+ (setq message-text (format "Found '%s'" search))
+ (org-index--update-line nil)
+ (org-table-goto-column (org-index--column-num :ref))
+ (if (looking-back " ") (backward-char))
+ ;; remember string to copy
+ (setq org-index--text-to-yank
+ (org-trim (org-table-get-field (org-index--column-num :copy)))))
+ (setq message-text (format "Did not find '%s'" search))
+ (goto-char initial)
+ (forward-line)
+ (setq what 'missed))))
+
+
+ ((eq what 'occur)
+
+ (org-index--do-occur what-input))
+
+
+ ((memq what '(ref link))
+
+ (let (new)
+
+ ;; add a new row (or reuse existing one)
+ (setq new (org-index--do-new-line (eq what 'ref)))
+
+ ;; fill special columns with standard values
+ (when (eq what 'ref)
+ (org-table-goto-column (org-index--column-num :ref))
+ (insert new)
+ (setq org-index--last-ref new))
+ (when (eq what 'link)
+ (org-table-goto-column (org-index--column-num :link))
+ (insert link-id))
+
+ (org-index--align)
+
+ ;; goto point-field or copy-field or first empty one or first field
+ (if (org-index--special-column :point)
+ (org-table-goto-column (org-index--column-num (org-index--special-column :point)))
+ (if (org-index--special-column :copy)
+ (org-table-goto-column (org-index--column-num (org-index--special-column :copy)))
+ (unless (catch 'empty
+ (dotimes (col org-index--numcols)
+ (org-table-goto-column (+ col 1))
+ (if (string= (org-trim (org-table-get-field)) "")
+ (throw 'empty t))))
+ ;; none found, goto first
+ (org-table-goto-column 1))))
+
+ (if org-index--active-region (setq kill-new-text org-index--active-region))
+ (if (eq what 'ref)
+ (setq message-text (format "Adding a new row with ref '%s'" new))
+ (setq message-text (format "Adding a new row linked to '%s'" link-id)))))
+
+
+ ((eq what 'put)
+
+ ;; put latest reference into property
+
+
+ (if org-index--last-ref
+ (progn
+ (org-entry-put (point) "org-index-ref" org-index--last-ref)
+ (message "Reference '%s' has been stored in property org-index-ref" org-index--last-ref))
+ (setq org-index--last-ref
+ (read-from-minibuffer "Reference to be stored in this node: "))
+ (unless org-index--last-ref
+ (message "No reference has been given."))
+ ))
+
+
+ ((eq what 'enter)
+
+ ;; simply go into table
+ (goto-char org-index--below-hline)
+ (show-subtree)
+ (recenter)
+ (if what-adjusted
+ (setq message-text "Nothing to search for; at index table")
+ (setq message-text "At index table")))
+
+
+ ((eq what 'fill)
+
+ ;; check, if within index table
+ (unless (and org-index--within-node
+ (org-at-table-p))
+ (error "Not within index table"))
+
+ ;; applies to missing refs and missing links alike
+ (let ((ref (org-index--get-field :ref))
+ (link (org-index--get-field :link)))
+
+ (if (and (not ref)
+ (not link))
+ ;; have already checked this during parse, check here anyway
+ (error "Columns ref and link are both empty in this line"))
+
+ ;; fill in new ref
+ (if (not ref)
+ (progn
+ (setq kill-new-text (format "%s%d%s" org-index--head (1+ org-index--maxref) org-index--tail))
+ (org-index--get-field :ref kill-new-text)
+ ;; remember for org-mark-ring-goto
+ (setq org-index--text-to-yank kill-new-text)
+ (org-id-goto link)
+ (setq message-text "Filled field of index table with new reference"))
+
+ ;; fill in new link
+ (if (not link)
+ (progn
+ (setq guarded-search (org-index--make-guarded-search ref))
+ (message (format "Scanning headlines for '%s' ..." ref))
+ (let ((search (concat ".*" guarded-search))
+ link)
+ (if (catch 'found
+ (org-map-entries
+ (lambda ()
+ (when (looking-at search)
+ (setq link (org-id-get-create))
+ (throw 'found t)))
+ nil 'agenda)
+ nil)
+
+ (progn
+ (org-index--get-field :link link)
+ (setq message-text "Inserted link"))
+
+ (setq message-text (format "Did not find reference '%s'" ref)))))
+
+ ;; nothing is missing
+ (setq message-text "Columns ref and link are already filled; nothing to do")))))
+
+
+ ((eq what 'sort)
+
+ ;; sort lines according to contained reference
+ (let (begin end where)
+ (catch 'aborted
+ ;; either active region or whole buffer
+ (if (and transient-mark-mode
+ mark-active)
+ ;; sort only region
+ (progn
+ (setq begin (region-beginning))
+ (setq end (region-end))
+ (setq where "region"))
+ ;; sort whole buffer
+ (setq begin (point-min))
+ (setq end (point-max))
+ (setq where "whole buffer")
+ ;; make sure
+ (unless (y-or-n-p "Sort whole buffer ")
+ (setq message-text "Sort aborted")
+ (throw 'aborted nil)))
+
+ (save-excursion
+ (save-restriction
+ (goto-char (point-min))
+ (narrow-to-region begin end)
+ (sort-subr nil 'forward-line 'end-of-line
+ (lambda ()
+ (if (looking-at (concat ".*"
+ (org-index--make-guarded-search org-index--ref-regex 'dont-quote)))
+ (string-to-number (match-string 1))
+ 0))))
+ (highlight-regexp org-index--ref-regex 'isearch)
+ (setq message-text (format "Sorted %s from character %d to %d, %d lines"
+ where begin end
+ (count-lines begin end)))))))
+
+
+ ((eq what 'update)
+
+ ;; simply update line in index table
+ (save-excursion
+ (let ((ref-or-link (if search-link "link" "reference")))
+ (beginning-of-line)
+ (if (org-index--update-line search)
+ (setq message-text (format "Updated %s '%s'" ref-or-link search))
+ (setq message-text (format "Did not find %s '%s'" ref-or-link search))))))
+
+
+ ((memq what '(highlight unhighlight))
+
+ (let ((where "buffer"))
+ (save-excursion
+ (save-restriction
+ (when (and transient-mark-mode
+ mark-active)
+ (narrow-to-region (region-beginning) (region-end))
+ (setq where "region"))
+
+ (if (eq what 'highlight)
+ (progn
+ (highlight-regexp org-index--ref-regex 'isearch)
+ (setq message-text (format "Highlighted references in %s" where)))
+ (unhighlight-regexp org-index--ref-regex)
+ (setq message-text (format "Removed highlights for references in %s" where)))))))
+
+
+ ((memq what '(missing statistics))
+
+ (setq message-text (org-index--do-statistics what)))
+
+
+ (t (error "This is a bug: unmatched case '%s'" what)))
+
+
+ ;; remember what we have done for next time
+ (setq org-index--last-action what)
+
+ ;; tell, what we have done and what can be yanked
+ (if kill-new-text (setq kill-new-text
+ (substring-no-properties kill-new-text)))
+ (if (string= kill-new-text "") (setq kill-new-text nil))
+ (let ((m (concat
+ message-text
+ (if (and message-text kill-new-text)
+ " and r"
+ (if kill-new-text "R" ""))
+ (if kill-new-text (format "eady to yank '%s'" kill-new-text) ""))))
+ (unless (string= m "") (message m)))
+ (if kill-new-text (kill-new kill-new-text))))
+
+
+(defun org-index-new-line (&rest keys-values)
+ "Create a new line within the index table, returning its reference.
+
+The function takes a varying number of arguments pairs; each pair
+is a symbol for an existing column heading followed by its value.
+their values.
+
+Example:
+
+ (org-index-new-line :ref t :x1 \"foo\" :link \"7f480c3e\")
+
+Passing \":ref t\" will make the function create a new reference within the new line.
+
+"
+
+ (let ((org-index--silent t))
+
+ (save-excursion
+ (org-index--retrieve-context)
+ (with-current-buffer org-index--buffer
+ (goto-char org-index--point)
+ (org-index--parse-table)
+
+ ;; check arguments early
+ (let ((kvs keys-values)
+ k v)
+ (while kvs
+ (setq k (car kvs))
+ (setq v (cadr kvs))
+ (if (eq k :ref)
+ (unless (memq v '(t nil))
+ (error "Argument :ref accepts only t or nil"))
+ (if (or (not (symbolp k))
+ (symbolp v))
+ (error "Arguments must be alternation of key and value")))
+ (unless (> (org-index--column-num k) 0)
+ (error "Unknown column or column not defined in table: '%s'" (symbol-name k)))
+ (setq kvs (cddr kvs))))
+
+ (if (and (not (plist-get keys-values :ref))
+ (not (stringp (plist-get keys-values :link))))
+ (error "Need a link when not creating a ref"))
+
+ (let (new)
+ ;; create new line
+ (setq new (org-index--do-new-line (plist-get keys-values :ref)))
+ (plist-put keys-values :ref (or new ""))
+
+ ;; fill columns
+ (let ((kvs keys-values)
+ k v n)
+ (while kvs
+ (setq k (car kvs))
+ (setq v (cadr kvs))
+ (setq n (org-index--column-num k))
+ (org-table-goto-column n)
+ (insert v)
+ (setq kvs (cddr kvs))))
+
+ (org-index--sort)
+ new)))))
+
+
+(defun org-index-get-line (what value)
+ "Retrieve an existing line within the index table by ref or
+link and return its contents as a property list.
+
+The function `plist-get' may be used to retrieve specific values.
+
+Example:
+
+ (plist-get (org-index-get-line \"12\") :count)
+
+retrieves the value of the count-column for reference 12.
+
+"
+ (interactive)
+ (let ((org-index--silent t)
+ found)
+
+ ;; check arguments
+ (unless (memq what '(:ref :link))
+ (error "Argument what can only be :ref or :link"))
+
+ (save-excursion
+ (org-index--retrieve-context)
+ (with-current-buffer org-index--buffer
+ (goto-char org-index--point)
+ (org-index--parse-table)
+
+ (goto-char org-index--below-hline)
+ (while (and (not found)
+ (org-at-table-p))
+ (when (string= (org-index--get-field what)
+ value)
+ (mapc (lambda (x)
+ (if (and (numberp (cdr x))
+ (> (cdr x) 0))
+ (setq found (cons (car x) (cons (or (org-index--get-field (car x)) "") found)))
+ )) (reverse org-index--columns)))
+ (forward-line))
+ found))))
+
+
+(defun org-index--read-what (what)
+ "Find out, what we are supposed to do"
+
+ (let (commands ; currently active set of selectable commands
+ trailing-digits ; any digits, that are are appended to what-input
+ reorder-once ; Column to use for single time sorting
+ what-input) ; Input on what question (need not necessary be "what")
+
+ ;; Set preferred action, that will be the default choice
+ (setq org-index--preferred-command
+ (if org-index--within-node
+ (if (memq org-index--last-action '(ref link))
+ 'leave
+ 'goto)
+ (if org-index--active-region
+ 'ref
+ (if (and org-index--below-cursor (string-match org-index--ref-regex org-index--below-cursor))
+ 'occur
+ nil))))
+
+ ;; Ask user, what to do
+ (if what
+ (setq what-input (symbol-name what))
+ ;; subset of most common commands for initial selection, ie. up to first plus
+ (setq commands (copy-list org-index--commands))
+ (let ((c commands))
+ (while (and c (not (eq (car c) '+)))
+ (setq c (cdr c)))
+ (setcdr c nil))
+
+ (while (let (completions starts-with-plus is-only-plus)
+
+ (setq what-input
+ (org-completing-read
+ "Please choose: "
+ (mapcar 'symbol-name
+ ;; Construct unique list of commands with
+ ;; preferred one at front
+ (delq nil (delete-dups
+ (append
+ (list org-index--preferred-command)
+ (copy-list commands)))))
+ nil nil))
+
+ ;; if input ends in digits, save them away and do completions on head of input
+ ;; this allows input like "h224" to be accepted
+ (when (string-match "^\\([^0-9]+\\)\\([0-9]+\\)\\s *$" what-input)
+ ;; remember digits
+ (setq trailing-digits (string-to-number (match-string 2 what-input)))
+ ;; and use non-digits-part to find match
+ (setq what-input (match-string 1 what-input)))
+
+ ;; if input starts with "+", any command (not only some) may follow
+ ;; this allows input like "+sort" to be accepted
+ (when (and (> (length what-input) 0)
+ (string= (substring what-input 0 1) "+"))
+ ;; make all commands available for selection
+ (setq commands (copy-list org-index--commands))
+ (setq what-input (substring what-input 1))
+ (setq starts-with-plus (> (length what-input) 0))
+ (setq is-only-plus (not starts-with-plus)))
+
+ ;; get list of possible completions for what-input; i.e.
+ ;; all commands, that start with what-input
+ (setq completions (delq nil (mapcar
+ (lambda (x)
+ (let ((where (search what-input (symbol-name x))))
+ (if (and where
+ (= where 0))
+ x
+ nil))) commands)))
+
+ ;; if input starts with "+" and not just "+"
+ (when starts-with-plus
+ ;; use first completion, if unambigously
+ (if (= (length completions) 1)
+ (setq what-input (symbol-name (car completions)))
+ (if completions
+ (error "Input \"+%s\" matches multiple commands: %s"
+ what-input
+ (mapconcat 'symbol-name completions ", "))
+ (error "Input \"+%s\" matches no commands" what-input))))
+
+ ;; if input ends in digits, use first completion, even if ambigous
+ ;; this allows input like "h224" to be accepted
+ (when (and trailing-digits completions)
+ ;; use first match as input, even if ambigously
+ (setq org-index--preferred-command (first completions))
+ (setq what-input (number-to-string trailing-digits)))
+
+ ;; convert to symbol
+ (setq what (intern what-input))
+ (if is-only-plus (setq what '+))
+
+ ;; user is not required to input one of the commands; if
+ ;; not, take the first one and use the original input for
+ ;; next question
+ (if (memq what commands)
+ ;; input matched one element of list, dont need original
+ ;; input any more
+ (setq what-input nil)
+ ;; what-input will be used for next question, use first
+ ;; command for what
+ (setq what (or org-index--preferred-command
+ (first commands)))
+ ;; remove any trailing dot, that user might have added to
+ ;; disambiguate his input
+ (if (and (> (length what-input) 0)
+ (equal (substring what-input -1) "."))
+ ;; but do this only, if dot was really necessary to
+ ;; disambiguate
+ (let ((shortened-what-input (substring what-input 0 -1)))
+ (unless (test-completion shortened-what-input
+ (mapcar 'symbol-name
+ commands))
+ (setq what-input shortened-what-input)))))
+
+ ;; ask for reorder in loop, because we have to ask for
+ ;; what right again
+ (if (eq what 'reorder)
+ (setq reorder-once
+ (intern
+ (org-icompleting-read
+ "Please choose column to reorder index table once: "
+ (mapcar 'symbol-name
+ (append '(:ref :count :first :last)
+ (delq nil (mapcar (lambda (x) (if (> (cdr (assoc x org-index--columns)) 0) x nil))
+ '(:x1 :x2 :x3)))))
+ nil t))))
+
+ ;; maybe ask initial question again
+ (memq what '(reorder +)))))
+ (list what what-input reorder-once)))
+
+
+(defun org-index--get-or-read-search (search what what-input)
+ "Get search string, maybe read from user"
+
+ (let (search-from-table
+ search-from-cursor)
+
+ (unless search
+ ;; Search string can come from several sources:
+ ;; From link or ref columns of table
+ (when (and org-index--within-node
+ (org-at-table-p))
+ (setq search-from-table (or (org-index--get-field :link)
+ (org-index--get-field :ref))))
+
+ ;; From string below cursor
+ (when (and (not org-index--within-node)
+ org-index--below-cursor
+ (string-match (concat "\\(" org-index--ref-regex "\\)")
+ org-index--below-cursor))
+ (setq search-from-cursor (match-string 1 org-index--below-cursor)))
+
+ ;; Depending on requested action, get search from one of the sources above
+ (cond ((eq what 'goto)
+ (setq search (or what-input search-from-cursor)))
+ ((memq what '(head occur))
+ (setq search (or what-input search-from-table search-from-cursor)))))
+
+
+ ;; If we still do not have a search string, ask user explicitly
+ (unless search
+
+ (if org-index--silent (error "Need to specify search, if silence is required"))
+
+ (unless (eq what 'occur)
+
+ (if what-input
+ (setq search what-input)
+ (setq search (read-from-minibuffer
+ (cond ((eq what 'head)
+ "Text or reference number to search for: ")
+ ((eq what 'goto)
+ "Reference number to search for, or enter \".\" for id of current node: ")
+ ((eq what 'update)
+ "Reference number to update: ")))))
+
+ (if (string-match "^\\s *[0-9]+\\s *$" search)
+ (setq search (format "%s%s%s" org-index--head search org-index--tail)))))
+
+
+ ;; Clean up and examine search string
+ (when search
+ (setq search (org-trim search))
+ (if (string= search "") (setq search nil))
+ (when search
+ (if (string-match "^[0-9]+$" search)
+ (setq search (concat org-index--head search org-index--tail)))))
+
+ ;; Check for special case
+ (when (and (memq what '(head goto))
+ (string= search "."))
+ (setq search (org-id-get)))
+
+ search))
+
+
+(defun org-index--verify-id ()
+
+ ;; Check id
+ (unless org-index-id
+ (org-index--create-new-index
+ t
+ (format "No index table has been created yet." org-index-id)))
+
+ ;; Find node
+ (let (marker)
+ (setq marker (org-id-find org-index-id 'marker))
+ (unless marker (org-index--create-new-index
+ t
+ (format "Cannot find node with id \"%s\"" org-index-id)))
+ ; Try again with new node
+ (setq marker (org-id-find org-index-id 'marker))
+ (unless marker (error "Could not create node"))
+ (setq org-index--buffer (marker-buffer marker)
+ org-index--point (marker-position marker))
+ (move-marker marker nil)))
+
+
+(defun org-index--retrieve-context ()
+
+ ;; Get the content of the active region or the word under cursor
+ (setq org-index--active-region
+ (if (and transient-mark-mode mark-active)
+ (buffer-substring (region-beginning) (region-end))
+ nil))
+ (setq org-index--below-cursor (thing-at-point 'symbol))
+
+ ;; Find out, if we are within favable or not
+ (setq org-index--within-node (string= (org-id-get) org-index-id))
+
+ ;; Check and remember, if active window contains buffer with index table
+ (if (eq (window-buffer) org-index--buffer)
+ (setq org-index--active-window-index (selected-window)))
+
+ ;; get current position in index-buffer
+ (with-current-buffer org-index--buffer
+ (setq org-index--point-before
+ (if (string= (org-id-get) org-index-id)
+ nil
+ (point-marker)))))
+
+
+(defun org-index--parse-table ()
+
+ (let (ref-field
+ link-field
+ initial-point
+ end-of-heading)
+
+ (with-current-buffer org-index--buffer
+
+ (setq org-index--maxref 0)
+ (setq initial-point (point))
+ (org-index--go-below-hline)
+ (setq org-index--below-hline (point))
+ (beginning-of-line)
+ (setq end-of-heading (point))
+ (while (org-at-table-p) (forward-line -1))
+ (forward-line)
+ (setq org-index--headings (buffer-substring (point) end-of-heading))
+ (goto-char org-index--below-hline)
+
+
+ ;; count columns
+ (org-table-goto-column 100)
+ (setq org-index--numcols (- (org-table-current-column) 1))
+
+ ;; get contents of columns
+ (forward-line -2)
+ (unless (org-at-table-p)
+ (org-index--create-new-index
+ nil
+ "Index table starts with a hline"))
+
+ ;; check for optional line consisting solely of width specifications
+ (beginning-of-line)
+ (if (looking-at "\\s *|\\(\\(\\s *|\\)\\|\\(\\s *<[0-9]+>\\s *|\\)\\)+\\s *$")
+ (forward-line -1))
+ (org-table-goto-column 1)
+
+ (org-index--parse-headings)
+
+ ;; Go beyond end of table
+ (while (org-at-table-p) (forward-line 1))
+
+ ;; Retrieve any decorations around the number within the first nonempty ref-field
+ (goto-char org-index--below-hline)
+ (while (and (org-at-table-p)
+ (not (setq ref-field (org-index--get-field :ref))))
+ (forward-line))
+
+ ;; Some Checking
+ (unless ref-field
+ (org-index--create-new-index
+ nil
+ "Reference column is empty"))
+
+ (unless (string-match "^\\([^0-9]*\\)\\([0-9]+\\)\\([^0-9]*\\)$" ref-field)
+ (org-index--create-new-index
+ nil
+ (format "First reference in index table ('%s') does not contain a number" ref-field)))
+
+
+ ;; These are the decorations used within the first ref of index
+ (setq org-index--head (match-string 1 ref-field))
+ (setq org-index--tail (match-string 3 ref-field))
+ (setq org-index--ref-regex (concat (regexp-quote org-index--head)
+ "\\([0-9]+\\)"
+ (regexp-quote org-index--tail)))
+ (setq org-index--ref-format (concat org-index--head "%d" org-index--tail))
+
+
+ ;; Go through table to find maximum number and do some checking
+ (let ((ref 0))
+
+ (while (org-at-table-p)
+
+ (setq ref-field (org-index--get-field :ref))
+ (setq link-field (org-index--get-field :link))
+
+ (when (and (not ref-field)
+ (not link-field))
+ (org-pop-to-buffer-same-window org-index--buffer)
+ (org-reveal)
+ (error "Columns ref and link are both empty in this line"))
+
+ (if ref-field
+ (if (string-match org-index--ref-regex ref-field)
+ ;; grab number
+ (setq ref (string-to-number (match-string 1 ref-field)))
+ (org-pop-to-buffer-same-window org-index--buffer)
+ (org-reveal)
+ (error "Column ref does not contain a number")))
+
+ ;; check, if higher ref
+ (if (> ref org-index--maxref) (setq org-index--maxref ref))
+
+ ;; check if ref is ment for reuse
+ (if (string= (org-index--get-field :count) ":reuse:")
+ (setq org-index--has-reuse t))
+
+ (forward-line 1)))
+
+ ;; go back to initial position
+ (goto-char initial-point))))
+
+
+(defun org-index--sort (&optional sort-column)
+
+ (unless sort-column (setq sort-column (org-index--special-column :sort)))
+
+ (let (top
+ bottom
+ ref-field
+ count-field
+ count-special)
+
+ (unless buffer-read-only
+
+ ;; get boundaries of table
+ (goto-char org-index--below-hline)
+ (forward-line 0)
+ (setq top (point))
+ (while (org-at-table-p) (forward-line))
+
+ ;; Kill all empty rows at bottom
+ (while (progn
+ (forward-line -1)
+ (org-table-goto-column 1)
+ (and
+ (not (org-index--get-field :ref))
+ (not (org-index--get-field :link))))
+ (org-table-kill-row))
+ (forward-line 1)
+ (setq bottom (point))
+
+ (save-restriction
+ (narrow-to-region top bottom)
+ (goto-char top)
+ (sort-subr t
+ 'forward-line
+ 'end-of-line
+ (lambda ()
+ (let (ref
+ (ref-field (or (org-index--get-field :ref) ""))
+ (count-field (or (org-index--get-field :count) ""))
+ (count-special 0))
+
+ ;; get reference with leading zeroes, so it can be
+ ;; sorted as text
+ (string-match org-index--ref-regex ref-field)
+ (setq ref (format
+ "%06d"
+ (string-to-number
+ (or (match-string 1 ref-field)
+ "0"))))
+
+ ;; find out, if special token in count-column
+ (setq count-special (format "%d"
+ (- 2
+ (length (member count-field '(":missing:" ":reuse:"))))))
+
+ ;; Construct different sort-keys according to
+ ;; requested sort column; prepend count-special to
+ ;; sort special entries at bottom of table, append ref
+ ;; as a secondary sort key
+ (cond
+
+ ((eq sort-column :count)
+ (concat count-special
+ (format
+ "%08d"
+ (string-to-number (or (org-index--get-field :count)
+ "")))
+ ref))
+
+ ((eq sort-column :ref)
+ (concat count-special
+ ref))
+
+ ((memq sort-column '(:last :x1 :x2 :x3))
+ (concat count-special
+ (org-index--get-field sort-column)
+ " "
+ ref))
+
+ (t (error "This is a bug: unmatched case '%s'" sort-column)))))
+
+ nil 'string<))
+
+ ;; sorting has moved point below hline
+ (org-index--go-below-hline)
+ (setq org-index--below-hline (point)))))
+
+
+(defun org-index--go-below-hline ()
+
+ (goto-char org-index--point)
+ ;; go to heading of node
+ (while (not (org-at-heading-p)) (forward-line -1))
+ (forward-line 1)
+ ;; go to table within node, but make sure we do not get into another node
+ (while (and (not (org-at-heading-p))
+ (not (org-at-table-p))
+ (not (eq (point) (point-max))))
+ (forward-line 1))
+
+ ;; check, if there really is a table
+ (unless (org-at-table-p)
+ (org-index--create-new-index
+ t
+ (format "Cannot find index table within node %s" org-index-id)))
+
+ ;; go to first hline
+ (while (and (not (org-at-table-hline-p))
+ (org-at-table-p))
+ (forward-line 1))
+
+ ;; and check
+ (unless (org-at-table-hline-p)
+ (org-index--create-new-index
+ nil
+ "Cannot find hline within index table"))
+
+ (forward-line 1)
+ (org-table-goto-column 1))
+
+
+(defun org-index--align ()
+ (unless buffer-read-only (org-table-align))
+ (org-index--go-below-hline)
+ (setq org-index--below-hline (point)))
+
+
+(defun org-index--parse-headings ()
+
+ ;; Associate names of special columns with column-numbers
+ (setq org-index--columns (copy-tree '((:ref . 0) (:link . 0) (:first . 0) (:last . 0)
+ (:count . 0) (:x1 . 0) (:x2 . 0) (:x3 . 0))))
+
+ ;; Associate names of special columns with names of columns
+ (setq org-index--special-columns (copy-tree '((:sort . nil) (:copy . nil) (:point . nil))))
+
+ ;; For each column
+ (dotimes (col org-index--numcols)
+ (let* (field-flags ;; raw heading, consisting of file name and maybe
+ ;; flags (seperated by ";")
+ field ;; field name only
+ field-symbol ;; and as a symbol
+ flags ;; flags from field-flags
+ found)
+
+ ;; parse field-flags into field and flags
+ (setq field-flags (org-trim (org-table-get-field (+ col 1))))
+ (if (string-match "^\\([^;]*\\);\\([a-z]+\\)$" field-flags)
+ (progn
+ (setq field (downcase (or (match-string 1 field-flags) "")))
+ ;; get flags as list of characters
+ (setq flags (mapcar 'string-to-char
+ (split-string
+ (downcase (match-string 2 field-flags))
+ "" t))))
+ ;; no flags
+ (setq field field-flags))
+
+ (unless (string= field "") (setq field-symbol (intern (concat ":" (downcase field)))))
+ ;; aliases for backward compatability
+ (if (eq field-symbol :last-accessed) (setq field-symbol :last))
+ (if (eq field-symbol :created) (setq field-symbol :first))
+
+ (if (and field-symbol
+ (not (assoc field-symbol org-index--columns)))
+ (error "Column %s is not a valid heading" (symbol-name field-symbol)))
+
+ ;; Check, that no flags appear twice
+ (mapc (lambda (x)
+ (when (memq (car x) flags)
+ (if (cdr (assoc (cdr x) org-index--columns))
+ (org-index--create-new-index
+ nil
+ (format "More than one heading is marked with flag '%c'" (car x))))))
+ '((?s . sort)
+ (?c . copy)))
+
+ ;; Process flags
+ (if (memq ?s flags)
+ (setcdr (assoc :sort org-index--special-columns) (or field-symbol (+ col 1))))
+ (if (memq ?c flags)
+ (setcdr (assoc :copy org-index--special-columns) (or field-symbol (+ col 1))))
+ (if (memq ?p flags)
+ (setcdr (assoc :point org-index--special-columns) (or field-symbol (+ col 1))))
+
+ ;; Store columns in alist
+ (setq found (assoc field-symbol org-index--columns))
+ (when found
+ (if (> (cdr found) 0)
+ (org-index--create-new-index
+ nil
+ (format "'%s' appears two times as column heading" (downcase field))))
+ (setcdr found (+ col 1)))))
+
+ ;; check if all necessary informations have been specified
+ (mapc (lambda (col)
+ (unless (> (cdr (assoc col org-index--columns)) 0)
+ (org-index--create-new-index
+ nil
+ (format "column '%s' has not been set" col))))
+ (list :ref :link :count :first :last))
+
+ ;; use count as a default sort-column
+ (unless (cdr (assoc :sort org-index--special-columns))
+ (setcdr (assoc :sort org-index--special-columns) :count)))
+
+
+(defun org-index--create-new-index (create-new-index reason)
+ "Create a new empty index table with detailed explanation."
+ (let (prompt buffer-name title firstref id)
+
+ ;; cannot proceed without querying user
+ (if org-index--silent (error "No valid index: %s" reason))
+
+ (setq prompt
+ (if create-new-index
+ (concat "There is this problem with the existing index table:\n\n " reason "\n\nThis assistant will guide you to create a new one.\n\nDo you want to proceed ?")
+ (concat "The existing index table contains this error:\n\n " reason "\n\nYou need to correct this error manually before trying again. However, this assistant will help you to create an new initial index table with detailed comments, so that you may fix the errors in your existing table more easily.\n\nDo you want to proceed ?")))
+ (unless (y-or-n-p prompt)
+ (error "Cannot proceed without a valid index table: %s" reason))
+
+ (setq buffer-name (org-completing-read "Please choose the buffer, where the new node for the index table should be created; the new node will be inserted at its end.\n\nBuffer: " (mapcar 'buffer-name (org-buffer-list)) nil nil))
+
+ (setq title (read-from-minibuffer "Please enter the title of the index node: "))
+
+ (while (progn
+ (setq firstref (read-from-minibuffer "Please enter your first reference-number. This is a number preceeded by some non-digit chars and optionally followed by some more non-digit chars, e.g. 'R1', '-1-' or '#1#' (and your initial number does not need to be '1'). The format of your reference-numbers only needs to make sense for yourself, so that you can spot it easily in your texts or write it on a piece of paper; it should however not already appear to frequently within your existing notes, to avoid too many false hits when searching.\n\nPlease choose: "))
+ (let (desc)
+ (unless (equal '(95 119) (sort (delete-dups (mapcar (lambda (x) (char-syntax x)) (concat "-1" firstref))) '<))
+ (setq desc "Contains other characters than those allowed in symbols"))
+ (unless (string-match "^[^0-9]+[0-9]+[^0-9]*$" firstref)
+ ;; firstref not okay, report details
+ (setq desc
+ (cond ((string= firstref "") "is empty")
+ ((not (string-match "^[^0-9]+" firstref)) "starts with a digit")
+ ((not (string-match "^[^0-9]+[0-9]+" firstref)) "does not contain a number")
+ ((not (string-match "^[^0-9]+[0-9]+[^0-9]*$" firstref)) "contains more than one sequence of digits")
+
+ )))
+ (if desc
+ (progn
+ (read-from-minibuffer (format "Your input '%s' does not meet the requirements because it %s. Please hit RET and try again" firstref desc))
+ t)
+ nil))))
+
+ (with-current-buffer buffer-name
+ (goto-char (point-max))
+ (insert (format "\n\n* %s %s\n" firstref title))
+ (insert "\n\n Below you find your initial index table, which will grow over time.\n"
+ " Following that your may read its detailed explanation, which will help you,\n"
+ " to adjust org-index to your needs. This however is optional reading and not\n"
+ " required to start using org-index.\n")
+
+ (setq id (org-id-get-create))
+ (insert (format "
+
+ | | | | | | comment |
+ | ref | link | first | count;s | last | ;c |
+ | | <4> | | | | |
+ |-----+------+-------+---------+------+---------|
+ | %s | %s | %s | | | %s |
+
+"
+ firstref
+ id
+ (with-temp-buffer (org-insert-time-stamp nil nil t))
+ "This node"))
+
+
+ (insert "
+
+ Detailed explanation:
+
+
+ The index table above has three lines of headings above the first
+ hline:
+
+ - The first one is ignored by org-index, and you can use it to
+ give meaningful names to columns. In the table above only one
+ column has a name (\"comment\"). This line is optional.
+
+ - The second line is the most important one, because it
+ contains the configuration information for org-index; please
+ read further below for its format.
+
+ - The third line is again optional; it may only specify the
+ widths of the individual columns (e.g. <4>).
+
+ The columns get their meaning by the second line of headings;
+ specifically by one of the keywords (e.g. \"ref\") or a flag
+ seperated by a semicolon (e.g. \";s\").
+
+
+
+ The keywords and flags are:
+
+
+ - ref: This contains the reference, which consists of a decorated
+ number, which is incremented for each new line. References are
+ meant to be used in org-mode headlines or outside of org,
+ e.g. within folder names.
+
+ - link: org-mode link pointing to the matching location within org.
+
+ - first: When has this line been first accessed (i.e. created) ?
+
+ - count: How many times has this line been accessed ? The
+ trailing flag \"s\" makes the table beeing sorted after this
+ column this column, so that often used entries appear at the
+ top of the table.
+
+ - last: When has this line been accessed last ?
+
+ - The last column above has no keyword, only the flag \"c\",
+ which makes its content beeing copied under certain
+ conditions. It is typically used for comments.
+
+ The sequence of columns does not matter. You may reorder them any
+ way you like. Columns are found by their name, which appears in
+ the second line of headings.
+
+ You can add further columns or even remove the last column. All
+ other columns are required.
+
+ Finally: This node needs not be a top level node; its name is
+ completely at you choice; it is found through its ID only.
+
+")
+
+
+ (while (not (org-at-table-p)) (forward-line -1))
+ (unless buffer-read-only (org-table-align))
+ (while (not (org-at-heading-p)) (forward-line -1))
+
+ ;; present results to user
+ (if create-new-index
+ (progn
+ ;; Only show the new index
+ (org-pop-to-buffer-same-window buffer-name)
+ (delete-other-windows)
+ (org-id-goto id)
+ (org-show-context)
+ (show-subtree)
+ (recenter 1)
+ (setq org-index-id id)
+ (if (y-or-n-p "This is your new index table. It is already set for this emacs session. Do you want to save its id to make it available for future emacs sessions too ? ")
+ (progn
+ (customize-save-variable 'org-index-id id)
+ (error "Saved org-index-id '%s' to %s" id custom-file))
+ (let (sq)
+ (setq sq (format "(setq org-index-id \"%s\")" id))
+ (kill-new sq)
+ (error "Did not make the id of the new index permamanent; you may want to put\n\n %s\n\ninto your own initialization; it is copied already, just yank it." sq))))
+ ;; we had an error with the existing index table, so present old
+ ;; and new one together
+ ;; show existing index
+ (org-pop-to-buffer-same-window org-index--buffer)
+ (goto-char org-index--point)
+ (org-show-context)
+ (show-subtree)
+ (recenter 1)
+ (delete-other-windows)
+ ;; show new index
+ (select-window (split-window-vertically))
+ (org-pop-to-buffer-same-window buffer-name)
+ (org-id-goto id)
+ (org-show-context)
+ (show-subtree)
+ (recenter 1)
+ (error "Please compare your existing index (upper window) and a temporary new one (lower window) to correct the previous error (\"%s\"); the explanations following the new index table should help." reason)))))
+
+
+(defun org-index--update-line (ref-or-link)
+
+ (let ((newcount 0)
+ initial)
+
+ (with-current-buffer org-index--buffer
+ (unless buffer-read-only
+
+ ;; search reference or link, if given (or assume, that we are already positioned right)
+ (when ref-or-link
+ (setq initial (point))
+ (goto-char org-index--below-hline)
+ (while (and (org-at-table-p)
+ (not (or (string= ref-or-link (org-index--get-field :ref))
+ (string= ref-or-link (org-index--get-field :link)))))
+ (forward-line)))
+
+ (if (not (org-at-table-p))
+ (error "Did not find reference or link '%s'" ref-or-link)
+ (org-index--update-current-line))
+
+ (if initial (goto-char initial))))))
+
+
+(defun org-index--update-current-line ()
+ (let (newcount (count-field (org-index--get-field :count)))
+
+ ;; update count field only if number or empty; leave :missing: and :reuse: as is
+ (when (or (not count-field)
+ (string-match "^[0-9]+$" count-field))
+ (setq newcount (+ 1 (string-to-number (or count-field "0"))))
+ (org-index--get-field :count
+ (number-to-string newcount)))
+
+ ;; update timestamp
+ (org-table-goto-column (org-index--column-num :last))
+ (org-table-blank-field)
+ (org-insert-time-stamp nil t t)))
+
+
+(defun org-index--get-field (key &optional value)
+ (let (field)
+ (save-excursion
+ (setq field (org-trim (org-table-get-field (cdr (assoc key org-index--columns)) value)))
+ (if (string= field "") (setq field nil))
+
+ (org-no-properties field))))
+
+
+(defun org-index--column-num (key)
+ (if (numberp key)
+ key
+ (cdr (assoc key org-index--columns))))
+
+
+(defun org-index--special-column (key)
+ (cdr (assoc key org-index--special-columns)))
+
+
+(defun org-index--make-guarded-search (ref &optional dont-quote)
+ (concat "\\_<" (if dont-quote ref (regexp-quote ref)) "\\_>"))
+
+
+(defun org-index--do-statistics (what)
+ (let ((total 0)
+ missing
+ ref-field
+ ref
+ min
+ max
+ message-text)
+
+
+ ;; start with list of all references
+ (setq missing (mapcar (lambda (x) (format "%s%d%s" org-index--head x org-index--tail))
+ (number-sequence 1 org-index--maxref)))
+
+ ;; go through table and remove all refs, that we see
+ (goto-char org-index--below-hline)
+ (while (org-at-table-p)
+
+ ;; get ref-field and number
+ (setq ref-field (org-index--get-field :ref))
+ (if (and ref-field
+ (string-match org-index--ref-regex ref-field))
+ (setq ref (string-to-number (match-string 1 ref-field))))
+
+ ;; remove existing refs from list
+ (if ref-field (setq missing (delete ref-field missing)))
+
+ ;; record min and max
+ (if (or (not min) (< ref min)) (setq min ref))
+ (if (or (not max) (> ref max)) (setq max ref))
+
+ ;; count
+ (setq total (1+ total))
+
+ (forward-line))
+
+ ;; insert them, if requested
+ (forward-line -1)
+ (if (eq what 'statistics)
+
+ (setq message-text (format "Found %d references from %s to %s. %d references below highest do not appear in table. "
+ total
+ (format org-index--ref-format min)
+ (format org-index--ref-format max)
+ (length missing)))
+
+ (if (y-or-n-p (format "Found %d missing references; do you wish to append them to the index table"
+ (length missing)))
+ (let (type)
+ (setq type (org-icompleting-read
+ "Insert new lines for reuse by command \"new\" or just as missing ? " '("reuse" "missing")))
+ (mapc (lambda (x)
+ (let (org-table-may-need-update) (org-table-insert-row t))
+ (org-index--get-field :ref x)
+ (org-index--get-field :count (format ":%s:" type)))
+ missing)
+ (org-index--align)
+
+ (setq message-text (format "Inserted %d new lines for missing refernces" (length missing))))
+ (setq message-text (format "%d missing references." (length missing)))))
+ message-text))
+
+
+(defun org-index--do-head (ref link &optional other)
+
+ (if ref (setq org-index--last-ref ref))
+
+ (let (message-text)
+ ;; Use link if available
+ (if link
+ (progn
+ (org-index--update-line link)
+ (org-id-goto link)
+ (org-reveal)
+ (setq message-text "Followed link"))
+
+ (message (format "Scanning headlines for '%s' ..." ref))
+ (org-index--update-line ref)
+ (let ((search (concat ".*" (org-index--make-guarded-search ref)))
+ (org-trust-scanner-tags t)
+ buffer point)
+ (if (catch 'found
+ (progn
+ ;; loop over all headlines, stop on first match
+ (org-map-entries
+ (lambda ()
+ (when (or (looking-at search)
+ (eq ref (org-entry-get (point) "org-index-ref")))
+ ;; If this is not an inlinetask ...
+ (when (< (org-element-property :level (org-element-at-point))
+ org-inlinetask-min-level)
+ ;; ... remember location and bail out
+ (setq buffer (current-buffer))
+ (setq point (point))
+ (throw 'found t))))
+ nil 'agenda)
+ nil))
+
+ (progn
+ (setq message-text (format "Found '%s'" (or ref link)))
+ (if other
+ (progn
+ (pop-to-buffer buffer)
+ (goto-char point)
+ (org-reveal t)
+ (recenter)
+ (pop-to-buffer "*org-index-occur*"))
+ (org-pop-to-buffer-same-window buffer)
+ (goto-char point)
+ (org-reveal t)
+ (recenter)))
+ (setq message-text (format "Did not find '%s'" (or ref link))))))
+ message-text))
+
+
+(defun org-index--do-occur (initial-search)
+ (let ((occur-buffer-name "*org-index-occur*")
+ (word "") ; last word to search for growing and shrinking on keystrokes
+ (prompt "Search for: ")
+ (hint "")
+ (key-help "<up>, <down> move. <return> finds node, <S-return> goes to table, <M-return> updates count. TAB finds in other window.\n")
+ words ; list of other words that must match too
+ occur-buffer
+ lines-to-show ; number of lines to show in window
+ start-of-lines ; position, where lines begin
+ start-of-help ; start of displayed help (if any)
+ left-off-at ; stack of last positions in index table
+ after-inserted ; in occur-buffer
+ at-end ; in occur-buffer
+ lines-visible ; in occur-buffer
+ below-hline-bol ; below-hline and at bol
+ exit-gracefully ; true if normal exit
+ in-c-backspace ; true while processing C-backspace
+ show-headings ; true, if headings should be shown
+ fun-on-ret ; function to be executed, if return is pressed
+ fun-on-s-ret ; shift
+ fun-on-m-ret ; shift
+ fun-on-tab ; function to be executed, if letter TAB is pressed
+ ret from to key)
+
+ ;; clear buffer
+ (if (get-buffer "*org-index-occur*")
+ (kill-buffer occur-buffer-name))
+ (setq occur-buffer (get-buffer-create "*org-index-occur*"))
+
+ ;; install keyboard-shortcuts within occur-buffer
+ (with-current-buffer occur-buffer
+ (let ((keymap (make-sparse-keymap)))
+
+ (set-keymap-parent keymap org-mode-map)
+ (setq fun-on-ret (lambda () (interactive) (org-index--occur-find-heading nil)))
+ (define-key keymap [return] fun-on-ret)
+ (setq fun-on-s-ret (lambda () (interactive)
+ (when (org-at-table-p)
+ (org-table-goto-column (org-index--column-num :ref))
+ (org-index 'goto))))
+ (define-key keymap [S-return] fun-on-s-ret)
+ (setq fun-on-m-ret (lambda () (interactive)
+ (when (org-at-table-p)
+ (org-index--update-current-line)
+ (org-table-align)
+ (org-table-goto-column (org-index--column-num :count))
+ (message (format "New count is %s" (org-trim (org-table-get-field))))
+ (org-index--update-line (org-index--get-field :ref)))))
+ (define-key keymap [M-return] fun-on-m-ret)
+ (setq fun-on-tab (lambda () (interactive)
+ (org-index--occur-find-heading t)
+ (setq org-index--occur-follow-mode (not org-index--occur-follow-mode))))
+ (define-key keymap [tab] fun-on-tab)
+ (define-key keymap [(control ?i)] fun-on-tab)
+ (define-key keymap [up] (lambda () (interactive)
+ (forward-line -1)
+ (if org-index--occur-follow-mode (org-index--occur-find-heading t))))
+ (define-key keymap [down] (lambda () (interactive)
+ (forward-line 1)
+ (if org-index--occur-follow-mode (org-index--occur-find-heading t))))
+ (use-local-map keymap)))
+
+ (with-current-buffer org-index--buffer
+ (let ((initial (point)))
+ (goto-char org-index--below-hline)
+ (forward-line 0)
+ (setq below-hline-bol (point))
+ (goto-char initial)))
+
+ (org-pop-to-buffer-same-window occur-buffer)
+ (toggle-truncate-lines 1)
+
+ (unwind-protect ; to reset cursor-shape even in case of errors
+ (progn
+
+ ;; fill in header
+ (erase-buffer)
+ (insert (concat "Incremental search, showing one window of matches. '?' toggles help.\n\n"))
+ (setq start-of-lines (point-marker))
+ (setq start-of-help start-of-lines)
+ (setq cursor-type 'hollow)
+
+ ;; get window size of occur-buffer as number of lines to be searched
+ (setq lines-to-show (+ (- (window-body-height) (line-number-at-pos)) 1))
+
+ ;; fill initially
+ (setq ret (org-index--get-matching-lines nil lines-to-show below-hline-bol))
+ (when (nth 0 ret)
+ (insert (nth 1 ret))
+ (setq left-off-at (cons (nth 0 ret) nil))
+ (setq after-inserted (cons (point) nil)))
+
+ ;; read keys
+ (while
+ (progn
+ (goto-char start-of-lines)
+ (setq lines-visible 0)
+
+ ;; use initial-search (if present) to simulate keyboard input
+ (if (and initial-search
+ (> (length initial-search) 0))
+ (progn
+ (setq key (string-to-char (substring initial-search 0 1)))
+ (if (length initial-search)
+ (setq initial-search (substring initial-search 1))))
+ (if in-c-backspace
+ (setq key 'backspace)
+ (let ((search-text (mapconcat 'identity (reverse (cons word words)) ",")))
+ (setq key (read-key
+ (format "%s%s%s%s"
+ prompt
+ search-text
+ (if (string= search-text "") "" " ")
+ hint))))
+ (setq hint "")
+ (setq exit-gracefully (member key (list 'up 'down 'left 'right 'RET ?\C-g ?\C-m 'C-return 'S-return ?\C-i 'TAB)))))
+
+ (not exit-gracefully))
+
+ (cond
+
+ ((eq key 'C-backspace)
+
+ (setq in-c-backspace t))
+
+ ((member key (list 'backspace 'deletechar ?\C-?)) ; erase last char
+
+ (if (= (length word) 0)
+
+ ;; nothing more to delete from current word; try next
+ (progn
+ (setq word (car words))
+ (setq words (cdr words))
+ (setq in-c-backspace nil))
+
+ ;; unhighlight longer match
+ (let ((case-fold-search t))
+ (unhighlight-regexp (regexp-quote word)))
+
+ ;; some chars are left; shorten word
+ (setq word (substring word 0 -1))
+ (when (= (length word) 0) ; when nothing left, use next word from list
+ (setq word (car words))
+ (setq words (cdr words))
+ (setq in-c-backspace nil))
+
+ ;; remove everything, that has been added for char just deleted
+ (when (cdr after-inserted)
+ (setq after-inserted (cdr after-inserted))
+ (goto-char (car after-inserted))
+ (delete-region (point) (point-max)))
+
+ ;; back up last position in index table too
+ (when (cdr left-off-at)
+ (setq left-off-at (cdr left-off-at)))
+
+ ;; go through buffer and check, if any invisible line should now be shown
+ (goto-char start-of-lines)
+ (while (< (point) (point-max))
+ (if (outline-invisible-p)
+ (progn
+ (setq from (line-beginning-position)
+ to (line-beginning-position 2))
+
+ ;; check for matches
+ (when (org-index--test-words (cons word words) (buffer-substring from to))
+ (when (<= lines-visible lines-to-show) ; show, if more lines required
+ (outline-flag-region from to nil)
+ (incf lines-visible))))
+
+ ;; already visible, just count
+ (incf lines-visible))
+
+ (forward-line 1))
+
+ ;; highlight shorter word
+ (unless (= (length word) 0)
+ (let ((case-fold-search t))
+ (highlight-regexp (regexp-quote word) 'isearch)))))
+
+
+ ((member key (list ?\s ?,)) ; space or comma: enter an additional search word
+
+ ;; push current word and clear, no need to change display
+ (setq words (cons word words))
+ (setq word ""))
+
+
+ ((eq key ??) ; question mark: toggle display of headlines and help
+ (setq show-headings (not show-headings))
+ (goto-char start-of-lines)
+ (if show-headings
+ (progn
+ (forward-line -1)
+; (kill-line)
+ (setq start-of-help (point-marker))
+ (insert "Normal keys add to search word, SPACE or COMMA start new word, BACKSPACE and C-BACKSPACE erase char or word. Every other key ends search: <C-return> completes list of matches. ")
+ (insert key-help)
+ (goto-char start-of-help)
+ (fill-paragraph)
+ (goto-char start-of-lines)
+ (insert org-index--headings))
+ (delete-region start-of-help start-of-lines)
+ (insert "\n\n"))
+ (setq start-of-lines (point-marker)))
+
+
+ ((and (integerp key)
+ (aref printable-chars key)) ; any printable char: add to current search word
+
+ ;; unhighlight short word
+ (unless (= (length word) 0)
+ (let ((case-fold-search t))
+ (unhighlight-regexp (regexp-quote word))))
+
+ ;; add to word
+ (setq word (concat word (char-to-string key)))
+
+ ;; hide lines, that do not match longer word any more
+ (while (< (point) (point-max))
+ (unless (outline-invisible-p)
+ (setq from (line-beginning-position)
+ to (line-beginning-position 2))
+
+ ;; check for matches
+ (if (org-index--test-words (list word) (buffer-substring from to))
+ (incf lines-visible) ; count as visible
+ (outline-flag-region from to t))) ; hide
+
+ (forward-line 1))
+
+ ;; duplicate top of stacks; eventually overwritten below
+ (setq left-off-at (cons (car left-off-at) left-off-at))
+ (setq after-inserted (cons (car after-inserted) after-inserted))
+
+ ;; get new lines from index table
+ (when (< lines-visible lines-to-show)
+ (setq ret (org-index--get-matching-lines (cons word words)
+ (- lines-to-show lines-visible)
+ (car left-off-at)))
+
+ (when (nth 0 ret)
+ (insert (nth 1 ret))
+ (setq at-end (nth 2 ret))
+ (setcar left-off-at (nth 0 ret))
+ (setcar after-inserted (point))))
+
+ ;; highlight longer word
+ (let ((case-fold-search t))
+ (highlight-regexp (regexp-quote word) 'isearch)))
+
+
+ (t ; non-printable chars
+ (setq hint (format "(cannot search for key '%s', use %s to quit)"
+ (if (symbolp key)
+ key
+ (key-description (char-to-string key)))
+ (substitute-command-keys "\\[keyboard-quit]"))))))
+
+ ;; search is done collect and brush up results
+ ;; remove any lines, that are still invisible
+ (goto-char start-of-lines)
+ (while (< (point) (point-max))
+ (if (outline-invisible-p)
+ (delete-region (line-beginning-position) (line-beginning-position 2))
+ (forward-line 1)))
+
+ ;; get all the rest
+ (when (eq key 'C-return)
+ (message "Getting all matches ...")
+ (setq ret (org-index--get-matching-lines (cons word words) 0 (car left-off-at)))
+ (message "done.")
+ (insert (nth 1 ret))))
+
+ ;; postprocessing even for non graceful exit
+ (setq cursor-type t)
+ ;; replace previous heading
+ (let ((numlines (count-lines (point) start-of-lines)))
+ (goto-char start-of-lines)
+ (delete-region (point-min) (point))
+ (insert (format (concat (if exit-gracefully "Search is done;" "Search aborted;")
+ (if (or at-end (eq key 'C-return))
+ " showing all %d matches. "
+ " showing only some matches. ")
+ key-help)
+ numlines))
+ (insert "\n")
+ (setq start-of-lines (point-marker))
+ (goto-char (point-min))
+ (fill-paragraph)
+ (goto-char start-of-lines)
+ (if show-headings (insert "\n\n" org-index--headings)))
+ (forward-line))
+
+ ;; perform action according to last char
+ (forward-line -1)
+ (cond
+
+ ((member key (list 'RET ?\C-m))
+ (funcall fun-on-ret))
+
+ ((member key (list 'TAB ?\C-i))
+ (funcall fun-on-tab))
+
+ ((eq key 'up)
+ (forward-line -1))
+
+ ((eq key 'down)
+ (forward-line 1))
+
+ ((eq key 'M-return)
+ (funcall fun-on-m-ret))
+
+ ((eq key 'S-return)
+ (funcall fun-on-s-ret)))))
+
+
+(defun org-index--occur-find-heading (x)
+ "helper for keymap of occur"
+ (interactive)
+ (save-excursion
+ (let ((ref (org-index--get-field :ref))
+ (link (org-index--get-field :link)))
+ (message (org-index--do-head ref link x)))))
+
+
+(defun org-index--do-new-line (create-ref)
+ "Do the common work for org-index-new-line and org-index"
+
+ (let (new)
+
+ (when create-ref
+ ;; go through table to find first entry to be reused
+ (when org-index--has-reuse
+ (goto-char org-index--below-hline)
+ ;; go through table
+ (while (and (org-at-table-p)
+ (not new))
+ (when (string=
+ (org-index--get-field :count)
+ ":reuse:")
+ (setq new (org-index--get-field :ref))
+ (if new (org-table-kill-row)))
+ (forward-line)))
+
+ ;; no ref to reuse; construct new reference
+ (unless new
+ (setq new (format "%s%d%s" org-index--head (1+ org-index--maxref) org-index--tail)))
+
+ ;; remember for org-mark-ring-goto
+ (setq org-index--text-to-yank new))
+
+ ;; insert ref or link as very first row
+ (goto-char org-index--below-hline)
+ (org-table-insert-row)
+
+ ;; insert some of the standard values
+ (org-table-goto-column (org-index--column-num :first))
+ (org-insert-time-stamp nil nil t)
+ (org-table-goto-column (org-index--column-num :count))
+ (insert "1")
+
+ new))
+
+
+(defun org-index--get-matching-lines (words numlines start-from)
+ (let ((numfound 0)
+ pos
+ initial line lines at-end)
+
+ (with-current-buffer org-index--buffer
+
+ ;; remember initial pos and start at requested
+ (setq initial (point))
+ (goto-char start-from)
+
+ ;; loop over buffer until we have found enough lines
+ (while (and (or (< numfound numlines)
+ (= numlines 0))
+ (org-at-table-p))
+
+ ;; check each word
+ (setq line (buffer-substring (line-beginning-position) (line-beginning-position 2)))
+ (when (org-index--test-words words line)
+ (setq lines (concat lines line))
+ (incf numfound))
+ (forward-line 1)
+ (setq pos (point)))
+
+ (setq at-end (not (org-at-table-p)))
+
+ ;; return to initial position
+ (goto-char initial))
+
+ (unless lines (setq lines ""))
+ (list pos lines at-end)))
+
+
+(defun org-index--test-words (words line)
+ (let ((found-all t))
+ (setq line (downcase line))
+ (catch 'not-found
+ (dolist (w words)
+ (or (search w line)
+ (throw 'not-found nil)))
+ t)))
+
+
+
+(defadvice org-mark-ring-goto (after org-index--advice-text-to-yank activate)
+ "Make text from org-index available for yank."
+ (when org-index--text-to-yank
+ (kill-new org-index--text-to-yank)
+ (message (format "Ready to yank '%s'" org-index--text-to-yank))
+ (setq org-index--text-to-yank nil)))
+
+
+(provide 'org-index)
+
+;; Local Variables:
+;; fill-column: 75
+;; comment-column: 50
+;; End:
+
+;;; org-index.el ends here
+
diff --git a/contrib/lisp/org-interactive-query.el b/contrib/lisp/org-interactive-query.el
index 57665e2..644132c 100644
--- a/contrib/lisp/org-interactive-query.el
+++ b/contrib/lisp/org-interactive-query.el
@@ -1,6 +1,6 @@
;;; org-interactive-query.el --- Interactive modification of agenda query
;;
-;; Copyright 2007-2013 Free Software Foundation, Inc.
+;; Copyright 2007-2014 Free Software Foundation, Inc.
;;
;; Author: Christopher League <league at contrapunctus dot net>
;; Version: 1.0
diff --git a/contrib/lisp/org-invoice.el b/contrib/lisp/org-invoice.el
index 88ff48f..c1340a7 100644
--- a/contrib/lisp/org-invoice.el
+++ b/contrib/lisp/org-invoice.el
@@ -1,6 +1,6 @@
;;; org-invoice.el --- Help manage client invoices in OrgMode
;;
-;; Copyright (C) 2008-2013 pmade inc. (Peter Jones pjones@pmade.com)
+;; Copyright (C) 2008-2014 pmade inc. (Peter Jones pjones@pmade.com)
;;
;; This file is not part of GNU Emacs.
;;
diff --git a/contrib/lisp/org-jira.el b/contrib/lisp/org-jira.el
index 57128fb..43edd08 100644
--- a/contrib/lisp/org-jira.el
+++ b/contrib/lisp/org-jira.el
@@ -1,6 +1,6 @@
;;; org-jira.el --- add a jira:ticket protocol to Org
(defconst org-jira-version "0.1")
-;; Copyright (C) 2008-2013 Jonathan Arkell.
+;; Copyright (C) 2008-2014 Jonathan Arkell.
;; Author: Jonathan Arkell <jonnay@jonnay.net>
;; This file is not part of GNU Emacs.
diff --git a/contrib/lisp/org-learn.el b/contrib/lisp/org-learn.el
index 1f5e76c..1755e71 100644
--- a/contrib/lisp/org-learn.el
+++ b/contrib/lisp/org-learn.el
@@ -1,6 +1,6 @@
;;; org-learn.el --- Implements SuperMemo's incremental learning algorithm
-;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2014 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw at gnu dot org>
;; Keywords: outlines, hypermedia, calendar, wp
diff --git a/contrib/lisp/org-license.el b/contrib/lisp/org-license.el
new file mode 100644
index 0000000..426b148
--- a/dev/null
+++ b/contrib/lisp/org-license.el
@@ -0,0 +1,540 @@
+;;; org-license.el --- Add a license to your org files
+
+;; Copyright (C) 2013 Free Software Foundation, Inc.
+
+;; Author: David Arroyo Menéndez <davidam@es.gnu.org>
+;; Keywords: licenses, creative commons
+;; Homepage: http://orgmode.org
+;;
+;; This file is not part of GNU Emacs, yet.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+
+;; This file implements functions to add a license fast in org files.
+;; Org-mode doesn't load this module by default - if this is not what
+;; you want, configure the variable `org-modules'. Thanks to #emacs-es
+;; irc channel for your support.
+
+;;; Code:
+
+;;
+;;
+;; You can download the images from http://www.davidam/img/licenses.tar.gz
+;;
+;;; CHANGELOG:
+;; v 0.2 - add public domain functions
+;; v 0.1 - Initial release
+
+
+(defvar org-license-images-directory "")
+
+(defun org-license-cc-by (language)
+ (interactive "MLanguage ( br | ca | de | en | es | eo | eu | fi | fr | gl | it | jp | nl | pt ): " language)
+ (cond ((equal language "br")
+ (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/br/deed.pt_BR")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição 3.0 Brasil]]\n")))
+ ((equal language "ca")
+ (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/es/deed.ca")
+ (insert (concat "* Licència
+El text està disponible sota la [[" org-license-cc-url "][Reconeixement 3.0 Espanya]]\n")))
+ ((equal language "de")
+ (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/de/deed.de")
+ (insert (concat "* Lizenz
+Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Lizenz Creative Commons Namensnennung 3.0 Deutschland]]\n")))
+ ((equal language "eo")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/eo/deed.eo")
+ (insert (concat "* Licenco
+Ĉi tiu verko estas disponebla laŭ la permesilo [[" org-license-cc-url "][Krea Komunaĵo Atribuite 3.0 Neadaptita]]\n")))
+ ((equal language "es")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/es/deed.es")
+ (insert (concat "* Licencia
+Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Atribución 3.0 España]]\n")))
+ ((equal language "eu")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/es/deed.eu")
+ (insert (concat "* Licenzua
+Testua [[" org-license-cc-url "][Aitortu 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n")))
+ ((equal language "fi")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/1.0/fi/deed.fi")
+ (insert (concat "* Lisenssi
+Teksti on saatavilla [[" org-license-cc-url "][Nimeä 1.0 Suomi]] lisenssillä\n")))
+ ((equal language "fr")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/fr/deed.fr")
+ (insert (concat "* Licence
+Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution 3.0 France]]\n")))
+ ((equal language "gl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/es/deed.gl")
+ (insert (concat "* Licenza
+Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n")))
+ ((equal language "it")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/it/deed.it")
+ (insert (concat "* Licenza
+Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione 3.0 Italia]]\n")))
+ ((equal language "jp")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/2.1/jp/deed.en")
+ (insert (concat "* ライセンス
+この文書は [[" org-license-cc-url "][Creative Commons Attribution 2.1 ]] ライセンスの下である\n")))
+ ((equal language "nl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/nl/deed.nl")
+ (insert (concat "* Licentie
+Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding 3.0 Nederland]]\n")))
+ ((equal language "pt")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/pt/deed.pt")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição 3.0 Portugal]]\n")))
+ (t
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by/4.0/deed")
+ (concat (insert "* License
+This document is under a [[" org-license-cc-url "][Creative Commons Attribution 4.0 International]]\n"))))
+ (if (string= "" org-license-images-directory)
+ (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by/3.0/80x15.png]]\n"))
+ (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by/3.0/80x15.png]]\n"))))
+
+(defun org-license-cc-by-sa (language)
+ (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | it | jp | nl | pt ): " language)
+ (cond ((equal language "br")
+ (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/br/deed.pt_BR")
+ (concat (insert "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Compartil ha Igual 3.0 Brasil]]\n")))
+ ((equal language "ca")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/es/deed.ca")
+ (insert (concat "* Licència
+El text està disponible sota la [[" org-license-cc-url "][Reconeixement-CompartirIgual 3.0 Espanya]]\n")))
+ ((equal language "de")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/de/deed.de")
+ (insert (concat "* Lizenz
+Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Deutschland]]\n")))
+ ((equal language "es")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/es/deed.es")
+ (concat (insert "* Licencia
+Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Atribución Compartir por Igual 3.0 España]]\n")))
+ ((equal language "eu")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/es/deed.eu")
+ (concat (insert "* Licenzua
+Testua [[" org-license-cc-url "][Aitortu-PartekatuBerdin 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n")))
+ ((equal language "fi")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/1.0/fi/deed.fi")
+ (insert (concat "* Lisenssi
+Teksti on saatavilla [[" org-license-cc-url "][Nimeä-JaaSamoin 1.0 Suomi]] lisenssillä\n")))
+ ((equal language "fr")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/fr/deed.fr")
+ (concat (insert "* Licence
+Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 3.0 France]]\n")))
+ ((equal language "gl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/es/deed.gl")
+ (insert (concat "* Licenza
+Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n")))
+ ((equal language "it")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/it/deed.it")
+ (insert (concat "* Licenza
+Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Condividi allo stesso modo 3.0 Italia]]\n")))
+ ((equal language "jp")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/2.1/jp/deed.en")
+ (insert (concat "* ライセンス
+この文書は、[[" org-license-cc-url "][Creative Commons Attribution 2.1 ]] ライセンスの下である\n")))
+ ((equal language "nl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/nl/deed.nl")
+ (insert (concat "* Licentie
+Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding Gelijk Delen 3.0 Nederland]]\n")))
+ ((equal language "pt")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/pt/deed.pt")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição-CompartilhaIgual 3.0 Portugal]]\n")))
+ (t
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/4.0/deed")
+ (insert (concat "* License
+This document is under a [[" org-license-cc-url "][Creative Commons Attribution-ShareAlike 4.0 International]]\n"))))
+ (if (string= "" org-license-images-directory)
+ (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-sa/3.0/80x15.png]]\n"))
+ (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-sa/3.0/80x15.png]]\n"))))
+
+(defun org-license-cc-by-nd (language)
+ (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | it | pt ): " language)
+ (cond ((equal language "br")
+ (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/br/deed.pt_BR")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Compartil ha Igual 3.0 Brasil]]\n")))
+ ((equal language "ca")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/es/deed.ca")
+ (insert (concat "* Licència
+El text està disponible sota la [[" org-license-cc-url "][Reconeixement-SenseObraDerivada 3.0 Espanya]]\n")))
+ ((equal language "de")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/de/deed.de")
+ (insert (concat "* Lizenz
+Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung-Keine Bearbeitung 3.0 Deutschland]]\n")))
+ ((equal language "es")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/es/deed.es")
+ (insert (concat "* Licencia
+Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Atribución-SinDerivadas 3.0]]\n")))
+ ((equal language "eu")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/es/deed.eu")
+ (insert (concat "* Licenzua
+Testua [[" org-license-cc-url "][Aitortu-LanEratorririkGabe 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n")))
+ ((equal language "fi")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/1.0/fi/deed.fi")
+ (insert (concat "* Lisenssi
+Teksti on saatavilla [[" org-license-cc-url "][Nimeä-JaaSamoin 1.0 Suomi]] lisenssillä\n")))
+ ((equal language "fr")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/fr/deed.fr")
+ (insert (concat "* Licence
+Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Pas de Modification 3.0 France]]\n")))
+ ((equal language "gl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/es/deed.gl")
+ (insert (concat "* Licenza
+Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n")))
+ ((equal language "it")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/it/deed.it")
+ (insert (concat "* Licenza
+Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Non opere derivate 3.0 Italia]]\n")))
+ ((equal language "jp")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/2.1/jp/deed.en")
+ (insert (concat "* ライセンス
+この文書は、[[" org-license-cc-url "][Creative Commons No Derivatives 2.1]] ライセンスの下である\n")))
+ ((equal language "nl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/nl/deed.nl")
+ (insert (concat "* Licentie
+Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding GeenAfgeleideWerken 3.0 Nederland]]\n")))
+ ((equal language "pt")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/pt/deed.pt")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Sem Derivados 3.0 Portugal]]\n")))
+ (t
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/4.0/deed")
+ (insert (concat "* License
+This document is under a [[" org-license-cc-url "][Creative Commons No Derivatives 4.0 International]]\n"))))
+ (if (string= "" org-license-images-directory)
+ (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nd/3.0/80x15.png]]\n"))
+ (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nd/3.0/80x15.png]]\n"))))
+
+
+(defun org-license-cc-by-nc (language)
+ (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | it | jp | nl | pt ): " language)
+ (cond ((equal language "br")
+ (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/br/deed.pt_BR")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial 3.0 Brasil]]\n")))
+ ((equal language "ca")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/es/deed.ca")
+ (insert (concat "* Licència
+El text està disponible sota la [[" org-license-cc-url "][Reconeixement-NoComercial 3.0 Espanya]]\n")))
+ ((equal language "de")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/de/deed.de")
+ (insert (concat "* Lizenz
+Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung-Nicht-kommerziell 3.0 Deutschland]]\n")))
+ ((equal language "es")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/es/deed.es")
+ (insert (concat "* Licencia
+Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Reconocimiento-NoComercial 3.0]]\n")))
+ ((equal language "eu")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/es/deed.eu")
+ (insert "* Licenzua
+Testua [[" org-license-cc-url "][Aitortu-EzKomertziala 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n"))
+ ((equal language "fi")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/1.0/fi/deed.fi")
+ (insert (concat "* Lisenssi
+Teksti on saatavilla [[" org-license-cc-url "][Nimeä-Epäkaupallinen 1.0 Suomi]] lisenssillä\n")))
+ ((equal language "fr")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/fr/deed.fr")
+ (insert (concat "* Licence
+Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Pas d'Utilisation Commerciale 3.0 France]]\n")))
+ ((equal language "gl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/es/deed.gl")
+ (insert (concat "* Licenza
+Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n")))
+ ((equal language "it")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/it/deed.it")
+ (insert (concat "* Licenza
+Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Non commerciale 3.0 Italia]]\n")))
+ ((equal language "jp")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/2.1/jp/deed.en")
+ (insert (concat "* ライセンス
+この文書は、[[" org-license-cc-url "][Creative Commons Attribution-NonCommercial 2.1 ]] ライセンスの下である\n")))
+ ((equal language "nl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/nl/deed.nl")
+ (insert (concat "* Licentie
+Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding NietCommercieel 3.0 Nederland 3.0 Nederland]]\n")))
+ ((equal language "pt")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/pt/deed.pt")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial 3.0 Portugal]]\n")))
+ (t
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/4.0/deed")
+ (insert (concat "* License
+This document is under a [[" org-license-cc-url "][Creative Commons Attribution-NonCommercial 4.0 International]]\n"))))
+ (if (string= "" org-license-images-directory)
+ (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nc/3.0/80x15.png]]\n"))
+ (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nc/3.0/80x15.png]]\n"))))
+
+(defun org-license-cc-by-nc-sa (language)
+ (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | gl | it | jp | nl | pt ): " language)
+ (cond ((equal language "br")
+ (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/3.0/br/deed.pt_BR")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial - Compartil ha Igual 3.0 Brasil]]\n")))
+ ((equal language "ca")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.ca")
+ (insert (concat "* Licència
+El text està disponible sota la [[" org-license-cc-url "][Reconeixement-NoComercial 3.0 Espanya]]\n")))
+ ((equal language "de")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/de/deed.de")
+ (insert (concat "* Lizenz
+Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Deutschland]]\n")))
+ ((equal language "es")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.es")
+ (insert (concat "* Licencia
+Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Reconocimiento-NoComercial 3.0]]\n")))
+ ((equal language "eu")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.eu")
+ (insert "* Licenzua
+Testua [[" org-license-cc-url "][Aitortu-EzKomertziala-PartekatuBerdin 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n"))
+ ((equal language "fi")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/1.0/fi/deed.fi")
+ (insert (concat "* Lisenssi
+Teksti on saatavilla [[" org-license-cc-url "][Nimeä-Epäkaupallinen-JaaSamoin 1.0 Suomi]] lisenssillä\n")))
+ ((equal language "fr")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/fr/deed.fr")
+ (insert (concat "* Licence
+Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 France]]\n")))
+ ((equal language "gl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.gl")
+ (insert (concat "* Licenza
+Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n")))
+ ((equal language "it")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/it/deed.it")
+ (insert (concat "* Licenza
+Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Non opere derivate 3.0 Italia]]\n")))
+ ((equal language "jp")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/2.1/jp/deed.en")
+ (insert (concat "* ライセンス
+この文書は、[[" org-license-cc-url "][License Creative Commons Attribution Non Commercial Share Alike 2.1 ]] ライセンスの下である\n")))
+ ((equal language "nl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/nl/deed.nl")
+ (insert (concat "* Licentie
+Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding NietCommercieel GelijkDelen 3.0 Nederland]]\n")))
+ ((equal language "pt")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/pt/deed.pt")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição NãoComercial Compartil ha Igual 3.0 Portugal]]\n")))
+ (t
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/4.0/deed")
+ (insert (concat "* License
+This document is under a [[" org-license-cc-url "][License Creative Commons Attribution Non Commercial Share Alike 4.0 International]]\n"))))
+ (if (string= "" org-license-images-directory)
+ (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nc-sa/3.0/80x15.png]]\n"))
+ (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nc-sa/3.0/80x15.png]]\n"))))
+
+(defun org-license-cc-by-nc-nd (language)
+ (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | gl | it | pt ): " language)
+ (cond ((equal language "br")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/pt/deed.pt")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial Sem Derivados 3.0 Brasil]]\n")))
+ ((equal language "ca")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.ca")
+ (insert (concat "* Licència
+El text està disponible sota la [[" org-license-cc-url "][Reconeixement-NoComercial-SenseObraDerivada 3.0 Espanya]]\n")))
+ ((equal language "de")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/de/deed.de")
+ (insert (concat "* Lizenz
+Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung-NichtKommerziell-KeineBearbeitung 3.0 Deutschland]]\n")))
+ ((equal language "es")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.es")
+ (insert (concat "* Licencia
+Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0]]\n")))
+ ((equal language "eu")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.eu")
+ (insert (concat "* Licenzua
+Testua [[" org-license-cc-url "][Aitortu-LanEratorririkGabe 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n")))
+ ((equal language "fi")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/1.0/fi/deed.fi")
+ (insert (concat "* Lisenssi
+Teksti on saatavilla [[" org-license-cc-url "][Nimeä-Ei muutoksia-Epäkaupallinen 1.0 Suomi]] lisenssillä\n")))
+ ((equal language "fr")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/fr/deed.fr")
+ (insert (concat "* Licence
+Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Pas de Modification 3.0 France]]\n")))
+ ((equal language "gl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.gl")
+ (insert (concat "* Licenza
+Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n")))
+ ((equal language "it")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/it/deed.it")
+ (insert (concat "* Licenza
+Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Non opere derivate 3.0 Italia]]\n")))
+ ((equal language "jp")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/2.1/jp/deed.en")
+ (insert (concat "* ライセンス
+この文書は [[" org-license-cc-url "][License Creative Commons Attribution Non Commercial - No Derivs 2.1]] ライセンスの下である\n")))
+ ((equal language "nl")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/nl/deed.nl")
+ (insert (concat "* Licentie
+Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding NietCommercieel GeenAfgeleideWerken 3.0 Nederland]]\n")))
+ ((equal language "pt")
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/pt/deed.pt")
+ (insert (concat "* Licença
+Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial Sem Derivados 3.0 Portugal]]\n")))
+ (t
+ (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/4.0/deed")
+ (insert (concat "* License
+This document is under a [[" org-license-cc-url "][License Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International]]\n"))))
+ (if (string= "" org-license-images-directory)
+ (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nc-nd/3.0/80x15.png]]\n"))
+ (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nc-nd/3.0/80x15.png]]\n"))))
+
+(defun org-license-gfdl (language)
+ (interactive "MLanguage (es | en): " language)
+ (cond ((equal language "es")
+ (insert "* Licencia
+Copyright (C) " (format-time-string "%Y") " " user-full-name
+"\n Se permite copiar, distribuir y/o modificar este documento
+ bajo los términos de la GNU Free Documentation License, Version 1.3
+ o cualquier versión publicada por la Free Software Foundation;
+ sin Secciones Invariantes y sin Textos de Portada o Contraportada.
+ Una copia de la licencia está incluida en [[https://www.gnu.org/copyleft/fdl.html][GNU Free Documentation License]].\n"))
+ (t (insert (concat "* License
+Copyright (C) " (format-time-string "%Y") " " user-full-name
+"\n Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.3
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
+ A copy of the license is included in [[https://www.gnu.org/copyleft/fdl.html][GNU Free Documentation License]].\n"))))
+ (if (string= "" org-license-images-directory)
+ (insert "\n[[https://www.gnu.org/copyleft/fdl.html][file:https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/GFDL_Logo.svg/200px-GFDL_Logo.svg.png]]\n")
+ (insert (concat "\n[[https://www.gnu.org/copyleft/fdl.html][file:" org-license-images-directory "/gfdl/gfdl.png]]\n"))))
+
+(defun org-license-publicdomain-zero (language)
+ (interactive "MLanguage ( en | es ): " language)
+ (setq org-license-pd-url "http://creativecommons.org/publicdomain/zero/1.0/")
+ (setq org-license-pd-file "zero/1.0/80x15.png")
+ (if (equal language "es")
+ (insert (concat "* Licencia
+Este documento está bajo una licencia [[" org-license-pd-url "][Public Domain Zero]]\n"))
+ (insert (concat "* License
+This documento is under a [[" org-license-pd-url "][Public Domain Zero]] license\n")))
+ (if (string= "" org-license-images-directory)
+ (insert (concat "\n[[" org-license-pd-url "][file:http://i.creativecommons.org/p/zero/1.0/80x15.png]]\n"))
+ (insert (concat "\n[[" org-license-pd-url "][file:" org-license-images-directory org-license-pd-file "]]\n"))))
+
+(defun org-license-publicdomain-mark (language)
+ (interactive "MLanguage ( en | es ): " language)
+ (setq org-license-pd-url "http://creativecommons.org/publicdomain/mark/1.0/")
+ (setq org-license-pd-file "mark/1.0/80x15.png")
+ (if (equal language "es")
+ (insert (concat "* Licencia
+Este documento está bajo una licencia [[" org-license-pd-url "][Etiqueta de Dominio Público 1.0]]\n"))
+ (insert (concat "* License
+This documento is under a [[" org-license-pd-url "][Public Domain Mark]] license\n")))
+ (if (string= "" org-license-images-directory)
+ (insert (concat "\n[[" org-license-pd-url "][file:http://i.creativecommons.org/p/mark/1.0/80x15.png]]\n"))
+ (insert (concat "\n[[" org-license-pd-url "][file:" org-license-images-directory org-license-pd-file "]]\n"))))
+
+(defun org-license-print-all ()
+"Print all combinations of licenses and languages, it's useful to find bugs"
+ (interactive)
+ (org-license-gfdl "es")
+ (org-license-gfdl "en")
+ (org-license-publicdomain-mark "es")
+ (org-license-publicdomain-mark "en")
+ (org-license-publicdomain-zero "es")
+ (org-license-publicdomain-zero "en")
+ (org-license-cc-by "br")
+ (org-license-cc-by "ca")
+ (org-license-cc-by "de")
+ (org-license-cc-by "es")
+ (org-license-cc-by "en")
+ (org-license-cc-by "eo")
+ (org-license-cc-by "eu")
+ (org-license-cc-by "fi")
+ (org-license-cc-by "fr")
+ (org-license-cc-by "gl")
+ (org-license-cc-by "it")
+ (org-license-cc-by "jp")
+ (org-license-cc-by "nl")
+ (org-license-cc-by "pt")
+ (org-license-cc-by-sa "br")
+ (org-license-cc-by-sa "ca")
+ (org-license-cc-by-sa "de")
+ (org-license-cc-by-sa "es")
+ (org-license-cc-by-sa "en")
+;; (org-license-cc-by-sa "eo")
+ (org-license-cc-by-sa "eu")
+ (org-license-cc-by-sa "fi")
+ (org-license-cc-by-sa "fr")
+ (org-license-cc-by-sa "gl")
+ (org-license-cc-by-sa "it")
+ (org-license-cc-by-sa "jp")
+ (org-license-cc-by-sa "nl")
+ (org-license-cc-by-sa "pt")
+ (org-license-cc-by-nd "br")
+ (org-license-cc-by-nd "ca")
+ (org-license-cc-by-nd "de")
+ (org-license-cc-by-nd "es")
+ (org-license-cc-by-nd "en")
+;; (org-license-cc-by-nd "eo")
+ (org-license-cc-by-nd "eu")
+ (org-license-cc-by-nd "fi")
+ (org-license-cc-by-nd "fr")
+ (org-license-cc-by-nd "gl")
+ (org-license-cc-by-nd "it")
+ (org-license-cc-by-nd "jp")
+ (org-license-cc-by-nd "nl")
+ (org-license-cc-by-nd "pt")
+ (org-license-cc-by-nc "br")
+ (org-license-cc-by-nc "ca")
+ (org-license-cc-by-nc "de")
+ (org-license-cc-by-nc "es")
+ (org-license-cc-by-nc "en")
+;; (org-license-cc-by-nc "eo")
+ (org-license-cc-by-nc "eu")
+ (org-license-cc-by-nc "fi")
+ (org-license-cc-by-nc "fr")
+ (org-license-cc-by-nc "gl")
+ (org-license-cc-by-nc "it")
+ (org-license-cc-by-nc "jp")
+ (org-license-cc-by-nc "nl")
+ (org-license-cc-by-nc "pt")
+ (org-license-cc-by-nc-sa "br")
+ (org-license-cc-by-nc-sa "ca")
+ (org-license-cc-by-nc-sa "de")
+ (org-license-cc-by-nc-sa "es")
+ (org-license-cc-by-nc-sa "en")
+;; (org-license-cc-by-nc-sa "eo")
+ (org-license-cc-by-nc-sa "eu")
+ (org-license-cc-by-nc-sa "fi")
+ (org-license-cc-by-nc-sa "fr")
+ (org-license-cc-by-nc-sa "gl")
+ (org-license-cc-by-nc-sa "it")
+ (org-license-cc-by-nc-sa "jp")
+ (org-license-cc-by-nc-sa "nl")
+ (org-license-cc-by-nc-sa "pt")
+ (org-license-cc-by-nc-nd "br")
+ (org-license-cc-by-nc-nd "ca")
+ (org-license-cc-by-nc-nd "de")
+ (org-license-cc-by-nc-nd "es")
+ (org-license-cc-by-nc-nd "en")
+;; (org-license-cc-by-nc-nd "eo")
+ (org-license-cc-by-nc-nd "eu")
+ (org-license-cc-by-nc-nd "fi")
+ (org-license-cc-by-nc-nd "fr")
+ (org-license-cc-by-nc-nd "gl")
+ (org-license-cc-by-nc-nd "it")
+ (org-license-cc-by-nc-nd "jp")
+ (org-license-cc-by-nc-nd "nl")
+ (org-license-cc-by-nc-nd "pt")
+)
+
+
diff --git a/contrib/lisp/org-mac-iCal.el b/contrib/lisp/org-mac-iCal.el
index afec84b..937b6dd 100644
--- a/contrib/lisp/org-mac-iCal.el
+++ b/contrib/lisp/org-mac-iCal.el
@@ -1,6 +1,6 @@
;;; org-mac-iCal.el --- Imports events from iCal.app to the Emacs diary
-;; Copyright (C) 2009-2013 Christopher Suckling
+;; Copyright (C) 2009-2014 Christopher Suckling
;; Author: Christopher Suckling <suckling at gmail dot com>
;; Version: 0.1057.104
diff --git a/contrib/lisp/org-mac-link.el b/contrib/lisp/org-mac-link.el
index 2ff6711..3b58d04 100644
--- a/contrib/lisp/org-mac-link.el
+++ b/contrib/lisp/org-mac-link.el
@@ -1,15 +1,16 @@
;;; org-mac-link.el --- Grab links and url from various mac
;; Application and insert them as links into org-mode documents
;;
-;; Copyright (c) 2010-2013 Free Software Foundation, Inc.
+;; Copyright (c) 2010-2014 Free Software Foundation, Inc.
+;;
+;; Author: Anthony Lander <anthony.lander@gmail.com>
+;; John Wiegley <johnw@gnu.org>
+;; Christopher Suckling <suckling at gmail dot com>
+;; Daniil Frumin <difrumin@gmail.com>
+;; Alan Schmitt <alan.schmitt@polytechnique.org>
+;; Mike McLean <mike.mclean@pobox.com>
;;
-;; Authors:
-;; Anthony Lander <anthony.lander@gmail.com>
-;; John Wiegley <johnw@gnu.org>
-;; Christopher Suckling <suckling at gmail dot com>
-;; Daniil Frumin <difrumin@gmail.com>
;;
-;;
;; Version: 1.1
;; Keywords: org, mac, hyperlink
;;
@@ -57,6 +58,7 @@
;; Together.app - Grab links to the selected items in the library list
;; Skim.app - Grab a link to the selected page in the topmost pdf document
;; Microsoft Outlook.app - Grab a link to the selected message in the message list
+;; DEVONthink Pro Office.app - Grab a link to the selected DEVONthink item(s); open DEVONthink item by reference
;;
;;
;; Installation:
@@ -86,61 +88,66 @@
(require 'org)
(defgroup org-mac-link nil
- "Options concerning grabbing links from external Mac
-applications and inserting them in org documents"
+ "Options for grabbing links from Mac applications."
:tag "Org Mac link"
:group 'org-link)
(defcustom org-mac-grab-Finder-app-p t
- "Enable menu option [F]inder to grab links from the Finder"
+ "Add menu option [F]inder to grab links from the Finder."
:tag "Grab Finder.app links"
:group 'org-mac-link
:type 'boolean)
(defcustom org-mac-grab-Mail-app-p t
- "Enable menu option [m]ail to grab links from Mail.app"
+ "Add menu option [m]ail to grab links from Mail.app."
:tag "Grab Mail.app links"
:group 'org-mac-link
:type 'boolean)
(defcustom org-mac-grab-Outlook-app-p t
- "Enable menu option [o]utlook to grab links from Microsoft Outlook.app"
+ "Add menu option [o]utlook to grab links from Microsoft Outlook.app."
:tag "Grab Microsoft Outlook.app links"
:group 'org-mac-link
:type 'boolean)
+(defcustom org-mac-grab-devonthink-app-p t
+ "Add menu option [d]EVONthink to grab links from DEVONthink Pro Office.app."
+ :tag "Grab DEVONthink Pro Office.app links"
+ :group 'org-mac-link
+ :type 'boolean)
+
(defcustom org-mac-grab-Addressbook-app-p t
- "Enable menu option [a]ddressbook to grab links from AddressBook.app"
+ "Add menu option [a]ddressbook to grab links from AddressBook.app."
:tag "Grab AddressBook.app links"
:group 'org-mac-link
:type 'boolean)
(defcustom org-mac-grab-Safari-app-p t
- "Enable menu option [s]afari to grab links from Safari.app"
+ "Add menu option [s]afari to grab links from Safari.app."
:tag "Grab Safari.app links"
:group 'org-mac-link
:type 'boolean)
(defcustom org-mac-grab-Firefox-app-p t
- "Enable menu option [f]irefox to grab links from Firefox.app"
+ "Add menu option [f]irefox to grab links from Firefox.app."
:tag "Grab Firefox.app links"
:group 'org-mac-link
:type 'boolean)
(defcustom org-mac-grab-Firefox+Vimperator-p nil
- "Enable menu option [v]imperator to grab links from Firefox.app running the Vimperator plugin"
+ "Add menu option [v]imperator to grab links from Firefox.app running the Vimperator plugin."
:tag "Grab Vimperator/Firefox.app links"
:group 'org-mac-link
:type 'boolean)
(defcustom org-mac-grab-Chrome-app-p t
- "Enable menu option [f]irefox to grab links from Google Chrome.app"
+ "Add menu option [c]hrome to grab links from Google Chrome.app."
:tag "Grab Google Chrome.app links"
:group 'org-mac-link
:type 'boolean)
(defcustom org-mac-grab-Together-app-p nil
- "Enable menu option [t]ogether to grab links from Together.app"
+ "Add menu option [t]ogether to grab links from Together.app."
:tag "Grab Together.app links"
:group 'org-mac-link
:type 'boolean)
@@ -148,19 +155,19 @@ applications and inserting them in org documents"
(defcustom org-mac-grab-Skim-app-p
(< 0 (length (shell-command-to-string
"mdfind kMDItemCFBundleIdentifier == 'net.sourceforge.skim-app.skim'")))
- "Enable menu option [S]kim to grab page links from Skim.app"
+ "Add menu option [S]kim to grab page links from Skim.app."
:tag "Grab Skim.app page links"
:group 'org-mac-link
:type 'boolean)
(defcustom org-mac-Skim-highlight-selection-p nil
- "Highlight (using notes) the selection (if present) when grabbing the a link from Skim.app"
+ "Highlight the active selection when grabbing a link from Skim.app."
:tag "Highlight selection in Skim.app"
:group 'org-mac-link
:type 'boolean)
(defgroup org-mac-flagged-mail nil
- "Options concerning linking to flagged Mail.app messages."
+ "Options foring linking to flagged Mail.app messages."
:tag "Org Mail.app"
:group 'org-link)
@@ -185,30 +192,35 @@ applications and inserting them in org documents"
(setq return (shell-command-to-string cmd))
(concat "\"" (org-trim return) "\""))))
-
(defun org-mac-grab-link ()
- "Prompt the user for an application to grab a link from, then go grab the link, and insert it at point"
+ "Prompt for an application to grab a link from.
+When done, go grab the link, and insert it at point."
(interactive)
- (let* ((descriptors `(("F" "inder" org-mac-finder-insert-selected ,org-mac-grab-Finder-app-p)
- ("m" "ail" org-mac-message-insert-selected ,org-mac-grab-Mail-app-p)
- ("o" "utlook" org-mac-outlook-message-insert-selected ,org-mac-grab-Outlook-app-p)
- ("a" "ddressbook" org-mac-addressbook-insert-selected ,org-mac-grab-Addressbook-app-p)
- ("s" "afari" org-mac-safari-insert-frontmost-url ,org-mac-grab-Safari-app-p)
- ("f" "irefox" org-mac-firefox-insert-frontmost-url ,org-mac-grab-Firefox-app-p)
- ("v" "imperator" org-mac-vimperator-insert-frontmost-url ,org-mac-grab-Firefox+Vimperator-p)
- ("c" "hrome" org-mac-chrome-insert-frontmost-url ,org-mac-grab-Chrome-app-p)
- ("t" "ogether" org-mac-together-insert-selected ,org-mac-grab-Together-app-p)
- ("S" "kim" org-mac-skim-insert-page ,org-mac-grab-Skim-app-p)))
+ (let* ((descriptors
+ `(("F" "inder" org-mac-finder-insert-selected ,org-mac-grab-Finder-app-p)
+ ("m" "ail" org-mac-message-insert-selected ,org-mac-grab-Mail-app-p)
+ ("d" "EVONthink Pro Office" org-mac-devonthink-item-insert-selected
+ ,org-mac-grab-devonthink-app-p)
+ ("o" "utlook" org-mac-outlook-message-insert-selected ,org-mac-grab-Outlook-app-p)
+ ("a" "ddressbook" org-mac-addressbook-insert-selected ,org-mac-grab-Addressbook-app-p)
+ ("s" "afari" org-mac-safari-insert-frontmost-url ,org-mac-grab-Safari-app-p)
+ ("f" "irefox" org-mac-firefox-insert-frontmost-url ,org-mac-grab-Firefox-app-p)
+ ("v" "imperator" org-mac-vimperator-insert-frontmost-url ,org-mac-grab-Firefox+Vimperator-p)
+ ("c" "hrome" org-mac-chrome-insert-frontmost-url ,org-mac-grab-Chrome-app-p)
+ ("t" "ogether" org-mac-together-insert-selected ,org-mac-grab-Together-app-p)
+ ("S" "kim" org-mac-skim-insert-page ,org-mac-grab-Skim-app-p)))
(menu-string (make-string 0 ?x))
input)
-
+
;; Create the menu string for the keymap
(mapc '(lambda (descriptor)
(when (elt descriptor 3)
- (setf menu-string (concat menu-string "[" (elt descriptor 0) "]" (elt descriptor 1) " "))))
+ (setf menu-string (concat menu-string
+ "[" (elt descriptor 0) "]"
+ (elt descriptor 1) " "))))
descriptors)
(setf (elt menu-string (- (length menu-string) 1)) ?:)
-
+
;; Prompt the user, and grab the link
(message menu-string)
(setq input (read-char-exclusive))
@@ -221,12 +233,13 @@ applications and inserting them in org documents"
descriptors)))
(defun org-mac-paste-applescript-links (as-link-list)
- "Paste in a list of links from an applescript handler. The
- links are of the form <link>::split::<name>"
+ "Paste in a list of links from an applescript handler.
+The links are of the form <link>::split::<name>."
(let* ((link-list
- (mapcar
- (lambda (x) (if (string-match "\\`\"\\(.*\\)\"\\'" x) (setq x (match-string 1 x))) x)
- (split-string as-link-list "[\r\n]+")))
+ (mapcar (lambda (x) (if (string-match "\\`\"\\(.*\\)\"\\'" x)
+ (setq x (match-string 1 x)))
+ x)
+ (split-string as-link-list "[\r\n]+")))
split-link URL description orglink orglink-insert rtn orglink-list)
(while link-list
(setq split-link (split-string (pop link-list) "::split::"))
@@ -240,7 +253,6 @@ applications and inserting them in org documents"
rtn))
-
;; Handle links from Firefox.app
;;
;; This code allows you to grab the current active url from the main
@@ -257,27 +269,28 @@ applications and inserting them in org documents"
;; seems that it is always the last active window).
(defun org-as-mac-firefox-get-frontmost-url ()
- (let ((result (do-applescript
- (concat
- "set oldClipboard to the clipboard\n"
- "set frontmostApplication to path to frontmost application\n"
- "tell application \"Firefox\"\n"
- " activate\n"
- " delay 0.15\n"
- " tell application \"System Events\"\n"
- " keystroke \"l\" using {command down}\n"
- " keystroke \"a\" using {command down}\n"
- " keystroke \"c\" using {command down}\n"
- " end tell\n"
- " delay 0.15\n"
- " set theUrl to the clipboard\n"
- " set the clipboard to oldClipboard\n"
- " set theResult to (get theUrl) & \"::split::\" & (get name of window 1)\n"
- "end tell\n"
- "activate application (frontmostApplication as text)\n"
- "set links to {}\n"
- "copy theResult to the end of links\n"
- "return links as string\n"))))
+ (let ((result
+ (do-applescript
+ (concat
+ "set oldClipboard to the clipboard\n"
+ "set frontmostApplication to path to frontmost application\n"
+ "tell application \"Firefox\"\n"
+ " activate\n"
+ " delay 0.15\n"
+ " tell application \"System Events\"\n"
+ " keystroke \"l\" using {command down}\n"
+ " keystroke \"a\" using {command down}\n"
+ " keystroke \"c\" using {command down}\n"
+ " end tell\n"
+ " delay 0.15\n"
+ " set theUrl to the clipboard\n"
+ " set the clipboard to oldClipboard\n"
+ " set theResult to (get theUrl) & \"::split::\" & (get name of window 1)\n"
+ "end tell\n"
+ "activate application (frontmostApplication as text)\n"
+ "set links to {}\n"
+ "copy theResult to the end of links\n"
+ "return links as string\n"))))
(car (split-string result "[\r\n]+" t))))
(defun org-mac-firefox-get-frontmost-url ()
@@ -303,27 +316,28 @@ applications and inserting them in org documents"
;; Firefox
(defun org-as-mac-vimperator-get-frontmost-url ()
- (let ((result (do-applescript
- (concat
- "set oldClipboard to the clipboard\n"
- "set frontmostApplication to path to frontmost application\n"
- "tell application \"Firefox\"\n"
- " activate\n"
- " delay 0.15\n"
- " tell application \"System Events\"\n"
- " keystroke \"y\"\n"
- " end tell\n"
- " delay 0.15\n"
- " set theUrl to the clipboard\n"
- " set the clipboard to oldClipboard\n"
- " set theResult to (get theUrl) & \"::split::\" & (get name of window 1)\n"
- "end tell\n"
- "activate application (frontmostApplication as text)\n"
- "set links to {}\n"
- "copy theResult to the end of links\n"
- "return links as string\n"))))
- (replace-regexp-in-string "\s+-\s+Vimperator" "" (car (split-string result "[\r\n]+" t)))))
-
+ (let ((result
+ (do-applescript
+ (concat
+ "set oldClipboard to the clipboard\n"
+ "set frontmostApplication to path to frontmost application\n"
+ "tell application \"Firefox\"\n"
+ " activate\n"
+ " delay 0.15\n"
+ " tell application \"System Events\"\n"
+ " keystroke \"y\"\n"
+ " end tell\n"
+ " delay 0.15\n"
+ " set theUrl to the clipboard\n"
+ " set the clipboard to oldClipboard\n"
+ " set theResult to (get theUrl) & \"::split::\" & (get name of window 1)\n"
+ "end tell\n"
+ "activate application (frontmostApplication as text)\n"
+ "set links to {}\n"
+ "copy theResult to the end of links\n"
+ "return links as string\n"))))
+ (replace-regexp-in-string
+ "\s+-\s+Vimperator" "" (car (split-string result "[\r\n]+" t)))))
(defun org-mac-vimperator-get-frontmost-url ()
(interactive)
@@ -348,27 +362,20 @@ applications and inserting them in org documents"
;; Firefox because Chrome doesn't publish an Applescript dictionary
(defun org-as-mac-chrome-get-frontmost-url ()
- (let ((result (do-applescript
- (concat
- "set oldClipboard to the clipboard\n"
- "set frontmostApplication to path to frontmost application\n"
- "tell application \"Google Chrome\"\n"
- " activate\n"
- " delay 0.15\n"
- " tell application \"System Events\"\n"
- " keystroke \"l\" using command down\n"
- " keystroke \"c\" using command down\n"
- " end tell\n"
- " delay 0.15\n"
- " set theUrl to the clipboard\n"
- " set the clipboard to oldClipboard\n"
- " set theResult to (get theUrl) & \"::split::\" & (get name of window 1)\n"
- "end tell\n"
- "activate application (frontmostApplication as text)\n"
- "set links to {}\n"
- "copy theResult to the end of links\n"
- "return links as string\n"))))
- (car (split-string result "[\r\n]+" t))))
+ (let ((result
+ (do-applescript
+ (concat
+ "set frontmostApplication to path to frontmost application\n"
+ "tell application \"Google Chrome\"\n"
+ " set theUrl to get URL of active tab of first window\n"
+ " set theResult to (get theUrl) & \"::split::\" & (get name of window 1)\n"
+ "end tell\n"
+ "activate application (frontmostApplication as text)\n"
+ "set links to {}\n"
+ "copy theResult to the end of links\n"
+ "return links as string\n"))))
+ (replace-regexp-in-string
+ "^\"\\|\"$" "" (car (split-string result "[\r\n]+" t)))))
(defun org-mac-chrome-get-frontmost-url ()
(interactive)
@@ -392,13 +399,14 @@ applications and inserting them in org documents"
;; Grab the frontmost url from Safari.
(defun org-as-mac-safari-get-frontmost-url ()
- (let ((result (do-applescript
- (concat
- "tell application \"Safari\"\n"
- " set theUrl to URL of document 1\n"
- " set theName to the name of the document 1\n"
- " return theUrl & \"::split::\" & theName & \"\n\"\n"
- "end tell\n"))))
+ (let ((result
+ (do-applescript
+ (concat
+ "tell application \"Safari\"\n"
+ " set theUrl to URL of document 1\n"
+ " set theName to the name of the document 1\n"
+ " return theUrl & \"::split::\" & theName & \"\n\"\n"
+ "end tell\n"))))
(car (split-string result "[\r\n]+" t))))
(defun org-mac-safari-get-frontmost-url ()
@@ -419,30 +427,26 @@ applications and inserting them in org documents"
(insert (org-mac-safari-get-frontmost-url)))
-;;
-;;
;; Handle links from together.app
-;;
-;;
(org-add-link-type "x-together-item" 'org-mac-together-item-open)
(defun org-mac-together-item-open (uid)
- "Open the given uid, which is a reference to an item in Together"
+ "Open UID, which is a reference to an item in Together."
(shell-command (concat "open -a Together \"x-together-item:" uid "\"")))
(defun as-get-selected-together-items ()
(do-applescript
- (concat
- "tell application \"Together\"\n"
- " set theLinkList to {}\n"
- " set theSelection to selected items\n"
- " repeat with theItem in theSelection\n"
- " set theLink to (get item link of theItem) & \"::split::\" & (get name of theItem) & \"\n\"\n"
- " copy theLink to end of theLinkList\n"
- " end repeat\n"
- " return theLinkList as string\n"
- "end tell")))
+ (concat
+ "tell application \"Together\"\n"
+ " set theLinkList to {}\n"
+ " set theSelection to selected items\n"
+ " repeat with theItem in theSelection\n"
+ " set theLink to (get item link of theItem) & \"::split::\" & (get name of theItem) & \"\n\"\n"
+ " copy theLink to end of theLinkList\n"
+ " end repeat\n"
+ " return theLinkList as string\n"
+ "end tell")))
(defun org-mac-together-get-selected ()
(interactive)
@@ -452,26 +456,22 @@ applications and inserting them in org documents"
(defun org-mac-together-insert-selected ()
(interactive)
(insert (org-mac-together-get-selected)))
-
-;;
-;;
+
;; Handle links from Finder.app
-;;
-;;
(defun as-get-selected-finder-items ()
(do-applescript
- (concat
- "tell application \"Finder\"\n"
- " set theSelection to the selection\n"
- " set links to {}\n"
- " repeat with theItem in theSelection\n"
- " set theLink to \"file://\" & (POSIX path of (theItem as string)) & \"::split::\" & (get the name of theItem) & \"\n\"\n"
- " copy theLink to the end of links\n"
- " end repeat\n"
- " return links as string\n"
- "end tell\n")))
+ (concat
+ "tell application \"Finder\"\n"
+ " set theSelection to the selection\n"
+ " set links to {}\n"
+ " repeat with theItem in theSelection\n"
+ " set theLink to \"file://\" & (POSIX path of (theItem as string)) & \"::split::\" & (get the name of theItem) & \"\n\"\n"
+ " copy theLink to the end of links\n"
+ " end repeat\n"
+ " return links as string\n"
+ "end tell\n")))
(defun org-mac-finder-item-get-selected ()
(interactive)
@@ -483,30 +483,26 @@ applications and inserting them in org documents"
(insert (org-mac-finder-item-get-selected)))
-;;
-;;
;; Handle links from AddressBook.app
-;;
-;;
(org-add-link-type "addressbook" 'org-mac-addressbook-item-open)
(defun org-mac-addressbook-item-open (uid)
- "Open the given uid, which is a reference to an item in Together"
+ "Open UID, which is a reference to an item in the addressbook."
(shell-command (concat "open \"addressbook:" uid "\"")))
(defun as-get-selected-addressbook-items ()
(do-applescript
- (concat
- "tell application \"Address Book\"\n"
- " set theSelection to the selection\n"
- " set links to {}\n"
- " repeat with theItem in theSelection\n"
- " set theLink to \"addressbook://\" & (the id of theItem) & \"::split::\" & (the name of theItem) & \"\n\"\n"
- " copy theLink to the end of links\n"
- " end repeat\n"
- " return links as string\n"
- "end tell\n")))
+ (concat
+ "tell application \"Address Book\"\n"
+ " set theSelection to the selection\n"
+ " set links to {}\n"
+ " repeat with theItem in theSelection\n"
+ " set theLink to \"addressbook://\" & (the id of theItem) & \"::split::\" & (the name of theItem) & \"\n\"\n"
+ " copy theLink to the end of links\n"
+ " end repeat\n"
+ " return links as string\n"
+ "end tell\n")))
(defun org-mac-addressbook-item-get-selected ()
(interactive)
@@ -517,8 +513,7 @@ applications and inserting them in org documents"
(interactive)
(insert (org-mac-addressbook-item-get-selected)))
-;;
-;;
+
;; Handle links from Skim.app
;;
;; Original code & idea by Christopher Suckling (org-mac-protocol)
@@ -531,40 +526,39 @@ applications and inserting them in org documents"
(match-string 1 uri)))
(document (substring uri 0 (match-beginning 0))))
(do-applescript
- (concat
- "tell application \"Skim\"\n"
- "activate\n"
- "set theDoc to \"" document "\"\n"
- "set thePage to " page "\n"
- "open theDoc\n"
- "go document 1 to page thePage of document 1\n"
- "end tell"))))
-
+ (concat
+ "tell application \"Skim\"\n"
+ "activate\n"
+ "set theDoc to \"" document "\"\n"
+ "set thePage to " page "\n"
+ "open theDoc\n"
+ "go document 1 to page thePage of document 1\n"
+ "end tell"))))
(defun as-get-skim-page-link ()
(do-applescript
+ (concat
+ "tell application \"Skim\"\n"
+ "set theDoc to front document\n"
+ "set theTitle to (name of theDoc)\n"
+ "set thePath to (path of theDoc)\n"
+ "set thePage to (get index for current page of theDoc)\n"
+ "set theSelection to selection of theDoc\n"
+ "set theContent to contents of (get text for theSelection)\n"
+ "if theContent is missing value then\n"
+ " set theContent to theTitle & \", p. \" & thePage\n"
+ (when org-mac-Skim-highlight-selection-p
(concat
- "tell application \"Skim\"\n"
- "set theDoc to front document\n"
- "set theTitle to (name of theDoc)\n"
- "set thePath to (path of theDoc)\n"
- "set thePage to (get index for current page of theDoc)\n"
- "set theSelection to selection of theDoc\n"
- "set theContent to contents of (get text for theSelection)\n"
- "if theContent is missing value then\n"
- " set theContent to theTitle & \", p. \" & thePage\n"
- (when org-mac-Skim-highlight-selection-p
- (concat
- "else\n"
- " tell theDoc\n"
- " set theNote to make note with properties {type:highlight note, selection:theSelection}\n"
- " set text of theNote to (get text for theSelection)\n"
- " end tell\n"))
- "end if\n"
- "set theLink to \"skim://\" & thePath & \"::\" & thePage & "
- "\"::split::\" & theContent\n"
- "end tell\n"
- "return theLink as string\n")))
+ "else\n"
+ " tell theDoc\n"
+ " set theNote to make note with properties {type:highlight note, selection:theSelection}\n"
+ " set text of theNote to (get text for theSelection)\n"
+ " end tell\n"))
+ "end if\n"
+ "set theLink to \"skim://\" & thePath & \"::\" & thePage & "
+ "\"::split::\" & theContent\n"
+ "end tell\n"
+ "return theLink as string\n")))
(defun org-mac-skim-get-page ()
(interactive)
@@ -583,23 +577,19 @@ applications and inserting them in org documents"
(interactive)
(insert (org-mac-skim-get-page)))
-
-;;
-;;
;; Handle links from Microsoft Outlook.app
-;;
(org-add-link-type "mac-outlook" 'org-mac-outlook-message-open)
(defun org-mac-outlook-message-open (msgid)
- "Open a message in outlook"
- (let* ((record-id-string (format "mdfind com_microsoft_outlook_recordID==%s" msgid))
- (found-message (replace-regexp-in-string "\n$" ""
- (shell-command-to-string record-id-string))))
- (if (string= found-message "")
- (message "org-mac-link: error could not find Outlook message %s" (substring-no-properties msgid))
- (shell-command (format "open \"`mdfind com_microsoft_outlook_recordID==%s`\"" msgid)))))
+ "Open a message in Outlook"
+ (do-applescript
+ (concat
+ "tell application \"Microsoft Outlook\"\n"
+ (format "open message id %s\n" (substring-no-properties msgid))
+ "activate\n"
+ "end tell")))
(defun org-as-get-selected-outlook-mail ()
"AppleScript to create links to selected messages in Microsoft Outlook.app."
@@ -680,16 +670,18 @@ The Org-syntax text will be pushed to the kill ring, and also returned."
(defun org-mac-outlook-message-insert-selected ()
"Insert a link to the messages currently selected in Microsoft Outlook.app.
-This will use AppleScript to get the message-id and the subject of the
-active mail in Microsoft Outlook.app and make a link out of it."
+This will use AppleScript to get the message-id and the subject
+of the active mail in Microsoft Outlook.app and make a link out
+of it."
(interactive)
(insert (org-mac-outlook-message-get-links "s")))
(defun org-mac-outlook-message-insert-flagged (org-buffer org-heading)
"Asks for an org buffer and a heading within it, and replace message links.
-If heading exists, delete all mac-outlook:// links within heading's first
-level. If heading doesn't exist, create it at point-max. Insert
-list of mac-outlook:// links to flagged mail after heading."
+If heading exists, delete all mac-outlook:// links within
+heading's first level. If heading doesn't exist, create it at
+point-max. Insert list of mac-outlook:// links to flagged mail
+after heading."
(interactive "bBuffer in which to insert links: \nsHeading after which to insert links: ")
(with-current-buffer org-buffer
(goto-char (point-min))
@@ -710,17 +702,78 @@ list of mac-outlook:// links to flagged mail after heading."
(org-insert-heading nil t)
(insert org-heading "\n" (org-mac-outlook-message-get-links "f"))))))
+
+;; Handle links from DEVONthink Pro Office.app
+
+(org-add-link-type "x-devonthink-item" 'org-devonthink-item-open)
+
+(defun org-devonthink-item-open (uid)
+ "Open UID, which is a reference to an item in DEVONthink Pro Office."
+ (shell-command (concat "open \"x-devonthink-item:" uid "\"")))
+
+(defun org-as-get-selected-devonthink-item ()
+ "AppleScript to create links to selected items in DEVONthink Pro Office.app."
+ (do-applescript
+ (concat
+ "set theLinkList to {}\n"
+ "tell application \"DEVONthink Pro\"\n"
+ "set selectedRecords to selection\n"
+ "set selectionCount to count of selectedRecords\n"
+ "if (selectionCount < 1) then\n"
+ "return\n"
+ "end if\n"
+ "repeat with theRecord in selectedRecords\n"
+ "set theID to uuid of theRecord\n"
+ "set theURL to \"x-devonthink-item:\" & theID\n"
+ "set theSubject to name of theRecord\n"
+ "set theLink to theURL & \"::split::\" & theSubject & \"\n\"\n"
+ "copy theLink to end of theLinkList\n"
+ "end repeat\n"
+ "end tell\n"
+ "return theLinkList as string"
+ )))
+
+(defun org-mac-devonthink-get-links ()
+ "Create links to the item(s) currently selected in DEVONthink Pro Office.
+This will use AppleScript to get the `uuid' and the `name' of the
+selected items in DEVONthink Pro Office.app and make links out of
+it/them. This function will push the Org-syntax text to the kill
+ring, and also return it."
+ (message "Org Mac DEVONthink: looking for selected items...")
+ (let* ((as-link-list (org-as-get-selected-devonthink-item))
+ (link-list (if as-link-list
+ (mapcar
+ (lambda (x) (if (string-match "\\`\"\\(.*\\)\"\\'" x)
+ (setq x (match-string 1 x)))
+ x)
+ (split-string as-link-list "[\r\n]+"))
+ nil))
+ orglink-list)
+ (while link-list
+ (let* ((current-item (pop link-list)))
+ (message "current item: %s" current-item)
+ (when (and current-item (not (string= current-item "")))
+ (let* ((split-link (split-string current-item "::split::"))
+ (orglink (org-make-link-string
+ (url-encode-url (car split-link))
+ (cadr split-link))))
+ (push orglink orglink-list)))))
+ (kill-new (mapconcat 'identity orglink-list "\n"))))
+
+(defun org-mac-devonthink-item-insert-selected ()
+ "Insert a link to the item(s) currently selected in DEVONthink Pro Office.
+This will use AppleScript to get the `uuid'(s) and the name(s) of the
+selected items in DEVONthink Pro Office and make link(s) out of it/them."
+ (interactive)
+ (insert (org-mac-devonthink-get-links)))
-;;
-;;
;; Handle links from Mail.app
-;;
(org-add-link-type "message" 'org-mac-message-open)
(defun org-mac-message-open (message-id)
- "Visit the message with the given MESSAGE-ID.
+ "Visit the message with MESSAGE-ID.
This will use the command `open' with the message URL."
(start-process (concat "open message:" message-id) nil
"open" (concat "message://<" (substring message-id 2) ">")))
@@ -728,67 +781,70 @@ This will use the command `open' with the message URL."
(defun org-as-get-selected-mail ()
"AppleScript to create links to selected messages in Mail.app."
(do-applescript
- (concat
- "tell application \"Mail\"\n"
- "set theLinkList to {}\n"
- "set theSelection to selection\n"
- "repeat with theMessage in theSelection\n"
- "set theID to message id of theMessage\n"
- "set theSubject to subject of theMessage\n"
- "set theLink to \"message://\" & theID & \"::split::\" & theSubject & \"\n\"\n"
- "copy theLink to end of theLinkList\n"
- "end repeat\n"
- "return theLinkList as string\n"
- "end tell")))
+ (concat
+ "tell application \"Mail\"\n"
+ "set theLinkList to {}\n"
+ "set theSelection to selection\n"
+ "repeat with theMessage in theSelection\n"
+ "set theID to message id of theMessage\n"
+ "set theSubject to subject of theMessage\n"
+ "set theLink to \"message://\" & theID & \"::split::\" & theSubject\n"
+ "if (theLinkList is not equal to {}) then\n"
+ "set theLink to \"\n\" & theLink\n"
+ "end if\n"
+ "copy theLink to end of theLinkList\n"
+ "end repeat\n"
+ "return theLinkList as string\n"
+ "end tell")))
(defun org-as-get-flagged-mail ()
"AppleScript to create links to flagged messages in Mail.app."
(do-applescript
- (concat
- ;; Is Growl installed?
- "tell application \"System Events\"\n"
- "set growlHelpers to the name of every process whose creator type contains \"GRRR\"\n"
- "if (count of growlHelpers) > 0 then\n"
- "set growlHelperApp to item 1 of growlHelpers\n"
- "else\n"
- "set growlHelperApp to \"\"\n"
- "end if\n"
- "end tell\n"
-
- ;; Get links
- "tell application \"Mail\"\n"
- "set theMailboxes to every mailbox of account \"" org-mac-mail-account "\"\n"
- "set theLinkList to {}\n"
- "repeat with aMailbox in theMailboxes\n"
- "set theSelection to (every message in aMailbox whose flagged status = true)\n"
- "repeat with theMessage in theSelection\n"
- "set theID to message id of theMessage\n"
- "set theSubject to subject of theMessage\n"
- "set theLink to \"message://\" & theID & \"::split::\" & theSubject & \"\n\"\n"
- "copy theLink to end of theLinkList\n"
-
- ;; Report progress through Growl
- ;; This "double tell" idiom is described in detail at
- ;; http://macscripter.net/viewtopic.php?id=24570 The
- ;; script compiler needs static knowledge of the
- ;; growlHelperApp. Hmm, since we're compiling
- ;; on-the-fly here, this is likely to be way less
- ;; portable than I'd hoped. It'll work when the name
- ;; is still "GrowlHelperApp", though.
- "if growlHelperApp is not \"\" then\n"
- "tell application \"GrowlHelperApp\"\n"
- "tell application growlHelperApp\n"
- "set the allNotificationsList to {\"FlaggedMail\"}\n"
- "set the enabledNotificationsList to allNotificationsList\n"
- "register as application \"FlaggedMail\" all notifications allNotificationsList default notifications enabledNotificationsList icon of application \"Mail\"\n"
- "notify with name \"FlaggedMail\" title \"Importing flagged message\" description theSubject application name \"FlaggedMail\"\n"
- "end tell\n"
- "end tell\n"
- "end if\n"
- "end repeat\n"
- "end repeat\n"
- "return theLinkList as string\n"
- "end tell")))
+ (concat
+ ;; Is Growl installed?
+ "tell application \"System Events\"\n"
+ "set growlHelpers to the name of every process whose creator type contains \"GRRR\"\n"
+ "if (count of growlHelpers) > 0 then\n"
+ "set growlHelperApp to item 1 of growlHelpers\n"
+ "else\n"
+ "set growlHelperApp to \"\"\n"
+ "end if\n"
+ "end tell\n"
+
+ ;; Get links
+ "tell application \"Mail\"\n"
+ "set theMailboxes to every mailbox of account \"" org-mac-mail-account "\"\n"
+ "set theLinkList to {}\n"
+ "repeat with aMailbox in theMailboxes\n"
+ "set theSelection to (every message in aMailbox whose flagged status = true)\n"
+ "repeat with theMessage in theSelection\n"
+ "set theID to message id of theMessage\n"
+ "set theSubject to subject of theMessage\n"
+ "set theLink to \"message://\" & theID & \"::split::\" & theSubject & \"\n\"\n"
+ "copy theLink to end of theLinkList\n"
+
+ ;; Report progress through Growl
+ ;; This "double tell" idiom is described in detail at
+ ;; http://macscripter.net/viewtopic.php?id=24570 The
+ ;; script compiler needs static knowledge of the
+ ;; growlHelperApp. Hmm, since we're compiling
+ ;; on-the-fly here, this is likely to be way less
+ ;; portable than I'd hoped. It'll work when the name
+ ;; is still "GrowlHelperApp", though.
+ "if growlHelperApp is not \"\" then\n"
+ "tell application \"GrowlHelperApp\"\n"
+ "tell application growlHelperApp\n"
+ "set the allNotificationsList to {\"FlaggedMail\"}\n"
+ "set the enabledNotificationsList to allNotificationsList\n"
+ "register as application \"FlaggedMail\" all notifications allNotificationsList default notifications enabledNotificationsList icon of application \"Mail\"\n"
+ "notify with name \"FlaggedMail\" title \"Importing flagged message\" description theSubject application name \"FlaggedMail\"\n"
+ "end tell\n"
+ "end tell\n"
+ "end if\n"
+ "end repeat\n"
+ "end repeat\n"
+ "return theLinkList as string\n"
+ "end tell")))
(defun org-mac-message-get-links (&optional select-or-flag)
"Create links to the messages currently selected or flagged in Mail.app.
@@ -803,13 +859,13 @@ The Org-syntax text will be pushed to the kill ring, and also returned."
(let* ((as-link-list
(if (string= select-or-flag "s")
(org-as-get-selected-mail)
- (if (string= select-or-flag "f")
- (org-as-get-flagged-mail)
- (error "Please select \"s\" or \"f\""))))
+ (if (string= select-or-flag "f")
+ (org-as-get-flagged-mail)
+ (error "Please select \"s\" or \"f\""))))
(link-list
(mapcar
(lambda (x) (if (string-match "\\`\"\\(.*\\)\"\\'" x) (setq x (match-string 1 x))) x)
- (split-string as-link-list "[\r\n]+")))
+ (split-string (substring as-link-list 1 -1) "[\r\n]+")))
split-link URL description orglink orglink-insert rtn orglink-list)
(while link-list
(setq split-link (split-string (pop link-list) "::split::"))
@@ -851,11 +907,11 @@ list of message:// links to flagged mail after heading."
(delete-region (match-beginning 0) (match-end 0)))
(insert "\n" (org-mac-message-get-links "f")))
(flush-lines "^$" (point) (outline-next-heading)))
- (insert "\n" (org-mac-message-get-links "f")))
- (goto-char (point-max))
- (insert "\n")
- (org-insert-heading nil t)
- (insert org-heading "\n" (org-mac-message-get-links "f"))))))
+ (insert "\n" (org-mac-message-get-links "f")))
+ (goto-char (point-max))
+ (insert "\n")
+ (org-insert-heading nil t)
+ (insert org-heading "\n" (org-mac-message-get-links "f"))))))
(provide 'org-mac-link)
diff --git a/contrib/lisp/org-mairix.el b/contrib/lisp/org-mairix.el
index b08897d..a19719e 100644
--- a/contrib/lisp/org-mairix.el
+++ b/contrib/lisp/org-mairix.el
@@ -1,6 +1,6 @@
;;; org-mairix.el - Support for hooking mairix search into Org for different MUAs
;;
-;; Copyright (C) 2007-2013 Georg C. F. Greve
+;; Copyright (C) 2007-2014 Georg C. F. Greve
;; mutt support by Adam Spiers <orgmode at adamspiers dot org>
;;
;; This file is not part of GNU Emacs.
diff --git a/contrib/lisp/org-mew.el b/contrib/lisp/org-mew.el
index ca6a352..4482375 100644
--- a/contrib/lisp/org-mew.el
+++ b/contrib/lisp/org-mew.el
@@ -1,6 +1,6 @@
;;; org-mew.el --- Support for links to Mew messages from within Org-mode
-;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;; Author: Tokuya Kameshima <kames at fa2 dot so-net dot ne dot jp>
;; Keywords: outlines, hypermedia, calendar, wp
diff --git a/contrib/lisp/org-mime.el b/contrib/lisp/org-mime.el
index ef2057c..44bf91b 100644
--- a/contrib/lisp/org-mime.el
+++ b/contrib/lisp/org-mime.el
@@ -1,6 +1,6 @@
;;; org-mime.el --- org html export for text/html MIME emails
-;; Copyright (C) 2010-2013 Eric Schulte
+;; Copyright (C) 2010-2014 Eric Schulte
;; Author: Eric Schulte
;; Keywords: mime, mail, email, html
@@ -163,10 +163,13 @@ and images in a multipart/related part."
('semi (concat
"--" "<<alternative>>-{\n"
"--" "[[text/plain]]\n" plain
- (when images (concat "--" "<<alternative>>-{\n"))
- "--" "[[text/html]]\n" html
- images
- (when images (concat "--" "}-<<alternative>>\n"))
+ (if (and images (> (length images) 0))
+ (concat "--" "<<related>>-{\n"
+ "--" "[[text/html]]\n" html
+ images
+ "--" "}-<<related>>\n")
+ (concat "--" "[[text/html]]\n" html
+ images))
"--" "}-<<alternative>>\n"))
('vm "?")))
@@ -269,8 +272,10 @@ export that region, otherwise export the entire body."
(defun org-mime-send-buffer (&optional fmt)
(run-hooks 'org-mime-send-buffer-hook)
(let* ((region-p (org-region-active-p))
- (subject (org-export-grab-title-from-buffer))
- (file (buffer-file-name (current-buffer)))
+ (file (buffer-file-name (current-buffer)))
+ (subject (if (not file) (buffer-name (buffer-base-buffer))
+ (file-name-sans-extension
+ (file-name-nondirectory file))))
(body-start (or (and region-p (region-beginning))
(save-excursion (goto-char (point-min)))))
(body-end (or (and region-p (region-end)) (point-max)))
diff --git a/contrib/lisp/org-mtags.el b/contrib/lisp/org-mtags.el
deleted file mode 100644
index dadcef7..0000000
--- a/contrib/lisp/org-mtags.el
+++ b/dev/null
@@ -1,255 +0,0 @@
-;;; org-mtags.el --- Muse-like tags in Org-mode
-
-;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
-;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: http://orgmode.org
-;; Version: 0.01
-;;
-;; This file is not yet part of GNU Emacs.
-;;
-;; This program 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,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Commentary:
-;;
-;; This modules implements some of the formatting tags available in
-;; Emacs Muse. This is not a way if adding new functionality, but just
-;; a different way to write some formatting directives. The advantage is
-;; that files written in this way can be read by Muse reasonably well,
-;; and that this provides an alternative way of writing formatting
-;; directives in Org, a way that some might find more pleasant to type
-;; and look at that the Org's #+BEGIN..#+END notation.
-
-;; The goal of this development is to make it easier for people to
-;; move between both worlds as they see fit for different tasks.
-
-;; The following muse tags will be translated during export into their
-;; native Org equivalents:
-;;
-;; <br>
-;; Needs to be at the end of a line. Will be translated to "\\".
-;;
-;; <example switches="-n -r">
-;; Needs to be on a line by itself, similarly the </example> tag.
-;; Will be translated into Org's #+BEGIN_EXAMPLE construct.
-;;
-;; <quote>
-;; Needs to be on a line by itself, similarly the </quote> tag.
-;; Will be translated into Org's #+BEGIN_QUOTE construct.
-;;
-;; <comment>
-;; Needs to be on a line by itself, similarly the </comment> tag.
-;; Will be translated into Org's #+BEGIN_COMMENT construct.
-;;
-;; <verse>
-;; Needs to be on a line by itself, similarly the </verse> tag.
-;; Will be translated into Org's #+BEGIN_VERSE construct.
-;;
-;; <contents>
-;; This gets translated into "[TABLE-OF-CONTENTS]". It will not
-;; trigger the production of a table of contents - that is done
-;; in Org with the "#+OPTIONS: toc:t" setting. But it will define
-;; the location where the TOC will be placed.
-;;
-;; <literal style="STYLE"> ;; only latex, html, and docbook supported
-;; in Org.
-;; Needs to be on a line by itself, similarly the </literal> tag.
-;;
-;; <src lang="LANG" switches="-n -r">
-;; Needs to be on a line by itself, similarly the </src> tag.
-;; Will be translated into Org's BEGIN_SRC construct.
-;;
-;; <include file="FILE" markup="MARKUP" lang="LANG"
-;; prefix="str" prefix1="str" switches="-n -r">
-;; Needs to be on a line by itself.
-;; Will be translated into Org's #+INCLUDE construct.
-;;
-;; The lisp/perl/ruby/python tags can be implemented using the
-;; `org-eval.el' module, which see.
-
-(require 'org)
-
-;;; Customization
-
-(defgroup org-mtags nil
- "Options concerning Muse tags in Org mode."
- :tag "Org Muse Tags"
- :group 'org)
-
-(defface org-mtags ; similar to shadow
- (org-compatible-face 'shadow
- '((((class color grayscale) (min-colors 88) (background light))
- (:foreground "grey50"))
- (((class color grayscale) (min-colors 88) (background dark))
- (:foreground "grey70"))
- (((class color) (min-colors 8) (background light))
- (:foreground "green"))
- (((class color) (min-colors 8) (background dark))
- (:foreground "yellow"))))
- "Face for Muse-like tags in Org."
- :group 'org-mtags
- :group 'org-faces)
-
-(defcustom org-mtags-prefer-muse-templates t
- "Non-nil means prefere Muse tags for structure elements.
-This is relevane when expanding the templates defined in the variable
-`org-structure-templates'."
- :group 'org-mtags
- :type 'boolean)
-
-(defconst org-mtags-supported-tags
- '("example" "quote" "comment" "verse" "contents" "literal" "src" "include")
- "The tags that are supported by org-mtags.el for conversion.
-In addition to this list, the <br> tag is supported as well.")
-
-(defconst org-mtags-fontification-re
- (concat
- "^[ \t]*</?\\("
- (mapconcat 'identity org-mtags-supported-tags "\\|")
- "\\)\\>[^>]*>\\|<br>[ \t]*$")
- "Regular expression used for fontifying muse tags.")
-
-(defun org-mtags-replace ()
- "Replace Muse-like tags with the appropriate Org constructs.
-The is done in the entire buffer."
- (interactive) ;; FIXME
- (let ((re (concat "^[ \t]*\\(</?\\("
- (mapconcat 'identity org-mtags-supported-tags "\\|")
- "\\)\\>\\)"))
- info tag rpl style markup lang file prefix prefix1 switches)
- ;; First, do the <br> tag
- (goto-char (point-min))
- (while (re-search-forward "<br>[ \t]*$" nil t)
- (replace-match "\\\\" t t))
- ;; Now, all the other tags
- (goto-char (point-min))
- (while (re-search-forward re nil t)
- (goto-char (match-beginning 1))
- (setq info (org-mtags-get-tag-and-attributes))
- (if (not info)
- (end-of-line 1)
- (setq tag (plist-get info :tag))
- (cond
- ((equal tag "contents")
- (setq rpl "[TABLE-OF-CONTENTS]")
- ;; FIXME: also trigger TOC in options-plist?????
- )
- ((member tag '("quote" "comment" "verse"))
- (if (plist-get info :closing)
- (setq rpl (format "#+END_%s" (upcase tag)))
- (setq rpl (format "#+BEGIN_%s" (upcase tag)))))
- ((equal tag "literal")
- (setq style (plist-get info :style))
- (and style (setq style (downcase style)))
- (if (plist-get info :closing)
- (setq rpl (cond
- ((member style '("latex"))
- "#+END_LaTeX")
- ((member style '("html"))
- "#+END_HTML")
- ((member style '("docbook"))
- "#+END_DOCBOOK")
- ((member style '("ascii"))
- "#+END_ASCII")))
- (setq rpl (cond
- ((member style '("latex"))
- "#+BEGIN_LaTeX")
- ((member style '("html"))
- "#+BEGIN_HTML")
- ((member style '("ascii"))
- "#+BEGIN_ASCII")))))
- ((equal tag "example")
- (if (plist-get info :closing)
- (setq rpl "#+END_EXAMPLE")
- (setq rpl "#+BEGIN_EXAMPLE")
- (when (setq switches (plist-get info :switches))
- (setq rpl (concat rpl " " switches)))))
- ((equal tag "src")
- (if (plist-get info :closing)
- (setq rpl "#+END_SRC")
- (setq rpl "#+BEGIN_SRC")
- (when (setq lang (plist-get info :lang))
- (setq rpl (concat rpl " " lang))
- (when (setq switches (plist-get info :switches))
- (setq rpl (concat rpl " " switches))))))
- ((equal tag "include")
- (setq file (plist-get info :file)
- markup (downcase (plist-get info :markup))
- lang (plist-get info :lang)
- prefix (plist-get info :prefix)
- prefix1 (plist-get info :prefix1)
- switches (plist-get info :switches))
- (setq rpl "#+INCLUDE")
- (setq rpl (concat rpl " " (prin1-to-string file)))
- (when markup
- (setq rpl (concat rpl " " markup))
- (when (and (equal markup "src") lang)
- (setq rpl (concat rpl " " lang))))
- (when prefix
- (setq rpl (concat rpl " :prefix " (prin1-to-string prefix))))
- (when prefix1
- (setq rpl (concat rpl " :prefix1 " (prin1-to-string prefix1))))
- (when switches
- (setq rpl (concat rpl " " switches)))))
- (when rpl
- (goto-char (plist-get info :match-beginning))
- (delete-region (point-at-bol) (plist-get info :match-end))
- (insert rpl))))))
-
-(defun org-mtags-get-tag-and-attributes ()
- "Parse a Muse-like tag at point ant rturn the information about it.
-The return value is a property list which contains all the attributes
-with string values. In addition, it reutnrs the following properties:
-
-:tag The tag as a string.
-:match-beginning The beginning of the match, just before \"<\".
-:match-end The end of the match, just after \">\".
-:closing t when the tag starts with \"</\"."
- (when (looking-at "<\\(/\\)?\\([a-zA-Z]+\\>\\)\\([^>]*\\)>")
- (let ((start 0)
- tag rest prop attributes endp val)
- (setq tag (org-match-string-no-properties 2)
- endp (match-end 1)
- rest (and (match-end 3)
- (org-match-string-no-properties 3))
- attributes (list :tag tag
- :match-beginning (match-beginning 0)
- :match-end (match-end 0)
- :closing endp))
- (when rest
- (while (string-match "\\([a-zA-Z]+\\)=\\([^ \t\n>]+\\|\"[^>]+\"\\)"
- rest start)
- (setq start (match-end 0)
- prop (org-match-string-no-properties 1 rest)
- val (org-remove-double-quotes
- (org-match-string-no-properties 2 rest)))
- (setq attributes (plist-put attributes
- (intern (concat ":" prop)) val))))
- attributes)))
-
-(defun org-mtags-fontify-tags (limit)
- "Fontify the muse-like tags."
- (while (re-search-forward org-mtags-fontification-re limit t)
- (add-text-properties (match-beginning 0) (match-end 0)
- '(face org-mtags font-lock-multiline t
- font-lock-fontified t))))
-
-(add-hook 'org-export-preprocess-hook 'org-mtags-replace)
-(add-hook 'org-font-lock-hook 'org-mtags-fontify-tags)
-
-(provide 'org-mtags)
-
-;;; org-mtags.el ends here
diff --git a/contrib/lisp/org-notify.el b/contrib/lisp/org-notify.el
index 4047448..da2c96f 100644
--- a/contrib/lisp/org-notify.el
+++ b/contrib/lisp/org-notify.el
@@ -1,6 +1,6 @@
;;; org-notify.el --- Notifications for Org-mode
-;; Copyright (C) 2012, 2013 Free Software Foundation, Inc.
+;; Copyright (C) 2012, 2013, 2014 Free Software Foundation, Inc.
;; Author: Peter Münster <pmrb@free.fr>
;; Keywords: notification, todo-list, alarm, reminder, pop-up
diff --git a/contrib/lisp/org-notmuch.el b/contrib/lisp/org-notmuch.el
index c7f92fe..ae9b50b 100644
--- a/contrib/lisp/org-notmuch.el
+++ b/contrib/lisp/org-notmuch.el
@@ -1,6 +1,6 @@
;;; org-notmuch.el --- Support for links to notmuch messages from within Org-mode
-;; Copyright (C) 2010-2013 Matthieu Lemerre
+;; Copyright (C) 2010-2014 Matthieu Lemerre
;; Author: Matthieu Lemerre <racin@free.fr>
;; Keywords: outlines, hypermedia, calendar, wp
@@ -41,6 +41,29 @@
(require 'org)
+;; customisable notmuch open functions
+(defcustom org-notmuch-open-function
+ 'org-notmuch-follow-link
+ "Function used to follow notmuch links.
+
+Should accept a notmuch search string as the sole argument."
+ :group 'org-notmuch
+ :version "24.4"
+ :package-version '(Org . "8.0")
+ :type 'function)
+
+(defcustom org-notmuch-search-open-function
+ 'org-notmuch-search-follow-link
+ "Function used to follow notmuch-search links.
+
+Should accept a notmuch search string as the sole argument."
+ :group 'org-notmuch
+ :version "24.4"
+ :package-version '(Org . "8.0")
+ :type 'function)
+
+
+
;; Install the link type
(org-add-link-type "notmuch" 'org-notmuch-open)
(add-hook 'org-store-link-functions 'org-notmuch-store-link)
@@ -62,7 +85,7 @@
(defun org-notmuch-open (path)
"Follow a notmuch message link specified by PATH."
- (org-notmuch-follow-link path))
+ (funcall org-notmuch-open-function path))
(defun org-notmuch-follow-link (search)
"Follow a notmuch link to SEARCH.
@@ -91,13 +114,20 @@ Can link to more than one message, if so all matching messages are shown."
(defun org-notmuch-search-open (path)
"Follow a notmuch message link specified by PATH."
(message path)
- (org-notmuch-search-follow-link path))
+ (funcall org-notmuch-search-open-function path))
(defun org-notmuch-search-follow-link (search)
"Follow a notmuch link by displaying SEARCH in notmuch-search mode."
(require 'notmuch)
(notmuch-search (org-link-unescape search)))
+
+
+(defun org-notmuch-tree-follow-link (search)
+ "Follow a notmuch link by displaying SEARCH in notmuch-tree mode."
+ (require 'notmuch)
+ (notmuch-tree (org-link-unescape search)))
+
(provide 'org-notmuch)
;;; org-notmuch.el ends here
diff --git a/contrib/lisp/org-passwords.el b/contrib/lisp/org-passwords.el
new file mode 100644
index 0000000..7ed8c80
--- a/dev/null
+++ b/contrib/lisp/org-passwords.el
@@ -0,0 +1,342 @@
+;;; org-passwords.el --- org derived mode for managing passwords
+
+;; Author: Jorge A. Alfaro-Murillo <jorge.alfaro-murillo@yale.edu>
+;; Created: December 26, 2012
+;; Keywords: passwords, password
+
+;; This file is NOT part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+
+;; This file contains the code for managing your passwords with
+;; Org-mode.
+
+;; A basic setup needs to indicate a passwords file, and a dictionary
+;; for the random words:
+
+;; (require org-passwords)
+;; (setq org-passwords-file "~/documents/passwords.gpg")
+;; (setq org-passwords-random-words-dictionary "/etc/dictionaries-common/words")
+
+;; Basic usage:
+
+;; `M-x org-passwords' opens the passwords file in
+;; `org-passwords-mode'.
+
+;; `M-x org-passwords-generate-password' generates a random string
+;; of numbers, lowercase letters and uppercase letters.
+
+;; `C-u M-x org-passwords-generate-password' generates a random
+;; string of numbers, lowercase letters, uppercase letters and
+;; symbols.
+
+;; `M-x org-passwords-random-words' concatenates random words from
+;; the dictionary defined by `org-passwords-random-words-dictionary'
+;; into a string, each word separated by the string defined in
+;; `org-passwords-random-words-separator'.
+
+;; `C-u M-x org-passwords-random-words' does the same as above, and
+;; also makes substitutions according to
+;; `org-passwords-random-words-substitutions'.
+
+;; It is also useful to set up keybindings for the functions
+;; `org-passwords-copy-username' and
+;; `org-passwords-copy-password' in the
+;; `org-passwords-mode', to easily make the passwords and usernames
+;; available to the facility for pasting text of the window system
+;; (clipboard on X and MS-Windows, pasteboard on Nextstep/Mac OS,
+;; etc.), without inserting them in the kill-ring. You can set for
+;; example:
+
+;; (eval-after-load "org-passwords"
+;; '(progn
+;; (define-key org-passwords-mode-map
+;; (kbd "C-c u")
+;; 'org-passwords-copy-username)
+;; (define-key org-passwords-mode-map
+;; (kbd "C-c p")
+;; 'org-passwords-copy-password)))
+
+;; Finally, to enter new passwords, you can use `org-capture' and a minimal template like:
+
+;; ("p" "password" entry (file "~/documents/passwords.gpg")
+;; "* %^{Title}\n %^{PASSWORD}p %^{USERNAME}p")
+
+;; When asked for the password you can then call either
+;; `org-passwords-generate-password' or `org-passwords-random-words'.
+;; Be sure to enable recursive minibuffers to call those functions
+;; from the minibuffer:
+
+;; (setq enable-recursive-minibuffers t)
+
+;;; Code:
+
+(require 'org)
+
+(define-derived-mode org-passwords-mode org-mode
+ "org-passwords-mode"
+ "Mode for storing passwords"
+ nil)
+
+(defgroup org-passwords nil
+ "Options for password management."
+ :group 'org)
+
+(defcustom org-passwords-password-property "PASSWORD"
+ "Name of the property for password entry password."
+ :type 'string
+ :group 'org-passwords)
+
+(defcustom org-passwords-username-property "USERNAME"
+ "Name of the property for password entry user name."
+ :type 'string
+ :group 'org-passwords)
+
+(defcustom org-passwords-file nil
+ "Default file name for the file that contains the passwords."
+ :type 'file
+ :group 'org-passwords)
+
+(defcustom org-passwords-time-opened "1 min"
+ "Time that the password file will remain open. It has to be a
+string, a number followed by units."
+ :type 'str
+ :group 'org-passwords)
+
+(defcustom org-passwords-random-words-dictionary nil
+ "Default file name for the file that contains a dictionary of
+words for `org-passwords-random-words'. Each non-empty line in
+the file is considered a word."
+ :type 'file
+ :group 'org-passwords)
+
+(defvar org-passwords-random-words-separator "-"
+ "A string to separate words in `org-passwords-random-words'.")
+
+(defvar org-passwords-random-words-substitutions
+ '(("a" . "@")
+ ("e" . "3")
+ ("o" . "0"))
+"A list of substitutions to be made with
+`org-passwords-random-words' if it is called with
+`universal-argument'. Each element is pair of
+strings (SUBSTITUTE-THIS . BY-THIS).")
+
+(defun org-passwords-copy-password ()
+ "Makes the password available to other programs. Puts the
+password of the entry at the location of the cursor in the
+facility for pasting text of the window system (clipboard on X
+and MS-Windows, pasteboard on Nextstep/Mac OS, etc.), without
+putting it in the kill ring."
+ (interactive)
+ (save-excursion
+ (search-backward-regexp "^\\*")
+ (search-forward-regexp (concat "^[[:space:]]*:"
+ org-passwords-password-property
+ ":[[:space:]]*"))
+ (funcall interprogram-cut-function
+ (buffer-substring-no-properties (point)
+ (funcall (lambda ()
+ (end-of-line)
+ (point)))))))
+
+(defun org-passwords-copy-username ()
+ "Makes the password available to other programs. Puts the
+username of the entry at the location of the cursor in the
+facility for pasting text of the window system (clipboard on X
+and MS-Windows, pasteboard on Nextstep/Mac OS, etc.), without
+putting it in the kill ring."
+ (interactive)
+ (save-excursion
+ (search-backward-regexp "^\\*")
+ (search-forward-regexp (concat "^[[:space:]]*:"
+ org-passwords-username-property
+ ":[[:space:]]*"))
+ (funcall interprogram-cut-function
+ (buffer-substring-no-properties (point)
+ (funcall (lambda ()
+ (end-of-line)
+ (point)))))))
+
+(defun org-passwords ()
+ "Open the password file. Open the password file defined by the
+variable `org-password-file' in read-only mode and kill that
+buffer later according to the value of the variable
+`org-passwords-time-opened'. It also adds the `org-password-file'
+to the auto-mode-alist so that it is opened with its mode being
+`org-passwords-mode'."
+ (interactive)
+ (if org-passwords-file
+ (progn
+ (add-to-list 'auto-mode-alist
+ (cons
+ (regexp-quote
+ (expand-file-name org-passwords-file))
+ 'org-passwords-mode))
+ (find-file-read-only org-passwords-file)
+ (org-passwords-set-up-kill-password-buffer))
+ (minibuffer-message "No default password file defined. Set the variable `org-password-file'.")))
+
+(defun org-passwords-set-up-kill-password-buffer ()
+ (run-at-time org-passwords-time-opened
+ nil
+ '(lambda ()
+ (if (get-file-buffer org-passwords-file)
+ (kill-buffer
+ (get-file-buffer org-passwords-file))))))
+
+;;; Password generator
+
+;; Set random number seed from current time and pid. Otherwise
+;; `random' gives the same results every time emacs restarts.
+(random t)
+
+(defun org-passwords-generate-password (arg)
+ "Ask a number of characters and insert a password of that size.
+Password has a random string of numbers, lowercase letters, and
+uppercase letters. Argument ARG include symbols."
+ (interactive "P")
+ (let ((number-of-chars
+ (string-to-number
+ (read-from-minibuffer "Number of Characters: "))))
+ (if arg
+ (insert (org-passwords-generate-password-with-symbols "" number-of-chars))
+ (insert (org-passwords-generate-password-without-symbols "" number-of-chars)))))
+
+(defun org-passwords-generate-password-with-symbols (previous-string nums-of-chars)
+ "Return a string consisting of PREVIOUS-STRING and
+NUMS-OF-CHARS random characters."
+ (if (eq nums-of-chars 0) previous-string
+ (insert (org-passwords-generate-password-with-symbols
+ (concat previous-string
+ (char-to-string
+ ;; symbols, letters, numbers are from 33 to 126
+ (+ (random (- 127 33)) 33)))
+ (1- nums-of-chars)))))
+
+(defun org-passwords-generate-password-without-symbols (previous-string nums-of-chars)
+ "Return string consisting of PREVIOUS-STRING and NUMS-OF-CHARS
+random numbers, lowercase letters, and numbers."
+ (if (eq nums-of-chars 0)
+ previous-string
+ ; There are 10 numbers, 26 lowercase letters and 26 uppercase
+ ; letters. 10 + 26 + 26 = 62. The number characters go from 48
+ ; to 57, the uppercase letters from 65 to 90, and the lowercase
+ ; from 97 to 122. The following makes each equally likely.
+ (let ((temp-value (random 62)))
+ (cond ((< temp-value 10)
+ ; If temp-value<10, then add a number
+ (org-passwords-generate-password-without-symbols
+ (concat previous-string
+ (char-to-string (+ 48 temp-value)))
+ (1- nums-of-chars)))
+ ((and (> temp-value 9) (< temp-value 36))
+ ; If 9<temp-value<36, then add an uppercase letter
+ (org-passwords-generate-password-without-symbols
+ (concat previous-string
+ (char-to-string (+ 65 (- temp-value 10))))
+ (1- nums-of-chars)))
+ ((> temp-value 35)
+ ; If temp-value>35, then add a lowecase letter
+ (org-passwords-generate-password-without-symbols
+ (concat previous-string
+ (char-to-string (+ 97 (- temp-value 36))))
+ (1- nums-of-chars)))))))
+
+;;; Random words
+
+(defun org-passwords-random-words (arg)
+ "Ask for a number of words and inserts a sequence of that many
+random words from the list in the file
+`org-passwords-random-words-dictionary' separated by
+`org-passwords-random-words-separator'. ARG make substitutions in
+the words as defined by
+`org-passwords-random-words-substitutions'."
+ (interactive "P")
+ (if org-passwords-random-words-dictionary
+ (let ((number-of-words
+ (string-to-number
+ (read-from-minibuffer "Number of words: ")))
+ (list-of-words
+ (with-temp-buffer
+ (insert-file-contents
+ org-passwords-random-words-dictionary)
+ (split-string (buffer-string) "\n" t))))
+ (insert
+ (org-passwords-substitute
+ (org-passwords-random-words-attach-number-of-words
+ (nth (random (length list-of-words))
+ list-of-words)
+ (1- number-of-words)
+ list-of-words
+ org-passwords-random-words-separator)
+ (if arg
+ org-passwords-random-words-substitutions
+ nil))))
+ (minibuffer-message
+ "No default dictionary file defined. Set the variable `org-passwords-random-words-dictionary'.")))
+
+(defun org-passwords-random-words-attach-number-of-words
+ (previous-string number-of-words list-of-words separator)
+ "Returns a string consisting of PREVIOUS-STRING followed by a
+succession of NUMBER-OF-WORDS random words from the list LIST-OF-WORDS
+separated SEPARATOR."
+ (if (eq number-of-words 0)
+ previous-string
+ (org-passwords-random-words-attach-number-of-words
+ (concat previous-string
+ separator
+ (nth (random (length list-of-words)) list-of-words))
+ (1- number-of-words)
+ list-of-words
+ separator)))
+
+(defun org-passwords-substitute (string-to-change list-of-substitutions)
+ "Substitutes each appearence in STRING-TO-CHANGE of the `car' of
+each element of LIST-OF-SUBSTITUTIONS by the `cdr' of that
+element. For example:
+ (org-passwords-substitute \"ab\" \'((\"a\" . \"b\") (\"b\" . \"c\")))
+ => \"bc\"
+Substitutions are made in order of the list, so for example:
+ (org-passwords-substitute \"ab\" \'((\"ab\" . \"c\") (\"b\" . \"d\")))
+ => \"c\""
+ (if list-of-substitutions
+ (concat (org-passwords-concat-this-with-string
+ (cdar list-of-substitutions)
+ (mapcar (lambda (x)
+ (org-passwords-substitute
+ x
+ (cdr list-of-substitutions)))
+ (split-string string-to-change
+ (caar list-of-substitutions)))))
+ string-to-change))
+
+(defun org-passwords-concat-this-with-string (this list-of-strings)
+ "Put the string THIS in between every string in LIST-OF-STRINGS. For example:
+ (org-passwords-concat-this-with-string \"Here\" \'(\"First\" \"Second\" \"Third\"))
+ => \"FirstHereSencondHereThird\""
+ (if (cdr list-of-strings)
+ (concat (car list-of-strings)
+ this
+ (org-passwords-concat-this-with-string
+ (cdr list-of-strings)
+ this))
+ (car list-of-strings)))
+
+(provide 'org-passwords)
+
+;;; org-passwords.el ends here
diff --git a/contrib/lisp/org-registry.el b/contrib/lisp/org-registry.el
index 1950797..402ce30 100644
--- a/contrib/lisp/org-registry.el
+++ b/contrib/lisp/org-registry.el
@@ -1,12 +1,12 @@
;;; org-registry.el --- a registry for Org links
;;
-;; Copyright 2007-2013 Bastien Guerry
+;; Copyright 2007-2014 Bastien Guerry
;;
;; Emacs Lisp Archive Entry
;; Filename: org-registry.el
;; Version: 0.1a
-;; Author: Bastien Guerry <bzg AT gnu DOT org>
-;; Maintainer: Bastien Guerry <bzg AT gnu DOT org>
+;; Author: Bastien Guerry <bzg@gnu.org>
+;; Maintainer: Bastien Guerry <bzg@gnu.org>
;; Keywords: org, wp, registry
;; Description: Shows Org files where the current buffer is linked
;; URL: http://www.cognition.ens.fr/~guerry/u/org-registry.el
diff --git a/contrib/lisp/org-screen.el b/contrib/lisp/org-screen.el
index 3334a0f..6b870f2 100644
--- a/contrib/lisp/org-screen.el
+++ b/contrib/lisp/org-screen.el
@@ -1,6 +1,6 @@
;;; org-screen.el --- Integreate Org-mode with screen.
-;; Copyright (c) 2008-2013 Andrew Hyatt
+;; Copyright (c) 2008-2014 Andrew Hyatt
;;
;; Author: Andrew Hyatt <ahyatt at gmail dot com>
;; Maintainer: Carsten Dominik <carsten at orgmode dot org>
diff --git a/contrib/lisp/org-screenshot.el b/contrib/lisp/org-screenshot.el
index a54cb8f..6d10783 100644
--- a/contrib/lisp/org-screenshot.el
+++ b/contrib/lisp/org-screenshot.el
@@ -1,6 +1,6 @@
;;; org-screenshot.el --- Take and manage screenshots in Org-mode files
;;
-;; Copyright (C) 2009-2013
+;; Copyright (C) 2009-2014
;; Free Software Foundation, Inc.
;;
;; Author: Max Mikhanosha <max@openchat.com>
diff --git a/contrib/lisp/org-secretary.el b/contrib/lisp/org-secretary.el
index e98eb34..babfb75 100644
--- a/contrib/lisp/org-secretary.el
+++ b/contrib/lisp/org-secretary.el
@@ -1,5 +1,5 @@
;;; org-secretary.el --- Team management with org-mode
-;; Copyright (C) 2010-2013 Juan Reyero
+;; Copyright (C) 2010-2014 Juan Reyero
;;
;; Author: Juan Reyero <juan _at_ juanreyero _dot_ com>
;; Keywords: outlines, tasks, team, management
diff --git a/contrib/lisp/org-sudoku.el b/contrib/lisp/org-sudoku.el
index 2bf24d8..4b4a3ac 100644
--- a/contrib/lisp/org-sudoku.el
+++ b/contrib/lisp/org-sudoku.el
@@ -1,6 +1,6 @@
;;; org-sudoku.el --- Greate and solve SUDOKU games in Org tables
-;; Copyright (C) 2012, 2013 Free Software Foundation, Inc.
+;; Copyright (C) 2012, 2013, 2014 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp, games
diff --git a/contrib/lisp/org-toc.el b/contrib/lisp/org-toc.el
index e0e6098..255b79e 100644
--- a/contrib/lisp/org-toc.el
+++ b/contrib/lisp/org-toc.el
@@ -1,8 +1,8 @@
;;; org-toc.el --- Table of contents for Org-mode buffer
-;; Copyright 2007-2013 Free Software Foundation, Inc.
+;; Copyright 2007-2014 Free Software Foundation, Inc.
;;
-;; Author: Bastien Guerry <bzg AT gnu DOT org>
+;; Author: Bastien Guerry <bzg@gnu.org>
;; Keywords: Org table of contents
;; Homepage: http://www.cognition.ens.fr/~guerry/u/org-toc.el
;; Version: 0.8
diff --git a/contrib/lisp/org-track.el b/contrib/lisp/org-track.el
index db8c34e..434060b 100644
--- a/contrib/lisp/org-track.el
+++ b/contrib/lisp/org-track.el
@@ -1,9 +1,9 @@
;;; org-track.el --- Track the most recent Org-mode version available.
;;
-;; Copyright (C) 2009-2013
+;; Copyright (C) 2009-2014
;; Free Software Foundation, Inc.
;;
-;; Author: Bastien Guerry <bzg at altern dot org>
+;; Author: Bastien Guerry <bzg@gnu.org>
;; Eric S Fraga <e.fraga at ucl.ac dot uk>
;; Sebastian Rose <sebastian_rose at gmx dot de>
;; The Worg people http://orgmode.org/worg/
diff --git a/contrib/lisp/org-velocity.el b/contrib/lisp/org-velocity.el
index fa41406..3631a59 100644
--- a/contrib/lisp/org-velocity.el
+++ b/contrib/lisp/org-velocity.el
@@ -1,6 +1,6 @@
;;; org-velocity.el --- something like Notational Velocity for Org.
-;; Copyright (C) 2010-2013 Paul M. Rodriguez
+;; Copyright (C) 2010-2014 Paul M. Rodriguez
;; Author: Paul M. Rodriguez <paulmrodriguez@gmail.com>
;; Created: 2010-05-05
diff --git a/contrib/lisp/org-vm.el b/contrib/lisp/org-vm.el
index f60c5bb..5d30f64 100644
--- a/contrib/lisp/org-vm.el
+++ b/contrib/lisp/org-vm.el
@@ -1,6 +1,6 @@
;;; org-vm.el --- Support for links to VM messages from within Org-mode
-;; Copyright (C) 2004-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
diff --git a/contrib/lisp/org-wikinodes.el b/contrib/lisp/org-wikinodes.el
index 4efc373..7f3e2e3 100644
--- a/contrib/lisp/org-wikinodes.el
+++ b/contrib/lisp/org-wikinodes.el
@@ -1,6 +1,6 @@
;;; org-wikinodes.el --- Wiki-like CamelCase links to outline nodes
-;; Copyright (C) 2010-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2014 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
@@ -82,8 +82,6 @@ to `directory'."
;; in heading - deactivate flyspell
(org-remove-flyspell-overlays-in (match-beginning 0)
(match-end 0))
- (add-text-properties (match-beginning 0) (match-end 0)
- '(org-no-flyspell t))
t)
;; this is a wiki link
(org-remove-flyspell-overlays-in (match-beginning 0)
@@ -270,7 +268,6 @@ If there is no such wiki target, return nil."
(car org-export-target-aliases))))
(push (caar target-alist) (cdr a)))))
-(defvar org-current-export-file)
(defun org-wikinodes-process-links-for-export ()
"Process Wiki links in the export preprocess buffer.
@@ -296,12 +293,6 @@ with working links."
((eq org-wikinodes-scope 'file)
;; No match in file, and other files are not allowed
(insert (format "%s" link)))
- ((setq file
- (and (org-string-nw-p org-current-export-file)
- (org-wikinodes-which-file
- link (file-name-directory org-current-export-file))))
- ;; Match in another file in the current directory
- (insert (format "[[file:%s::%s][%s]]" file link link)))
(t ;; No match for this link
(insert (format "%s" link)))))))))
diff --git a/contrib/lisp/org-wl.el b/contrib/lisp/org-wl.el
index 1128ef7..632c9e3 100644
--- a/contrib/lisp/org-wl.el
+++ b/contrib/lisp/org-wl.el
@@ -1,6 +1,6 @@
;;; org-wl.el --- Support for links to Wanderlust messages from within Org-mode
-;; Copyright (C) 2004-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;; Author: Tokuya Kameshima <kames at fa2 dot so-net dot ne dot jp>
;; David Maus <dmaus at ictsoc dot de>
diff --git a/contrib/lisp/orgtbl-sqlinsert.el b/contrib/lisp/orgtbl-sqlinsert.el
index b00c93d..ed8f915 100644
--- a/contrib/lisp/orgtbl-sqlinsert.el
+++ b/contrib/lisp/orgtbl-sqlinsert.el
@@ -1,6 +1,6 @@
;;; orgtbl-sqlinsert.el --- orgtbl to SQL insert statements.
-;; Copyright (C) 2008-2013 Free Software Foundation
+;; Copyright (C) 2008-2014 Free Software Foundation
;; Author: Jason Riedy <jason@acm.org>
;; Keywords: org, tables, sql
diff --git a/contrib/lisp/ox-bibtex.el b/contrib/lisp/ox-bibtex.el
index 29a97eb..7cb8972 100644
--- a/contrib/lisp/ox-bibtex.el
+++ b/contrib/lisp/ox-bibtex.el
@@ -1,6 +1,6 @@
;;; ox-bibtex.el --- Export bibtex fragments
-;; Copyright (C) 2009-2013 Taru Karttunen
+;; Copyright (C) 2009-2014 Taru Karttunen
;; Author: Taru Karttunen <taruti@taruti.net>
;; Nicolas Goaziou <n dot goaziou at gmail dot com>
@@ -23,21 +23,31 @@
;;; Commentary:
;;
-;; This is an utility to handle BibTeX export to both LaTeX and html
-;; exports. It uses the bibtex2html software from:
+;; This is an utility to handle BibTeX export to LaTeX, html and ascii
+;; exports. For HTML and ascii it uses the bibtex2html software from:
;;
;; http://www.lri.fr/~filliatr/bibtex2html/
;;
+;; For ascii it uses the pandoc software from:
+;;
+;; http://johnmacfarlane.net/pandoc/
+;;
;; It also introduces "cite" syntax for Org links.
;;
;; The usage is as follows:
;;
-;; #+BIBLIOGRAPHY: bibfilebasename stylename optional-options
+;; #+BIBLIOGRAPHY: bibfilename stylename optional-options
;;
;; e.g. given foo.bib and using style plain:
;;
;; #+BIBLIOGRAPHY: foo plain option:-d
;;
+;; "stylename" can also be "nil", in which case no style will be used.
+;;
+;; Full filepaths are also possible:
+;;
+;; #+BIBLIOGRAPHY: /home/user/Literature/foo.bib plain option:-d
+;;
;; Optional options are of the form:
;;
;; option:-foobar pass '-foobar' to bibtex2html
@@ -71,14 +81,18 @@
;; 2) creates a foo.html and foo_bib.html,
;; 3) includes the contents of foo.html in the exported HTML file.
;;
+;; For ascii export it:
+;; 1) converts all \cite{foo} and [[cite:foo]] to links to the
+;; bibliography,
+;; 2) creates a foo.txt and foo_bib.html,
+;; 3) includes the contents of foo.txt in the exported ascii file.
+;;
;; For LaTeX export it:
;; 1) converts all [[cite:foo]] to \cite{foo}.
;; Initialization
(eval-when-compile (require 'cl))
-(org-add-link-type "cite" 'ebib)
-
;;; Internal Functions
@@ -103,9 +117,9 @@ return nil instead."
(defun org-bibtex-get-arguments (keyword)
"Return \"bibtex2html\" arguments specified by the user.
KEYWORD is a \"BIBLIOGRAPHY\" keyword. Return value is a plist
-containing `:options' and `:limit' properties. The former
-contains a list of strings to be passed as options ot
-\"bibtex2html\" process. The latter contains a boolean."
+containing `:options' and `:limit' properties. The former
+contains a list of strings to be passed as options to
+\"bibtex2html\" process. The latter contains a boolean."
(let ((value (org-element-property :value keyword)))
(and value
(string-match "\\(\\S-+\\)[ \t]+\\(\\S-+\\)\\(.*\\)" value)
@@ -137,6 +151,196 @@ to `org-bibtex-citation-p' predicate."
(and (string-match "\\`\\\\cite{" value)
(substring value (match-end 0) -1)))))
+
+;;; Follow cite: links
+
+(defun org-bibtex-file nil "Org-mode file of bibtex entries.")
+
+(defun org-bibtex-goto-citation (&optional citation)
+ "Visit a citation given its ID."
+ (interactive)
+ (let ((citation (or citation
+ (org-icompleting-read "Citation: "
+ (obe-citations)))))
+ (find-file (or org-bibtex-file
+ (error "`org-bibtex-file' has not been configured")))
+ (goto-char (point-min))
+ (when (re-search-forward (format " :CUSTOM_ID: %s" citation) nil t)
+ (outline-previous-visible-heading 1)
+ t)))
+
+(let ((jump-fn (car (org-remove-if-not #'fboundp '(ebib org-bibtex-goto-citation)))))
+ (org-add-link-type "cite" jump-fn))
+
+
+
+;;; Filters
+
+(defun org-bibtex-process-bib-files (tree backend info)
+ "Send each bibliography in parse tree to \"bibtex2html\" process.
+Return new parse tree."
+ (when (org-export-derived-backend-p backend 'ascii 'html)
+ ;; Initialize dynamically scoped variables. The first one
+ ;; contain an alist between keyword objects and their HTML
+ ;; translation. The second one will contain an alist between
+ ;; citation keys and names in the output (according to style).
+ (setq org-bibtex-html-entries-alist nil
+ org-bibtex-html-keywords-alist nil)
+ (org-element-map tree 'keyword
+ (lambda (keyword)
+ (when (equal (org-element-property :key keyword) "BIBLIOGRAPHY")
+ (let ((arguments (org-bibtex-get-arguments keyword))
+ (file (org-bibtex-get-file keyword))
+ temp-file
+ out-file)
+ ;; Test if filename is given with .bib-extension and strip
+ ;; it off. Filenames with another extensions will be
+ ;; untouched and will finally rise an error in bibtex2html.
+ (setq file (if (equal (file-name-extension file) "bib")
+ (file-name-sans-extension file) file))
+ ;; Outpufiles of bibtex2html will be put into current working directory
+ ;; so define a variable for this.
+ (setq out-file (file-name-base file))
+ ;; limit is set: collect citations throughout the document
+ ;; in TEMP-FILE and pass it to "bibtex2html" as "-citefile"
+ ;; argument.
+ (when (plist-get arguments :limit)
+ (let ((citations
+ (org-element-map tree '(latex-fragment link)
+ (lambda (object)
+ (and (org-bibtex-citation-p object)
+ (org-bibtex-get-citation-key object))))))
+ (with-temp-file (setq temp-file (make-temp-file "ox-bibtex"))
+ (insert (mapconcat 'identity citations "\n")))
+ (setq arguments
+ (plist-put arguments
+ :options
+ (append (plist-get arguments :options)
+ (list "-citefile" temp-file))))))
+ ;; Call "bibtex2html" on specified file.
+ (unless (eq 0 (apply
+ 'call-process
+ (append '("bibtex2html" nil nil nil)
+ '("-a" "-nodoc" "-noheader" "-nofooter")
+ (let ((style
+ (org-not-nil
+ (org-bibtex-get-style keyword))))
+ (and style (list "--style" style)))
+ (plist-get arguments :options)
+ (list (concat file ".bib")))))
+ (error "Executing bibtex2html failed"))
+ (and temp-file (delete-file temp-file))
+ ;; Open produced HTML file, and collect Bibtex key names
+ (with-temp-buffer
+ (insert-file-contents (concat out-file ".html"))
+ ;; Update `org-bibtex-html-entries-alist'.
+ (goto-char (point-min))
+ (while (re-search-forward
+ "a name=\"\\([-_a-zA-Z0-9:]+\\)\">\\(\\w+\\)" nil t)
+ (push (cons (match-string 1) (match-string 2))
+ org-bibtex-html-entries-alist)))
+ ;; Open produced HTML file, wrap references within a block and
+ ;; return it.
+ (with-temp-buffer
+ (cond
+ ((org-export-derived-backend-p backend 'html)
+ (insert (format "<div id=\"bibliography\">\n<h2>%s</h2>\n"
+ (org-export-translate "References" :html info)))
+ (insert-file-contents (concat out-file ".html"))
+ (insert "\n</div>"))
+ ((org-export-derived-backend-p backend 'ascii)
+ ;; convert HTML references to text w/pandoc
+ (unless (eq 0 (call-process "pandoc" nil nil nil
+ (concat out-file ".html")
+ "-o"
+ (concat out-file ".txt")))
+ (error "Executing pandoc failed"))
+ (insert
+ (format
+ "%s\n==========\n\n"
+ (org-export-translate
+ "References"
+ (intern (format ":%s" (plist-get info :ascii-charset)))
+ info)))
+ (insert-file-contents (concat out-file ".txt"))
+ (goto-char (point-min))
+ (while (re-search-forward
+ "\\[ \\[bib\\][^ ]+ \\(\\]\\||[\n\r]\\)" nil t)
+ (replace-match ""))
+ (goto-char (point-min))
+ (while (re-search-forward "\\( \\]\\| \\]\\| |\\)" nil t)
+ (replace-match ""))
+ (goto-char (point-min))
+ (while (re-search-forward "[\n\r]\\([\n\r][\n\r]\\)" nil t)
+ (replace-match "\\1"))))
+ ;; Update `org-bibtex-html-keywords-alist'.
+ (push (cons keyword (buffer-string))
+ org-bibtex-html-keywords-alist)))))))
+ ;; Return parse tree unchanged.
+ tree)
+
+(defun org-bibtex-merge-contiguous-citations (tree backend info)
+ "Merge all contiguous citation in parse tree.
+As a side effect, this filter will also turn all \"cite\" links
+into \"\\cite{...}\" LaTeX fragments and will extract options.
+Cite options are placed into square brackets at the beginning of
+the \"\\cite\" command for the LaTeX backend, and are removed for
+the HTML and ASCII backends."
+ (when (org-export-derived-backend-p backend 'html 'latex 'ascii)
+ (org-element-map tree '(link latex-fragment)
+ (lambda (object)
+ (when (org-bibtex-citation-p object)
+ (let ((new-citation (list 'latex-fragment
+ (list :value ""
+ :post-blank (org-element-property
+ :post-blank object))))
+ option)
+ ;; Insert NEW-CITATION right before OBJECT.
+ (org-element-insert-before new-citation object)
+ ;; Remove all subsequent contiguous citations from parse
+ ;; tree, keeping only their citation key.
+ (let ((keys (list (org-bibtex-get-citation-key object)))
+ next)
+ (while (and (setq next (org-export-get-next-element object info))
+ (or (and (stringp next)
+ (not (org-string-match-p "\\S-" next)))
+ (org-bibtex-citation-p next)))
+ (unless (stringp next)
+ (push (org-bibtex-get-citation-key next) keys))
+ (org-element-extract-element object)
+ (setq object next))
+ ;; Find any options in keys, e.g., "(Chapter 2)key" has
+ ;; the option "Chapter 2".
+ (setq keys
+ (mapcar
+ (lambda (k)
+ (if (string-match "^(\\([^)]\+\\))\\(.*\\)" k)
+ (progn
+ (when (org-export-derived-backend-p backend 'latex)
+ (setq option (format "[%s]" (match-string 1 k))))
+ (match-string 2 k))
+ k))
+ keys))
+ (org-element-extract-element object)
+ ;; Eventually merge all keys within NEW-CITATION. Also
+ ;; ensure NEW-CITATION has the same :post-blank property
+ ;; as the last citation removed.
+ (org-element-put-property
+ new-citation
+ :post-blank (org-element-property :post-blank object))
+ (org-element-put-property
+ new-citation
+ :value (format "\\cite%s{%s}"
+ (or option "")
+ (mapconcat 'identity (nreverse keys) ",")))))))))
+ tree)
+
+(eval-after-load 'ox
+ '(progn (add-to-list 'org-export-filter-parse-tree-functions
+ 'org-bibtex-process-bib-files)
+ (add-to-list 'org-export-filter-parse-tree-functions
+ 'org-bibtex-merge-contiguous-citations)))
+
;;; LaTeX Part
@@ -148,22 +352,13 @@ Fallback to `latex' back-end for other keywords."
(if (not (equal (org-element-property :key keyword) "BIBLIOGRAPHY"))
ad-do-it
(let ((file (org-bibtex-get-file keyword))
- (style (org-bibtex-get-style keyword)))
+ (style (org-not-nil (org-bibtex-get-style keyword))))
(setq ad-return-value
(when file
(concat (and style (format "\\bibliographystyle{%s}\n" style))
(format "\\bibliography{%s}" file))))))))
-(defadvice org-latex-link (around bibtex-link)
- "Translate \"cite\" type links into LaTeX syntax.
-Fallback to `latex' back-end for other keywords."
- (let ((link (ad-get-arg 0)))
- (if (not (org-bibtex-citation-p link)) ad-do-it
- (setq ad-return-value
- (format "\\cite{%s}" (org-bibtex-get-citation-key link))))))
-
(ad-activate 'org-latex-keyword)
-(ad-activate 'org-latex-link)
@@ -190,103 +385,46 @@ Fallback to `html' back-end for other keywords."
(let ((fragment (ad-get-arg 0)))
(if (not (org-bibtex-citation-p fragment)) ad-do-it
(setq ad-return-value
- (mapconcat
- (lambda (key)
- (let ((key (org-trim key)))
- (format "[<a href=\"#%s\">%s</a>]"
- key
- (or (cdr (assoc key org-bibtex-html-entries-alist))
- key))))
- (org-split-string (org-bibtex-get-citation-key fragment) ",")
- "")))))
-
-(defadvice org-html-link (around bibtex-link)
- "Translate \"cite:\" type links into HTML syntax.
-Fallback to `html' back-end for other types."
- (let ((link (ad-get-arg 0)))
- (if (not (org-bibtex-citation-p link)) ad-do-it
- (setq ad-return-value
- (mapconcat
- (lambda (key)
- (format "[<a href=\"#%s\">%s</a>]"
- key
- (or (cdr (assoc key org-bibtex-html-entries-alist))
- key)))
- (org-split-string (org-bibtex-get-citation-key link)
- "[ \t]*,[ \t]*")
- "")))))
+ (format "[%s]"
+ (mapconcat
+ (lambda (key)
+ (format "<a href=\"#%s\">%s</a>"
+ key
+ (or (cdr (assoc key org-bibtex-html-entries-alist))
+ key)))
+ (org-split-string
+ (org-bibtex-get-citation-key fragment) ",") ","))))))
(ad-activate 'org-html-keyword)
(ad-activate 'org-html-latex-fragment)
-(ad-activate 'org-html-link)
-
-
-;;;; Filter
-
-(defun org-bibtex-process-bib-files (tree backend info)
- "Send each bibliography in parse tree to \"bibtex2html\" process.
-Return new parse tree. This function assumes current back-end is HTML."
- ;; Initialize dynamically scoped variables. The first one
- ;; contain an alist between keyword objects and their HTML
- ;; translation. The second one will contain an alist between
- ;; citation keys and names in the output (according to style).
- (setq org-bibtex-html-entries-alist nil
- org-bibtex-html-keywords-alist nil)
- (org-element-map tree 'keyword
- (lambda (keyword)
- (when (equal (org-element-property :key keyword) "BIBLIOGRAPHY")
- (let ((arguments (org-bibtex-get-arguments keyword))
- (file (org-bibtex-get-file keyword))
- temp-file)
- ;; limit is set: collect citations throughout the document
- ;; in TEMP-FILE and pass it to "bibtex2html" as "-citefile"
- ;; argument.
- (when (plist-get arguments :limit)
- (let ((citations
- (org-element-map tree '(latex-fragment link)
- (lambda (object)
- (and (org-bibtex-citation-p object)
- (org-bibtex-get-citation-key object))))))
- (with-temp-file (setq temp-file (make-temp-file "ox-bibtex"))
- (insert (mapconcat 'identity citations "\n")))
- (setq arguments
- (plist-put arguments
- :options
- (append (plist-get arguments :options)
- (list "-citefile" temp-file))))))
- ;; Call "bibtex2html" on specified file.
- (unless (eq 0 (apply 'call-process
- (append '("bibtex2html" nil nil nil)
- '("-a" "-nodoc" "-noheader" "-nofooter")
- (list "--style"
- (org-bibtex-get-style keyword))
- (plist-get arguments :options)
- (list (concat file ".bib")))))
- (error "Executing bibtex2html failed"))
- (and temp-file (delete-file temp-file))
- ;; Open produced HTML file, wrap references within a block and
- ;; return it.
- (with-temp-buffer
- (insert "<div id=\"bibliography\">\n<h2>References</h2>\n")
- (insert-file-contents (concat file ".html"))
- (insert "\n</div>")
- ;; Update `org-bibtex-html-keywords-alist'.
- (push (cons keyword (buffer-string))
- org-bibtex-html-keywords-alist)
- ;; Update `org-bibtex-html-entries-alist'.
- (goto-char (point-min))
- (while (re-search-forward
- "a name=\"\\([-_a-zA-Z0-9:]+\\)\">\\(\\w+\\)" nil t)
- (push (cons (match-string 1) (match-string 2))
- org-bibtex-html-entries-alist)))))))
- ;; Return parse tree unchanged.
- tree)
-(eval-after-load 'ox
- '(add-to-list 'org-export-filter-parse-tree-functions
- 'org-bibtex-process-bib-files))
+
+;;; Ascii Part
+(defadvice org-ascii-keyword (around bibtex-keyword)
+ "Translate \"BIBLIOGRAPHY\" keywords into ascii syntax.
+Fallback to `ascii' back-end for other keywords."
+ (let ((keyword (ad-get-arg 0)))
+ (if (not (equal (org-element-property :key keyword) "BIBLIOGRAPHY"))
+ ad-do-it
+ (setq ad-return-value
+ (cdr (assq keyword org-bibtex-html-keywords-alist))))))
+(defadvice org-ascii-latex-fragment (around bibtex-citation)
+ "Translate \"\\cite\" LaTeX fragments into ascii syntax.
+Fallback to `ascii' back-end for other keywords."
+ (let ((fragment (ad-get-arg 0)))
+ (if (not (org-bibtex-citation-p fragment)) ad-do-it
+ (setq ad-return-value
+ (format "[%s]"
+ (mapconcat
+ (lambda (key)
+ (or (cdr (assoc key org-bibtex-html-entries-alist))
+ key))
+ (org-split-string
+ (org-bibtex-get-citation-key fragment) ",") ","))))))
+(ad-activate 'org-ascii-keyword)
+(ad-activate 'org-ascii-latex-fragment)
(provide 'ox-bibtex)
diff --git a/contrib/lisp/ox-confluence.el b/contrib/lisp/ox-confluence.el
index 150d36c..9b96d5f 100644
--- a/contrib/lisp/ox-confluence.el
+++ b/contrib/lisp/ox-confluence.el
@@ -1,8 +1,8 @@
;;; ox-confluence --- Confluence Wiki Back-End for Org Export Engine
-;; Copyright (C) 2012 Sébastien Delafond
+;; Copyright (C) 2012, 2014 Sébastien Delafond
-;; Author: Sébastien Delafond <sdelafond at gmx dot net>
+;; Author: Sébastien Delafond <sdelafond@gmail.com>
;; Keywords: outlines, confluence, wiki
;; This file is not part of GNU Emacs.
@@ -45,7 +45,9 @@
(footnote-reference . org-confluence-empty)
(headline . org-confluence-headline)
(italic . org-confluence-italic)
+ (item . org-confluence-item)
(link . org-confluence-link)
+ (property-drawer . org-confluence-property-drawer)
(section . org-confluence-section)
(src-block . org-confluence-src-block)
(strike-through . org-confluence-strike-through)
@@ -70,6 +72,11 @@
(defun org-confluence-italic (italic contents info)
(format "_%s_" contents))
+(defun org-confluence-item (item contents info)
+ (concat (make-string (1+ (org-confluence--li-depth item)) ?\-)
+ " "
+ (org-trim contents)))
+
(defun org-confluence-fixed-width (fixed-width contents info)
(format "\{\{%s\}\}" contents))
@@ -93,6 +100,11 @@
(t
raw-link))
"]")))
+
+(defun org-confluence-property-drawer (property-drawer contents info)
+ (and (org-string-nw-p contents)
+ (format "\{\{%s\}\}" contents)))
+
(defun org-confluence-section (section contents info)
contents)
@@ -138,6 +150,22 @@
contents
"\{code\}\n"))
+(defun org-confluence--li-depth (item)
+ "Return depth of a list item; -1 means not a list item"
+ ;; FIXME check whether it's worth it to cache depth
+ ;; (it gets recalculated quite a few times while
+ ;; traversing a list)
+ (let ((depth -1)
+ (tag))
+ (while (and item
+ (setq tag (car item))
+ (or (eq tag 'item) ; list items interleave with plain-list
+ (eq tag 'plain-list)))
+ (when (eq tag 'item)
+ (incf depth))
+ (setq item (org-export-get-parent item)))
+ depth))
+
;; main interactive entrypoint
(defun org-confluence-export-as-confluence
(&optional async subtreep visible-only body-only ext-plist)
diff --git a/contrib/lisp/ox-deck.el b/contrib/lisp/ox-deck.el
index 847f7af..0ebde41 100644
--- a/contrib/lisp/ox-deck.el
+++ b/contrib/lisp/ox-deck.el
@@ -1,6 +1,6 @@
;;; ox-deck.el --- deck.js Presentation Back-End for Org Export Engine
-;; Copyright (C) 2013 Rick Frankel
+;; Copyright (C) 2013, 2014 Rick Frankel
;; Author: Rick Frankel <emacs at rickster dot com>
;; Keywords: outlines, hypermedia, slideshow
@@ -55,7 +55,7 @@
(:html-link-up "HTML_LINK_UP" nil nil)
(:deck-postamble "DECK_POSTAMBLE" nil org-deck-postamble newline)
(:deck-preamble "DECK_PREAMBLE" nil org-deck-preamble newline)
- (:html-head-include-default-style "HTML_INCLUDE_DEFAULT_STYLE" nil nil)
+ (:html-head-include-default-style "HTML_INCLUDE_DEFAULT_STYLE" "html-style" nil)
(:html-head-include-scripts "HTML_INCLUDE_SCRIPTS" nil nil)
(:deck-base-url "DECK_BASE_URL" nil org-deck-base-url)
(:deck-theme "DECK_THEME" nil org-deck-theme)
@@ -319,7 +319,7 @@ and have the id \"title-slide\"."
(include (plist-get info :deck-include-extensions))
(exclude (plist-get info :deck-exclude-extensions))
(scripts '()) (sheets '()) (snippets '()))
- (add-to-list 'scripts (concat prefix "jquery-1.7.2.min.js"))
+ (add-to-list 'scripts (concat prefix "jquery.min.js"))
(add-to-list 'scripts (concat prefix "core/deck.core.js"))
(add-to-list 'scripts (concat prefix "modernizr.custom.js"))
(add-to-list 'sheets (concat prefix "core/deck.core.css"))
@@ -368,7 +368,7 @@ holding export options."
"Transcode an ITEM element from Org to HTML.
CONTENTS holds the contents of the item. INFO is a plist holding
contextual information.
-If the containing headline has the property :slide, then
+If the containing headline has the property :STEP, then
the \"slide\" class will be added to the to the list element,
which will make the list into a \"build\"."
(let ((text (org-html-item item contents info)))
@@ -378,7 +378,7 @@ the \"slide\" class will be added to the to the list element,
(defun org-deck-link (link desc info)
(replace-regexp-in-string "href=\"#" "href=\"#outline-container-"
- (org-html-link link desc info)))
+ (org-export-with-backend 'html link desc info)))
(defun org-deck-template (contents info)
"Return complete document string after HTML conversion.
diff --git a/contrib/lisp/ox-extra.el b/contrib/lisp/ox-extra.el
new file mode 100644
index 0000000..e6d45cc
--- a/dev/null
+++ b/contrib/lisp/ox-extra.el
@@ -0,0 +1,190 @@
+;;; ox-extra.el --- Convenience functions for org export
+
+;; Copyright (C) 2014 Aaron Ecay
+
+;; Author: Aaron Ecay <aaronecay@gmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file contains some convenience functions for org export, which
+;; are not part of org's core. Call `ox-extras-activate' passing a
+;; list of symbols naming extras, which will be installed globally in
+;; your org session.
+;;
+;; For example, you could include the following in your .emacs file:
+;;
+;; (require 'ox-extra)
+;; (ox-extras-activate '(latex-header-blocks ignore-headlines))
+;;
+
+;; Currently available extras:
+
+;; - `latex-header-blocks' -- allow the use of latex blocks, the
+;; contents of which which will be interpreted as #+latex_header lines
+;; for export. These blocks should be tagged with #+header: :header
+;; yes. For example:
+;; #+header: :header yes
+;; #+begin_latex
+;; ...
+;; #+end_latex
+
+;; - `ignore-headlines' -- allow a headline (but not its children) to
+;; be ignored. Any headline tagged with the 'ignore' tag will be
+;; ignored (i.e. will not be included in the export), but any child
+;; headlines will not be ignored (unless explicitly tagged to be
+;; ignored), and will instead have their levels promoted by one.
+
+;; TODO:
+;; - add a function to org-mode-hook that looks for a ox-extras local
+;; variable and activates the specified extras buffer-locally
+;; - allow specification of desired extras to be activated via
+;; customize
+
+;;; Code:
+
+(require 'ox)
+(eval-when-compile (require 'cl))
+
+(defun org-latex-header-blocks-filter (backend)
+ (when (org-export-derived-backend-p backend 'latex)
+ (let ((positions
+ (org-element-map (org-element-parse-buffer 'greater-element nil) 'export-block
+ (lambda (block)
+ (when (and (string= (org-element-property :type block) "LATEX")
+ (string= (org-export-read-attribute
+ :header block :header)
+ "yes"))
+ (list (org-element-property :begin block)
+ (org-element-property :end block)
+ (org-element-property :post-affiliated block)))))))
+ (mapc (lambda (pos)
+ (goto-char (nth 2 pos))
+ (destructuring-bind
+ (beg end &rest ignore)
+ (org-edit-src-find-region-and-lang)
+ (let ((contents-lines (split-string
+ (buffer-substring-no-properties beg end)
+ "\n")))
+ (delete-region (nth 0 pos) (nth 1 pos))
+ (dolist (line contents-lines)
+ (insert (concat "#+latex_header: "
+ (replace-regexp-in-string "\\` *" "" line)
+ "\n"))))))
+ ;; go in reverse, to avoid wrecking the numeric positions
+ ;; earlier in the file
+ (reverse positions)))))
+
+
+;; During export headlines which have the "ignore" tag are removed
+;; from the parse tree. Their contents are retained (leading to a
+;; possibly invalid parse tree, which nevertheless appears to function
+;; correctly with most export backends) all children headlines are
+;; retained and are promoted to the level of the ignored parent
+;; headline.
+;;
+;; This makes it possible to add structure to the original Org-mode
+;; document which does not effect the exported version, such as in the
+;; following examples.
+;;
+;; Wrapping an abstract in a headline
+;;
+;; * Abstract :ignore:
+;; #+LaTeX: \begin{abstract}
+;; #+HTML: <div id="abstract">
+;;
+;; ...
+;;
+;; #+HTML: </div>
+;; #+LaTeX: \end{abstract}
+;;
+;; Placing References under a headline (using ox-bibtex in contrib)
+;;
+;; * References :ignore:
+;; #+BIBLIOGRAPHY: dissertation plain
+;;
+;; Inserting an appendix for LaTeX using the appendix package.
+;;
+;; * Appendix :ignore:
+;; #+LaTeX: \begin{appendices}
+;; ** Reproduction
+;; ...
+;; ** Definitions
+;; #+LaTeX: \end{appendices}
+;;
+(defun org-export-ignore-headlines (data backend info)
+ "Remove headlines tagged \"ignore\" retaining contents and promoting children.
+Each headline tagged \"ignore\" will be removed retaining its
+contents and promoting any children headlines to the level of the
+parent."
+ (org-element-map data 'headline
+ (lambda (object)
+ (when (member "ignore" (org-element-property :tags object))
+ (let ((level-top (org-element-property :level object))
+ level-diff)
+ (mapc (lambda (el)
+ ;; recursively promote all nested headlines
+ (org-element-map el 'headline
+ (lambda (el)
+ (when (equal 'headline (org-element-type el))
+ (unless level-diff
+ (setq level-diff (- (org-element-property :level el)
+ level-top)))
+ (org-element-put-property el
+ :level (- (org-element-property :level el)
+ level-diff)))))
+ ;; insert back into parse tree
+ (org-element-insert-before el object))
+ (org-element-contents object)))
+ (org-element-extract-element object)))
+ info nil)
+ data)
+
+(defconst ox-extras
+ '((latex-header-blocks org-latex-header-blocks-filter org-export-before-parsing-hook)
+ (ignore-headlines org-export-ignore-headlines org-export-filter-parse-tree-functions))
+ "A list of org export extras that can be enabled.
+
+Should be a list of items of the form (NAME FN HOOK). NAME is a
+symbol, which can be passed to `ox-extras-activate'. FN is a
+function which will be added to HOOK.")
+
+(defun ox-extras-activate (extras)
+ "Activate certain org export extras.
+
+EXTRAS should be a list of extras (defined in `ox-extras') which
+should be activated."
+ (dolist (extra extras)
+ (let* ((lst (assq extra ox-extras))
+ (fn (nth 1 lst))
+ (hook (nth 2 lst)))
+ (when (and fn hook)
+ (add-hook hook fn)))))
+
+(defun ox-extras-deactivate (extras)
+ "Deactivate certain org export extras.
+
+This function is the opposite of `ox-extras-activate'. EXTRAS
+should be a list of extras (defined in `ox-extras') which should
+be activated."
+ (dolist (extra extras)
+ (let* ((lst (assq extra ox-extras))
+ (fn (nth 1 lst))
+ (hook (nth 2 lst)))
+ (when (and fn hook)
+ (remove-hook hook fn)))))
+
+(provide 'ox-extra)
+;;; ox-extra.el ends here
diff --git a/contrib/lisp/ox-freemind.el b/contrib/lisp/ox-freemind.el
index aafd714..39fb1cc 100644
--- a/contrib/lisp/ox-freemind.el
+++ b/contrib/lisp/ox-freemind.el
@@ -1,6 +1,6 @@
;;; ox-freemind.el --- Freemind Mindmap Back-End for Org Export Engine
-;; Copyright (C) 2013 Free Software Foundation, Inc.
+;; Copyright (C) 2013, 2014 Free Software Foundation, Inc.
;; Author: Jambunathan K <kjambunathan at gmail dot com>
;; Keywords: outlines, hypermedia, calendar, wp
@@ -520,7 +520,7 @@ Return output file's name."
(let* ((extension (concat ".mm" ))
(file (org-export-output-file-name extension subtreep))
(org-export-coding-system 'utf-8))
- (org-export-to-file 'freemind ,file
+ (org-export-to-file 'freemind file
async subtreep visible-only body-only ext-plist)))
(provide 'ox-freemind)
diff --git a/contrib/lisp/ox-gfm.el b/contrib/lisp/ox-gfm.el
new file mode 100644
index 0000000..f7acc94
--- a/dev/null
+++ b/contrib/lisp/ox-gfm.el
@@ -0,0 +1,193 @@
+;;; ox-gfm.el --- Github Flavored Markdown Back-End for Org Export Engine
+
+;; Copyright (C) 2014 Lars Tveito
+
+;; Author: Lars Tveito
+;; Keywords: org, wp, markdown, github
+
+;; This file is not part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library implements a Markdown back-end (github flavor) for Org
+;; exporter, based on the `md' back-end.
+
+;;; Code:
+
+(require 'ox-md)
+
+
+
+;;; User-Configurable Variables
+
+(defgroup org-export-gfm nil
+ "Options specific to Markdown export back-end."
+ :tag "Org Github Flavored Markdown"
+ :group 'org-export
+ :version "24.4"
+ :package-version '(Org . "8.0"))
+
+(defcustom org-gfm-lang '(("emacs-lisp" . "lisp") ("elisp" . "lisp"))
+ "Alist of languages that are not recognized by Github, to
+ languages that are. Emacs lisp is a good example of this, where
+ we can use lisp as a nice replacement."
+ :group 'org-export-gfm)
+
+
+
+;;; Define Back-End
+
+(org-export-define-derived-backend 'gfm 'md
+ :export-block '("GFM" "GITHUB FLAVORED MARKDOWN")
+ :filters-alist '((:filter-parse-tree . org-md-separate-elements))
+ :menu-entry
+ '(?g "Export to Github Flavored Markdown"
+ ((?G "To temporary buffer"
+ (lambda (a s v b) (org-gfm-export-as-markdown a s v)))
+ (?g "To file" (lambda (a s v b) (org-gfm-export-to-markdown a s v)))
+ (?o "To file and open"
+ (lambda (a s v b)
+ (if a (org-gfm-export-to-markdown t s v)
+ (org-open-file (org-gfm-export-to-markdown nil s v)))))))
+ :translate-alist '((inner-template . org-gfm-inner-template)
+ (strike-through . org-gfm-strike-through)
+ (src-block . org-gfm-src-block)))
+
+
+
+;;; Transcode Functions
+
+;;;; Src Block
+
+(defun org-gfm-src-block (src-block contents info)
+ "Transcode SRC-BLOCK element into Github Flavored Markdown
+format. CONTENTS is nil. INFO is a plist used as a communication
+channel."
+ (let* ((lang (org-element-property :language src-block))
+ (lang (or (assoc-default lang org-gfm-lang) lang))
+ (code (org-export-format-code-default src-block info))
+ (prefix (concat "```" lang "\n"))
+ (suffix "```"))
+ (concat prefix code suffix)))
+
+
+;;;; Strike-Through
+
+(defun org-html-strike-through (strike-through contents info)
+ "Transcode STRIKE-THROUGH from Org to Markdown (GFM).
+CONTENTS is the text with strike-through markup. INFO is a plist
+holding contextual information."
+ (format "~~%s~~" contents))
+
+;;;; Table of contents
+
+(defun org-gfm-format-toc (headline)
+ "Return an appropriate table of contents entry for HEADLINE. INFO is a
+plist used as a communication channel."
+ (let* ((title (org-export-data
+ (org-export-get-alt-title headline info) info))
+ (level (1- (org-element-property :level headline)))
+ (indent (concat (make-string (* level 2) ? )))
+ (ref-str (replace-regexp-in-string " " "-" (downcase title))))
+ (concat indent "- [" title "]" "(#" ref-str ")")))
+
+
+;;;; Template
+
+(defun org-gfm-inner-template (contents info)
+ "Return body of document after converting it to Markdown syntax.
+CONTENTS is the transcoded contents string. INFO is a plist
+holding export options."
+ (let* ((depth (plist-get info :with-toc))
+ (headlines (and depth (org-export-collect-headlines info depth)))
+ (toc-string (or (mapconcat 'org-gfm-format-toc headlines "\n") ""))
+ (toc-tail (if headlines "\n\n" "")))
+ (concat toc-string toc-tail contents)))
+
+
+
+;;; Interactive function
+
+;;;###autoload
+(defun org-gfm-export-as-markdown (&optional async subtreep visible-only)
+ "Export current buffer to a Github Flavored Markdown buffer.
+
+If narrowing is active in the current buffer, only export its
+narrowed part.
+
+If a region is active, export that region.
+
+A non-nil optional argument ASYNC means the process should happen
+asynchronously. The resulting buffer should be accessible
+through the `org-export-stack' interface.
+
+When optional argument SUBTREEP is non-nil, export the sub-tree
+at point, extracting information from the headline properties
+first.
+
+When optional argument VISIBLE-ONLY is non-nil, don't export
+contents of hidden elements.
+
+Export is done in a buffer named \"*Org GFM Export*\", which will
+be displayed when `org-export-show-temporary-export-buffer' is
+non-nil."
+ (interactive)
+ (org-export-to-buffer 'gfm "*Org GFM Export*"
+ async subtreep visible-only nil nil (lambda () (text-mode))))
+
+
+;;;###autoload
+(defun org-gfm-convert-region-to-md ()
+ "Assume the current region has org-mode syntax, and convert it
+to Github Flavored Markdown. This can be used in any buffer.
+For example, you can write an itemized list in org-mode syntax in
+a Markdown buffer and use this command to convert it."
+ (interactive)
+ (org-export-replace-region-by 'gfm))
+
+
+;;;###autoload
+(defun org-gfm-export-to-markdown (&optional async subtreep visible-only)
+ "Export current buffer to a Github Flavored Markdown file.
+
+If narrowing is active in the current buffer, only export its
+narrowed part.
+
+If a region is active, export that region.
+
+A non-nil optional argument ASYNC means the process should happen
+asynchronously. The resulting file should be accessible through
+the `org-export-stack' interface.
+
+When optional argument SUBTREEP is non-nil, export the sub-tree
+at point, extracting information from the headline properties
+first.
+
+When optional argument VISIBLE-ONLY is non-nil, don't export
+contents of hidden elements.
+
+Return output file's name."
+ (interactive)
+ (let ((outfile (org-export-output-file-name ".md" subtreep)))
+ (org-export-to-file 'gfm outfile async subtreep visible-only)))
+
+(provide 'ox-gfm)
+
+;; Local variables:
+;; generated-autoload-file: "org-loaddefs.el"
+;; End:
+
+;;; ox-gfm.el ends here
diff --git a/contrib/lisp/ox-groff.el b/contrib/lisp/ox-groff.el
index 9a4fed1..7fbd16b 100644
--- a/contrib/lisp/ox-groff.el
+++ b/contrib/lisp/ox-groff.el
@@ -1,6 +1,6 @@
;;; ox-groff.el --- Groff Back-End for Org Export Engine
-;; Copyright (C) 2011-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
;; Author: Luis R Anaya <papoanaya aroba hot mail punto com>
@@ -70,13 +70,13 @@
(keyword . org-groff-keyword)
(line-break . org-groff-line-break)
(link . org-groff-link)
+ (node-property . org-groff-node-property)
(paragraph . org-groff-paragraph)
(plain-list . org-groff-plain-list)
(plain-text . org-groff-plain-text)
(planning . org-groff-planning)
- (property-drawer . (lambda (&rest args) ""))
+ (property-drawer . org-groff-property-drawer)
(quote-block . org-groff-quote-block)
- (quote-section . org-groff-quote-section)
(radio-target . org-groff-radio-target)
(section . org-groff-section)
(special-block . org-groff-special-block)
@@ -1253,12 +1253,8 @@ INFO is a plist holding contextual information. See
(path (cond
((member type '("http" "https" "ftp" "mailto"))
(concat type ":" raw-path))
- ((string= type "file")
- (when (string-match "\\(.+\\)::.+" raw-path)
- (setq raw-path (match-string 1 raw-path)))
- (if (file-name-absolute-p raw-path)
- (concat "file://" (expand-file-name raw-path))
- (concat "file://" raw-path)))
+ ((and (string= type "file") (file-name-absolute-p raw-path))
+ (concat "file://" raw-path))
(t raw-path)))
protocol)
(cond
@@ -1272,9 +1268,10 @@ INFO is a plist holding contextual information. See
;; description.
((string= type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) desc
(format "\\fI [%s] \\fP"
- (org-export-solidify-link-text path)))))
+ (org-export-solidify-link-text
+ (org-element-property :value destination))))))
;; Links pointing to a headline: find destination and build
;; appropriate referencing command.
@@ -1316,6 +1313,17 @@ INFO is a plist holding contextual information. See
;; No path, only description. Try to do something useful.
(t (format org-groff-link-with-unknown-path-format desc)))))
+;;; Node Property
+
+(defun org-groff-node-property (node-property contents info)
+ "Transcode a NODE-PROPERTY element from Org to Groff.
+CONTENTS is nil. INFO is a plist holding contextual
+information."
+ (format "%s:%s"
+ (org-element-property :key node-property)
+ (let ((value (org-element-property :value node-property)))
+ (if value (concat " " value) ""))))
+
;;; Paragraph
(defun org-groff-paragraph (paragraph contents info)
@@ -1426,6 +1434,15 @@ information."
"")
""))
+;;;; Property Drawer
+
+(defun org-groff-property-drawer (property-drawer contents info)
+ "Transcode a PROPERTY-DRAWER element from Org to Groff.
+CONTENTS holds the contents of the drawer. INFO is a plist
+holding contextual information."
+ (and (org-string-nw-p contents)
+ (format "\\fC\n%s\\fP" contents)))
+
;;; Quote Block
(defun org-groff-quote-block (quote-block contents info)
@@ -1436,15 +1453,6 @@ holding contextual information."
quote-block
(format ".DS I\n.I\n%s\n.R\n.DE" contents)))
-;;; Quote Section
-
-(defun org-groff-quote-section (quote-section contents info)
- "Transcode a QUOTE-SECTION element from Org to Groff.
-CONTENTS is nil. INFO is a plist holding contextual information."
- (let ((value (org-remove-indentation
- (org-element-property :value quote-section))))
- (when value (format ".DS L\n\\fI%s\\fP\n.DE\n" value))))
-
;;; Radio Target
(defun org-groff-radio-target (radio-target text info)
diff --git a/contrib/lisp/ox-koma-letter.el b/contrib/lisp/ox-koma-letter.el
index 240de29..32dd199 100644
--- a/contrib/lisp/ox-koma-letter.el
+++ b/contrib/lisp/ox-koma-letter.el
@@ -1,6 +1,6 @@
;;; ox-koma-letter.el --- KOMA Scrlttr2 Back-End for Org Export Engine
-;; Copyright (C) 2007-2012 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2012, 2014 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou AT gmail DOT com>
;; Alan Schmitt <alan.schmitt AT polytechnique DOT org>
@@ -34,14 +34,14 @@
;; On top of buffer keywords supported by `latex' back-end (see
;; `org-latex-options-alist'), this back-end introduces the following
;; keywords:
-;; - "CLOSING" (see `org-koma-letter-closing'),
-;; - "FROM_ADDRESS" (see `org-koma-letter-from-address'),
-;; - "LCO" (see `org-koma-letter-class-option-file'),
-;; - "OPENING" (see `org-koma-letter-opening'),
-;; - "PHONE_NUMBER" (see `org-koma-letter-phone-number'),
-;; - "SIGNATURE" (see `org-koma-letter-signature')
-;; - "PLACE" (see `org-koma-letter-place')
-;; - and "TO_ADDRESS". If unspecified this is set to "\mbox{}".
+;; - CLOSING: see `org-koma-letter-closing',
+;; - FROM_ADDRESS: see `org-koma-letter-from-address',
+;; - LCO: see `org-koma-letter-class-option-file',
+;; - OPENING: see `org-koma-letter-opening',
+;; - PHONE_NUMBER: see `org-koma-letter-phone-number',
+;; - SIGNATURE: see `org-koma-letter-signature',
+;; - PLACE: see `org-koma-letter-place',
+;; - TO_ADDRESS: If unspecified this is set to "\mbox{}".
;;
;; TO_ADDRESS and FROM_ADDRESS can also be specified using heading
;; with the special tags specified in
@@ -67,8 +67,9 @@
;; (see `org-koma-letter-special-tags-after-letter').
;;
;; The following variables works differently from the main LaTeX class
-;; - "AUTHOR": default to user-full-name but may be disabled. (see org-koma-letter-author),
-;; - "EMAIL": same as AUTHOR, (see org-koma-letter-email),
+;; - AUTHOR: Default to user-full-name but may be disabled.
+;; (See also `org-koma-letter-author'),
+;; - EMAIL: Same as AUTHOR. (see also `org-koma-letter-email'),
;;
;; Headlines are in general ignored. However, headlines with special
;; tags can be used for specified contents like postscript (ps),
@@ -84,16 +85,10 @@
;; with information is present precedence is determined by
;; `org-koma-letter-prefer-special-headings'.
;;
-;; You will need to add an appropriate association in
-;; `org-latex-classes' in order to use the KOMA Scrlttr2 class.
-;; The easiest way to do this is by adding
-;;
-;; (eval-after-load "ox-koma-letter"
-;; '(org-koma-letter-plug-into-ox))
-;;
-;; to your init file. This will add a sparse scrlttr2 class and
-;; set it as the default `org-koma-latex-default-class'. You can also
-;; add you own letter class. For instace:
+;; You need an appropriate association in `org-latex-classes' in order
+;; to use the KOMA Scrlttr2 class. By default, a sparse scrlttr2
+;; class is provided: "default-koma-letter". You can also add you own
+;; letter class. For instance:
;;
;; (add-to-list 'org-latex-classes
;; '("my-letter"
@@ -111,16 +106,26 @@
;; \[EXTRA]"))
;;
;; Then, in your Org document, be sure to require the proper class
-;; with :
+;; with:
;;
;; #+LATEX_CLASS: my-letter
;;
;; Or by setting `org-koma-letter-default-class'.
+;;
+;; You may have to load (LaTeX) Babel as well, e.g., by adding
+;; it to `org-latex-packages-alist',
+;;
+;; (add-to-list 'org-latex-packages-alist '("AUTO" "babel" nil))
;;; Code:
(require 'ox-latex)
+;; Install a default letter class.
+(unless (assoc "default-koma-letter" org-latex-classes)
+ (add-to-list 'org-latex-classes
+ '("default-koma-letter" "\\documentclass[11pt]{scrlttr2}")))
+
;;; User-Configurable Variables
@@ -130,17 +135,20 @@
:group 'org-export)
(defcustom org-koma-letter-class-option-file "NF"
- "Letter Class Option File."
+ "Letter Class Option File.
+This option can also be set with the LCO keyword."
:group 'org-export-koma-letter
:type 'string)
(defcustom org-koma-letter-author 'user-full-name
- "The sender's name.
+ "Sender's name.
This variable defaults to calling the function `user-full-name'
-which just returns the current function `user-full-name'. Alternatively a
-string, nil or a function may be given. Functions must return a
-string."
+which just returns the current function `user-full-name'.
+Alternatively a string, nil or a function may be given.
+Functions must return a string.
+
+This option can also be set with the AUTHOR keyword."
:group 'org-export-koma-letter
:type '(radio (function-item user-full-name)
(string)
@@ -148,134 +156,219 @@ string."
(const :tag "Do not export author" nil)))
(defcustom org-koma-letter-email 'org-koma-letter-email
- "The sender's email address.
+ "Sender's email address.
This variable defaults to the value `org-koma-letter-email' which
-returns `user-mail-address'. Alternatively a string, nil or a
-function may be given. Functions must return a string."
+returns `user-mail-address'. Alternatively a string, nil or
+a function may be given. Functions must return a string.
+
+This option can also be set with the EMAIL keyword."
:group 'org-export-koma-letter
:type '(radio (function-item org-koma-letter-email)
(string)
(function)
(const :tag "Do not export email" nil)))
-(defcustom org-koma-letter-from-address nil
- "Sender's address, as a string."
+(defcustom org-koma-letter-from-address ""
+ "Sender's address, as a string.
+This option can also be set with one or more FROM_ADDRESS
+keywords."
:group 'org-export-koma-letter
:type 'string)
-(defcustom org-koma-letter-phone-number nil
- "Sender's phone number, as a string."
+(defcustom org-koma-letter-phone-number ""
+ "Sender's phone number, as a string.
+This option can also be set with the PHONE_NUMBER keyword."
:group 'org-export-koma-letter
:type 'string)
-(defcustom org-koma-letter-place nil
- "Place from which the letter is sent."
+(defcustom org-koma-letter-place ""
+ "Place from which the letter is sent, as a string.
+This option can also be set with the PLACE keyword."
:group 'org-export-koma-letter
:type 'string)
-(defcustom org-koma-letter-opening nil
+(defcustom org-koma-letter-opening ""
"Letter's opening, as a string.
-If (1) this value is nil; (2) the letter is started with a
-headline; and (3) `org-koma-letter-headline-is-opening-maybe' is
-t the value opening will be implicit set as the headline title."
+This option can also be set with the OPENING keyword. Moreover,
+when:
+ (1) this value is the empty string;
+ (2) there's no OPENING keyword or it is empty;
+ (3) `org-koma-letter-headline-is-opening-maybe' is non-nil;
+ (4) the letter contains a headline without a special
+ tag (e.g. \"to\" or \"ps\");
+then the opening will be implicitly set as the headline title."
:group 'org-export-koma-letter
:type 'string)
-(defcustom org-koma-letter-closing nil
- "Koma-Letter's closing, as a string."
+(defcustom org-koma-letter-closing ""
+ "Letter's closing, as a string.
+This option can also be set with the CLOSING keyword."
:group 'org-export-koma-letter
:type 'string)
-(defcustom org-koma-letter-prefer-special-headings nil
- "If TO and/or FROM is specified using both a heading and a keyword the heading value will be preferred if the variable is t."
+(defcustom org-koma-letter-signature ""
+ "Signature, as a string.
+This option can also be set with the SIGNATURE keyword."
:group 'org-export-koma-letter
- :type 'boolean)
+ :type 'string)
-(defcustom org-koma-letter-signature nil
- "String used as the signature."
+(defcustom org-koma-letter-prefer-special-headings nil
+ "Non-nil means prefer headlines over keywords for TO and FROM.
+This option can also be set with the OPTIONS keyword, e.g.:
+\"special-headings:t\"."
:group 'org-export-koma-letter
- :type 'string)
+ :type 'boolean)
(defcustom org-koma-letter-subject-format t
"Use the title as the subject of the letter.
-At this time the following values are allowed:
+When t, insert a subject using default options. When nil, do not
+insert a subject at all. It can also be a list of symbols among
+the following ones:
- - afteropening: subject after opening.
- - beforeopening: subject before opening.
- - centered: subject centered.
- - left:subject left-justified.
- - right: subject right-justified.
- - titled: add title/description to subject.
- - underlined: set subject underlined.
- - untitled: do not add title/description to subject.
- - No-export: do no insert a subject even if present.
+ `afteropening' Subject after opening
+ `beforeopening' Subject before opening
+ `centered' Subject centered
+ `left' Subject left-justified
+ `right' Subject right-justified
+ `titled' Add title/description to subject
+ `underlined' Set subject underlined
+ `untitled' Do not add title/description to subject
Please refer to the KOMA-script manual (Table 4.16. in the
-English manual of 2012-07-22)."
- :type '(radio
- (const :tag "No export" nil)
- (const :tag "Default options" t)
- (set :tag "selection"
- (const 'afteropening)
- (const 'beforeopening)
- (const 'centered)
- (const 'left)
- (const 'right)
- (const 'underlined)
- (const 'titled)
- (const 'untitled))
- (string))
+English manual of 2012-07-22).
+
+This option can also be set with the OPTIONS keyword, e.g.:
+\"subject:(underlined centered)\"."
+ :type
+ '(choice
+ (const :tag "No export" nil)
+ (const :tag "Default options" t)
+ (set :tag "Configure options"
+ (const :tag "Subject after opening" afteropening)
+ (const :tag "Subject before opening" beforeopening)
+ (const :tag "Subject centered" centered)
+ (const :tag "Subject left-justified" left)
+ (const :tag "Subject right-justified" right)
+ (const :tag "Add title or description to subject" underlined)
+ (const :tag "Set subject underlined" titled)
+ (const :tag "Do not add title or description to subject" untitled)))
:group 'org-export-koma-letter)
-
-
(defcustom org-koma-letter-use-backaddress nil
- "Print return address in small line above to address."
+ "Non-nil prints return address in line above to address.
+This option can also be set with the OPTIONS keyword, e.g.:
+\"backaddress:t\"."
:group 'org-export-koma-letter
:type 'boolean)
-(defcustom org-koma-letter-use-foldmarks "true"
- "Configure appearence of fold marks.
+(defcustom org-koma-letter-use-foldmarks t
+ "Configure appearance of folding marks.
+
+When t, activate default folding marks. When nil, do not insert
+folding marks at all. It can also be a list of symbols among the
+following ones:
+
+ `B' Activate upper horizontal mark on left paper edge
+ `b' Deactivate upper horizontal mark on left paper edge
+
+ `H' Activate all horizontal marks on left paper edge
+ `h' Deactivate all horizontal marks on left paper edge
+
+ `L' Activate left vertical mark on upper paper edge
+ `l' Deactivate left vertical mark on upper paper edge
+
+ `M' Activate middle horizontal mark on left paper edge
+ `m' Deactivate middle horizontal mark on left paper edge
+
+ `P' Activate punch or center mark on left paper edge
+ `p' Deactivate punch or center mark on left paper edge
+
+ `T' Activate lower horizontal mark on left paper edge
+ `t' Deactivate lower horizontal mark on left paper edge
-Accepts any valid value for the KOMA-Script `foldmarks' option.
+ `V' Activate all vertical marks on upper paper edge
+ `v' Deactivate all vertical marks on upper paper edge
-Use `foldmarks:true' to activate default fold marks or
-`foldmarks:nil' to deactivate fold marks."
+This option can also be set with the OPTIONS keyword, e.g.:
+\"foldmarks:(b l m t)\"."
:group 'org-export-koma-letter
- :type 'string)
+ :type '(choice
+ (const :tag "Activate default folding marks" t)
+ (const :tag "Deactivate folding marks" nil)
+ (set
+ :tag "Configure folding marks"
+ (const :tag "Activate upper horizontal mark on left paper edge" B)
+ (const :tag "Deactivate upper horizontal mark on left paper edge" b)
+ (const :tag "Activate all horizontal marks on left paper edge" H)
+ (const :tag "Deactivate all horizontal marks on left paper edge" h)
+ (const :tag "Activate left vertical mark on upper paper edge" L)
+ (const :tag "Deactivate left vertical mark on upper paper edge" l)
+ (const :tag "Activate middle horizontal mark on left paper edge" M)
+ (const :tag "Deactivate middle horizontal mark on left paper edge" m)
+ (const :tag "Activate punch or center mark on left paper edge" P)
+ (const :tag "Deactivate punch or center mark on left paper edge" p)
+ (const :tag "Activate lower horizontal mark on left paper edge" T)
+ (const :tag "Deactivate lower horizontal mark on left paper edge" t)
+ (const :tag "Activate all vertical marks on upper paper edge" V)
+ (const :tag "Deactivate all vertical marks on upper paper edge" v))))
(defcustom org-koma-letter-use-phone nil
- "Print sender's phone number."
+ "Non-nil prints sender's phone number.
+This option can also be set with the OPTIONS keyword, e.g.:
+\"phone:t\"."
:group 'org-export-koma-letter
:type 'boolean)
(defcustom org-koma-letter-use-email nil
- "Print sender's email address."
+ "Non-nil prints sender's email address.
+This option can also be set with the OPTIONS keyword, e.g.:
+\"email:t\"."
:group 'org-export-koma-letter
:type 'boolean)
(defcustom org-koma-letter-use-place t
- "Print the letter's place next to the date."
+ "Non-nil prints the letter's place next to the date.
+This option can also be set with the OPTIONS keyword, e.g.:
+\"place:nil\"."
:group 'org-export-koma-letter
:type 'boolean)
-(defcustom org-koma-letter-default-class nil
- "Default class for `org-koma-letter'.
+(defcustom org-koma-letter-use-title t
+ "Non-nil means use a title in the letter if present.
+This option can also be set with the OPTIONS keyword,
+e.g. \"title:nil\".
+
+See also `org-koma-letter-prefer-subject' for the handling of
+title versus subject."
+ :group 'org-export-koma-letter
+ :type 'boolean)
+(defcustom org-koma-letter-default-class "default-koma-letter"
+ "Default class for `org-koma-letter'.
The value must be a member of `org-latex-classes'."
:group 'org-export-koma-letter
:type 'string)
(defcustom org-koma-letter-headline-is-opening-maybe t
- "Whether a headline may be used as an opening.
+ "Non-nil means a headline may be used as an opening.
A headline is only used if #+OPENING is not set. See also
`org-koma-letter-opening'."
:group 'org-export-koma-letter
:type 'boolean)
+(defcustom org-koma-letter-prefer-subject nil
+ "Non-nil means title should be interpret as subject if subject is missing.
+This option can also be set with the OPTIONS keyword,
+e.g. \"title-subject:t\".
+
+This may be useful for older documents where the SUBJECT keyword
+was not present."
+ :group 'org-export-koma-letter
+ :type 'boolean)
+
(defconst org-koma-letter-special-tags-in-letter '(to from)
"Header tags related to the letter itself.")
@@ -294,41 +387,49 @@ A headline is only used if #+OPENING is not set. See also
(org-export-define-derived-backend 'koma-letter 'latex
:options-alist
- '((:lco "LCO" nil org-koma-letter-class-option-file)
- (:latex-class "LATEX_CLASS" nil (if org-koma-letter-default-class
- org-koma-letter-default-class
- org-latex-default-class) t)
+ '((:latex-class "LATEX_CLASS" nil org-koma-letter-default-class t)
+ (:lco "LCO" nil org-koma-letter-class-option-file)
(:author "AUTHOR" nil (org-koma-letter--get-value org-koma-letter-author) t)
(:author-changed-in-buffer-p "AUTHOR" nil nil t)
(:from-address "FROM_ADDRESS" nil nil newline)
(:phone-number "PHONE_NUMBER" nil org-koma-letter-phone-number)
(:email "EMAIL" nil (org-koma-letter--get-value org-koma-letter-email) t)
- (:email-changed-in-buffer-p "EMAIL" nil nil t)
(:to-address "TO_ADDRESS" nil nil newline)
(:place "PLACE" nil org-koma-letter-place)
+ (:subject "SUBJECT" nil nil space)
(:opening "OPENING" nil org-koma-letter-opening)
(:closing "CLOSING" nil org-koma-letter-closing)
(:signature "SIGNATURE" nil org-koma-letter-signature newline)
+ (:special-headings nil "special-headings"
+ org-koma-letter-prefer-special-headings)
(:special-tags nil nil (append
org-koma-letter-special-tags-in-letter
org-koma-letter-special-tags-after-closing
org-koma-letter-special-tags-after-letter))
- (:special-headings nil "special-headings"
- org-koma-letter-prefer-special-headings)
(:with-after-closing nil "after-closing-order"
org-koma-letter-special-tags-after-closing)
(:with-after-letter nil "after-letter-order"
org-koma-letter-special-tags-after-letter)
(:with-backaddress nil "backaddress" org-koma-letter-use-backaddress)
- (:with-backaddress-changed-in-buffer-p nil "backaddress" nil)
+ (:with-email nil "email" org-koma-letter-use-email)
(:with-foldmarks nil "foldmarks" org-koma-letter-use-foldmarks)
- (:with-foldmarks-changed-in-buffer-p nil "foldmarks" "foldmarks-not-set")
(:with-phone nil "phone" org-koma-letter-use-phone)
- (:with-phone-changed-in-buffer-p nil "phone" nil)
- (:with-email nil "email" org-koma-letter-use-email)
- (:with-email-changed-in-buffer-p nil "email" nil)
(:with-place nil "place" org-koma-letter-use-place)
- (:with-subject nil "subject" org-koma-letter-subject-format))
+ (:with-subject nil "subject" org-koma-letter-subject-format)
+ (:with-title nil "title" org-koma-letter-use-title)
+ (:with-title-as-subject nil "title-subject" org-koma-letter-prefer-subject)
+ ;; Special properties non-nil when a setting happened in buffer.
+ ;; They are used to prioritize in-buffer settings over "lco"
+ ;; files. See `org-koma-letter-template'.
+ (:inbuffer-author "AUTHOR" nil 'koma-letter:empty)
+ (:inbuffer-email "EMAIL" nil 'koma-letter:empty)
+ (:inbuffer-phone-number "PHONE_NUMBER" nil 'koma-letter:empty)
+ (:inbuffer-place "PLACE" nil 'koma-letter:empty)
+ (:inbuffer-signature "SIGNATURE" nil 'koma-letter:empty)
+ (:inbuffer-with-backaddress nil "backaddress" 'koma-letter:empty)
+ (:inbuffer-with-email nil "email" 'koma-letter:empty)
+ (:inbuffer-with-foldmarks nil "foldmarks" 'koma-letter:empty)
+ (:inbuffer-with-phone nil "phone" 'koma-letter:empty))
:translate-alist '((export-block . org-koma-letter-export-block)
(export-snippet . org-koma-letter-export-snippet)
(headline . org-koma-letter-headline)
@@ -344,19 +445,8 @@ A headline is only used if #+OPENING is not set. See also
(if a (org-koma-letter-export-to-pdf t s v b)
(org-open-file (org-koma-letter-export-to-pdf nil s v b))))))))
-
-;;; Initialize class function
-
-(defun org-koma-letter-plug-into-ox ()
- "Add a sparse `default-koma-letter' to `org-latex-classes' and set `org-koma-letter-default-class' to `default-koma-letter'."
- (let ((class "default-koma-letter"))
- (eval-after-load "ox-latex"
- `(unless (member ,class 'org-latex-classes)
- (add-to-list 'org-latex-classes
- `(,class
- "\\documentclass[11pt]{scrlttr2}") ())
- (setq org-koma-letter-default-class class)))))
+
;;; Helper functions
(defun org-koma-letter-email ()
@@ -368,83 +458,64 @@ A headline is only used if #+OPENING is not set. See also
(defun org-koma-letter--get-tagged-contents (key)
"Get contents from a headline tagged with KEY.
-Technically, the contents is stored in `org-koma-letter-special-contents'."
+The contents is stored in `org-koma-letter-special-contents'."
(cdr (assoc (org-koma-letter--get-value key)
org-koma-letter-special-contents)))
(defun org-koma-letter--get-value (value)
- "Determines if VALUE is nil, a string, a function or a symbol and return a string or nil."
+ "Turn value into a string whenever possible.
+Determines if VALUE is nil, a string, a function or a symbol and
+return a string or nil."
(when value
(cond ((stringp value) value)
((functionp value) (funcall value))
((symbolp value) (symbol-name value))
(t value))))
+(defun org-koma-letter--special-contents-as-macro
+ (keywords &optional keep-newlines no-tag)
+ "Process KEYWORDS members of `org-koma-letter-special-contents'.
+KEYWORDS is a list of symbols. Return them as a string to be
+formatted.
-(defun org-koma-letter--special-contents-as-macro (a-list &optional keep-newlines no-tag)
- "Find members of `org-koma-letter-special-contents' corresponding to A-LIST.
-Return them as a string to be formatted.
-
-The function is used for inserting content of speciall headings
+The function is used for inserting content of special headings
such as PS.
If KEEP-NEWLINES is t newlines will not be removed. If NO-TAG is
-is t the content in `org-koma-letter-special-contents' will not
-be wrapped in a macro named whatever the members of A-LIST are
+t the content in `org-koma-letter-special-contents' will not be
+wrapped in a macro named whatever the members of KEYWORDS are
called."
- (let (output)
- (dolist (ac* a-list output)
- (let*
- ((ac (org-koma-letter--get-value ac*))
- (x (org-koma-letter--get-tagged-contents ac)))
- (when x
- (setq output
- (concat
- output "\n"
- ;; sometimes LaTeX complains about newlines
- ;; at the end or beginning of macros. Remove them.
- (org-koma-letter--format-string-as-macro
- (if keep-newlines x (org-koma-letter--normalize-string x))
- (unless no-tag ac)))))))))
-
-(defun org-koma-letter--format-string-as-macro (string &optional macro)
- "Format STRING as \"\\macro{string}\" if MACRO is given else as \"string\"."
- (if macro
- (format "\\%s{%s}" macro string)
- (format "%s" string)))
-
-(defun org-koma-letter--normalize-string (string)
- "Remove new lines in the beginning and end of `STRING'."
- (replace-regexp-in-string "\\`[ \n\t]+\\|[\n\t ]*\\'" "" string))
+ (mapconcat
+ #'(lambda (keyword)
+ (let* ((name (org-koma-letter--get-value keyword))
+ (value (org-koma-letter--get-tagged-contents name)))
+ (when value
+ (if no-tag (if keep-newlines value (org-trim value))
+ (format "\\%s{%s}\n"
+ name
+ (if keep-newlines value (org-trim value)))))))
+ keywords
+ ""))
(defun org-koma-letter--determine-to-and-from (info key)
"Given INFO determine KEY for the letter.
KEY should be `to' or `from'.
-`ox-koma-letter' allows two ways to specify to and from. If both
+`ox-koma-letter' allows two ways to specify TO and FROM. If both
are present return the preferred one as determined by
`org-koma-letter-prefer-special-headings'."
- (let* ((plist-alist '((from . :from-address)
- (to . :to-address)))
- (default-alist `((from ,org-koma-letter-from-address)
- (to "\\mbox{}")))
- (option-value (plist-get info (cdr-safe (assoc key plist-alist))))
- (head-value (org-koma-letter--get-tagged-contents key))
- (order (append
- (funcall
- (if (plist-get info :special-headings)
- 'reverse 'identity)
- `(,option-value ,head-value))
- (cdr-safe (assoc key default-alist))))
- tmp
- (adr (dolist (x order tmp)
- (when (and (not tmp) x)
- (setq tmp x)))))
- (when adr
+ (let ((option (plist-get info (if (eq key 'to) :to-address :from-address)))
+ (headline (org-koma-letter--get-tagged-contents key)))
(replace-regexp-in-string
"\n" "\\\\\\\\\n"
- (org-koma-letter--normalize-string adr)))))
+ (org-trim
+ (or (if (plist-get info :special-headings) (or headline option)
+ (or option headline))
+ ;; Fallback values.
+ (if (eq key 'to) "\\mbox{}" org-koma-letter-from-address))))))
+
+
;;; Transcode Functions
;;;; Export Block
@@ -473,12 +544,11 @@ CONTENTS is nil. INFO is a plist used as a communication
channel."
(let ((key (org-element-property :key keyword))
(value (org-element-property :value keyword)))
- ;; Handle specifically BEAMER and TOC (headlines only) keywords.
- ;; Otherwise, fallback to `latex' back-end.
+ ;; Handle specifically KOMA-LETTER keywords. Otherwise, fallback
+ ;; to `latex' back-end.
(if (equal key "KOMA-LETTER") value
(org-export-with-backend 'latex keyword contents info))))
-
;; Headline
(defun org-koma-letter-headline (headline contents info)
@@ -490,24 +560,19 @@ Note that if a headline is tagged with a tag from
`org-koma-letter-special-tags' it will not be exported, but
stored in `org-koma-letter-special-contents' and included at the
appropriate place."
- (let*
- ((tags (org-export-get-tags headline info))
- (tag* (car tags))
- (tag (when tag*
- (car (member-ignore-case
- tag*
- (mapcar 'symbol-name (plist-get info :special-tags)))))))
- (if tag
- (progn
- (push (cons tag contents)
- org-koma-letter-special-contents)
- nil)
- (unless (or (plist-get info :opening)
- (not org-koma-letter-headline-is-opening-maybe))
- (plist-put info :opening
- (org-export-data (org-element-property :title headline) info)))
- contents)))
-
+ (unless (let ((tag (car (org-export-get-tags headline info))))
+ (and tag
+ (member-ignore-case
+ tag (mapcar #'symbol-name (plist-get info :special-tags)))
+ ;; Store association for later use and bail out.
+ (push (cons tag contents) org-koma-letter-special-contents)))
+ ;; Opening is not defined yet: use headline's title.
+ (when (and org-koma-letter-headline-is-opening-maybe
+ (not (org-string-nw-p (plist-get info :opening))))
+ (plist-put info :opening
+ (org-export-data (org-element-property :title headline) info)))
+ ;; In any case, insert contents in letter's body.
+ contents))
;;;; Template
@@ -515,9 +580,6 @@ appropriate place."
"Return complete document string after KOMA Scrlttr2 conversion.
CONTENTS is the transcoded contents string. INFO is a plist
holding export options."
- ;; FIXME: instead of setq'ing org-koma-letter-special-contents and
- ;; callying varioues stuff it might be nice to put a big let* around the templace
- ;; as in org-groff...
(concat
;; Time-stamp.
(and (plist-get info :time-stamp-file)
@@ -544,94 +606,53 @@ holding export options."
(concat (org-element-normalize-string (plist-get info :latex-header))
(plist-get info :latex-header-extra)))))
info)))
- (let ((lco (plist-get info :lco))
- (author (plist-get info :author))
- (author-set (plist-get info :author-changed-in-buffer-p))
- (from-address (org-koma-letter--determine-to-and-from info 'from))
- (phone-number (plist-get info :phone-number))
- (email (plist-get info :email))
- (email-set (plist-get info :email-changed-in-buffer-p))
- (signature (plist-get info :signature)))
- (concat
- ;; author or email not set in file: may be overridden by lco
- (unless author-set
- (when author (format "\\setkomavar{fromname}{%s}\n"
- (org-export-data author info))))
- (unless email-set
- (when email (format "\\setkomavar{fromemail}{%s}\n" email)))
- ;; Letter Class Option File
- (when lco
- (let ((lco-files (split-string lco " "))
- (lco-def ""))
- (dolist (lco-file lco-files lco-def)
- (setq lco-def (format "%s\\LoadLetterOption{%s}\n" lco-def lco-file)))
- lco-def))
- ;; Define "From" data.
- (when (and author author-set) (format "\\setkomavar{fromname}{%s}\n"
- (org-export-data author info)))
- (when from-address (format "\\setkomavar{fromaddress}{%s}\n" from-address))
- (when phone-number
- (format "\\setkomavar{fromphone}{%s}\n" phone-number))
- (when (and email email-set) (format "\\setkomavar{fromemail}{%s}\n" email))
- (when signature (format "\\setkomavar{signature}{%s}\n" signature))))
+ ;; Settings. They can come from three locations, in increasing
+ ;; order of precedence: global variables, LCO files and in-buffer
+ ;; settings. Thus, we first insert settings coming from global
+ ;; variables, then we insert LCO files, and, eventually, we insert
+ ;; settings coming from buffer keywords.
+ (org-koma-letter--build-settings 'global info)
+ (mapconcat #'(lambda (file) (format "\\LoadLetterOption{%s}\n" file))
+ (org-split-string (or (plist-get info :lco) "") " ")
+ "")
+ (org-koma-letter--build-settings 'buffer info)
+ ;; From address.
+ (let ((from-address (org-koma-letter--determine-to-and-from info 'from)))
+ (when (org-string-nw-p from-address)
+ (format "\\setkomavar{fromaddress}{%s}\n" from-address)))
;; Date.
(format "\\date{%s}\n" (org-export-data (org-export-get-date info) info))
- ;; Place
- (let ((with-place (plist-get info :with-place))
- (place (plist-get info :place)))
- (when (or place (not with-place))
- (format "\\setkomavar{place}{%s}\n" (if with-place place ""))))
- ;; KOMA options
- (let ((with-backaddress (plist-get info :with-backaddress))
- (with-backaddress-set (plist-get info :with-backaddress-changed-in-buffer-p))
- (with-foldmarks (plist-get info :with-foldmarks))
- (with-foldmarks-set
- (not (string-equal (plist-get info :with-foldmarks-changed-in-buffer-p)
- "foldmarks-not-set")))
- (with-phone (plist-get info :with-phone))
- (with-phone-set (plist-get info :with-phone-changed-in-buffer-p))
- (with-email (plist-get info :with-email))
- (with-email-set (plist-get info :with-email-changed-in-buffer-p)))
- (concat
- (when with-backaddress-set
- (format "\\KOMAoption{backaddress}{%s}\n" (if with-backaddress "true" "false")))
- (when with-foldmarks-set
- (format "\\KOMAoption{foldmarks}{%s}\n" (if with-foldmarks with-foldmarks "false")))
- (when with-phone-set
- (format "\\KOMAoption{fromphone}{%s}\n" (if with-phone "true" "false")))
- (when with-email-set
- (format "\\KOMAoption{fromemail}{%s}\n" (if with-email "true" "false")))))
;; Document start
"\\begin{document}\n\n"
- ;; Subject
- (let* ((with-subject (plist-get info :with-subject))
- (subject-format (cond ((member with-subject '("true" "t" t)) nil)
- ((stringp with-subject) (list with-subject))
- ((symbolp with-subject)
- (list (symbol-name with-subject)))
- (t with-subject)))
- (subject (org-export-data (plist-get info :title) info))
- (l (length subject-format))
- (y ""))
- (concat
- (when (and with-subject subject-format)
- (concat
- "\\KOMAoption{subject}{"
- (apply 'format
- (dotimes (x l y)
- (setq y (concat (if (> x 0) "%s," "%s") y)))
- subject-format) "}\n"))
- (when (and subject with-subject)
- (format "\\setkomavar{subject}{%s}\n\n" subject))))
- ;; Letter start
+ ;; Subject and title
+ (let ((with-subject (plist-get info :with-subject)))
+ (when with-subject
+ (concat
+ (unless (eq with-subject t)
+ (format "\\KOMAoption{subject}{%s}\n"
+ (if (symbolp with-subject) with-subject
+ (mapconcat #'symbol-name with-subject ","))))
+ (let* ((title-as-subject (plist-get info :with-title-as-subject))
+ (subject* (org-string-nw-p
+ (org-export-data (plist-get info :subject) info)))
+ (title* (and (plist-get info :with-title)
+ (org-string-nw-p
+ (org-export-data (plist-get info :title) info))))
+ (subject (if title-as-subject (or subject* title*) subject*))
+ (title (if title-as-subject (and subject* title*) title*)))
+ (concat
+ (and subject (format "\\setkomavar{subject}{%s}\n" subject))
+ (and title (format "\\setkomavar{title}{%s}\n" title))
+ (when (or (org-string-nw-p title) (org-string-nw-p subject)) "\n"))))))
+ ;; Letter start.
(format "\\begin{letter}{%%\n%s}\n\n"
(org-koma-letter--determine-to-and-from info 'to))
;; Opening.
- (format "\\opening{%s}\n\n" (or (plist-get info :opening) ""))
+ (format "\\opening{%s}\n\n" (plist-get info :opening))
;; Letter body.
contents
;; Closing.
- (format "\n\\closing{%s}\n" (or (plist-get info :closing) ""))
+ (format "\n\\closing{%s}\n" (plist-get info :closing))
(org-koma-letter--special-contents-as-macro
(plist-get info :with-after-closing))
;; Letter end.
@@ -639,8 +660,65 @@ holding export options."
(org-koma-letter--special-contents-as-macro
(plist-get info :with-after-letter) t t)
;; Document end.
- "\n\\end{document}"
- ))
+ "\n\\end{document}"))
+
+(defun org-koma-letter--build-settings (scope info)
+ "Build settings string according to type.
+SCOPE is either `global' or `buffer'. INFO is a plist used as
+a communication channel."
+ (let ((check-scope
+ (function
+ ;; Non-nil value when SETTING was defined in SCOPE.
+ (lambda (setting)
+ (let ((property (intern (format ":inbuffer-%s" setting))))
+ (if (eq scope 'global)
+ (eq (plist-get info property) 'koma-letter:empty)
+ (not (eq (plist-get info property) 'koma-letter:empty))))))))
+ (concat
+ ;; Name.
+ (let ((author (plist-get info :author)))
+ (and author
+ (funcall check-scope 'author)
+ (format "\\setkomavar{fromname}{%s}\n"
+ (org-export-data author info))))
+ ;; Email.
+ (let ((email (plist-get info :email)))
+ (and email
+ (funcall check-scope 'email)
+ (format "\\setkomavar{fromemail}{%s}\n" email)))
+ (and (funcall check-scope 'with-email)
+ (format "\\KOMAoption{fromemail}{%s}\n"
+ (if (plist-get info :with-email) "true" "false")))
+ ;; Phone number.
+ (let ((phone-number (plist-get info :phone-number)))
+ (and (org-string-nw-p phone-number)
+ (funcall check-scope 'phone-number)
+ (format "\\setkomavar{fromphone}{%s}\n" phone-number)))
+ (and (funcall check-scope 'with-phone)
+ (format "\\KOMAoption{fromphone}{%s}\n"
+ (if (plist-get info :with-phone) "true" "false")))
+ ;; Signature.
+ (let ((signature (plist-get info :signature)))
+ (and (org-string-nw-p signature)
+ (funcall check-scope 'signature)
+ (format "\\setkomavar{signature}{%s}\n" signature)))
+ ;; Back address.
+ (and (funcall check-scope 'with-backaddress)
+ (format "\\KOMAoption{backaddress}{%s}\n"
+ (if (plist-get info :with-backaddress) "true" "false")))
+ ;; Place.
+ (and (funcall check-scope 'place)
+ (format "\\setkomavar{place}{%s}\n"
+ (if (plist-get info :with-place) (plist-get info :place) "")))
+ ;; Folding marks.
+ (and (funcall check-scope 'with-foldmarks)
+ (let ((foldmarks (plist-get info :with-foldmarks)))
+ (cond ((consp foldmarks)
+ (format "\\KOMAoptions{foldmarks=true,foldmarks=%s}\n"
+ (mapconcat #'symbol-name foldmarks "")))
+ (foldmarks "\\KOMAoptions{foldmarks=true}\n")
+ (t "\\KOMAoptions{foldmarks=false}\n")))))))
+
;;; Commands
diff --git a/contrib/lisp/ox-rss.el b/contrib/lisp/ox-rss.el
index 672e970..fddaa1d 100644
--- a/contrib/lisp/ox-rss.el
+++ b/contrib/lisp/ox-rss.el
@@ -1,8 +1,8 @@
;;; ox-rss.el --- RSS 2.0 Back-End for Org Export Engine
-;; Copyright (C) 2013 Bastien Guerry
+;; Copyright (C) 2013, 2014 Bastien Guerry
-;; Author: Bastien Guerry <bzg at gnu dot org>
+;; Author: Bastien Guerry <bzg@gnu.org>
;; Keywords: org, wp, blog, feed, rss
;; This file is not yet part of GNU Emacs.
@@ -204,10 +204,12 @@ publishing directory.
Return output file name."
(let ((bf (get-file-buffer filename)))
(if bf
- (with-current-buffer bf
- (org-rss-add-pubdate-property)
- (write-file filename))
+ (with-current-buffer bf
+ (org-icalendar-create-uid filename 'warn-user)
+ (org-rss-add-pubdate-property)
+ (write-file filename))
(find-file filename)
+ (org-icalendar-create-uid filename 'warn-user)
(org-rss-add-pubdate-property)
(write-file filename) (kill-buffer)))
(org-publish-org-to
@@ -222,7 +224,10 @@ communication channel."
(unless (or (org-element-property :footnote-section-p headline)
;; Only consider first-level headlines
(> (org-export-get-relative-level headline info) 1))
- (let* ((htmlext (plist-get info :html-extension))
+ (let* ((author (and (plist-get info :with-author)
+ (let ((auth (plist-get info :author)))
+ (and auth (org-export-data auth info)))))
+ (htmlext (plist-get info :html-extension))
(hl-number (org-export-get-headline-number headline info))
(hl-home (file-name-as-directory (plist-get info :html-link-home)))
(hl-pdir (plist-get info :publishing-directory))
@@ -233,14 +238,17 @@ communication channel."
(concat "sec-" (mapconcat 'number-to-string hl-number "-")))))
(category (org-rss-plain-text
(or (org-element-property :CATEGORY headline) "") info))
- (pubdate
- (let ((system-time-locale "C"))
- (format-time-string
- "%a, %d %h %Y %H:%M:%S %z"
- (org-time-string-to-time
- (or (org-element-property :PUBDATE headline)
- (error "Missing PUBDATE property"))))))
- (title (org-element-property :raw-value headline))
+ (pubdate0 (org-element-property :PUBDATE headline))
+ (pubdate (let ((system-time-locale "C"))
+ (if pubdate0
+ (format-time-string
+ "%a, %d %b %Y %H:%M:%S %z"
+ (org-time-string-to-time pubdate0)))))
+ (title (replace-regexp-in-string
+ org-bracket-link-regexp
+ (lambda (m) (or (match-string 3 m)
+ (match-string 1 m)))
+ (org-element-property :raw-value headline)))
(publink
(or (and hl-perm (concat (or hl-home hl-pdir) hl-perm))
(concat
@@ -255,17 +263,19 @@ communication channel."
(org-element-property :CUSTOM_ID headline)
publink)
info))))
- (format
- (concat
- "<item>\n"
- "<title>%s</title>\n"
- "<link>%s</link>\n"
- "<guid isPermaLink=\"false\">%s</guid>\n"
- "<pubDate>%s</pubDate>\n"
- (org-rss-build-categories headline info) "\n"
- "<description><![CDATA[%s]]></description>\n"
- "</item>\n")
- title publink guid pubdate contents))))
+ (if (not pubdate0) "" ;; Skip entries with no PUBDATE prop
+ (format
+ (concat
+ "<item>\n"
+ "<title>%s</title>\n"
+ "<link>%s</link>\n"
+ "<author>%s</author>\n"
+ "<guid isPermaLink=\"false\">%s</guid>\n"
+ "<pubDate>%s</pubDate>\n"
+ (org-rss-build-categories headline info) "\n"
+ "<description><![CDATA[%s]]></description>\n"
+ "</item>\n")
+ title publink author guid pubdate contents)))))
(defun org-rss-build-categories (headline info)
"Build categories for the RSS item."
@@ -308,7 +318,7 @@ as a communication channel."
(author (and (plist-get info :with-author)
(let ((auth (plist-get info :author)))
(and auth (org-export-data auth info)))))
- (date (format-time-string "%a, %d %h %Y %H:%M:%S %z")) ;; RFC 882
+ (date (format-time-string "%a, %d %b %Y %H:%M:%S %z")) ;; RFC 882
(description (org-export-data (plist-get info :description) info))
(lang (plist-get info :language))
(keywords (plist-get info :keywords))
@@ -319,8 +329,8 @@ as a communication channel."
(ifile (plist-get info :input-file))
(publink
(concat (file-name-as-directory blogurl)
- (file-name-nondirectory
- (file-name-sans-extension ifile))
+ (file-name-nondirectory
+ (file-name-sans-extension ifile))
"." rssext)))
(format
"\n<title>%s</title>
diff --git a/contrib/lisp/ox-s5.el b/contrib/lisp/ox-s5.el
index d97a9b2..b94c38c 100644
--- a/contrib/lisp/ox-s5.el
+++ b/contrib/lisp/ox-s5.el
@@ -1,6 +1,6 @@
;;; ox-s5.el --- S5 Presentation Back-End for Org Export Engine
-;; Copyright (C) 2011-2013 Rick Frankel
+;; Copyright (C) 2011-2014 Rick Frankel
;; Author: Rick Frankel <emacs at rickster dot com>
;; Keywords: outlines, hypermedia, S5, wp
@@ -174,8 +174,8 @@ or an empty string."
(defcustom org-s5-title-slide-template
"<h1>%t</h1>
<h2>%a</h2>
-<h2>%e</h2>
-<h2>%d</h2>"
+<h3>%e</h3>
+<h4>%d</h4>"
"Format template to specify title page section.
See `org-html-postamble-format' for the valid elements which
can be included.
@@ -201,7 +201,7 @@ INFO is a plist used as a communication channel."
(concat section-number
(org-export-data
(org-export-get-alt-title headline info) info)
- (and tags "&nbsp;&nbsp;&nbsp;") (org-html--tags tags))))
+ (and tags "&nbsp;&nbsp;&nbsp;") (org-html--tags tags info))))
(defun org-s5-toc (depth info)
(let* ((headlines (org-export-collect-headlines info depth))
diff --git a/contrib/lisp/ox-taskjuggler.el b/contrib/lisp/ox-taskjuggler.el
index 13f2f5e..807d702 100644
--- a/contrib/lisp/ox-taskjuggler.el
+++ b/contrib/lisp/ox-taskjuggler.el
@@ -1,6 +1,6 @@
;;; ox-taskjuggler.el --- TaskJuggler Back-End for Org Export Engine
;;
-;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2014 Free Software Foundation, Inc.
;;
;; Emacs Lisp Archive Entry
;; Filename: ox-taskjuggler.el
@@ -310,6 +310,19 @@ If one of these appears as a property for a headline, it will be
exported with the corresponding task."
:group 'org-export-taskjuggler)
+(defcustom org-taskjuggler-valid-project-attributes
+ '(timingresolution timezone alertlevels currency currencyformat
+ dailyworkinghours extend includejournalentry now numberformat
+ outputdir scenario shorttimeformat timeformat trackingscenario
+ weekstartsmonday weekstartssunday workinghours
+ yearlyworkingdays)
+ "Valid attributes for Taskjuggler project.
+If one of these appears as a property for a headline that is a
+project definition, it will be exported with the corresponding
+task. Attribute 'timingresolution' should be the first in the
+list."
+ :group 'org-export-taskjuggler)
+
(defcustom org-taskjuggler-valid-resource-attributes
'(limits vacation shift booking efficiency journalentry rate
workinghours flags)
@@ -483,9 +496,9 @@ Return new string. If S is the empty string, return it."
(if (equal "" s) s (replace-regexp-in-string "^ *\\S-" " \\&" s)))
(defun org-taskjuggler--build-attributes (item attributes)
- "Return attributes string for task, resource or report ITEM.
-ITEM is a headline. ATTRIBUTES is a list of symbols
-representing valid attributes for ITEM."
+ "Return attributes string for ITEM.
+ITEM is a project, task, resource or report headline. ATTRIBUTES
+is a list of symbols representing valid attributes for ITEM."
(mapconcat
(lambda (attribute)
(let ((value (org-element-property
@@ -715,18 +728,27 @@ PROJECT is a headline. INFO is a plist used as a communication
channel. If no start date is specified, start today. If no end
date is specified, end `org-taskjuggler-default-project-duration'
days from now."
- (format "project %s \"%s\" \"%s\" %s %s {\n}\n"
- (org-taskjuggler-get-id project info)
- (org-taskjuggler-get-name project)
- ;; Version is obtained through :TASKJUGGLER_VERSION:
- ;; property or `org-taskjuggler-default-project-version'.
- (or (org-element-property :VERSION project)
- org-taskjuggler-default-project-version)
- (or (org-taskjuggler-get-start project)
- (format-time-string "%Y-%m-%d"))
- (let ((end (org-taskjuggler-get-end project)))
- (or (and end (format "- %s" end))
- (format "+%sd" org-taskjuggler-default-project-duration)))))
+ (concat
+ ;; Opening project.
+ (format "project %s \"%s\" \"%s\" %s %s {\n"
+ (org-taskjuggler-get-id project info)
+ (org-taskjuggler-get-name project)
+ ;; Version is obtained through :TASKJUGGLER_VERSION:
+ ;; property or `org-taskjuggler-default-project-version'.
+ (or (org-element-property :VERSION project)
+ org-taskjuggler-default-project-version)
+ (or (org-taskjuggler-get-start project)
+ (format-time-string "%Y-%m-%d"))
+ (let ((end (org-taskjuggler-get-end project)))
+ (or (and end (format "- %s" end))
+ (format "+%sd"
+ org-taskjuggler-default-project-duration))))
+ ;; Add attributes.
+ (org-taskjuggler--indent-string
+ (org-taskjuggler--build-attributes
+ project org-taskjuggler-valid-project-attributes))
+ ;; Closing project.
+ "}\n"))
(defun org-taskjuggler--build-resource (resource info)
"Return a resource declaration.
@@ -800,7 +822,9 @@ a unique id will be associated to it."
(if (eq (org-element-property :todo-type task) 'done) "100"
(org-element-property :COMPLETE task)))
(depends (org-taskjuggler-resolve-dependencies task info))
- (effort (org-element-property :EFFORT task))
+ (effort (let ((property
+ (intern (concat ":" (upcase org-effort-property)))))
+ (org-element-property property task)))
(milestone
(or (org-element-property :MILESTONE task)
(not (or (org-element-map (org-element-contents task) 'headline
diff --git a/doc/Makefile b/doc/Makefile
index 234ab7e..2c8a3c5 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -54,8 +54,9 @@ clean-install:
%: %.texi org-version.inc
$(MAKEINFO) --no-split $< -o $@
-%.pdf: LC_ALL=C # work around a bug in texi2dvi
-%.pdf: LANG=C # work around a bug in texi2dvi
+# the following two lines work around a bug in some versions of texi2dvi
+%.pdf: LC_ALL=C
+%.pdf: LANG=C
%.pdf: %.texi org-version.inc
$(TEXI2PDF) $<
%.pdf: %.tex
diff --git a/doc/doclicense.texi b/doc/doclicense.texi
index b0c97cd..aa9288e 100644
--- a/doc/doclicense.texi
+++ b/doc/doclicense.texi
@@ -5,7 +5,7 @@
@c hence no sectioning command or @node.
@display
-Copyright @copyright{} 2000, 2001, 2002, 2007, 2008, 2013 Free Software Foundation, Inc.
+Copyright @copyright{} 2000, 2001, 2002, 2007, 2008, 2013, 2014 Free Software Foundation, Inc.
@uref{http://fsf.org/}
Everyone is permitted to copy and distribute verbatim copies
diff --git a/doc/htmlxref.cnf b/doc/htmlxref.cnf
new file mode 100644
index 0000000..13aa8ce
--- a/dev/null
+++ b/doc/htmlxref.cnf
@@ -0,0 +1,2 @@
+calc mono http://www.gnu.org/software/emacs/manual/html_mono/calc.html
+calc node http://www.gnu.org/software/emacs/manual/html_node/calc/
diff --git a/doc/org.texi b/doc/org.texi
index 8764145..6406a89 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -1,21 +1,17 @@
\input texinfo
@c %**start of header
-@setfilename ../../info/org
+@setfilename ../../info/org.info
@settitle The Org Manual
@include org-version.inc
-@c Use proper quote and backtick for code sections in PDF output
-@c Cf. Texinfo manual 14.2
-@set txicodequoteundirected
-@set txicodequotebacktick
-
@c Version and Contact Info
@set MAINTAINERSITE @uref{http://orgmode.org,maintainers web page}
@set AUTHOR Carsten Dominik
@set MAINTAINER Carsten Dominik
@set MAINTAINEREMAIL @email{carsten at orgmode dot org}
@set MAINTAINERCONTACT @uref{mailto:carsten at orgmode dot org,contact the maintainer}
+@documentencoding UTF-8
@c %**end of header
@finalout
@@ -263,7 +259,7 @@
@copying
This manual is for Org version @value{VERSION}.
-Copyright @copyright{} 2004--2013 Free Software Foundation, Inc.
+Copyright @copyright{} 2004--2014 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -288,8 +284,8 @@ modify this GNU manual.''
@subtitle Release @value{VERSION}
@author by Carsten Dominik
-with contributions by David O'Toole, Bastien Guerry, Philip Rooke, Dan
-Davison, Eric Schulte, Thomas Dye, Jambunathan K and Nicolas Goaziou.
+with contributions by Bastien Guerry, Nicolas Goaziou, Eric Schulte,
+Jambunathan K, Dan Davison, Thomas Dye, David O'Toole, and Philip Rooke.
@c The following two commands start the copyright page.
@page
@@ -297,6 +293,9 @@ Davison, Eric Schulte, Thomas Dye, Jambunathan K and Nicolas Goaziou.
@insertcopying
@end titlepage
+@c Output the short table of contents at the beginning.
+@shortcontents
+
@c Output the table of contents at the beginning.
@contents
@@ -312,23 +311,23 @@ Davison, Eric Schulte, Thomas Dye, Jambunathan K and Nicolas Goaziou.
@menu
* Introduction:: Getting started
-* Document Structure:: A tree works like your brain
+* Document structure:: A tree works like your brain
* Tables:: Pure magic for quick formatting
* Hyperlinks:: Notes in context
-* TODO Items:: Every tree branch can be a TODO item
+* TODO items:: Every tree branch can be a TODO item
* Tags:: Tagging headlines and matching sets of tags
-* Properties and Columns:: Storing information about an entry
-* Dates and Times:: Making items useful for planning
+* Properties and columns:: Storing information about an entry
+* Dates and times:: Making items useful for planning
* Capture - Refile - Archive:: The ins and outs for projects
-* Agenda Views:: Collecting information into views
+* Agenda views:: Collecting information into views
* Markup:: Prepare text for rich export
* Exporting:: Sharing and publishing notes
* Publishing:: Create a web site of linked Org files
-* Working With Source Code:: Export, evaluate, and tangle code blocks
+* Working with source code:: Export, evaluate, and tangle code blocks
* Miscellaneous:: All the rest which did not fit elsewhere
* Hacking:: How to hack your way around
* MobileOrg:: Viewing and capture on a mobile device
-* History and Acknowledgments:: How Org came into being
+* History and acknowledgments:: How Org came into being
* GNU Free Documentation License:: The license for this documentation.
* Main Index:: An index of Org's concepts and features
* Key Index:: Key bindings and where they are described
@@ -367,11 +366,6 @@ Visibility cycling
* Initial visibility:: Setting the initial visibility state
* Catching invisible edits:: Preventing mistakes when editing invisible parts
-Global and local cycling
-
-* Initial visibility:: Setting the initial visibility state
-* Catching invisible edits:: Preventing mistakes when editing invisible parts
-
Tables
* Built-in table editor:: Simple tables
@@ -491,7 +485,7 @@ Capture - Refile - Archive
* Capture:: Capturing new stuff
* Attachments:: Add files to tasks
-* RSS Feeds:: Getting input from RSS feeds
+* RSS feeds:: Getting input from RSS feeds
* Protocols:: External (e.g., Browser) access to Emacs and Org
* Refile and copy:: Moving/copying a tree from one place to another
* Archiving:: What to do with finished projects
@@ -521,7 +515,7 @@ Agenda views
* Presentation and sorting:: How agenda items are prepared for display
* Agenda commands:: Remote editing of Org trees
* Custom agenda views:: Defining special searches and views
-* Exporting Agenda Views:: Writing a view to a file
+* Exporting agenda views:: Writing a view to a file
* Agenda column view:: Using column view for collected entries
The built-in agenda views
@@ -544,7 +538,7 @@ Custom agenda views
* Storing searches:: Type once, use often
* Block agenda:: All the stuff you need in a single buffer
-* Setting Options:: Changing the rules
+* Setting options:: Changing the rules
Markup for rich export
@@ -579,7 +573,7 @@ Embedded @LaTeX{}
Exporting
-* The Export Dispatcher:: The main exporter interface
+* The export dispatcher:: The main exporter interface
* Export back-ends:: Built-in export formats
* Export settings:: Generic export settings
* ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding
@@ -588,9 +582,11 @@ Exporting
* @LaTeX{} and PDF export:: Exporting to @LaTeX{}, and processing to PDF
* Markdown export:: Exporting to Markdown
* OpenDocument Text export:: Exporting to OpenDocument Text
+* Org export:: Exporting to Org
+* Texinfo export:: Exporting to Texinfo
* iCalendar export:: Exporting to iCalendar
-* Other built-in back-ends:: Exporting to @code{Texinfo}, a man page, or Org
-* Export in foreign buffers:: Author tables in lists in Org syntax
+* Other built-in back-ends:: Exporting to a man page
+* Export in foreign buffers:: Author tables and lists in Org syntax
* Advanced configuration:: Fine-tuning the export output
HTML export
@@ -614,7 +610,7 @@ HTML export
* Quoting @LaTeX{} code:: Incorporating literal @LaTeX{} code
* @LaTeX{} specific attributes:: Controlling @LaTeX{} output
-OpenDocument Text export
+OpenDocument text export
* Pre-requisites for ODT export:: What packages ODT exporter relies on
* ODT export commands:: How to invoke ODT export
@@ -641,6 +637,16 @@ Advanced topics in ODT export
* Customizing tables in ODT export:: How to define and use Table templates
* Validating OpenDocument XML:: How to debug corrupt OpenDocument files
+Texinfo export
+
+* Texinfo export commands:: How to invoke Texinfo export
+* Document preamble:: File header, title and copyright page
+* Headings and sectioning structure:: Building document structure
+* Indices:: Creating indices
+* Quoting Texinfo code:: Incorporating literal Texinfo code
+* Texinfo specific attributes:: Controlling Texinfo output
+* An example::
+
Publishing
* Configuration:: Defining projects
@@ -689,14 +695,14 @@ Using header arguments
* System-wide header arguments:: Set global default values
* Language-specific header arguments:: Set default values by language
* Header arguments in Org mode properties:: Set default values for a buffer or heading
-* Language-specific header arguments in Org mode properties:: Set langugage-specific default values for a buffer or heading
+* Language-specific header arguments in Org mode properties:: Set language-specific default values for a buffer or heading
* Code block specific header arguments:: The most common way to set values
* Header arguments in function calls:: The most specific level
Specific header arguments
* var:: Pass arguments to code blocks
-* results:: Specify the type of results and how they will
+* Results:: Specify the type of results and how they will
be collected and handled
* file:: Specify a path for file output
* file-desc:: Specify a description for file results
@@ -732,7 +738,7 @@ Specific header arguments
Miscellaneous
* Completion:: M-TAB knows what you need
-* Easy Templates:: Quick insertion of structural elements
+* Easy templates:: Quick insertion of structural elements
* Speed keys:: Electric commands at the beginning of a headline
* Code evaluation security:: Org mode files evaluate inline code
* Customization:: Adapting Org to your taste
@@ -779,7 +785,7 @@ MobileOrg
@end detailmenu
@end menu
-@node Introduction, Document Structure, Top, Top
+@node Introduction
@chapter Introduction
@cindex introduction
@@ -791,76 +797,63 @@ MobileOrg
* Conventions:: Typesetting conventions in the manual
@end menu
-@node Summary, Installation, Introduction, Introduction
+@node Summary
@section Summary
@cindex summary
-Org is a mode for keeping notes, maintaining TODO lists, and doing
-project planning with a fast and effective plain-text system.
-
-Org develops organizational tasks around NOTES files that contain
-lists or information about projects as plain text. Org is
-implemented on top of Outline mode, which makes it possible to keep the
-content of large files well structured. Visibility cycling and
-structure editing help to work with the tree. Tables are easily created
-with a built-in table editor. Org supports TODO items, deadlines,
-timestamps, and scheduling. It dynamically compiles entries into an
-agenda that utilizes and smoothly integrates much of the Emacs calendar
-and diary. Plain text URL-like links connect to websites, emails,
-Usenet messages, BBDB entries, and any files related to the projects.
-For printing and sharing notes, an Org file can be exported as a
-structured ASCII file, as HTML, or (TODO and agenda items only) as an
-iCalendar file. It can also serve as a publishing tool for a set of
-linked web pages.
-
-As a project planning environment, Org works by adding metadata to outline
-nodes. Based on this data, specific entries can be extracted in queries and
-create dynamic @i{agenda views}.
-
-Org mode contains the Org Babel environment which allows you to work with
-embedded source code blocks in a file, to facilitate code evaluation,
-documentation, and literate programming techniques.
-
-Org's automatic, context-sensitive table editor with spreadsheet
-capabilities can be integrated into any major mode by activating the
-minor Orgtbl mode. Using a translation step, it can be used to maintain
-tables in arbitrary file types, for example in @LaTeX{}. The structure
-editing and list creation capabilities can be used outside Org with
-the minor Orgstruct mode.
-
-Org keeps simple things simple. When first fired up, it should
-feel like a straightforward, easy to use outliner. Complexity is not
-imposed, but a large amount of functionality is available when you need
-it. Org is a toolbox and can be used in different ways and for different
-ends, for example:
-
-@example
-@r{@bullet{} an outline extension with visibility cycling and structure editing}
-@r{@bullet{} an ASCII system and table editor for taking structured notes}
-@r{@bullet{} a TODO list editor}
-@r{@bullet{} a full agenda and planner with deadlines and work scheduling}
-@pindex GTD, Getting Things Done
-@r{@bullet{} an environment in which to implement David Allen's GTD system}
-@r{@bullet{} a simple hypertext system, with HTML and @LaTeX{} export}
-@r{@bullet{} a publishing tool to create a set of interlinked web pages}
-@r{@bullet{} an environment for literate programming}
-@end example
+Org is a mode for keeping notes, maintaining TODO lists, and project planning
+with a fast and effective plain-text system. It also is an authoring system
+with unique support for literate programming and reproducible research.
+
+Org is implemented on top of Outline mode, which makes it possible to keep
+the content of large files well structured. Visibility cycling and structure
+editing help to work with the tree. Tables are easily created with a
+built-in table editor. Plain text URL-like links connect to websites,
+emails, Usenet messages, BBDB entries, and any files related to the projects.
+
+Org develops organizational tasks around notes files that contain lists or
+information about projects as plain text. Project planning and task
+management makes use of metadata which is part of an outline node. Based on
+this data, specific entries can be extracted in queries and create dynamic
+@i{agenda views} that also integrate the Emacs calendar and diary. Org can
+be used to implement many different project planning schemes, such as David
+Allen's GTD system.
+
+Org files can serve as a single source authoring system with export to many
+different formats such as HTML, @LaTeX{}, Open Document, and Markdown. New
+export backends can be derived from existing ones, or defined from scratch.
+
+Org files can include source code blocks, which makes Org uniquely suited for
+authoring technical documents with code examples. Org source code blocks are
+fully functional; they can be evaluated in place and their results can be
+captured in the file. This makes it possible to create a single file
+reproducible research compendium.
+
+Org keeps simple things simple. When first fired up, it should feel like a
+straightforward, easy to use outliner. Complexity is not imposed, but a
+large amount of functionality is available when needed. Org is a toolbox.
+Many users usilize only a (very personal) fraction of Org's capabilities, and
+know that there is more whenever they need it.
+
+All of this is achieved with strictly plain text files, the most portable and
+future-proof file format. Org runs in Emacs. Emacs is one of the most
+widely ported programs, so that Org mode is available on every major
+platform.
@cindex FAQ
There is a website for Org which provides links to the newest
version of Org, as well as additional information, frequently asked
questions (FAQ), links to tutorials, etc. This page is located at
@uref{http://orgmode.org}.
-
@cindex print edition
-The version 7.3 of this manual is available as a
-@uref{http://www.network-theory.co.uk/org/manual/, paperback book from Network
-Theory Ltd.}
-@page
+An earlier version (7.3) of this manual is available as a
+@uref{http://www.network-theory.co.uk/org/manual/, paperback book from
+Network Theory Ltd.}
+@page
-@node Installation, Activation, Summary, Introduction
+@node Installation
@section Installation
@cindex installation
@cindex XEmacs
@@ -881,7 +874,11 @@ We @b{strongly recommend} to stick to a single installation method.
Recent Emacs distributions include a packaging system which lets you install
Elisp libraries. You can install Org with @kbd{M-x package-install RET org}.
-You need to do this in a session where no @code{.org} file has been visited.
+
+@noindent @b{Important}: you need to do this in a session where no @code{.org} file has
+been visited, i.e. where no Org built-in function have been loaded.
+Otherwise autoload Org functions will mess up the installation.
+
Then, to make sure your Org configuration is taken into account, initialize
the package system with @code{(package-initialize)} in your @file{.emacs}
before setting any Org option. If you want to use Org's package repository,
@@ -933,7 +930,7 @@ For more detailed explanations on Org's build system, please check the Org
Build System page on @uref{http://orgmode.org/worg/dev/org-build-system.html,
Worg}.
-@node Activation, Feedback, Installation, Introduction
+@node Activation
@section Activation
@cindex activation
@cindex autoload
@@ -967,15 +964,14 @@ suggested bindings for these keys, please modify the keys to your own
liking.
@lisp
(global-set-key "\C-cl" 'org-store-link)
-(global-set-key "\C-cc" 'org-capture)
(global-set-key "\C-ca" 'org-agenda)
+(global-set-key "\C-cc" 'org-capture)
(global-set-key "\C-cb" 'org-iswitchb)
@end lisp
@cindex Org mode, turning on
-With this setup, all files with extension @samp{.org} will be put
-into Org mode. As an alternative, make the first line of a file look
-like this:
+To turn on Org mode in a file that does not have the extension @file{.org},
+make the first line of a file look like this:
@example
MY PROJECTS -*- mode: org; -*-
@@ -997,7 +993,7 @@ in Emacs 22 you need to do this yourself with
active region by using the mouse to select a region, or pressing
@kbd{C-@key{SPC}} twice before moving the cursor.
-@node Feedback, Conventions, Activation, Introduction
+@node Feedback
@section Feedback
@cindex feedback
@cindex bug reports
@@ -1006,6 +1002,8 @@ active region by using the mouse to select a region, or pressing
If you find problems with Org, or if you have questions, remarks, or ideas
about it, please mail to the Org mailing list @email{emacs-orgmode@@gnu.org}.
+You can subscribe to the list
+@uref{https://lists.gnu.org/mailman/listinfo/emacs-orgmode, on this web page}.
If you are not a member of the mailing list, your mail will be passed to the
list after a moderator has approved it@footnote{Please consider subscribing
to the mailing list, in order to minimize the work the mailing list
@@ -1022,7 +1020,7 @@ version information of Emacs (@kbd{M-x emacs-version @key{RET}}) and Org
@kbd{M-x org-submit-bug-report RET}
@end example
@noindent which will put all this information into an Emacs mail buffer so
-that you only need to add your description. If you re not sending the Email
+that you only need to add your description. If you are not sending the Email
from within Emacs, please copy and paste the content into your Email program.
Sometimes you might face a problem due to an error in your Emacs or Org mode
@@ -1096,7 +1094,7 @@ screen. Save this buffer to a file (for example using @kbd{C-x C-w}) and
attach it to your bug report.
@end enumerate
-@node Conventions, , Feedback, Introduction
+@node Conventions
@section Typesetting conventions used in this manual
@subsubheading TODO keywords, tags, properties, etc.
@@ -1132,9 +1130,10 @@ templates insert lowercase keywords and Babel dynamically inserts
@kindex C-c c
@findex org-capture
-The manual suggests two global keybindings: @kbd{C-c a} for @code{org-agenda}
-and @kbd{C-c c} for @code{org-capture}. These are only suggestions, but the
-rest of the manual assumes that you are using these keybindings.
+The manual suggests a few global keybindings, in particular @kbd{C-c a} for
+@code{org-agenda} and @kbd{C-c c} for @code{org-capture}. These are only
+suggestions, but the rest of the manual assumes that these keybindings are in
+place in order to list commands by key access.
Also, the manual lists both the keys and the corresponding commands for
accessing a functionality. Org mode often uses the same key for different
@@ -1147,7 +1146,7 @@ will be listed to call @code{org-table-move-column-right}. If you prefer,
you can compile the manual without the command names by unsetting the flag
@code{cmdnames} in @file{org.texi}.
-@node Document Structure, Tables, Introduction, Top
+@node Document structure
@chapter Document structure
@cindex document structure
@cindex structure of document
@@ -1170,7 +1169,7 @@ edit the structure of the document.
* Org syntax:: Formal description of Org's syntax
@end menu
-@node Outlines, Headlines, Document Structure, Document Structure
+@node Outlines
@section Outlines
@cindex outlines
@cindex Outline mode
@@ -1184,7 +1183,7 @@ currently being worked on. Org greatly simplifies the use of
outlines by compressing the entire show/hide functionality into a single
command, @command{org-cycle}, which is bound to the @key{TAB} key.
-@node Headlines, Visibility cycling, Outlines, Document Structure
+@node Headlines
@section Headlines
@cindex headlines
@cindex outline tree
@@ -1221,7 +1220,7 @@ least two empty lines, one empty line will remain visible after folding
the subtree, in order to structure the collapsed view. See the
variable @code{org-cycle-separator-lines} to modify this behavior.
-@node Visibility cycling, Motion, Headlines, Document Structure
+@node Visibility cycling
@section Visibility cycling
@cindex cycling, visibility
@cindex visibility cycling
@@ -1235,7 +1234,7 @@ variable @code{org-cycle-separator-lines} to modify this behavior.
* Catching invisible edits:: Preventing mistakes when editing invisible parts
@end menu
-@node Global and local cycling, Initial visibility, Visibility cycling, Visibility cycling
+@node Global and local cycling
@subsection Global and local cycling
Outlines make it possible to hide parts of the text in the buffer.
@@ -1283,6 +1282,9 @@ When @kbd{S-@key{TAB}} is called with a numeric prefix argument N, the
CONTENTS view up to headlines of level N will be shown. Note that inside
tables, @kbd{S-@key{TAB}} jumps to the previous field.
+@cindex set startup visibility, command
+@orgcmd{C-u C-u @key{TAB},org-set-startup-visibility}
+Switch back to the startup visibility of the buffer (@pxref{Initial visibility}).
@cindex show all, command
@orgcmd{C-u C-u C-u @key{TAB},show-all}
Show all, including drawers.
@@ -1302,30 +1304,18 @@ Expose all the headings of the subtree, CONTENT view for just one subtree.
Expose all direct children of the subtree. With a numeric prefix argument N,
expose all children down to level N@.
@orgcmd{C-c C-x b,org-tree-to-indirect-buffer}
-Show the current subtree in an indirect buffer@footnote{The indirect
-buffer
-@ifinfo
-(@pxref{Indirect Buffers,,,emacs,GNU Emacs Manual})
-@end ifinfo
-@ifnotinfo
-(see the Emacs manual for more information about indirect buffers)
-@end ifnotinfo
-will contain the entire buffer, but will be narrowed to the current
-tree. Editing the indirect buffer will also change the original buffer,
-but without affecting visibility in that buffer.}. With a numeric
-prefix argument N, go up to level N and then take that tree. If N is
-negative then go up that many levels. With a @kbd{C-u} prefix, do not remove
-the previously used indirect buffer.
+Show the current subtree in an indirect buffer@footnote{The indirect buffer
+(@pxref{Indirect Buffers,,,emacs,GNU Emacs Manual}) will contain the entire
+buffer, but will be narrowed to the current tree. Editing the indirect
+buffer will also change the original buffer, but without affecting visibility
+in that buffer.}. With a numeric prefix argument N, go up to level N and
+then take that tree. If N is negative then go up that many levels. With a
+@kbd{C-u} prefix, do not remove the previously used indirect buffer.
@orgcmd{C-c C-x v,org-copy-visible}
Copy the @i{visible} text in the region into the kill ring.
@end table
-@menu
-* Initial visibility:: Setting the initial visibility state
-* Catching invisible edits:: Preventing mistakes when editing invisible parts
-@end menu
-
-@node Initial visibility, Catching invisible edits, Global and local cycling, Visibility cycling
+@node Initial visibility
@subsection Initial visibility
@cindex visibility, initialize
@@ -1340,7 +1330,7 @@ When Emacs first visits an Org file, the global state is set to OVERVIEW,
i.e., only the top level headlines are visible@footnote{When
@code{org-agenda-inhibit-startup} is non-@code{nil}, Org will not honor the default
visibility state when first opening a file for the agenda (@pxref{Speeding up
-your agendas}).} This can be configured through the variable
+your agendas}).}. This can be configured through the variable
@code{org-startup-folded}, or on a per-file basis by adding one of the
following lines anywhere in the buffer:
@@ -1358,7 +1348,7 @@ the startup visibility, set @code{org-agenda-inhibit-startup} to @code{nil}.
@cindex property, VISIBILITY
@noindent
Furthermore, any entries with a @samp{VISIBILITY} property (@pxref{Properties
-and Columns}) will get their visibility adapted accordingly. Allowed values
+and columns}) will get their visibility adapted accordingly. Allowed values
for this property are @code{folded}, @code{children}, @code{content}, and
@code{all}.
@@ -1369,18 +1359,18 @@ requested by startup options and @samp{VISIBILITY} properties in individual
entries.
@end table
-@node Catching invisible edits, , Initial visibility, Visibility cycling
+@node Catching invisible edits
@subsection Catching invisible edits
@vindex org-catch-invisible-edits
@cindex edits, catching invisible
Sometimes you may inadvertently edit an invisible part of the buffer and be
-confused on what as been edited and how to undo the mistake. Setting
+confused on what has been edited and how to undo the mistake. Setting
@code{org-catch-invisible-edits} to non-@code{nil} will help prevent this. See the
docstring of this option on how Org should catch invisible edits and process
them.
-@node Motion, Structure editing, Visibility cycling, Document Structure
+@node Motion
@section Motion
@cindex motion, between headlines
@cindex jumping, to headlines
@@ -1420,7 +1410,7 @@ q @r{Quit}
See also the option @code{org-goto-interface}.
@end table
-@node Structure editing, Sparse trees, Motion, Document Structure
+@node Structure editing
@section Structure editing
@cindex structure editing
@cindex headline, promotion and demotion
@@ -1436,20 +1426,24 @@ See also the option @code{org-goto-interface}.
@table @asis
@orgcmd{M-@key{RET},org-insert-heading}
@vindex org-M-RET-may-split-line
-Insert a new heading/item with the same level than the one at point.
-If the cursor is in a plain list item, a new item is created
-(@pxref{Plain lists}). To prevent this behavior in lists, call the
-command with a prefix argument. When this command is used in the
-middle of a line, the line is split and the rest of the line becomes
-the new item or headline@footnote{If you do not want the line to be
-split, customize the variable @code{org-M-RET-may-split-line}.}. If
-the command is used at the @emph{beginning} of a headline, the new
-headline is created before the current line. If the command is used
-at the @emph{end} of a folded subtree (i.e., behind the ellipses at
-the end of a headline), then a headline will be
-inserted after the end of the subtree. Calling this command with
-@kbd{C-u C-u} will unconditionally respect the headline's content and
-create a new item at the end of the parent subtree.
+Insert a new heading/item with the same level as the one at point.
+
+If the cursor is in a plain list item, a new item is created (@pxref{Plain
+lists}). To prevent this behavior in lists, call the command with one prefix
+argument. When this command is used in the middle of a line, the line is
+split and the rest of the line becomes the new item or headline. If you do
+not want the line to be split, customize @code{org-M-RET-may-split-line}.
+
+If the command is used at the @emph{beginning} of a line, and if there is a
+heading or an item at point, the new heading/item is created @emph{before}
+the current line. If the command is used at the @emph{end} of a folded
+subtree (i.e., behind the ellipses at the end of a headline), then a headline
+will be inserted after the end of the subtree.
+
+Calling this command with @kbd{C-u C-u} will unconditionally respect the
+headline's content and create a new item at the end of the parent subtree.
+
+If point is at the beginning of a normal line, turn this line into a heading.
@orgcmd{C-@key{RET},org-insert-heading-respect-content}
Just like @kbd{M-@key{RET}}, except when adding a new heading below the
current heading, the new heading is placed after the body instead of before
@@ -1557,7 +1551,7 @@ inside a table (@pxref{Tables}), the Meta-Cursor keys have different
functionality.
-@node Sparse trees, Plain lists, Structure editing, Document Structure
+@node Sparse trees
@section Sparse trees
@cindex sparse trees
@cindex trees, sparse
@@ -1577,7 +1571,7 @@ variables @code{org-show-hierarchy-above}, @code{org-show-following-heading},
control on how much context is shown around each match.}. Just try it out
and you will see immediately how it works.
-Org mode contains several commands creating such trees, all these
+Org mode contains several commands for creating such trees, all these
commands can be accessed through a dispatcher:
@table @asis
@@ -1630,7 +1624,7 @@ XEmacs uses selective display for outlining, not text properties.}.
Or you can use @kbd{C-c C-e C-v} to export only the visible part of
the document and print the resulting file.
-@node Plain lists, Drawers, Sparse trees, Document Structure
+@node Plain lists
@section Plain lists
@cindex plain lists
@cindex lists, plain
@@ -1717,7 +1711,7 @@ blocks can be indented to signal that they belong to a particular item.
If you find that using a different bullet for a sub-list (than that used for
the current list-level) improves readability, customize the variable
@code{org-list-demote-modify-bullet}. To get a greater difference of
-indentation between items and theirs sub-items, customize
+indentation between items and their sub-items, customize
@code{org-list-indent-offset}.
@vindex org-list-automatic-rules
@@ -1755,7 +1749,7 @@ one.
@table @kbd
@kindex M-S-@key{RET}
-@item M-S-RET
+@item M-S-@key{RET}
Insert a new item with a checkbox (@pxref{Checkboxes}).
@kindex S-@key{down}
@item S-up
@@ -1784,8 +1778,8 @@ is automatic.
Decrease/increase the indentation of an item, leaving children alone.
@kindex M-S-@key{left}
@kindex M-S-@key{right}
-@item M-S-left
-@itemx M-S-right
+@item M-S-@key{left}
+@itemx M-S-@key{right}
Decrease/increase the indentation of the item, including subitems.
Initially, the item tree is selected based on current indentation. When
these commands are executed several times in direct succession, the initially
@@ -1838,20 +1832,17 @@ numerically, alphabetically, by time, by checked status for check lists,
or by a custom function.
@end table
-@node Drawers, Blocks, Plain lists, Document Structure
+@node Drawers
@section Drawers
@cindex drawers
-@cindex #+DRAWERS
@cindex visibility cycling, drawers
-@vindex org-drawers
@cindex org-insert-drawer
@kindex C-c C-x d
Sometimes you want to keep information associated with an entry, but you
-normally don't want to see it. For this, Org mode has @emph{drawers}.
-Drawers need to be configured with the option @code{org-drawers}@footnote{You
-can define additional drawers on a per-file basis with a line like
-@code{#+DRAWERS: HIDDEN STATE}}. Drawers look like this:
+normally don't want to see it. For this, Org mode has @emph{drawers}. They
+can contain anything but a headline and another drawer. Drawers look like
+this:
@example
** This is a headline
@@ -1873,10 +1864,11 @@ Visibility cycling (@pxref{Visibility cycling}) on the headline will hide and
show the entry, but keep the drawer collapsed to a single line. In order to
look inside the drawer, you need to move the cursor to the drawer line and
press @key{TAB} there. Org mode uses the @code{PROPERTIES} drawer for
-storing properties (@pxref{Properties and Columns}), and you can also arrange
+storing properties (@pxref{Properties and columns}), and you can also arrange
for state change notes (@pxref{Tracking TODO state changes}) and clock times
(@pxref{Clocking work time}) to be stored in a drawer @code{LOGBOOK}. If you
-want to store a quick note in the LOGBOOK drawer, in a similar way to state changes, use
+want to store a quick note in the LOGBOOK drawer, in a similar way to state
+changes, use
@table @kbd
@kindex C-c C-z
@@ -1885,12 +1877,13 @@ Add a time-stamped note to the LOGBOOK drawer.
@end table
@vindex org-export-with-drawers
+@vindex org-export-with-properties
You can select the name of the drawers which should be exported with
@code{org-export-with-drawers}. In that case, drawer contents will appear in
-export output. Property drawers are not affected by this variable and are
-never exported.
+export output. Property drawers are not affected by this variable: configure
+@code{org-export-with-properties} instead.
-@node Blocks, Footnotes, Drawers, Document Structure
+@node Blocks
@section Blocks
@vindex org-hide-block-startup
@@ -1909,7 +1902,7 @@ or on a per-file basis by using
#+STARTUP: nohideblocks
@end example
-@node Footnotes, Orgstruct mode, Blocks, Document Structure
+@node Footnotes
@section Footnotes
@cindex footnotes
@@ -2016,7 +2009,7 @@ Footnote labels are also links to the corresponding definition/reference, and
you can use the usual commands to follow these links.
@end table
-@node Orgstruct mode, Org syntax, Footnotes, Document Structure
+@node Orgstruct mode
@section The Orgstruct minor mode
@cindex Orgstruct mode
@cindex minor mode for structure editing
@@ -2051,7 +2044,7 @@ Lisp files, you will be able to fold and unfold headlines in Emacs Lisp
commented lines. Some commands like @code{org-demote} are disabled when the
prefix is set, but folding/unfolding will work correctly.
-@node Org syntax, , Orgstruct mode, Document Structure
+@node Org syntax
@section Org syntax
@cindex Org syntax
@@ -2073,7 +2066,7 @@ abstract structure. The export engine relies on the information stored in
this list. Most interactive commands (e.g., for structure editing) also
rely on the syntactic meaning of the surrounding context.
-@node Tables, Hyperlinks, Document Structure, Top
+@node Tables
@chapter Tables
@cindex tables
@cindex editing tables
@@ -2091,7 +2084,7 @@ calculations are supported using the Emacs @file{calc} package
* Org-Plot:: Plotting from org tables
@end menu
-@node Built-in table editor, Column width and alignment, Tables, Tables
+@node Built-in table editor
@section The built-in table editor
@cindex table editor, built-in
@@ -2140,12 +2133,13 @@ unpredictable for you, configure the options
@table @kbd
@tsubheading{Creation and conversion}
@orgcmd{C-c |,org-table-create-or-convert-from-region}
-Convert the active region to table. If every line contains at least one
+Convert the active region to a table. If every line contains at least one
TAB character, the function assumes that the material is tab separated.
If every line contains a comma, comma-separated values (CSV) are assumed.
If not, lines are split at whitespace into fields. You can use a prefix
argument to force a specific separator: @kbd{C-u} forces CSV, @kbd{C-u
-C-u} forces TAB, and a numeric argument N indicates that at least N
+C-u} forces TAB, @kbd{C-u C-u C-u} will prompt for a regular expression to
+match the separator, and a numeric argument N indicates that at least N
consecutive spaces, or alternatively a TAB will be the separator.
@*
If there is no active region, this command creates an empty Org
@@ -2307,7 +2301,7 @@ it off with
@noindent Then the only table command that still works is
@kbd{C-c C-c} to do a manual re-align.
-@node Column width and alignment, Column groups, Built-in table editor, Tables
+@node Column width and alignment
@section Column width and alignment
@cindex narrow columns in tables
@cindex alignment in tables
@@ -2367,7 +2361,7 @@ also combine alignment and field width like this: @samp{<r10>}.
Lines which only contain these formatting cookies will be removed
automatically when exporting the document.
-@node Column groups, Orgtbl mode, Column width and alignment, Tables
+@node Column groups
@section Column groups
@cindex grouping columns in tables
@@ -2403,7 +2397,7 @@ every vertical line you would like to have:
| / | < | | | < | |
@end example
-@node Orgtbl mode, The spreadsheet, Column groups, Tables
+@node Orgtbl mode
@section The Orgtbl minor mode
@cindex Orgtbl mode
@cindex minor mode for tables
@@ -2424,7 +2418,7 @@ construct @LaTeX{} tables with the underlying ease and power of
Orgtbl mode, including spreadsheet capabilities. For details, see
@ref{Tables in arbitrary syntax}.
-@node The spreadsheet, Org-Plot, Orgtbl mode, Tables
+@node The spreadsheet
@section The spreadsheet
@cindex calculations, in tables
@cindex spreadsheet capabilities
@@ -2453,7 +2447,7 @@ formula, moving these references by arrow keys
* Advanced features:: Field and column names, parameters and automatic recalc
@end menu
-@node References, Formula syntax for Calc, The spreadsheet, The spreadsheet
+@node References
@subsection References
@cindex references
@@ -2539,7 +2533,7 @@ format at least for the first field (i.e the reference must start with
@example
$1..$3 @r{first three fields in the current row}
$P..$Q @r{range, using column names (see under Advanced)}
-$<<<..$>> @r{start in third column, continue to the one but last}
+$<<<..$>> @r{start in third column, continue to the last but one}
@@2$1..@@4$3 @r{6 fields between these two fields (same as @code{A2..C4})}
@@-1$-2..@@-1 @r{3 fields in the row above, starting from 2 columns on the left}
@@I..II @r{between first and second hline, short for @code{@@I..@@II}}
@@ -2557,21 +2551,28 @@ for Calc}.
@cindex row, of field coordinates
@cindex column, of field coordinates
-For Calc formulas and Lisp formulas @code{@@#} and @code{$#} can be used to
-get the row or column number of the field where the formula result goes.
-The traditional Lisp formula equivalents are @code{org-table-current-dline}
-and @code{org-table-current-column}. Examples:
+One of the very first actions during evaluation of Calc formulas and Lisp
+formulas is to substitute @code{@@#} and @code{$#} in the formula with the
+row or column number of the field where the current result will go to. The
+traditional Lisp formula equivalents are @code{org-table-current-dline} and
+@code{org-table-current-column}. Examples:
-@example
-if(@@# % 2, $#, string("")) @r{column number on odd lines only}
-$3 = remote(FOO, @@@@#$2) @r{copy column 2 from table FOO into}
- @r{column 3 of the current table}
-@end example
+@table @code
+@item if(@@# % 2, $#, string(""))
+Insert column number on odd rows, set field to empty on even rows.
+@item $2 = '(identity remote(FOO, @@@@#$1))
+Copy text or values of each row of column 1 of the table named @code{FOO}
+into column 2 of the current table.
+@item @@3 = 2 * remote(FOO, @@1$$#)
+Insert the doubled value of each column of row 1 of the table named
+@code{FOO} into row 3 of the current table.
+@end table
-@noindent For the second example, table FOO must have at least as many rows
-as the current table. Note that this is inefficient@footnote{The computation time scales as
-O(N^2) because table FOO is parsed for each field to be copied.} for large
-number of rows.
+@noindent For the second/third example, the table named @code{FOO} must have
+at least as many rows/columns as the current table. Note that this is
+inefficient@footnote{The computation time scales as O(N^2) because the table
+named @code{FOO} is parsed for each field to be read.} for large number of
+rows/columns.
@subsubheading Named references
@cindex named references
@@ -2593,7 +2594,7 @@ line like
@noindent
@vindex constants-unit-system
@pindex constants.el
-Also properties (@pxref{Properties and Columns}) can be used as
+Also properties (@pxref{Properties and columns}) can be used as
constants in table formulas: for a property @samp{:Xyz:} use the name
@samp{$PROP_Xyz}, and the property will be searched in the current
outline entry and in the hierarchy above it. If you have the
@@ -2632,7 +2633,13 @@ table in that entry. REF is an absolute field or range reference as
described above for example @code{@@3$3} or @code{$somename}, valid in the
referenced table.
-@node Formula syntax for Calc, Formula syntax for Lisp, References, The spreadsheet
+Indirection of NAME-OR-ID: When NAME-OR-ID has the format @code{@@ROW$COLUMN}
+it will be substituted with the name or ID found in this field of the current
+table. For example @code{remote($1, @@>$2)} => @code{remote(year_2013,
+@@>$1)}. The format @code{B3} is not supported because it can not be
+distinguished from a plain table name or ID.
+
+@node Formula syntax for Calc
@subsection Formula syntax for Calc
@cindex formula syntax, Calc
@cindex syntax, of formulas
@@ -2722,9 +2729,11 @@ Operations, , Logical Operations, calc, GNU Emacs Calc Manual}). For example
@item if($1 < 20, teen, string(""))
"teen" if age $1 is less than 20, else the Org table result field is set to
empty with the empty string.
-@item if("$1" == "nan" || "$2" == "nan", string(""), $1 + $2); E
+@item if("$1" == "nan" || "$2" == "nan", string(""), $1 + $2); E f-1
Sum of the first two columns. When at least one of the input fields is empty
-the Org table result field is set to empty.
+the Org table result field is set to empty. @samp{E} is required to not
+convert empty fields to 0. @samp{f-1} is an optional Calc format string
+similar to @samp{%.1f} but leaves empty results empty.
@item if(typeof(vmean($1..$7)) == 12, string(""), vmean($1..$7); E
Mean value of a range unless there is any empty field. Every field in the
range that is empty is replaced by @samp{nan} which lets @samp{vmean} result
@@ -2745,7 +2754,7 @@ should be padded with 0 to the full size.
You can add your own Calc functions defined in Emacs Lisp with @code{defmath}
and use them in formula syntax for Calc.
-@node Formula syntax for Lisp, Durations and time values, Formula syntax for Calc, The spreadsheet
+@node Formula syntax for Lisp
@subsection Emacs Lisp forms as formulas
@cindex Lisp forms, as table formulas
@@ -2781,7 +2790,7 @@ Add columns 1 and 2, equivalent to Calc's @code{$1+$2}.
Compute the sum of columns 1 to 4, like Calc's @code{vsum($1..$4)}.
@end table
-@node Durations and time values, Field and range formulas, Formula syntax for Lisp, The spreadsheet
+@node Durations and time values
@subsection Durations and time values
@cindex Duration, computing
@cindex Time, computing
@@ -2800,7 +2809,7 @@ formulas or Elisp formulas:
@end group
@end example
-Input duration values must be of the form @code{[HH:MM[:SS]}, where seconds
+Input duration values must be of the form @code{HH:MM[:SS]}, where seconds
are optional. With the @code{T} flag, computed durations will be displayed
as @code{HH:MM:SS} (see the first formula above). With the @code{t} flag,
computed durations will be displayed according to the value of the option
@@ -2811,7 +2820,7 @@ example above).
Negative duration values can be manipulated as well, and integers will be
considered as seconds in addition and subtraction.
-@node Field and range formulas, Column formulas, Durations and time values, The spreadsheet
+@node Field and range formulas
@subsection Field and range formulas
@cindex field formula
@cindex range formula
@@ -2828,13 +2837,13 @@ current field will be replaced with the result.
Formulas are stored in a special line starting with @samp{#+TBLFM:} directly
below the table. If you type the equation in the 4th field of the 3rd data
line in the table, the formula will look like @samp{@@3$4=$1+$2}. When
-inserting/deleting/swapping column and rows with the appropriate commands,
+inserting/deleting/swapping columns and rows with the appropriate commands,
@i{absolute references} (but not relative ones) in stored formulas are
-modified in order to still reference the same field. To avoid this from
-happening, in particular in range references, anchor ranges at the table
-borders (using @code{@@<}, @code{@@>}, @code{$<}, @code{$>}), or at hlines
-using the @code{@@I} notation. Automatic adaptation of field references does
-of course not happen if you edit the table structure with normal editing
+modified in order to still reference the same field. To avoid this, in
+particular in range references, anchor ranges at the table borders (using
+@code{@@<}, @code{@@>}, @code{$<}, @code{$>}), or at hlines using the
+@code{@@I} notation. Automatic adaptation of field references does of course
+not happen if you edit the table structure with normal editing
commands---then you must fix the equations yourself.
Instead of typing an equation into the field, you may also use the following
@@ -2867,7 +2876,7 @@ can also be used to assign a formula to some but not all fields in a row.
Named field, see @ref{Advanced features}.
@end table
-@node Column formulas, Lookup functions, Field and range formulas, The spreadsheet
+@node Column formulas
@subsection Column formulas
@cindex column formula
@cindex formula, for table column
@@ -2891,7 +2900,7 @@ and the current field replaced with the result. If the field contains only
@samp{=}, the previously stored formula for this column is used. For each
column, Org will only remember the most recently used formula. In the
@samp{#+TBLFM:} line, column formulas will look like @samp{$4=$1+$2}. The
-left-hand side of a column formula can not be the name of column, it must be
+left-hand side of a column formula cannot be the name of column, it must be
the numeric column reference or @code{$>}.
Instead of typing an equation into the field, you may also use the
@@ -2906,7 +2915,7 @@ stores it. With a numeric prefix argument(e.g., @kbd{C-5 C-c =}) the command
will apply it to that many consecutive fields in the current column.
@end table
-@node Lookup functions, Editing and debugging formulas, Column formulas, The spreadsheet
+@node Lookup functions
@subsection Lookup functions
@cindex lookup functions in tables
@cindex table lookup functions
@@ -2950,7 +2959,7 @@ matching cells, rank results, group data etc. For practical examples
see @uref{http://orgmode.org/worg/org-tutorials/org-lookups.html, this
tutorial on Worg}.
-@node Editing and debugging formulas, Updating the table, Lookup functions, The spreadsheet
+@node Editing and debugging formulas
@subsection Editing and debugging formulas
@cindex formula editing
@cindex editing, of table formulas
@@ -3101,7 +3110,7 @@ turn on formula debugging in the @code{Tbl} menu and repeat the
calculation, for example by pressing @kbd{C-u C-u C-c = @key{RET}} in a
field. Detailed information will be displayed.
-@node Updating the table, Advanced features, Editing and debugging formulas, The spreadsheet
+@node Updating the table
@subsection Updating the table
@cindex recomputing table fields
@cindex updating, table
@@ -3138,7 +3147,7 @@ Iterate all tables in the current buffer, in order to converge table-to-table
dependencies.
@end table
-@node Advanced features, , Updating the table, The spreadsheet
+@node Advanced features
@subsection Advanced features
If you want the recalculation of fields to happen automatically, or if you
@@ -3243,7 +3252,7 @@ functions.
@end group
@end example
-@node Org-Plot, , The spreadsheet, Tables
+@node Org-Plot
@section Org-Plot
@cindex graph, in tables
@cindex plot tables using Gnuplot
@@ -3328,7 +3337,7 @@ may still want to specify the plot type, as that can impact the content of
the data file.
@end table
-@node Hyperlinks, TODO Items, Tables, Top
+@node Hyperlinks
@chapter Hyperlinks
@cindex hyperlinks
@@ -3346,7 +3355,7 @@ other files, Usenet articles, emails, and much more.
* Custom searches:: When the default search is not enough
@end menu
-@node Link format, Internal links, Hyperlinks, Hyperlinks
+@node Link format
@section Link format
@cindex link format
@cindex format, of links
@@ -3377,7 +3386,7 @@ missing bracket hides the link internals again. To show the
internal structure of all links, use the menu entry
@code{Org->Hyperlinks->Literal links}.
-@node Internal links, External links, Link format, Hyperlinks
+@node Internal links
@section Internal links
@cindex internal links
@cindex links, internal
@@ -3402,8 +3411,8 @@ a @i{dedicated target}: the same string in double angular brackets, like
@cindex #+NAME
If no dedicated target exists, the link will then try to match the exact name
of an element within the buffer. Naming is done with the @code{#+NAME}
-keyword, which has to be put the line before the element it refers to, as in
-the following example
+keyword, which has to be put in the line before the element it refers to, as
+in the following example
@example
#+NAME: My Target
@@ -3448,7 +3457,7 @@ earlier.
* Radio targets:: Make targets trigger links in plain text
@end menu
-@node Radio targets, , Internal links, Internal links
+@node Radio targets
@subsection Radio targets
@cindex radio targets
@cindex targets, radio
@@ -3464,7 +3473,7 @@ for radio targets only when the file is first loaded into Emacs. To
update the target list during editing, press @kbd{C-c C-c} with the
cursor on or at a target.
-@node External links, Handling links, Internal links, Hyperlinks
+@node External links
@section External links
@cindex links, external
@cindex external links
@@ -3565,7 +3574,7 @@ as links. If spaces must be part of the link (for example in
@samp{bbdb:Richard Stallman}), or if you need to remove ambiguities
about the end of the link, enclose them in square brackets.
-@node Handling links, Using links outside Org, External links, Hyperlinks
+@node Handling links
@section Handling links
@cindex links, handling
@@ -3639,7 +3648,7 @@ entry referenced by the current line.
@cindex completion, of links
@cindex inserting links
@vindex org-keep-stored-link-after-insertion
-Insert a link@footnote{ Note that you don't have to use this command to
+Insert a link@footnote{Note that you don't have to use this command to
insert a link. Links in Org are plain text, and you can type or paste them
straight into the buffer. By using this command, the links are automatically
enclosed in double brackets, and you will be asked for the optional
@@ -3761,7 +3770,7 @@ to @kbd{C-n} and @kbd{C-p}
@end lisp
@end table
-@node Using links outside Org, Link abbreviations, Handling links, Hyperlinks
+@node Using links outside Org
@section Using links outside Org
You can insert and follow links that have Org syntax not only in
@@ -3774,7 +3783,7 @@ yourself):
(global-set-key "\C-c o" 'org-open-at-point-global)
@end lisp
-@node Link abbreviations, Search options, Using links outside Org, Hyperlinks
+@node Link abbreviations
@section Link abbreviations
@cindex link abbreviations
@cindex abbreviation, links
@@ -3813,7 +3822,7 @@ url-encode the tag (see the example above, where we need to encode
the URL parameter.) Using @samp{%(my-function)} will pass the tag
to a custom function, and replace it by the resulting string.
-If the replacement text don't contain any specifier, it will simply
+If the replacement text doesn't contain any specifier, it will simply
be appended to the string in order to create the link.
Instead of a string, you may also specify a function that will be
@@ -3843,7 +3852,7 @@ complete link abbreviations. You may also define a function
support for inserting such a link with @kbd{C-c C-l}. Such a function should
not accept any arguments, and return the full link with prefix.
-@node Search options, Custom searches, Link abbreviations, Hyperlinks
+@node Search options
@section Search options in file links
@cindex search option in file links
@cindex file links, searching
@@ -3875,7 +3884,7 @@ Jump to line 255.
Search for a link target @samp{<<My Target>>}, or do a text search for
@samp{my target}, similar to the search in internal links, see
@ref{Internal links}. In HTML export (@pxref{HTML export}), such a file
-link will become a HTML reference to the corresponding named anchor in
+link will become an HTML reference to the corresponding named anchor in
the linked file.
@item *My Target
In an Org file, restrict search to headlines.
@@ -3895,7 +3904,7 @@ to search the current file. For example, @code{[[file:::find me]]} does
a search for @samp{find me} in the current file, just as
@samp{[[find me]]} would.
-@node Custom searches, , Search options, Hyperlinks
+@node Custom searches
@section Custom Searches
@cindex custom search strings
@cindex search strings, custom
@@ -3919,7 +3928,7 @@ variables for more information. Org actually uses this mechanism
for Bib@TeX{} database files, and you can use the corresponding code as
an implementation example. See the file @file{org-bibtex.el}.
-@node TODO Items, Tags, Hyperlinks, Top
+@node TODO items
@chapter TODO items
@cindex TODO items
@@ -3944,7 +3953,7 @@ methods to give you an overview of all the things that you have to do.
* Checkboxes:: Tick-off lists
@end menu
-@node TODO basics, TODO extensions, TODO Items, TODO Items
+@node TODO basics
@section Basic TODO functionality
Any headline becomes a TODO item when it starts with the word
@@ -4005,7 +4014,7 @@ N, show the tree for the Nth keyword in the option @code{org-todo-keywords}.
With two prefix arguments, find all TODO states, both un-done and done.
@orgcmd{C-c a t,org-todo-list}
Show the global TODO list. Collects the TODO items (with not-DONE states)
-from all agenda files (@pxref{Agenda Views}) into a single buffer. The new
+from all agenda files (@pxref{Agenda views}) into a single buffer. The new
buffer will be in @code{agenda-mode}, which provides commands to examine and
manipulate the TODO entries from the new buffer (@pxref{Agenda commands}).
@xref{Global TODO list}, for more information.
@@ -4018,7 +4027,7 @@ Insert a new TODO entry below the current one.
Changing a TODO state can also trigger tag changes. See the docstring of the
option @code{org-todo-state-tags-triggers} for details.
-@node TODO extensions, Progress logging, TODO basics, TODO Items
+@node TODO extensions
@section Extended use of TODO keywords
@cindex extended TODO keywords
@@ -4042,7 +4051,7 @@ TODO items in particular (@pxref{Tags}).
* TODO dependencies:: When one task needs to wait for others
@end menu
-@node Workflow states, TODO types, TODO extensions, TODO extensions
+@node Workflow states
@subsection TODO keywords as workflow states
@cindex TODO workflow
@cindex workflow states as TODO keywords
@@ -4073,7 +4082,7 @@ define many keywords, you can use in-buffer completion
buffer. Changing a TODO state can be logged with a timestamp, see
@ref{Tracking TODO state changes}, for more information.
-@node TODO types, Multiple sets in one file, Workflow states, TODO extensions
+@node TODO types
@subsection TODO keywords as types
@cindex TODO types
@cindex names as TODO keywords
@@ -4105,7 +4114,7 @@ Lucy has to do, you would use @kbd{C-3 C-c / t}. To collect Lucy's items
from all agenda files into a single buffer, you would use the numeric prefix
argument as well when creating the global TODO list: @kbd{C-3 C-c a t}.
-@node Multiple sets in one file, Fast access to TODO states, TODO types, TODO extensions
+@node Multiple sets in one file
@subsection Multiple keyword sets in one file
@cindex TODO keyword sets
@@ -4147,14 +4156,14 @@ These keys jump from one TODO subset to the next. In the above example,
@kindex S-@key{left}
@item S-@key{right}
@itemx S-@key{left}
-@kbd{S-@key{<left>}} and @kbd{S-@key{<right>}} and walk through @emph{all}
-keywords from all sets, so for example @kbd{S-@key{<right>}} would switch
+@kbd{S-@key{left}} and @kbd{S-@key{right}} and walk through @emph{all}
+keywords from all sets, so for example @kbd{S-@key{right}} would switch
from @code{DONE} to @code{REPORT} in the example above. See also
@ref{Conflicts}, for a discussion of the interaction with
@code{shift-selection-mode}.
@end table
-@node Fast access to TODO states, Per-file keywords, Multiple sets in one file, TODO extensions
+@node Fast access to TODO states
@subsection Fast access to TODO states
If you would like to quickly change an entry to an arbitrary TODO state
@@ -4179,7 +4188,7 @@ state through the tags interface (@pxref{Setting tags}), in case you like to
mingle the two concepts. Note that this means you need to come up with
unique keys across both sets of keywords.}
-@node Per-file keywords, Faces for TODO keywords, Fast access to TODO states, TODO extensions
+@node Per-file keywords
@subsection Setting up keywords for individual files
@cindex keyword options
@cindex per-file keywords
@@ -4226,7 +4235,7 @@ Org mode is activated after visiting a file. @kbd{C-c C-c} with the
cursor in a line starting with @samp{#+} is simply restarting Org mode
for the current buffer.}.
-@node Faces for TODO keywords, TODO dependencies, Per-file keywords, TODO extensions
+@node Faces for TODO keywords
@subsection Faces for TODO keywords
@cindex faces, for TODO keywords
@@ -4254,7 +4263,7 @@ special face and use that. A string is interpreted as a color. The option
@code{org-faces-easy-properties} determines if that color is interpreted as a
foreground or a background color.
-@node TODO dependencies, , Faces for TODO keywords, TODO extensions
+@node TODO dependencies
@subsection TODO dependencies
@cindex TODO dependencies
@cindex dependencies, of TODO states
@@ -4302,7 +4311,7 @@ Change TODO state, circumventing any state blocking.
@vindex org-agenda-dim-blocked-tasks
If you set the option @code{org-agenda-dim-blocked-tasks}, TODO entries
that cannot be closed because of such dependencies will be shown in a dimmed
-font or even made invisible in agenda views (@pxref{Agenda Views}).
+font or even made invisible in agenda views (@pxref{Agenda views}).
@cindex checkboxes and TODO dependencies
@vindex org-enforce-todo-dependencies
@@ -4316,7 +4325,7 @@ between entries in different trees or files, check out the contributed
module @file{org-depend.el}.
@page
-@node Progress logging, Priorities, TODO extensions, TODO Items
+@node Progress logging
@section Progress logging
@cindex progress logging
@cindex logging, of progress
@@ -4334,7 +4343,7 @@ work time}.
* Tracking your habits:: How consistent have you been?
@end menu
-@node Closing items, Tracking TODO state changes, Progress logging, Progress logging
+@node Closing items
@subsection Closing items
The most basic logging is to keep track of @emph{when} a certain TODO
@@ -4370,7 +4379,7 @@ In the timeline (@pxref{Timeline}) and in the agenda
display the TODO items with a @samp{CLOSED} timestamp on each day,
giving you an overview of what has been done.
-@node Tracking TODO state changes, Tracking your habits, Closing items, Progress logging
+@node Tracking TODO state changes
@subsection Tracking TODO state changes
@cindex drawer, for state change recording
@@ -4407,7 +4416,7 @@ To record a timestamp without a note for TODO keywords configured with
@noindent
@vindex org-log-done
-you not only define global TODO keywords and fast access keys, but also
+You not only define global TODO keywords and fast access keys, but also
request that a time is recorded when the entry is set to
DONE@footnote{It is possible that Org mode will record two timestamps
when you are using both @code{org-log-done} and state change logging.
@@ -4453,7 +4462,7 @@ settings like @code{TODO(!)}. For example
:END:
@end example
-@node Tracking your habits, , Tracking TODO state changes, Progress logging
+@node Tracking your habits
@subsection Tracking your habits
@cindex habits
@@ -4553,7 +4562,7 @@ temporarily be disabled and they won't appear at all. Press @kbd{K} again to
bring them back. They are also subject to tag filtering, if you have habits
which should only be done in certain contexts, for example.
-@node Priorities, Breaking down tasks, Progress logging, TODO Items
+@node Priorities
@section Priorities
@cindex priorities
@@ -4611,7 +4620,7 @@ priority):
#+PRIORITIES: A C B
@end example
-@node Breaking down tasks, Checkboxes, Priorities, TODO Items
+@node Breaking down tasks
@section Breaking tasks down into subtasks
@cindex tasks, breaking down
@cindex statistics, for TODO items
@@ -4672,7 +4681,7 @@ Another possibility is the use of checkboxes to identify (a hierarchy of) a
large number of subtasks (@pxref{Checkboxes}).
-@node Checkboxes, , Breaking down tasks, TODO Items
+@node Checkboxes
@section Checkboxes
@cindex checkboxes
@@ -4681,7 +4690,7 @@ Every item in a plain list@footnote{With the exception of description
lists. But you can allow it by modifying @code{org-list-automatic-rules}
accordingly.} (@pxref{Plain lists}) can be made into a checkbox by starting
it with the string @samp{[ ]}. This feature is similar to TODO items
-(@pxref{TODO Items}), but is more lightweight. Checkboxes are not included
+(@pxref{TODO items}), but is more lightweight. Checkboxes are not included
in the global TODO list, so they are often great to split a task into a
number of simple steps. Or you can use them in a shopping list. To toggle a
checkbox, use @kbd{C-c C-c}, or use the mouse (thanks to Piotr Zielinski's
@@ -4778,7 +4787,7 @@ changing TODO states. If you delete boxes/entries or add/change them by
hand, use this command to get things back into sync.
@end table
-@node Tags, Properties and Columns, TODO Items, Top
+@node Tags
@chapter Tags
@cindex tags
@cindex headline tagging
@@ -4806,7 +4815,7 @@ You may specify special faces for specific tags using the option
* Tag searches:: Searching for combinations of tags
@end menu
-@node Tag inheritance, Setting tags, Tags, Tags
+@node Tag inheritance
@section Tag inheritance
@cindex tag inheritance
@cindex inheritance, of tags
@@ -4860,7 +4869,7 @@ with inherited tags. Set @code{org-agenda-use-tag-inheritance} to control
this: the default value includes all agenda types, but setting this to @code{nil}
can really speed up agenda generation.
-@node Setting tags, Tag groups, Tag inheritance, Tags
+@node Setting tags
@section Setting tags
@cindex setting tags
@cindex tags, setting
@@ -5041,7 +5050,7 @@ instead of @kbd{C-c C-c}). If you set the variable to the value
@code{expert}, the special window is not even shown for single-key tag
selection, it comes up only when you press an extra @kbd{C-c}.
-@node Tag groups, Tag searches, Setting tags, Tags
+@node Tag groups
@section Tag groups
@cindex group tags
@@ -5083,7 +5092,7 @@ If you want to ignore group tags temporarily, toggle group tags support
with @command{org-toggle-tags-groups}, bound to @kbd{C-c C-x q}. If you
want to disable tag groups completely, set @code{org-group-tags} to @code{nil}.
-@node Tag searches, , Tag groups, Tags
+@node Tag searches
@section Tag searches
@cindex tag searches
@cindex searching for tags
@@ -5115,7 +5124,7 @@ and properties. For a complete description with many examples, see
@ref{Matching tags and properties}.
-@node Properties and Columns, Dates and Times, Tags, Top
+@node Properties and columns
@chapter Properties and columns
@cindex properties
@@ -5145,7 +5154,7 @@ Properties can be conveniently edited and viewed in column view
* Property API:: Properties for Lisp programmers
@end menu
-@node Property syntax, Special properties, Properties and Columns, Properties and Columns
+@node Property syntax
@section Property syntax
@cindex property syntax
@cindex drawer, for properties
@@ -5170,7 +5179,7 @@ first, and the value after it. Here is an example:
@end example
Depending on the value of @code{org-use-property-inheritance}, a property set
-this way will either be associated with a single entry, or the sub-tree
+this way will either be associated with a single entry, or the subtree
defined by the entry, see @ref{Property inheritance}.
You may define the allowed values for a particular property @samp{:Xyz:}
@@ -5198,7 +5207,7 @@ file, use a line like
@end example
Contrary to properties set from a special drawer, you have to refresh the
-buffer with @kbd{C-c C-c} to activate this changes.
+buffer with @kbd{C-c C-c} to activate this change.
If you want to add to the value of an existing property, append a @code{+} to
the property name. The following results in the property @code{var} having
@@ -5267,7 +5276,7 @@ Compute the property at point, using the operator and scope from the
nearest column format definition.
@end table
-@node Special properties, Property searches, Property syntax, Properties and Columns
+@node Special properties
@section Special properties
@cindex properties, special
@@ -5318,7 +5327,7 @@ ITEM @r{The headline of the entry.}
FILE @r{The filename the entry is located in.}
@end example
-@node Property searches, Property inheritance, Special properties, Properties and Columns
+@node Property searches
@section Property searches
@cindex properties, searching
@cindex searching, of properties
@@ -5355,7 +5364,7 @@ value. If you enclose the value in curly braces, it is interpreted as
a regular expression and matched against the property values.
@end table
-@node Property inheritance, Column view, Property searches, Properties and Columns
+@node Property inheritance
@section Property Inheritance
@cindex properties, inheritance
@cindex inheritance, of properties
@@ -5399,7 +5408,7 @@ The LOGGING property may define logging settings for an entry or a
subtree (@pxref{Tracking TODO state changes}).
@end table
-@node Column view, Property API, Property inheritance, Properties and Columns
+@node Column view
@section Column view
A great way to view and edit properties in an outline tree is
@@ -5413,7 +5422,7 @@ view (@kbd{S-@key{TAB} S-@key{TAB}}, or simply @kbd{c} while column view
is active), but you can still open, read, and edit the entry below each
headline. Or, you can switch to column view after executing a sparse
tree command and in this way get a table only for the selected items.
-Column view also works in agenda buffers (@pxref{Agenda Views}) where
+Column view also works in agenda buffers (@pxref{Agenda views}) where
queries have collected selected items, possibly from a number of files.
@menu
@@ -5422,7 +5431,7 @@ queries have collected selected items, possibly from a number of files.
* Capturing column view:: A dynamic block for column view
@end menu
-@node Defining columns, Using column view, Column view, Column view
+@node Defining columns
@subsection Defining columns
@cindex column view, for properties
@cindex properties, column view
@@ -5435,7 +5444,7 @@ done by defining a column format line.
* Column attributes:: Appearance and content of a column
@end menu
-@node Scope of column definitions, Column attributes, Defining columns, Defining columns
+@node Scope of column definitions
@subsubsection Scope of column definitions
To define a column format for an entire file, use a line like
@@ -5462,7 +5471,7 @@ you can define columns on level 1 that are general enough for all
sublevels, and more specific columns further down, when you edit a
deeper part of the tree.
-@node Column attributes, , Scope of column definitions, Defining columns
+@node Column attributes
@subsubsection Column attributes
A column definition sets the attributes of a column. The general
definition looks like this:
@@ -5526,6 +5535,9 @@ of 5 to 20 days, representing what to expect if everything goes either
extremely well or extremely poorly. In contrast, @code{est+} estimates the
full job more realistically, at 10--15 days.
+Numbers are right-aligned when a format specifier with an explicit width like
+@code{%5d} or @code{%5.1f} is used.
+
Here is an example for a complete columns definition, along with allowed
values.
@@ -5554,7 +5566,7 @@ an @samp{[X]} status if all children have been checked. The
sums of CLOCK intervals in the subtree, either for all clocks or just for
today.
-@node Using column view, Capturing column view, Defining columns, Column view
+@node Using column view
@subsection Using column view
@table @kbd
@@ -5600,7 +5612,7 @@ View the full value of this property. This is useful if the width of
the column is smaller than that of the value.
@orgcmd{a,org-columns-edit-allowed}
Edit the list of allowed values for this property. If the list is found
-in the hierarchy, the modified values is stored there. If no list is
+in the hierarchy, the modified value is stored there. If no list is
found, the new value is stored in the first entry that is part of the
current column view.
@tsubheading{Modifying the table structure}
@@ -5612,7 +5624,7 @@ Insert a new column, to the left of the current column.
Delete the current column.
@end table
-@node Capturing column view, , Using column view, Column view
+@node Capturing column view
@subsection Capturing column view
Since column view is just an overlay over a buffer, it cannot be
@@ -5689,7 +5701,7 @@ distributed with the main distribution of Org (visit
properties from entries in a certain scope, and arbitrary Lisp expressions to
process these values before inserting them into a table or a dynamic block.
-@node Property API, , Column view, Properties and Columns
+@node Property API
@section The Property API
@cindex properties, API
@cindex API, for properties
@@ -5699,7 +5711,7 @@ be used by Emacs Lisp programs to work with properties and to implement
features based on them. For more information see @ref{Using the
property API}.
-@node Dates and Times, Capture - Refile - Archive, Properties and Columns, Top
+@node Dates and times
@chapter Dates and times
@cindex dates
@cindex times
@@ -5709,7 +5721,7 @@ property API}.
To assist project planning, TODO items can be labeled with a date and/or
a time. The specially formatted string carrying the date and time
information is called a @emph{timestamp} in Org mode. This may be a
-little confusing because timestamp is often used as indicating when
+little confusing because timestamp is often used to indicate when
something was created or last changed. However, in Org mode this term
is used in a much wider sense.
@@ -5724,7 +5736,7 @@ is used in a much wider sense.
@end menu
-@node Timestamps, Creating timestamps, Dates and Times, Dates and Times
+@node Timestamps
@section Timestamps, deadlines, and scheduling
@cindex timestamps
@cindex ranges, time
@@ -5775,7 +5787,7 @@ following will show up in the agenda every Wednesday:
For more complex date specifications, Org mode supports using the special
sexp diary entries implemented in the Emacs calendar/diary
package@footnote{When working with the standard diary sexp functions, you
-need to be very careful with the order of the arguments. That order depend
+need to be very careful with the order of the arguments. That order depends
evilly on the variable @code{calendar-date-style} (or, for older Emacs
versions, @code{european-calendar-style}). For example, to specify a date
December 12, 2005, the call might look like @code{(diary-date 12 1 2005)} or
@@ -5818,7 +5830,7 @@ angular ones. These timestamps are inactive in the sense that they do
@end table
-@node Creating timestamps, Deadlines and scheduling, Timestamps, Dates and Times
+@node Creating timestamps
@section Creating timestamps
@cindex creating timestamps
@cindex timestamps, creating
@@ -5889,7 +5901,7 @@ the following column).
* Custom time format:: Making dates look different
@end menu
-@node The date/time prompt, Custom time format, Creating timestamps, Creating timestamps
+@node The date/time prompt
@subsection The date/time prompt
@cindex date, reading in minibuffer
@cindex time, reading in minibuffer
@@ -6015,7 +6027,7 @@ on, the current interpretation of your input will be displayed live in the
minibuffer@footnote{If you find this distracting, turn the display off with
@code{org-read-date-display-live}.}.
-@node Custom time format, , The date/time prompt, Creating timestamps
+@node Custom time format
@subsection Custom time format
@cindex custom date/time format
@cindex time format, custom
@@ -6063,7 +6075,7 @@ format is shorter, things do work as expected.
@end itemize
-@node Deadlines and scheduling, Clocking work time, Creating timestamps, Dates and Times
+@node Deadlines and scheduling
@section Deadlines and scheduling
A timestamp may be preceded by special keywords to facilitate planning:
@@ -6090,9 +6102,9 @@ until the entry is marked DONE@. An example:
@end example
You can specify a different lead time for warnings for a specific
-deadlines using the following syntax. Here is an example with a warning
+deadline using the following syntax. Here is an example with a warning
period of 5 days @code{DEADLINE: <2004-02-29 Sun -5d>}. This warning is
-deactivated if the task get scheduled and you set
+deactivated if the task gets scheduled and you set
@code{org-agenda-skip-deadline-prewarning-if-scheduled} to @code{t}.
@item SCHEDULED
@@ -6152,7 +6164,7 @@ sexp entry matches.
* Repeated tasks:: Items that show up again and again
@end menu
-@node Inserting deadline/schedule, Repeated tasks, Deadlines and scheduling, Deadlines and scheduling
+@node Inserting deadline/schedule
@subsection Inserting deadlines or schedules
The following commands allow you to quickly insert@footnote{The @samp{SCHEDULED} and
@@ -6210,7 +6222,7 @@ setting the date by indicating a relative time: e.g., +1d will set
the date to the next day after today, and --1w will set the date
to the previous week before any current timestamp.
-@node Repeated tasks, , Inserting deadline/schedule, Deadlines and scheduling
+@node Repeated tasks
@subsection Repeated tasks
@cindex tasks, repeated
@cindex repeated tasks
@@ -6251,6 +6263,9 @@ switch the date like this:
DEADLINE: <2005-11-01 Tue +1m>
@end example
+To mark a task with a repeater as @code{DONE}, use @kbd{C-- 1 C-c C-t}
+(i.e., @code{org-todo} with a numeric prefix argument of -1.)
+
@vindex org-log-repeat
A timestamp@footnote{You can change this using the option
@code{org-log-repeat}, or the @code{#+STARTUP} options @code{logrepeat},
@@ -6299,7 +6314,7 @@ subtree, with dates shifted in each copy. The command @kbd{C-c C-x c} was
created for this purpose, it is described in @ref{Structure editing}.
-@node Clocking work time, Effort estimates, Deadlines and scheduling, Dates and Times
+@node Clocking work time
@section Clocking work time
@cindex clocking time
@cindex time clocking
@@ -6311,7 +6326,7 @@ stopped and the corresponding time interval is recorded. It also computes
the total time spent on each subtree@footnote{Clocking only works if all
headings are indented with less than 30 stars. This is a hardcoded
limitation of `lmax' in `org-clock-sum'.} of a project. And it remembers a
-history or tasks recently clocked, to that you can jump quickly between a
+history or tasks recently clocked, so that you can jump quickly between a
number of tasks absorbing your time.
To save the clock history across Emacs sessions, use
@@ -6331,7 +6346,7 @@ what to do with it.
* Resolving idle time:: Resolving time when you've been idle
@end menu
-@node Clocking commands, The clock table, Clocking work time, Clocking work time
+@node Clocking commands
@subsection Clocking commands
@table @kbd
@@ -6376,7 +6391,7 @@ mode line entry will pop up a menu with clocking options.
@vindex org-log-note-clock-out
Stop the clock (clock-out). This inserts another timestamp at the same
location where the clock was last started. It also directly computes
-the resulting time in inserts it after the time range as @samp{=>
+the resulting time and inserts it after the time range as @samp{=>
HH:MM}. See the variable @code{org-log-note-clock-out} for the
possibility to record an additional note together with the clock-out
timestamp@footnote{The corresponding in-buffer setting is:
@@ -6431,7 +6446,7 @@ worked on or closed during a day.
@code{org-clock-in-last} can have a global keybinding and will not
modify the window disposition.
-@node The clock table, Resolving idle time, Clocking commands, Clocking work time
+@node The clock table
@subsection The clock table
@cindex clocktable, dynamic block
@cindex report, of clocked time
@@ -6471,7 +6486,7 @@ buffer with the @kbd{C-c C-x C-r} command:
@end example
@noindent
@vindex org-clocktable-defaults
-The @samp{BEGIN} line and specify a number of options to define the scope,
+The @samp{BEGIN} line specifies a number of options to define the scope,
structure, and formatting of the report. Defaults for all these options can
be configured in the variable @code{org-clocktable-defaults}.
@@ -6491,7 +6506,7 @@ be selected:
file-with-archives @r{current file and its archives}
agenda-with-archives @r{all agenda files, including archives}
:block @r{The time block to consider. This block is specified either}
- @r{absolute, or relative to the current time and may be any of}
+ @r{absolutely, or relative to the current time and may be any of}
@r{these formats:}
2007-12-31 @r{New year eve 2007}
2007-12 @r{December 2007}
@@ -6520,7 +6535,7 @@ be selected:
@r{@ref{Matching tags and properties} for the match syntax.}
@end example
-Then there are options which determine the formatting of the table. There
+Then there are options which determine the formatting of the table. These
options are interpreted by the function @code{org-clocktable-write-default},
but you can specify your own function using the @code{:formatter} parameter.
@example
@@ -6534,6 +6549,8 @@ but you can specify your own function using the @code{:formatter} parameter.
:tcolumns @r{Number of columns to be used for times. If this is smaller}
@r{than @code{:maxlevel}, lower levels will be lumped into one column.}
:level @r{Should a level number column be included?}
+:sort @r{A cons cell like containing the column to sort and a sorting type.}
+ @r{E.g., @code{:sort (1 . ?a)} sorts the first column alphabetically.}
:compact @r{Abbreviation for @code{:level nil :indent t :narrow 40! :tcolumns 1}}
@r{All are overwritten except if there is an explicit @code{:narrow}}
:timestamp @r{A timestamp for the entry, when available. Look for SCHEDULED,}
@@ -6579,7 +6596,7 @@ would be
#+END: clocktable
@end example
-@node Resolving idle time, , The clock table, Clocking work time
+@node Resolving idle time
@subsection Resolving idle time and continuous clocking
@subsubheading Resolving idle time
@@ -6664,7 +6681,7 @@ last clocked entry for this session, and start the new clock from there.
If you only want this from time to time, use three universal prefix arguments
with @code{org-clock-in} and two @kbd{C-u C-u} with @code{org-clock-in-last}.
-@node Effort estimates, Relative timer, Clocking work time, Dates and Times
+@node Effort estimates
@section Effort estimates
@cindex effort estimates
@@ -6727,7 +6744,7 @@ with the @kbd{/} key in the agenda (@pxref{Agenda commands}). If you have
these estimates defined consistently, two or three key presses will narrow
down the list to stuff that fits into an available time slot.
-@node Relative timer, Countdown timer, Effort estimates, Dates and Times
+@node Relative timer
@section Taking notes with a relative timer
@cindex relative timer
@@ -6767,7 +6784,7 @@ by a certain amount. This can be used to fix timer strings if the timer was
not started at exactly the right moment.
@end table
-@node Countdown timer, , Relative timer, Dates and Times
+@node Countdown timer
@section Countdown timer
@cindex Countdown timer
@kindex C-c C-x ;
@@ -6781,7 +6798,7 @@ countdown timer in the modeline. @code{org-timer-default-timer} sets the
default countdown value. Giving a prefix numeric argument overrides this
default value.
-@node Capture - Refile - Archive, Agenda Views, Dates and Times, Top
+@node Capture - Refile - Archive
@chapter Capture - Refile - Archive
@cindex capture
@@ -6795,13 +6812,13 @@ trees to an archive file keeps the system compact and fast.
@menu
* Capture:: Capturing new stuff
* Attachments:: Add files to tasks
-* RSS Feeds:: Getting input from RSS feeds
+* RSS feeds:: Getting input from RSS feeds
* Protocols:: External (e.g., Browser) access to Emacs and Org
* Refile and copy:: Moving/copying a tree from one place to another
* Archiving:: What to do with finished projects
@end menu
-@node Capture, Attachments, Capture - Refile - Archive, Capture - Refile - Archive
+@node Capture
@section Capture
@cindex capture
@@ -6828,7 +6845,7 @@ customization.
* Capture templates:: Define the outline of different note types
@end menu
-@node Setting up capture, Using capture, Capture, Capture
+@node Setting up capture
@subsection Setting up capture
The following customization sets a default target file for notes, and defines
@@ -6843,7 +6860,7 @@ suggestion.} for capturing new material.
@end group
@end smalllisp
-@node Using capture, Capture templates, Setting up capture, Capture
+@node Using capture
@subsection Using capture
@table @kbd
@@ -6900,7 +6917,7 @@ automatically be created unless you set @code{org-capture-bookmark} to
To insert the capture at point in an Org buffer, call @code{org-capture} with
a @code{C-0} prefix argument.
-@node Capture templates, , Using capture, Capture
+@node Capture templates
@subsection Capture templates
@cindex templates, for Capture
@@ -6959,7 +6976,7 @@ like this:
* Templates in contexts:: Only show a template in a specific context
@end menu
-@node Template elements, Template expansion, Capture templates, Capture templates
+@node Template elements
@subsubsection Template elements
Now lets look at the elements of a template definition. Each entry in
@@ -7096,9 +7113,10 @@ narrow it so that you only see the new material.
@item :table-line-pos
Specification of the location in the table where the new line should be
-inserted. It should be a string like @code{"II-3"} meaning that the new
-line should become the third line before the second horizontal separator
-line.
+inserted. It can be a string, a variable holding a string or a function
+returning a string. The string should look like @code{"II-3"} meaning that
+the new line should become the third line before the second horizontal
+separator line.
@item :kill-buffer
If the target file was not yet visited when capture was invoked, kill the
@@ -7106,7 +7124,7 @@ buffer again after capture is completed.
@end table
@end table
-@node Template expansion, Templates in contexts, Template elements, Capture templates
+@node Template expansion
@subsubsection Template expansion
In the template itself, special @kbd{%}-escapes@footnote{If you need one of
@@ -7186,7 +7204,7 @@ To place the cursor after template expansion use:
%? @r{After completing the template, position cursor here.}
@end smallexample
-@node Templates in contexts, , Template expansion, Capture templates
+@node Templates in contexts
@subsubsection Templates in contexts
@vindex org-capture-templates-contexts
@@ -7210,7 +7228,7 @@ template. In that case, add this command key like this:
See the docstring of the variable for more information.
-@node Attachments, RSS Feeds, Capture, Capture - Refile - Archive
+@node Attachments
@section Attachments
@cindex attachments
@@ -7298,7 +7316,7 @@ same directory for attachments as the parent does.
@end table
@end table
-@node RSS Feeds, Protocols, Attachments, Capture - Refile - Archive
+@node RSS feeds
@section RSS feeds
@cindex RSS feeds
@cindex Atom feeds
@@ -7336,17 +7354,12 @@ Prompt for a feed name and go to the inbox configured for this feed.
Under the same headline, Org will create a drawer @samp{FEEDSTATUS} in which
it will store information about the status of items in the feed, to avoid
-adding the same item several times. You should add @samp{FEEDSTATUS} to the
-list of drawers in that file:
-
-@example
-#+DRAWERS: LOGBOOK PROPERTIES FEEDSTATUS
-@end example
+adding the same item several times.
For more information, including how to read atom feeds, see
@file{org-feed.el} and the docstring of @code{org-feed-alist}.
-@node Protocols, Refile and copy, RSS Feeds, Capture - Refile - Archive
+@node Protocols
@section Protocols for external access
@cindex protocols, for external access
@cindex emacsserver
@@ -7360,7 +7373,7 @@ a remote website you are looking at with the browser. See
@uref{http://orgmode.org/worg/org-contrib/org-protocol.php} for detailed
documentation and setup instructions.
-@node Refile and copy, Archiving, Protocols, Capture - Refile - Archive
+@node Refile and copy
@section Refile and copy
@cindex refiling notes
@cindex copying notes
@@ -7417,7 +7430,7 @@ setting @code{org-refile-use-cache}. To make the command see new possible
targets, you have to clear the cache with this command.
@end table
-@node Archiving, , Refile and copy, Capture - Refile - Archive
+@node Archiving
@section Archiving
@cindex archiving
@@ -7438,7 +7451,7 @@ Archive the current entry using the command specified in the variable
* Internal archiving:: Switch off a tree but keep it in the file
@end menu
-@node Moving subtrees, Internal archiving, Archiving, Archiving
+@node Moving subtrees
@subsection Moving a tree to the archive file
@cindex external archiving
@@ -7485,7 +7498,7 @@ archive locations in a buffer is using properties.}:
@noindent
If you would like to have a special ARCHIVE location for a single entry
or a (sub)tree, give the entry an @code{:ARCHIVE:} property with the
-location as the value (@pxref{Properties and Columns}).
+location as the value (@pxref{Properties and columns}).
@vindex org-archive-save-context-info
When a subtree is moved, it receives a number of special properties that
@@ -7495,7 +7508,7 @@ outline path the archiving time etc. Configure the variable
added.
-@node Internal archiving, , Moving subtrees, Archiving
+@node Internal archiving
@subsection Internal archiving
If you want to just switch off (for agenda views) certain subtrees without
@@ -7518,7 +7531,7 @@ archived subtrees are not exposed, unless you configure the option
@code{org-sparse-tree-open-archived-trees}.
@item
@vindex org-agenda-skip-archived-trees
-During agenda view construction (@pxref{Agenda Views}), the content of
+During agenda view construction (@pxref{Agenda views}), the content of
archived trees is ignored unless you configure the option
@code{org-agenda-skip-archived-trees}, in which case these trees will always
be included. In the agenda you can press @kbd{v a} to get archives
@@ -7558,7 +7571,7 @@ outline.
@end table
-@node Agenda Views, Markup, Capture - Refile - Archive, Top
+@node Agenda views
@chapter Agenda views
@cindex agenda views
@@ -7615,11 +7628,11 @@ window configuration is restored when the agenda exits:
* Presentation and sorting:: How agenda items are prepared for display
* Agenda commands:: Remote editing of Org trees
* Custom agenda views:: Defining special searches and views
-* Exporting Agenda Views:: Writing a view to a file
+* Exporting agenda views:: Writing a view to a file
* Agenda column view:: Using column view for collected entries
@end menu
-@node Agenda files, Agenda dispatcher, Agenda Views, Agenda Views
+@node Agenda files
@section Agenda files
@cindex agenda files
@cindex files for agenda
@@ -7696,7 +7709,7 @@ effect immediately.
Lift the restriction.
@end table
-@node Agenda dispatcher, Built-in agenda views, Agenda files, Agenda Views
+@node Agenda dispatcher
@section The agenda dispatcher
@cindex agenda dispatcher
@cindex dispatching agenda commands
@@ -7742,15 +7755,17 @@ current region/subtree.}. After pressing @kbd{< <}, you still need to press the
character selecting the command.
@item *
+@cindex agenda, sticky
@vindex org-agenda-sticky
Toggle sticky agenda views. By default, Org maintains only a single agenda
buffer and rebuilds it each time you change the view, to make sure everything
-is always up to date. If you switch between views often and the build time
-bothers you, you can turn on sticky agenda buffers (make this the default by
-customizing the variable @code{org-agenda-sticky}). With sticky agendas, the
-dispatcher only switches to the selected view, you need to update it by hand
-with @kbd{r} or @kbd{g}. You can toggle sticky agenda view any time with
-@code{org-toggle-sticky-agenda}.
+is always up to date. If you often switch between agenda views and the build
+time bothers you, you can turn on sticky agenda buffers or make this the
+default by customizing the variable @code{org-agenda-sticky}. With sticky
+agendas, the agenda dispatcher will not recreate agenda views from scratch,
+it will only switch to the selected one, and you need to update the agenda by
+hand with @kbd{r} or @kbd{g} when needed. You can toggle sticky agenda view
+any time with @code{org-toggle-sticky-agenda}.
@end table
You can also define custom commands that will be accessible through the
@@ -7759,7 +7774,7 @@ possibility to create extended agenda buffers that contain several
blocks together, for example the weekly agenda, the global TODO list and
a number of special tags matches. @xref{Custom agenda views}.
-@node Built-in agenda views, Presentation and sorting, Agenda dispatcher, Agenda Views
+@node Built-in agenda views
@section The built-in agenda views
In this section we describe the built-in views.
@@ -7773,7 +7788,7 @@ In this section we describe the built-in views.
* Stuck projects:: Find projects you need to review
@end menu
-@node Weekly/daily agenda, Global TODO list, Built-in agenda views, Built-in agenda views
+@node Weekly/daily agenda
@subsection The weekly/daily agenda
@cindex agenda
@cindex weekly agenda
@@ -7912,7 +7927,7 @@ It also reads a @code{APPT_WARNTIME} property which will then override the
value of @code{appt-message-warning-time} for this appointment. See the
docstring for details.
-@node Global TODO list, Matching tags and properties, Weekly/daily agenda, Built-in agenda views
+@node Global TODO list
@subsection The global TODO list
@cindex global TODO list
@cindex TODO list, global
@@ -7923,7 +7938,7 @@ collected into a single place.
@table @kbd
@orgcmd{C-c a t,org-todo-list}
Show the global TODO list. This collects the TODO items from all agenda
-files (@pxref{Agenda Views}) into a single buffer. By default, this lists
+files (@pxref{Agenda views}) into a single buffer. By default, this lists
items with a state the is not a DONE state. The buffer is in
@code{agenda-mode}, so there are commands to examine and manipulate the TODO
entries directly from that buffer (@pxref{Agenda commands}).
@@ -7973,7 +7988,7 @@ and omit the sublevels from the global list. Configure the variable
@code{org-agenda-todo-list-sublevels} to get this behavior.
@end itemize
-@node Matching tags and properties, Timeline, Global TODO list, Built-in agenda views
+@node Matching tags and properties
@subsection Matching tags and properties
@cindex matching, of tags
@cindex matching, of properties
@@ -7981,7 +7996,7 @@ and omit the sublevels from the global list. Configure the variable
@cindex match view
If headlines in the agenda files are marked with @emph{tags} (@pxref{Tags}),
-or have properties (@pxref{Properties and Columns}), you can select headlines
+or have properties (@pxref{Properties and columns}), you can select headlines
based on this metadata and collect them into an agenda buffer. The match
syntax described here also applies when creating sparse trees with @kbd{C-c /
m}.
@@ -8046,23 +8061,23 @@ Group tags (@pxref{Tag groups}) are expanded as regular expressions. E.g.,
if @samp{:work:} is a group tag for the group @samp{:work:lab:conf:}, then
searching for @samp{work} will search for @samp{@{\(?:work\|lab\|conf\)@}}
and searching for @samp{-work} will search for all headlines but those with
-one of the tag in the group (i.e., @samp{-@{\(?:work\|lab\|conf\)@}}).
+one of the tags in the group (i.e., @samp{-@{\(?:work\|lab\|conf\)@}}).
@cindex TODO keyword matching, with tags search
@cindex level, require for tags/property match
@cindex category, require for tags/property match
@vindex org-odd-levels-only
-You may also test for properties (@pxref{Properties and Columns}) at the same
+You may also test for properties (@pxref{Properties and columns}) at the same
time as matching tags. The properties may be real properties, or special
properties that represent other metadata (@pxref{Special properties}). For
example, the ``property'' @code{TODO} represents the TODO keyword of the
-entry and the ``propety'' @code{PRIORITY} represents the PRIORITY keyword of
+entry and the ``property'' @code{PRIORITY} represents the PRIORITY keyword of
the entry. The ITEM special property cannot currently be used in tags/property
searches@footnote{But @pxref{x-agenda-skip-entry-regexp,
,skipping entries based on regexp}.}.
-Except the @pxref{Special properties}, one other ``property'' can also be
-used. @code{LEVEL} represents the level of an entry. So a search
+In addition to the @pxref{Special properties}, one other ``property'' can
+also be used. @code{LEVEL} represents the level of an entry. So a search
@samp{+LEVEL=3+boss-TODO="DONE"} lists all level three headlines that have
the tag @samp{boss} and are @emph{not} marked with the TODO keyword DONE@.
In buffers with @code{org-odd-levels-only} set, @samp{LEVEL} does not count
@@ -8153,7 +8168,7 @@ Select @samp{:work:}-tagged TODO lines that are either @samp{WAITING} or
@samp{NEXT}.
@end table
-@node Timeline, Search view, Matching tags and properties, Built-in agenda views
+@node Timeline
@subsection Timeline for a single file
@cindex timeline, single file
@cindex time-sorted view
@@ -8173,7 +8188,7 @@ When called with a @kbd{C-u} prefix, all unfinished TODO entries
The commands available in the timeline buffer are listed in
@ref{Agenda commands}.
-@node Search view, Stuck projects, Timeline, Built-in agenda views
+@node Search view
@subsection Search view
@cindex search view
@cindex text search
@@ -8203,7 +8218,7 @@ the docstring of the command @code{org-search-view}.
Note that in addition to the agenda files, this command will also search
the files listed in @code{org-agenda-text-search-extra-files}.
-@node Stuck projects, , Search view, Built-in agenda views
+@node Stuck projects
@subsection Stuck projects
@pindex GTD, Getting Things Done
@@ -8251,7 +8266,7 @@ correct customization for this is
Note that if a project is identified as non-stuck, the subtree of this entry
will still be searched for stuck projects.
-@node Presentation and sorting, Agenda commands, Built-in agenda views, Agenda Views
+@node Presentation and sorting
@section Presentation and sorting
@cindex presentation, of agenda items
@@ -8273,7 +8288,7 @@ associated with the item.
* Filtering/limiting agenda items:: Dynamically narrow the agenda
@end menu
-@node Categories, Time-of-day specifications, Presentation and sorting, Presentation and sorting
+@node Categories
@subsection Categories
@cindex category
@@ -8307,7 +8322,7 @@ longer than 10 characters.
You can set up icons for category by customizing the
@code{org-agenda-category-icon-alist} variable.
-@node Time-of-day specifications, Sorting agenda items, Categories, Presentation and sorting
+@node Time-of-day specifications
@subsection Time-of-day specifications
@cindex time-of-day specification
@@ -8358,7 +8373,7 @@ The time grid can be turned on and off with the variable
@code{org-agenda-use-time-grid}, and can be configured with
@code{org-agenda-time-grid}.
-@node Sorting agenda items, Filtering/limiting agenda items, Time-of-day specifications, Presentation and sorting
+@node Sorting agenda items
@subsection Sorting agenda items
@cindex sorting, of agenda items
@cindex priorities, of agenda items
@@ -8392,14 +8407,14 @@ Sorting can be customized using the variable
@code{org-agenda-sorting-strategy}, and may also include criteria based on
the estimated effort of an entry (@pxref{Effort estimates}).
-@node Filtering/limiting agenda items, , Sorting agenda items, Presentation and sorting
+@node Filtering/limiting agenda items
@subsection Filtering/limiting agenda items
Agenda built-in or customized commands are statically defined. Agenda
filters and limits provide two ways of dynamically narrowing down the list of
-agenda entries: @emph{fitlers} and @emph{limits}. Filters only act on the
+agenda entries: @emph{filters} and @emph{limits}. Filters only act on the
display of the items, while limits take effect before the list of agenda
-entries is built. Filter are more often used interactively, while limits are
+entries is built. Filters are more often used interactively, while limits are
mostly useful when defined as local variables within custom agenda commands.
@subsubheading Filtering in the agenda
@@ -8434,24 +8449,6 @@ will be narrowed by requiring or forbidding the selected additional tag.
Instead of pressing @kbd{+} or @kbd{-} after @kbd{/}, you can also
immediately use the @kbd{\} command.
-@vindex org-sort-agenda-noeffort-is-high
-In order to filter for effort estimates, you should set up allowed
-efforts globally, for example
-@lisp
-(setq org-global-properties
- '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00")))
-@end lisp
-You can then filter for an effort by first typing an operator, one of
-@kbd{<}, @kbd{>}, and @kbd{=}, and then the one-digit index of an effort
-estimate in your array of allowed values, where @kbd{0} means the 10th value.
-The filter will then restrict to entries with effort smaller-or-equal, equal,
-or larger-or-equal than the selected value. If the digits 0--9 are not used
-as fast access keys to tags, you can also simply press the index digit
-directly without an operator. In this case, @kbd{<} will be assumed. For
-application of the operator, entries without a defined effort will be treated
-according to the value of @code{org-sort-agenda-noeffort-is-high}. To filter
-for tasks without effort definition, press @kbd{?} as the operator.
-
Org also supports automatic, context-aware tag filtering. If the variable
@code{org-agenda-auto-exclude-function} is set to a user-defined function,
that function can decide which tags should be excluded from the agenda
@@ -8522,6 +8519,23 @@ universal prefix arguments, it will remove all the regexp filters, which can
be accumulated. You can add a filter preset through the option
@code{org-agenda-category-filter-preset} (see below.)
+@orgcmd{_,org-agenda-filter-by-effort}
+@vindex org-agenda-effort-filter-preset
+@vindex org-sort-agenda-noeffort-is-high
+Filter the agenda view with respect to effort estimates.
+You first need to set up allowed efforts globally, for example
+@lisp
+(setq org-global-properties
+ '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00")))
+@end lisp
+You can then filter for an effort by first typing an operator, one of
+@kbd{<}, @kbd{>}, and @kbd{=}, and then the one-digit index of an effort
+estimate in your array of allowed values, where @kbd{0} means the 10th value.
+The filter will then restrict to entries with effort smaller-or-equal, equal,
+or larger-or-equal than the selected value. For application of the operator,
+entries without a defined effort will be treated according to the value of
+@code{org-sort-agenda-noeffort-is-high}.
+
@orgcmd{|,org-agenda-filter-remove-all}
Remove all filters in the current agenda view.
@end table
@@ -8548,8 +8562,8 @@ Limit the number of tagged entries.
@end table
When set to a positive integer, each option will exclude entries from other
-catogories: for example, @code{(setq org-agenda-max-effort 100)} will limit
-the agenda to 100 minutes of effort and exclude any entry that as no effort
+categories: for example, @code{(setq org-agenda-max-effort 100)} will limit
+the agenda to 100 minutes of effort and exclude any entry that has no effort
property. If you want to include entries with no effort property, use a
negative value for @code{org-agenda-max-effort}.
@@ -8567,15 +8581,15 @@ Once you mark one of these five entry as @code{DONE}, rebuilding the agenda
will again the next five entries again, including the first entry that was
excluded so far.
-You can also dynamically set temporary limits@footnote{Those temporary limits
-are lost when rebuilding the agenda.}:
+You can also dynamically set temporary limits, which will be lost when
+rebuilding the agenda:
@table @kbd
@orgcmd{~,org-agenda-limit-interactively}
This prompts for the type of limit to apply and its value.
@end table
-@node Agenda commands, Custom agenda views, Presentation and sorting, Agenda Views
+@node Agenda commands
@section Commands in the agenda buffer
@cindex commands, in agenda buffer
@@ -8596,6 +8610,10 @@ the other commands, the cursor needs to be in the desired line.
Next line (same as @key{down} and @kbd{C-n}).
@orgcmd{p,org-agenda-previous-line}
Previous line (same as @key{up} and @kbd{C-p}).
+@orgcmd{N,org-agenda-next-item}
+Next item: same as next line, but only consider items.
+@orgcmd{P,org-agenda-previous-item}
+Previous item: same as previous line, but only consider items.
@tsubheading{View/Go to Org file}
@orgcmdkkc{@key{SPC},mouse-3,org-agenda-show-and-scroll-up}
Display the original location of the item in another window.
@@ -9103,7 +9121,7 @@ visit Org files will not be removed.
@end table
-@node Custom agenda views, Exporting Agenda Views, Agenda commands, Agenda Views
+@node Custom agenda views
@section Custom agenda views
@cindex custom agenda views
@cindex agenda views, custom
@@ -9116,10 +9134,10 @@ dispatcher (@pxref{Agenda dispatcher}), just like the default commands.
@menu
* Storing searches:: Type once, use often
* Block agenda:: All the stuff you need in a single buffer
-* Setting Options:: Changing the rules
+* Setting options:: Changing the rules
@end menu
-@node Storing searches, Block agenda, Custom agenda views, Custom agenda views
+@node Storing searches
@subsection Storing searches
The first application of custom searches is the definition of keyboard
@@ -9211,7 +9229,7 @@ Peter, or Kim) as additional tag to match.
Note that the @code{*-tree} agenda views need to be called from an
Org buffer as they operate on the current buffer only.
-@node Block agenda, Setting Options, Storing searches, Custom agenda views
+@node Block agenda
@subsection Block agenda
@cindex block agenda
@cindex agenda, with block views
@@ -9245,7 +9263,7 @@ your agenda for the current week, all TODO items that carry the tag
@samp{home}, and also all lines tagged with @samp{garden}. Finally the
command @kbd{C-c a o} provides a similar view for office tasks.
-@node Setting Options, , Block agenda, Custom agenda views
+@node Setting options
@subsection Setting options for custom commands
@cindex options, for custom agenda views
@@ -9319,7 +9337,7 @@ yourself.
@vindex org-agenda-custom-commands-contexts
To control whether an agenda command should be accessible from a specific
context, you can customize @code{org-agenda-custom-commands-contexts}. Let's
-say for example that you have an agenda commands @code{"o"} displaying a view
+say for example that you have an agenda command @code{"o"} displaying a view
that you only need when reading emails. Then you would configure this option
like this:
@@ -9338,8 +9356,8 @@ command key @code{"r"}. In that case, add this command key like this:
See the docstring of the variable for more information.
-@node Exporting Agenda Views, Agenda column view, Custom agenda views, Agenda Views
-@section Exporting Agenda Views
+@node Exporting agenda views
+@section Exporting agenda views
@cindex agenda views, exporting
If you are away from your computer, it can be very useful to have a printed
@@ -9477,7 +9495,7 @@ processing by other programs. See @ref{Extracting agenda information}, for
more information.
-@node Agenda column view, , Exporting Agenda Views, Agenda Views
+@node Agenda column view
@section Using column view in the agenda
@cindex column view, in agenda
@cindex agenda, column view
@@ -9541,12 +9559,12 @@ spent (via @code{CLOCKSUM}) and with the planned total effort for it.
@end enumerate
-@node Markup, Exporting, Agenda Views, Top
+@node Markup
@chapter Markup for rich export
When exporting Org mode documents, the exporter tries to reflect the
structure of the document as accurately as possible in the back-end. Since
-export targets like HTML, @LaTeX{} allow much richer formatting, Org mode has
+export targets like HTML and @LaTeX{} allow much richer formatting, Org mode has
rules on how to prepare text for rich export. This section summarizes the
markup rules used in an Org mode buffer.
@@ -9561,7 +9579,7 @@ markup rules used in an Org mode buffer.
* Special blocks:: Containers targeted at export back-ends
@end menu
-@node Structural markup elements, Images and tables, Markup, Markup
+@node Structural markup elements
@section Structural markup elements
@menu
@@ -9576,7 +9594,7 @@ markup rules used in an Org mode buffer.
* Comment lines:: What will *not* be exported
@end menu
-@node Document title, Headings and sections, Structural markup elements, Structural markup elements
+@node Document title
@subheading Document title
@cindex document title, markup rules
@@ -9588,22 +9606,18 @@ The title of the exported document is taken from the special line
#+TITLE: This is the title of the document
@end example
-@noindent
-If this line does not exist, the title will be the name of the file
-associated to buffer, without extension, or the buffer name.
-
@cindex property, EXPORT_TITLE
If you are exporting only a subtree, its heading will become the title of the
document. If the subtree has a property @code{EXPORT_TITLE}, that will take
precedence.
-@node Headings and sections, Table of contents, Document title, Structural markup elements
+@node Headings and sections
@subheading Headings and sections
@cindex headings and sections, markup rules
@vindex org-export-headline-levels
The outline structure of the document as described in @ref{Document
-Structure}, forms the basis for defining sections of the exported document.
+structure}, forms the basis for defining sections of the exported document.
However, since the outline structure is also used for (for example) lists of
tasks, only the first three outline levels will be used as headings. Deeper
levels will become itemized lists. You can change the location of this
@@ -9615,7 +9629,7 @@ per-file basis with a line
#+OPTIONS: H:4
@end example
-@node Table of contents, Lists, Headings and sections, Structural markup elements
+@node Table of contents
@subheading Table of contents
@cindex table of contents, markup rules
@@ -9633,7 +9647,7 @@ or on a per-file basis with a line like
@end example
If you would like to move the table of contents to a different location, you
-should turn off the detault table using @code{org-export-with-toc} or
+should turn off the default table using @code{org-export-with-toc} or
@code{#+OPTIONS} and insert @code{#+TOC: headlines N} at the desired
location(s).
@@ -9658,7 +9672,7 @@ contents. However, it is possible to specify an alternative title by
setting @code{ALT_TITLE} property accordingly. It will then be used when
building the table.
-@node Lists, Paragraphs, Table of contents, Structural markup elements
+@node Lists
@subheading Lists
@cindex lists, markup rules
@@ -9666,7 +9680,7 @@ Plain lists as described in @ref{Plain lists}, are translated to the back-end's
syntax for such lists. Most back-ends support unordered, ordered, and
description lists.
-@node Paragraphs, Footnote markup, Lists, Structural markup elements
+@node Paragraphs
@subheading Paragraphs, line breaks, and quoting
@cindex paragraphs, markup rules
@@ -9709,7 +9723,7 @@ but not any simpler
@end example
-@node Footnote markup, Emphasis and monospace, Paragraphs, Structural markup elements
+@node Footnote markup
@subheading Footnote markup
@cindex footnotes, markup rules
@cindex @file{footnote.el}
@@ -9718,7 +9732,7 @@ Footnotes defined in the way described in @ref{Footnotes}, will be exported
by all back-ends. Org allows multiple references to the same note, and
multiple footnotes side by side.
-@node Emphasis and monospace, Horizontal rules, Footnote markup, Structural markup elements
+@node Emphasis and monospace
@subheading Emphasis and monospace
@cindex underlined text, markup rules
@@ -9730,8 +9744,8 @@ multiple footnotes side by side.
@vindex org-fontify-emphasized-text
@vindex org-emphasis-regexp-components
@vindex org-emphasis-alist
-You can make words @b{*bold*}, @i{/italic/}, _underlined_, @code{=code=}
-and @code{~verbatim~}, and, if you must, @samp{+strike-through+}. Text
+You can make words @b{*bold*}, @i{/italic/}, _underlined_, @code{=verbatim=}
+and @code{~code~}, and, if you must, @samp{+strike-through+}. Text
in the code and verbatim string is not processed for Org mode specific
syntax, it is exported verbatim.
@@ -9743,32 +9757,38 @@ can tweak @code{org-emphasis-regexp-components}. Beware that changing one of
the above variables will no take effect until you reload Org, for which you
may need to restart Emacs.
-@node Horizontal rules, Comment lines, Emphasis and monospace, Structural markup elements
+@node Horizontal rules
@subheading Horizontal rules
@cindex horizontal rules, markup rules
A line consisting of only dashes, and at least 5 of them, will be exported as
a horizontal line.
-@node Comment lines, , Horizontal rules, Structural markup elements
+@node Comment lines
@subheading Comment lines
@cindex comment lines
@cindex exporting, not
@cindex #+BEGIN_COMMENT
Lines starting with zero or more whitespace characters followed by one
-@samp{#} and a whitespace are treated as comments and will never be exported.
-Also entire subtrees starting with the word @samp{COMMENT} will never be
-exported. Finally, regions surrounded by @samp{#+BEGIN_COMMENT}
-... @samp{#+END_COMMENT} will not be exported.
+@samp{#} and a whitespace are treated as comments and, as such, are not
+exported.
+
+Likewise, regions surrounded by @samp{#+BEGIN_COMMENT}
+... @samp{#+END_COMMENT} are not exported.
+
+Finally, a @samp{COMMENT} keyword at the beginning of an entry, but after any
+other keyword or priority cookie, comments out the entire subtree. In this
+case, the subtree is not exported and no code block within it is executed
+either. The command below helps changing the comment status of a headline.
@table @kbd
@kindex C-c ;
@item C-c ;
-Toggle the COMMENT keyword at the beginning of an entry.
+Toggle the @samp{COMMENT} keyword at the beginning of an entry.
@end table
-@node Images and tables, Literal examples, Structural markup elements, Markup
+@node Images and tables
@section Images and Tables
@cindex tables, markup rules
@@ -9816,7 +9836,7 @@ the same caption mechanism can apply to many others (e.g., @LaTeX{}
equations, source code blocks). Depending on the export back-end, those may
or may not be handled.
-@node Literal examples, Include files, Images and tables, Markup
+@node Literal examples
@section Literal examples
@cindex literal examples, markup rules
@cindex code line references, markup rules
@@ -9844,6 +9864,7 @@ Here is an example
@end example
@cindex formatting source code, markup rules
+@vindex org-latex-listings
If the example is source code from a programming language, or any other text
that can be marked up by font-lock in Emacs, you can ask for the example to
look like the fontified Emacs buffer@footnote{This works automatically for
@@ -9855,8 +9876,8 @@ achieved using either the listings or the
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@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.}, see @ref{Easy Templates} for shortcuts to easily insert code
+See @pxref{Working with source code} for more information on evaluating code
+blocks.}, see @ref{Easy templates} for shortcuts to easily insert code
blocks.
@cindex #+BEGIN_SRC
@@ -9889,12 +9910,16 @@ Here is an example:
@example
#+BEGIN_SRC emacs-lisp -n -r
(save-excursion (ref:sc)
- (goto-char (point-min)) (ref:jump)
+ (goto-char (point-min))) (ref:jump)
#+END_SRC
In line [[(sc)]] we remember the current position. [[(jump)][Line (jump)]]
jumps to point-min.
@end example
+@cindex indentation, in source blocks
+Finally, you can use @code{-i} to preserve the indentation of a specific code
+block (@pxref{Editing source code}).
+
@vindex org-coderef-label-format
If the syntax for the label format conflicts with the language syntax, use a
@code{-l} switch to change the format, for example @samp{#+BEGIN_SRC pascal
@@ -9904,8 +9929,8 @@ HTML export also allows examples to be published as text areas (@pxref{Text
areas in HTML export}).
Because the @code{#+BEGIN_...} and @code{#+END_...} patterns need to be added
-so often, shortcuts are provided using the Easy Templates facility
-(@pxref{Easy Templates}).
+so often, shortcuts are provided using the Easy templates facility
+(@pxref{Easy templates}).
@table @kbd
@kindex C-c '
@@ -9932,7 +9957,7 @@ label is stored as a link @samp{(label)}, for retrieval with @kbd{C-c C-l}.
@end table
-@node Include files, Index entries, Literal examples, Markup
+@node Include files
@section Include files
@cindex include files, markup rules
@@ -9945,28 +9970,37 @@ include your @file{.emacs} file, you could use:
@end example
@noindent
-The optional second and third parameter are the markup (e.g., @samp{quote},
-@samp{example}, or @samp{src}), and, if the markup is @samp{src}, the
-language for formatting the contents. The markup is optional; if it is not
-given, the text will be assumed to be in Org mode format and will be
-processed normally.
-
-Contents of the included file will belong to the same structure (headline,
-item) containing the @code{INCLUDE} keyword. In particular, headlines within
-the file will become children of the current section. That behaviour can be
-changed by providing an additional keyword parameter, @code{:minlevel}. In
-that case, all headlines in the included file will be shifted so the one with
-the lowest level reaches that specified level. For example, to make a file
-become a sibling of the current top-level headline, use
+The first parameter names the the file to include. The optional second and
+third parameter specify the markup (i.e., @samp{example} or @samp{src}), and,
+if the markup is @samp{src}, the language for formatting the contents.
+
+If markup is requested, the included content will be placed within an
+appropriate block@footnote{While you can request paragraphs (@samp{verse},
+@samp{quote}, @samp{center}), but this places severe restrictions on the type
+of content that is permissible}. No changes to the included content are made
+and it is the responsibility of the user to ensure that the result is valid
+Org syntax. For markup @samp{example} and @samp{src}, which is requesting a
+literal example, the content will be code-escaped before inclusion.
+
+If no markup is requested, the text will be assumed to be in Org mode format
+and will be processed normally. However, footnote labels (@pxref{Footnotes})
+in the file will be made local to that file. Contents of the included file
+will belong to the same structure (headline, item) containing the
+@code{INCLUDE} keyword. In particular, headlines within the file will become
+children of the current section. That behavior can be changed by providing
+an additional keyword parameter, @code{:minlevel}. In that case, all
+headlines in the included file will be shifted so the one with the lowest
+level reaches that specified level. For example, to make a file become a
+sibling of the current top-level headline, use
@example
#+INCLUDE: "~/my-book/chapter2.org" :minlevel 1
@end example
You can also include a portion of a file by specifying a lines range using
-the @code{:lines} parameter. The line at the upper end of the range will not
-be included. The start and/or the end of the range may be omitted to use the
-obvious defaults.
+the @code{:lines} keyword parameter. The line at the upper end of the range
+will not be included. The start and/or the end of the range may be omitted
+to use the obvious defaults.
@example
#+INCLUDE: "~/.emacs" :lines "5-10" @r{Include lines 5 to 10, 10 excluded}
@@ -9980,7 +10014,7 @@ obvious defaults.
Visit the include file at point.
@end table
-@node Index entries, Macro replacement, Include files, Markup
+@node Index entries
@section Index entries
@cindex index entries, for publishing
@@ -9998,7 +10032,7 @@ an index} for more information.
-@node Macro replacement, Embedded @LaTeX{}, Index entries, Markup
+@node Macro replacement
@section Macro replacement
@cindex macro replacement, during export
@cindex #+MACRO
@@ -10009,24 +10043,34 @@ You can define text snippets with
#+MACRO: name replacement text $1, $2 are arguments
@end example
-@noindent which can be referenced in
-paragraphs, verse blocks, table cells and some keywords with
-@code{@{@{@{name(arg1,arg2)@}@}@}}@footnote{Since commas separate arguments,
+@noindent which can be referenced
+@code{@{@{@{name(arg1, arg2)@}@}@}}@footnote{Since commas separate arguments,
commas within arguments have to be escaped with a backslash character.
Conversely, backslash characters before a comma, and only them, need to be
-escaped with another backslash character.}. In addition to defined macros,
-@code{@{@{@{title@}@}@}}, @code{@{@{@{author@}@}@}}, etc., will reference
-information set by the @code{#+TITLE:}, @code{#+AUTHOR:}, and similar lines.
-Also, @code{@{@{@{time(@var{FORMAT})@}@}@}} and
+escaped with another backslash character.}.
+
+These references, called macros, can be inserted anywhere Org markup is
+recognized: paragraphs, headlines, verse blocks, tables cells and lists.
+They cannot be used within ordinary keywords (starting with @code{#+}) but
+are allowed in @code{#+CAPTION}, @code{#+TITLE}, @code{#+AUTHOR} and
+@code{#+EMAIL}.
+