summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile1
-rw-r--r--README_maintainer1
-rw-r--r--contrib/README3
-rw-r--r--contrib/lisp/ob-eukleides.el2
-rw-r--r--contrib/lisp/ob-mathematica.el79
-rw-r--r--contrib/lisp/ob-oz.el2
-rw-r--r--contrib/lisp/ob-stata.el313
-rw-r--r--contrib/lisp/ob-tcl.el4
-rw-r--r--contrib/lisp/org-annotate-file.el26
-rw-r--r--contrib/lisp/org-bibtex-extras.el22
-rw-r--r--contrib/lisp/org-colview-xemacs.el101
-rw-r--r--contrib/lisp/org-contacts.el124
-rw-r--r--contrib/lisp/org-download.el84
-rw-r--r--contrib/lisp/org-drill.el157
-rw-r--r--contrib/lisp/org-effectiveness.el55
-rw-r--r--contrib/lisp/org-eldoc.el165
-rw-r--r--contrib/lisp/org-eww.el162
-rw-r--r--contrib/lisp/org-expiry.el5
-rw-r--r--contrib/lisp/org-git-link.el27
-rw-r--r--contrib/lisp/org-index.el3712
-rw-r--r--contrib/lisp/org-license.el41
-rw-r--r--contrib/lisp/org-mac-link.el595
-rw-r--r--contrib/lisp/org-mew.el4
-rw-r--r--contrib/lisp/org-mime.el132
-rw-r--r--contrib/lisp/org-mtags.el255
-rw-r--r--contrib/lisp/org-notmuch.el36
-rw-r--r--contrib/lisp/org-passwords.el384
-rw-r--r--contrib/lisp/org-toc.el4
-rw-r--r--contrib/lisp/org-velocity.el309
-rw-r--r--contrib/lisp/org-wikinodes.el9
-rw-r--r--contrib/lisp/ox-bibtex.el85
-rw-r--r--contrib/lisp/ox-deck.el13
-rw-r--r--contrib/lisp/ox-extra.el190
-rw-r--r--contrib/lisp/ox-freemind.el2
-rw-r--r--contrib/lisp/ox-gfm.el193
-rw-r--r--contrib/lisp/ox-groff.el39
-rw-r--r--contrib/lisp/ox-koma-letter.el101
-rw-r--r--contrib/lisp/ox-rss.el68
-rw-r--r--contrib/lisp/ox-s5.el10
-rw-r--r--contrib/lisp/ox-taskjuggler.el61
-rw-r--r--doc/htmlxref.cnf2
-rw-r--r--doc/org.texi2335
-rw-r--r--doc/orgguide.texi111
-rw-r--r--doc/texinfo.tex3161
-rw-r--r--etc/ORG-NEWS409
-rw-r--r--etc/styles/OrgOdtStyles.xml20
-rw-r--r--lisp/ob-C.el355
-rw-r--r--lisp/ob-J.el10
-rw-r--r--lisp/ob-R.el191
-rw-r--r--lisp/ob-asymptote.el5
-rw-r--r--lisp/ob-awk.el23
-rw-r--r--lisp/ob-clojure.el58
-rw-r--r--lisp/ob-comint.el2
-rw-r--r--lisp/ob-coq.el2
-rw-r--r--lisp/ob-core.el649
-rw-r--r--lisp/ob-ditaa.el18
-rw-r--r--lisp/ob-dot.el4
-rw-r--r--lisp/ob-emacs-lisp.el2
-rw-r--r--lisp/ob-eval.el7
-rw-r--r--lisp/ob-exp.el76
-rw-r--r--lisp/ob-forth.el86
-rw-r--r--lisp/ob-gnuplot.el18
-rw-r--r--lisp/ob-groovy.el20
-rw-r--r--lisp/ob-haskell.el9
-rw-r--r--lisp/ob-io.el10
-rw-r--r--lisp/ob-java.el22
-rw-r--r--lisp/ob-js.el9
-rw-r--r--lisp/ob-keys.el1
-rw-r--r--lisp/ob-latex.el85
-rw-r--r--lisp/ob-lilypond.el286
-rw-r--r--lisp/ob-lisp.el4
-rw-r--r--lisp/ob-lob.el9
-rw-r--r--lisp/ob-maxima.el9
-rw-r--r--lisp/ob-ocaml.el9
-rw-r--r--lisp/ob-octave.el12
-rw-r--r--lisp/ob-processing.el197
-rw-r--r--lisp/ob-python.el10
-rw-r--r--lisp/ob-ref.el33
-rw-r--r--lisp/ob-ruby.el41
-rw-r--r--lisp/ob-scala.el10
-rw-r--r--lisp/ob-scheme.el23
-rw-r--r--lisp/ob-screen.el4
-rw-r--r--lisp/ob-shell.el88
-rw-r--r--lisp/ob-sql.el23
-rw-r--r--lisp/ob-table.el32
-rw-r--r--lisp/ob-tangle.el42
-rw-r--r--lisp/org-agenda.el1267
-rw-r--r--lisp/org-archive.el80
-rw-r--r--lisp/org-attach.el29
-rw-r--r--lisp/org-bbdb.el7
-rw-r--r--lisp/org-bibtex.el41
-rw-r--r--lisp/org-capture.el57
-rw-r--r--lisp/org-clock.el465
-rw-r--r--lisp/org-colview.el153
-rw-r--r--lisp/org-compat.el36
-rw-r--r--lisp/org-docview.el6
-rw-r--r--lisp/org-element.el2391
-rw-r--r--lisp/org-entities.el943
-rw-r--r--lisp/org-faces.el109
-rw-r--r--lisp/org-footnote.el648
-rw-r--r--lisp/org-gnus.el14
-rw-r--r--lisp/org-habit.el79
-rw-r--r--lisp/org-info.el32
-rw-r--r--lisp/org-inlinetask.el23
-rw-r--r--lisp/org-list.el296
-rw-r--r--lisp/org-macro.el137
-rw-r--r--lisp/org-macs.el81
-rw-r--r--lisp/org-mobile.el5
-rw-r--r--lisp/org-mouse.el16
-rw-r--r--lisp/org-pcomplete.el4
-rw-r--r--lisp/org-plot.el148
-rw-r--r--lisp/org-rmail.el2
-rw-r--r--lisp/org-src.el1361
-rw-r--r--lisp/org-table.el1947
-rw-r--r--lisp/org-timer.el241
-rwxr-xr-x[-rw-r--r--]lisp/org.el7467
-rw-r--r--lisp/ox-ascii.el777
-rw-r--r--lisp/ox-beamer.el180
-rw-r--r--lisp/ox-html.el1266
-rw-r--r--lisp/ox-icalendar.el360
-rw-r--r--lisp/ox-latex.el1457
-rw-r--r--lisp/ox-man.el97
-rw-r--r--lisp/ox-md.el160
-rw-r--r--lisp/ox-odt.el695
-rw-r--r--lisp/ox-org.el102
-rw-r--r--lisp/ox-publish.el193
-rw-r--r--lisp/ox-texinfo.el1497
-rw-r--r--lisp/ox.el2263
-rw-r--r--mk/org-fixup.el16
-rw-r--r--mk/server.mk4
-rw-r--r--mk/targets.mk4
-rw-r--r--testing/README20
-rw-r--r--testing/examples/babel.org82
-rw-r--r--testing/examples/include.html1
-rw-r--r--testing/examples/include.org25
-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/setupfile.org1
-rw-r--r--testing/lisp/test-ob-C.el161
-rw-r--r--testing/lisp/test-ob-awk.el9
-rw-r--r--testing/lisp/test-ob-emacs-lisp.el10
-rw-r--r--testing/lisp/test-ob-exp.el232
-rw-r--r--testing/lisp/test-ob-lilypond.el365
-rw-r--r--testing/lisp/test-ob-lob.el108
-rw-r--r--testing/lisp/test-ob-ruby.el39
-rw-r--r--testing/lisp/test-ob-shell.el39
-rw-r--r--testing/lisp/test-ob.el401
-rw-r--r--testing/lisp/test-org-clock.el69
-rw-r--r--testing/lisp/test-org-element.el892
-rw-r--r--testing/lisp/test-org-footnote.el264
-rw-r--r--testing/lisp/test-org-list.el56
-rw-r--r--testing/lisp/test-org-macro.el59
-rw-r--r--testing/lisp/test-org-src.el54
-rw-r--r--testing/lisp/test-org-table.el595
-rw-r--r--testing/lisp/test-org-timer.el275
-rw-r--r--testing/lisp/test-org.el2508
-rw-r--r--testing/lisp/test-ox.el1288
-rw-r--r--testing/org-test.el19
160 files changed, 31848 insertions, 19172 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 ce06116..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)
diff --git a/README_maintainer b/README_maintainer
index 04dc2c0..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.
diff --git a/contrib/README b/contrib/README
index 2a67b65..7204cc3 100644
--- a/contrib/README
+++ b/contrib/README
@@ -26,9 +26,11 @@ 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-eldoc.el --- Eldoc documentation for SRC blocks
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-eww.el --- Support link/copy/paste from eww to Org-mode
org-expiry.el --- Expiry mechanism for Org entries
org-export-generic.el --- Export framework for configurable backends
org-git-link.el --- Provide org links to specific file version
@@ -80,6 +82,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 c8ce881..cb5bb84 100644
--- a/contrib/lisp/ob-eukleides.el
+++ b/contrib/lisp/ob-eukleides.el
@@ -81,7 +81,7 @@ This function is called by `org-babel-execute-src-block'."
(shell-command (format org-eukleides-eps-to-raster
(concat (file-name-sans-extension out-file) ".eps")
(concat (file-name-sans-extension out-file) ".png")))
- (error "Conversion to PNG not supported. use a file with an EPS name")))
+ (error "Conversion to PNG not supported. Use a file with an EPS name")))
(with-temp-file in-file (insert body))
(message "%s" cmd) (org-babel-eval cmd "")
diff --git a/contrib/lisp/ob-mathematica.el b/contrib/lisp/ob-mathematica.el
new file mode 100644
index 0000000..a796741
--- a/dev/null
+++ b/contrib/lisp/ob-mathematica.el
@@ -0,0 +1,79 @@
+;;; ob-mathematica.el --- org-babel functions for Mathematica evaluation
+
+;; Copyright (C) 2014 Yi Wang
+
+;; Authors: Yi Wang
+;; Keywords: literate programming, reproducible research
+;; Homepage: https://github.com/tririver/wy-els/blob/master/ob-mathematica.el
+;; Distributed under the GNU GPL v2 or later
+
+;; Org-Babel support for evaluating Mathematica source code.
+
+;;; Code:
+(require 'ob)
+(require 'ob-ref)
+(require 'ob-comint)
+(require 'ob-eval)
+;; Optionally require mma.el for font lock, etc
+(require 'mma nil 'noerror)
+(add-to-list 'org-src-lang-modes '("mathematica" . "mma"))
+
+(defvar org-babel-tangle-lang-exts)
+(add-to-list 'org-babel-tangle-lang-exts '("mathematica" . "m"))
+
+(defvar org-babel-default-header-args:mathematica '())
+
+(defvar org-babel-mathematica-command "MathematicaScript -script"
+ "Name of the command for executing Mathematica code.")
+
+(defvar org-babel-mathematica-command-alt "math -noprompt"
+ "Name of the command for executing Mathematica code.")
+
+(defun org-babel-expand-body:mathematica (body params)
+ "Expand BODY according to PARAMS, return the expanded body."
+ (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
+ (concat
+ (mapconcat ;; define any variables
+ (lambda (pair)
+ (format "%s=%s;"
+ (car pair)
+ (org-babel-mathematica-var-to-mathematica (cdr pair))))
+ vars "\n") "\nPrint[\n" body "\n]\n")))
+
+(defun org-babel-execute:mathematica (body params)
+ "Execute a block of Mathematica code with org-babel. This function is
+called by `org-babel-execute-src-block'"
+ (let* ((result-params (cdr (assoc :result-params params)))
+ (full-body (org-babel-expand-body:mathematica body params))
+ (tmp-script-file (org-babel-temp-file "mathematica-"))
+ (cmd org-babel-mathematica-command))
+ ;; actually execute the source-code block
+ (with-temp-file tmp-script-file (insert full-body))
+ ;; (with-temp-file "/tmp/dbg" (insert full-body))
+ ((lambda (raw)
+ (if (or (member "code" result-params)
+ (member "pp" result-params)
+ (and (member "output" result-params)
+ (not (member "table" result-params))))
+ raw
+ (org-babel-script-escape (org-babel-trim raw))))
+ (org-babel-eval (concat cmd " " tmp-script-file) ""))))
+
+(defun org-babel-prep-session:mathematica (session params)
+ "This function does nothing so far"
+ (error "Currently no support for sessions"))
+
+(defun org-babel-prep-session:mathematica (session body params)
+ "This function does nothing so far"
+ (error "Currently no support for sessions"))
+
+(defun org-babel-mathematica-var-to-mathematica (var)
+ "Convert an elisp value to a Mathematica variable.
+Convert an elisp value, VAR, into a string of Mathematica source code
+specifying a variable of the same value."
+ (if (listp var)
+ (concat "{" (mapconcat #'org-babel-mathematica-var-to-mathematica var ", ") "}")
+ (format "%S" var)))
+
+(provide 'ob-mathematica)
+
diff --git a/contrib/lisp/ob-oz.el b/contrib/lisp/ob-oz.el
index 3531d95..fc778f5 100644
--- a/contrib/lisp/ob-oz.el
+++ b/contrib/lisp/ob-oz.el
@@ -226,7 +226,7 @@ called by `org-babel-execute-src-block' via multiple-value-bind."
((member "value" result-params)
(message "Org-babel: executing Oz expression")
(oz-send-string-expression full-body (or wait-time 1)))
- (t (error "either 'output' or 'results' must be members of :results.")))
+ (t (error "either 'output' or 'results' must be members of :results")))
(org-babel-pick-name (cdr (assoc :colname-names params))
(cdr (assoc :colnames params)))
(org-babel-pick-name (cdr (assoc :roname-names params))
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 50afe5a..d66357d 100644
--- a/contrib/lisp/ob-tcl.el
+++ b/contrib/lisp/ob-tcl.el
@@ -62,7 +62,7 @@ This function is called by `org-babel-execute-src-block'."
(defun org-babel-prep-session:tcl (session params)
"Prepare SESSION according to the header arguments in PARAMS."
- (error "Sessions are not supported for Tcl."))
+ (error "Sessions are not supported for Tcl"))
(defun org-babel-variable-assignments:tcl (params)
"Return list of tcl statements assigning the block's variables."
@@ -111,7 +111,7 @@ close $o
If RESULT-TYPE equals 'output then return a list of the outputs
of the statements in BODY, if RESULT-TYPE equals 'value then
return the value of the last statement in BODY, as elisp."
- (when session (error "Sessions are not supported for Tcl."))
+ (when session (error "Sessions are not supported for Tcl"))
(case result-type
(output (org-babel-eval org-babel-tcl-command body))
(value (let ((tmp-file (org-babel-temp-file "tcl-")))
diff --git a/contrib/lisp/org-annotate-file.el b/contrib/lisp/org-annotate-file.el
index 8fbb590..b8e8bd9 100644
--- a/contrib/lisp/org-annotate-file.el
+++ b/contrib/lisp/org-annotate-file.el
@@ -59,14 +59,24 @@
(require 'org)
-(defvar org-annotate-file-storage-file "~/.org-annotate-file.org"
- "File in which to keep annotations.")
-
-(defvar org-annotate-file-add-search nil
- "If non-nil, add a link as a second level to the actual file location.")
-
-(defvar org-annotate-file-always-open t
- "If non-nil, always expand the full tree when visiting the annotation file.")
+(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.
diff --git a/contrib/lisp/org-bibtex-extras.el b/contrib/lisp/org-bibtex-extras.el
index 8d5b2ac..5f05039 100644
--- a/contrib/lisp/org-bibtex-extras.el
+++ b/contrib/lisp/org-bibtex-extras.el
@@ -83,19 +83,6 @@ For example, to point to your `obe-bibtex-file' use the following.
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 (or obe-bibtex-file
- (error "`obe-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)))
-
(defun obe-html-export-citations ()
"Convert all \\cite{...} citations in the current file into HTML links."
(save-excursion
@@ -107,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-colview-xemacs.el b/contrib/lisp/org-colview-xemacs.el
index 67a2aad..a27275e 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-2014
+;; Copyright (C) 2004-2015
;; Carsten Dominik
;; Author: Carsten Dominik <carsten at orgmode dot org>
@@ -303,10 +303,6 @@ This is the compiled version of the format.")
(beginning-of-line 1)
(and (looking-at "\\(\\**\\)\\(\\* \\)")
(org-get-level-face 2))))
- (item (save-match-data
- (org-remove-tabs
- (buffer-substring-no-properties
- (point-at-bol) (point-at-eol)))))
(color (if (featurep 'xemacs)
(save-excursion
(beginning-of-line 1)
@@ -335,10 +331,10 @@ This is the compiled version of the format.")
(while (setq column (pop fmt))
(setq property (car column)
title (nth 1 column)
- ass (if (equal property "ITEM")
- (cons "ITEM" item)
- (assoc property props))
- width (or (cdr (assoc property org-columns-current-maxwidths))
+ ass (assoc-string property props t)
+ width (or (cdr (assoc-string property
+ org-columns-current-maxwidths
+ t))
(nth 2 column)
(length property))
f (format (if (featurep 'xemacs) "%%-%d.%ds |" "%%-%d.%ds | ")
@@ -351,9 +347,7 @@ This is the compiled version of the format.")
(funcall org-columns-modify-value-for-display-function
title val))
((equal property "ITEM")
- (if (derived-mode-p 'org-mode)
- (org-columns-cleanup-item
- val org-columns-current-fmt-compiled)))
+ (org-columns-compact-links val))
((and calc (functionp calc)
(not (string= val ""))
(not (get-text-property 0 'org-computed val)))
@@ -438,7 +432,9 @@ This is the compiled version of the format.")
(while (setq column (pop fmt))
(setq property (car column)
str (or (nth 1 column) property)
- width (or (cdr (assoc property org-columns-current-maxwidths))
+ width (or (cdr (assoc-string property
+ org-columns-current-maxwidths
+ t))
(nth 2 column)
(length str))
widths (push width widths)
@@ -503,26 +499,6 @@ This is the compiled version of the format.")
(current-buffer))
(setq truncate-lines org-colview-initial-truncate-line-value)))))
-
-(defun org-columns-cleanup-item (item fmt)
- "Remove from ITEM what is a column in the format FMT."
- (if (not org-complex-heading-regexp)
- item
- (when (string-match org-complex-heading-regexp item)
- (setq item
- (concat
- (org-add-props (match-string 1 item) nil
- 'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) (match-beginning 1))))))
- (and (match-end 2) (not (assoc "TODO" fmt)) (concat " " (match-string 2 item)))
- (and (match-end 3) (not (assoc "PRIORITY" fmt)) (concat " " (match-string 3 item)))
- " " (save-match-data (org-columns-compact-links (or (match-string 4 item) "")))
- (and (match-end 5) (not (assoc "TAGS" fmt)) (concat " " (match-string 5 item)))))
- (add-text-properties
- 0 (1+ (match-end 1))
- (list 'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) (match-beginning 1))))))
- item)
- item)))
-
(defun org-columns-compact-links (s)
"Replace [[link][desc]] with [desc] or [link]."
(while (string-match org-bracket-link-regexp s)
@@ -657,7 +633,7 @@ Where possible, use the standard interface for changing this line."
(org-columns-display-here)))
(org-move-to-column col)
(if (and (derived-mode-p 'org-mode)
- (nth 3 (assoc key org-columns-current-fmt-compiled)))
+ (nth 3 (assoc-string key org-columns-current-fmt-compiled t)))
(org-columns-update key)))))))
(defun org-edit-headline () ; FIXME: this is not columns specific. Make interactive????? Use from agenda????
@@ -736,7 +712,9 @@ an integer, select that value."
org-columns-overlays)))
(allowed (or (org-property-get-allowed-values pom key)
(and (memq
- (nth 4 (assoc key org-columns-current-fmt-compiled))
+ (nth 4 (assoc-string key
+ org-columns-current-fmt-compiled
+ t))
'(checkbox checkbox-n-of-m checkbox-percent))
'("[ ]" "[X]"))
(org-colview-construct-allowed-dates value)))
@@ -785,7 +763,7 @@ an integer, select that value."
(org-columns-eval '(org-entry-put pom key nval)))
(org-columns-display-here)))
(org-move-to-column col)
- (and (nth 3 (assoc key org-columns-current-fmt-compiled))
+ (and (nth 3 (assoc-string key org-columns-current-fmt-compiled t))
(org-columns-update key))))))
(defun org-colview-construct-allowed-dates (s)
@@ -924,7 +902,9 @@ interactive function `org-columns-new'.
"Insert a new column, to the left of the current column."
(interactive)
(let ((n (org-columns-current-column))
- (editp (and prop (assoc prop org-columns-current-fmt-compiled)))
+ (editp (and prop (assoc-string prop
+ org-columns-current-fmt-compiled
+ t)))
cell)
(setq prop (org-icompleting-read
"Property: " (mapcar 'list (org-buffer-property-keys t nil t))
@@ -980,7 +960,9 @@ interactive function `org-columns-new'.
(let* ((n (org-columns-current-column))
(entry (nth n org-columns-current-fmt-compiled))
(width (or (nth 2 entry)
- (cdr (assoc (car entry) org-columns-current-maxwidths)))))
+ (cdr (assoc-string (car entry)
+ org-columns-current-maxwidths
+ t)))))
(setq width (max 1 (+ width arg)))
(setcar (nthcdr 2 entry) width)
(org-columns-store-format)
@@ -1052,11 +1034,14 @@ Don't set this, this is meant for dynamic scoping.")
(push (cons (match-string 1 s) 1) rtn)
(setq start (match-end 0)))
(mapc (lambda (x)
- (setcdr x (apply 'max
+ (setcdr x
+ (apply 'max
+ (let ((prop (car x)))
(mapcar
(lambda (y)
- (length (or (cdr (assoc (car x) (cdr y))) " ")))
- cache))))
+ (length (or (cdr (assoc-string prop (cdr y) t))
+ " ")))
+ cache)))))
rtn)
rtn))
@@ -1081,9 +1066,11 @@ Don't set this, this is meant for dynamic scoping.")
(when (equal (overlay-get ov 'org-columns-key) property)
(setq pos (overlay-start ov))
(goto-char pos)
- (when (setq val (cdr (assoc property
- (get-text-property
- (point-at-bol) 'org-summaries))))
+ (when (setq val (cdr (assoc-string
+ property
+ (get-text-property
+ (point-at-bol) 'org-summaries)
+ t)))
(setq fmt (overlay-get ov 'org-columns-format))
(overlay-put ov 'org-columns-value val)
(if (featurep 'xemacs)
@@ -1098,11 +1085,11 @@ Don't set this, this is meant for dynamic scoping.")
"Sum the values of property PROPERTY hierarchically, for the entire buffer."
(interactive)
(let* ((re org-outline-regexp-bol)
- (lmax 30) ; Does anyone use deeper levels???
+ (lmax 30) ; Does anyone use deeper levels???
(lvals (make-vector lmax nil))
(lflag (make-vector lmax nil))
(level 0)
- (ass (assoc property org-columns-current-fmt-compiled))
+ (ass (assoc-string property org-columns-current-fmt-compiled t))
(format (nth 4 ass))
(printf (nth 5 ass))
(fun (nth 6 ass))
@@ -1131,12 +1118,12 @@ Don't set this, this is meant for dynamic scoping.")
str1 (org-add-props (copy-sequence str) nil 'org-computed t 'face 'bold)
useval (if flag str1 (if valflag val ""))
sum-alist (get-text-property sumpos 'org-summaries))
- (if (assoc property sum-alist)
- (setcdr (assoc property sum-alist) useval)
- (push (cons property useval) sum-alist)
- (org-unmodified
- (add-text-properties sumpos (1+ sumpos)
- (list 'org-summaries sum-alist))))
+ (let ((old (assoc-string property sum-alist t)))
+ (if old (setcdr old useval)
+ (push (cons property useval) sum-alist)
+ (org-unmodified
+ (add-text-properties sumpos (1+ sumpos)
+ (list 'org-summaries sum-alist)))))
(when (and val (not (equal val (if flag str val))))
(org-entry-put nil property (if flag str val)))
;; add current to current level accumulator
@@ -1553,7 +1540,7 @@ and tailing newline characters."
(org-get-at-bol 'org-marker)))
(setq p (org-entry-properties m))
- (when (or (not (setq a (assoc org-effort-property p)))
+ (when (or (not (setq a (assoc-string org-effort-property p t)))
(not (string-match "\\S-" (or (cdr a) ""))))
;; OK, the property is not defined. Use appointment duration?
(when (and org-agenda-columns-add-appointments-to-effort-sum
@@ -1617,7 +1604,7 @@ This will add overlays to the date lines, to show the summary for each day."
(t ;; do the summary
(setq lsum nil)
(dolist (x entries)
- (setq v (cdr (assoc prop x)))
+ (setq v (cdr (assoc-string prop x t)))
(if v
(push
(funcall
@@ -1667,8 +1654,10 @@ This will add overlays to the date lines, to show the summary for each day."
(if (equal (car fm) "CLOCKSUM")
(org-clock-sum)
(when (and (nth 4 fm)
- (setq a (assoc (car fm)
- org-columns-current-fmt-compiled))
+ (setq a (assoc-string
+ (car fm)
+ org-columns-current-fmt-compiled
+ t))
(equal (nth 4 a) (nth 4 fm)))
(org-columns-compute (car fm)))))))))))
diff --git a/contrib/lisp/org-contacts.el b/contrib/lisp/org-contacts.el
index 7cc42fc..bc07fc1 100644
--- a/contrib/lisp/org-contacts.el
+++ b/contrib/lisp/org-contacts.el
@@ -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."
@@ -826,7 +882,7 @@ address."
(setq email (org-contacts-strip-link email))
(org-contacts-check-mail-address email)
(compose-mail (org-contacts-format-email (org-get-heading t) email)))))
- (error (format "This contact has no mail address set (no %s property)."
+ (error (format "This contact has no mail address set (no %s property)"
org-contacts-email-property)))))))
(defun org-contacts-get-icon (&optional pom)
@@ -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-download.el b/contrib/lisp/org-download.el
index 39312cf..6bff649 100644
--- a/contrib/lisp/org-download.el
+++ b/contrib/lisp/org-download.el
@@ -1,12 +1,12 @@
;;; org-download.el --- Image drag-and-drop for Emacs org-mode
-;; Copyright (C) 2014 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2015 Free Software Foundation, Inc.
;; Author: Oleh Krehel
;; Keywords: images, screenshots, download
;; Homepage: http://orgmode.org
-;; This file is part of GNU Emacs.
+;; 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
@@ -48,7 +48,7 @@
;; * 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; -*-
+;; # -*- 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
@@ -112,6 +112,14 @@ Set this to \"\" if you don't want time stamps."
:type 'string
:group 'org-download)
+(defcustom org-download-img-regex-list
+ '("<img +src=\"" "<img +\\(class=\"[^\"]+\"\\)? *src=\"")
+ "This regex is used to unalias links that look like images.
+The html to which the links points will be searched for these
+regexes, one by one, until one succeeds. The found image address
+will be used."
+ :group 'org-download)
+
(defcustom org-download-screenshot-method "gnome-screenshot -a -f %s"
"The tool to capture screenshots."
:type '(choice
@@ -129,10 +137,13 @@ Set this to \"\" if you don't want time stamps."
"Return the heading of the current entry's LVL level parent."
(save-excursion
(let ((cur-lvl (org-current-level)))
+ (if cur-lvl
+ (progn
(unless (= cur-lvl 1)
(org-up-heading-all (- (1- (org-current-level)) lvl)))
(substring-no-properties
- (org-get-heading)))))
+ (org-get-heading)))
+ ""))))
(defun org-download--dir-1 ()
"Return the first part of the directory path for `org-download--dir'.
@@ -170,17 +181,22 @@ It's affected by `org-download-timestamp' and `org-download--dir'."
(car (url-path-and-query
(url-generic-parse-url link)))))
(dir (org-download--dir)))
- (format "%s/%s%s.%s"
- dir
+ (when (string-match ".*?\\.\\(?:png\\|jpg\\)\\(.*\\)$" filename)
+ (setq filename (replace-match "" nil nil filename 1)))
+ (abbreviate-file-name
+ (expand-file-name
+ (format "%s%s.%s"
(file-name-sans-extension filename)
(format-time-string org-download-timestamp)
- (file-name-extension filename))))
+ (file-name-extension filename))
+ dir))))
(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)
+ (cond ((and (not (file-remote-p link))
+ (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))
@@ -241,6 +257,19 @@ The screenshot tool is determined by `org-download-screenshot-method'."
(defun org-download-image (link)
"Save image at address LINK to `org-download--dir'."
(interactive "sUrl: ")
+ (unless (image-type-from-file-name link)
+ (with-current-buffer
+ (url-retrieve-synchronously link t)
+ (let ((regexes org-download-img-regex-list)
+ lnk)
+ (while (and (not lnk) regexes)
+ (goto-char (point-min))
+ (when (re-search-forward (pop regexes) nil t)
+ (backward-char)
+ (setq lnk (read (current-buffer)))))
+ (if lnk
+ (setq link lnk)
+ (error "link %s does not point to an image; unaliasing failed" link)))))
(let ((filename
(if (eq org-download-method 'attach)
(let ((org-download-image-dir (progn (require 'org-attach)
@@ -255,12 +284,14 @@ The screenshot tool is determined by `org-download-screenshot-method'."
(if (looking-back "^[ \t]+")
(delete-region (match-beginning 0) (match-end 0))
(newline))
- (insert (format "#+DOWNLOADED: %s @ %s\n%s [[%s]]"
+ (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))
+ (format
+ "#+attr_html: :width %dpx\n" org-download-image-width))
filename))
(org-display-inline-images))))
@@ -299,7 +330,7 @@ When TIMES isn't nil, delete only TIMES links."
(while (and (>= (decf times) 0)
(re-search-forward "\\[\\[\\([^]]*\\)\\]\\]" end t))
(let ((str (match-string-no-properties 1)))
- (delete-region (match-beginning 0)
+ (delete-region beg
(match-end 0))
(when (file-exists-p str)
(delete-file str))))))
@@ -307,16 +338,41 @@ When TIMES isn't nil, delete only TIMES links."
(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)
+ (cond ((eq major-mode 'org-mode)
;; probably shouldn't redirect
(unless (org-download-image uri)
- (message "not an image URL"))
+ (message "not an image URL")))
+ ((eq major-mode 'dired-mode)
+ (org-download-dired uri))
;; redirect to someone else
+ (t
(let ((dnd-protocol-alist
(rassq-delete-all
'org-download-dnd
(copy-alist dnd-protocol-alist))))
- (dnd-handle-one-url nil action uri))))
+ (dnd-handle-one-url nil action uri)))))
+
+(defun org-download-dired (uri)
+ "Download URI to current directory."
+ (raise-frame)
+ (let ((filename (file-name-nondirectory
+ (car (url-path-and-query
+ (url-generic-parse-url uri))))))
+ (message "Downloading %s to %s ..."
+ filename
+ (expand-file-name filename))
+ (url-retrieve
+ uri
+ (lambda (status filename)
+ (let ((err (plist-get status :error)))
+ (if err (error
+ "\"%s\" %s" uri
+ (downcase (nth 2 (assq (nth 2 err) url-http-codes))))))
+ (let ((coding-system-for-write 'no-conversion))
+ (write-region nil nil filename nil nil nil 'confirm)))
+ (list
+ (expand-file-name filename))
+ t t)))
(defun org-download-enable ()
"Enable org-download."
diff --git a/contrib/lisp/org-drill.el b/contrib/lisp/org-drill.el
index e5b0d49..81012e1 100644
--- a/contrib/lisp/org-drill.el
+++ b/contrib/lisp/org-drill.el
@@ -2,7 +2,7 @@
;;; org-drill.el - Self-testing using spaced repetition
;;;
;;; Author: Paul Sexton <eeeickythump@gmail.com>
-;;; Version: 2.4.1
+;;; Version: 2.4.5
;;; Repository at http://bitbucket.org/eeeickythump/org-drill/
;;;
;;;
@@ -512,6 +512,11 @@ for review unless they were already reviewed in the recent past?")
'("LEARN_DATA" "DRILL_LAST_INTERVAL" "DRILL_REPEATS_SINCE_FAIL"
"DRILL_TOTAL_REPEATS" "DRILL_FAILURE_COUNT" "DRILL_AVERAGE_QUALITY"
"DRILL_EASE" "DRILL_LAST_QUALITY" "DRILL_LAST_REVIEWED"))
+(defvar org-drill--lapse-very-overdue-entries-p nil
+ "If non-nil, entries more than 90 days overdue are regarded as 'lapsed'.
+This means that when the item is eventually re-tested it will be
+treated as 'failed' (quality 2) for rescheduling purposes,
+regardless of whether the test was successful.")
;;; Make the above settings safe as file-local variables.
@@ -1198,8 +1203,8 @@ See the documentation for `org-drill-get-item-data' for a description of these."
"If DAYS-AHEAD is supplied it must be a positive integer. The
item will be scheduled exactly this many days into the future."
(let ((delta-days (- (time-to-days (current-time))
- (time-to-days (or (org-get-scheduled-time (point))
- (current-time)))))
+ (time-to-days (or (org-get-scheduled-time (point))
+ (current-time)))))
(ofmatrix org-drill-optimal-factor-matrix)
;; Entries can have weights, 1 by default. Intervals are divided by the
;; item's weight, so an item with a weight of 2 will have all intervals
@@ -1343,8 +1348,9 @@ How well did you do? (0-5, ?=help, e=edit, t=tags, q=quit)"
(failures (org-drill-entry-failure-count)))
(unless *org-drill-cram-mode*
(save-excursion
- (org-drill-smart-reschedule quality
- (nth quality next-review-dates)))
+ (let ((quality (if (org-drill--entry-lapsed-p) 2 quality)))
+ (org-drill-smart-reschedule quality
+ (nth quality next-review-dates))))
(push quality *org-drill-session-qualities*)
(cond
((<= quality org-drill-failure-quality)
@@ -1363,7 +1369,7 @@ 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-active-org-timestamp (current-time))))
+ (time-to-inactive-org-timestamp (current-time))))
quality))
((= ch ?e)
'edit)
@@ -1548,12 +1554,15 @@ visual overlay, or with the string TEXT if it is supplied."
(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.
- ;; And don't hide LaTeX math fragments.
+ ;; Don't hide:
+ ;; - org links, partly because they might contain inline
+ ;; images which we want to keep visible.
+ ;; - LaTeX math fragments
+ ;; - the contents of SRC blocks
(unless (save-match-data
(or (org-pos-in-regexp (match-beginning 0)
org-bracket-link-regexp 1)
+ (org-in-src-block-p)
(org-inside-LaTeX-fragment-p)))
(org-drill-hide-matched-cloze-text)))))
@@ -1704,7 +1713,9 @@ Note: does not actually alter the item."
(org-back-to-heading t)
(let ((lim (save-excursion
(outline-next-heading) (point))))
- (org-end-of-meta-data-and-drawers)
+ (if (fboundp 'org-end-of-meta-data-and-drawers)
+ (org-end-of-meta-data-and-drawers) ; function removed Feb 2015
+ (org-end-of-meta-data t))
(or (>= (point) lim)
(null (re-search-forward "[[:graph:]]" lim t))))))
@@ -1720,12 +1731,13 @@ Note: does not actually alter the item."
;; topic, and should return t if the user chose to see the answer and rate their
;; recall, nil if they chose to quit.
+
(defun org-drill-present-simple-card ()
(with-hidden-comments
(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
+ (org-drill--show-latex-fragments) ; overlay all LaTeX fragments with images
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
@@ -1744,7 +1756,7 @@ 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)
+ (org-drill--show-latex-fragments)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
@@ -1752,6 +1764,13 @@ Note: does not actually alter the item."
(funcall reschedule-fn)))))
+(defun org-drill--show-latex-fragments ()
+ (org-remove-latex-fragment-image-overlays)
+ (if (fboundp 'org-toggle-latex-fragment)
+ (org-toggle-latex-fragment '(4))
+ (org-preview-latex-fragment '(4))))
+
+
(defun org-drill-present-two-sided-card ()
(with-hidden-comments
(with-hidden-cloze-hints
@@ -1762,7 +1781,7 @@ 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)
+ (org-drill--show-latex-fragments)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
@@ -1780,7 +1799,7 @@ 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)
+ (org-drill--show-latex-fragments)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
@@ -1862,7 +1881,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)
+ (org-drill--show-latex-fragments)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
@@ -1911,12 +1930,12 @@ the second to last, etc."
;; 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-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)
+ (org-drill--show-latex-fragments)
(ignore-errors
(org-display-inline-images t))
(org-cycle-hide-drawers 'all)
@@ -2111,26 +2130,28 @@ See `org-drill' for more details."
'org-drill-present-default-answer)
present-empty-cards (third presentation-fn)
presentation-fn (first presentation-fn)))
- (cond
- ((null presentation-fn)
- (message "%s:%d: Unrecognised card type '%s', skipping..."
- (buffer-name) (point) card-type)
- (sit-for 0.5)
- 'skip)
- (t
- (setq cont (funcall presentation-fn))
- (cond
- ((not cont)
- (message "Quit")
- nil)
- ((eql cont 'edit)
- 'edit)
- ((eql cont 'skip)
- 'skip)
- (t
- (save-excursion
- (funcall answer-fn
- (lambda () (org-drill-reschedule)))))))))))))
+ (prog1
+ (cond
+ ((null presentation-fn)
+ (message "%s:%d: Unrecognised card type '%s', skipping..."
+ (buffer-name) (point) card-type)
+ (sit-for 0.5)
+ 'skip)
+ (t
+ (setq cont (funcall presentation-fn))
+ (cond
+ ((not cont)
+ (message "Quit")
+ nil)
+ ((eql cont 'edit)
+ 'edit)
+ ((eql cont 'skip)
+ 'skip)
+ (t
+ (save-excursion
+ (funcall answer-fn
+ (lambda () (org-drill-reschedule))))))))
+ (org-remove-latex-fragment-image-overlays)))))))
(defun org-drill-entries-pending-p ()
@@ -2384,17 +2405,57 @@ all the markers used by Org-Drill will be freed."
(free-marker m)))
+;;; overdue-data is a list of entries, each entry has the form (POS DUE AGE)
+;;; where POS is a marker pointing to the start of the entry, and
+;;; DUE is a number indicating how many days ago the entry was due.
+;;; AGE is the number of days elapsed since item creation (nil if unknown).
+;;; if age > lapse threshold (default 90), sort by age (oldest first)
+;;; if age < lapse threshold, sort by due (biggest first)
+
+
(defun org-drill-order-overdue-entries (overdue-data)
- (setq *org-drill-overdue-entries*
- (mapcar 'car
- (sort (shuffle-list overdue-data)
- (lambda (a b) (> (cdr a) (cdr b)))))))
+ (let* ((lapsed-days (if org-drill--lapse-very-overdue-entries-p
+ 90 most-positive-fixnum))
+ (not-lapsed (remove-if (lambda (a) (> (or (second a) 0) lapsed-days))
+ overdue-data))
+ (lapsed (remove-if-not (lambda (a) (> (or (second a) 0)
+ lapsed-days)) overdue-data)))
+ (setq *org-drill-overdue-entries*
+ (mapcar 'first
+ (append
+ (sort (shuffle-list not-lapsed)
+ (lambda (a b) (> (second a) (second b))))
+ (sort lapsed
+ (lambda (a b) (> (third a) (third b)))))))))
+
+
+(defun org-drill--entry-lapsed-p ()
+ (let ((lapsed-days 90))
+ (and org-drill--lapse-very-overdue-entries-p
+ (> (or (org-drill-entry-days-overdue) 0) lapsed-days))))
+
+
+
+
+(defun org-drill-entry-days-since-creation (&optional use-last-interval-p)
+ "If USE-LAST-INTERVAL-P is non-nil, and DATE_ADDED is missing, use the
+value of DRILL_LAST_INTERVAL instead (as the item's age must be at least
+that many days)."
+ (let ((timestamp (org-entry-get (point) "DATE_ADDED")))
+ (cond
+ (timestamp
+ (- (org-time-stamp-to-now timestamp)))
+ (use-last-interval-p
+ (+ (or (org-drill-entry-days-overdue) 0)
+ (read (or (org-entry-get (point) "DRILL_LAST_INTERVAL") "0"))))
+ (t nil))))
(defun org-drill-entry-status ()
- "Returns a list (STATUS DUE) where DUE is the number of days overdue,
-zero being due today, -1 being scheduled 1 day in the future. STATUS is
-one of the following values:
+ "Returns a list (STATUS DUE AGE) where DUE is the number of days overdue,
+zero being due today, -1 being scheduled 1 day in the future.
+AGE is the number of days elapsed since the item was created (nil if unknown).
+STATUS is one of the following values:
- nil, if the item is not a drill entry, or has an empty body
- :unscheduled
- :future
@@ -2408,6 +2469,7 @@ one of the following values:
(unless (org-at-heading-p)
(org-back-to-heading))
(let ((due (org-drill-entry-days-overdue))
+ (age (org-drill-entry-days-since-creation t))
(last-int (org-drill-entry-last-interval 1)))
(list
(cond
@@ -2446,7 +2508,7 @@ one of the following values:
:young)
(t
:old))
- due))))
+ due age))))
(defun org-drill-progress-message (collected scanned)
@@ -2554,7 +2616,8 @@ work correctly with older versions of org mode. Your org mode version (%s) appea
(sit-for 0.5)
(setq warned-about-id-creation t))
(org-id-get-create) ; ensure drill entry has unique ID
- (destructuring-bind (status due) (org-drill-entry-status)
+ (destructuring-bind (status due age)
+ (org-drill-entry-status)
(case status
(:unscheduled
(incf *org-drill-dormant-entry-count*))
@@ -2572,7 +2635,7 @@ work correctly with older versions of org mode. Your org mode version (%s) appea
(:young
(push (point-marker) *org-drill-young-mature-entries*))
(:overdue
- (push (cons (point-marker) due) overdue-data))
+ (push (list (point-marker) due age) overdue-data))
(:old
(push (point-marker) *org-drill-old-mature-entries*))
)))))
diff --git a/contrib/lisp/org-effectiveness.el b/contrib/lisp/org-effectiveness.el
index 9981712..0d830ab 100644
--- a/contrib/lisp/org-effectiveness.el
+++ b/contrib/lisp/org-effectiveness.el
@@ -127,7 +127,7 @@ many TODO pending"
(concat "0" (number-to-string m))
(number-to-string m)))
-(defun org-effectiveness-plot(startdate enddate)
+(defun org-effectiveness-plot(startdate enddate &optional save)
(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)))
@@ -156,7 +156,7 @@ many TODO pending"
(let ((month startmonth)
(year startyear)
(str ""))
- (while (and (>= endyear year) (>= endmonth month))
+ (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
@@ -165,10 +165,20 @@ many TODO pending"
(setq month (+ 1 month))))
(write-region str nil "/tmp/org-effectiveness"))
;; Create the bar graph
+ (if (eq save t)
+ (setq strplot "/usr/bin/gnuplot -e 'set term png; set output \"/tmp/org-effectiveness.png\"; plot \"/tmp/org-effectiveness\" using 2:xticlabels(1) with histograms' -p")
+ (setq strplot "/usr/bin/gnuplot -e 'plot \"/tmp/org-effectiveness\" using 2:xticlabels(1) with histograms' -p"))
(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")
+ (call-process "/bin/bash" nil t nil "-c" strplot)
(message "gnuplot is not installed")))
+(defun org-effectiveness-plot-save(startdate enddate &optional save)
+ (interactive "sGive me the start date: \nsGive me the end date: " startdate enddate)
+ (org-effectiveness-plot startdate enddate t))
+
+;; (defun org-effectiveness-plot(startdate enddate)
+
+
(defun org-effectiveness-ascii-bar(n &optional label)
"Print a bar with the percentage from 0 to 100 printed in ascii"
(interactive "nPercentage: \nsLabel: ")
@@ -196,6 +206,18 @@ many TODO pending"
(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)
@@ -244,6 +266,33 @@ many TODO pending"
(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-eldoc.el b/contrib/lisp/org-eldoc.el
new file mode 100644
index 0000000..c970b27
--- a/dev/null
+++ b/contrib/lisp/org-eldoc.el
@@ -0,0 +1,165 @@
+;;; org-eldoc.el --- display org header and src block info using eldoc
+
+;; Copyright (c) 2014 Free Software Foundation, Inc.
+
+;; Author: Łukasz Gruner <lukasz@gruner.lu>
+;; Maintainer: Łukasz Gruner <lukasz@gruner.lu>
+;; Version: 6
+;; Package-Requires: ((org "8"))
+;; URL: https://bitbucket.org/ukaszg/org-eldoc
+;; Created: 25/05/2014
+;; Keywords: eldoc, outline, breadcrumb, org, babel, minibuffer
+
+;; This file is not part of 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:
+
+;;; Changelog:
+
+;; As of 01/11/14 switching license to GPL3 to allow submission to org-mode.
+;; 08/11/14 switch code to automatically define eldoc-documentation-function, but don't autostart eldoc-mode.
+
+;;; Code:
+
+(require 'org)
+(require 'ob-core)
+(require 'eldoc)
+
+(defgroup org-eldoc nil "" :group 'org)
+
+(defcustom org-eldoc-breadcrumb-separator "/"
+ "Breadcrumb separator."
+ :group 'org-eldoc
+ :type 'string)
+
+(defcustom org-eldoc-test-buffer-name " *Org-eldoc test buffer*"
+ "Name of the buffer used while testing for mode-local variable values."
+ :group 'org-eldoc
+ :type 'string)
+
+(defun org-eldoc-get-breadcrumb ()
+ "Return breadcrumb if on a headline or nil."
+ (let ((case-fold-search t) cur)
+ (save-excursion
+ (beginning-of-line)
+ (save-match-data
+ (when (looking-at org-complex-heading-regexp)
+ (setq cur (match-string 4))
+ (org-format-outline-path
+ (append (org-get-outline-path) (list cur))
+ (frame-width) "" org-eldoc-breadcrumb-separator))))))
+
+(defun org-eldoc-get-src-header ()
+ "Returns lang and list of header properties if on src definition line and nil otherwise."
+ (let ((case-fold-search t) info lang hdr-args)
+ (save-excursion
+ (beginning-of-line)
+ (save-match-data
+ (when (looking-at "^[ \t]*#\\+\\(begin\\|end\\)_src")
+ (setq info (org-babel-get-src-block-info 'light)
+ lang (propertize (nth 0 info) 'face 'font-lock-string-face)
+ hdr-args (nth 2 info))
+ (concat
+ lang
+ ": "
+ (mapconcat
+ (lambda (elem)
+ (when (and (cdr elem) (not (string= "" (cdr elem))))
+ (concat
+ (propertize (symbol-name (car elem)) 'face 'org-list-dt)
+ " "
+ (propertize (cdr elem) 'face 'org-verbatim)
+ " ")))
+ hdr-args " ")))))))
+
+(defun org-eldoc-get-src-lang ()
+ "Return value of lang for the current block if in block body and nil otherwise."
+ (let ((case-fold-search t))
+ (save-match-data
+ (when (org-between-regexps-p ".*#\\+begin_src"
+ ".*#\\+end_src")
+ (save-excursion
+ (goto-char (org-babel-where-is-src-block-head))
+ (car (org-babel-parse-src-block-match)))))))
+
+(defvar org-eldoc-local-functions-cache (make-hash-table :size 40 :test 'equal)
+ "Cache of major-mode's eldoc-documentation-functions,
+ used by \\[org-eldoc-get-mode-local-documentation-function].")
+
+(defun org-eldoc-get-mode-local-documentation-function (lang)
+ "Check if LANG-mode sets eldoc-documentation-function and return its value."
+ (let ((cached-func (gethash lang org-eldoc-local-functions-cache 'empty))
+ (mode-func (intern-soft (format "%s-mode" lang)))
+ doc-func)
+ (if (eq 'empty cached-func)
+ (when (fboundp mode-func)
+ (with-temp-buffer
+ (funcall mode-func)
+ (setq doc-func (and eldoc-documentation-function
+ (symbol-value 'eldoc-documentation-function)))
+ (puthash lang doc-func org-eldoc-local-functions-cache))
+ doc-func)
+ cached-func)))
+
+(declare-function c-eldoc-print-current-symbol-info "c-eldoc" ())
+(declare-function css-eldoc-function "css-eldoc" ())
+(declare-function php-eldoc-function "php-eldoc" ())
+(declare-function go-eldoc--documentation-function "go-eldoc" ())
+
+(defun org-eldoc-documentation-function ()
+ "Return breadcrumbs when on a headline, args for src block header-line,
+ calls other documentation functions depending on lang when inside src body."
+ (or
+ (org-eldoc-get-breadcrumb)
+ (org-eldoc-get-src-header)
+ (let ((lang (org-eldoc-get-src-lang)))
+ (cond ((or
+ (string= lang "emacs-lisp")
+ (string= lang "elisp")) (if (fboundp 'elisp-eldoc-documentation-function)
+ (elisp-eldoc-documentation-function)
+ (let (eldoc-documentation-function)
+ (eldoc-print-current-symbol-info))))
+ ((or
+ (string= lang "c") ;; http://github.com/nflath/c-eldoc
+ (string= lang "C")) (when (require 'c-eldoc nil t)
+ (c-eldoc-print-current-symbol-info)))
+ ;; https://github.com/zenozeng/css-eldoc
+ ((string= lang "css") (when (require 'css-eldoc nil t)
+ (css-eldoc-function)))
+ ;; https://github.com/zenozeng/php-eldoc
+ ((string= lang "php") (when (require 'php-eldoc nil t)
+ (php-eldoc-function)))
+ ((or
+ (string= lang "go")
+ (string= lang "golang")) (when (require 'go-eldoc nil t)
+ (go-eldoc--documentation-function)))
+ (t (let ((doc-fun (org-eldoc-get-mode-local-documentation-function lang)))
+ (when (fboundp doc-fun) (funcall doc-fun))))))))
+
+;;;###autoload
+(defun org-eldoc-load ()
+ "Set up org-eldoc documentation function."
+ (interactive)
+ (setq-local eldoc-documentation-function #'org-eldoc-documentation-function))
+
+;;;###autoload
+(add-hook 'org-mode-hook #'org-eldoc-load)
+
+(provide 'org-eldoc)
+
+;; -*- coding: utf-8-emacs; -*-
+
+;;; org-eldoc.el ends here
diff --git a/contrib/lisp/org-eww.el b/contrib/lisp/org-eww.el
new file mode 100644
index 0000000..08dac11
--- a/dev/null
+++ b/contrib/lisp/org-eww.el
@@ -0,0 +1,162 @@
+;;; org-eww.el --- Store url and kill from Eww mode for Org
+
+;; Copyright (C) 2014 Free Software Foundation, Inc.
+
+;; Author: Marco Wahl <marcowahlsoft>a<gmailcom>
+;; Keywords: link, eww
+;; Homepage: http://orgmode.org
+;;
+;; 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:
+
+;; When this module is active `org-store-link' (often on key C-c l) in
+;; a eww buffer stores a link to the current url of the eww buffer.
+
+;; In an eww buffer function `org-eww-copy-for-org-mode' kills either
+;; a region or the whole buffer if no region is set and transforms the
+;; text on the fly so that it can be pasted into an org-mode buffer
+;; with hot links.
+
+;; C-c C-x C-w (and also C-c C-x M-w) trigger
+;; `org-eww-copy-for-org-mode'.
+
+;; Hint: A lot of code of this module comes from module org-w3m which
+;; has been written by Andy Steward based on the idea of Richard
+;; Riley. Thanks!
+
+;; Potential: Since the code for w3m and eww is so similar one could
+;; try to refactor.
+
+
+;;; Code:
+(require 'org)
+
+
+;; Store Org-link in eww-mode buffer
+(add-hook 'org-store-link-functions 'org-eww-store-link)
+(defun org-eww-store-link ()
+ "Store a link to the url of a eww buffer."
+ (when (eq major-mode 'eww-mode)
+ (org-store-link-props
+ :type "eww"
+ :link (if (< emacs-major-version 25)
+ eww-current-url
+ (eww-current-url))
+ :url (url-view-url t)
+ :description (if (< emacs-major-version 25)
+ (or eww-current-title eww-current-url)
+ (or (plist-get eww-data :title)
+ (eww-current-url))))))
+
+
+;; Some auxiliary functions concerning links in eww buffers
+(defun org-eww-goto-next-url-property-change ()
+ "Move cursor to the start of next link if exists. Else no
+move. Return point."
+ (goto-char
+ (or (next-single-property-change (point) 'shr-url)
+ (point))))
+
+(defun org-eww-no-next-link-p ()
+ "Whether there is no next link after the cursor.
+Return t if there is no next link; otherwise, return nil."
+ (save-excursion
+ (and (eq (point) (org-eww-goto-next-url-property-change)) t)))
+
+(defun org-eww-url-below-point ()
+ "Return the url below point if there is an url; otherwise, return nil."
+ (get-text-property (point) 'shr-url))
+
+
+(defun org-eww-copy-for-org-mode ()
+ "Copy current buffer content or active region with `org-mode' style links.
+This will encode `link-title' and `link-location' with
+`org-make-link-string', and insert the transformed test into the kill ring,
+so that it can be yanked into an Org-mode buffer with links working correctly."
+ (interactive)
+ (let* ((regionp (org-region-active-p))
+ (transform-start (point-min))
+ (transform-end (point-max))
+ return-content
+ link-location link-title
+ temp-position out-bound)
+ (when regionp
+ (setq transform-start (region-beginning))
+ (setq transform-end (region-end))
+ ;; Deactivate mark if current mark is activate.
+ (if (fboundp 'deactivate-mark) (deactivate-mark)))
+ (message "Transforming links...")
+ (save-excursion
+ (goto-char transform-start)
+ (while (and (not out-bound) ; still inside region to copy
+ (not (org-eww-no-next-link-p))) ; there is a next link
+ ;; store current point before jump next anchor
+ (setq temp-position (point))
+ ;; move to next anchor when current point is not at anchor
+ (or (org-eww-url-below-point)
+ (org-eww-goto-next-url-property-change))
+ (assert (org-eww-url-below-point) t
+ "program logic error: point must have an url below but it hasn't")
+ (if (<= (point) transform-end) ; if point is inside transform bound
+ (progn
+ ;; get content between two links.
+ (if (> (point) temp-position)
+ (setq return-content (concat return-content
+ (buffer-substring
+ temp-position (point)))))
+ ;; get link location at current point.
+ (setq link-location (org-eww-url-below-point))
+ ;; get link title at current point.
+ (setq link-title
+ (buffer-substring
+ (point)
+ (org-eww-goto-next-url-property-change)))
+ ;; concat `org-mode' style url to `return-content'.
+ (setq return-content (concat return-content
+ (org-make-link-string
+ link-location link-title))))
+ (goto-char temp-position) ; reset point before jump next anchor
+ (setq out-bound t) ; for break out `while' loop
+ ))
+ ;; add the rest until end of the region to be copied
+ (if (< (point) transform-end)
+ (setq return-content
+ (concat return-content
+ (buffer-substring (point) transform-end))))
+ (org-kill-new return-content)
+ (message "Transforming links...done, use C-y to insert text into Org-mode file"))))
+
+
+;; Additional keys for eww-mode
+
+(defun org-eww-extend-eww-keymap ()
+ (define-key eww-mode-map "\C-c\C-x\M-w" 'org-eww-copy-for-org-mode)
+ (define-key eww-mode-map "\C-c\C-x\C-w" 'org-eww-copy-for-org-mode))
+
+(when (and (boundp 'eww-mode-map)
+ (keymapp eww-mode-map)) ; eww is already up.
+ (org-eww-extend-eww-keymap))
+
+(add-hook
+ 'eww-mode-hook
+ (lambda () (org-eww-extend-eww-keymap)))
+
+
+(provide 'org-eww)
+
+;;; org-eww.el ends here
diff --git a/contrib/lisp/org-expiry.el b/contrib/lisp/org-expiry.el
index d58043f..1506c3b 100644
--- a/contrib/lisp/org-expiry.el
+++ b/contrib/lisp/org-expiry.el
@@ -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-git-link.el b/contrib/lisp/org-git-link.el
index 7d95bbb..ad0ce71 100644
--- a/contrib/lisp/org-git-link.el
+++ b/contrib/lisp/org-git-link.el
@@ -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
index ce53947..26edc85 100644
--- a/contrib/lisp/org-index.el
+++ b/contrib/lisp/org-index.el
@@ -1,11 +1,10 @@
;;; org-index.el --- A personal index for org and beyond
-;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2015 Free Software Foundation, Inc.
;; Author: Marc Ihm <org-index@2484.de>
-;; Keywords: outlines, hypermedia, matching
-;; Requires: org
-;; Version: 2.4.2
+;; Version: 4.2.1
+;; Keywords: outlines index
;; This file is not part of GNU Emacs.
@@ -28,40 +27,42 @@
;; 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.
+;; Fast search for selected org headings and things outside of org.
;;
-;; 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.
+;; This package creates and updates an index table of headings or
+;; keywords, references and ids, where each line points to a heading
+;; within org or references something outside. This table is sorted by
+;; usage count, so that frequently used lines appear among the first
+;; search results.
+;;
+;; References are essentially small numbers (e.g. 'R237' or '--455--'), as
+;; created by this package; they are well suited to be used outside of
+;; org, e.g. in folder names, issue trackers or on printed documents.
+;;
+;; On first invocation org-index will guide you to create a dedicated node
+;; for its index table and its configuration flags.
+;;
+;; For basic usage, subcommands 'add' and 'occur' are most important.
;;
;;
;; 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)
+;; (org-index-default-keybindings) ; optional
;;
-;; - Restart your emacs to make these lines effective
+;; - 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
+;; 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
+;; by invoking `org-index' and choosing the help-command.
;;
;;
;; Updates:
@@ -72,66 +73,67 @@
;;; Change Log:
-;; [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
+;; [2015-03-18 We] Version 4.2.1
+;; - No garbage in kill-ring
+;; - No recentering after add
;;
-;; [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
+;; [2015-03-08 Su] Version 4.2.0
+;; - Reference numbers for subcommands can be passed as a prefix argument
+;; - Renamed subcommand 'point' to 'ping'
+;; - New variable org-index-default-keybindings-list with a list of
+;; default keybindings for org-index-default-keybindings
+;; - Added new column level
+;; - removed flags get-category-on-add and get-heading-on-add
;;
-;; [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
+;; [2015-03-05 Th] Version 4.1.1 and 4.1.2
+;; - org-mark-ring is now used more consistently
+;; - Bugfix when going to a heading by ref
;;
-;; [2013-02-28 Th] Version 2.2.0:
-;; - Allowed shortcuts like "h237" for command "head" with argument "237"
-;; - Integrated with org-mark-ring-goto
+;; [2015-02-26 Th] Version 4.0.0 and 4.1.0:
+;; - Removed command "leave"; rather go back with org-mark-ring-goto
+;; - Property "org-index-ref" is no longer used or needed
+;; - Renamed column "link" to "id"
+;; - Added maintainance options to find duplicate rows, to check ids,
+;; update index or remove property org-index-ref from nodes
+;; - New command point
+;; - Shortened versin history
;;
-;; [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
+;; [2014-12-07 Sa] to [2015-01-31 Sa] Version 3.0.0 to 3.2.0:
+;; - Complete sorting of index only occurs in idle-timer
+;; - New command "maintain" with some subcommands
+;; - Rewrote command "occur" with overlays in an indirect buffer
+;; - introduced variable org-index-version
+;; - Command "add" updates index, if node is already present
+;; - New commands "add" and "delete" to easily add and remove
+;; the current node to or from your index.
+;; - New command "example" to create an example index.
+;; - Moved flags to a list within the same node as the index table;
+;; this breaks compatibility to prior versions of the package.
+;; - Several new flags that are explained within index node.
+;; - Removed commands "reuse", "missing", "put", "goto",
+;; "update", "link", "fill", "unhighlight"
+;; - New function `org-index-default-keybindings'
;;
-;; [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-12-07 Fr] to [2014-04-26 Sa] Version 2.0.0 to 2.4.3:
+;; - New functions org-index-new-line and org-index-get-line
+;; offer access to org-index from other lisp programs
+;; - Regression tests with ert
+;; - Renamed from "org-favtable" to "org-index"
+;; - Added an assistant to set up the index table
+;; - occur is now incremental, searching as you type
+;; - Integrated with org-mark-ring-goto
+;; - Added full support for ids
+;; - Renamed the package from "org-reftable" to "org-favtable"
+;; - Additional columns are required (e.g. "link"). Error messages will
+;; guide you
+;; - 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:
+;; [2011-12-10 Sa] to [2012-09-22 Sa] Version Version 1.2.0 to 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:
@@ -139,198 +141,213 @@
(require 'org-table)
(require 'cl)
-(defcustom org-index-id nil
+(defcustom org-index-id nil
"Id of the Org-mode node, which contains the index table."
:group 'org
:group 'org-index)
+;; Version of this package
+(defvar org-index-version "4.2.1" "Version of `org-index', format is major.minor.bugfix, where \"major\" is a change in index-table and \"minor\" are new features.")
+
;; 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
+(defvar org-index--maxref nil "Maximum number from reference table (e.g. '153').")
+(defvar org-index--head nil "Any header before number (e.g. 'R').")
+(defvar org-index--tail nil "Tail after number (e.g. '}' or ')'.")
+(defvar org-index--numcols nil "Number of columns in index table.")
+(defvar org-index--ref-regex nil "Regular expression to match a reference.")
+(defvar org-index--ref-format nil "Format, that can print a reference.")
+(defvar org-index--columns nil "Columns of index-table.")
+(defvar org-index--special-columns nil "Columns with flags, that may appear only once.")
+(defvar org-index--flagged-columns nil "Columns with flags, that may appear multiple times.")
+(defvar org-index--buffer nil "Buffer of index table.")
+(defvar org-index--point nil "Position at start of headline of index table.")
+(defvar org-index--below-hline nil "Position of first cell in first line below hline.")
+(defvar org-index--headings nil "Headlines of index-table as a string.")
+(defvar org-index--headings-visible nil "Visible part of headlines of index-table as a string.")
+(defvar org-index--keymap nil "Keymap for shortcuts for some commands of `org-index'. Filled and activated by `org-index-default-keybings'.")
;; 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--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 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.0 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:
+(defvar org-index--last-ref nil "Last reference created or visited.")
+(defvar org-index--category-before nil "Category of node before.")
+(defvar org-index--active-region nil "Active region, initially. I.e. what has been marked.")
+(defvar org-index--below-cursor nil "Word below cursor.")
+(defvar org-index--within-node nil "True, if we are within node of the index table.")
+(defvar org-index--message-text nil "Text that was issued as an explanation; helpful for regression tests.")
+(defvar org-index--occur-help-text nil "Text for help in occur buffer.")
+(defvar org-index--occur-help-overlay nil "Overlay for help in occur buffer.")
+(defvar org-index--occur-stack nil "Stack with overlays for hiding lines.")
+(defvar org-index--occur-tail-overlay nil "Overlay to cover invisible lines.")
+(defvar org-index--last-sort nil "Last column, the index has been sorted after.")
+(defvar org-index--sort-timer nil "Timer to sort index in correct order.")
+(defvar org-index--aligned nil "Remember for this Emacs session, if table has been aligned at least once.")
+
+;; static information for this program package
+(defconst org-index--commands '(occur add delete head ping enter ref help example sort multi-occur highlight maintain) "List of commands available.")
+(defconst org-index--required-flags '(sort) "Flags that are required.")
+(defconst org-index--single-flags '(sort point-on-add yank-after-add shift-ref-and-date-on-add) "Flags, that may only appear once; these can appear as special-columns.")
+(defconst org-index--multiple-flags '(edit-on-add) "Flags, that might appear multiple times.")
+(defconst org-index--all-flags (append org-index--single-flags org-index--multiple-flags) "All flags.")
+(defconst org-index--required-headings '(ref id created last-accessed count) "All required headings.")
+(defconst org-index--valid-headings (append org-index--required-headings '(keywords category level)) "All valid headings.")
+(defconst org-index--occur-buffer-name "*org-index-occur*" "Name of occur buffer.")
+(defconst org-index--sort-idle-delay 300 "Delay in seconds after which buffer will sorted.")
+(defvar org-index-default-keybindings-list '(("a" . 'add) ("i " . nil) ("o" . 'occur) ("a" . 'add) ("d" . 'delete) ("h" . 'head) ("e" . 'enter) ("p." . 'ping) ("r" . 'ref) ("?" . 'help)) "One-letter short cuts for selected subcommands of `org-index', put in effect by `org-index-default-keybindings'")
+(defconst org-index--sample-flags
+"
+ - columns-and-flags :: associate columns of index table with flags. Do not remove.
+ - ref
+ - yank-after-add
+ - category
+ - edit-on-add
+ - keywords
+ - edit-on-add
+ - point-on-add
+ - count
+ - sort
+ - last-accessed
+ - created
+ - id
+ - all-columns-explained :: All columns of the index table and their meaning.
+ - ref :: The reference number; will be generated automatically.
+ - id :: id of the node, that this line represents
+ - created :: When has this entry been created ?
+ - last-accessed :: When has this entry been accessed last ?
+ - count :: How many times has this entry been picked ?
+ - keywords :: Optional column, suggested to keep a list of keywords,
+ which may match your input during occur. While adding a line to your index,
+ this column will be filled with the nodes heading.
+ - category :: (optional) column to store the category of newly added nodes.
+ - level :: Nesting level of node
+ - Any name starting with a dot (`.') :: No predefined meaning,
+ depends on its flags.
+ - all-flags-explained :: All flags, that can be associated with columns.
+ - sort :: Sort whole table according to this column.
+ - yank-after-add :: This column will be yanked after picking this line during
+ occur.
+ - edit-on-add :: This field will be presented for editing, when adding
+ a new line to your index.
+ - point-on-add :: Point will land here, when adding a new line, e.g. with
+ command ref.
+ - shift-ref-and-date-on-add :: Remove leading reference and timestamp on add."
+"A sample string of flags.")
+
+
+(defmacro org-index--on (column value &rest body)
+ "Execute the forms in BODY with point on index line whose COLUMN is VALUE.
+The value returned is the value of the last form in BODY or nil,
+if VALUE cannot be found."
+ (declare (indent 2) (debug t))
+ (let ((pointvar (make-symbol "point")) ; avoid clash with same-named variables in body
+ (foundvar (make-symbol "found"))
+ (retvar (make-symbol "ret")))
+ `(save-current-buffer
+ (set-buffer org-index--buffer)
+ (setq ,pointvar (point))
+ (setq ,foundvar nil)
+ (setq ,retvar nil)
+
+ (setq ,foundvar (org-index--go ,column ,value))
+ (when ,foundvar
+ (setq ,retvar (progn ,@body)))
+
+ (goto-char ,pointvar)
+
+ ,retvar)))
- - A reference (e.g. \"R237\")
- - An optional link to another location in org
+(defun org-index (&optional command search-ref arg)
+ "Fast search for selected org headings and things outside of 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.
+This package creates and updates an index table of headings or
+keywords, references and ids, where each line points to a heading
+within org or references something outside. This table is sorted by
+usage count, so that frequently used lines appear among the first
+search results.
- - The creation date of the line
+References are essentially small numbers (e.g. 'R237' or '--455--'), as
+created by this package; they are well suited to be used outside of
+org, e.g. in folder names, issue trackers or on printed documents.
- - Date and time of last access. This column can alternatively be
- used to sort the table.
+On first invocation `org-index' will guide you to create a dedicated node
+for its index table and its configuration flags.
- - A column for your own comments
+For basic usage, subcommands 'add' and 'occur' are most important.
-The index table is found through the id of the containing
-node; this id is stored within the variable `org-index-id'.
+This is version 4.2.1 of org-index.el.
+\\<org-mode-map>
+The function `org-index' operates on a dedicated table, the index
+table, which lives within its own Org-mode node. The table and
+its containing node will be created, when you first invoke
+`org-index'. The node also contains a commented list, describing
+the columns of the index table and their associated flags. The
+node is found through its id, which 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:
+package and its main entry point; it will present you with a list
+of subcommands to choose from:
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.
-
- If you supply a number (e.g. \"237\"): Apply emacs standard
- multi-occur operation on all org-mode buffers to search for
- this specific reference.
+ index table. It is 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.
+ add: Add the current node to your index, so that it can be
+ found through the subcommand \"occur\". Update index,
+ if node has already been present.
- 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.
+ delete: Delete the current node from your index.
- ref: Create a new reference, copy any previously selected text.
- If already within index table, fill in ref-column.
+ head: Ask for a reference number and search for this heading.
- 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.
+ enter: Enter index table and maybe go to a specific reference;
+ use `org-mark-ring-goto' (\\[org-mark-ring-goto]) to go back.
- 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.
+ ping: Echo line from index table for current node or first of
+ its ancestor from index.
- 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.
+ ref: Create a new 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.
-
- highlight: Highlight references in active region or buffer.
+ example: Create a temporary index, that will not be saved, but
+ may serve as an example.
- unhighlight: Remove those highlights.
+ sort: Sort lines in index, in region or buffer by contained
+ reference, or sort index by count, reference or last access.
- 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.
+ multi-occur: Apply Emacs standard `multi-occur' operation on all
+ `org-mode' buffers to search for the given reference.
- statistics : Show some statistics (e.g. minimum and maximum
- reference) about index table.
+ highlight: Highlight or unhiglight references in active region or buffer.
+ Call with prefix argument (`C-u') to remove highlights.
+ maintain: Offers some choices to check, update or fix your index.
+If you invoke `org-index' for the first time, an assistant will be
+invoked, that helps you to create your own, commented index.
-Two ways to save keystrokes:
+Use `org-index-default-keybindings' to establish convenient
+keyboard shortcuts.
-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.
+See the commented list of flags within your index node for ways to
+modify the behaviour of org-index.
-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\".
+A numeric prefix argument is used as a reference number for
+commands, that need one (e.g. 'head').
+Optional arguments for use from elisp: COMMAND is a symbol naming
+the command to execute. SEARCH-REF specifies a reference to
+search for, if needed. ARG allows passing in a prefix argument
+as in interactive calls."
-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 "i\ni\nP")
-"
-
- (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
- )
+ (let (search-id ; id to search for
+ sort-what ; sort what ?
+ kill-new-text ; text that will be appended to kill ring
+ message-text) ; text that will be issued as an explanation
;;
@@ -338,124 +355,113 @@ command \"head\" for reference \"237\".
;;
;; creates index table, if necessary
- (org-index--verify-id)
+ (org-index--verify-id)
+
+ ;; Get configuration of index table
+ (org-index--parse-table)
;; store context information
(org-index--retrieve-context)
- ;; Get configuration of index table
- (org-index--parse-table)
+
+ ;;
+ ;; Arrange for proper sorting of index
+ ;;
+
+ ;; lets assume, that it has been sorted this way (we try hard to make sure)
+ (unless org-index--last-sort (setq org-index--last-sort (org-index--special-column 'sort)))
+ ;; rearrange for index beeing sorted into default sort order after 300 secs of idle time
+ (unless org-index--sort-timer
+ (setq org-index--sort-timer
+ (run-with-idle-timer org-index--sort-idle-delay t 'org-index--sort-silent)))
;;
;; 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))))
+ ;; check or read command
+ (if command
+ (unless (memq command org-index--commands)
+ (error "Unknown command '%s' passed as argument, valid choices are any of these symbols: %s"
+ command (mapconcat 'symbol-name org-index--commands ",")))
+ (setq command (intern (org-completing-read
+ "Please choose: "
+ (mapcar 'symbol-name org-index--commands)))))
;;
- ;; Get search, if required
+ ;; Get search string, if required; process possible sources one after
+ ;; another (lisp argument, prefix argumen, user input).
;;
- ;; 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))
+ ;; Try prefix, if no lisp argument given
+ (if (and (not search-ref)
+ (numberp arg))
+ (setq search-ref (format "%s%d%s" org-index--head arg org-index--tail)))
- (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))))
+ ;; These actions really need a search string and may even prompt for it
+ (when (memq command '(enter head multi-occur))
+
+ ;; search from surrounding text ?
+ (unless search-ref
+ (if org-index--within-node
+
+ (if (org-at-table-p)
+ (setq search-ref (org-index--get-or-set-field 'ref)))
+
+ (if (and org-index--below-cursor
+ (string-match (concat "\\(" org-index--ref-regex "\\)")
+ org-index--below-cursor))
+ (setq search-ref (match-string 1 org-index--below-cursor)))))
+
+ ;; If we still do not have a search string, ask user explicitly
+ (unless search-ref
+ (if (eq command 'enter)
+ (let ((r (org-index--read-search-for-enter)))
+ (setq search-ref (car r))
+ (setq search-id (cdr r)))
+ (setq search-ref (read-from-minibuffer "Search reference number: "))))
+
+ ;; Clean up search string
+ (when search-ref
+ (setq search-ref (org-trim search-ref))
+ (if (string-match "^[0-9]+$" search-ref)
+ (setq search-ref (concat org-index--head search-ref org-index--tail)))
+ (if (string= search-ref "") (setq search-ref nil)))
+
+ (if (and (not search-ref)
+ (not (eq command 'enter)))
+ (error "Command %s needs a reference number" command)))
;;
- ;; Do some sanity checking before really starting
+ ;; Command sort needs to know in advance, what to sort for
;;
- ;; Correct requested action, if nothing to search
- (when (and (not search)
- (memq what '(search head)))
- (setq what 'enter)
- (setq what-adjusted t))
+ (when (eq command 'sort)
+ (setq sort-what (intern (org-completing-read "You may sort:\n - index : your index table by various columns\n - region : the active region by contained reference\n - buffer : the whole current buffer\nPlease choose what to sort: " (list "index" "region" "buffer") nil t))))
- ;; For a proper reference as input, we do multi-occur
- (if (and (eq what 'occur) search-ref)
- (setq what 'multi-occur))
-
- ;; 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
+ ;; 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))
+ ;; Arrange for beeing able to return
+ (when (and (memq command '(occur head enter ref example sort maintain))
+ (not (string= (buffer-name) org-index--occur-buffer-name)))
+ (org-mark-ring-push))
;; These commands will leave user in index table after they are finished
- (when (memq what '(enter ref link goto missing))
+ (when (or (memq command '(enter ref maintain))
+ (and (eq command 'sort)
+ (eq sort-what 'index)))
- ;; Support orgmode-standard of going back (buffer and position)
- (org-mark-ring-push)
-
- (org-pop-to-buffer-same-window org-index--buffer)
+ (pop-to-buffer-same-window org-index--buffer)
(goto-char org-index--point)
- (show-subtree)
- (org-show-context)
+ (org-index--unfold-buffer))
+
- ;; Sort and align
- (org-index--sort reorder-once)
- (org-index--align))
-
- ;; Return to initial position
- (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
;;
@@ -463,26 +469,13 @@ command \"head\" for reference \"237\".
(cond
- ((eq what 'help)
-
+ ((eq command '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)))
+ ((eq command 'multi-occur)
;; Construct list of all org-buffers
(let (buff org-buffers)
@@ -492,250 +485,192 @@ command \"head\" for reference \"237\".
(setq org-buffers (cons buff org-buffers))))
;; Do multi-occur
- (multi-occur org-buffers guarded-search)
+ (multi-occur org-buffers (org-index--make-guarded-search search-ref))
;; Present results
(if (get-buffer "*Occur*")
- (progn
- (setq message-text (format "multi-occur for '%s'" search))
+ (progn
+ (setq message-text (format "multi-occur for '%s'" search-ref))
(other-window 1)
(toggle-truncate-lines 1))
- (setq message-text (format "Did not find '%s'" search)))))
+ (setq message-text (format "Did not find '%s'" search-ref)))))
- ((eq what 'head)
+ ((eq command 'add)
- (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)))
+ (let ((r (org-index--do-add-or-update)))
+ (setq message-text (car r))
+ (setq kill-new-text (cdr r))))
- ((eq what 'leave)
+ ((eq command 'delete)
- (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-before
- ;; 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 org-index--point-before))
- ;; set position in buffer in any case and second
- (with-current-buffer org-index--buffer
- (goto-char org-index--point-before)))
- (setq org-index--point-before 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))))
+ (setq message-text (org-index--do-delete)))
- ((eq what 'occur)
+ ((eq command 'head)
- (org-index--do-occur what-input))
+ (if (and org-index--within-node
+ (org-at-table-p))
+ (setq search-id (org-index--get-or-set-field 'id)))
+ (setq search-id (or search-id (org-index--id-from-ref search-ref)))
+ (setq message-text
+ (if search-id
+ (org-index--do-head search-ref search-id)
+ (message "Current line has no id."))))
- ((memq what '(ref link))
- (let (new)
+ ((eq command 'enter)
- ;; add a new row (or reuse existing one)
- (setq new (org-index--do-new-line (eq what 'ref)))
+ (goto-char org-index--below-hline)
- ;; 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)))))
+ (setq message-text
+ (if search-ref
+ (if (org-index--go 'ref search-ref)
+ (progn
+ (org-index--update-current-line)
+ (org-table-goto-column (org-index--column-num 'ref))
+ (format "Found index line '%s'" search-ref))
+ (format "Did not find index line with reference '%s'" search-ref))
- ((eq what 'put)
+ (if search-id
+ (if (org-index--go 'id search-id)
+ (progn
+ (org-index--update-current-line)
+ (org-table-goto-column (org-index--column-num 'ref))
+ (format "Found index line '%s'" (org-index--get-or-set-field 'ref)))
+ (format "Did not find index line with id '%s'" search-id))
- ;; put latest reference into property
+ ;; simply go into table
+ (setq message-text "At index table"))))
-
- (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."))
- ))
+ (recenter))
-
- ((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 command 'ping)
-
- ((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)
+ (let ((moved-up 0) id info reached-top)
- (progn
- (org-index--get-field :link link)
- (setq message-text "Inserted link"))
+ (unless (string= major-mode "org-mode") (error "No node at point"))
+ ;; take id from current node or reference
+ (setq id (if search-ref
+ (org-index--id-from-ref search-ref)
+ (org-id-get)))
- (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")))))
-
+ ;; move up until we find a node in index
+ (save-excursion
+ (outline-back-to-heading)
+ (while (not (or info
+ reached-top))
+ (if id
+ (setq info (org-index--on 'id id
+ (mapcar (lambda (x) (org-index--get-or-set-field x))
+ (list 'ref 'count 'created 'last-accessed 'category 'keywords 'ref)))))
+
+ (setq reached-top (= (org-outline-level) 1))
+
+ (unless (or info
+ reached-top)
+ (outline-up-heading 1 t)
+ (incf moved-up))
+
+ (setq id (org-id-get))))
+
+ (if info
+ (progn
+ (setq message-text
+ (apply 'format
+ (append (list "'%s'%shas been accessed %s times between %s and %s; category is '%s', keywords are '%s'"
+ (pop info)
+ (if (> moved-up 0) (format " (parent node, %d level up) " moved-up) " "))
+ info)))
+ (setq kill-new-text (car (last info))))
+ (setq message-text "Neither this node nor any of its parents is part of index"))))
- ((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 command 'occur)
- ((eq what 'update)
+ (set-buffer org-index--buffer)
+ (org-index--do-occur))
- ;; 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))))))
+ ((eq command 'ref)
- ((memq what '(highlight unhighlight))
+ (let (new)
+
+ ;; add a new row
+ (setq new (org-index--create-new-line))
+
+ ;; fill special columns with standard values
+ (org-table-goto-column (org-index--column-num 'ref))
+ (insert new)
+ (setq org-index--last-ref new)
+
+ ;; goto point-field or first empty one or first field
+ (if (org-index--special-column 'point-on-add)
+ (org-table-goto-column (org-index--column-num (org-index--special-column 'point-on-add)))
+ (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))
+ (setq message-text (format "Adding a new row with ref '%s'" new))))
+
+
+ ((eq command 'sort)
+
+ (let ((columns (list "ref" "count" "created" "last-accessed" "id"))
+ sort groups-and-counts)
+
+ (cond
+ ((eq sort-what 'index)
+ (setq sort
+ (intern
+ (org-icompleting-read
+ "Please choose column to sort index table: "
+ (append (copy-list columns) (list "group-by"))
+ nil t nil nil (symbol-name (org-index--special-column 'sort)))))
+
+ (when (eq sort 'group-by)
+ (setq sort
+ (intern
+ (org-icompleting-read
+ "Please choose column to group index table by: "
+ columns
+ nil t nil nil (symbol-name (org-index--special-column 'sort)))))
+ (setq groups-and-counts (org-index--collect-sort-groups sort)))
+
+ (org-index--do-sort-index sort (first groups-and-counts))
+ (org-table-goto-column (org-index--column-num sort))
+ ;; When saving index, it should again be sorted correctly
+ (with-current-buffer org-index--buffer
+ (add-hook 'before-save-hook 'org-index--sort-silent t))
+
+ (setq message-text
+ (format
+ (concat "Your index has been sorted temporarily by %s and will be sorted again by %s after %d seconds of idle time"
+ (if groups-and-counts
+ "; %d groups with equal %s and a total of %d lines have been found"
+ ""))
+ (symbol-name sort)
+ (org-index--special-column 'sort)
+ org-index--sort-idle-delay
+ (second groups-and-counts)
+ (symbol-name sort)
+ (third groups-and-counts))))
+
+ ((memq sort-what '(region buffer))
+ (org-index--do-sort-lines sort-what)
+ (setq message-text (format "Sorted %s by contained references" sort-what))))))
+
+
+ ((eq command 'highlight)
(let ((where "buffer"))
(save-excursion
@@ -745,726 +680,807 @@ command \"head\" for reference \"237\".
(narrow-to-region (region-beginning) (region-end))
(setq where "region"))
- (if (eq what 'highlight)
+ (if arg
(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)))))))
+ (unhighlight-regexp org-index--ref-regex)
+ (setq message-text (format "Removed highlights for references in %s" where)))
+ (highlight-regexp org-index--ref-regex 'isearch)
+ (setq message-text (format "Highlighted references in %s" where)))))))
- ((memq what '(missing statistics))
+ ((eq command 'maintain)
+ (setq message-text (org-index--do-maintain)))
- (setq message-text (org-index--do-statistics what)))
-
- (t (error "This is a bug: unmatched case '%s'" what)))
+ ((eq command 'example)
+
+ (if (y-or-n-p "This assistant will help you to create a temporary index with detailed comments.\nDo you want to proceed ? ")
+ (org-index--create-index t)))
+
+
+ (t (error "Unknown subcommand '%s'" command)))
- ;; 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
+ (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
+ (let ((m (concat
message-text
- (if (and message-text kill-new-text)
- " and r"
+ (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 (format "eady to yank '%s'." kill-new-text) (if message-text "." "")))))
+ (unless (string= m "")
+ (message m)
+ (setq org-index--message-text m)))
(if kill-new-text (kill-new kill-new-text))))
+(defun org-index-default-keybindings (&optional prefix)
+ "Set default keybindings for `org-index'.
+
+Invoke subcommands of org index with a single key
+sequence. Establish the common prefix key 'C-c i' which should be
+followed by the first letter of a subcommand.
+
+The ist of letters and subcommands is specified in within
+`org-index-default-keybindings-list'.
+
+See `org-index' for a description of all subcommands.
+
+Optional argument PREFIX specifies common prefix, defaults to 'C-c i'"
+ (interactive)
+
+ (define-prefix-command 'org-index--keymap)
+ ;; prefix command
+ (global-set-key (kbd (or prefix "C-c i")) 'org-index--keymap)
+ ;; loop over subcommands
+ (mapcar
+ (lambda (x)
+ ;; loop over letters, that invoke the same subcommand
+ (mapcar (lambda (c)
+ (define-key org-index--keymap (kbd (char-to-string c))
+ `(lambda (arg) (interactive "P")
+ (message nil)
+ (org-index ,(cdr x) nil arg))))
+ (car x)))
+ org-index-default-keybindings-list))
+
+
(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
+The function takes a varying number of argument pairs; each pair
is a symbol for an existing column heading followed by its value.
-their values.
+The return value is the new reference.
Example:
- (org-index-new-line :ref t :x1 \"foo\" :link \"7f480c3e\")
+ (message \"Created reference %s\"
+ (org-index-new-line 'keywords \"foo bar\" 'category \"baz\"))
-Passing \":ref t\" will make the function create a new reference within the new line.
+Optional argument KEYS-VALUES specifies content of new line."
-"
+ (org-index--verify-id)
+ (org-index--parse-table)
- (let ((org-index--silent t))
+ (car (apply 'org-index--do-new-line keys-values)))
- (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)
+
+(defun org-index--do-new-line (&rest keys-values)
+ "Do the work for `org-index-new-line'.
+Optional argument KEYS-VALUES specifies content of new line."
+
+ (save-excursion
+ (org-index--retrieve-context)
+ (with-current-buffer org-index--buffer
+ (goto-char org-index--point)
+
+ ;; check arguments early; they might come from lisp-user
+ (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 "Column 'ref' accepts only \"t\" or \"nil\""))
+ (if (or (not (symbolp k))
+ (and (symbolp v) (not (eq v t)) (not (eq v nil))))
+ (error "Arguments must be alternation of key and value")))
+ (unless (org-index--column-num k)
+ (error "Unknown column or column not defined in table: '%s'" (symbol-name k)))
+ (setq kvs (cddr kvs))))
+
+ (let (ref yank)
+ ;; create new line
+ (setq ref (org-index--create-new-line))
+ (plist-put keys-values 'ref ref)
+
+ ;; fill columns
+ (let ((kvs keys-values)
+ k v n)
(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)))
+ (org-table-goto-column (org-index--column-num k))
+ (insert (org-trim v))
(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)))))
+ ;; align and fontify line
+ (org-index--promote-current-line)
+ (org-index--align-and-fontify-current-line)
+
+ ;; get column to yank
+ (setq yank (org-index--get-or-set-field (org-index--special-column 'yank-after-add)))
+ (cons ref yank)))))
-(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.
+(defun org-index-get-line (column value)
+ "Retrieve an existing line within the index table by ref or id.
+Return its contents as a property list.
+
+The function `plist-get' may be used to retrieve specific elements
+from the result.
Example:
- (plist-get (org-index-get-line \"12\") :count)
+ (plist-get (org-index-get-line 'ref \"R12\") 'count)
-retrieves the value of the count-column for reference 12.
+retrieves the value of the count-column for reference number 12.
-"
- (interactive)
- (let ((org-index--silent t)
- found)
+Argument COLUMN is a symbol, either ref or id,
+argument VALUE specifies the value to search for."
+ ;; check arguments
+ (unless (memq column '(ref id))
+ (error "Argument column can only be 'ref' or 'id'"))
- ;; check arguments
- (unless (memq what '(:ref :link))
- (error "Argument what can only be :ref or :link"))
+ (unless value
+ (error "Need a value to search for"))
+
+ (org-index--verify-id)
+ (org-index--parse-table)
- (save-excursion
- (org-index--retrieve-context)
- (with-current-buffer org-index--buffer
- (goto-char org-index--point)
- (org-index--parse-table)
+ (org-index--get-line column value))
- (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 org-index--within-node
- (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)))))
+
+(defun org-index--get-line (column value)
+ "Find a line by ID, return its contents.
+Argument COLUMN and VALUE specify line to get."
+ (let (content)
+ (org-index--on
+ column value
+ (mapc (lambda (x)
+ (if (and (numberp (cdr x))
+ (> (cdr x) 0))
+ (setq content (cons (car x) (cons (or (org-index--get-or-set-field (car x)) "") content)))))
+ (reverse org-index--columns)))
+ content))
+
+
+(defun org-index--delete-line (id)
+ "Delete a line specified by ID."
+ (let (content)
+ (org-index--on
+ 'id id
+ (let ((start (line-beginning-position)))
+ (beginning-of-line)
+ (forward-line)
+ (delete-region start (point))
+ t))))
+
+
+(defun org-index--ref-from-id (id)
+ "Get reference from line ID."
+ (org-index--on 'id id (org-index--get-or-set-field 'ref)))
+
+
+(defun org-index--id-from-ref (ref)
+ "Get id from line REF."
+ (org-index--on 'ref ref (org-index--get-or-set-field 'id)))
+
+
+(defun org-index--read-search-for-enter ()
+ "Special input routine for command enter."
+ ;; Accept single char commands or switch to reading a sequence of digits
+ (let (char prompt search-ref search-id)
+
+ ;; start with short prompt but give more help on next iteration
+ (setq prompt "Please specify, where to go in index (0-9.,space,backspace,return or ? for help): ")
- ;; Check for special case
- (when (and (memq what '(head goto))
- (string= search "."))
- (setq search (org-id-get)))
+ ;; read one character
+ (while (not (memq char (append (number-sequence ?0 ?9) (list ?\d ?\b ?\r ?\j ?\s ?.))))
+ (setq char (read-char prompt))
+ (setq prompt "Go to index table and specific position. Digits specify a reference number to got to, <space> goes to top of index, <backspace> or <delete> to last line created and <return> or `.' to index line of current node. Please choose: "))
- search))
+ (if (memq char (number-sequence ?0 ?9))
+ ;; read rest of digits
+ (setq search-ref (read-from-minibuffer "Search reference number: " (char-to-string char))))
+ ;; decode single chars
+ (if (memq char '(?\r ?\n ?.)) (setq search-id (org-id-get)))
+ (if (memq char '(?\d ?\b)) (setq search-ref (number-to-string org-index--maxref)))
+
+ (cons search-ref search-id)))
(defun org-index--verify-id ()
+ "Check, that we have a valid id."
;; Check id
(unless org-index-id
- (setq org-index-id (org-index--create-new-index
- t
- (format "No index table has been created yet." org-index-id))))
+ (let ((answer (org-completing-read "Cannot find an index (org-index-id is not set). You may:\n - read-help : to learn more about org-index\n - create-index : invoke an assistant to create an initial index\nPlease choose: " (list "read-help" "create-index") nil t nil nil "read-help")))
+ (if (string= "create-index" answer)
+ (org-index--create-missing-index "Variable org-index-id is not set, so probably no index table has been created yet.")
+ (describe-function 'org-index))))
;; Find node
- (let (marker)
+ (let (marker)
(setq marker (org-id-find org-index-id 'marker))
- (unless marker (setq org-index-id (org-index--create-new-index
- t
- (format "Cannot find node with id \"%s\"" org-index-id))))
+ (unless marker (org-index--create-missing-index "Cannot find the node with id \"%s\" (as specified by variable org-index-id)." org-index-id))
; Try again with new node
- (setq marker (org-id-find org-index-id 'marker))
+ (setq marker (org-id-find org-index-id 'marker))
(unless marker (error "Could not create node"))
- (setq org-index--buffer (marker-buffer marker)
+ (setq org-index--buffer (marker-buffer marker)
org-index--point (marker-position marker))
(move-marker marker nil)))
(defun org-index--retrieve-context ()
+ "Collect context information before starting with command."
;; Get the content of the active region or the word under cursor
- (setq org-index--active-region
+ (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
- (unless (string= (org-id-get) org-index-id)
- (unless org-index--point-before
- (setq org-index--point-before (point))))))
+ ;; get category of current node
+ (setq org-index--category-before
+ (save-excursion ; workaround: org-get-category does not give category when at end of buffer
+ (beginning-of-line)
+ (org-get-category (point) t)))
+
+ ;; Find out, if we are within index table or not
+ (setq org-index--within-node (string= (org-id-get) org-index-id)))
(defun org-index--parse-table ()
+ "Parse content of index table."
(let (ref-field
- link-field
+ id-field
initial-point
- end-of-heading)
+ end-of-headings
+ start-of-headings)
(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))
+
+ ;; align and fontify table once for this emacs session
+ (unless org-index--aligned
+ (org-table-align) ; needs to happen before fontification to be effective ?
+ (let ((is-modified (buffer-modified-p))
+ (below (point)))
+ (while (org-at-table-p)
+ (forward-line))
+ (font-lock-fontify-region below (point))
+ (org-index--go-below-hline)
+ (setq org-index--aligned t)
+ (set-buffer-modified-p is-modified)))
+
+ (org-index--go-below-hline)
+ (setq org-index--below-hline (point-marker))
(beginning-of-line)
- (setq end-of-heading (point))
+
+ ;; get headings to display during occur
+ (setq end-of-headings (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)
-
-
+ (setq start-of-headings (point))
+ (setq org-index--headings-visible (substring-no-properties (org-index--copy-visible start-of-headings end-of-headings)))
+ (setq org-index--headings (buffer-substring start-of-headings end-of-headings))
+
;; 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)
+ ;; go to top of table
+ (while (org-at-table-p)
+ (forward-line -1))
+ (forward-line)
+
+ ;; parse line of headings
(org-index--parse-headings)
-
- ;; Go beyond end of table
- (while (org-at-table-p) (forward-line 1))
-
+
+ ;; parse list of flags
+ (goto-char org-index--point)
+ (org-index--parse-flags)
+
;; 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))))
+ (not (setq ref-field (org-index--get-or-set-field 'ref))))
(forward-line))
;; Some Checking
(unless ref-field
- (org-index--create-new-index
- nil
- "Reference column is empty"))
-
+ (org-index--report-index-error "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)))
-
+ (org-index--report-index-error
+ "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]+\\)"
+ "\\([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)
+ (while (org-at-table-p)
- (setq ref-field (org-index--get-field :ref))
- (setq link-field (org-index--get-field :link))
+ (setq ref-field (org-index--get-or-set-field 'ref))
+ (setq id-field (org-index--get-or-set-field 'id))
(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"))
+ (not id-field))
+ (kill-whole-line)
+ (message "Removing line from index-table with both ref and id empty"))
(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")))
+ (kill-whole-line)
+ (message "Removing line from index-table whose 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)
+(defun org-index--do-maintain ()
+ "Choose among and perform some tasks to maintain index."
+ (let ((check-what) (max-mini-window-height 1.0) message-text)
+ (setq check-what (intern (org-completing-read "These checks and fixes are available:\n - statistics : compute statistics about index table\n - check : check ids by visiting their nodes\n - duplicates : check index for duplicate rows (any column)\n - clean : remove obsolete property org-index-id\n - update : update content of index lines, with an id \nPlease choose: " (list "statistics" "check" "duplicates" "clean" "update") nil t nil nil "statistics")))
+ (message nil)
+
+ (cond
+ ((eq check-what 'check)
+ (setq message-text (or (org-index--check-ids)
+ "No problems found")))
+
+ ((eq check-what 'statistics)
+ (setq message-text (org-index--do-statistics)))
+
+ ((eq check-what 'duplicates)
+ (setq message-text "Finding duplcates can be done by sorting your index appropriately: Choose 'group-by' and select a column; rows will then be sorted together, if they have the same value within the coosen column."))
+
+ ((eq check-what 'clean)
+ (let ((lines 0))
+ (org-map-entries
+ (lambda ()
+ (when (org-entry-get (point) "org-index-ref")
+ (incf lines)
+ (org-entry-delete (point) "org-index-ref")))
+ nil 'agenda)
+ (setq message-text (format "Removed property 'org-index-ref' from %d lines" lines))))
+
+ ((eq check-what 'update)
+ (if (y-or-n-p "Updating your index will overwrite certain columns with content from the associated heading and category. If unsure, you may try this for a single, already existing line of your index by doing `add' from within your index. Are you SURE to proceed for ALL INDEX LINES ? ")
+ (setq message-text (org-index--update-all-lines))
+ (setq message-text "Canceled."))))
+ message-text))
- (unless sort-column (setq sort-column (org-index--special-column :sort)))
- (let (top
+(defun org-index--do-sort-index (sort &optional groups)
+ "Sort index table according to SORT, optinally with GROUPS."
+
+ (let ((is-modified (buffer-modified-p))
+ top
bottom
ref-field
- count-field
- count-special)
+ count-field)
- (unless buffer-read-only
+ (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)))))
+ (message "Sorting table for %s..." (symbol-name sort))
+ (undo-boundary)
+
+ (let ((message-log-max nil)) ; we have just issued a message, dont need those of sort-subr
+
+ ;; 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-or-set-field 'ref))
+ (not (org-index--get-or-set-field 'id))))
+ (org-table-kill-row))
+ (forward-line 1)
+ (setq bottom (point))
+
+ ;; sort lines
+ (save-restriction
+ (narrow-to-region top bottom)
+ (goto-char top)
+ (sort-subr t
+ 'forward-line
+ 'end-of-line
+ (lambda ()
+ (concat
+ (if groups
+ (format "%06d-" (cdr (assoc (org-index--get-or-set-field sort) groups)))
+ "")
+ (org-index--get-sort-key sort t)))
+ nil
+ 'string<)
+ (goto-char (point-min))
+
+ ;; restore modification state
+ (set-buffer-modified-p is-modified)))
+
+ (setq org-index--last-sort sort))))
+
+
+(defun org-index--collect-sort-groups (sort)
+ "Collect groups to SORT for."
+ (let ((count-groups 0) (count-lines 0)
+ groups key key-value)
+
+ (org-index--on
+ nil nil
+ (while (org-at-table-p)
+ (setq key (org-index--get-or-set-field sort))
+ (setq key-value (assoc key groups))
+ (if key-value
+ (progn
+ (incf (cdr key-value)))
+ (setq groups (cons (cons key 1) groups)))
+ (forward-line)))
+
+ (mapc (lambda (x) (when (> (cdr x) 1)
+ (incf count-groups)
+ (incf count-lines (cdr x))))
+ groups)
+
+ (list groups count-groups count-lines)))
+
+
+(defun org-index--do-sort-lines (what)
+ "Sort lines in WHAT according to contained reference."
+ (save-restriction
+ (cond
+ ((eq what 'region)
+ (if (region-active-p)
+ (narrow-to-region (region-beginning) (region-end))
+ (error "No active region, cannot sort")))
+ ((eq what 'buffer)
+ (unless (y-or-n-p "Sort whole current buffer ? ")
+ (error "Canceled"))
+ (narrow-to-region (point-min) (point-max))))
+
+ (goto-char (point-min))
+ (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)))))
(defun org-index--go-below-hline ()
+ "Move below hline in index-table."
+
+ (let ((count 0)
+ (errstring (format "index table within node %s" org-index-id)))
+
+ (goto-char org-index--point)
+
+ ;; go to heading of node
+ (while (not (org-at-heading-p)) (forward-line -1))
+ (forward-line 1)
+ ;; go to first table, but make sure we do not get into another node
+ (while (and (not (org-at-table-p))
+ (not (org-at-heading-p))
+ (not (eobp)))
+ (forward-line))
+
+ ;; check, if there really is a table
+ (unless (org-at-table-p)
+ (org-index--create-missing-index "Cannot find %s." errstring))
+
+ ;; go just after hline
+ (while (and (not (org-at-table-hline-p))
+ (org-at-table-p))
+ (forward-line))
+ (forward-line)
+
+ ;; and check
+ (unless (org-at-table-p)
+ (org-index--report-index-error "Cannot find a hline within %s" errstring))
+
+ (org-table-goto-column 1)))
+
+
+(defun org-index--parse-headings ()
+ "Parse headings of index table."
+
+ (let (field ;; field content
+ field-symbol ;; and as a symbol
+ found)
+
+ (setq org-index--columns nil)
+
+ ;; For each column
+ (dotimes (col org-index--numcols)
+
+ (setq field (substring-no-properties (downcase (org-trim (org-table-get-field (+ col 1))))))
+
+ (if (string= field "")
+ (error "Heading of column cannot be empty"))
+ (if (and (not (string= (substring field 0 1) "."))
+ (not (member (intern field) org-index--valid-headings)))
+
+ (if (string= field "link")
+ ;; Ask user to migrate his index to new version (since [2015-02-11 Mi])
+ (progn
+ ;; pop to index buffer
+ (pop-to-buffer-same-window org-index--buffer)
+ (goto-char org-index--below-hline)
+ (org-reveal t)
+ ;; go to column
+ (while (org-at-table-p)
+ (forward-line -1))
+ (forward-line)
+ (org-table-goto-column (+ 1 col))
+ (error "Column 'link' should be named 'id' with recent versions of org-index,\nplease adjust your table (cursor is already positioned right)"))
+ (error "Column name '%s' is not a valid heading (custom headings may start with a dot, e.g. '.foo')" field)))
+
+ (setq field-symbol (intern field))
+
+ ;; check if heading has already appeared
+ (if (assoc field-symbol org-index--columns)
+ (org-index--report-index-error
+ "'%s' appears two times as column heading" (downcase field))
+ ;; add it to list at front, reverse later
+ (setq org-index--columns (cons (cons field-symbol (+ col 1)) org-index--columns)))))
+
+ (setq org-index--columns (reverse org-index--columns))
+
+ ;; check if all necessary headings have appeared
+ (mapc (lambda (head)
+ (unless (cdr (assoc head org-index--columns))
+ (org-index--report-index-error "No column has heading '%s'" head)))
+ org-index--required-headings))
+
+
+(defun org-index--parse-flags ()
+ "Parse list of flags in index table."
+
+ (let (parent parent-is-comment child)
+
+ ;; reset configuration variables
+ (setq org-index--special-columns nil)
+ (setq org-index--flagged-columns nil)
+
+ (org-index--goto-list "columns-and-flags" t)
+ (forward-line 1)
+
+ ;; outer loop over columns
+ (while (and (setq parent (org-index--parse-list-item))
+ parent
+ (> (cdr (assoc :indent parent)) 0))
+
+ (setq parent-is-comment (member (cdr (assoc :text parent)) '("all-columns-explained" "all-flags-explained")))
+
+ ;; check, that we have a valid heading
+ (unless (or parent-is-comment
+ (assoc (cdr (assoc :sym parent)) org-index--columns))
+ (when (string= "link" (cdr (assoc :text parent)))
+ (pop-to-buffer-same-window org-index--buffer)
+ (org-reveal t)
+ (error "Flag 'link' should be named 'id' with recent versions of org-index,\nplease adjust this flag (cursor is already positioned right)"))
+ (org-index--report-index-error "'%s' appears within flags, but not as a index column. " (cdr (assoc :text parent))))
+
+ ;; inner loop over children
+ (while (and (forward-line 1)
+ (setq child (org-index--parse-list-item))
+ child
+ (> (cdr (assoc :indent child))
+ (cdr (assoc :indent parent))))
+
+ (unless parent-is-comment
+ ;; check, that we have a valid flag
+ (unless (memq (cdr (assoc :sym child)) org-index--all-flags)
+ (org-index--report-index-error "'%s' is not a valid flag" (cdr (assoc :text child))))
+
+ ;; process flag with respect to current index-column
+ (if (memq (cdr (assoc :sym child)) org-index--single-flags)
+ ;; Check, that none of org-index--single-flags appears twice
+ (if (assoc (cdr (assoc :sym child)) org-index--special-columns)
+ (org-index--report-index-error
+ "More than one column is marked with flag '%s'" (cdr (assoc :text child)))
+ ;; add it to list
+ (setq org-index--special-columns (cons (cons (cdr (assoc :sym child)) (cdr (assoc :sym parent)))
+ org-index--special-columns))))
+
+ ;; all flags are stored in org-index--flagged-columns
+ (let ((l (assoc (cdr (assoc :sym child)) org-index--flagged-columns))) ;; list of flag and columns, that carry this flag
+ (unless l
+ ;; no list of columns with this flag is present, create one
+ (setq org-index--flagged-columns
+ (cons (cons (cdr (assoc :sym child)) nil)
+ org-index--flagged-columns))
+ (setq l (car org-index--flagged-columns)))
+ ;; prepend this column to list of columns with this flag
+ (setcdr l (cons (cdr (assoc :sym parent)) (cdr l)))))))
+
+ ;; check, that all needed flags have been specified
+ (mapc (lambda (x)
+ (unless (assoc x org-index--special-columns)
+ (org-index--report-index-error "Required flag '%s' does not appear" (substring (symbol-name x) 1))))
+ org-index--required-flags)))
+
+
+(defun org-index--goto-list (name &optional required non-top)
+ "Goto list NAME (maybe NON-TOP Level) in index node, err if REQUIRED list is not present."
(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))
+
+ ;; go to named list
+ (while (and (not (let ((item (org-index--parse-list-item)))
+ (if item
+ (and (or non-top (= (cdr (assoc :indent item)) 0)) ;; accept only toplevel ?
+ (string= (cdr (assoc :text item)) name)) ;; with requested name
+ nil)))
(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))
+ (not (org-at-heading-p))
+ (not (eobp)))
(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))
+ (if (org-at-item-p)
+ t
+ (if required
+ (org-index--report-index-error "Could not find required list '%s'" name)
+ nil)))
-(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-list-item ()
+ "Parse a list item into an assoc array (indent, checkbox, text, value)."
+ ;; matche full list-item, maybe with checkbox and double-colon
+ (if (looking-at org-list-full-item-re)
-(defun org-index--parse-headings ()
+ ;; retrieve interesting parts of list item from match data
+ (let (indent checkbox text value next-line)
- ;; 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)))
+ (setq indent
+ (- (save-excursion (goto-char (match-beginning 1)) (current-column)) ; first column
+ (save-match-data (org-current-level)) ; indent-level
+ 1))
+ (setq checkbox (match-string 3))
+ (setq text (match-string 4))
+ (set (if text 'value 'text) (buffer-substring (match-end 0) (line-end-position))) ; regexp did not capture this
+
+ ;; peek ahead, if item continues on next line
+ (forward-line 1)
+ (if (looking-at org-list-full-item-re)
+ (forward-line -1) ; already at next item; go back
+ (setq next-line (buffer-substring (line-beginning-position) (line-end-position))))
- ;; 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))))
+ ;; clean up strings
+ (mapc (lambda (x)
+ (if (stringp (symbol-value x))
+ (set x (org-trim (substring-no-properties (symbol-value x))))))
+ '(text value next-line))
+
+ (if next-line (setq text (concat text " " next-line))) ; append next line if
- ;; 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))
+ (list (cons :indent indent) (cons :text text) (cons :value value) (cons :sym (intern text))))
+ nil))
+
+
+(defun org-index--create-missing-index (&rest reasons)
+ "Create a new empty index table with detailed explanation. Argument REASONS explains why."
+
+ (org-index--ask-before-create-index "Cannot find your index table: "
+ "new permanent" "."
+ reasons)
+ (org-index--create-index))
+
+
+(defun org-index--report-index-error (&rest reasons)
+ "Report an error (explained by REASONS) with the existing index and offer to create a valid one to compare with."
+
+ (when org-index--buffer
+ (pop-to-buffer-same-window org-index--buffer)
+ (goto-char org-index--below-hline)
+ (org-reveal t))
+ (org-index--ask-before-create-index "The existing index contains this error: "
+ "temporary" ", to compare with."
+ reasons)
+ (org-index--create-index t t))
+
+
+(defun org-index--ask-before-create-index (explanation type for-what reasons)
+ ; checkdoc-params: (explanation type for-what reasons)
+ "Ask the user before creating an index or throw error. Arguments specify bits of issued message."
+ (let (reason prompt)
+
+ (setq reason (apply 'format reasons))
+
+ (setq prompt (concat explanation reason "\n\n"
+ "However, this assistant can help you to create a "
+ type " index with detailed comments" for-what "\n\n"
+ "Do you want to proceed ?"))
+
+ (unless (let ((max-mini-window-height 1.0))
+ (y-or-n-p prompt))
+ (error (concat explanation reason)))))
+
+
+(defun org-index--create-index (&optional temporary compare)
+ "Create a new empty index table with detailed explanation.
+specify flag TEMPORARY for th new table temporary, maybe COMPARE it with existing index."
+ (let (buffer
+ title
+ firstref
+ id)
+
+ (if temporary
+ (let ((file-name (concat temporary-file-directory "org-index--example-index.org"))
+ (buffer-name "*org-index-example-index*"))
+ (setq buffer (get-buffer-create buffer-name))
+ (with-current-buffer buffer
+ ;; but it needs a file for its index to be found
+ (unless (string= (buffer-file-name) file-name)
+ (set-visited-file-name file-name))
+ (rename-buffer buffer-name) ; name is change by line above
+
+ (erase-buffer)
+ (org-mode)))
+
+ (setq buffer (get-buffer (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))))))
(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"))
+ (when (string-match "[[:blank:]]" firstref)
+ (setq desc "Contains whitespace"))
+ (when (string-match "[[:cntrl:]]" firstref)
+ (setq desc "Contains control characters"))
(unless (string-match "^[^0-9]+[0-9]+[^0-9]*$" firstref)
;; firstref not okay, report details
(setq desc
- (cond ((string= firstref "") "is empty")
+ (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")
@@ -1472,738 +1488,1003 @@ retrieves the value of the count-column for reference 12.
)))
(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))
+ (read-from-minibuffer (format "Your input '%s' does not meet the requirements because it %s.\nPlease hit RET and try again: " firstref desc))
t)
nil))))
- (with-current-buffer buffer-name
+ (with-current-buffer buffer
(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 "
+ (insert (format "* %s %s\n" firstref title))
+ (if temporary
+ (insert "
+ Below you find your temporary index table, which WILL NOT LAST LONGER
+ THAN YOUR CURRENT EMACS SESSION.
+")
+ (insert "
+ Below you find your initial index table, which will grow over time.
+"))
+ (insert "
+ You may start using it by adding some lines. Just move to
+ another heading, invoke `org-index' and choose the command
+ 'add'. After adding a few nodes, try the command 'occur'
+ to search among them.
- | | | | | | comment |
- | ref | link | first | count;s | last | ;c |
- | | <4> | | | | |
- |-----+------+-------+---------+------+---------|
- | %s | %s | %s | | | %s |
+ To gain further insight you may invoke the subcommand 'help', or
+ read the description of `org-index'.
-"
- firstref
- id
- (with-temp-buffer (org-insert-time-stamp nil nil t))
- "This node"))
+ Within the index table below, dhe sequence of columns does not
+ matter. You may reorder them in any way you please. Columns are
+ found by their heading. You may also add your own columns,
+ which should start with a dot (e.g. '.custom').
+ Following this explanations you will find the item-list
+ `columns-and-flags', which influences the behaviour of
+ `org-index'. See the explanations which are part of this list.
- (insert "
+ This node needs not be a top level node; its name is completely
+ at your choice; it is found through its ID only.
+")
+ (unless temporary
+ (insert "
+ Remark: These lines of explanation can be removed at any time.
+"))
- Detailed explanation:
+ (setq id (org-id-get-create))
+ (insert (format "
+%s
- The index table above has three lines of headings above the first
- hline:
+ | ref | category | keywords | count | last-accessed | created | id |
+ | | | | | | | <4> |
+ |-----+-----------+----------+-------+---------------+---------+------|
+ | %s | | %s | | | %s | %s |
- - 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.
+"
+ org-index--sample-flags
+ firstref
+ "This node"
+ (with-temp-buffer (org-insert-time-stamp nil nil t))
+ id))
- - The second line is the most important one, because it
- contains the configuration information for org-index; please
- read further below for its format.
+ ;; make sure, that node can be found
+ (org-id-add-location id (buffer-file-name))
+ (setq buffer-save-without-query t)
+ (basic-save-buffer)
- - The third line is again optional; it may only specify the
- widths of the individual columns (e.g. <4>).
+ (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))
- 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\").
+ ;; read back some info about new index
+ (let ((org-index-id id))
+ (org-index--verify-id))
+ ;; remember at least for this session
+ (setq org-index-id id)
+ ;; present results to user
+ (if temporary
+ (progn
+ ;; Present existing and temporary index together
+ (when compare
+ (pop-to-buffer-same-window org-index--buffer)
+ (goto-char org-index--point)
+ (org-index--unfold-buffer)
+ (delete-other-windows)
+ (select-window (split-window-vertically)))
+ ;; show new index
+ (pop-to-buffer-same-window buffer)
+ (org-id-goto id)
+ (org-index--unfold-buffer)
+ (if compare
+ (error "Please compare your existing index (upper window) and a temporary new one (lower window) to fix your index")
+ (message "This is your new temporary index.")))
+ (progn
+ ;; Only show the new index
+ (pop-to-buffer-same-window buffer)
+ (delete-other-windows)
+ (org-id-goto id)
+ (org-index--unfold-buffer)
+ (if (y-or-n-p "This is your new index table. It is already set for this Emacs session, so you may try it out. 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 (or custom-file
+ user-init-file)))
+ (let (sq)
+ (setq sq (format "(setq org-index-id \"%s\")" id))
+ (kill-new sq)
+ (error "Did not make the id of this new index permanent; you may want to put\n\n %s\n\ninto your own initialization; it is copied already, just yank it" sq))))))))
+
+
+(defun org-index--unfold-buffer ()
+ "Helper function to unfold buffer."
+ (org-show-context)
+ (org-show-subtree)
+ (recenter 1)
+ (save-excursion
+ (org-back-to-heading)
+ (forward-line) ;; on property drawer
+ (org-cycle)
+ (org-index--goto-list "columns-and-flags")
+ (org-cycle)))
- The keywords and flags are:
+(defun org-index--update-line (&optional ref-or-id)
+ "Update columns count and last-accessed in line REF-OR-ID."
- - 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.
+ (let ((newcount 0)
+ initial)
- - link: org-mode link pointing to the matching location within org.
+ (with-current-buffer org-index--buffer
+ (unless buffer-read-only
- - first: When has this line been first accessed (i.e. created) ?
+ ;; search reference or id, if given (or assume, that we are already positioned right)
+ (when ref-or-id
+ (setq initial (point))
+ (goto-char org-index--below-hline)
+ (while (and (org-at-table-p)
+ (not (or (string= ref-or-id (org-index--get-or-set-field 'ref))
+ (string= ref-or-id (org-index--get-or-set-field 'id)))))
+ (forward-line)))
- - 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.
+ (if (not (org-at-table-p))
+ (error "Did not find reference or id '%s'" ref-or-id)
+ (org-index--update-current-line))
- - last: When has this line been accessed last ?
+ (if initial (goto-char initial))))))
- - 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.
+(defun org-index--update-current-line ()
+ "Update current lines columns count and last-accessed."
+ (let (newcount (count-field (org-index--get-or-set-field 'count)))
- You can add further columns or even remove the last column. All
- other columns are required.
+ ;; update count field only if number or empty
+ (when (or (not count-field)
+ (string-match "^[0-9]+$" count-field))
+ (setq newcount (+ 1 (string-to-number (or count-field "0"))))
+ (org-index--get-or-set-field 'count
+ (number-to-string newcount)))
+ ;; update timestamp
+ (org-table-goto-column (org-index--column-num 'last-accessed))
+ (org-table-blank-field)
+ (org-insert-time-stamp nil t t)
- Finally: This node needs not be a top level node; its name is
- completely at you choice; it is found through its ID only.
+ ;; move line according to new content
+ (org-index--promote-current-line)
+ (org-index--align-and-fontify-current-line)))
-")
+(defun org-index--align-and-fontify-current-line ()
+ "Make current line blend well among others."
+ (let ((line (substring-no-properties (delete-and-extract-region (line-beginning-position) (line-end-position)))))
+ ;; create minimum table with fixed-width columns to align and fontiry new line
+ (insert (with-temp-buffer
+ (org-set-font-lock-defaults)
+ (insert org-index--headings-visible)
+ (goto-char (point-min))
+ ;; fill columns, so that aligning cannot shrink them
+ (search-forward "|")
+ (replace-string " " "." nil (point) (line-end-position))
+ (replace-string ".|." " | " nil (line-beginning-position) (line-end-position))
+ (replace-string "|." "| " nil (line-beginning-position) (line-end-position))
+ (goto-char (point-max))
+ (insert line)
+ (forward-line 0)
+ (org-table-align)
+ (font-lock-fontify-region (point-min) (point-max))
+ (goto-char (point-max))
+ (forward-line -1)
+ (buffer-substring (line-beginning-position) (line-end-position))))))
+
+
+(defun org-index--promote-current-line ()
+ "Move current line up in table according to changed sort fields."
+ (let (begin end key
+ (to-skip 0))
+
+ (forward-line 0) ; stay at beginning of line
+
+ (setq key (org-index--get-sort-key))
+ (setq begin (point))
+ (setq end (line-beginning-position 2))
- (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)
- (if (y-or-n-p "This is your new index table; Do you want to save its id to make it permanent ? ")
- (progn
- (customize-save-variable 'org-index-id id)
- (message "Saved org-index-id '%s' to %s" org-index-id custom-file))
- (let (sq)
- (setq sq (format "(setq org-index-id \"%s\")" org-index-id))
- (kill-new sq)
- (message "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))
- id))
- ;; 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 (initial
- found
- count-field)
+ (forward-line -1)
+ (while (and (org-at-table-p)
+ (not (org-at-table-hline-p))
+ (string< (org-index--get-sort-key) key))
- (with-current-buffer org-index--buffer
- (unless buffer-read-only
+ (incf to-skip)
+ (forward-line -1))
+ (forward-line 1)
- ;; 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)
- (setq count-field (org-index--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-index--get-field :count
- (number-to-string
- (+ 1 (string-to-number (or count-field "0"))))))
-
- ;; update timestamp
- (org-table-goto-column (org-index--column-num :last))
- (org-table-blank-field)
- (org-insert-time-stamp nil t t)
-
- (setq found t))
-
- (if initial (goto-char initial))
-
- found))))
+ ;; insert line at new position
+ (when (> to-skip 0)
+ (insert (delete-and-extract-region begin end))
+ (forward-line -1))))
-(defun org-index--get-field (key &optional value)
+(defun org-index--get-sort-key (&optional sort with-ref)
+ "Get value for sorting from column SORT, optional WITH-REF."
+ (let (ref
+ ref-field
+ key)
+
+ (unless sort (setq sort org-index--last-sort)) ; use default value
+
+ (when (or with-ref
+ (eq sort 'ref))
+ ;; get reference with leading zeroes, so it can be
+ ;; sorted as text
+ (setq ref-field (org-index--get-or-set-field 'ref))
+ (string-match org-index--ref-regex ref-field)
+ (setq ref (format
+ "%06d"
+ (string-to-number
+ (or (match-string 1 ref-field)
+ "0")))))
+
+ (setq key
+ (cond
+ ((eq sort 'count)
+ (format "%08d" (string-to-number (or (org-index--get-or-set-field 'count) ""))))
+ ((eq sort 'ref)
+ ref)
+ ((eq sort 'id)
+ (org-index--get-or-set-field sort))
+ ((eq sort 'last-accessed)
+ (org-index--get-or-set-field sort))
+ ((eq sort 'created)
+ (org-index--get-or-set-field sort))
+ (t (error "This is a bug: unmatched case '%s'" sort))))
+
+ (if with-ref (setq key (concat key ref)))
+
+ key))
+
+
+(defun org-index--get-or-set-field (key &optional value)
+ "Retrieve field KEY from index table or set it to VALUE."
(let (field)
- (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)))
+ (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)
+ "Return number of column KEY."
+ (if (numberp key)
key
(cdr (assoc key org-index--columns))))
(defun org-index--special-column (key)
+ "Return column (not a number) for special column KEY."
(cdr (assoc key org-index--special-columns)))
+(defun org-index--flag-p (flag column)
+ "Check if COLUMN has FLAG set."
+ (unless (memq flag org-index--all-flags)
+ (error (format "Internal error: unknown flag %s" (symbol-name flag))))
+ (memq column (assoc flag org-index--flagged-columns)))
+
+
(defun org-index--make-guarded-search (ref &optional dont-quote)
+ "Make robust search string from REF; DONT-QUOTE it, if requested."
(concat "\\_<" (if dont-quote ref (regexp-quote ref)) "\\_>"))
-(defun org-index--do-statistics (what)
+(defun org-index--do-statistics ()
+ "Compute statistics about index table."
(let ((total 0)
- missing
- ref-field
- ref
- min
- max
- message-text)
+ ref-field ref min max message)
-
- ;; 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
+ (setq ref-field (org-index--get-or-set-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
+ ;; 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)
+ (setq message (format "First reference is %s, last %s; %d values in between, %d of them are used (%d percent)"
+ (format org-index--ref-format min)
+ (format org-index--ref-format max)
+ (1+ (- max min))
+ total
+ (truncate (* 100 (/ (float total) (1+ (- max min)))))
+
+))
+
+ (goto-char org-index--below-hline)
+ message))
+
+
+(defun org-index--do-add-or-update ()
+ "For current node or current line in index, add a new line to index table or update existing."
+
+ (let* (id ref args yank ref-and-yank)
+
+ ;; do the same things from within index and from outside
+ (if org-index--within-node
+
+ (progn
+ (unless (org-at-table-p)
+ (error "Within index node but not on table"))
+
+ (setq id (org-index--get-or-set-field 'id))
+ (setq ref (org-index--get-or-set-field 'ref))
+ (setq args (org-index--collect-values-for-add-update-remote id))
+ (org-index--write-fields-for-add-update args)
+ (setq yank (org-index--get-or-set-field (org-index--special-column 'yank-after-add)))
+
+ (cons (format "Updated index line %s" ref) yank))
+
+ (unless (org-at-heading-p)
+ (error "Not at headline"))
+
+ (setq id (org-id-get-create))
+ (setq ref (org-index--on 'id id (org-index--get-or-set-field 'ref)))
+ (setq args (org-index--collect-values-for-add-update id ref))
+
+ (if ref
+ ;; already have a ref, find it in index and update fields
+ (let ((kvs args)
+ found-and-message)
+
+ (org-index--on
+ 'ref ref
+ (org-index--write-fields-for-add-update args)
+ (setq yank (org-index--get-or-set-field (org-index--special-column 'yank-after-add))))
+
+ (cons (format "Updated index line %s" ref) yank))
+
+ ;; no ref here, create new line in index
+ (setq ref-and-yank (apply 'org-index--do-new-line args))
+
+ (cons (format "Added index line %s" (car ref-and-yank)) (concat (cdr ref-and-yank) " "))))))
+
+
+(defun org-index--check-ids ()
+ "Check, that ids really point to a node."
+
+ (let ((lines 0)
+ id ids marker)
+
+ (goto-char org-index--below-hline)
+
+ (catch 'problem
+ (while (org-at-table-p)
+
+ (when (setq id (org-index--get-or-set-field 'id))
+
+ ;; check for double ids
+ (when (member id ids)
+ (org-table-goto-column (org-index--column-num 'id))
+ (throw 'problem "This id appears twice in index; please use command 'maintain' to check for duplicate ids"))
+ (incf lines)
+ (setq ids (cons id ids))
+
+ ;; check, if id is valid
+ (setq marker (org-id-find id t))
+ (unless marker
+ (org-table-goto-column (org-index--column-num 'id))
+ (throw 'problem "This id cannot be found")))
+
+ (forward-line))
+
+ (goto-char org-index--below-hline)
+ nil)))
+
+
+(defun org-index--update-all-lines ()
+ "Update all lines of index at once."
+
+ (let ((lines 0)
+ id ref kvs)
+
+ ;; check for double ids
+ (or
+ (org-index--check-ids)
+
+ (progn
+ (goto-char org-index--below-hline)
+ (while (org-at-table-p)
+
+ ;; update single line
+ (when (setq id (org-index--get-or-set-field 'id))
+ (setq ref (org-index--get-or-set-field 'ref))
+ (setq kvs (org-index--collect-values-for-add-update-remote id))
+ (org-index--write-fields-for-add-update kvs)
+ (incf lines))
+ (forward-line))
+
+ (goto-char org-index--below-hline)
+ (org-table-align)
+ (format "Updated %d lines" lines)))))
+
+
+(defun org-index--collect-values-for-add-update (id &optional silent category)
+ "Collect values for adding or updating line specified by ID, do not ask if SILENT, use CATEGORY, if given."
+
+ (let ((args (list 'ref t 'id id))
+ content)
- (if ref (setq org-index--last-ref ref))
+ (dolist (col-num org-index--columns)
- (let (message-text)
- ;; Use link if available
- (if link
- (progn
- (org-index--update-line link)
- (org-id-goto link)
- (org-reveal)
- (if (eq (current-buffer) org-index--buffer)
- (setq org-index--point-before nil))
- (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))
+ (setq content "")
+
+ (if (eq (car col-num) 'keywords)
+ (setq content (nth 4 (org-heading-components))))
+
+ (if (eq (car col-num) 'category)
+ (setq content (or category org-index--category-before)))
- (progn
- (if (eq buffer org-index--buffer)
- (setq org-index--point-before nil))
- (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))
+ (if (eq (car col-num) 'level)
+ (setq content (number-to-string (org-outline-level))))
+
+ ;; Shift ref and timestamp ?
+ (if (org-index--flag-p 'shift-ref-and-date-on-add (car col-num))
+ (dotimes (i 2)
+ (if (or (string-match (concat "^\\s-*" org-index--ref-regex) content)
+ (string-match (concat org-ts-regexp-both) content))
+ (setq content (substring content (match-end 0))))))
+
+ (if (and (not silent) ; do not edit, if heading has already been added
+ (org-index--flag-p 'edit-on-add (car col-num)))
+ (setq content (read-from-minibuffer
+ (format "Edit text for column '%s': " (symbol-name (car col-num)))
+ content)))
+
+ (if (not (string= content ""))
+ (setq args (append (list (car col-num) content) args))))
+ args))
-(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 "")
- 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-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 (kbd "RET") fun-on-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 (kbd "<tab>") fun-on-tab)
- (define-key keymap [(control ?i)] fun-on-tab)
- (define-key keymap (kbd "<up>") (lambda () (interactive)
- (forward-line -1)
- (if org-index--occur-follow-mode (org-index--occur-find-heading t))))
- (define-key keymap (kbd "<down>") (lambda () (interactive)
- (forward-line 1)
- (if org-index--occur-follow-mode (org-index--occur-find-heading t))))
- (use-local-map keymap)))
+(defun org-index--collect-values-for-add-update-remote (id)
+ "Wrap `org-index--collect-values-for-add-update' by prior moving to remote node identified by ID."
+
+ (let (marker point args)
- (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)))
+ (setq marker (org-id-find id t))
+ ;; enter buffer and collect information
+ (with-current-buffer (marker-buffer marker)
+ (setq point (point))
+ (goto-char marker)
+ (setq args (org-index--collect-values-for-add-update id t (org-get-category (point) t)))
+ (goto-char point))
- (org-pop-to-buffer-same-window occur-buffer)
- (toggle-truncate-lines 1)
+ args))
- (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))
- (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)))
+(defun org-index--write-fields-for-add-update (kvs)
+ "Update current line with values from KVS (keys-values)."
+ (while kvs
+ (unless (eq (car kvs) 'ref)
+ (org-index--get-or-set-field (car kvs) (org-trim (cadr kvs))))
+ (setq kvs (cddr kvs))))
- ;; 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 ?\C-i 'TAB)))))
-
- (not exit-gracefully))
-
- (cond
- ((eq key 'C-backspace)
+(defun org-index--do-delete ()
+ "Perform command delete."
+
+ (unless (org-at-heading-p)
+ (error "Not at headline"))
- (setq in-c-backspace t))
+ (let* ((id (org-entry-get (point) "ID"))
+ (ref (org-index--ref-from-id id)))
- ((member key (list 'backspace 'deletechar ?\C-?)) ; erase last char
+ ;; maybe delete from heading
+ (if ref
+ (save-excursion
+ (end-of-line)
+ (let ((end (point)))
+ (beginning-of-line)
+ (when (search-forward ref end t)
+ (delete-char (- (length ref)))
+ (just-one-space)))))
- (if (= (length word) 0)
+ ;; delete from index table
+ (if (org-index--delete-line id)
+ (format "Deleted index line %s" ref)
+ (format "Did not find id %s in index" id))))
- ;; 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)))
+(defun org-index--go (&optional column value)
+ "Position cursor on index line where COLUMN equals VALUE.
+Return t or nil, leave point on line or at top of table, needs to be in buffer initially."
+ (let (found text)
+
+ (unless (eq (current-buffer) org-index--buffer)
+ (error "This is a bug: Not in index buffer"))
+
+ ;; loop over lines
+ (goto-char org-index--below-hline)
+ (if column
+ (progn
+ (forward-line -1)
+ (while (and (not found)
+ (forward-line)
+ (org-at-table-p))
+ (setq found (string= value (org-index--get-or-set-field column)))))
+ (setq found t))
+
+ ;; return value
+ (if found
+ t
+ (goto-char org-index--below-hline)
+ nil)))
+
+
+(defun org-index--do-head (ref id &optional other)
+ "Perform command head: Find node with REF or ID and present it.
+If OTHER in separate window."
+
+ (setq org-index--last-ref ref)
+
+ (let (message marker)
+
+ (setq marker (org-id-find id t))
+
+ (if marker
+ (progn
+ (org-index--update-line id)
+ (let (cb)
+ (if other
+ (progn
+ (setq cb (current-buffer))
+ (pop-to-buffer (marker-buffer marker)))
+ (pop-to-buffer-same-window (marker-buffer marker)))
+
+ (goto-char marker)
+ (org-reveal t)
+ (org-show-entry)
+ (recenter))
+ (setq message (format "Found headline %s" ref)))
+ (setq message (format "Did not find headline %s" ref)))))
+
+
+(defun org-index--do-occur ()
+ "Perform command occur."
+ (let ((word "") ; last word to search for growing and shrinking on keystrokes
+ (prompt "Search for: ")
+ (lines-wanted (window-body-height))
+ (lines-found 0) ; number of lines found
+ words ; list words that should match
+ occur-buffer
+ begin ; position of first line
+ narrow ; start of narrowed buffer
+ help-text ; cons with help text short and long
+ key-help ; for keys with special function
+ search-text ; description of text to search for
+ done ; true, if loop is done
+ in-c-backspace ; true, while processing C-backspace
+ show-headings ; true, if headings should be shown
+ help-overlay ; Overlay with help text
+ last-point ; Last position before end of search
+ key ; input from user
+ key-sequence) ; as a sequence
- ;; 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 ??) ; tab: 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))
- (if (display-graphic-p)
- (insert "<backspace> and <c-backspace> erase, cursor keys move. RET finds node, C-RET all matches.\nTAB finds in other window. Comma seperates words, any other key adds to search word.\n\n")
- (insert "BACKSPACE to erase, to finish. Then cursor keys and RET to find node.\n\n"))
- (insert org-index--headings))
- (delete-region start-of-help start-of-lines)
- (insert "\n"))
- (setq start-of-lines (point)))
-
-
- ((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 (kbd "<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.")
- " Use cursor keys to move, press RET or TAB to find node.\n\n")
- numlines))
- (if show-headings (insert "\n\n" org-index--headings)))
- (forward-line))
+ ;; make and show buffer
+ (if (get-buffer org-index--occur-buffer-name)
+ (kill-buffer org-index--occur-buffer-name))
+ (setq occur-buffer (make-indirect-buffer org-index--buffer org-index--occur-buffer-name))
+ (pop-to-buffer-same-window occur-buffer)
+ ;; avoid modifying direct buffer
(setq buffer-read-only t)
+ (toggle-truncate-lines 1)
+ (setq font-lock-keywords-case-fold-search t)
+ (setq case-fold-search t)
- ;; perform action according to last char
+ ;; reset stack and overlays
+ (setq org-index--occur-stack nil)
+ (setq org-index--occur-tail-overlay nil)
+
+ ;; narrow to table rows and one line before
+ (goto-char (marker-position org-index--below-hline))
+ (forward-line 0)
+ (setq begin (point))
(forward-line -1)
- (cond
+ (setq narrow (point))
+ (while (org-at-table-p)
+ (forward-line))
+ (narrow-to-region narrow (point))
+ (goto-char (point-min))
+ (forward-line)
+
+ ;; initialize help text
+ (setq help-text (cons
+ "Incremental occur; `?' toggles help and headlines.\n"
+ (concat
+ (org-index--wrap
+ (concat
+ "Normal keys add to search word; <space> or <comma> start additional word; <backspace> erases last char, <C-backspace> last word; <return> jumps to heading, <tab> jumps to heading in other window; all other keys end search.\n"))
+ org-index--headings)))
+
+ ;; insert overlays for help text and to cover unsearched lines
+ (setq help-overlay (make-overlay (point-min) begin))
+ (overlay-put help-overlay 'display (car help-text))
+ (overlay-put help-overlay 'face 'org-agenda-dimmed-todo-face)
+ (setq org-index--occur-tail-overlay (make-overlay (point-max) (point-max)))
+ (overlay-put org-index--occur-tail-overlay 'invisible t)
- ((member key (list 'RET ?\C-m))
- (funcall fun-on-ret))
+ (while (not done)
- ((member key (list 'TAB ?\C-i))
- (funcall fun-on-tab))
+ (if in-c-backspace
+ (setq key "<backspace>")
+ (setq search-text (mapconcat 'identity (reverse (cons word words)) ","))
+ ;; read key
+ (setq key-sequence
+ (vector (read-key
+ (format "%s%s%s"
+ prompt
+ search-text
+ (if (string= search-text "") "" " ")))))
+ (setq key (key-description key-sequence)))
- ((eq key 'up)
- (forward-line -1))
+ (cond
- ((eq key 'down)
- (forward-line 1))
- ((eq key 'left)
- (forward-char -1))
+ ((string= key "<C-backspace>")
+ (setq in-c-backspace t))
- ((eq key 'right)
- (forward-char 1)))))
-(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)))))
+ ((member key (list "<backspace>" "DEL")) ; erase last char
+ (if (= (length word) 0)
-(defun org-index--do-new-line (create-ref)
- "Do the common work for org-index-new-line and org-index"
+ ;; 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
+ (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))
+
+ ;; free top list of overlays and remove list
+ (setq lines-found (or (org-index--unhide) lines-wanted))
+ (move-overlay org-index--occur-tail-overlay
+ (if org-index--occur-stack (cdr (assoc :end-of-visible (car org-index--occur-stack)))
+ (point-max))
+ (point-max))
+
+
+ ;; highlight shorter word
+ (unless (= (length word) 0)
+ (highlight-regexp (regexp-quote word) 'isearch))
- (let (new)
+ ;; make sure, point is still visible
+ (goto-char begin)))
- (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)
+ ((member key (list "SPC" ",")) ; space or comma: enter an additional search word
- ;; 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")
+ ;; push current word and clear, no need to change display
+ (setq words (cons word words))
+ (setq word ""))
- new))
+ ((string= key "?") ; question mark: toggle display of headlines and help
+ (setq help-text (cons (cdr help-text) (car help-text)))
+ (overlay-put help-overlay 'display (car help-text)))
+
+ ((and (= (length key) 1)
+ (aref printable-chars (elt key 0))) ; any printable char: add to current search word
+
+ ;; unhighlight short word
+ (unless (= (length word) 0)
+ (unhighlight-regexp (regexp-quote word)))
+
+ ;; add to word
+ (setq word (concat word key))
+
+ ;; make overlays to hide lines, that do not match longer word any more
+ (goto-char begin)
+ (setq lines-found (org-index--hide-with-overlays (cons word words) lines-wanted))
+ (move-overlay org-index--occur-tail-overlay
+ (if org-index--occur-stack (cdr (assoc :end-of-visible (car org-index--occur-stack)))
+ (point-max))
+ (point-max))
+
+ (goto-char begin)
+
+ ;; highlight longer word
+ (highlight-regexp (regexp-quote word) 'isearch)
+
+ ;; make sure, point is on a visible line
+ (line-move -1 t)
+ (line-move 1 t))
-(defun org-index--get-matching-lines (words numlines start-from)
- (let ((numfound 0)
- pos
- initial line lines at-end)
+ ;; anything else terminates loop
+ (t (setq done t))))
+
+ ;; put back input event, that caused the loop to end
+ (unless (string= key "C-g")
+ (setq unread-command-events (listify-key-sequence key-sequence))
+ (message key))
- (with-current-buffer org-index--buffer
+ ;; postprocessing
+ (setq last-point (point))
+
+ ;; For performance reasons do not show matching lines for rest of table. So no code here.
+
+ ;; make permanent copy
+ ;; copy visible lines
+ (let ((lines-collected 0)
+ keymap line all-lines end-of-head)
- ;; remember initial pos and start at requested
- (setq initial (point))
- (goto-char start-from)
+ (setq cursor-type t)
+ (goto-char begin)
+
+ ;; collect all visible lines
+ (while (and (not (eobp))
+ (< lines-collected lines-wanted))
+ ;; skip over invisible lines
+ (while (and (invisible-p (point))
+ (not (eobp)))
+ (goto-char (1+ (overlay-end (car (overlays-at (point)))))))
+ (setq line (buffer-substring (line-beginning-position) (line-end-position)))
+ (unless (string= line "")
+ (incf lines-collected)
+ (setq all-lines (cons (concat line
+ "\n")
+ all-lines)))
+ (forward-line 1))
+
+ (kill-buffer org-index--occur-buffer-name) ; cannot keep this buffer; might become stale soon
+
+ ;; create new buffer
+ (setq occur-buffer (get-buffer-create org-index--occur-buffer-name))
+ (pop-to-buffer-same-window occur-buffer)
+ (insert org-index--headings)
+ (setq end-of-head (point))
+
+ ;; insert into new buffer
+ (save-excursion
+ (apply 'insert (reverse all-lines))
+ (if (= lines-collected lines-wanted)
+ (insert "\n(more lines omitted)\n")))
- ;; 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)))
+ (org-mode)
+ (setq truncate-lines t)
+ (if (org-at-table-p) (org-table-align))
+ (font-lock-fontify-buffer)
+
+ ;; prepare help text
+ (setq org-index--occur-help-overlay (make-overlay (point-min) end-of-head))
+ (setq org-index--occur-help-text
+ (cons
+ (org-index--wrap
+ (concat "Search is done; `?' toggles help and headlines.\n"))
+ (concat
+ (org-index--wrap (format (concat "Search is done. "
+ (if (< lines-collected lines-wanted)
+ " Showing all %d matches for "
+ " Showing one window of matches for ")
+ "\"" search-text
+ "\". <return> jumps to heading, <tab> jumps to heading in other window, <S-return> to matching line in index, <space> increments count.\n" )
+ (length all-lines)))
+ org-index--headings)))
+
+ (overlay-put org-index--occur-help-overlay 'display (car org-index--occur-help-text))
+ (overlay-put org-index--occur-help-overlay 'face 'org-agenda-dimmed-todo-face)
- (setq at-end (not (org-at-table-p)))
+ ;; highlight words
+ (setq case-fold-search t)
+ (setq font-lock-keywords-case-fold-search t)
+ (mapc (lambda (w) (unless (or (not w) (string= w "")) (highlight-regexp (regexp-quote w) 'isearch)))
+ (cons word words))
- ;; return to initial position
- (goto-char initial))
+ (setq buffer-read-only t)
- (unless lines (setq lines ""))
- (list pos lines at-end)))
+ ;; install keyboard-shortcuts
+ (setq keymap (make-sparse-keymap))
+ (set-keymap-parent keymap org-mode-map)
+ (mapc (lambda (x) (define-key keymap (kbd x)
+ (lambda () (interactive)
+ (message "%s" (org-index--occur-to-head)))))
+ (list "<return>" "RET"))
-(defun org-index--test-words (words line)
- (let ((found-all t))
- (setq line (downcase line))
+ (define-key keymap (kbd "<tab>")
+ (lambda () (interactive)
+ (message (org-index--occur-to-head t))))
+
+ (define-key keymap (kbd "SPC")
+ (lambda () (interactive)
+ ;; increment in index
+ (let ((ref (org-index--get-or-set-field 'ref))
+ count)
+ (org-index--on
+ 'ref ref
+ (setq count (+ 1 (string-to-number (org-index--get-or-set-field 'count))))
+ (org-index--get-or-set-field 'count (number-to-string count))
+ (org-index--promote-current-line)
+ (org-index--align-and-fontify-current-line))
+ ;; increment in this buffer
+ (let ((inhibit-read-only t))
+ (org-index--get-or-set-field 'count (number-to-string count)))
+ (message "Incremented count to %d" count))))
+
+ (define-key keymap (kbd "<S-return>")
+ (lambda () (interactive)
+ (org-index 'enter (org-index--get-or-set-field 'ref))))
+
+ (define-key keymap (kbd "?")
+ (lambda () (interactive)
+ (setq-local org-index--occur-help-text (cons (cdr org-index--occur-help-text) (car org-index--occur-help-text)))
+ (overlay-put org-index--occur-help-overlay 'display (car org-index--occur-help-text))))
+
+ (use-local-map keymap))))
+
+
+(defun org-index--wrap (text)
+ "Wrap TEXT at fill column."
+ (with-temp-buffer
+ (insert text)
+ (fill-region (point-min) (point-max) nil t)
+ (buffer-string)))
+
+
+(defun org-index--occur-to-head (&optional other)
+ "Helper for `org-index--occur', find heading with ref or id; if OTHER, in other window."
+ (let ((ref (org-index--get-or-set-field 'ref))
+ (id (org-index--get-or-set-field 'id)))
+ (if id
+ (org-index--do-head ref id other)
+ (message "Current line has no id."))))
+
+
+(defun org-index--hide-with-overlays (words lines-wanted)
+ "Hide text that is currently visible and does not match WORDS by creating overlays; leave LINES-WANTED lines visible."
+ (let ((lines-found 0)
+ (end-of-visible (point))
+ overlay overlays start matched)
+
+ ;; main loop
+ (while (and (not (eobp))
+ (< lines-found lines-wanted))
+
+ ;; skip invisible lines
+ (while (and (not (eobp))
+ (and
+ (invisible-p (point))
+ (< (point) (overlay-start org-index--occur-tail-overlay))))
+ (goto-char (overlay-end (car (overlays-at (point))))))
+
+ ;; find stretch of lines, that are currently visible but should be invisible now
+ (setq matched nil)
+ (setq start (point))
+ (while (and (not (eobp))
+ (not
+ (and
+ (invisible-p (point))
+ (< (point) (overlay-start org-index--occur-tail-overlay))))
+ (not (and (org-index--test-words words)
+ (setq matched t)))) ; for its side effect
+ (forward-line 1))
+
+ ;; create overlay to hide this stretch
+ (when (< start (point)) ; avoid creating an empty overlay
+ (setq overlay (make-overlay start (point)))
+ (overlay-put overlay 'invisible t)
+ (setq overlays (cons overlay overlays)))
+
+ ;; skip and count line, that matched
+ (when matched
+ (forward-line 1)
+ (setq end-of-visible (point))
+ (incf lines-found)))
+
+ ;; put new list on top of stack
+ (setq org-index--occur-stack
+ (cons (list (cons :overlays overlays)
+ (cons :end-of-visible end-of-visible)
+ (cons :lines lines-found))
+ org-index--occur-stack))
+
+ lines-found))
+
+
+(defun org-index--unhide ()
+ "Unhide text that does has been hidden by `org-index--hide-with-overlays'."
+ (when org-index--occur-stack
+ ;; delete overlays and make visible again
+ (mapc (lambda (y)
+ (delete-overlay y))
+ (cdr (assoc :overlays (car org-index--occur-stack))))
+ ;; remove from stack
+ (setq org-index--occur-stack (cdr org-index--occur-stack))
+ ;; return number of lines, that are now visible
+ (if org-index--occur-stack (cdr (assoc :lines (car org-index--occur-stack))))))
+
+
+(defun org-index--test-words (words)
+ "Test current line for match against WORDS."
+ (let (line)
+ (setq line (downcase (buffer-substring (line-beginning-position) (line-beginning-position 2))))
(catch 'not-found
- (dolist (w words)
- (or (search w line)
- (throw 'not-found nil)))
- t)))
+ (dolist (w words)
+ (or (search w line)
+ (throw 'not-found nil)))
+ t)))
-(defun org-index--dump-variables ()
- "Dump variables of org-index; mostly for debugging"
- (interactive)
- "Dump all variables of org-index for debugging"
- (let ((buff (get-buffer-create "*org-index-dump-variables*"))
- (maxlen 0)
- vars name value)
-
- (with-current-buffer buff
- (erase-buffer)
- (mapatoms (lambda (s) (when (and (boundp s)
- (string-prefix-p "org-index-" (symbol-name s)))
-
- (setq name (symbol-name s))
- (setq value (symbol-value s))
- (setq vars (cons (cons name value) vars))
- (if (> (length name) maxlen)
- (setq maxlen (length name))))))
- (setq vars (sort vars (lambda (x y) (string< (car x) (car y)))))
- (mapc (lambda (x) (insert (format (format "%%-%ds: %%s\n" (+ maxlen 1)) (car x) (cdr x))))
- vars)
- (pop-to-buffer buff))))
-
-
-(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)))
+(defun org-index--create-new-line ()
+ "Do the common work for `org-index-new-line' and `org-index'."
+
+ (let (new)
+
+ ;; construct new reference
+ (unless new
+ (setq new (format "%s%d%s" org-index--head (1+ org-index--maxref) org-index--tail)))
+
+ ;; insert ref or id as last or first line, depending on sort-column
+ (goto-char org-index--below-hline)
+ (if (eq (org-index--special-column 'sort) 'count)
+ (progn
+ (while (org-at-table-p)
+ (forward-line))
+ (forward-line -1)
+ (org-table-insert-row t))
+ (org-table-insert-row))
+
+ ;; insert some of the standard values
+ (org-table-goto-column (org-index--column-num 'created))
+ (org-insert-time-stamp nil nil t)
+ (org-table-goto-column (org-index--column-num 'count))
+ (insert "1")
+
+ new))
+
+
+(defun org-index--sort-silent ()
+ "Sort index for default column to remove any effects of temporary sorting."
+ (save-excursion
+ (org-index--verify-id)
+ (org-index--parse-table)
+ (org-index--on nil nil
+ (org-index--do-sort-index (org-index--special-column 'sort))
+ (org-table-align)
+ (remove-hook 'before-save-hook 'org-index--sort-silent))))
+
+
+(defun org-index--copy-visible (beg end)
+ "Copy the visible parts of the region without adding it to kill-ring; copy of `org-copy-visible'"
+ (let (snippets s)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (setq s (goto-char (point-min)))
+ (while (not (= (point) (point-max)))
+ (goto-char (org-find-invisible))
+ (push (buffer-substring s (point)) snippets)
+ (setq s (goto-char (org-find-visible))))))
+ (apply 'concat (nreverse snippets))))
(provide 'org-index)
@@ -2214,4 +2495,3 @@ retrieves the value of the count-column for reference 12.
;; End:
;;; org-index.el ends here
-
diff --git a/contrib/lisp/org-license.el b/contrib/lisp/org-license.el
index 44a1ea7..426b148 100644
--- a/contrib/lisp/org-license.el
+++ b/contrib/lisp/org-license.el
@@ -45,15 +45,15 @@
(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-sa/3.0/br/deed.pt_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-sa/3.0/es/deed.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-sa/3.0/de/deed.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")
@@ -96,8 +96,10 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
(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 (concat (insert "* License
-This document is under a [[" org-license-cc-url "][Creative Commons Attribution 3.0]]\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"))))
@@ -153,9 +155,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
(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/3.0/deed")
+ (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 Unported 3.0]]\n"))))
+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"))))
@@ -179,11 +181,11 @@ Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennun
(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-sa/3.0/es/deed.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-sa/1.0/fi/deed.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")
@@ -211,9 +213,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
(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/3.0/deed")
+ (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 Unported 3.0]]\n"))))
+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"))))
@@ -270,9 +272,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
(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/3.0/deed")
+ (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 3.0 Unported]]\n"))))
+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"))))
@@ -328,9 +330,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
(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/3.0/deed")
+ (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 3.0 Unported]]\n"))))
+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"))))
@@ -386,10 +388,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
(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/3.0/deed")
+ (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
-Reconocimiento-NoComercial-SinObraDerivada 3.0 Unported]]\n"))))
+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"))))
@@ -398,14 +399,14 @@ Reconocimiento-NoComercial-SinObraDerivada 3.0 Unported]]\n"))))
(interactive "MLanguage (es | en): " language)
(cond ((equal language "es")
(insert "* Licencia
-Copyright (C) 2013 " user-full-name
+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) 2013 " user-full-name
+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;
diff --git a/contrib/lisp/org-mac-link.el b/contrib/lisp/org-mac-link.el
index d1687e0..e0636a5 100644
--- a/contrib/lisp/org-mac-link.el
+++ b/contrib/lisp/org-mac-link.el
@@ -1,13 +1,13 @@
-;;; org-mac-link.el --- Grab links and url from various mac
-;; Application and insert them as links into org-mode documents
+;;; org-mac-link.el --- Insert org-mode links to items selected in various Mac apps
;;
;; Copyright (c) 2010-2014 Free Software Foundation, Inc.
;;
-;; Authors:
-;; Anthony Lander <anthony.lander@gmail.com>
-;; John Wiegley <johnw@gnu.org>
-;; Christopher Suckling <suckling at gmail dot com>
-;; Daniil Frumin <difrumin@gmail.com>
+;; 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>
;;
;;
;; Version: 1.1
@@ -57,6 +57,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 +87,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 [c]hrome 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,23 +154,23 @@ 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)
-(defcustom org-mac-mail-account "customize"
+(defcustom org-mac-mail-account nil
"The Mail.app account in which to search for flagged messages."
:group 'org-mac-flagged-mail
:type 'string)
@@ -185,27 +191,32 @@ 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)) ?:)
@@ -221,12 +232,17 @@ 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>"
- (let* ((link-list
- (mapcar
- (lambda (x) (if (string-match "\\`\"\\(.*\\)\"\\'" x) (setq x (match-string 1 x))) x)
- (split-string as-link-list "[\r\n]+")))
+ "Paste in a list of links from an applescript handler.
+The links are of the form <link>::split::<name>."
+ (let* ((noquote-as-link-list
+ (if (string-prefix-p "\"" as-link-list)
+ (substring as-link-list 1 -1)
+ as-link-list))
+ (link-list
+ (mapcar (lambda (x) (if (string-match "\\`\"\\(.*\\)\"\\'" x)
+ (setq x (match-string 1 x)))
+ x)
+ (split-string noquote-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 +256,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 +272,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 +319,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,19 +365,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 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)))))
+ (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)
@@ -384,57 +402,45 @@ 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"))))
- (car (split-string result "[\r\n]+" t))))
+ (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")))
(defun org-mac-safari-get-frontmost-url ()
(interactive)
(message "Applescript: Getting Safari url...")
- (let* ((url-and-title (org-as-mac-safari-get-frontmost-url))
- (split-link (split-string url-and-title "::split::"))
- (URL (car split-link))
- (description (cadr split-link))
- (org-link))
- (when (not (string= URL ""))
- (setq org-link (org-make-link-string URL description)))
- (kill-new org-link)
- org-link))
+ (org-mac-paste-applescript-links
+ (org-as-mac-safari-get-frontmost-url)))
(defun org-mac-safari-insert-frontmost-url ()
(interactive)
(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)
@@ -444,26 +450,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)
@@ -475,30 +477,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)
@@ -509,8 +507,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)
@@ -523,40 +520,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)
@@ -575,12 +571,8 @@ 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)
@@ -589,9 +581,9 @@ applications and inserting them in org documents"
(do-applescript
(concat
"tell application \"Microsoft Outlook\"\n"
- (format "open message id %s\n" (substring-no-properties msgid))
- "activate\n"
- "end tell")))
+ (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."
@@ -672,16 +664,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))
@@ -702,17 +696,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) ">")))
@@ -720,67 +775,43 @@ 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."
+ (unless org-mac-mail-account
+ (error "You must set org-mac-mail-account"))
(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
+ ;; 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"
+ "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.
@@ -792,27 +823,11 @@ The Org-syntax text will be pushed to the kill ring, and also returned."
(interactive "sLink to (s)elected or (f)lagged messages: ")
(setq select-or-flag (or select-or-flag "s"))
(message "AppleScript: searching mailboxes...")
- (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\""))))
- (link-list
- (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::"))
- (setq URL (car split-link))
- (setq description (cadr split-link))
- (when (not (string= URL ""))
- (setq orglink (org-make-link-string URL description))
- (push orglink orglink-list)))
- (setq rtn (mapconcat 'identity orglink-list "\n"))
- (kill-new rtn)
- rtn))
+ (org-mac-paste-applescript-links
+ (cond
+ ((string= select-or-flag "s") (org-as-get-selected-mail))
+ ((string= select-or-flag "f") (org-as-get-flagged-mail))
+ (t (error "Please select \"s\" or \"f\"")))))
(defun org-mac-message-insert-selected ()
"Insert a link to the messages currently selected in Mail.app.
@@ -843,11 +858,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-mew.el b/contrib/lisp/org-mew.el
index 4482375..eb0afc0 100644
--- a/contrib/lisp/org-mew.el
+++ b/contrib/lisp/org-mew.el
@@ -308,7 +308,7 @@ the subject and the group number to extract. You can get rid of
org-mew-subject-alist))
(setq id-list (cons subject id-list)))
(cond ((null id-list)
- (error "No message ID to search."))
+ (error "No message ID to search"))
((equal (length id-list) 1)
(org-search-view nil (car id-list)))
(t
@@ -342,7 +342,7 @@ asks you to select the capture template."
(mew-message-goto-summary))
(let ((mew-mark-afterstep-spec '((?o 0 0 0 0 0 0 0))))
(mew-summary-refile)))
- (error "No refile folder selected."))
+ (error "No refile folder selected"))
(let* ((org-mew-link-to-refile-destination t)
(folder-name (org-mew-folder-name))
(keys (if arg
diff --git a/contrib/lisp/org-mime.el b/contrib/lisp/org-mime.el
index b0007ac..197c712 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-2014 Eric Schulte
+;; Copyright (C) 2010-2015 Eric Schulte
;; Author: Eric Schulte
;; Keywords: mime, mail, email, html
@@ -111,7 +111,7 @@
;; example hook, for setting a dark background in <pre style="background-color: #EEE;"> elements
(defun org-mime-change-element-style (element style)
"Set new default htlm style for <ELEMENT> elements in exported html."
- (while (re-search-forward (format "<%s" element) nil t)
+ (while (re-search-forward (format "<%s\\>" element) nil t)
(replace-match (format "<%s style=\"%s\"" element style))))
(defun org-mime-change-class-style (class style)
@@ -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 "?")))
@@ -249,28 +252,30 @@ export that region, otherwise export the entire body."
(save-restriction
(org-narrow-to-subtree)
(run-hooks 'org-mime-send-subtree-hook)
- (flet ((mp (p) (org-entry-get nil p org-mime-use-property-inheritance)))
- (let* ((file (buffer-file-name (current-buffer)))
- (subject (or (mp "MAIL_SUBJECT") (nth 4 (org-heading-components))))
- (to (mp "MAIL_TO"))
- (cc (mp "MAIL_CC"))
- (bcc (mp "MAIL_BCC"))
- (body (buffer-substring
- (save-excursion (goto-char (point-min))
- (forward-line 1)
- (when (looking-at "[ \t]*:PROPERTIES:")
- (re-search-forward ":END:" nil)
- (forward-char))
- (point))
- (point-max))))
- (org-mime-compose body (or fmt 'org) file to subject
- `((cc . ,cc) (bcc . ,bcc)))))))
+ (let* ((mp (lambda (p) (org-entry-get nil p org-mime-use-property-inheritance)))
+ (file (buffer-file-name (current-buffer)))
+ (subject (or (funcall mp "MAIL_SUBJECT") (nth 4 (org-heading-components))))
+ (to (funcall mp "MAIL_TO"))
+ (cc (funcall mp "MAIL_CC"))
+ (bcc (funcall mp "MAIL_BCC"))
+ (body (buffer-substring
+ (save-excursion (goto-char (point-min))
+ (forward-line 1)
+ (when (looking-at "[ \t]*:PROPERTIES:")
+ (re-search-forward ":END:" nil)
+ (forward-char))
+ (point))
+ (point-max))))
+ (org-mime-compose body (or fmt 'org) file to subject
+ `((cc . ,cc) (bcc . ,bcc))))))
(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)))
@@ -282,45 +287,46 @@ export that region, otherwise export the entire body."
(require 'message)
(message-mail to subject headers nil)
(message-goto-body)
- (flet ((bhook (body fmt)
- (let ((hook (intern (concat "org-mime-pre-"
- (symbol-name fmt)
- "-hook"))))
- (if (> (eval `(length ,hook)) 0)
- (with-temp-buffer
- (insert body)
- (goto-char (point-min))
- (eval `(run-hooks ',hook))
- (buffer-string))
- body))))
- (let ((fmt (if (symbolp fmt) fmt (intern fmt))))
- (cond
- ((eq fmt 'org)
- (require 'ox-org)
- (insert (org-export-string-as
- (org-babel-trim (bhook body 'org)) 'org t)))
- ((eq fmt 'ascii)
- (require 'ox-ascii)
- (insert (org-export-string-as
- (concat "#+Title:\n" (bhook body 'ascii)) 'ascii t)))
- ((or (eq fmt 'html) (eq fmt 'html-ascii))
- (require 'ox-ascii)
- (require 'ox-org)
- (let* ((org-link-file-path-type 'absolute)
- ;; we probably don't want to export a huge style file
- (org-export-htmlize-output-type 'inline-css)
- (html-and-images
- (org-mime-replace-images
- (org-export-string-as (bhook body 'html) 'html t) file))
- (images (cdr html-and-images))
- (html (org-mime-apply-html-hook (car html-and-images))))
- (insert (org-mime-multipart
- (org-export-string-as
- (org-babel-trim
- (bhook body (if (eq fmt 'html) 'org 'ascii)))
- (if (eq fmt 'html) 'org 'ascii) t)
- html)
- (mapconcat 'identity images "\n"))))))))
+ (let ((bhook
+ (lambda (body fmt)
+ (let ((hook (intern (concat "org-mime-pre-"
+ (symbol-name fmt)
+ "-hook"))))
+ (if (> (eval `(length ,hook)) 0)
+ (with-temp-buffer
+ (insert body)
+ (goto-char (point-min))
+ (eval `(run-hooks ',hook))
+ (buffer-string))
+ body))))
+ (fmt (if (symbolp fmt) fmt (intern fmt))))
+ (cond
+ ((eq fmt 'org)
+ (require 'ox-org)
+ (insert (org-export-string-as
+ (org-babel-trim (funcall bhook body 'org)) 'org t)))
+ ((eq fmt 'ascii)
+ (require 'ox-ascii)
+ (insert (org-export-string-as
+ (concat "#+Title:\n" (funcall bhook body 'ascii)) 'ascii t)))
+ ((or (eq fmt 'html) (eq fmt 'html-ascii))
+ (require 'ox-ascii)
+ (require 'ox-org)
+ (let* ((org-link-file-path-type 'absolute)
+ ;; we probably don't want to export a huge style file
+ (org-export-htmlize-output-type 'inline-css)
+ (html-and-images
+ (org-mime-replace-images
+ (org-export-string-as (funcall bhook body 'html) 'html t) file))
+ (images (cdr html-and-images))
+ (html (org-mime-apply-html-hook (car html-and-images))))
+ (insert (org-mime-multipart
+ (org-export-string-as
+ (org-babel-trim
+ (funcall bhook body (if (eq fmt 'html) 'org 'ascii)))
+ (if (eq fmt 'html) 'org 'ascii) t)
+ html)
+ (mapconcat 'identity images "\n")))))))
(defun org-mime-org-buffer-htmlize ()
"Create an email buffer containing the current org-mode file
diff --git a/contrib/lisp/org-mtags.el b/contrib/lisp/org-mtags.el
deleted file mode 100644
index 5342184..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-2014 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-notmuch.el b/contrib/lisp/org-notmuch.el
index 2ab5c17..712ec5a 100644
--- a/contrib/lisp/org-notmuch.el
+++ b/contrib/lisp/org-notmuch.el
@@ -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.
@@ -90,14 +113,21 @@ 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))
+ (message "%s" 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..4ebd5a6
--- a/dev/null
+++ b/contrib/lisp/org-passwords.el
@@ -0,0 +1,384 @@
+;;; 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. It is part of org/contrib (see http://orgmode.org/). If
+;; you want to contribute with development, or have a problem, do it
+;; here: https://bitbucket.org/alfaromurillo/org-passwords.el
+
+;; 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', `org-passwords-copy-password' and
+;; `org-passwords-open-url' 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)
+;; (kbd "C-c o")
+;; 'org-passwords-open-url)))
+
+;; Finally, to enter new passwords, you can use `org-capture' and a
+;; minimal template like:
+
+;; ("p" "password" entry (file "~/documents/passwords.gpg")
+;; "* %^{Title}\n %^{URL}p %^{USERNAME}p %^{PASSWORD}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)
+
+;;;###autoload
+(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."
+ :type 'string
+ :group 'org-passwords)
+
+(defcustom org-passwords-username-property "USERNAME"
+ "Name of the property for user name entry."
+ :type 'string
+ :group 'org-passwords)
+
+(defcustom org-passwords-url-property "URL"
+ "Name of the property for URL entry."
+ :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-default-password-size "20"
+ "Default number of characters to use in
+org-passwords-generate-password. It has to be a string."
+ :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)
+
+(defcustom org-passwords-default-random-words-number "5"
+ "Default number of words to use in org-passwords-random-words.
+It has to be a string."
+ :type 'str
+ :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)
+ (funcall interprogram-cut-function
+ (org-entry-get (point)
+ org-passwords-password-property)))
+
+(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)
+ (funcall interprogram-cut-function
+ (org-entry-get (point)
+ org-passwords-username-property
+ t)))
+
+(defun org-passwords-open-url ()
+ "Browse the URL associated with the entry at the location of
+the cursor."
+ (interactive)
+ (browse-url (org-entry-get (point)
+ org-passwords-url-property
+ t)))
+
+;;;###autoload
+(defun org-passwords (&optional arg)
+ "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'.
+
+With prefix arg ARG, the command does not set up a timer to kill the buffer.
+
+With a double prefix arg \\[universal-argument] \\[universal-argument], open the file for editing.
+"
+ (interactive "P")
+ (if org-passwords-file
+ (progn
+ (add-to-list 'auto-mode-alist
+ (cons
+ (regexp-quote
+ (expand-file-name org-passwords-file))
+ 'org-passwords-mode))
+ (if (equal arg '(4))
+ (find-file-read-only org-passwords-file)
+ (if (equal arg '(16))
+ (find-file org-passwords-file)
+ (progn
+ (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
+ (read-from-minibuffer
+ (concat "Number of characters (default "
+ org-passwords-default-password-size
+ "): ")
+ nil
+ nil
+ t
+ nil
+ org-passwords-default-password-size)))
+ (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
+ (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
+ (read-from-minibuffer
+ (concat "Number of words (default "
+ org-passwords-default-random-words-number
+ "): ")
+ nil
+ nil
+ t
+ nil
+ org-passwords-default-random-words-number))
+ (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
+ this
+ (cdr list-of-strings)))
+ (car list-of-strings)))
+
+(provide 'org-passwords)
+
+;;; org-passwords.el ends here
diff --git a/contrib/lisp/org-toc.el b/contrib/lisp/org-toc.el
index 255b79e..622cc02 100644
--- a/contrib/lisp/org-toc.el
+++ b/contrib/lisp/org-toc.el
@@ -338,7 +338,7 @@ If DELETE is non-nil, delete other windows when in the Org buffer."
(interactive)
(condition-case nil
(outline-forward-same-level 1)
- (error (message "No next headline at this level.")))
+ (error (message "No next headline at this level")))
(if org-toc-info-mode (org-toc-info))
(if org-toc-follow-mode (org-toc-goto)))
@@ -347,7 +347,7 @@ If DELETE is non-nil, delete other windows when in the Org buffer."
(interactive)
(condition-case nil
(outline-backward-same-level 1)
- (error (message "No previous headline at this level.")))
+ (error (message "No previous headline at this level")))
(if org-toc-info-mode (org-toc-info))
(if org-toc-follow-mode (org-toc-goto)))
diff --git a/contrib/lisp/org-velocity.el b/contrib/lisp/org-velocity.el
index 3631a59..a7820f1 100644
--- a/contrib/lisp/org-velocity.el
+++ b/contrib/lisp/org-velocity.el
@@ -1,10 +1,10 @@
-;;; org-velocity.el --- something like Notational Velocity for Org.
+;;; org-velocity.el --- something like Notational Velocity for Org. -*- lexical-binding: t -*-
;; Copyright (C) 2010-2014 Paul M. Rodriguez
;; Author: Paul M. Rodriguez <paulmrodriguez@gmail.com>
;; Created: 2010-05-05
-;; Version: 3.0
+;; Version: 4.0
;; This file is not part of GNU Emacs.
@@ -64,7 +64,7 @@
(require 'button)
(require 'electric)
(require 'dabbrev)
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
(defgroup org-velocity nil
"Notational Velocity-style interface for Org."
@@ -133,9 +133,9 @@ file."
"Match on whole phrase, any word, or all words?"
:group 'org-velocity
:type '(choice
- (const :tag "Match whole phrase" phrase)
- (const :tag "Match any word" any)
- (const :tag "Match all words" all)
+ (const :tag "Match whole phrase" phrase)
+ (const :tag "Match any word" any)
+ (const :tag "Match all words" all)
(const :tag "Match a regular expression" regexp))
:safe (lambda (v) (memq v '(phrase any all regexp))))
@@ -152,6 +152,17 @@ See the documentation for `org-capture-templates'."
:group 'org-velocity
:type (or (get 'org-capture-templates 'custom-type) 'list))
+(defcustom org-velocity-heading-level 1
+ "Only match headings at this level or higher.
+0 means to match headings at any level."
+ :group 'org-velocity
+ :type 'integer
+ :safe (lambda (x)
+ (and (integerp x)
+ (>= x 0))))
+
+(defvar crm-separator) ;Ensure dynamic binding.
+
(defsubst org-velocity-grab-preview ()
"Grab preview of a subtree.
The length of the preview is determined by `window-width'.
@@ -172,14 +183,14 @@ Replace all contiguous whitespace with single spaces."
(point-max))))
" ")))
-(defstruct org-velocity-heading buffer position name level preview)
+(cl-defstruct org-velocity-heading buffer position name level preview)
(defsubst org-velocity-nearest-heading (position)
"Return last heading at POSITION.
If there is no last heading, return nil."
(save-excursion
(goto-char position)
- (re-search-backward org-velocity-heading-regexp)
+ (re-search-backward (org-velocity-heading-regexp))
(let ((components (org-heading-components)))
(make-org-velocity-heading
:buffer (current-buffer)
@@ -191,15 +202,18 @@ If there is no last heading, return nil."
(defconst org-velocity-index
(eval-when-compile
- (nconc (number-sequence 49 57) ;numbers
+ (nconc (number-sequence 49 57) ;numbers
(number-sequence 97 122) ;lowercase letters
(number-sequence 65 90))) ;uppercase letters
"List of chars for indexing results.")
(defconst org-velocity-match-buffer-name "*Velocity matches*")
-(defconst org-velocity-heading-regexp "^\\* "
- "Regexp to match only top-level headings.")
+(cl-defun org-velocity-heading-regexp (&optional (level org-velocity-heading-level))
+ "Regexp to match headings at LEVEL or deeper."
+ (if (zerop level)
+ "^\\*+ "
+ (format "^\\*\\{1,%d\\} " level)))
(defvar org-velocity-search nil
"Variable to bind to current search.")
@@ -223,12 +237,6 @@ of the base buffer; in the latter, return the file name of
(with-current-buffer (window-buffer (active-minibuffer-window))
(minibuffer-contents))))
-(defsubst org-velocity-singlep (object)
- "Return t when OBJECT is a list or sequence of one element."
- (if (consp object)
- (null (cdr object))
- (= (length object) 1)))
-
(defun org-velocity-bucket-file ()
"Return the proper file for Org-Velocity to search.
If `org-velocity-always-use-bucket' is t, use bucket file;
@@ -260,17 +268,22 @@ use it."
"Return the proper buffer for Org-Velocity to display in."
(get-buffer-create org-velocity-match-buffer-name))
+(defsubst org-velocity-match-window ()
+ (get-buffer-window (org-velocity-match-buffer)))
+
+(defsubst org-velocity-match-staging-buffer ()
+ (get-buffer-create " Velocity matches"))
+
(defun org-velocity-beginning-of-headings ()
"Goto the start of the first heading."
(goto-char (point-min))
;; If we are before the first heading we could still be at the
;; first heading.
- (or (looking-at org-velocity-heading-regexp)
- (re-search-forward org-velocity-heading-regexp)))
+ (or (looking-at (org-velocity-heading-regexp))
+ (re-search-forward (org-velocity-heading-regexp))))
(defun org-velocity-make-indirect-buffer (heading)
"Make or switch to an indirect buffer visiting HEADING."
-
(let* ((bucket (org-velocity-heading-buffer heading))
(name (org-velocity-heading-name heading))
(existing (get-buffer name)))
@@ -279,7 +292,8 @@ use it."
existing
(make-indirect-buffer
bucket
- (generate-new-buffer-name (org-velocity-heading-name heading))))))
+ (generate-new-buffer-name (org-velocity-heading-name heading))
+ t))))
(defun org-velocity-capture ()
"Record a note with `org-capture'."
@@ -287,34 +301,38 @@ use it."
org-velocity-capture-templates))
(org-capture nil
;; This is no longer automatically selected.
- (when (org-velocity-singlep org-capture-templates)
+ (when (null (cdr org-capture-templates))
(caar org-capture-templates)))
- (if org-capture-mode (rename-buffer org-velocity-search t))))
+ (when org-capture-mode
+ (rename-buffer org-velocity-search t))))
(defvar org-velocity-saved-winconf nil)
(make-variable-buffer-local 'org-velocity-saved-winconf)
(defun org-velocity-edit-entry (heading)
"Edit entry at HEADING in an indirect buffer."
- (let ((winconf (current-window-configuration)))
- (let ((buffer (org-velocity-make-indirect-buffer heading)))
- (with-current-buffer buffer
- (let ((org-inhibit-startup t))
- (org-mode))
- (setq org-velocity-saved-winconf winconf)
- (goto-char (org-velocity-heading-position heading))
- (narrow-to-region (point)
- (save-excursion
- (org-end-of-subtree t)
- (point)))
- (goto-char (point-min))
- (add-hook 'org-ctrl-c-ctrl-c-hook 'org-velocity-dismiss nil t))
- (pop-to-buffer buffer)
- (set (make-local-variable 'header-line-format)
- (format "%s Use C-c C-c to finish."
- (abbreviate-file-name
- (buffer-file-name
- (org-velocity-heading-buffer heading))))))))
+ (let ((winconf (current-window-configuration))
+ (buffer (org-velocity-make-indirect-buffer heading))
+ (inhibit-point-motion-hooks t)
+ (inhibit-field-text-motion t))
+ (with-current-buffer buffer
+ (setq org-velocity-saved-winconf winconf)
+ (goto-char (org-velocity-heading-position heading))
+ (let ((start (point))
+ (end (save-excursion
+ (org-end-of-subtree t)
+ (point))))
+ ;; Outline view and narrow-to-region interact poorly.
+ (outline-flag-region start end nil)
+ (narrow-to-region start end))
+ (goto-char (point-max))
+ (add-hook 'org-ctrl-c-ctrl-c-hook 'org-velocity-dismiss nil t))
+ (pop-to-buffer buffer)
+ (set (make-local-variable 'header-line-format)
+ (format "%s Use C-c C-c to finish."
+ (abbreviate-file-name
+ (buffer-file-name
+ (org-velocity-heading-buffer heading)))))))
(defun org-velocity-dismiss ()
"Save current entry and close indirect buffer."
@@ -327,14 +345,18 @@ use it."
(defun org-velocity-visit-button (button)
(run-hooks 'mouse-leave-buffer-hook)
- (if org-velocity-use-search-ring
- (add-to-history 'search-ring
- (button-get button 'search)
- search-ring-max))
- (org-velocity-edit-entry (button-get button 'match)))
+ (when org-velocity-use-search-ring
+ (add-to-history 'search-ring
+ (button-get button 'search)
+ search-ring-max))
+ (let ((match (button-get button 'match)))
+ (throw 'org-velocity-done
+ (lambda ()
+ (org-velocity-edit-entry match)))))
(define-button-type 'org-velocity-button
- 'action #'org-velocity-visit-button)
+ 'action #'org-velocity-visit-button
+ 'follow-link 'mouse-face)
(defsubst org-velocity-buttonize (heading)
"Insert HEADING as a text button with no hints."
@@ -352,8 +374,8 @@ use it."
(org-velocity-heading-preview heading)
'face 'shadow))))
-(defsubst* org-velocity-present-match (&key hint match)
- (with-current-buffer (org-velocity-match-buffer)
+(defsubst org-velocity-present-match (hint match)
+ (with-current-buffer (org-velocity-match-staging-buffer)
(when hint (insert "#" hint " "))
(org-velocity-buttonize match)
(org-velocity-insert-preview match)
@@ -362,19 +384,19 @@ use it."
(defun org-velocity-generic-search (search &optional hide-hints)
"Display any entry containing SEARCH."
(let ((hints org-velocity-index) matches)
- (block nil
+ (cl-block nil
(while (and hints (re-search-forward search nil t))
(let ((match (org-velocity-nearest-heading (point))))
(org-velocity-present-match
- :hint (unless hide-hints (car hints))
- :match match)
+ (unless hide-hints (car hints))
+ match)
(push match matches))
(setq hints (cdr hints))
- (unless (re-search-forward org-velocity-heading-regexp nil t)
+ (unless (re-search-forward (org-velocity-heading-regexp) nil t)
(return))))
(nreverse matches)))
-(defun* org-velocity-all-search (search &optional hide-hints max)
+(cl-defun org-velocity-all-search (search &optional hide-hints)
"Display only entries containing every word in SEARCH."
(let ((keywords (mapcar 'regexp-quote (split-string search)))
(hints org-velocity-index)
@@ -388,23 +410,23 @@ use it."
(setq org-map-continue-from
(save-excursion
(goto-char (line-end-position))
- (if (re-search-forward org-velocity-heading-regexp nil t)
+ (if (re-search-forward (org-velocity-heading-regexp) nil t)
(line-end-position)
(point-max))))
- (when (loop for word in keywords
- always (save-excursion
- (re-search-forward
- (concat "\\<" word "\\>")
- org-map-continue-from t)))
+ (when (cl-loop for word in keywords
+ always (save-excursion
+ (re-search-forward
+ (concat "\\<" word "\\>")
+ org-map-continue-from t)))
(let ((match (org-velocity-nearest-heading (match-end 0))))
(org-velocity-present-match
- :hint (unless hide-hints (car hints))
- :match match)
+ (unless hide-hints (car hints))
+ match)
(push match matches)
(setq hints (cdr hints))))))
(nreverse matches)))
-(defun* org-velocity-present (search &key hide-hints)
+(cl-defun org-velocity-present (search &key hide-hints)
"Buttonize matches for SEARCH in `org-velocity-match-buffer'.
If HIDE-HINTS is non-nil, display entries without indices. SEARCH
binds `org-velocity-search'.
@@ -425,7 +447,7 @@ Return matches."
(inhibit-field-text-motion t))
(save-excursion
(org-velocity-beginning-of-headings)
- (case org-velocity-search-method
+ (cl-case org-velocity-search-method
(all (org-velocity-all-search search hide-hints))
(phrase (org-velocity-generic-search
(concat "\\<" (regexp-quote search))
@@ -440,6 +462,7 @@ Return matches."
(invalid-regexp
(minibuffer-message "%s" lossage))))))))
(with-current-buffer (org-velocity-match-buffer)
+ (buffer-swap-text (org-velocity-match-staging-buffer))
(goto-char (point-min)))))
(with-current-buffer (org-velocity-match-buffer)
(erase-buffer))))
@@ -452,14 +475,14 @@ Return matches."
(add-hook 'org-store-link-functions 'org-velocity-store-link)
-(defun* org-velocity-create (search &key ask)
+(cl-defun org-velocity-create (search &key ask)
"Create new heading named SEARCH.
If ASK is non-nil, ask first."
(when (or (null ask) (y-or-n-p "No match found, create? "))
(let ((org-velocity-search search)
- (org-default-notes-file (org-velocity-bucket-file))
- ;; save a stored link
- org-store-link-plist)
+ (org-default-notes-file (org-velocity-bucket-file))
+ ;; save a stored link
+ org-store-link-plist)
(org-velocity-capture))
search))
@@ -469,17 +492,18 @@ If ASK is non-nil, ask first."
(unless (or
(not (stringp search))
(string= "" search)) ;exit on empty string
- (case
+ (cl-case
(if (and org-velocity-force-new (eq last-command-event ?\C-j))
:force
- (let ((matches (org-velocity-present search)))
+ (let* ((org-velocity-index (org-velocity-adjust-index))
+ (matches (org-velocity-present search)))
(cond ((null matches) :new)
- ((org-velocity-singlep matches) :follow)
+ ((null (cdr matches)) :follow)
(t :prompt))))
(:prompt (progn
(pop-to-buffer (org-velocity-match-buffer))
(let ((hint (org-velocity-electric-read-hint)))
- (when hint (case hint
+ (when hint (cl-case hint
(:edit (org-velocity-read nil search))
(:force (org-velocity-create search))
(otherwise (org-velocity-activate-button hint)))))))
@@ -493,17 +517,10 @@ If ASK is non-nil, ask first."
(button-activate (next-button (point))))
(org-velocity-read nil search)))))))
-(defun org-velocity-position (item list)
- "Return first position of ITEM in LIST."
- (loop for elt in list
- for i from 0
- when (equal elt item)
- return i))
-
(defun org-velocity-activate-button (char)
"Go to button on line number associated with CHAR in `org-velocity-index'."
(goto-char (point-min))
- (forward-line (org-velocity-position char org-velocity-index))
+ (forward-line (cl-position char org-velocity-index))
(goto-char
(button-start
(next-button (point))))
@@ -514,8 +531,8 @@ If ASK is non-nil, ask first."
"Complain about an undefined key."
(interactive)
(message "%s"
- (substitute-command-keys
- "\\[org-velocity-electric-new] for new entry,
+ (substitute-command-keys
+ "\\[org-velocity-electric-new] for new entry,
\\[org-velocity-electric-edit] to edit search,
\\[scroll-up] to scroll up,
\\[scroll-down] to scroll down,
@@ -525,20 +542,11 @@ If ASK is non-nil, ask first."
(defun org-velocity-electric-follow (ev)
"Follow a hint indexed by keyboard event EV."
(interactive (list last-command-event))
- (if (not (> (org-velocity-position ev org-velocity-index)
+ (if (not (> (cl-position ev org-velocity-index)
(1- (count-lines (point-min) (point-max)))))
(throw 'org-velocity-select ev)
(call-interactively 'org-velocity-electric-undefined)))
-(defun org-velocity-electric-click (ev)
- "Follow hint indexed by a mouse event EV."
- (interactive "e")
- (throw 'org-velocity-select
- (nth (1- (count-lines
- (point-min)
- (posn-point (event-start ev))))
- org-velocity-index)))
-
(defun org-velocity-electric-edit ()
"Edit the search string."
(interactive)
@@ -552,14 +560,15 @@ If ASK is non-nil, ask first."
(defvar org-velocity-electric-map
(let ((map (make-sparse-keymap)))
(define-key map [t] 'org-velocity-electric-undefined)
- (loop for c in org-velocity-index
- do (define-key map (char-to-string c) 'org-velocity-electric-follow))
+ (dolist (c org-velocity-index)
+ (define-key map (char-to-string c)
+ 'org-velocity-electric-follow))
(define-key map "0" 'org-velocity-electric-new)
(define-key map "\C-v" 'scroll-up)
(define-key map "\M-v" 'scroll-down)
(define-key map (kbd "RET") 'org-velocity-electric-edit)
- (define-key map [mouse-1] 'org-velocity-electric-click)
- (define-key map [mouse-2] 'org-velocity-electric-click)
+ (define-key map [mouse-1] nil)
+ (define-key map [mouse-2] nil)
(define-key map [escape] 'keyboard-quit)
(define-key map "\C-h" 'help-command)
map))
@@ -567,29 +576,19 @@ If ASK is non-nil, ask first."
(defun org-velocity-electric-read-hint ()
"Read index of button electrically."
(with-current-buffer (org-velocity-match-buffer)
+ (when (featurep 'evil)
+ ;; NB Idempotent.
+ (evil-make-overriding-map org-velocity-electric-map))
(use-local-map org-velocity-electric-map)
(catch 'org-velocity-select
(Electric-command-loop 'org-velocity-select "Follow: "))))
(defvar org-velocity-incremental-keymap
(let ((map (make-sparse-keymap)))
- (define-key map [mouse-1] 'org-velocity-click-for-incremental)
- (define-key map [mouse-2] 'org-velocity-click-for-incremental)
(define-key map "\C-v" 'scroll-up)
(define-key map "\M-v" 'scroll-down)
map))
-(defun org-velocity-click-for-incremental ()
- "Jump out of search and select hint clicked on."
- (interactive)
- (let ((ev last-command-event))
- (org-velocity-activate-button
- (nth (- (count-lines
- (point-min)
- (posn-point (event-start ev))) 2)
- org-velocity-index)))
- (throw 'click (current-buffer)))
-
(defun org-velocity-displaying-completions-p ()
"Is there a *Completions* buffer showing?"
(get-window-with-predicate
@@ -598,8 +597,7 @@ If ASK is non-nil, ask first."
'completion-list-mode))))
(defun org-velocity-update ()
- "Display results of search without hinting.
-Stop searching once there are more matches than can be displayed."
+ "Display results of search without hinting."
(unless (org-velocity-displaying-completions-p)
(let* ((search (org-velocity-minibuffer-contents))
(matches (org-velocity-present search :hide-hints t)))
@@ -607,20 +605,20 @@ Stop searching once there are more matches than can be displayed."
(select-window (active-minibuffer-window))
(unless (or (null search) (string= "" search))
(minibuffer-message "No match; RET to create")))
- ((and (org-velocity-singlep matches)
+ ((and (null (cdr matches))
org-velocity-exit-on-match)
(throw 'click search))
(t
(with-current-buffer (org-velocity-match-buffer)
(use-local-map org-velocity-incremental-keymap)))))))
-(defvar dabbrev--last-abbrev)
+(defvar dabbrev--last-abbreviation)
(defun org-velocity-dabbrev-completion-list (abbrev)
"Return all dabbrev completions for ABBREV."
;; This is based on `dabbrev-completion'.
(dabbrev--reset-global-variables)
- (setq dabbrev--last-abbrev abbrev)
+ (setq dabbrev--last-abbreviation abbrev)
(dabbrev--find-all-expansions abbrev case-fold-search))
(defvar org-velocity-local-completion-map
@@ -638,7 +636,7 @@ Stop searching once there are more matches than can be displayed."
(completion-no-auto-exit t)
(crm-separator " "))
(funcall
- (case org-velocity-search-method
+ (cl-case org-velocity-search-method
(phrase #'completing-read)
(any #'completing-read-multiple)
(all #'completing-read-multiple))
@@ -652,38 +650,50 @@ Stop searching once there are more matches than can be displayed."
;; `read-from-minibuffer'), but in this case it is the user-friendly
;; thing to do.
(minibuffer-with-setup-hook
- (lexical-let ((initial-input initial-input))
+ (let ((initial-input initial-input))
(lambda ()
(and initial-input (insert initial-input))
(goto-char (point-max))))
(if (eq org-velocity-search-method 'regexp)
- (read-regexp prompt)
+ (read-regexp prompt)
(if org-velocity-use-completion
- (org-velocity-read-with-completion prompt)
- (read-string prompt)))))
+ (org-velocity-read-with-completion prompt)
+ (read-string prompt)))))
+
+(cl-defun org-velocity-adjust-index
+ (&optional (match-window (org-velocity-match-window)))
+ "Truncate or extend `org-velocity-index' to the lines in
+MATCH-WINDOW."
+ (with-selected-window match-window
+ (let ((lines (window-height))
+ (hints (length org-velocity-index)))
+ (cond ((= lines hints)
+ org-velocity-index)
+ ;; Truncate the index to the size of
+ ;; the buffer to be displayed.
+ ((< lines hints)
+ (cl-subseq org-velocity-index 0 lines))
+ ;; If the window is so tall we run out of indices, at
+ ;; least make the additional results clickable.
+ ((> lines hints)
+ (append org-velocity-index
+ (make-list (- lines hints) nil)))))))
(defun org-velocity-incremental-read (prompt)
- "Read string with PROMPT and display results incrementally."
+ "Read string with PROMPT and display results incrementally.
+Stop searching once there are more matches than can be
+displayed."
(let ((res
(unwind-protect
(let* ((match-window (display-buffer (org-velocity-match-buffer)))
- (org-velocity-index
- ;; Truncate the index to the size of the buffer to be
- ;; displayed.
- (with-selected-window match-window
- (if (> (window-height) (length org-velocity-index))
- ;; (subseq org-velocity-index 0 (window-height))
- (let ((hints (copy-sequence org-velocity-index)))
- (setcdr (nthcdr (window-height) hints) nil)
- hints)
- org-velocity-index))))
+ (org-velocity-index (org-velocity-adjust-index match-window)))
(catch 'click
(add-hook 'post-command-hook 'org-velocity-update)
- (if (eq org-velocity-search-method 'regexp)
- (read-regexp prompt)
- (if org-velocity-use-completion
- (org-velocity-read-with-completion prompt)
- (read-string prompt)))))
+ (cond ((eq org-velocity-search-method 'regexp)
+ (read-regexp prompt))
+ (org-velocity-use-completion
+ (org-velocity-read-with-completion prompt))
+ (t (read-string prompt)))))
(remove-hook 'post-command-hook 'org-velocity-update))))
(if (bufferp res) (org-pop-to-buffer-same-window res) res)))
@@ -697,24 +707,31 @@ created named SEARCH.
If `org-velocity-bucket' is defined and
`org-velocity-always-use-bucket' is non-nil, then the bucket file
will be used; otherwise, this will work when called in any Org
-file. Calling with ARG forces current file."
+file.
+
+Calling with ARG reverses which file – the current file or the
+bucket file – to use. If the bucket file would have been used,
+then the current file is used instead, and vice versa."
(interactive "P")
(let ((org-velocity-always-use-bucket
- (if arg nil org-velocity-always-use-bucket)))
+ (if org-velocity-always-use-bucket
+ (not arg)
+ arg)))
;; complain if inappropriate
- (assert (org-velocity-bucket-file))
+ (cl-assert (org-velocity-bucket-file))
(let ((org-velocity-bucket-buffer
(find-file-noselect (org-velocity-bucket-file))))
(unwind-protect
(let ((dabbrev-search-these-buffers-only
(list (org-velocity-bucket-buffer))))
- (org-velocity-engine
- (if org-velocity-search-is-incremental
- (org-velocity-incremental-read "Velocity search: ")
- (org-velocity-read-string "Velocity search: " search))))
- (progn
- (kill-buffer (org-velocity-match-buffer))
- (delete-other-windows))))))
+ (funcall
+ (catch 'org-velocity-done
+ (org-velocity-engine
+ (if org-velocity-search-is-incremental
+ (org-velocity-incremental-read "Velocity search: ")
+ (org-velocity-read-string "Velocity search: " search)))
+ #'ignore)))
+ (kill-buffer (org-velocity-match-buffer))))))
(defalias 'org-velocity-read 'org-velocity)
diff --git a/contrib/lisp/org-wikinodes.el b/contrib/lisp/org-wikinodes.el
index 7f3e2e3..ff2d55a 100644
--- a/contrib/lisp/org-wikinodes.el
+++ b/contrib/lisp/org-wikinodes.el
@@ -316,11 +316,10 @@ with working links."
(defun org-wikinodes-add-to-font-lock-keywords ()
"Add wikinode CamelCase highlighting to `org-font-lock-extra-keywords'."
- (let ((m (member '(org-activate-plain-links) org-font-lock-extra-keywords)))
- (if m
- (setcdr m (cons '(org-wikinodes-activate-links) (cdr m)))
- (message
- "Failed to add wikinodes to `org-font-lock-extra-keywords'."))))
+ (let ((m (member '(org-activate-plain-links (0 'org-link t))
+ org-font-lock-extra-keywords)))
+ (if m (push '(org-wikinodes-activate-links) (cdr m))
+ (message "Failed to add wikinodes to `org-font-lock-extra-keywords'."))))
(add-hook 'org-font-lock-set-keywords-hook
'org-wikinodes-add-to-font-lock-keywords)
diff --git a/contrib/lisp/ox-bibtex.el b/contrib/lisp/ox-bibtex.el
index d92a1e4..0719866 100644
--- a/contrib/lisp/ox-bibtex.el
+++ b/contrib/lisp/ox-bibtex.el
@@ -36,7 +36,7 @@
;;
;; The usage is as follows:
;;
-;; #+BIBLIOGRAPHY: bibfilebasename stylename optional-options
+;; #+BIBLIOGRAPHY: bibfilename stylename optional-options
;;
;; e.g. given foo.bib and using style plain:
;;
@@ -44,6 +44,10 @@
;;
;; "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
@@ -89,8 +93,6 @@
;; Initialization
(eval-when-compile (require 'cl))
-(let ((jump-fn (car (org-remove-if-not #'fboundp '(ebib obe-goto-citation)))))
- (org-add-link-type "cite" jump-fn))
;;; Internal Functions
@@ -149,6 +151,27 @@ 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
@@ -168,7 +191,17 @@ Return new parse tree."
(when (equal (org-element-property :key keyword) "BIBLIOGRAPHY")
(let ((arguments (org-bibtex-get-arguments keyword))
(file (org-bibtex-get-file keyword))
- temp-file)
+ 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-sans-extension
+ (file-name-nondirectory file)))
;; limit is set: collect citations throughout the document
;; in TEMP-FILE and pass it to "bibtex2html" as "-citefile"
;; argument.
@@ -200,7 +233,7 @@ Return new parse tree."
(and temp-file (delete-file temp-file))
;; Open produced HTML file, and collect Bibtex key names
(with-temp-buffer
- (insert-file-contents (concat file ".html"))
+ (insert-file-contents (concat out-file ".html"))
;; Update `org-bibtex-html-entries-alist'.
(goto-char (point-min))
(while (re-search-forward
@@ -212,18 +245,25 @@ Return new parse tree."
(with-temp-buffer
(cond
((org-export-derived-backend-p backend 'html)
- (insert "<div id=\"bibliography\">\n<h2>References</h2>\n")
- (insert-file-contents (concat file ".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 file ".html")
+ (concat out-file ".html")
"-o"
- (concat file ".txt")))
+ (concat out-file ".txt")))
(error "Executing pandoc failed"))
- (insert "References\n==========\n\n")
- (insert-file-contents (concat file ".txt"))
+ (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)
@@ -243,7 +283,10 @@ Return new parse 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."
+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)
@@ -251,7 +294,8 @@ into \"\\cite{...}\" LaTeX fragments."
(let ((new-citation (list 'latex-fragment
(list :value ""
:post-blank (org-element-property
- :post-blank object)))))
+ :post-blank object))))
+ option)
;; Insert NEW-CITATION right before OBJECT.
(org-element-insert-before new-citation object)
;; Remove all subsequent contiguous citations from parse
@@ -266,6 +310,18 @@ into \"\\cite{...}\" LaTeX fragments."
(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
@@ -275,7 +331,8 @@ into \"\\cite{...}\" LaTeX fragments."
:post-blank (org-element-property :post-blank object))
(org-element-put-property
new-citation
- :value (format "\\cite{%s}"
+ :value (format "\\cite%s{%s}"
+ (or option "")
(mapconcat 'identity (nreverse keys) ",")))))))))
tree)
diff --git a/contrib/lisp/ox-deck.el b/contrib/lisp/ox-deck.el
index ea2d8fe..915373f 100644
--- a/contrib/lisp/ox-deck.el
+++ b/contrib/lisp/ox-deck.el
@@ -38,6 +38,12 @@
;; See ox.el and ox-html.el for more details on how this exporter
;; works (it is derived from ox-html.)
+;; TODOs
+;; ------
+;; The title page is formatted using format-spec. This is error prone
+;; when details are missing and may insert empty tags, like <h2></h2>,
+;; for missing values.
+
(require 'ox-html)
(eval-when-compile (require 'cl))
@@ -51,7 +57,9 @@
(if a (org-deck-export-to-html t s v b)
(org-open-file (org-deck-export-to-html nil s v b)))))))
:options-alist
- '((:html-link-home "HTML_LINK_HOME" nil nil)
+ '((:description "DESCRIPTION" nil nil newline)
+ (:keywords "KEYWORDS" nil nil space)
+ (:html-link-home "HTML_LINK_HOME" nil nil)
(: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)
@@ -259,6 +267,7 @@ Defaults to styles for the title page."
(defcustom org-deck-title-slide-template
"<h1>%t</h1>
+<h2>%s</h2>
<h2>%a</h2>
<h2>%e</h2>
<h2>%d</h2>"
@@ -378,7 +387,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 39fb1cc..3287d5d 100644
--- a/contrib/lisp/ox-freemind.el
+++ b/contrib/lisp/ox-freemind.el
@@ -312,7 +312,7 @@ will result in following node:
(org-element-property :title element))
(org-data
(plist-get info :title))
- (t (error "Shouldn't come here."))))
+ (t (error "Shouldn't come here"))))
(element-contents (org-element-contents element))
(section (assq 'section element-contents))
(section-contents
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 f1f0dd1..ade3478 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-2014 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2015 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
;; Author: Luis R Anaya <papoanaya aroba hot mail punto com>
@@ -50,8 +50,6 @@
(center-block . org-groff-center-block)
(clock . org-groff-clock)
(code . org-groff-code)
- (comment . (lambda (&rest args) ""))
- (comment-block . (lambda (&rest args) ""))
(drawer . org-groff-drawer)
(dynamic-block . org-groff-dynamic-block)
(entity . org-groff-entity)
@@ -563,7 +561,8 @@ See `org-groff-text-markup-alist' for details."
(t (format ".AF \"%s\" \n" (or org-groff-organization "")))))
;; 2. Title
- (let ((subtitle1 (plist-get attr :subtitle1))
+ (let ((title (if (plist-get info :with-title) title ""))
+ (subtitle1 (plist-get attr :subtitle1))
(subtitle2 (plist-get attr :subtitle2)))
(cond
@@ -1253,15 +1252,10 @@ 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)))
- (t raw-path)))
- protocol)
+ ((string= type "file") (org-export-file-uri raw-path))
+ (t raw-path))))
(cond
+ ((org-export-custom-protocol-maybe link desc 'groff))
;; Image file.
(imagep (org-groff-link--inline-image link info))
;; import groff files
@@ -1272,10 +1266,9 @@ 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
- (org-element-property :value destination))))))
+ (org-export-get-reference destination info)))))
;; Links pointing to a headline: find destination and build
;; appropriate referencing command.
@@ -1307,9 +1300,9 @@ INFO is a plist holding contextual information. See
(org-element-property :title destination) info))))))
;; Fuzzy link points to a target. Do as above.
(otherwise
- (let ((path (org-export-solidify-link-text path)))
- (if (not desc) (format "\\fI%s\\fP" path)
- (format "%s \\fBat\\fP \\fI%s\\fP" desc path)))))))
+ (let ((ref (org-export-get-reference destination info)))
+ (if (not desc) (format "\\fI%s\\fP" ref)
+ (format "%s \\fBat\\fP \\fI%s\\fP" desc ref)))))))
;; External link with a description part.
((and path desc) (format "%s \\fBat\\fP \\fI%s\\fP" path desc))
;; External link without a description part.
@@ -1463,10 +1456,7 @@ holding contextual information."
"Transcode a RADIO-TARGET object from Org to Groff.
TEXT is the text of the target. INFO is a plist holding
contextual information."
- (format "%s - %s"
- (org-export-solidify-link-text
- (org-element-property :value radio-target))
- text))
+ (format "%s - %s" (org-export-get-reference radio-target info) text))
;;; Section
@@ -1482,7 +1472,7 @@ holding contextual information."
"Transcode a SPECIAL-BLOCK element from Org to Groff.
CONTENTS holds the contents of the block. INFO is a plist
holding contextual information."
- (let ((type (downcase (org-element-property :type special-block))))
+ (let ((type (org-element-property :type special-block)))
(org-groff--wrap-label
special-block
(format "%s\n" contents))))
@@ -1796,8 +1786,7 @@ a communication channel."
"Transcode a TARGET object from Org to Groff.
CONTENTS is nil. INFO is a plist holding contextual
information."
- (format "\\fI%s\\fP"
- (org-export-solidify-link-text (org-element-property :value target))))
+ (format "\\fI%s\\fP" (org-export-get-reference target info)))
;;; Timestamp
diff --git a/contrib/lisp/ox-koma-letter.el b/contrib/lisp/ox-koma-letter.el
index aa75ab8..fde0a0b 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, 2014 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2015 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou AT gmail DOT com>
;; Alan Schmitt <alan.schmitt AT polytechnique DOT org>
@@ -222,7 +222,9 @@ This option can also be set with the OPTIONS keyword, e.g.:
:type 'boolean)
(defcustom org-koma-letter-subject-format t
- "Use the title as the subject of the letter.
+ "Non-nil means include the subject.
+
+Support formatting options.
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
@@ -336,16 +338,6 @@ This option can also be set with the OPTIONS keyword, e.g.:
:group 'org-export-koma-letter
:type 'boolean)
-(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'."
@@ -381,6 +373,9 @@ was not present."
(defvar org-koma-letter-special-contents nil
"Holds special content temporarily.")
+(make-obsolete-variable 'org-koma-letter-use-title
+ 'org-export-with-title
+ "25.1" 'set)
;;; Define Back-End
@@ -390,12 +385,13 @@ was not present."
'((: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)
- (:from-address "FROM_ADDRESS" nil nil newline)
+ (:author-changed-in-buffer-p "AUTHOR" nil nil t)
+ (:from-address "FROM_ADDRESS" nil org-koma-letter-from-address newline)
(:phone-number "PHONE_NUMBER" nil org-koma-letter-phone-number)
(:email "EMAIL" nil (org-koma-letter--get-value org-koma-letter-email) t)
(:to-address "TO_ADDRESS" nil nil newline)
(:place "PLACE" nil org-koma-letter-place)
- (:subject "SUBJECT" nil nil space)
+ (:subject "SUBJECT" nil nil parse)
(:opening "OPENING" nil org-koma-letter-opening)
(:closing "CLOSING" nil org-koma-letter-closing)
(:signature "SIGNATURE" nil org-koma-letter-signature newline)
@@ -415,8 +411,8 @@ was not present."
(:with-phone nil "phone" org-koma-letter-use-phone)
(:with-place nil "place" org-koma-letter-use-place)
(: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)
+ (:with-headline-opening nil nil org-koma-letter-headline-is-opening-maybe)
;; 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'.
@@ -458,8 +454,8 @@ was not present."
(defun org-koma-letter--get-tagged-contents (key)
"Get contents from a headline tagged with KEY.
The contents is stored in `org-koma-letter-special-contents'."
- (cdr (assoc (org-koma-letter--get-value key)
- org-koma-letter-special-contents)))
+ (cdr (assoc-string (org-koma-letter--get-value key)
+ org-koma-letter-special-contents)))
(defun org-koma-letter--get-value (value)
"Turn value into a string whenever possible.
@@ -503,15 +499,14 @@ KEY should be `to' or `from'.
`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 ((option (plist-get info (if (eq key 'to) :to-address :from-address)))
+ (let ((option (org-string-nw-p
+ (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-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))))))
+ (if (plist-get info :special-headings) (or headline option "")
+ (or option headline ""))))))
@@ -559,19 +554,21 @@ 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."
- (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))
+ (let ((special-tag (org-koma-letter--special-tag headline info)))
+ (if (not special-tag)
+ contents
+ (push (cons special-tag contents) org-koma-letter-special-contents)
+ "")))
+
+(defun org-koma-letter--special-tag (headline info)
+ "Non-nil if HEADLINE is a special headline.
+INFO is a plist holding contextual information. Return first
+special tag headline."
+ (let ((special-tags (plist-get info :special-tags)))
+ (catch 'exit
+ (dolist (tag (org-export-get-tags headline info))
+ (let ((tag (assoc-string tag special-tags)))
+ (when tag (throw 'exit tag)))))))
;;;; Template
@@ -617,15 +614,13 @@ holding export options."
(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)
+ (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))
- ;; Document start
- "\\begin{document}\n\n"
- ;; Subject and title
+ ;; Hyperref, document start, and subject and title.
(let ((with-subject (plist-get info :with-subject)))
- (when with-subject
+ (when (and with-subject (plist-get info :with-title))
(concat
(unless (eq with-subject t)
(format "\\KOMAoption{subject}{%s}\n"
@@ -638,16 +633,34 @@ holding export options."
(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*)))
+ (title (if title-as-subject (and subject* title*) title*))
+ (hyperref-template (plist-get info :latex-hyperref-template))
+ (spec (append (list (cons ?t (or title subject "")))
+ (org-latex--format-spec info))))
(concat
- (and subject (format "\\setkomavar{subject}{%s}\n" subject))
- (and title (format "\\setkomavar{title}{%s}\n" title))
+ ;; Hyperref.
+ (format-spec hyperref-template spec)
+ ;; Document start.
+ "\\begin{document}\n\n"
+ ;; Subject and title.
+ (when subject (format "\\setkomavar{subject}{%s}\n" subject))
+ (when 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" (plist-get info :opening))
+ (format "\\opening{%s}\n\n"
+ (org-export-data
+ (or (org-string-nw-p (plist-get info :opening))
+ (when (plist-get info :with-headline-opening)
+ (org-element-map (plist-get info :parse-tree) 'headline
+ (lambda (head)
+ (unless (org-koma-letter--special-tag head info)
+ (org-element-property :title head)))
+ info t))
+ "")
+ info))
;; Letter body.
contents
;; Closing.
diff --git a/contrib/lisp/ox-rss.el b/contrib/lisp/ox-rss.el
index c69a37b..4cdfe0e 100644
--- a/contrib/lisp/ox-rss.el
+++ b/contrib/lisp/ox-rss.el
@@ -1,6 +1,6 @@
;;; ox-rss.el --- RSS 2.0 Back-End for Org Export Engine
-;; Copyright (C) 2013, 2014 Bastien Guerry
+;; Copyright (C) 2013-2015 Bastien Guerry
;; Author: Bastien Guerry <bzg@gnu.org>
;; Keywords: org, wp, blog, feed, rss
@@ -42,6 +42,9 @@
;; PUBDATE property. If `org-rss-use-entry-url-as-guid', it will also add
;; an ID property, later used as the guid for the feed's item.
;;
+;; The top-level headline is used as the title of each RSS item unless
+;; an RSS_TITLE property is set on the headline.
+;;
;; You typically want to use it within a publishing project like this:
;;
;; (add-to-list
@@ -119,7 +122,9 @@ When nil, Org will create ids using `org-icalendar-create-uid'."
(if a (org-rss-export-to-rss t s v)
(org-open-file (org-rss-export-to-rss nil s v)))))))
:options-alist
- '((:with-toc nil nil nil) ;; Never include HTML's toc
+ '((:description "DESCRIPTION" nil nil newline)
+ (:keywords "KEYWORDS" nil nil space)
+ (:with-toc nil nil nil) ;; Never include HTML's toc
(:rss-extension "RSS_EXTENSION" nil org-rss-extension)
(:rss-image-url "RSS_IMAGE_URL" nil org-rss-image-url)
(:rss-categories nil nil org-rss-categories))
@@ -204,11 +209,10 @@ publishing directory.
Return output file name."
(let ((bf (get-file-buffer filename)))
(if bf
- (progn
- (org-icalendar-create-uid filename 'warn-user)
(with-current-buffer bf
+ (org-icalendar-create-uid filename 'warn-user)
(org-rss-add-pubdate-property)
- (write-file filename)))
+ (write-file filename))
(find-file filename)
(org-icalendar-create-uid filename 'warn-user)
(org-rss-add-pubdate-property)
@@ -233,24 +237,21 @@ communication channel."
(hl-home (file-name-as-directory (plist-get info :html-link-home)))
(hl-pdir (plist-get info :publishing-directory))
(hl-perm (org-element-property :RSS_PERMALINK headline))
- (anchor
- (org-export-solidify-link-text
- (or (org-element-property :CUSTOM_ID headline)
- (concat "sec-" (mapconcat 'number-to-string hl-number "-")))))
+ (anchor (org-export-get-reference headline info))
(category (org-rss-plain-text
(or (org-element-property :CATEGORY headline) "") info))
- (pubdate
- (let ((system-time-locale "C"))
- (format-time-string
- "%a, %d %b %Y %H:%M:%S %z"
- (org-time-string-to-time
- (or (org-element-property :PUBDATE headline)
- (error "Missing PUBDATE property"))))))
- (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)))
+ (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 (or (org-element-property :RSS_TITLE headline)
+ (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
@@ -265,18 +266,19 @@ communication channel."
(org-element-property :CUSTOM_ID headline)
publink)
info))))
- (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))))
+ (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."
diff --git a/contrib/lisp/ox-s5.el b/contrib/lisp/ox-s5.el
index 26e83a3..503bfd0 100644
--- a/contrib/lisp/ox-s5.el
+++ b/contrib/lisp/ox-s5.el
@@ -48,7 +48,14 @@
;; in an Org mode buffer. See ox.el and ox-html.el for more details
;; on how this exporter works.
+;; TODOs
+;; ------
+;; The title page is formatted using format-spec. This is error prone
+;; when details are missing and may insert empty tags, like <h2></h2>,
+;; for missing values.
+
(require 'ox-html)
+(eval-when-compile (require 'cl))
(org-export-define-derived-backend 's5 'html
:menu-entry
@@ -173,6 +180,7 @@ or an empty string."
(defcustom org-s5-title-slide-template
"<h1>%t</h1>
+<h2>%s</h2>
<h2>%a</h2>
<h3>%e</h3>
<h4>%d</h4>"
@@ -201,7 +209,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 761e180..2bd47e6 100644
--- a/contrib/lisp/ox-taskjuggler.el
+++ b/contrib/lisp/ox-taskjuggler.el
@@ -64,7 +64,7 @@
;; should end up with something similar to the example by Peter Jones
;; in:
;;
-;; http://www.contextualdevelopment.com/static/artifacts/articles/2008/project-planning/project-planning.org.
+;; http://www.devalot.com/assets/articles/2008/07/project-planning/project-planning.org.
;;
;; Now mark the top node of your tasks with a tag named
;; "taskjuggler_project" (or whatever you customized
@@ -307,7 +307,23 @@ but before any resource and task declarations."
startbuffer startcredit statusnote chargeset charge)
"Valid attributes for Taskjuggler tasks.
If one of these appears as a property for a headline, it will be
-exported with the corresponding task."
+exported with the corresponding task.
+
+Note that multiline properties are not supported, so attributes
+like note or journalentry have to be on a single line."
+ :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
@@ -483,9 +499,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
@@ -587,7 +603,7 @@ doesn't include leading \"depends\"."
(let ((id (org-element-property :TASK_ID dep)))
(and id
(string-match (concat id " +\\({.*?}\\)") dep-str)
- (org-match-string-no-properties 1))))
+ (org-match-string-no-properties 1 dep-str))))
path)
;; Compute number of exclamation marks by looking for the
;; common ancestor between TASK and DEP.
@@ -715,18 +731,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.
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 9205abb..1430c3e 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -1,6 +1,6 @@
-\input texinfo
+\input texinfo @c -*- coding: utf-8 -*-
@c %**start of header
-@setfilename ../../info/org
+@setfilename ../../info/org.info
@settitle The Org Manual
@include org-version.inc
@@ -259,13 +259,13 @@
@copying
This manual is for Org version @value{VERSION}.
-Copyright @copyright{} 2004--2014 Free Software Foundation, Inc.
+Copyright @copyright{} 2004--2015 Free Software Foundation, Inc.
@quotation
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, with the Front-Cover texts being ``A GNU Manual,''
+Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
and with the Back-Cover Texts as in (a) below. A copy of the license
is included in the section entitled ``GNU Free Documentation License.''
@@ -432,7 +432,7 @@ Tags
* Tag inheritance:: Tags use the tree structure of the outline
* Setting tags:: How to assign tags to a headline
-* Tag groups:: Use one tag to search for several tags
+* Tag hierarchy:: Create a hierarchy of tags
* Tag searches:: Searching for combinations of tags
Properties and columns
@@ -462,8 +462,7 @@ Dates and times
* Deadlines and scheduling:: Planning your work
* Clocking work time:: Tracking how long you spend on a task
* Effort estimates:: Planning work effort in advance
-* Relative timer:: Notes with a running timer
-* Countdown timer:: Starting a countdown timer for a task
+* Timers:: Notes with a running timer
Creating timestamps
@@ -581,10 +580,11 @@ Exporting
* HTML export:: Exporting to HTML
* @LaTeX{} and PDF export:: Exporting to @LaTeX{}, and processing to PDF
* Markdown export:: Exporting to Markdown
-* OpenDocument text export:: Exporting to OpenDocument Text
+* 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} or a man page
+* 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
@@ -636,6 +636,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
@@ -821,7 +831,7 @@ 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
+Many users actually run 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
@@ -863,7 +873,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,
@@ -987,6 +1001,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
@@ -1179,7 +1195,7 @@ start with one or more stars, on the left margin@footnote{See the variables
@code{org-special-ctrl-a/e}, @code{org-special-ctrl-k}, and
@code{org-ctrl-k-protect-subtree} to configure special behavior of @kbd{C-a},
@kbd{C-e}, and @kbd{C-k} in headlines.} @footnote{Clocking only works with
-headings indented less then 30 stars.}. For example:
+headings indented less than 30 stars.}. For example:
@example
* Top level headline
@@ -1192,7 +1208,12 @@ headings indented less then 30 stars.}. For example:
* Another top level headline
@end example
-@noindent Some people find the many stars too noisy and would prefer an
+@vindex org-footnote-section
+@noindent Note that a headline named after @code{org-footnote-section},
+which defaults to @samp{Footnotes}, is considered as special. A subtree with
+this headline will be silently ignored by exporting functions.
+
+Some people find the many stars too noisy and would prefer an
outline that has whitespace followed by a single star as headline
starters. @ref{Clean view}, describes a setup to realize this.
@@ -1287,20 +1308,13 @@ 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
@@ -1417,19 +1431,23 @@ See also the option @code{org-goto-interface}.
@orgcmd{M-@key{RET},org-insert-heading}
@vindex org-M-RET-may-split-line
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 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.
+
+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
@@ -1544,18 +1562,14 @@ functionality.
@cindex folding, sparse trees
@cindex occur, command
-@vindex org-show-hierarchy-above
-@vindex org-show-following-heading
-@vindex org-show-siblings
-@vindex org-show-entry-below
+@vindex org-show-context-detail
An important feature of Org mode is the ability to construct @emph{sparse
trees} for selected information in an outline tree, so that the entire
document is folded as much as possible, but the selected information is made
visible along with the headline structure above it@footnote{See also the
-variables @code{org-show-hierarchy-above}, @code{org-show-following-heading},
-@code{org-show-siblings}, and @code{org-show-entry-below} for detailed
-control on how much context is shown around each match.}. Just try it out
-and you will see immediately how it works.
+variable @code{org-show-context-detail} to decide 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 for creating such trees, all these
commands can be accessed through a dispatcher:
@@ -1993,6 +2007,15 @@ location with a prefix argument, offer the same menu as @kbd{C-c C-x f}.
@item C-c C-o @r{or} mouse-1/2
Footnote labels are also links to the corresponding definition/reference, and
you can use the usual commands to follow these links.
+
+@vindex org-edit-footnote-reference
+@kindex C-c '
+@item C-c '
+@item C-c '
+Edit the footnote definition corresponding to the reference at point in a
+seperate window. This may be useful if editing footnotes in a narrowed
+buffer. The window can be closed by pressing @kbd{C-c '}.
+
@end table
@node Orgstruct mode
@@ -2136,6 +2159,9 @@ table. But it is easier just to start typing, like
@orgcmd{C-c C-c,org-table-align}
Re-align the table and don't move to another field.
@c
+@orgcmd{C-c SPC,org-table-blank-field}
+Blank the field at point.
+@c
@orgcmd{<TAB>,org-table-next-field}
Re-align the table, move to the next field. Creates a new row if
necessary.
@@ -2189,8 +2215,10 @@ point is before the first column, you will be prompted for the sorting
column. If there is an active region, the mark specifies the first line
and the sorting column, while point should be in the last line to be
included into the sorting. The command prompts for the sorting type
-(alphabetically, numerically, or by time). When called with a prefix
-argument, alphabetic sorting will be case-sensitive.
+(alphabetically, numerically, or by time). You can sort in normal or
+reverse order. You can also supply your own key extraction and comparison
+functions. When called with a prefix argument, alphabetic sorting will be
+case-sensitive.
@tsubheading{Regions}
@orgcmd{C-c C-x M-w,org-table-copy-region}
@@ -2715,9 +2743,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
@@ -3242,11 +3272,17 @@ functions.
@cindex plot tables using Gnuplot
@cindex #+PLOT
-Org-Plot can produce 2D and 3D graphs of information stored in org tables
-using @file{Gnuplot} @uref{http://www.gnuplot.info/} and @file{gnuplot-mode}
+Org-Plot can produce graphs of information stored in org tables, either
+graphically or in ASCII-art.
+
+@subheading Graphical plots using @file{Gnuplot}
+
+Org-Plot produces 2D and 3D graphs using @file{Gnuplot}
+@uref{http://www.gnuplot.info/} and @file{gnuplot-mode}
@uref{http://xafs.org/BruceRavel/GnuplotMode}. To see this in action, ensure
that you have both Gnuplot and Gnuplot mode installed on your system, then
-call @code{org-plot/gnuplot} on the following table.
+call @kbd{C-c " g} or @kbd{M-x org-plot/gnuplot @key{RET}} on the following
+table.
@example
@group
@@ -3264,8 +3300,8 @@ call @code{org-plot/gnuplot} on the following table.
Notice that Org Plot is smart enough to apply the table's headers as labels.
Further control over the labels, type, content, and appearance of plots can
be exercised through the @code{#+PLOT:} lines preceding a table. See below
-for a complete list of Org-plot options. For more information and examples
-see the Org-plot tutorial at
+for a complete list of Org-plot options. The @code{#+PLOT:} lines are
+optional. For more information and examples see the Org-plot tutorial at
@uref{http://orgmode.org/worg/org-tutorials/org-plot.html}.
@subsubheading Plot Options
@@ -3321,6 +3357,47 @@ may still want to specify the plot type, as that can impact the content of
the data file.
@end table
+@subheading ASCII bar plots
+
+While the cursor is on a column, typing @kbd{C-c " a} or
+@kbd{M-x orgtbl-ascii-plot @key{RET}} create a new column containing an
+ASCII-art bars plot. The plot is implemented through a regular column
+formula. When the source column changes, the bar plot may be updated by
+refreshing the table, for example typing @kbd{C-u C-c *}.
+
+@example
+@group
+| Sede | Max cites | |
+|---------------+-----------+--------------|
+| Chile | 257.72 | WWWWWWWWWWWW |
+| Leeds | 165.77 | WWWWWWWh |
+| Sao Paolo | 71.00 | WWW; |
+| Stockholm | 134.19 | WWWWWW: |
+| Morelia | 257.56 | WWWWWWWWWWWH |
+| Rochefourchat | 0.00 | |
+#+TBLFM: $3='(orgtbl-ascii-draw $2 0.0 257.72 12)
+@end group
+@end example
+
+The formula is an elisp call:
+@lisp
+(orgtbl-ascii-draw COLUMN MIN MAX WIDTH)
+@end lisp
+
+@table @code
+@item COLUMN
+ is a reference to the source column.
+
+@item MIN MAX
+ are the minimal and maximal values displayed. Sources values
+ outside this range are displayed as @samp{too small}
+ or @samp{too large}.
+
+@item WIDTH
+ is the width in characters of the bar-plot. It defaults to @samp{12}.
+
+@end table
+
@node Hyperlinks
@chapter Hyperlinks
@cindex hyperlinks
@@ -3494,10 +3571,14 @@ file:projects.org::some words @r{text search in Org file}@footnote{
The actual behavior of the search will depend on the value of
the option @code{org-link-search-must-match-exact-headline}. If its value
is @code{nil}, then a fuzzy text search will be done. If it is t, then only the
-exact headline will be matched. If the value is @code{'query-to-create},
-then an exact headline will be searched; if it is not found, then the user
-will be queried to create it.}
-file:projects.org::*task title @r{heading search in Org file}
+exact headline will be matched, ignoring spaces and cookies. If the value is
+@code{query-to-create}, then an exact headline will be searched; if it is not
+found, then the user will be queried to create it.}
+file:projects.org::*task title @r{heading search in Org
+file}@footnote{ Headline searches always match the exact headline, ignoring
+spaces and cookies. If the headline is not found and the value of the option
+@code{org-link-search-must-match-exact-headline} is @code{query-to-create},
+then the user will be queried to create it.}
file+sys:/path/to/file @r{open via OS, like double-click}
file+emacs:/path/to/file @r{force opening by Emacs}
docview:papers/last.pdf::NNN @r{open in doc-view mode at page}
@@ -3512,7 +3593,7 @@ gnus:group @r{Gnus group link}
gnus:group#id @r{Gnus article link}
bbdb:R.*Stallman @r{BBDB link (with regexp)}
irc:/irc.com/#emacs/bob @r{IRC link}
-info:org#External links @r{Info node link}
+info:org#External links @r{Info node or index link}
shell:ls *.org @r{A shell command}
elisp:org-agenda @r{Interactive Elisp command}
elisp:(find-file-other-frame "Elisp.org") @r{Elisp form to evaluate}
@@ -4181,11 +4262,10 @@ unique keys across both sets of keywords.}
@cindex #+SEQ_TODO
It can be very useful to use different aspects of the TODO mechanism in
-different files. For file-local settings, you need to add special lines
-to the file which set the keywords and interpretation for that file
-only. For example, to set one of the two examples discussed above, you
-need one of the following lines, starting in column zero anywhere in the
-file:
+different files. For file-local settings, you need to add special lines to
+the file which set the keywords and interpretation for that file only. For
+example, to set one of the two examples discussed above, you need one of the
+following lines anywhere in the file:
@example
#+TODO: TODO FEEDBACK VERIFY | DONE CANCELED
@@ -4251,6 +4331,7 @@ foreground or a background color.
@subsection TODO dependencies
@cindex TODO dependencies
@cindex dependencies, of TODO states
+@cindex TODO dependencies, NOBLOCKING
@vindex org-enforce-todo-dependencies
@cindex property, ORDERED
@@ -4279,6 +4360,16 @@ example:
** TODO c, needs to wait for (a) and (b)
@end example
+You can ensure an entry is never blocked by using the @code{NOBLOCKING}
+property:
+
+@example
+* This entry is never blocked
+ :PROPERTIES:
+ :NOBLOCKING: t
+ :END:
+@end example
+
@table @kbd
@orgcmd{C-c C-x o,org-toggle-ordered-property}
@vindex org-track-ordered-property-with-tag
@@ -4482,6 +4573,10 @@ actual habit with some history:
@example
** TODO Shave
SCHEDULED: <2009-10-17 Sat .+2d/4d>
+ :PROPERTIES:
+ :STYLE: habit
+ :LAST_REPEAT: [2009-10-19 Mon 00:36]
+ :END:
- State "DONE" from "TODO" [2009-10-15 Thu]
- State "DONE" from "TODO" [2009-10-12 Mon]
- State "DONE" from "TODO" [2009-10-10 Sat]
@@ -4492,10 +4587,6 @@ actual habit with some history:
- State "DONE" from "TODO" [2009-09-19 Sat]
- State "DONE" from "TODO" [2009-09-16 Wed]
- State "DONE" from "TODO" [2009-09-12 Sat]
- :PROPERTIES:
- :STYLE: habit
- :LAST_REPEAT: [2009-10-19 Mon 00:36]
- :END:
@end example
What this habit says is: I want to shave at most every 2 days (given by the
@@ -4795,7 +4886,7 @@ You may specify special faces for specific tags using the option
@menu
* Tag inheritance:: Tags use the tree structure of the outline
* Setting tags:: How to assign tags to a headline
-* Tag groups:: Use one tag to search for several tags
+* Tag hierarchy:: Create a hierarchy of tags
* Tag searches:: Searching for combinations of tags
@end menu
@@ -5034,41 +5125,105 @@ 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
-@section Tag groups
+@node Tag hierarchy
+@section Tag hierarchy
@cindex group tags
@cindex tags, groups
-In a set of mutually exclusive tags, the first tag can be defined as a
-@emph{group tag}. When you search for a group tag, it will return matches
-for all members in the group. In an agenda view, filtering by a group tag
-will display headlines tagged with at least one of the members of the
-group. This makes tag searches and filters even more flexible.
+@cindex tag hierarchy
+Tags can be defined in hierarchies. A tag can be defined as a @emph{group
+tag} for a set of other tags. The group tag can be seen as the ``broader
+term'' for its set of tags. Defining multiple @emph{group tags} and nesting
+them creates a tag hierarchy.
+
+One use-case is to create a taxonomy of terms (tags) that can be used to
+classify nodes in a document or set of documents.
+
+When you search for a group tag, it will return matches for all members in
+the group and its subgroup. In an agenda view, filtering by a group tag will
+display or hide headlines tagged with at least one of the members of the
+group or any of its subgroups. This makes tag searches and filters even more
+flexible.
+
+You can set group tags by using brackets and inserting a colon between the
+group tag and its related tags---beware that all whitespaces are mandatory so
+that Org can parse this line correctly:
+
+@example
+#+TAGS: [ GTD : Control Persp ]
+@end example
-You can set group tags by inserting a colon between the group tag and other
-tags---beware that all whitespaces are mandatory so that Org can parse this
-line correctly:
+In this example, @samp{GTD} is the @emph{group tag} and it is related to two
+other tags: @samp{Control}, @samp{Persp}. Defining @samp{Control} and
+@samp{Persp} as group tags creates an hierarchy of tags:
@example
-#+TAGS: @{ @@read : @@read_book @@read_ebook @}
+#+TAGS: [ Control : Context Task ]
+#+TAGS: [ Persp : Vision Goal AOF Project ]
@end example
-In this example, @samp{@@read} is a @emph{group tag} for a set of three
-tags: @samp{@@read}, @samp{@@read_book} and @samp{@@read_ebook}.
+That can conceptually be seen as a hierarchy of tags:
+
+@example
+- GTD
+ - Persp
+ - Vision
+ - Goal
+ - AOF
+ - Project
+ - Control
+ - Context
+ - Task
+@end example
-You can also use the @code{:grouptags} keyword directly when setting
-@code{org-tag-alist}:
+You can use the @code{:startgrouptag}, @code{:grouptags} and
+@code{:endgrouptag} keyword directly when setting @code{org-tag-alist}
+directly:
@lisp
-(setq org-tag-alist '((:startgroup . nil)
- ("@@read" . nil)
- (:grouptags . nil)
- ("@@read_book" . nil)
- ("@@read_ebook" . nil)
- (:endgroup . nil)))
+(setq org-tag-alist '((:startgrouptag)
+ ("GTD")
+ (:grouptags)
+ ("Control")
+ ("Persp")
+ (:endgrouptag)
+ (:startgrouptag)
+ ("Control")
+ (:grouptags)
+ ("Context")
+ ("Task")
+ (:endgrouptag)))
@end lisp
-You cannot nest group tags or use a group tag as a tag in another group.
+The tags in a group can be mutually exclusive if using the same group syntax
+as is used for grouping mutually exclusive tags together; using curly
+brackets.
+
+@example
+#+TAGS: @{ Context : @@Home @@Work @@Call @}
+@end example
+
+When setting @code{org-tag-alist} you can use @code{:startgroup} &
+@code{:endgroup} instead of @code{:startgrouptag} & @code{:endgrouptag} to
+make the tags mutually exclusive.
+
+Furthermore; The members of a @emph{group tag} can also be regular
+expression, creating the possibility of more dynamic and rule-based
+tag-structure. The regular expressions in the group must be marked up within
+@{ @}. Example use, to expand on the example given above:
+
+@example
+#+TAGS: [ Vision : @{V@.+@} ]
+#+TAGS: [ Goal : @{G@.+@} ]
+#+TAGS: [ AOF : @{AOF@.+@} ]
+#+TAGS: [ Project : @{P@.+@} ]
+@end example
+
+Searching for the tag @samp{Project} will now list all tags also including
+regular expression matches for @samp{P@@.+}. Similar for tag-searches on
+@samp{Vision}, @samp{Goal} and @samp{AOF}. This can be good for example if
+tags for a certain project is tagged with a common project-identifier,
+i.e. @samp{P@@2014_OrgTags}.
@kindex C-c C-x q
@vindex org-group-tags
@@ -5144,10 +5299,12 @@ Properties can be conveniently edited and viewed in column view
@cindex drawer, for properties
Properties are key-value pairs. When they are associated with a single entry
-or with a tree they need to be inserted into a special
-drawer (@pxref{Drawers}) with the name @code{PROPERTIES}. Each property
-is specified on a single line, with the key (surrounded by colons)
-first, and the value after it. Here is an example:
+or with a tree they need to be inserted into a special drawer
+(@pxref{Drawers}) with the name @code{PROPERTIES}, which has to be located
+right below a headline, and its planning line (@pxref{Deadlines and
+scheduling}) when applicable. Each property is specified on a single line,
+with the key (surrounded by colons) first, and the value after it. Keys are
+case-insensitives. Here is an example:
@example
* CD collection
@@ -5163,7 +5320,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:}
@@ -5266,49 +5423,43 @@ nearest column format definition.
Special properties provide an alternative access method to Org mode features,
like the TODO state or the priority of an entry, discussed in the previous
-chapters. This interface exists so that you can include these states in a
-column view (@pxref{Column view}), or to use them in queries. The following
-property names are special and (except for @code{:CATEGORY:}) should not be
-used as keys in the properties drawer:
+chapters. This interface exists so that you can include these states in
+a column view (@pxref{Column view}), or to use them in queries. The
+following property names are special and should not be used as keys in the
+properties drawer:
-@cindex property, special, ID
-@cindex property, special, TODO
-@cindex property, special, TAGS
@cindex property, special, ALLTAGS
-@cindex property, special, CATEGORY
-@cindex property, special, PRIORITY
+@cindex property, special, BLOCKED
+@cindex property, special, CLOCKSUM
+@cindex property, special, CLOCKSUM_T
+@cindex property, special, CLOSED
@cindex property, special, DEADLINE
+@cindex property, special, FILE
+@cindex property, special, ITEM
+@cindex property, special, PRIORITY
@cindex property, special, SCHEDULED
-@cindex property, special, CLOSED
+@cindex property, special, TAGS
@cindex property, special, TIMESTAMP
@cindex property, special, TIMESTAMP_IA
-@cindex property, special, CLOCKSUM
-@cindex property, special, CLOCKSUM_T
-@cindex property, special, BLOCKED
-@c guessing that ITEM is needed in this area; also, should this list be sorted?
-@cindex property, special, ITEM
-@cindex property, special, FILE
+@cindex property, special, TODO
@example
-ID @r{A globally unique ID used for synchronization during}
- @r{iCalendar or MobileOrg export.}
-TODO @r{The TODO keyword of the entry.}
-TAGS @r{The tags defined directly in the headline.}
ALLTAGS @r{All tags, including inherited ones.}
-CATEGORY @r{The category of an entry.}
-PRIORITY @r{The priority of the entry, a string with a single letter.}
-DEADLINE @r{The deadline time string, without the angular brackets.}
-SCHEDULED @r{The scheduling timestamp, without the angular brackets.}
-CLOSED @r{When was this entry closed?}
-TIMESTAMP @r{The first keyword-less timestamp in the entry.}
-TIMESTAMP_IA @r{The first inactive timestamp in the entry.}
+BLOCKED @r{"t" if task is currently blocked by children or siblings.}
CLOCKSUM @r{The sum of CLOCK intervals in the subtree. @code{org-clock-sum}}
@r{must be run first to compute the values in the current buffer.}
CLOCKSUM_T @r{The sum of CLOCK intervals in the subtree for today.}
@r{@code{org-clock-sum-today} must be run first to compute the}
@r{values in the current buffer.}
-BLOCKED @r{"t" if task is currently blocked by children or siblings}
-ITEM @r{The headline of the entry.}
+CLOSED @r{When was this entry closed?}
+DEADLINE @r{The deadline time string, without the angular brackets.}
FILE @r{The filename the entry is located in.}
+ITEM @r{The headline of the entry, with stars.}
+PRIORITY @r{The priority of the entry, a string with a single letter.}
+SCHEDULED @r{The scheduling timestamp, without the angular brackets.}
+TAGS @r{The tags defined directly in the headline.}
+TIMESTAMP @r{The first keyword-less timestamp in the entry.}
+TIMESTAMP_IA @r{The first inactive timestamp in the entry.}
+TODO @r{The TODO keyword of the entry.}
@end example
@node Property searches
@@ -5495,7 +5646,7 @@ optional. The individual parts have the following meaning:
@{@@min@} @r{Minimum age (in days/hours/mins/seconds).}
@{@@max@} @r{Maximum age (in days/hours/mins/seconds).}
@{@@mean@} @r{Arithmetic mean of ages (in days/hours/mins/seconds).}
- @{est+@} @r{Add low-high estimates.}
+ @{est+@} @r{Add @samp{low-high} estimates.}
@end example
@noindent
@@ -5504,11 +5655,12 @@ include. Subsequent columns referencing the same property will all display the
same summary information.
The @code{est+} summary type requires further explanation. It is used for
-combining estimates, expressed as low-high ranges. For example, instead
-of estimating a particular task will take 5 days, you might estimate it as
-5--6 days if you're fairly confident you know how much work is required, or
-1--10 days if you don't really know what needs to be done. Both ranges
-average at 5.5 days, but the first represents a more predictable delivery.
+combining estimates, expressed as @samp{low-high} ranges or plain numbers.
+For example, instead of estimating a particular task will take 5 days, you
+might estimate it as 5--6 days if you're fairly confident you know how much
+work is required, or 1--10 days if you don't really know what needs to be
+done. Both ranges average at 5.5 days, but the first represents a more
+predictable delivery.
When combining a set of such estimates, simply adding the lows and highs
produces an unrealistically wide result. Instead, @code{est+} adds the
@@ -5715,8 +5867,7 @@ is used in a much wider sense.
* Deadlines and scheduling:: Planning your work
* Clocking work time:: Tracking how long you spend on a task
* Effort estimates:: Planning work effort in advance
-* Relative timer:: Notes with a running timer
-* Countdown timer:: Starting a countdown timer for a task
+* Timers:: Notes with a running timer
@end menu
@@ -5993,14 +6144,18 @@ from the minibuffer:
@kindex M-S-@key{right}
@kindex M-S-@key{left}
@kindex @key{RET}
+@kindex M-S-@key{down}
+@kindex M-S-@key{up}
+
@example
-@key{RET} @r{Choose date at cursor in calendar.}
-mouse-1 @r{Select date by clicking on it.}
-S-@key{right}/@key{left} @r{One day forward/backward.}
-S-@key{down}/@key{up} @r{One week forward/backward.}
-M-S-@key{right}/@key{left} @r{One month forward/backward.}
-> / < @r{Scroll calendar forward/backward by one month.}
-M-v / C-v @r{Scroll calendar forward/backward by 3 months.}
+@key{RET} @r{Choose date at cursor in calendar.}
+mouse-1 @r{Select date by clicking on it.}
+S-@key{right}/@key{left} @r{One day forward/backward.}
+S-@key{down}/@key{up} @r{One week forward/backward.}
+M-S-@key{right}/@key{left} @r{One month forward/backward.}
+> / < @r{Scroll calendar forward/backward by one month.}
+M-v / C-v @r{Scroll calendar forward/backward by 3 months.}
+M-S-@key{down}/@key{up} @r{Scroll calendar forward/backward by one year.}
@end example
@vindex org-read-date-display-live
@@ -6177,14 +6332,6 @@ keywords @code{logreschedule}, @code{lognotereschedule}, and
@code{nologreschedule}}, a note will be taken when changing an existing
scheduling time.
@c
-@orgcmd{C-c C-x C-k,org-mark-entry-for-agenda-action}
-@kindex k a
-@kindex k s
-Mark the current entry for agenda action. After you have marked the entry
-like this, you can open the agenda or the calendar to find an appropriate
-date. With the cursor on the selected date, press @kbd{k s} or @kbd{k d} to
-schedule the marked item.
-@c
@orgcmd{C-c / d,org-check-deadlines}
@cindex sparse tree, for deadlines
@vindex org-deadline-warning-days
@@ -6533,6 +6680,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,}
@@ -6668,15 +6817,13 @@ with @code{org-clock-in} and two @kbd{C-u C-u} with @code{org-clock-in-last}.
@cindex effort estimates
@cindex property, Effort
-@vindex org-effort-property
If you want to plan your work in a very detailed way, or if you need to
produce offers with quotations of the estimated work effort, you may want to
assign effort estimates to entries. If you are also clocking your work, you
-may later want to compare the planned effort with the actual working time, a
-great way to improve planning estimates. Effort estimates are stored in a
-special property @samp{Effort}@footnote{You may change the property being
-used with the variable @code{org-effort-property}.}. You can set the effort
-for an entry with the following commands:
+may later want to compare the planned effort with the actual working time,
+a great way to improve planning estimates. Effort estimates are stored in
+a special property @code{EFFORT}. You can set the effort for an entry with
+the following commands:
@table @kbd
@orgcmd{C-c C-x e,org-set-effort}
@@ -6726,60 +6873,56 @@ 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
-@section Taking notes with a relative timer
+@node Timers
+@section Taking notes with a timer
@cindex relative timer
+@cindex countdown timer
+@kindex ;
+
+Org provides provides two types of timers. There is a relative timer that
+counts up, which can be useful when taking notes during, for example, a
+meeting or a video viewing. There is also a countdown timer.
+
+The relative and countdown are started with separate commands.
+
+@table @kbd
+@orgcmd{C-c C-x 0,org-timer-start}
+Start or reset the relative timer. By default, the timer is set to 0. When
+called with a @kbd{C-u} prefix, prompt the user for a starting offset. If
+there is a timer string at point, this is taken as the default, providing a
+convenient way to restart taking notes after a break in the process. When
+called with a double prefix argument @kbd{C-u C-u}, change all timer strings
+in the active region by a certain amount. This can be used to fix timer
+strings if the timer was not started at exactly the right moment.
+@orgcmd{C-c C-x ;,org-timer-set-timer}
+Start a countdown timer. The user is prompted for a duration.
+@code{org-timer-default-timer} sets the default countdown value. Giving a
+prefix numeric argument overrides this default value. This command is
+available as @kbd{;} in agenda buffers.
+@end table
-When taking notes during, for example, a meeting or a video viewing, it can
-be useful to have access to times relative to a starting time. Org provides
-such a relative timer and make it easy to create timed notes.
+Once started, relative and countdown timers are controlled with the same
+commands.
@table @kbd
@orgcmd{C-c C-x .,org-timer}
-Insert a relative time into the buffer. The first time you use this, the
-timer will be started. When called with a prefix argument, the timer is
-restarted.
+Insert the value of the current relative or countdown timer into the buffer.
+If no timer is running, the relative timer will be started. When called with
+a prefix argument, the relative timer is restarted.
@orgcmd{C-c C-x -,org-timer-item}
-Insert a description list item with the current relative time. With a prefix
-argument, first reset the timer to 0.
+Insert a description list item with the value of the current relative or
+countdown timer. With a prefix argument, first reset the relative timer to
+0.
@orgcmd{M-@key{RET},org-insert-heading}
Once the timer list is started, you can also use @kbd{M-@key{RET}} to insert
new timer items.
-@c for key sequences with a comma, command name macros fail :(
-@kindex C-c C-x ,
-@item C-c C-x ,
-Pause the timer, or continue it if it is already paused
-(@command{org-timer-pause-or-continue}).
-@c removed the sentence because it is redundant to the following item
-@kindex C-u C-c C-x ,
-@item C-u C-c C-x ,
+@orgcmd{C-c C-x \\,org-timer-pause-or-continue}
+Pause the timer, or continue it if it is already paused.
+@orgcmd{C-c C-x _,org-timer-stop}
Stop the timer. After this, you can only start a new timer, not continue the
old one. This command also removes the timer from the mode line.
-@orgcmd{C-c C-x 0,org-timer-start}
-Reset the timer without inserting anything into the buffer. By default, the
-timer is reset to 0. When called with a @kbd{C-u} prefix, reset the timer to
-specific starting offset. The user is prompted for the offset, with a
-default taken from a timer string at point, if any, So this can be used to
-restart taking notes after a break in the process. When called with a double
-prefix argument @kbd{C-u C-u}, change all timer strings in the active region
-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
-@section Countdown timer
-@cindex Countdown timer
-@kindex C-c C-x ;
-@kindex ;
-
-Calling @code{org-timer-set-timer} from an Org mode buffer runs a countdown
-timer. Use @kbd{;} from agenda buffers, @key{C-c C-x ;} everywhere else.
-
-@code{org-timer-set-timer} prompts the user for a duration and displays a
-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
@chapter Capture - Refile - Archive
@cindex capture
@@ -7148,7 +7291,7 @@ dynamic insertion of content. The templates are expanded in the order given her
@r{You may specify a default value and a completion table with}
@r{%^@{prompt|default|completion2|completion3...@}.}
@r{The arrow keys access a prompt-specific history.}
-%\n @r{Insert the text entered at the nth %^@{@var{prompt}@}, where @code{n} is}
+%\\n @r{Insert the text entered at the nth %^@{@var{prompt}@}, where @code{n} is}
@r{a number, starting from 1.}
%? @r{After completing the template, position cursor here.}
@end smallexample
@@ -7451,6 +7594,10 @@ the archive. To do this, each subtree is checked for open TODO entries.
If none are found, the command offers to move it to the archive
location. If the cursor is @emph{not} on a headline when this command
is invoked, the level 1 trees will be checked.
+@orgkey{C-u C-u C-c C-x C-s}
+As above, but check subtree for timestamps instead of TODO entries. The
+command will offer to archive the subtree if it @emph{does} contain a
+timestamp, and that timestamp is in the past.
@end table
@cindex archive locations
@@ -7462,14 +7609,7 @@ For information and examples on how to specify the file and the heading,
see the documentation string of the variable
@code{org-archive-location}.
-There is also an in-buffer option for setting this variable, for
-example@footnote{For backward compatibility, the following also works:
-If there are several such lines in a file, each specifies the archive
-location for the text below it. The first such line also applies to any
-text before its definition. However, using this method is
-@emph{strongly} deprecated as it is incompatible with the outline
-structure of the document. The correct method for setting multiple
-archive locations in a buffer is using properties.}:
+There is also an in-buffer option for setting this variable, for example:
@cindex #+ARCHIVE
@example
@@ -7737,15 +7877,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
@@ -7846,10 +7988,16 @@ the following segment of an Org file will be processed and entries
will be made in the agenda:
@example
-* Birthdays and similar stuff
-#+CATEGORY: Holiday
+* Holidays
+ :PROPERTIES:
+ :CATEGORY: Holiday
+ :END:
%%(org-calendar-holiday) ; special function for holiday names
-#+CATEGORY: Ann
+
+* Birthdays
+ :PROPERTIES:
+ :CATEGORY: Ann
+ :END:
%%(org-anniversary 1956 5 14)@footnote{@code{org-anniversary} is just like @code{diary-anniversary}, but the argument order is always according to ISO and therefore independent of the value of @code{calendar-date-style}.} Arthur Dent is %d years old
%%(org-anniversary 1869 10 2) Mahatma Gandhi would be %d years old
@end example
@@ -8037,7 +8185,7 @@ braces. For example,
@samp{:work:} and any tag @i{starting} with @samp{boss}.
@cindex group tags, as regular expressions
-Group tags (@pxref{Tag groups}) are expanded as regular expressions. E.g.,
+Group tags (@pxref{Tag hierarchy}) 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
@@ -8052,12 +8200,10 @@ 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 ``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}.}.
+the entry.
-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
+In addition to the @ref{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
@@ -8115,11 +8261,6 @@ property that is numerically smaller than 2, a @samp{:With:} property that is
matched by the regular expression @samp{Sarah\|Denny}, and that are scheduled
on or after October 11, 2008.
-Accessing TODO, LEVEL, and CATEGORY during a search is fast. Accessing any
-other properties will slow down the search. However, once you have paid the
-price by accessing one property, testing additional properties is cheap
-again.
-
You can configure Org mode to use property inheritance during a search, but
beware that this can slow down searches considerably. See @ref{Property
inheritance}, for details.
@@ -8273,16 +8414,9 @@ associated with the item.
@cindex category
@cindex #+CATEGORY
-The category is a broad label assigned to each agenda item. By default,
-the category is simply derived from the file name, but you can also
-specify it with a special line in the buffer, like this@footnote{For
-backward compatibility, the following also works: if there are several
-such lines in a file, each specifies the category for the text below it.
-The first category also applies to any text before the first CATEGORY
-line. However, using this method is @emph{strongly} deprecated as it is
-incompatible with the outline structure of the document. The correct
-method for setting multiple categories in a buffer is using a
-property.}:
+The category is a broad label assigned to each agenda item. By default, the
+category is simply derived from the file name, but you can also specify it
+with a special line in the buffer, like this:
@example
#+CATEGORY: Thesis
@@ -8429,24 +8563,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
@@ -8517,6 +8633,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
@@ -8529,9 +8662,9 @@ Remove all filters in the current agenda view.
@vindex org-agenda-max-tags
Here is a list of options that you can set, either globally, or locally in
-your custom agenda views@pxref{Custom agenda views}.
+your custom agenda views (@pxref{Custom agenda views}).
-@table @var
+@table @code
@item org-agenda-max-entries
Limit the number of entries.
@item org-agenda-max-effort
@@ -8562,8 +8695,8 @@ 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}
@@ -8591,6 +8724,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.
@@ -8970,8 +9107,8 @@ Bulk action: act on all marked entries in the agenda. This will prompt for
another key to select the action to be applied. The prefix arg to @kbd{B}
will be passed through to the @kbd{s} and @kbd{d} commands, to bulk-remove
these special timestamps. By default, marks are removed after the bulk. If
-you want them to persist, set @code{org-agenda-bulk-persistent-marks} to
-@code{t} or hit @kbd{p} at the prompt.
+you want them to persist, set @code{org-agenda-persistent-marks} to @code{t}
+or hit @kbd{p} at the prompt.
@table @kbd
@item *
@@ -9259,8 +9396,7 @@ right spot in @code{org-agenda-custom-commands}. For example:
((org-agenda-sorting-strategy '(priority-down))
(org-agenda-prefix-format " Mixed: ")))
("U" tags-tree "+boss-urgent"
- ((org-show-following-heading nil)
- (org-show-hierarchy-above nil)))
+ ((org-show-context-detail 'minimal)))
("N" search ""
((org-agenda-files '("~org/notes.org"))
(org-agenda-text-search-extra-files nil)))))
@@ -9583,10 +9719,6 @@ 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 with the 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
@@ -9623,8 +9755,8 @@ of contents entirely, by configuring the variable @code{org-export-with-toc},
or on a per-file basis with a line like
@example
-#+OPTIONS: toc:2 (only to two levels in TOC)
-#+OPTIONS: toc:nil (no default TOC at all)
+#+OPTIONS: toc:2 @r{only inlcude two levels in TOC}
+#+OPTIONS: toc:nil @r{no default TOC at all}
@end example
If you would like to move the table of contents to a different location, you
@@ -9633,18 +9765,29 @@ should turn off the default table using @code{org-export-with-toc} or
location(s).
@example
-#+OPTIONS: toc:nil (no default TOC)
+#+OPTIONS: toc:nil @r{no default TOC}
...
-#+TOC: headlines 2 (insert TOC here, with two headline levels)
+#+TOC: headlines 2 @r{insert TOC here, with two headline levels}
+@end example
+
+Moreover, if you append @samp{local} parameter, the table contains only
+entries for the children of the current section@footnote{For @LaTeX{} export,
+this feature requires the @code{titletoc} package. Note that @code{titletoc}
+must be loaded @emph{before} @code{hyperref}. Thus, you may have to
+customize @code{org-latex-default-packages-alist}.}. In this case, any depth
+parameter becomes relative to the current level.
+
+@example
+* Section
+#+TOC: headlines 1 local @r{insert local TOC, with direct children only}
@end example
-Multiple @code{#+TOC: headline} lines are allowed. The same @code{TOC}
-keyword can also generate a list of all tables (resp.@: all listings) with a
-caption in the buffer.
+The same @code{TOC} keyword can also generate a list of all tables (resp.@:
+all listings) with a caption in the document.
@example
-#+TOC: listings (build a list of listings)
-#+TOC: tables (build a list of tables)
+#+TOC: listings @r{build a list of listings}
+#+TOC: tables @r{build a list of tables}
@end example
@cindex property, ALT_TITLE
@@ -9751,13 +9894,18 @@ a horizontal line.
@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.
+@samp{#} and a whitespace are treated as comments and, as such, are not
+exported.
-Also entire subtrees starting with the keyword @samp{COMMENT} will never be
-exported (and included code blocks will not be executed on export).
+Likewise, regions surrounded by @samp{#+BEGIN_COMMENT}
+... @samp{#+END_COMMENT} are not exported.
-Finally, regions surrounded by @samp{#+BEGIN_COMMENT}
-... @samp{#+END_COMMENT} will not be 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@footnote{For a less drastic behavior, consider using a select tag
+(@pxref{Export settings}) instead.}. The command below helps changing the
+comment status of a headline.
@table @kbd
@kindex C-c ;
@@ -9948,28 +10096,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 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
+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}
@@ -9977,6 +10134,23 @@ obvious defaults.
#+INCLUDE: "~/.emacs" :lines "10-" @r{Include lines from 10 to EOF}
@end example
+Finally, you may use a file-link to extract an object as matched by
+@code{org-link-search}@footnote{Note that
+@code{org-link-search-must-match-exact-headline} is locally bound to non-@code{nil}.
+Therefore, @code{org-link-search} only matches headlines and named elements.}
+(@pxref{Search options}). If the @code{:only-contents} property is non-@code{nil},
+only the contents of the requested element will be included, omitting
+properties drawer and planning-line if present. The @code{:lines} keyword
+operates locally with respect to the requested element. Some examples:
+
+@example
+#+INCLUDE: "./paper.org::#theory" :only-contents t
+ @r{Include the body of the heading with the custom id @code{theory}}
+#+INCLUDE: "./paper.org::mytable" @r{Include named element.}
+#+INCLUDE: "./paper.org::*conclusion" :lines 1-20
+ @r{Include the first 20 lines of the headline named conclusion.}
+@end example
+
@table @kbd
@kindex C-c '
@item C-c '
@@ -10000,7 +10174,6 @@ an index} for more information.
-
@node Macro replacement
@section Macro replacement
@cindex macro replacement, during export
@@ -10019,24 +10192,52 @@ Conversely, backslash characters before a comma, and only them, need to be
escaped with another backslash character.}.
These references, called macros, can be inserted anywhere Org markup is
-recognized: paragraphs, headlines, verse and example blocks, tables cells,
-lists and comments. They cannot be used within ordinary keywords (starting
-with @code{#+:}) but are allowed in @code{#+CAPTION}, @code{#+TITLE},
-@code{#+AUTHOR} and @code{#+EMAIL}.
-
-In addition to user-defined macros, a set of already defined macros can be
-used: @code{@{@{@{title@}@}@}}, @code{@{@{@{author@}@}@}}, etc., will
-reference information set by the @code{#+TITLE:}, @code{#+AUTHOR:}, and
-similar lines. Also, @code{@{@{@{time(@var{FORMAT})@}@}@}} and
-@code{@{@{@{modification-time(@var{FORMAT})@}@}@}} refer to current date time
-and to the modification time of the file being exported, respectively.
-@var{FORMAT} should be a format string understood by
-@code{format-time-string}.
+recognized: paragraphs, headlines, verse blocks, tables cells and lists.
+They can also be used in keywords accepting Org syntax, e.g.,
+@code{#+CAPTION}, @code{#+TITLE}, @code{#+AUTHOR}, @code{#+DATE} and some
+others, export back-end specific, ones.
+
+In addition to user-defined macros, a set of predefined macros can be used:
+
+@table @code
+@item @{@{@{title@}@}@}
+@itemx @{@{@{author@}@}@}
+@itemx @{@{@{email@}@}@}
+@cindex title, macro
+@cindex author, macro
+@cindex email, macro
+These macros are replaced with the information available at the time of
+export.
+
+@item @{@{@{date@}@}@}
+@itemx @{@{@{date(@var{FORMAT})@}@}@}
+@itemx @{@{@{time(@var{FORMAT})@}@}@}
+@itemx @{@{@{modification-time(@var{FORMAT})@}@}@}
+@cindex date, macro
+@cindex time, macro
+@cindex modification time, macro
+These macros refer to the @code{#+DATE} keyword, the current date, and the
+modification time of the file being exported, respectively. @var{FORMAT}
+should be a format string understood by @code{format-time-string}. Note that
+@var{FORMAT} is an optional argument to the @code{@{@{@{date@}@}@}} macro,
+and that it will only be used if @code{#+DATE} is a single timestamp.
+
+@item @{@{@{input-file@}@}@}
+@cindex input file, macro
+This macro refers to the filename of the exported file, if any.
+
+@item @{@{@{property(@var{PROPERTY-NAME})@}@}@}
+@itemx @{@{@{property(@var{PROPERTY-NAME},@var{SEARCH-OPTION})@}@}@}
+@cindex property, macro
+This macro returns the value of property @var{PROPERTY-NAME} in current
+entry. If @var{SEARCH-OPTION} (@pxref{Search options}) refers to a remote
+entry, it will be used instead.
+@end table
The surrounding brackets can be made invisible by setting
-@code{org-hide-macro-markers} to @code{t}.
+@code{org-hide-macro-markers} non-@code{nil}.
-Macro expansion takes place during export.
+Macro expansion takes place during the very beginning of the export process.
@node Embedded @LaTeX{}
@@ -10085,7 +10286,7 @@ Angles are written as Greek letters \alpha, \beta and \gamma.
@vindex org-entities
During export, these symbols will be transformed into the native format of
the exporter back-end. Strings like @code{\alpha} will be exported as
-@code{&alpha;} in the HTML output, and as @code{$\alpha$} in the @LaTeX{}
+@code{&alpha;} in the HTML output, and as @code{\(\alpha\)} in the @LaTeX{}
output. Similarly, @code{\nbsp} will become @code{&nbsp;} in HTML and
@code{~} in @LaTeX{}. If you need such a symbol inside a word, terminate it
like this: @samp{\Aacute@{@}stor}.
@@ -10148,32 +10349,30 @@ format sub- and superscripts in a WYSIWYM way.
Going beyond symbols and sub- and superscripts, a full formula language is
needed. Org mode can contain @LaTeX{} math fragments, and it supports ways
to process these for several export back-ends. When exporting to @LaTeX{},
-the code is obviously left as it is. When exporting to HTML, Org can invoke
-the @uref{http://www.mathjax.org, MathJax library} (@pxref{Math formatting in
-HTML export}) to process and display the math@footnote{If you plan to use
-this regularly or on pages with significant page views, you should install
-@file{MathJax} on your own server in order to limit the load of our server.}.
-It can also process the mathematical expressions into images that can be
-displayed in a browser (see @pxref{Previewing @LaTeX{} fragments}).
+the code is left as it is. When exporting to HTML, Org can use either
+@uref{http://www.mathjax.org, MathJax} (@pxref{Math formatting in HTML
+export}) or transcode the math into images (see @pxref{Previewing @LaTeX{}
+fragments}).
@LaTeX{} fragments don't need any special marking at all. The following
snippets will be identified as @LaTeX{} source code:
@itemize @bullet
@item
-Environments of any kind@footnote{When @file{MathJax} is used, only the
-environments recognized by @file{MathJax} will be processed. When
+Environments of any kind@footnote{When MathJax is used, only the
+environments recognized by MathJax will be processed. When
@file{dvipng} program or @file{imagemagick} suite is used to create images,
any @LaTeX{} environment will be handled.}. The only requirement is that the
-@code{\begin} and @code{\end} statements appear on a new line, at the
-beginning of the line or after whitespaces only.
+@code{\begin} statement appears on a new line, at the beginning of the line
+or after whitespaces only.
@item
Text within the usual @LaTeX{} math delimiters. To avoid conflicts with
currency specifications, single @samp{$} characters are only recognized as
math delimiters if the enclosed text contains at most two line breaks, is
directly attached to the @samp{$} characters with no whitespace in between,
-and if the closing @samp{$} is followed by whitespace, punctuation or a dash.
-For the other delimiters, there is no such restriction, so when in doubt, use
-@samp{\(...\)} as inline math delimiters.
+and if the closing @samp{$} is followed by whitespace or punctuation
+(parentheses and quotes are considered to be punctuation in this
+context). For the other delimiters, there is no such restriction, so when in
+doubt, use @samp{\(...\)} as inline math delimiters.
@end itemize
@noindent For example:
@@ -10197,7 +10396,7 @@ either $$ a=+\sqrt@{2@} $$ or \[ a=-\sqrt@{2@} \].
@vindex org-export-with-latex
@LaTeX{} processing can be configured with the variable
@code{org-export-with-latex}. The default setting is @code{t} which means
-@file{MathJax} for HTML, and no processing for ASCII and @LaTeX{} back-ends.
+MathJax for HTML, and no processing for ASCII and @LaTeX{} back-ends.
You can also set this variable on a per-file basis using one of these
lines:
@@ -10324,16 +10523,16 @@ Org syntax includes pre-defined blocks (@pxref{Paragraphs} and @ref{Literal
examples}). It is also possible to create blocks containing raw code
targeted at a specific back-end (e.g., @samp{#+BEGIN_LATEX}).
-Any other block is a @emph{special block}.
+Any other block is a @emph{special block}. Its name is case-sensitive.
-For example, @samp{#+BEGIN_ABSTRACT} and @samp{#+BEGIN_VIDEO} are special
+For example, @samp{#+BEGIN_abstract} and @samp{#+BEGIN_video} are special
blocks. The first one is useful when exporting to @LaTeX{}, the second one
when exporting to HTML5.
Each export back-end decides if they should be exported, and how. When the
block is ignored, its contents are still exported, as if the opening and
closing block lines were not there. For example, when exporting a
-@samp{#+BEGIN_TEST} block, HTML back-end wraps its contents within a
+@samp{#+BEGIN_test} block, HTML back-end wraps its contents within a
@samp{<div name="test">} tag.
Refer to back-end specific documentation for more information.
@@ -10367,10 +10566,11 @@ in the iCalendar format.
* HTML export:: Exporting to HTML
* @LaTeX{} and PDF export:: Exporting to @LaTeX{}, and processing to PDF
* Markdown export:: Exporting to Markdown
-* OpenDocument text export:: Exporting to OpenDocument Text
+* 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} or a man page
+* 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
@end menu
@@ -10389,7 +10589,6 @@ minibuffer. From there one can still switch back to regular menu by pressing
@key{?}.} from which it is possible to select an export format and to toggle
export options.
-@c @quotation
@table @asis
@orgcmd{C-c C-e,org-export-dispatch}
@@ -10398,7 +10597,6 @@ prefix argument, repeat the last export command on the current buffer while
preserving toggled options. If the current buffer hasn't changed and subtree
export was activated, the command will affect that same subtree.
@end table
-@c @end quotation
Normally the entire buffer is exported, but if there is an active region
only that part of the buffer will be exported.
@@ -10412,10 +10610,10 @@ export dispatcher with the following key combinations:
Toggle asynchronous export. Asynchronous export uses an external Emacs
process that is configured with a specified initialization file.
-While exporting asynchronously, the output is not displayed. It is stored in
-a list called ``the export stack'', and can be viewed from there. The stack
-can be reached by calling the dispatcher with a double @kbd{C-u} prefix
-argument, or with @kbd{&} key from the dispatcher.
+While exporting asynchronously, the output is not displayed, but stored in
+a place called ``the export stack''. This stack can be displayed by calling
+the dispatcher with a double @kbd{C-u} prefix argument, or with @kbd{&} key
+from the dispatcher menu.
@vindex org-export-in-background
To make this behavior the default, customize the variable
@@ -10436,14 +10634,8 @@ You can change the default state of this option by setting
@item C-v
Toggle visible-only export. Only export the text that is currently
visible, i.e. not hidden by outline visibility in the buffer.
-
@end table
-@vindex org-export-copy-to-kill-ring
-With the exception of asynchronous export, a successful export process writes
-its output to the kill-ring. You can configure this behavior by altering the
-option @code{org-export-copy-to-kill-ring}.
-
@node Export back-ends
@section Export back-ends
@cindex Export, back-ends
@@ -10517,23 +10709,11 @@ A date or a time-stamp@footnote{The variable
@code{org-export-date-timestamp-format} defines how this time-stamp will be
exported.}.
-@item DESCRIPTION
-@cindex #+DESCRIPTION
-The document description. Back-ends handle it as they see fit (e.g., for the
-XHTML meta tag), if at all. You can use several such keywords for long
-descriptions.
-
@item EMAIL
@cindex #+EMAIL
@vindex user-mail-address
The email address (@code{user-mail-address}).
-@item KEYWORDS
-@cindex #+KEYWORDS
-The keywords defining the contents of the document. Back-ends handle it as
-they see fit (e.g., for the XHTML meta tag), if at all. You can use several
-such keywords if the list is long.
-
@item LANGUAGE
@cindex #+LANGUAGE
@vindex org-export-default-language
@@ -10562,8 +10742,7 @@ be executed during export even though the subtree is not exported.
@item TITLE
@cindex #+TITLE
-The title to be shown (otherwise derived from buffer's name). You can use
-several such keywords for long titles.
+The title to be shown. You can use several such keywords for long titles.
@end table
The @code{#+OPTIONS} keyword is a compact@footnote{If you want to configure
@@ -10593,7 +10772,7 @@ Toggle fixed-width sections
Toggle inclusion of any time/date active/inactive stamps
(@code{org-export-with-timestamps}).
-@item :
+@item \n:
@vindex org-export-preserve-breaks
Toggle line-break-preservation (@code{org-export-preserve-breaks}).
@@ -10620,14 +10799,18 @@ Toggle inclusion of CLOCK keywords (@code{org-export-with-clocks}).
@item creator:
@vindex org-export-with-creator
-Configure inclusion of creator info into exported file. It may be set to
-@code{comment} (@code{org-export-with-creator}).
+Toggle inclusion of creator info into exported file
+(@code{org-export-with-creator}).
@item d:
@vindex org-export-with-drawers
Toggle inclusion of drawers, or list drawers to include
(@code{org-export-with-drawers}).
+@item date:
+@vindex org-export-with-date
+Toggle inclusion of a date into exported file (@code{org-export-with-date}).
+
@item e:
@vindex org-export-with-entities
Toggle inclusion of entities (@code{org-export-with-entities}).
@@ -10653,9 +10836,12 @@ Toggle inclusion of inlinetasks (@code{org-export-with-inlinetasks}).
@item num:
@vindex org-export-with-section-numbers
+@cindex property, UNNUMBERED
Toggle section-numbers (@code{org-export-with-section-numbers}). It can also
be set to a number @samp{n}, so only headlines at that level or above will be
-numbered.
+numbered. Finally, irrespective of the level of a specific headline, the
+numbering of it can be disabled by setting the @code{UNNUMBERED} property to
+non-@code{nil}. This also affects subheadings.
@item p:
@vindex org-export-with-planning
@@ -10698,6 +10884,10 @@ Configure export of @LaTeX{} fragments and environments. It may be set to
Toggle inclusion of the creation time into exported file
(@code{org-export-time-stamp-file}).
+@item title:
+@vindex org-export-with-title
+Toggle inclusion of title (@code{org-export-with-title}).
+
@item toc:
@vindex org-export-with-toc
Toggle inclusion of the table of contents, or set the level limit
@@ -10711,18 +10901,15 @@ Toggle inclusion of TODO keywords into exported text
@item |:
@vindex org-export-with-tables
Toggle inclusion of tables (@code{org-export-with-tables}).
+
@end table
-@cindex property, EXPORT_FILE_NAME
When exporting only a subtree, each of the previous keywords@footnote{With
the exception of @samp{SETUPFILE}.} can be overridden locally by special node
properties. These begin with @samp{EXPORT_}, followed by the name of the
keyword they supplant. For example, @samp{DATE} and @samp{OPTIONS} keywords
become, respectively, @samp{EXPORT_DATE} and @samp{EXPORT_OPTIONS}
-properties. Subtree export also supports the self-explicit
-@samp{EXPORT_FILE_NAME} property@footnote{There is no buffer-wide equivalent
-for this property. The file name in this case is derived from the file
-associated to the buffer, if possible, or asked to the user otherwise.}.
+properties.
@cindex #+BIND
@vindex org-export-allow-bind-keywords
@@ -10731,6 +10918,13 @@ can become buffer-local during export by using the BIND keyword. Its syntax
is @samp{#+BIND: variable value}. This is particularly useful for in-buffer
settings that cannot be changed using specific keywords.
+@cindex property, EXPORT_FILE_NAME
+The name of the output file to be generated is taken from the file associated
+to the buffer, when possible, or asked to you otherwise. For subtree export,
+you can also set @code{EXPORT_FILE_NAME} property. In all cases, only the
+base name of the file is retained, and a back-end specific extension is
+added.
+
@node ASCII/Latin-1/UTF-8 export
@section ASCII/Latin-1/UTF-8 export
@cindex ASCII export
@@ -10741,6 +10935,10 @@ ASCII export produces a simple and very readable version of an Org mode
file, containing only plain ASCII@. Latin-1 and UTF-8 export augment the file
with special characters and symbols available in these encodings.
+@vindex org-ascii-text-width
+Upon exporting, text is filled and justified, when appropriate, according the
+text width set in @code{org-ascii-text-width}.
+
@vindex org-ascii-links-to-notes
Links are exported in a footnote-like style, with the descriptive part in the
text and the link in a note before the next heading. See the variable
@@ -10758,6 +10956,17 @@ When the original file is @file{myfile.txt}, the resulting file becomes
Export to a temporary buffer. Do not create a file.
@end table
+@subheading ASCII specific export settings
+
+ASCII export introduces a single of keywords, similar to the general options
+settings described in @ref{Export settings}.
+
+@table @samp
+@item SUBTITLE
+@cindex #+SUBTITLE (ASCII)
+The document subtitle.
+@end table
+
@subheading Header and sectioning structure
In the exported version, the first three outline levels become headlines,
@@ -10795,6 +11004,25 @@ specified using an @code{ATTR_ASCII} line, directly preceding the rule.
-----
@end example
+@subheading ASCII special blocks
+@cindex special blocks, in ASCII export
+@cindex #+BEGIN_JUSTIFYLEFT
+@cindex #+BEGIN_JUSTIFYRIGHT
+
+In addition to @code{#+BEGIN_CENTER} blocks (@pxref{Paragraphs}), it is
+possible to justify contents to the left or the right of the page with the
+following dedicated blocks.
+
+@example
+#+BEGIN_JUSTIFYLEFT
+It's just a jump to the left...
+#+END_JUSTIFYLEFT
+
+#+BEGIN_JUSTIFYRIGHT
+...and then a step to the right.
+#+END_JUSTIFYRIGHT
+@end example
+
@node Beamer export
@section Beamer export
@cindex Beamer export
@@ -10803,7 +11031,17 @@ The @LaTeX{} class @emph{Beamer} allows production of high quality
presentations using @LaTeX{} and pdf processing. Org mode has special
support for turning an Org mode file or tree into a Beamer presentation.
-@subheading Beamer export commands
+@menu
+* Beamer export commands:: How to export Beamer documents.
+* Beamer specific export settings:: Export settings for Beamer export.
+* Sectioning Frames and Blocks in Beamer:: Blocks and sections in Beamer.
+* Beamer specific syntax:: Syntax specific to Beamer.
+* Editing support:: Helper functions for Org Beamer export.
+* A Beamer Example:: An complete Beamer example.
+@end menu
+
+@node Beamer export commands
+@subsection Beamer export commands
@table @kbd
@orgcmd{C-c C-e l b,org-beamer-export-to-latex}
@@ -10818,7 +11056,66 @@ Export as @LaTeX{} and then process to PDF.
Export as @LaTeX{} and then process to PDF, then open the resulting PDF file.
@end table
-@subheading Sectioning, Frames and Blocks
+@node Beamer specific export settings
+@subsection Beamer specific export settings
+
+Beamer export introduces a number of keywords, similar to the general options
+settings described in @ref{Export settings}.
+
+@table @samp
+@item BEAMER_THEME
+@cindex #+BEAMER_THEME
+@vindex org-beamer-theme
+The Beamer theme (@code{org-beamer-theme}). Options can be specified via
+brackets, for example:
+@smallexample
+#+BEAMER_THEME: Rochester [height=20pt]
+@end smallexample
+
+@item BEAMER_FONT_THEME
+@cindex #+BEAMER_FONT_THEME
+The Beamer font theme.
+
+@item BEAMER_INNER_THEME
+@cindex #+BEAMER_INNER_THEME
+The Beamer inner theme.
+
+@item BEAMER_OUTER_THEME
+@cindex #+BEAMER_OUTER_THEME
+The Beamer outer theme.
+
+@item BEAMER_HEADER
+@cindex #+BEAMER_HEADER
+Arbitrary lines inserted into the preamble, just before the @samp{hyperref}
+settings.
+
+@item DESCRIPTION
+@cindex #+DESCRIPTION (Beamer)
+The document description. By default these are inserted as metadata using
+@samp{hyperref}. Document metadata can be configured via
+@code{org-latex-hyperref-template}. Description can also be typeset as part
+of the front matter via @code{org-latex-title-command}. You can use several
+@code{#+DESCRIPTION} keywords if the description is is long.
+
+@item KEYWORDS
+@cindex #+KEYWORDS (Beamer)
+The keywords defining the contents of the document. By default these are
+inserted as metadata using @samp{hyperref}. Document metadata can be
+configured via @code{org-latex-hyperref-template}. Description can also be
+typeset as part of the front matter via @code{org-latex-title-command}. You
+can use several @code{#+KEYWORDS} if the description is is long.
+
+@item SUBTITLE
+@cindex #+SUBTITLE (Beamer)
+@vindex org-beamer-subtitle-format
+The document subtitle. This is typeset using the format string
+@code{org-beamer-subtitle-format}. It can also access via
+@code{org-latex-hyperref-template} or typeset as part of the front
+matter via @code{org-latex-title-command}.
+@end table
+
+@node Sectioning Frames and Blocks in Beamer
+@subsection Sectioning, Frames and Blocks in Beamer
Any tree with not-too-deep level nesting should in principle be exportable as
a Beamer presentation. Headlines fall into three categories: sectioning
@@ -10884,30 +11181,13 @@ Although, it can also be explicitly created, with a special @code{columns}
value for @code{BEAMER_ENV} property (if it needs to be set up with some
specific options, for example).
-@subheading Beamer specific syntax
+@node Beamer specific syntax
+@subsection Beamer specific syntax
-Beamer back-end is an extension of @LaTeX{} back-end. As such, all @LaTeX{}
+The Beamer back-end is an extension of the @LaTeX{} back-end. As such, all @LaTeX{}
specific syntax (e.g., @samp{#+LATEX:} or @samp{#+ATTR_LATEX:}) is
recognized. See @ref{@LaTeX{} and PDF export} for more information.
-@cindex #+BEAMER_THEME
-@cindex #+BEAMER_COLOR_THEME
-@cindex #+BEAMER_FONT_THEME
-@cindex #+BEAMER_INNER_THEME
-@cindex #+BEAMER_OUTER_THEME
-Beamer export introduces a number of keywords to insert code in the
-document's header. Four control appearance of the presentation:
-@code{#+BEAMER_THEME}, @code{#+BEAMER_COLOR_THEME},
-@code{#+BEAMER_FONT_THEME}, @code{#+BEAMER_INNER_THEME} and
-@code{#+BEAMER_OUTER_THEME}. All of them accept optional arguments
-within square brackets. The last one, @code{#+BEAMER_HEADER}, is more
-generic and allows you to append any line of code in the header.
-
-@example
-#+BEAMER_THEME: Rochester [height=20pt]
-#+BEAMER_COLOR_THEME: spruce
-@end example
-
Table of contents generated from @code{toc:t} @code{OPTION} keyword are
wrapped within a @code{frame} environment. Those generated from a @code{TOC}
keyword (@pxref{Table of contents}) are not. In that case, it is also
@@ -10953,7 +11233,8 @@ the last one inserts optional arguments in current list environment.
- item 2
@end example
-@subheading Editing support
+@node Editing support
+@subsection Editing support
You can turn on a special minor mode @code{org-beamer-mode} for faster
editing with:
@@ -10968,19 +11249,15 @@ In @code{org-beamer-mode}, this key offers fast selection of a Beamer
environment or the @code{BEAMER_COL} property.
@end table
-Also, a template for useful in-buffer settings or properties can be inserted
-into the buffer with @kbd{M-x org-beamer-insert-options-template}. Among
-other things, this will install a column view format which is very handy for
-editing special properties used by Beamer.
-
-@subheading An example
+@node A Beamer Example
+@subsection A Beamer example
Here is a simple example Org document that is intended for Beamer export.
-@smallexample
+@example
#+TITLE: Example Presentation
#+AUTHOR: Carsten Dominik
-#+OPTIONS: H:2
+#+OPTIONS: H:2 toc:t num:t
#+LATEX_CLASS: beamer
#+LATEX_CLASS_OPTIONS: [presentation]
#+BEAMER_THEME: Madrid
@@ -10989,27 +11266,27 @@ Here is a simple example Org document that is intended for Beamer export.
* This is the first structural section
** Frame 1
-*** Thanks to Eric Fraga :B_block:BMCOL:
+*** Thanks to Eric Fraga :B_block:
:PROPERTIES:
:BEAMER_COL: 0.48
:BEAMER_ENV: block
:END:
for the first viable Beamer setup in Org
-*** Thanks to everyone else :B_block:BMCOL:
+*** Thanks to everyone else :B_block:
:PROPERTIES:
:BEAMER_COL: 0.48
:BEAMER_ACT: <2->
:BEAMER_ENV: block
:END:
for contributing to the discussion
-**** This will be formatted as a beamer note :B_note:
+**** This will be formatted as a beamer note :B_note:
:PROPERTIES:
:BEAMER_env: note
:END:
** Frame 2 (where we will not use columns)
*** Request
Please test this stuff!
-@end smallexample
+@end example
@node HTML export
@section HTML export
@@ -11021,6 +11298,7 @@ language, but with additional support for tables.
@menu
* HTML Export commands:: How to invoke HTML export
+* HTML Specific export settings:: Export settings for HTML export.
* HTML doctypes:: Org can export to various (X)HTML flavors
* HTML preamble and postamble:: How to insert a preamble and a postamble
* Quoting HTML tags:: Using direct HTML in Org mode
@@ -11033,6 +11311,7 @@ language, but with additional support for tables.
* JavaScript support:: Info and Folding in a web browser
@end menu
+
@node HTML Export commands
@subsection HTML export commands
@@ -11061,6 +11340,76 @@ Export to a temporary buffer. Do not create a file.
@c @noindent
@c creates two levels of headings and does the rest as items.
+@node HTML Specific export settings
+@subsection HTML Specific export settings
+HTML export introduces a number of keywords, similar to the general options
+settings described in @ref{Export settings}.
+
+@table @samp
+@item DESCRIPTION
+@cindex #+DESCRIPTION (HTML)
+The document description. This description is inserted as a HTML meta tag.
+You can use several such keywords if the list is long.
+
+@item HTML_DOCTYPE
+@cindex #+HTML_DOCTYPE
+@vindex org-html-doctype
+The document type, e.g. HTML5, (@code{org-html-doctype}).
+
+@item HTML_CONTAINER
+@cindex #+HTML_CONTAINER
+@vindex org-html-container-element
+The container, e.g. @samp{div}, used to wrap sections and elements
+(@code{org-html-container-element}).
+
+@item HTML_LINK_HOME
+@cindex #+HTML_LINK_HOME
+@vindex org-html-link-home
+The home link URL (@code{org-html-link-home}).
+
+@item HTML_LINK_UP
+@cindex #+HTML_LINK_UP
+@vindex org-html-link-up
+The up link URL (@code{org-html-link-up}).
+
+@item HTML_MATHJAX
+@cindex #+HTML_MATHJAX
+@vindex org-html-mathjax-options
+Options for the MathJax (@code{org-html-mathjax-options}). MathJax is used
+to typeset @LaTeX{} math in HTML documents. @ref{Math formatting in HTML
+export} contains an example.
+
+@item HTML_HEAD
+@cindex #+HTML_HEAD
+@vindex org-html-head
+Arbitrary lines appended to the end of the head of the document
+(@code{org-html-head}).
+
+@item HTML_HEAD_EXTRA
+@cindex #+HTML_HEAD_EXTRA
+@vindex org-html-head-extra
+Arbitrary lines appended to the end of the header of the document
+(@code{org-html-head-extra}).
+
+@item KEYWORDS
+@cindex #+KEYWORDS (HTML)
+The keywords defining the contents of the document. This description is
+inserted as a HTML meta tag. You can use several such keywords if the list
+is long.
+
+@item LATEX_HEADER
+@cindex #+LATEX_HEADER (HTML)
+Arbitrary lines appended to the preamble used when transcoding @LaTeX{}
+fragments to images. See @ref{Math formatting in HTML export} for details.
+
+@item SUBTITLE
+@cindex #+SUBTILE (HTML)
+The document subtitle. The formatting depends on whether HTML5 in used
+and on the @samp{subtitle} CSS class.
+@end table
+
+These keywords are treated in details in the following sections.
+
@node HTML doctypes
@subsection HTML doctypes
@vindex org-html-doctype
@@ -11146,7 +11495,7 @@ Becomes:
Special blocks that do not correspond to HTML5 elements (see
@code{org-html-html5-elements}) will revert to the usual behavior, i.e.,
-@code{#+BEGIN_LEDERHOSEN} will still export to @samp{<div class="lederhosen">}.
+@code{#+BEGIN_lederhosen} will still export to @samp{<div class="lederhosen">}.
Headlines cannot appear within special blocks. To wrap a headline and its
contents in e.g., @samp{<section>} or @samp{<article>} tags, set the
@@ -11211,15 +11560,17 @@ All lines between these markers are exported literally
@cindex links, in HTML export
@cindex internal links, in HTML export
@cindex external links, in HTML export
+@vindex org-html-link-org-files-as-html
Internal links (@pxref{Internal links}) will continue to work in HTML@. This
includes automatic links created by radio targets (@pxref{Radio
targets}). Links to external files will still work if the target file is on
the same @i{relative} path as the published Org file. Links to other
@file{.org} files will be translated into HTML links under the assumption
that an HTML version also exists of the linked file, at the same relative
-path. @samp{id:} links can then be used to jump to specific entries across
-files. For information related to linking files while publishing them to a
-publishing directory see @ref{Publishing links}.
+path; setting @code{org-html-link-org-files-as-html} to @code{nil} disables
+this translation. @samp{id:} links can then be used to jump to specific
+entries across files. For information related to linking files while
+publishing them to a publishing directory see @ref{Publishing links}.
If you want to specify attributes for links, you can do so using a special
@code{#+ATTR_HTML} line to define attributes that will be added to the
@@ -11256,11 +11607,11 @@ Below is a list of options for customizing tables HTML export.
@table @code
@vindex org-html-table-align-individual-fields
@item org-html-table-align-individual-fields
-Non-nil means attach style attributes for alignment to each table field.
+Non-@code{nil} means attach style attributes for alignment to each table field.
@vindex org-html-table-caption-above
@item org-html-table-caption-above
-When non-nil, place caption string at the beginning of the table.
+When non-@code{nil}, place caption string at the beginning of the table.
@vindex org-html-table-data-tags
@item org-html-table-data-tags
@@ -11280,7 +11631,7 @@ The opening and ending tags for table rows.
@vindex org-html-table-use-header-tags-for-first-column
@item org-html-table-use-header-tags-for-first-column
-Non-nil means format column one in tables with header tags.
+Non-@code{nil} means format column one in tables with header tags.
@end table
@node Images in HTML export
@@ -11327,25 +11678,23 @@ You could use @code{http} addresses just as well.
@cindex imagemagick
@LaTeX{} math snippets (@pxref{@LaTeX{} fragments}) can be displayed in two
-different ways on HTML pages. The default is to use the
-@uref{http://www.mathjax.org, MathJax system} which should work out of the
-box with Org mode installation because @uref{http://orgmode.org} serves
-@file{MathJax} for Org mode users for small applications and for testing
-purposes. @b{If you plan to use this regularly or on pages with significant
-page views, you should install@footnote{Installation instructions can be
-found on the MathJax website, see
-@uref{http://www.mathjax.org/resources/docs/?installation.html}.} MathJax on
-your own server in order to limit the load of our server.} To configure
-@file{MathJax}, use the variable @code{org-html-mathjax-options} or
-insert something like the following into the buffer:
-
-@example
-#+HTML_MATHJAX: align:"left" mathml:t path:"/MathJax/MathJax.js"
-@end example
+different ways on HTML pages. The default is to use
+@uref{http://www.mathjax.org, MathJax} which should work out of the box with
+Org@footnote{By default Org loads MathJax from
+@uref{http://docs.mathjax.org/en/latest/start.html#using-the-mathjax-content-delivery-network-cdn,
+MathJax.org}. A link to the terms of service of the MathJax CDN can be found
+in the docstring of @code{org-html-mathjax-options}.}. Some MathJax display
+options can be configured via @code{org-html-mathjax-options}, or in the
+buffer. For example, with the following settings,
+@smallexample
+#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Euler
+@end smallexample
+equation labels will be displayed on the left marign and equations will be
+five ems from the left margin.
-@noindent See the docstring of the variable
-@code{org-html-mathjax-options} for the meaning of the parameters in
-this line.
+@noindent See the docstring of
+@code{org-html-mathjax-options} for all supported variables. The MathJax
+template can be configure via @code{org-html-mathjax-template}.
If you prefer, you can also request that @LaTeX{} fragments are processed
into small images that will be inserted into the browser page. Before the
@@ -11405,6 +11754,7 @@ p.author @r{author information, including email}
p.date @r{publishing date}
p.creator @r{creator info, about org mode version}
.title @r{document title}
+.subtitle @r{document subtitle}
.todo @r{TODO keywords, all not-done states}
.done @r{the DONE keywords, all states that count as done}
.WAITING @r{each TODO keyword also uses a class named after itself}
@@ -11539,14 +11889,13 @@ pages, configure the variable @code{org-html-use-infojs}.
@LaTeX{} export can produce an arbitrarily complex LaTeX document of any
standard or custom document class. With further processing@footnote{The
default @LaTeX{} output is designed for processing with @code{pdftex} or
-@LaTeX{}. It includes packages that are not compatible with @code{xetex} and
-possibly @code{luatex}. The @LaTeX{} exporter can be configured to support
-alternative TeX engines, see the options
-@code{org-latex-default-packages-alist} and @code{org-latex-packages-alist}.},
-which the @LaTeX{} exporter is able to control, this back-end is able to
-produce PDF output. Because the @LaTeX{} exporter can be configured to use
-the @code{hyperref} package, the default setup produces fully-linked PDF
-output.
+@code{latex}. The @LaTeX{} exporter can be configured to support alternative
+TeX engines, see see @code{org-latex-pdf-process}, and alternative packages,
+see @code{org-latex-default-packages-alist} and
+@code{org-latex-packages-alist}.}, which the @LaTeX{} exporter is able to
+control, this back-end is able to produce PDF output. Because the @LaTeX{}
+exporter can be configured to use the @code{hyperref} package, the default
+setup produces fully-linked PDF output.
As in @LaTeX{}, blank lines are meaningful for this back-end: a paragraph
will not be started if two contiguous syntactical elements are not separated
@@ -11558,6 +11907,7 @@ description.
@menu
* @LaTeX{} export commands:: How to export to LaTeX and PDF
+* @LaTeX{} specific export settings:: Export settings for @LaTeX{}
* Header and sectioning:: Setting up the export file structure
* Quoting @LaTeX{} code:: Incorporating literal @LaTeX{} code
* @LaTeX{} specific attributes:: Controlling @LaTeX{} output
@@ -11579,6 +11929,67 @@ Export as @LaTeX{} and then process to PDF.
Export as @LaTeX{} and then process to PDF, then open the resulting PDF file.
@end table
+@node @LaTeX{} specific export settings
+@subsection @LaTeX{} specific export settings
+The @LaTeX{} exporter introduces a number of keywords, similar to the general
+options settings described in @ref{Export settings}.
+
+@table @samp
+@item DESCRIPTION
+@cindex #+DESCRIPTION (@LaTeX{})
+The document description. By default these are inserted as metadata using
+@samp{hyperref}. Document metadata can be configured via
+@code{org-latex-hyperref-template}. Description can also be typeset as part
+of the front matter via @code{org-latex-title-command}. You can use several
+@code{#+DESCRIPTION} keywords if the description is is long.
+
+@item LATEX_CLASS
+@cindex #+LATEX_CLASS
+@vindex org-latex-default-class
+@vindex org-latex-classes
+The predefined preamble and headline level mapping to use
+(@code{org-latex-default-class}). Must be an element in
+@code{org-latex-classes}.
+
+@item LATEX_CLASS_OPTIONS
+@cindex #+LATEX_CLASS_OPTIONS
+Options given to the @LaTeX{} document class.
+
+@item LATEX_HEADER
+@cindex #+LATEX_HEADER
+@vindex org-latex-classes
+Arbitrary lines added to the preamble of the document, before the
+@samp{hyperref} settings. The location can be controlled via
+@code{org-latex-classes}.
+
+@item LATEX_HEADER_EXTRA
+@cindex #+LATEX_HEADER_EXTRA
+@vindex org-latex-classes
+Arbitrary lines added to the preamble of the document, before the
+@samp{hyperref} settings. The location can be controlled via
+@code{org-latex-classes}.
+
+@item KEYWORDS
+@cindex #+KEYWORDS (@LaTeX{})
+The keywords defining the contents of the document. By default these are
+inserted as metadata using @samp{hyperref}. Document metadata can be
+configured via @code{org-latex-hyperref-template}. Description can also be
+typeset as part of the front matter via @code{org-latex-title-command}. You
+can use several @code{#+KEYWORDS} if the description is is long.
+
+@item SUBTITLE
+@cindex #+SUBTITLE (@LaTeX{})
+@vindex org-latex-subtitle-separate
+@vindex org-latex-subtitle-format
+The document subtitle. This is typeset according to
+@code{org-latex-subtitle-format}. If @code{org-latex-subtitle-separate}
+is non-@code{nil} it is typed as part of the @samp{\title}-macro. It
+can also access via @code{org-latex-hyperref-template} or typeset as
+part of the front matter via @code{org-latex-title-command}.
+@end table
+
+These keywords are treated in details in the following sections.
+
@node Header and sectioning
@subsection Header and sectioning structure
@cindex @LaTeX{} class
@@ -11696,10 +12107,13 @@ task, you can use @code{:caption} attribute instead. Its value should be raw
@LaTeX{} code. It has precedence over @code{#+CAPTION}.
@item :float
@itemx :placement
-Float environment for the table. Possible values are @code{sidewaystable},
+The @code{:float} specifies the float environment for the table. Possible
+values are @code{sideways}@footnote{Formerly, the value was
+@code{sidewaystable}. This is deprecated since Org 8.3.},
@code{multicolumn}, @code{t} and @code{nil}. When unspecified, a table with
-a caption will have a @code{table} environment. Moreover, @code{:placement}
-attribute can specify the positioning of the float.
+a caption will have a @code{table} environment. Moreover, the
+@code{:placement} attribute can specify the positioning of the float. Note:
+@code{:placement} is ignored for @code{:float sideways} tables.
@item :align
@itemx :font
@itemx :width
@@ -11802,6 +12216,11 @@ environment.
@code{wrap}: if you would like to let text flow around the image. It will
make the figure occupy the left half of the page.
@item
+@code{sideways}: if you would like the image to appear alone on a separate
+page rotated ninety degrees using the @code{sidewaysfigure}
+environment. Setting this @code{:float} option will ignore the
+@code{:placement} setting.
+@item
@code{nil}: if you need to avoid any floating environment, even when
a caption is provided.
@end itemize
@@ -11882,15 +12301,15 @@ Value of @code{:options} attribute will be appended as-is to that
environment's opening string. For example:
@example
-#+BEGIN_ABSTRACT
+#+BEGIN_abstract
We demonstrate how to solve the Syracuse problem.
-#+END_ABSTRACT
+#+END_abstract
#+ATTR_LATEX: :options [Proof of important theorem]
-#+BEGIN_PROOF
+#+BEGIN_proof
...
Therefore, any even number greater than 2 is the sum of two primes.
-#+END_PROOF
+#+END_proof
@end example
@noindent
@@ -11913,9 +12332,9 @@ example:
@example
#+ATTR_LATEX: :caption \MyCaption@{HeadingA@}
-#+BEGIN_PROOF
+#+BEGIN_proof
...
-#+END_PROOF
+#+END_proof
@end example
@subsubheading Horizontal rules
@@ -11965,8 +12384,8 @@ that one (@pxref{Export settings}).
@c begin opendocument
-@node OpenDocument text export
-@section OpenDocument text export
+@node OpenDocument Text export
+@section OpenDocument Text export
@cindex ODT
@cindex OpenDocument
@cindex export, OpenDocument
@@ -11982,6 +12401,7 @@ are compatible with LibreOffice 3.4.
@menu
* Pre-requisites for ODT export:: What packages ODT exporter relies on
* ODT export commands:: How to invoke ODT export
+* ODT specific export settings:: Export settings for ODT
* Extending ODT export:: How to produce @samp{doc}, @samp{pdf} files
* Applying custom styles:: How to apply custom styles to the output
* Links in ODT export:: How links will be interpreted and formatted
@@ -12001,10 +12421,7 @@ output. Check the availability of this program before proceeding further.
@node ODT export commands
@subsection ODT export commands
-
-@subsubheading Exporting to ODT
@anchor{x-export-to-odt}
-
@cindex region, active
@cindex active region
@cindex transient-mark-mode
@@ -12037,6 +12454,33 @@ file instead. @xref{x-export-to-other-formats, , Automatically exporting to
other formats}.
@end table
+@node ODT specific export settings
+@subsection ODT specific export settings
+The ODT exporter introduces a number of keywords, similar to the general
+options settings described in @ref{Export settings}.
+
+@table @samp
+@item DESCRIPTION
+@cindex #+DESCRIPTION (ODT)
+The document description. These are inserted as document metadata. You can
+use several such keywords if the list is long.
+
+@item KEYWORDS
+@cindex #+KEYWORDS (ODT)
+The keywords defining the contents of the document. These are inserted as
+document metadata. You can use several such keywords if the list is long.
+
+@item ODT_STYLES_FILE
+@cindex ODT_STYLES_FILE
+@vindex org-odt-styles-file
+The style file of the document (@code{org-odt-styles-file}). See
+@ref{Applying custom styles} for details.
+
+@item SUBTITLE
+@cindex SUBTITLE (ODT)
+The document subtitle.
+@end table
+
@node Extending ODT export
@subsection Extending ODT export
@@ -12297,7 +12741,7 @@ height:width ratio, do the following
@cindex #+ATTR_ODT
You can control the manner in which an image is anchored by setting the
@code{:anchor} property of it's @code{#+ATTR_ODT} line. You can specify one
-of the the following three values for the @code{:anchor} property:
+of the following three values for the @code{:anchor} property:
@samp{"as-char"}, @samp{"paragraph"} and @samp{"page"}.
To create an image that is anchored to a page, do the following:
@@ -12344,9 +12788,9 @@ You can specify the @LaTeX{}-to-MathML converter by customizing the variables
@code{org-latex-to-mathml-convert-command} and
@code{org-latex-to-mathml-jar-file}.
-If you prefer to use @file{MathToWeb}@footnote{See
-@uref{http://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl, MathToWeb}} as your
-converter, you can configure the above variables as shown below.
+To use MathToWeb@footnote{See
+@uref{http://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl, MathToWeb}.} as your
+converter, you can configure the above variables as
@lisp
(setq org-latex-to-mathml-convert-command
@@ -12354,6 +12798,11 @@ converter, you can configure the above variables as shown below.
org-latex-to-mathml-jar-file
"/path/to/mathtoweb.jar")
@end lisp
+To use @LaTeX{}ML@footnote{See @uref{http://dlmf.nist.gov/LaTeXML/}.} use
+@lisp
+(setq org-latex-to-mathml-convert-command
+ "latexmlmath \"%i\" --presentationmathml=%o")
+@end lisp
You can use the following commands to quickly verify the reliability of
the @LaTeX{}-to-MathML converter.
@@ -12724,7 +13173,7 @@ export the table that follows:
@end lisp
@example
-#+ATTR_ODT: :style "TableWithHeaderRowAndColumn"
+#+ATTR_ODT: :style TableWithHeaderRowAndColumn
| Name | Phone | Age |
| Peter | 1234 | 17 |
| Anna | 4321 | 25 |
@@ -12900,6 +13349,376 @@ Export to a temporary buffer. Do not create a file.
Export to an Org file, then open it.
@end table
+@node Texinfo export
+@section Texinfo export
+@cindex Texinfo export
+
+@samp{texinfo} export back-end generates Texinfo code and can compile it into
+an Info file.
+
+@menu
+* Texinfo export commands:: How to invoke Texinfo export
+* Texinfo specific export settings:: Export settings for Texinfo
+* 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::
+@end menu
+
+@node Texinfo export commands
+@subsection Texinfo export commands
+
+@vindex org-texinfo-info-process
+@table @kbd
+@orgcmd{C-c C-e i t,org-texinfo-export-to-texinfo}
+Export as a Texinfo file. For an Org file, @file{myfile.org}, the resulting
+file will be @file{myfile.texi}. The file will be overwritten without
+warning.
+@orgcmd{C-c C-e i i,org-texinfo-export-to-info}
+Export to Texinfo and then process to an Info file@footnote{By setting
+@code{org-texinfo-info-process}, it is possible to generate other formats,
+including DocBook.}.
+@end table
+
+@node Texinfo specific export settings
+@subsection Texinfo specific export settings
+The Texinfo exporter introduces a number of keywords, similar to the general
+options settings described in @ref{Export settings}.
+
+@table @samp
+
+@item SUBTITLE
+@cindex #+SUBTITLE (Texinfo)
+The document subtitle.
+
+@item SUBAUTHOR
+@cindex #+SUBAUTHOR
+The document subauthor.
+
+@item TEXINFO_FILENAME
+@cindex #+TEXINFO_FILENAME
+The Texinfo filename.
+
+@item TEXINFO_CLASS
+@cindex #+TEXINFO_CLASS
+@vindex org-texinfo-default-class
+The class of the document (@code{org-texinfo-default-class}). This must be a
+member of @code{org-texinfo-classes}.
+
+@item TEXINFO_HEADER
+@cindex #+TEXINFO_HEADER
+Arbitrary lines inserted at the end of the preamble.
+
+@item TEXINFO_POST_HEADER
+@cindex #+TEXINFO_POST_HEADER
+Arbitrary lines inserted at the end of the preamble.
+
+@item TEXINFO_DIR_CATEGORY
+@cindex #+TEXINFO_DIR_CATEGORY
+The directory category of the document.
+
+@item TEXINFO_DIR_TITLE
+@cindex #+TEXINFO_DIR_TITLE
+The directory title of the document.
+
+@item TEXINFO_DIR_DESC
+@cindex #+TEXINFO_DIR_DESC
+The directory description of the document.
+
+@item TEXINFO_PRINTED_TITLE
+@cindex #+TEXINFO_PRINTED_TITLE
+The printed title of the document.
+@end table
+
+These keywords are treated in details in the following sections.
+
+@node Document preamble
+@subsection Document preamble
+
+When processing a document, @samp{texinfo} back-end generates a minimal file
+header along with a title page, a copyright page, and a menu. You control
+the latter through the structure of the document (@pxref{Headings and
+sectioning structure}). Various keywords allow to tweak the other parts. It
+is also possible to give directions to install the document in the @samp{Top}
+node.
+
+@subsubheading File header
+
+@cindex #+TEXINFO_FILENAME
+Upon creating the header of a Texinfo file, the back-end guesses a name for
+the Info file to be compiled. This may not be a sensible choice, e.g., if
+you want to produce the final document in a different directory. Specify an
+alternate path with @code{#+TEXINFO_FILENAME} keyword to override the default
+destination.
+
+@vindex org-texinfo-coding-system
+@vindex org-texinfo-classes
+@cindex #+TEXINFO_HEADER
+@cindex #+TEXINFO_CLASS
+Along with the output file name, the header contains information about the
+language (@pxref{Export settings}) and current encoding used@footnote{See
+@code{org-texinfo-coding-system} for more information.}. Insert
+a @code{#+TEXINFO_HEADER} keyword for each additional command needed, e.g.,
+@@code@{@@synindex@}.
+
+If you happen to regularly install the same set of commands, it may be easier
+to define your own class in @code{org-texinfo-classes}, which see. Set
+@code{#+TEXINFO_CLASS} keyword accordingly in your document to activate it.
+
+@subsubheading Title and copyright page
+
+@cindex #+TEXINFO_PRINTED_TITLE
+The default template includes a title page for hard copy output. The title
+and author displayed on this page are extracted from, respectively,
+@code{#+TITLE} and @code{#+AUTHOR} keywords (@pxref{Export settings}). It is
+also possible to print a different, more specific, title with
+@code{#+TEXINFO_PRINTED_TITLE} keyword, and add subtitles with
+@code{#+SUBTITLE} keyword. Both expect raw Texinfo code in their value.
+
+@cindex #+SUBAUTHOR
+Likewise, information brought by @code{#+AUTHOR} may not be enough. You can
+include other authors with several @code{#+SUBAUTHOR} keywords. Values are
+also expected to be written in Texinfo code.
+
+@example
+#+AUTHOR: Jane Smith
+#+SUBAUTHOR: John Doe
+#+TEXINFO_PRINTED_TITLE: This Long Title@@inlinefmt@{tex,@@*@} Is Broken in @@TeX@{@}
+@end example
+
+@cindex property, COPYING
+Copying material is defined in a dedicated headline with a non-@code{nil}
+@code{:COPYING:} property. The contents are inserted within
+a @code{@@copying} command at the beginning of the document whereas the
+heading itself does not appear in the structure of the document.
+
+Copyright information is printed on the back of the title page.
+
+@example
+* Copying
+ :PROPERTIES:
+ :COPYING: t
+ :END:
+
+ This is a short example of a complete Texinfo file, version 1.0.
+
+ Copyright \copy 2014 Free Software Foundation, Inc.
+@end example
+
+@subsubheading The Top node
+
+@cindex #+TEXINFO_DIR_CATEGORY
+@cindex #+TEXINFO_DIR_TITLE
+@cindex #+TEXINFO_DIR_DESC
+You may ultimately want to install your new Info file in your system. You
+can write an appropriate entry in the top level directory specifying its
+category and title with, respectively, @code{#+TEXINFO_DIR_CATEGORY} and
+@code{#+TEXINFO_DIR_TITLE}. Optionally, you can add a short description
+using @code{#+TEXINFO_DIR_DESC}. The following example would write an entry
+similar to Org's in the @samp{Top} node.
+
+@example
+#+TEXINFO_DIR_CATEGORY: Emacs
+#+TEXINFO_DIR_TITLE: Org Mode: (org)
+#+TEXINFO_DIR_DESC: Outline-based notes management and organizer
+@end example
+
+@node Headings and sectioning structure
+@subsection Headings and sectioning structure
+
+@vindex org-texinfo-classes
+@vindex org-texinfo-default-class
+@cindex #+TEXINFO_CLASS
+@samp{texinfo} uses a pre-defined scheme, or class, to convert headlines into
+Texinfo structuring commands. For example, a top level headline appears as
+@code{@@chapter} if it should be numbered or as @code{@@unnumbered}
+otherwise. If you need to use a different set of commands, e.g., to start
+with @code{@@part} instead of @code{@@chapter}, install a new class in
+@code{org-texinfo-classes}, then activate it with @code{#+TEXINFO_CLASS}
+keyword. Export process defaults to @code{org-texinfo-default-class} when
+there is no such keyword in the document.
+
+If a headline's level has no associated structuring command, or is below
+a certain threshold (@pxref{Export settings}), that headline becomes a list
+in Texinfo output.
+
+@cindex property, APPENDIX
+As an exception, a headline with a non-@code{nil} @code{:APPENDIX:} property becomes
+an appendix, independently on its level and the class used.
+
+@cindex property, DESCRIPTION
+Each regular sectioning structure creates a menu entry, named after the
+heading. You can provide a different, e.g., shorter, title in
+@code{:ALT_TITLE:} property (@pxref{Table of contents}). Optionally, you can
+specify a description for the item in @code{:DESCRIPTION:} property. E.g.,
+
+@example
+* Controlling Screen Display
+ :PROPERTIES:
+ :ALT_TITLE: Display
+ :DESCRIPTION: Controlling Screen Display
+ :END:
+@end example
+
+@node Indices
+@subsection Indices
+
+@cindex #+CINDEX
+@cindex #+FINDEX
+@cindex #+KINDEX
+@cindex #+PINDEX
+@cindex #+TINDEX
+@cindex #+VINDEX
+Index entries are created using dedicated keywords. @samp{texinfo} back-end
+provides one for each predefined type: @code{#+CINDEX}, @code{#+FINDEX},
+@code{#+KINDEX}, @code{#+PINDEX}, @code{#+TINDEX} and @code{#+VINDEX}. For
+custom indices, you can write raw Texinfo code (@pxref{Quoting Texinfo
+code}).
+
+@example
+#+CINDEX: Defining indexing entries
+@end example
+
+@cindex property, INDEX
+To generate an index, you need to set the @code{:INDEX:} property of
+a headline to an appropriate abbreviation (e.g., @samp{cp} or @samp{vr}).
+The headline is then exported as an unnumbered chapter or section command and
+the index is inserted after its contents.
+
+@example
+* Concept Index
+ :PROPERTIES:
+ :INDEX: cp
+ :END:
+@end example
+
+@node Quoting Texinfo code
+@subsection Quoting Texinfo code
+
+It is possible to insert raw Texinfo code using any of the following
+constructs
+
+@cindex #+TEXINFO
+@cindex #+BEGIN_TEXINFO
+@example
+Richard @@@@texinfo:@@sc@{@@@@Stallman@@@@texinfo:@}@@@@ commence' GNU.
+
+#+TEXINFO: @@need800
+This paragraph is preceded by...
+
+#+BEGIN_TEXINFO
+@@auindex Johnson, Mark
+@@auindex Lakoff, George
+#+END_TEXINFO
+@end example
+
+@node Texinfo specific attributes
+@subsection Texinfo specific attributes
+
+@cindex #+ATTR_TEXINFO
+@samp{texinfo} back-end understands several attributes in plain lists and
+tables. They must be specified using an @code{#+ATTR_TEXINFO} keyword,
+written just above the list or table.
+
+@subsubheading Plain lists
+
+In Texinfo output, description lists appear as two-column tables, using the
+default command @code{@@table}. You can use @code{@@ftable} or
+@code{@@vtable}@footnote{For more information, @inforef{Two-column
+Tables,,texinfo}.} instead with @code{:table-type} attribute.
+
+@vindex org-texinfo-def-table-markup
+In any case, these constructs require a highlighting command for entries in
+the list. You can provide one with @code{:indic} attribute. If you do not,
+it defaults to the value stored in @code{org-texinfo-def-table-markup}, which
+see.
+
+@example
+#+ATTR_TEXINFO: :indic @@asis
+- foo :: This is the text for /foo/, with no highlighting.
+@end example
+
+@subsubheading Tables
+
+When exporting a table, column widths are deduced from the longest cell in
+each column. You can also define them explicitly as fractions of the line
+length, using @code{:columns} attribute.
+
+@example
+#+ATTR_TEXINFO: :columns .5 .5
+| a cell | another cell |
+@end example
+
+@node An example
+@subsection An example
+
+Here is a thorough example. @inforef{GNU Sample Texts,,texinfo} for an
+equivalent Texinfo code.
+
+@example
+#+MACRO: version 2.0
+#+MACRO: updated last updated 4 March 2014
+
+#+OPTIONS: ':t toc:t author:t email:t
+#+TITLE: GNU Sample @{@{@{version@}@}@}
+#+AUTHOR: A.U. Thor
+#+EMAIL: bug-sample@@gnu.org
+#+LANGUAGE: en
+
+#+TEXINFO_FILENAME: sample.info
+#+TEXINFO_HEADER: @@syncodeindex pg cp
+
+#+TEXINFO_DIR_CATEGORY: Texinfo documentation system
+#+TEXINFO_DIR_TITLE: sample: (sample)
+#+TEXINFO_DIR_DESC: Invoking sample
+
+#+TEXINFO_PRINTED_TITLE: GNU Sample
+#+SUBTITLE: for version @{@{@{version@}@}@}, @{@{@{updated@}@}@}
+
+* Copying
+ :PROPERTIES:
+ :COPYING: t
+ :END:
+
+ This manual is for GNU Sample (version @{@{@{version@}@}@},
+ @{@{@{updated@}@}@}), which is an example in the Texinfo documentation.
+
+ Copyright @@@@texinfo:@@copyright@{@}@@@@ 2013 Free Software Foundation,
+ Inc.
+
+ #+BEGIN_QUOTE
+ 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, with no Front-Cover Texts,
+ and with no Back-Cover Texts. A copy of the license is included in
+ the section entitled "GNU Free Documentation License".
+ #+END_QUOTE
+
+* Invoking sample
+
+ #+PINDEX: sample
+ #+CINDEX: invoking @@command@{sample@}
+
+ This is a sample manual. There is no sample program to invoke, but
+ if there were, you could see its basic usage and command line
+ options here.
+
+* GNU Free Documentation License
+ :PROPERTIES:
+ :APPENDIX: t
+ :END:
+
+ #+TEXINFO: @@include fdl.texi
+
+* Index
+ :PROPERTIES:
+ :INDEX: cp
+ :END:
+@end example
+
@node iCalendar export
@section iCalendar export
@cindex iCalendar export
@@ -12978,12 +13797,11 @@ On top of the aforementioned back-ends, Org comes with other built-in ones:
@itemize
@item @file{ox-man.el}: export to a man page.
-@item @file{ox-texinfo.el}: export to @code{Texinfo} format.
@end itemize
-To activate these export back-ends, customize @code{org-export-backends} or
-load them directly with e.g., @code{(require 'ox-texinfo)}. This will add
-new keys in the export dispatcher (@pxref{The export dispatcher}).
+To activate these export back-end, customize @code{org-export-backends} or
+load them directly with e.g., @code{(require 'ox-man)}. This will add new
+keys in the export dispatcher (@pxref{The export dispatcher}).
See the comment section of these files for more information on how to use
them.
@@ -13057,63 +13875,61 @@ are all named after the same scheme: @code{org-export-filter-TYPE-functions},
where @code{TYPE} is the type targeted by the filter. Valid types are:
@multitable @columnfractions .33 .33 .33
-@item bold
+@item body
+@tab bold
@tab babel-call
-@tab center-block
-@item clock
+@item center-block
+@tab clock
@tab code
-@tab comment
-@item comment-block
-@tab diary-sexp
+@item diary-sexp
@tab drawer
-@item dynamic-block
-@tab entity
+@tab dynamic-block
+@item entity
@tab example-block
-@item export-block
-@tab export-snippet
+@tab export-block
+@item export-snippet
@tab final-output
-@item fixed-width
-@tab footnote-definition
+@tab fixed-width
+@item footnote-definition
@tab footnote-reference
-@item headline
-@tab horizontal-rule
+@tab headline
+@item horizontal-rule
@tab inline-babel-call
-@item inline-src-block
-@tab inlinetask
+@tab inline-src-block
+@item inlinetask
@tab italic
-@item item
-@tab keyword
+@tab item
+@item keyword
@tab latex-environment
-@item latex-fragment
-@tab line-break
+@tab latex-fragment
+@item line-break
@tab link
-@item node-property
-@tab options
+@tab node-property
+@item options
@tab paragraph
-@item parse-tree
-@tab plain-list
+@tab parse-tree
+@item plain-list
@tab plain-text
-@item planning
-@tab property-drawer
+@tab planning
+@item property-drawer
@tab quote-block
-@item quote-section
-@tab radio-target
+@tab quote-section
+@item radio-target
@tab section
-@item special-block
-@tab src-block
+@tab special-block
+@item src-block
@tab statistics-cookie
-@item strike-through
-@tab subscript
+@tab strike-through
+@item subscript
@tab superscript
-@item table
-@tab table-cell
+@tab table
+@item table-cell
@tab table-row
-@item target
-@tab timestamp
+@tab target
+@item timestamp
@tab underline
-@item verbatim
-@tab verse-block
-@tab
+@tab verbatim
+@item verse-block
@end multitable
For example, the following snippet allows me to use non-breaking spaces in
@@ -13379,52 +14195,32 @@ result into the destination folder.
@subsection Options for the exporters
@cindex options, for publishing
-The property list can be used to set many export options for the exporters.
-In most cases, these properties correspond to user variables in Org. The
-first table below lists these properties along with the variable they belong
-to. The second table list HTML specific properties. See the documentation
-string of these options for details.
+The property list can be used to set export options during the publishing
+process. In most cases, these properties correspond to user variables in
+Org. While some properties are available for all export back-ends, most of
+them are back-end specific. The following sections list properties along
+with the variable they belong to. See the documentation string of these
+options for details.
-@vindex org-display-custom-times
-@vindex org-export-default-language
-@vindex org-export-exclude-tags
-@vindex org-export-headline-levels
-@vindex org-export-preserve-breaks
-@vindex org-export-publishing-directory
-@vindex org-export-select-tags
-@vindex org-export-with-archived-trees
-@vindex org-export-with-author
-@vindex org-export-with-creator
-@vindex org-export-with-drawers
-@vindex org-export-with-email
-@vindex org-export-with-emphasize
-@vindex org-export-with-fixed-width
-@vindex org-export-with-footnotes
-@vindex org-export-with-latex
-@vindex org-export-with-planning
-@vindex org-export-with-priority
-@vindex org-export-with-properties
-@vindex org-export-with-section-numbers
-@vindex org-export-with-special-strings
-@vindex org-export-with-sub-superscripts
-@vindex org-export-with-tables
-@vindex org-export-with-tags
-@vindex org-export-with-tasks
-@vindex org-export-with-timestamps
-@vindex org-export-with-toc
-@vindex org-export-with-todo-keywords
-@vindex user-mail-address
-@multitable @columnfractions 0.32 0.68
+@vindex org-publish-project-alist
+When a property is given a value in @code{org-publish-project-alist}, its
+setting overrides the value of the corresponding user variable (if any)
+during publishing. Options set within a file (@pxref{Export settings}),
+however, override everything.
+
+@subsubheading Generic properties
+
+@multitable {@code{:with-sub-superscript}} {@code{org-export-with-sub-superscripts}}
@item @code{:archived-trees} @tab @code{org-export-with-archived-trees}
@item @code{:exclude-tags} @tab @code{org-export-exclude-tags}
@item @code{:headline-levels} @tab @code{org-export-headline-levels}
@item @code{:language} @tab @code{org-export-default-language}
@item @code{:preserve-breaks} @tab @code{org-export-preserve-breaks}
-@item @code{:publishing-directory} @tab @code{org-export-publishing-directory}
@item @code{:section-numbers} @tab @code{org-export-with-section-numbers}
@item @code{:select-tags} @tab @code{org-export-select-tags}
@item @code{:with-author} @tab @code{org-export-with-author}
@item @code{:with-creator} @tab @code{org-export-with-creator}
+@item @code{:with-date} @tab @code{org-export-with-date}
@item @code{:with-drawers} @tab @code{org-export-with-drawers}
@item @code{:with-email} @tab @code{org-export-with-email}
@item @code{:with-emphasize} @tab @code{org-export-with-emphasize}
@@ -13440,57 +14236,183 @@ string of these options for details.
@item @code{:with-tags} @tab @code{org-export-with-tags}
@item @code{:with-tasks} @tab @code{org-export-with-tasks}
@item @code{:with-timestamps} @tab @code{org-export-with-timestamps}
+@item @code{:with-title} @tab @code{org-export-with-title}
@item @code{:with-toc} @tab @code{org-export-with-toc}
@item @code{:with-todo-keywords} @tab @code{org-export-with-todo-keywords}
@end multitable
-@vindex org-html-doctype
-@vindex org-html-container-element
-@vindex org-html-html5-fancy
-@vindex org-html-xml-declaration
-@vindex org-html-link-up
-@vindex org-html-link-home
-@vindex org-html-link-org-files-as-html
-@vindex org-html-link-use-abs-url
-@vindex org-html-head
-@vindex org-html-head-extra
-@vindex org-html-inline-images
-@vindex org-html-extension
-@vindex org-html-preamble
-@vindex org-html-postamble
-@vindex org-html-table-default-attributes
-@vindex org-html-table-row-tags
-@vindex org-html-head-include-default-style
-@vindex org-html-head-include-scripts
-@multitable @columnfractions 0.32 0.68
-@item @code{:html-doctype} @tab @code{org-html-doctype}
-@item @code{:html-container} @tab @code{org-html-container-element}
-@item @code{:html-html5-fancy} @tab @code{org-html-html5-fancy}
-@item @code{:html-xml-declaration} @tab @code{org-html-xml-declaration}
-@item @code{:html-link-up} @tab @code{org-html-link-up}
-@item @code{:html-link-home} @tab @code{org-html-link-home}
-@item @code{:html-link-org-as-html} @tab @code{org-html-link-org-files-as-html}
-@item @code{:html-link-use-abs-url} @tab @code{org-html-link-use-abs-url}
-@item @code{:html-head} @tab @code{org-html-head}
-@item @code{:html-head-extra} @tab @code{org-html-head-extra}
-@item @code{:html-inline-images} @tab @code{org-html-inline-images}
-@item @code{:html-extension} @tab @code{org-html-extension}
-@item @code{:html-preamble} @tab @code{org-html-preamble}
-@item @code{:html-postamble} @tab @code{org-html-postamble}
-@item @code{:html-table-attributes} @tab @code{org-html-table-default-attributes}
-@item @code{:html-table-row-tags} @tab @code{org-html-table-row-tags}
+@subsubheading ASCII specific properties
+
+@multitable {@code{:ascii-table-keep-all-vertical-lines}} {@code{org-ascii-table-keep-all-vertical-lines}}
+@item @code{:ascii-bullets} @tab @code{org-ascii-bullets}
+@item @code{:ascii-caption-above} @tab @code{org-ascii-caption-above}
+@item @code{:ascii-charset} @tab @code{org-ascii-charset}
+@item @code{:ascii-global-margin} @tab @code{org-ascii-global-margin}
+@item @code{:ascii-format-drawer-function} @tab @code{org-ascii-format-drawer-function}
+@item @code{:ascii-format-inlinetask-function} @tab @code{org-ascii-format-inlinetask-function}
+@item @code{:ascii-headline-spacing} @tab @code{org-ascii-headline-spacing}
+@item @code{:ascii-indented-line-width} @tab @code{org-ascii-indented-line-width}
+@item @code{:ascii-inlinetask-width} @tab @code{org-ascii-inlinetask-width}
+@item @code{:ascii-inner-margin} @tab @code{org-ascii-inner-margin}
+@item @code{:ascii-links-to-notes} @tab @code{org-ascii-links-to-notes}
+@item @code{:ascii-list-margin} @tab @code{org-ascii-list-margin}
+@item @code{:ascii-paragraph-spacing} @tab @code{org-ascii-paragraph-spacing}
+@item @code{:ascii-quote-margin} @tab @code{org-ascii-quote-margin}
+@item @code{:ascii-table-keep-all-vertical-lines} @tab @code{org-ascii-table-keep-all-vertical-lines}
+@item @code{:ascii-table-use-ascii-art} @tab @code{org-ascii-table-use-ascii-art}
+@item @code{:ascii-table-widen-columns} @tab @code{org-ascii-table-widen-columns}
+@item @code{:ascii-text-width} @tab @code{org-ascii-text-width}
+@item @code{:ascii-underline} @tab @code{org-ascii-underline}
+@item @code{:ascii-verbatim-format} @tab @code{org-ascii-verbatim-format}
+@end multitable
+
+@subsubheading Beamer specific properties
+
+@multitable {@code{:beamer-frame-default-options}} {@code{org-beamer-frame-default-options}}
+@item @code{:beamer-theme} @tab @code{org-beamer-theme}
+@item @code{:beamer-column-view-format} @tab @code{org-beamer-column-view-format}
+@item @code{:beamer-environments-extra} @tab @code{org-beamer-environments-extra}
+@item @code{:beamer-frame-default-options} @tab @code{org-beamer-frame-default-options}
+@item @code{:beamer-outline-frame-options} @tab @code{org-beamer-outline-frame-options}
+@item @code{:beamer-outline-frame-title} @tab @code{org-beamer-outline-frame-title}
+@item @code{:beamer-subtitle-format} @tab @code{org-beamer-subtitle-format}
+@end multitable
+
+@subsubheading HTML specific properties
+
+@multitable {@code{:html-table-use-header-tags-for-first-column}} {@code{org-html-table-use-header-tags-for-first-column}}
+@item @code{:html-allow-name-attribute-in-anchors} @tab @code{org-html-allow-name-attribute-in-anchors}
+@item @code{:html-checkbox-type} @tab @code{org-html-checkbox-type}
+@item @code{:html-container} @tab @code{org-html-container-element}
+@item @code{:html-divs} @tab @code{org-html-divs}
+@item @code{:html-doctype} @tab @code{org-html-doctype}
+@item @code{:html-extension} @tab @code{org-html-extension}
+@item @code{:html-footnote-format} @tab @code{org-html-footnote-format}
+@item @code{:html-footnote-separator} @tab @code{org-html-footnote-separator}
+@item @code{:html-footnotes-section} @tab @code{org-html-footnotes-section}
+@item @code{:html-format-drawer-function} @tab @code{org-html-format-drawer-function}
+@item @code{:html-format-headline-function} @tab @code{org-html-format-headline-function}
+@item @code{:html-format-inlinetask-function} @tab @code{org-html-format-inlinetask-function}
+@item @code{:html-head-extra} @tab @code{org-html-head-extra}
@item @code{:html-head-include-default-style} @tab @code{org-html-head-include-default-style}
-@item @code{:html-head-include-scripts} @tab @code{org-html-head-include-scripts}
+@item @code{:html-head-include-scripts} @tab @code{org-html-head-include-scripts}
+@item @code{:html-head} @tab @code{org-html-head}
+@item @code{:html-home/up-format} @tab @code{org-html-home/up-format}
+@item @code{:html-html5-fancy} @tab @code{org-html-html5-fancy}
+@item @code{:html-indent} @tab @code{org-html-indent}
+@item @code{:html-infojs-options} @tab @code{org-html-infojs-options}
+@item @code{:html-infojs-template} @tab @code{org-html-infojs-template}
+@item @code{:html-inline-image-rules} @tab @code{org-html-inline-image-rules}
+@item @code{:html-inline-images} @tab @code{org-html-inline-images}
+@item @code{:html-link-home} @tab @code{org-html-link-home}
+@item @code{:html-link-org-files-as-html} @tab @code{org-html-link-org-files-as-html}
+@item @code{:html-link-up} @tab @code{org-html-link-up}
+@item @code{:html-link-use-abs-url} @tab @code{org-html-link-use-abs-url}
+@item @code{:html-mathjax-options} @tab @code{org-html-mathjax-options}
+@item @code{:html-mathjax-template} @tab @code{org-html-mathjax-template}
+@item @code{:html-metadata-timestamp-format} @tab @code{org-html-metadata-timestamp-format}
+@item @code{:html-postamble-format} @tab @code{org-html-postamble-format}
+@item @code{:html-postamble} @tab @code{org-html-postamble}
+@item @code{:html-preamble-format} @tab @code{org-html-preamble-format}
+@item @code{:html-preamble} @tab @code{org-html-preamble}
+@item @code{:html-table-align-individual-fields} @tab @code{org-html-table-align-individual-fields}
+@item @code{:html-table-attributes} @tab @code{org-html-table-default-attributes}
+@item @code{:html-table-caption-above} @tab @code{org-html-table-caption-above}
+@item @code{:html-table-data-tags} @tab @code{org-html-table-data-tags}
+@item @code{:html-table-header-tags} @tab @code{org-html-table-header-tags}
+@item @code{:html-table-row-tags} @tab @code{org-html-table-row-tags}
+@item @code{:html-table-use-header-tags-for-first-column} @tab @code{org-html-table-use-header-tags-for-first-column}
+@item @code{:html-tag-class-prefix} @tab @code{org-html-tag-class-prefix}
+@item @code{:html-text-markup-alist} @tab @code{org-html-text-markup-alist}
+@item @code{:html-todo-kwd-class-prefix} @tab @code{org-html-todo-kwd-class-prefix}
+@item @code{:html-toplevel-hlevel} @tab @code{org-html-toplevel-hlevel}
+@item @code{:html-use-infojs} @tab @code{org-html-use-infojs}
+@item @code{:html-use-unicode-chars} @tab @code{org-html-use-unicode-chars}
+@item @code{:html-validation-link} @tab @code{org-html-validation-link}
+@item @code{:html-viewport} @tab @code{org-html-viewport}
+@item @code{:html-xml-declaration} @tab @code{org-html-xml-declaration}
@end multitable
-Most of the @code{org-export-with-*} variables have the same effect in each
-exporter.
+@subsubheading @LaTeX{} specific properties
+
+@multitable {@code{:latex-link-with-unknown-path-format}} {@code{org-latex-link-with-unknown-path-format}}
+@item @code{:latex-active-timestamp-format} @tab @code{org-latex-active-timestamp-format}
+@item @code{:latex-caption-above} @tab @code{org-latex-caption-above}
+@item @code{:latex-classes} @tab @code{org-latex-classes}
+@item @code{:latex-class} @tab @code{org-latex-default-class}
+@item @code{:latex-default-figure-position} @tab @code{org-latex-default-figure-position}
+@item @code{:latex-default-table-environment} @tab @code{org-latex-default-table-environment}
+@item @code{:latex-default-table-mode} @tab @code{org-latex-default-table-mode}
+@item @code{:latex-diary-timestamp-format} @tab @code{org-latex-diary-timestamp-format}
+@item @code{:latex-footnote-separator} @tab @code{org-latex-footnote-separator}
+@item @code{:latex-format-drawer-function} @tab @code{org-latex-format-drawer-function}
+@item @code{:latex-format-headline-function} @tab @code{org-latex-format-headline-function}
+@item @code{:latex-format-inlinetask-function} @tab @code{org-latex-format-inlinetask-function}
+@item @code{:latex-hyperref-template} @tab @code{org-latex-hyperref-template}
+@item @code{:latex-image-default-height} @tab @code{org-latex-image-default-height}
+@item @code{:latex-image-default-option} @tab @code{org-latex-image-default-option}
+@item @code{:latex-image-default-width} @tab @code{org-latex-image-default-width}
+@item @code{:latex-inactive-timestamp-format} @tab @code{org-latex-inactive-timestamp-format}
+@item @code{:latex-inline-image-rules} @tab @code{org-latex-inline-image-rules}
+@item @code{:latex-link-with-unknown-path-format} @tab @code{org-latex-link-with-unknown-path-format}
+@item @code{:latex-listings-langs} @tab @code{org-latex-listings-langs}
+@item @code{:latex-listings-options} @tab @code{org-latex-listings-options}
+@item @code{:latex-listings} @tab @code{org-latex-listings}
+@item @code{:latex-minted-langs} @tab @code{org-latex-minted-langs}
+@item @code{:latex-minted-options} @tab @code{org-latex-minted-options}
+@item @code{:latex-prefer-user-labels} @tab @code{org-latex-prefer-user-labels}
+@item @code{:latex-subtitle-format} @tab @code{org-latex-subtitle-format}
+@item @code{:latex-subtitle-separate} @tab @code{org-latex-subtitle-separate}
+@item @code{:latex-table-scientific-notation} @tab @code{org-latex-table-scientific-notation}
+@item @code{:latex-tables-booktabs} @tab @code{org-latex-tables-booktabs}
+@item @code{:latex-tables-centered} @tab @code{org-latex-tables-centered}
+@item @code{:latex-text-markup-alist} @tab @code{org-latex-text-markup-alist}
+@item @code{:latex-title-command} @tab @code{org-latex-title-command}
+@item @code{:latex-toc-command} @tab @code{org-latex-toc-command}
+@end multitable
-@vindex org-publish-project-alist
-When a property is given a value in @code{org-publish-project-alist}, its
-setting overrides the value of the corresponding user variable (if any)
-during publishing. Options set within a file (@pxref{Export settings}),
-however, override everything.
+@subsubheading Markdown specific properties
+
+@multitable {@code{:md-headline-style}} {@code{org-md-headline-style}}
+@item @code{:md-headline-style} @tab @code{org-md-headline-style}
+@end multitable
+
+@subsubheading ODT specific properties
+
+@multitable {@code{:odt-format-inlinetask-function}} {@code{org-odt-format-inlinetask-function}}
+@item @code{:odt-content-template-file} @tab @code{org-odt-content-template-file}
+@item @code{:odt-display-outline-level} @tab @code{org-odt-display-outline-level}
+@item @code{:odt-fontify-srcblocks} @tab @code{org-odt-fontify-srcblocks}
+@item @code{:odt-format-drawer-function} @tab @code{org-odt-format-drawer-function}
+@item @code{:odt-format-headline-function} @tab @code{org-odt-format-headline-function}
+@item @code{:odt-format-inlinetask-function} @tab @code{org-odt-format-inlinetask-function}
+@item @code{:odt-inline-formula-rules} @tab @code{org-odt-inline-formula-rules}
+@item @code{:odt-inline-image-rules} @tab @code{org-odt-inline-image-rules}
+@item @code{:odt-pixels-per-inch} @tab @code{org-odt-pixels-per-inch}
+@item @code{:odt-styles-file} @tab @code{org-odt-styles-file}
+@item @code{:odt-table-styles} @tab @code{org-odt-table-styles}
+@item @code{:odt-use-date-fields} @tab @code{org-odt-use-date-fields}
+@end multitable
+
+@subsubheading Texinfo specific properties
+
+@multitable {@code{:texinfo-link-with-unknown-path-format}} {@code{org-texinfo-link-with-unknown-path-format}}
+@item @code{:texinfo-active-timestamp-format} @tab @code{org-texinfo-active-timestamp-format}
+@item @code{:texinfo-classes} @tab @code{org-texinfo-classes}
+@item @code{:texinfo-class} @tab @code{org-texinfo-default-class}
+@item @code{:texinfo-def-table-markup} @tab @code{org-texinfo-def-table-markup}
+@item @code{:texinfo-diary-timestamp-format} @tab @code{org-texinfo-diary-timestamp-format}
+@item @code{:texinfo-filename} @tab @code{org-texinfo-filename}
+@item @code{:texinfo-format-drawer-function} @tab @code{org-texinfo-format-drawer-function}
+@item @code{:texinfo-format-headline-function} @tab @code{org-texinfo-format-headline-function}
+@item @code{:texinfo-format-inlinetask-function} @tab @code{org-texinfo-format-inlinetask-function}
+@item @code{:texinfo-inactive-timestamp-format} @tab @code{org-texinfo-inactive-timestamp-format}
+@item @code{:texinfo-link-with-unknown-path-format} @tab @code{org-texinfo-link-with-unknown-path-format}
+@item @code{:texinfo-node-description-column} @tab @code{org-texinfo-node-description-column}
+@item @code{:texinfo-table-scientific-notation} @tab @code{org-texinfo-table-scientific-notation}
+@item @code{:texinfo-tables-verbatim} @tab @code{org-texinfo-tables-verbatim}
+@item @code{:texinfo-text-markup-alist} @tab @code{org-texinfo-text-markup-alist}
+@end multitable
@node Publishing links
@subsection Links between published files
@@ -13863,7 +14785,7 @@ Controls the way Emacs windows are rearranged when the edit buffer is created.
@cindex indentation, in source blocks
By default, the value is @code{nil}, which means that when code blocks are
evaluated during export or tangled, they are re-inserted into the code block,
-which may replace sequences of spaces with tab characters. When non-nil,
+which may replace sequences of spaces with tab characters. When non-@code{nil},
whitespace in code blocks will be preserved during export or tangling,
exactly as it appears. This variable is especially useful for tangling
languages such as Python, in which whitespace indentation in the output is
@@ -14020,16 +14942,15 @@ option @code{org-babel-no-eval-on-ctrl-c-ctrl-c} can be used to remove code
evaluation from the @kbd{C-c C-c} key binding.}. This will call the
@code{org-babel-execute-src-block} function to evaluate the block and insert
its results into the Org mode buffer.
-@cindex #+CALL
+@cindex #+CALL
It is also possible to evaluate named code blocks from anywhere in an Org
mode buffer or an Org mode table. These named code blocks can be located in
-the current Org mode buffer or in the ``Library of Babel'' (see @ref{Library
-of Babel}). Named code blocks can be evaluated with a separate
-@code{#+CALL:} line or inline within a block of text. In both cases
-the result is wrapped according to the value of
-@var{org-babel-inline-result-wrap}, which by default is @code{"=%s="} for
-markup that produces verbatim text.
+the current Org mode buffer or in the ``Library of Babel'' (@pxref{Library of
+Babel}). Named code blocks can be evaluated with a separate @code{#+CALL:}
+line or inline within a block of text. In both cases the result is wrapped
+according to the value of @code{org-babel-inline-result-wrap}, which by
+default is @code{"=%s="} for markup that produces verbatim text.
The syntax of the @code{#+CALL:} line is
@@ -14104,25 +15025,26 @@ i}.
Code blocks in the following languages are supported.
-@multitable @columnfractions 0.28 0.3 0.22 0.2
-@item @b{Language} @tab @b{Identifier} @tab @b{Language} @tab @b{Identifier}
+@multitable @columnfractions 0.25 0.25 0.25 0.25
+@headitem @b{Language} @tab @b{Identifier} @tab @b{Language} @tab @b{Identifier}
@item Asymptote @tab asymptote @tab Awk @tab awk
-@item Emacs Calc @tab calc @tab C @tab C
-@item C++ @tab C++ @tab Clojure @tab clojure
-@item CSS @tab css @tab ditaa @tab ditaa
-@item Graphviz @tab dot @tab Emacs Lisp @tab emacs-lisp
-@item gnuplot @tab gnuplot @tab Haskell @tab haskell
-@item Java @tab java @tab @tab
-@item Javascript @tab js @tab LaTeX @tab latex
-@item Ledger @tab ledger @tab Lisp @tab lisp
-@item Lilypond @tab lilypond @tab MATLAB @tab matlab
-@item Mscgen @tab mscgen @tab Objective Caml @tab ocaml
-@item Octave @tab octave @tab Org mode @tab org
-@item Oz @tab oz @tab Perl @tab perl
-@item Plantuml @tab plantuml @tab Python @tab python
-@item R @tab R @tab Ruby @tab ruby
-@item Sass @tab sass @tab Scheme @tab scheme
-@item GNU Screen @tab screen @tab shell @tab sh
+@item C @tab C @tab C++ @tab C++
+@item Clojure @tab clojure @tab CSS @tab css
+@item D @tab d @tab ditaa @tab ditaa
+@item Graphviz @tab dot @tab Emacs Calc @tab calc
+@item Emacs Lisp @tab emacs-lisp @tab Fortran @tab fortran
+@item gnuplot @tab gnuplot @tab Haskell @tab haskell
+@item Java @tab java @tab Javascript @tab js
+@item LaTeX @tab latex @tab Ledger @tab ledger
+@item Lisp @tab lisp @tab Lilypond @tab lilypond
+@item MATLAB @tab matlab @tab Mscgen @tab mscgen
+@item Objective Caml @tab ocaml @tab Octave @tab octave
+@item Org mode @tab org @tab Oz @tab oz
+@item Perl @tab perl @tab Plantuml @tab plantuml
+@item Processing.js @tab processing @tab Python @tab python
+@item R @tab R @tab Ruby @tab ruby
+@item Sass @tab sass @tab Scheme @tab scheme
+@item GNU Screen @tab screen @tab shell @tab sh
@item SQL @tab sql @tab SQLite @tab sqlite
@end multitable
@@ -14135,10 +15057,8 @@ enabled for evaluation (by default only @code{emacs-lisp} is enabled). This
variable can be set using the customization interface or by adding code like
the following to your emacs configuration.
-@quotation
The following disables @code{emacs-lisp} evaluation and enables evaluation of
@code{R} code blocks.
-@end quotation
@lisp
(org-babel-do-load-languages
@@ -14150,9 +15070,7 @@ The following disables @code{emacs-lisp} evaluation and enables evaluation of
It is also possible to enable support for a language by loading the related
elisp file with @code{require}.
-@quotation
The following adds support for evaluating @code{clojure} code blocks.
-@end quotation
@lisp
(require 'ob-clojure)
@@ -14389,6 +15307,8 @@ argument in lowercase letters. The following header arguments are defined:
be collected and handled
* file:: Specify a path for file output
* file-desc:: Specify a description for file results
+* file-ext:: Specify an extension for file output
+* output-dir:: Specify a directory to write file output to
* dir:: Specify the default (possibly remote)
directory for code block execution
* exports:: Export code and/or results
@@ -14823,6 +15743,29 @@ description for file code block results which are inserted as Org mode links
with no value the link path will be placed in both the ``link'' and the
``description'' portion of the Org mode link.
+@node file-ext
+@subsubsection @code{:file-ext}
+@cindex @code{:file-ext}, src header argument
+
+The value of the @code{:file-ext} header argument is used to provide an
+extension to write the file output to. It is combined with the
+@code{#+NAME:} of the source block and the value of the @ref{output-dir}
+header argument to generate a complete file name.
+
+This header arg will be overridden by @code{:file}, and thus has no effect
+when the latter is specified.
+
+@node output-dir
+@subsubsection @code{:output-dir}
+@cindex @code{:output-dir}, src header argument
+
+The value of the @code{:output-dir} header argument is used to provide a
+directory to write the file output to. It may specify an absolute directory
+(beginning with @code{/}) or a relative directory (without @code{/}). It can
+be combined with the @code{#+NAME:} of the source block and the value of the
+@ref{file-ext} header argument to generate a complete file name, or used
+along with a @ref{file} header arg.
+
@node dir
@subsubsection @code{:dir} and remote execution
@cindex @code{:dir}, src header argument
@@ -14994,19 +15937,32 @@ during tangling. This has the effect of assigning values to variables
specified with @code{:var} (see @ref{var}), and of replacing ``noweb''
references (see @ref{Noweb reference syntax}) with their targets. The
@code{:no-expand} header argument can be used to turn off this behavior.
+Note: The @code{:no-expand} header argument has no impact on export,
+i.e. code blocks will irrespective of this header argument expanded for
+execution.
@node session
@subsubsection @code{:session}
@cindex @code{:session}, src header argument
-The @code{:session} header argument starts a session for an interpreted
-language where state is preserved.
-
+The @code{:session} header argument starts a (possibly named) session for an
+interpreted language where the interpreter’s state is preserved. All code
+blocks sharing the same name are exectuted by the same interpreter process.
By default, a session is not started.
-A string passed to the @code{:session} header argument will give the session
-a name. This makes it possible to run concurrent sessions for each
-interpreted language.
+@itemize @bullet
+@item @code{none}
+The default. Each block is evaluated in its own interpreter process, which
+is terminated after the evaluation.
+@item @code{other}
+Any other string passed to the @code{:session} header argument will give the
+session a name. For example, @code{:session mysession}. If @code{:session}
+is given but no name string is specified, the session is named according to
+the language used in the block. All blocks with the same session name share
+the same session. Using different session names enables concurrent sessions
+(even for the same interpreted language).
+
+@end itemize
@node noweb
@subsubsection @code{:noweb}
@@ -15069,12 +16025,12 @@ references.
@node noweb-ref
@subsubsection @code{:noweb-ref}
@cindex @code{:noweb-ref}, src header argument
-When expanding ``noweb'' style references the bodies of all code block with
+When expanding ``noweb'' style references, the bodies of all code block with
@emph{either} a block name matching the reference name @emph{or} a
@code{:noweb-ref} header argument matching the reference name will be
concatenated together to form the replacement text.
-By setting this header argument at the sub-tree or file level, simple code
+By setting this header argument at the subtree or file level, simple code
block concatenation may be achieved. For example, when tangling the
following Org mode file, the bodies of code blocks will be concatenated into
the resulting pure code file@footnote{(The example needs property inheritance
@@ -15395,10 +16351,11 @@ code block execution. When a post argument is given, the results of the code
block will temporarily be bound to the @code{*this*} variable. This variable
may then be included in header argument forms such as those used in @ref{var}
header argument specifications allowing passing of results to other code
-blocks, or direct execution via Emacs Lisp.
+blocks, or direct execution via Emacs Lisp. Additional header arguments may
+be passed to the @code{:post}-function.
-The following example illustrates the usage of the @code{:post} header
-argument.
+The following two examples illustrate the usage of the @code{:post} header
+argument. The first example shows how to attach a attribute-line via @code{:post}.
@example
#+name: attr_wrap
@@ -15423,6 +16380,31 @@ argument.
:END:
@end example
+The second examples shows how to use @code{:post} together with the
+@code{:colnames} header argument.
+@example
+#+name: round-tbl
+#+begin_src emacs-lisp :var tbl="" fmt="%.3f"
+ (mapcar (lambda (row)
+ (mapcar (lambda (cell)
+ (if (numberp cell)
+ (format fmt cell)
+ cell))
+ row))
+ tbl)
+#+end_src
+
+#+begin_src R :colnames yes :post round-tbl[:colnames yes](*this*)
+set.seed(42)
+data.frame(foo=rnorm(1))
+#+end_src
+
+#+RESULTS:
+| foo |
+|-------|
+| 1.371 |
+@end example
+
@node prologue
@subsubsection @code{:prologue}
@cindex @code{:prologue}, src header argument
@@ -15596,10 +16578,10 @@ are active:
@item @kbd{C-c C-c} @tab @code{org-babel-execute-src-block}
@kindex C-c C-o
@item @kbd{C-c C-o} @tab @code{org-babel-open-src-block-result}
-@kindex C-up
-@item @kbd{C-@key{up}} @tab @code{org-babel-load-in-session}
+@kindex M-up
+@item @kbd{M-@key{up}} @tab @code{org-babel-load-in-session}
@kindex M-down
-@item @kbd{M-@key{down}} @tab @code{org-babel-pop-to-session}
+@item @kbd{M-@key{down}} @tab @code{org-babel-switch-to-session}
@end multitable
In an Org mode buffer, the following key bindings are active:
@@ -15958,9 +16940,8 @@ all subsequent lines until the next @samp{#+ARCHIVE} line, or the end
of the file. The first such line also applies to any entries before it.
The corresponding variable is @code{org-archive-location}.
@item #+CATEGORY:
-This line sets the category for the agenda file. The category applies
-for all subsequent lines until the next @samp{#+CATEGORY} line, or the
-end of the file. The first such line also applies to any entries before it.
+This line sets the category for the agenda file. The category applies to the
+whole document.
@item #+COLUMNS: %25ITEM ...
@cindex property, COLUMNS
Set the default format for columns view. This format applies when
@@ -16219,9 +17200,6 @@ multiple #+TBLFM lines} in @ref{Editing and debugging formulas}.
@item #+TITLE:, #+AUTHOR:, #+EMAIL:, #+LANGUAGE:, #+DATE:,
@itemx #+OPTIONS:, #+BIND:,
-@itemx #+DESCRIPTION:, #+KEYWORDS:,
-@itemx #+LaTeX_HEADER:, #+LaTeX_HEADER_EXTRA:,
-@itemx #+HTML_HEAD:, #+HTML_HEAD_EXTRA:, #+HTML_LINK_UP:, #+HTML_LINK_HOME:,
@itemx #+SELECT_TAGS:, #+EXCLUDE_TAGS:
These lines provide settings for exporting files. For more details see
@ref{Export settings}.
@@ -16884,8 +17862,8 @@ back-end from scratch) and @file{ox-beamer.el} (for how to derive a new
back-end from an existing one.
When creating a new back-end from scratch, the basic idea is to set the name
-of the back-end (as a symbol) and an an alist of elements and export
-functions. On top of this, you will need to set additional keywords like
+of the back-end (as a symbol) and an alist of elements and export functions.
+On top of this, you will need to set additional keywords like
@code{:menu-entry} (to display the back-end in the export dispatcher),
@code{:export-block} (to specify what blocks should not be exported by this
back-end), and @code{:options-alist} (to let the user set export options that
@@ -17015,10 +17993,6 @@ calculation marks, that column is automatically discarded as well.
Please note that the translator function sees the table @emph{after} the
removal of these columns, the function never knows that there have been
additional columns.
-
-@item :no-escape t
-When non-@code{nil}, do not escape special characters @code{&%#_^} when exporting
-the table. The default value is @code{nil}.
@end table
@noindent
@@ -17126,14 +18100,15 @@ Month & \multicolumn@{1@}@{c@}@{Days@} & Nr.\ sold & per day\\
@end example
The @LaTeX{} translator function @code{orgtbl-to-latex} is already part of
-Orgtbl mode. It uses a @code{tabular} environment to typeset the table
-and marks horizontal lines with @code{\hline}. Furthermore, it
-interprets the following parameters (see also @pxref{Translator functions}):
+Orgtbl mode. By default, it uses a @code{tabular} environment to typeset the
+table and marks horizontal lines with @code{\hline}. You can control the
+output through several parameters (see also @pxref{Translator functions}),
+including the following ones :
@table @code
@item :splice nil/t
-When set to t, return only table body lines, don't wrap them into a
-tabular environment. Default is @code{nil}.
+When non-@code{nil}, return only table body lines, don't wrap them into a tabular
+environment. Default is @code{nil}.
@item :fmt fmt
A format to be used to wrap each field, it should contain @code{%s} for the
@@ -17144,14 +18119,14 @@ A function of one argument can be used in place of the strings; the
function must return a formatted string.
@item :efmt efmt
-Use this format to print numbers with exponentials. The format should
-have @code{%s} twice for inserting mantissa and exponent, for example
-@code{"%s\\times10^@{%s@}"}. The default is @code{"%s\\,(%s)"}. This
-may also be a property list with column numbers and formats, for example
-@code{:efmt (2 "$%s\\times10^@{%s@}$" 4 "$%s\\cdot10^@{%s@}$")}. After
-@code{efmt} has been applied to a value, @code{fmt} will also be
-applied. Similar to @code{fmt}, functions of two arguments can be
-supplied instead of strings.
+Use this format to print numbers with exponentials. The format should have
+@code{%s} twice for inserting mantissa and exponent, for example
+@code{"%s\\times10^@{%s@}"}. This may also be a property list with column
+numbers and formats, for example @code{:efmt (2 "$%s\\times10^@{%s@}$"
+4 "$%s\\cdot10^@{%s@}$")}. After @code{efmt} has been applied to a value,
+@code{fmt} will also be applied. Similar to @code{fmt}, functions of two
+arguments can be supplied instead of strings. By default, no special
+formatting is applied.
@end table
@node Translator functions
@@ -17161,54 +18136,36 @@ supplied instead of strings.
Orgtbl mode has several translator functions built-in: @code{orgtbl-to-csv}
(comma-separated values), @code{orgtbl-to-tsv} (TAB-separated values)
-@code{orgtbl-to-latex}, @code{orgtbl-to-html}, and @code{orgtbl-to-texinfo}.
-Except for @code{orgtbl-to-html}@footnote{The HTML translator uses the same
-code that produces tables during HTML export.}, these all use a generic
-translator, @code{orgtbl-to-generic}. For example, @code{orgtbl-to-latex}
-itself is a very short function that computes the column definitions for the
-@code{tabular} environment, defines a few field and line separators and then
-hands processing over to the generic translator. Here is the entire code:
-
-@lisp
-@group
-(defun orgtbl-to-latex (table params)
- "Convert the Orgtbl mode TABLE to LaTeX."
- (let* ((alignment (mapconcat (lambda (x) (if x "r" "l"))
- org-table-last-alignment ""))
- (params2
- (list
- :tstart (concat "\\begin@{tabular@}@{" alignment "@}")
- :tend "\\end@{tabular@}"
- :lstart "" :lend " \\\\" :sep " & "
- :efmt "%s\\,(%s)" :hline "\\hline")))
- (orgtbl-to-generic table (org-combine-plists params2 params))))
-@end group
-@end lisp
+@code{orgtbl-to-latex}, @code{orgtbl-to-html}, @code{orgtbl-to-texinfo},
+@code{orgtbl-to-unicode} and @code{orgtbl-to-orgtbl}. These all use
+a generic translator, @code{orgtbl-to-generic}, which, in turn, can delegate
+translations to various export back-ends (@pxref{Export back-ends}).
-As you can see, the properties passed into the function (variable
-@var{PARAMS}) are combined with the ones newly defined in the function
-(variable @var{PARAMS2}). The ones passed into the function (i.e., the
-ones set by the @samp{ORGTBL SEND} line) take precedence. So if you
-would like to use the @LaTeX{} translator, but wanted the line endings to
-be @samp{\\[2mm]} instead of the default @samp{\\}, you could just
-overrule the default with
+In particular, properties passed into the function (i.e., the ones set by the
+@samp{ORGTBL SEND} line) take precedence over translations defined in the
+function. So if you would like to use the @LaTeX{} translator, but wanted
+the line endings to be @samp{\\[2mm]} instead of the default @samp{\\}, you
+could just overrule the default with
@example
#+ORGTBL: SEND test orgtbl-to-latex :lend " \\\\[2mm]"
@end example
-For a new language, you can either write your own converter function in
-analogy with the @LaTeX{} translator, or you can use the generic function
-directly. For example, if you have a language where a table is started
-with @samp{!BTBL!}, ended with @samp{!ETBL!}, and where table lines are
-started with @samp{!BL!}, ended with @samp{!EL!}, and where the field
-separator is a TAB, you could call the generic translator like this (on
-a single line!):
+For a new language, you can use the generic function to write your own
+converter function. For example, if you have a language where a table is
+started with @samp{!BTBL!}, ended with @samp{!ETBL!}, and where table lines
+are started with @samp{!BL!}, ended with @samp{!EL!}, and where the field
+separator is a TAB, you could define your generic translator like this:
-@example
-#+ORGTBL: SEND test orgtbl-to-generic :tstart "!BTBL!" :tend "!ETBL!"
- :lstart "!BL! " :lend " !EL!" :sep "\t"
-@end example
+@lisp
+(defun orgtbl-to-language (table params)
+ "Convert the orgtbl-mode TABLE to language."
+ (orgtbl-to-generic
+ table
+ (org-combine-plists
+ '(:tstart "!BTBL!" :tend "!ETBL!" :lstart "!BL!" :lend "!EL!" :sep "\t")
+ params)))
+@end lisp
@noindent
Please check the documentation string of the function
@@ -17628,7 +18585,7 @@ Get all property keys in the current buffer.
@end defun
@defun org-insert-property-drawer
-Insert a property drawer for the current entry. Also
+Insert a property drawer for the current entry.
@end defun
@defun org-entry-put-multivalued-property pom property &rest values
diff --git a/doc/orgguide.texi b/doc/orgguide.texi
index cacca3c..12d3a51 100644
--- a/doc/orgguide.texi
+++ b/doc/orgguide.texi
@@ -35,7 +35,8 @@
@end macro
@macro seealso{text}
-@noindent @b{Further reading}@*@noindent \text\
+@noindent
+@b{Further reading}@*@noindent \text\
@end macro
@copying
@@ -45,7 +46,7 @@ Copyright @copyright{} 2010--2014 Free Software Foundation
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, with the Front-Cover texts being ``A GNU Manual,''
+Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
and with the Back-Cover Texts as in (a) below. A copy of the license
is included in the section entitled ``GNU Free Documentation License''
in the full Org manual, which is distributed together with the compact
@@ -211,7 +212,7 @@ Exporting
* ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding
* HTML export:: Exporting to HTML
* @LaTeX{} and PDF export:: Exporting to @LaTeX{}, and processing to PDF
-* iCalendar export:: Exporting to iCalendar
+* iCalendar export:: Exporting to iCalendar
Miscellaneous
@@ -263,7 +264,8 @@ to the Emacs load path. To do this, add the following line to @file{.emacs}:
(setq load-path (cons "~/path/to/orgdir/contrib/lisp" load-path))
@end smallexample
-@noindent If you have been using git or a tar ball to get Org, you need to
+@noindent
+If you have been using git or a tar ball to get Org, you need to
run the following command to generate autoload information.
command:
@@ -343,7 +345,11 @@ of @kbd{C-a} and @kbd{C-e} in headlines.}. For example:
* Another top level headline
@end smallexample
-@noindent Some people find the many stars too noisy and would prefer an
+@noindent Note that a headline named after @code{org-footnote-section},
+which defaults to @samp{Footnotes}, is considered as special. A subtree with
+this headline will be silently ignored by exporting functions.
+
+Some people find the many stars too noisy and would prefer an
outline that has whitespace followed by a single star as headline
starters. @ref{Clean view}, describes a setup to realize this.
@@ -444,10 +450,9 @@ An important feature of Org mode is the ability to construct @emph{sparse
trees} for selected information in an outline tree, so that the entire
document is folded as much as possible, but the selected information is made
visible along with the headline structure above it@footnote{See also the
-variables @code{org-show-hierarchy-above}, @code{org-show-following-heading},
-@code{org-show-siblings}, and @code{org-show-entry-below} for detailed
-control on how much context is shown around each match.}. Just try it out
-and you will see immediately how it works.
+variable @code{org-show-context-detail} to decide 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
commands can be accessed through a dispatcher:
@@ -543,7 +548,8 @@ The Org homepage[fn:1] now looks a lot better than it used to.
[fn:1] The link is: http://orgmode.org
@end smallexample
-@noindent The following commands handle footnotes:
+@noindent
+The following commands handle footnotes:
@table @kbd
@item C-c C-x f
@@ -604,7 +610,8 @@ create the above table, you would only type
|-
@end smallexample
-@noindent and then press @key{TAB} to align the table and start filling in
+@noindent
+and then press @key{TAB} to align the table and start filling in
fields. Even faster would be to type @code{|Name|Phone|Age} followed by
@kbd{C-c @key{RET}}.
@@ -1068,7 +1075,8 @@ are checkboxes, toggling one of the children checkboxes will make the
parent checkbox reflect if none, some, or all of the children are
checked.
-@noindent The following commands work with checkboxes:
+@noindent
+The following commands work with checkboxes:
@table @kbd
@item C-c C-c
@@ -1176,7 +1184,8 @@ like:
(setq org-tag-alist '(("@@work" . ?w) ("@@home" . ?h) ("laptop" . ?l)))
@end smalllisp
-@noindent If the tag is only relevant to the file you are working on, then you
+@noindent
+If the tag is only relevant to the file you are working on, then you
can instead set the TAGS option line as:
@smallexample
@@ -1332,7 +1341,8 @@ timestamp can appear anywhere in the headline or body of an Org tree entry.
Its presence causes entries to be shown on specific dates in the agenda
(@pxref{Weekly/daily agenda}). We distinguish:
-@noindent @b{Plain timestamp; Event; Appointment}@*
+@noindent
+@b{Plain timestamp; Event; Appointment}@*
A simple timestamp just assigns a date/time to an item. This is just
like writing down an appointment or event in a paper agenda.
@@ -1343,7 +1353,8 @@ like writing down an appointment or event in a paper agenda.
<2006-11-02 Thu 20:00-22:00>
@end smallexample
-@noindent @b{Timestamp with repeater interval}@*
+@noindent
+@b{Timestamp with repeater interval}@*
A timestamp may contain a @emph{repeater interval}, indicating that it
applies not only on the given date, but again and again after a certain
interval of N days (d), weeks (w), months (m), or years (y). The
@@ -1353,7 +1364,8 @@ following will show up in the agenda every Wednesday:
<2007-05-16 Wed 12:30 +1w>
@end smallexample
-@noindent @b{Diary-style sexp entries}@*
+@noindent
+@b{Diary-style sexp entries}@*
For more complex date specifications, Org mode supports using the
special sexp diary entries implemented in the Emacs calendar/diary
package. For example
@@ -1362,14 +1374,16 @@ package. For example
<%%(diary-float t 4 2)>
@end smallexample
-@noindent @b{Time/Date range}@*
+@noindent
+@b{Time/Date range}@*
Two timestamps connected by @samp{--} denote a range.
@smallexample
** Meeting in Amsterdam
<2004-08-23 Mon>--<2004-08-26 Thu>
@end smallexample
-@noindent @b{Inactive timestamp}@*
+@noindent
+@b{Inactive timestamp}@*
Just like a plain timestamp, but with square brackets instead of
angular ones. These timestamps are inactive in the sense that they do
@emph{not} trigger an entry to show up in the agenda.
@@ -1421,7 +1435,8 @@ information on how exactly the date/time prompt works.
A timestamp may be preceded by special keywords to facilitate planning:
-@noindent @b{DEADLINE}@*
+@noindent
+@b{DEADLINE}@*
Meaning: the task (most likely a TODO item, though not necessarily) is supposed
to be finished on that date.
@table @kbd
@@ -1443,7 +1458,8 @@ until the entry is marked DONE. An example:
@end smallexample
-@noindent @b{SCHEDULED}@*
+@noindent
+@b{SCHEDULED}@*
Meaning: you are @i{planning to start working} on that task on the given
date@footnote{This is quite different from what is normally understood by
@i{scheduling a meeting}, which is done in Org-mode by just inserting a time
@@ -1498,7 +1514,7 @@ the resulting time in inserts it after the time range as @samp{=>
HH:MM}.
@item C-c C-x C-e
Update the effort estimate for the current clock task.
-@item C-c C-x C-x
+@item C-c C-x C-q
Cancel the current clock. This is useful if a clock was started by
mistake, or if you ended up working on something else.
@item C-c C-x C-j
@@ -1605,7 +1621,8 @@ use:
"* %?\nEntered on %U\n %i\n %a")))
@end smallexample
-@noindent In these entries, the first string is the key to reach the
+@noindent
+In these entries, the first string is the key to reach the
template, the second is a short description. Then follows the type of the
entry and a definition of the target location for storing the note. Finally,
the template itself, a string with %-escapes to fill in information based on
@@ -2169,10 +2186,14 @@ consisting of only dashes, and at least 5 of them.
@subheading Comment lines
Lines starting with zero or more whitespace characters followed by @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.
+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. The
+command below helps changing the comment status of a headline.
@table @kbd
@item C-c ;
@@ -2257,11 +2278,16 @@ include your @file{.emacs} file, you could use:
#+INCLUDE: "~/.emacs" src emacs-lisp
@end smallexample
@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. @kbd{C-c '} will visit the included file.
+The optional second and third parameter are the markup (i.e., @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. File-links
+will be interpreted as well:
+@smallexample
+#+INCLUDE: "./otherfile.org::#my_custom_id" :only-contents t
+@end smallexample
+@noindent
+@kbd{C-c '} will visit the included file.
@node Embedded @LaTeX{}, , Include files, Markup
@section Embedded @LaTeX{}
@@ -2281,7 +2307,8 @@ $a=+\sqrt@{2@}$ or $a=-\sqrt@{2@}$.
x=\sqrt@{b@}
\end@{equation@}
@end smallexample
-@noindent With
+@noindent
+With
@uref{http://orgmode.org/manual/LaTeX-fragments.html#LaTeX-fragments,special
setup}, @LaTeX{} snippets will be included as images when exporting to HTML.
@@ -2303,30 +2330,27 @@ that planning information can be incorporated into desktop calendars.
* ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding
* HTML export:: Exporting to HTML
* @LaTeX{} and PDF export:: Exporting to @LaTeX{}, and processing to PDF
-* iCalendar export:: Exporting to iCalendar
+* iCalendar export:: Exporting to iCalendar
@end menu
@node Export options, The export dispatcher, Exporting, Exporting
@section Export options
-The exporter recognizes special lines in the buffer which provide
-additional information. These lines may be put anywhere in the file.
-The whole set of lines can be inserted into the buffer with @kbd{C-c
-C-e t}.
+The exporter recognizes special lines in the buffer which provide additional
+information. These lines may be put anywhere in the file. The whole set of
+lines can be inserted into the buffer with @kbd{C-c C-e #}.
@table @kbd
-@item C-c C-e t
+@item C-c C-e #
Insert template with export options, see example below.
@end table
@smallexample
-#+TITLE: the title to be shown (default is the buffer name)
+#+TITLE: the title to be shown
#+AUTHOR: the author (default taken from @code{user-full-name})
#+DATE: a date, fixed, or an Org timestamp
#+EMAIL: his/her email address (default from @code{user-mail-address})
-#+DESCRIPTION: the page description, e.g.@: for the XHTML meta tag
-#+KEYWORDS: the page keywords, e.g.@: for the XHTML meta tag
-#+LANGUAGE: language for HTML, e.g.@: @samp{en} (@code{org-export-default-language})
+#+LANGUAGE: language, e.g.@: @samp{en} (@code{org-export-default-language})
#+OPTIONS: H:2 num:t toc:t \n:nil ::t |:t ^:t f:t tex:t ...
@end smallexample
@@ -2375,7 +2399,8 @@ the exported file use either
@smallexample
#+HTML: Literal HTML code for export
@end smallexample
-@noindent or
+@noindent
+or
@smallexample
#+BEGIN_HTML
All lines between these markers are exported literally
diff --git a/doc/texinfo.tex b/doc/texinfo.tex
index 0b958d3..5f5818d 100644
--- a/doc/texinfo.tex
+++ b/doc/texinfo.tex
@@ -3,11 +3,11 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2012-01-03.18}
+\def\texinfoversion{2013-09-11.11}
%
-% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
+% Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-% 2007, 2008-2013 Free Software Foundation, Inc.
+% 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
%
% This texinfo.tex file is free software: you can redistribute it and/or
% modify it under the terms of the GNU General Public License as
@@ -24,13 +24,14 @@
%
% As a special exception, when this file is read by TeX when processing
% a Texinfo source document, you may use the result without
-% restriction. (This has been our intent since Texinfo was invented.)
+% restriction. This Exception is an additional permission under section 7
+% of the GNU General Public License, version 3 ("GPLv3").
%
% Please try the latest version of texinfo.tex before submitting bug
% reports; you can get the latest version from:
-% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
-% ftp://tug.org/tex/texinfo.tex
-% (and all CTAN mirrors, see http://www.ctan.org).
+% http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or
+% http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or
+% http://www.gnu.org/software/texinfo/ (the Texinfo home page)
% The texinfo.tex in any given distribution could well be out
% of date, so if that's what you're using, please check.
%
@@ -65,7 +66,6 @@
\everyjob{\message{[Texinfo version \texinfoversion]}%
\catcode`+=\active \catcode`\_=\active}
-
\chardef\other=12
% We never want plain's \outer definition of \+ in Texinfo.
@@ -93,11 +93,13 @@
\let\ptexnewwrite\newwrite
\let\ptexnoindent=\noindent
\let\ptexplus=+
+\let\ptexraggedright=\raggedright
\let\ptexrbrace=\}
\let\ptexslash=\/
\let\ptexstar=\*
\let\ptext=\t
\let\ptextop=\top
+{\catcode`\'=\active \global\let\ptexquoteright'}% active in plain's math mode
% If this character appears in an error message or help string, it
% starts a new line in the output.
@@ -115,10 +117,11 @@
% Set up fixed words for English if not already set.
\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi
\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi
+\ifx\putworderror\undefined \gdef\putworderror{error}\fi
\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi
\ifx\putwordin\undefined \gdef\putwordin{in}\fi
-\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
-\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
+\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
+\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi
\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi
@@ -157,15 +160,18 @@
\def\spaceisspace{\catcode`\ =\spacecat}
% sometimes characters are active, so we need control sequences.
+\chardef\ampChar = `\&
\chardef\colonChar = `\:
\chardef\commaChar = `\,
\chardef\dashChar = `\-
\chardef\dotChar = `\.
\chardef\exclamChar= `\!
+\chardef\hashChar = `\#
\chardef\lquoteChar= `\`
\chardef\questChar = `\?
\chardef\rquoteChar= `\'
\chardef\semiChar = `\;
+\chardef\slashChar = `\/
\chardef\underChar = `\_
% Ignore a token.
@@ -196,36 +202,7 @@
% that mark overfull boxes (in case you have decided
% that the text looks ok even though it passes the margin).
%
-\def\finalout{\overfullrule=0pt}
-
-% @| inserts a changebar to the left of the current line. It should
-% surround any changed text. This approach does *not* work if the
-% change spans more than two lines of output. To handle that, we would
-% have adopt a much more difficult approach (putting marks into the main
-% vertical list for the beginning and end of each change).
-%
-\def\|{%
- % \vadjust can only be used in horizontal mode.
- \leavevmode
- %
- % Append this vertical mode material after the current line in the output.
- \vadjust{%
- % We want to insert a rule with the height and depth of the current
- % leading; that is exactly what \strutbox is supposed to record.
- \vskip-\baselineskip
- %
- % \vadjust-items are inserted at the left edge of the type. So
- % the \llap here moves out into the left-hand margin.
- \llap{%
- %
- % For a thicker or thinner bar, change the `1pt'.
- \vrule height\baselineskip width1pt
- %
- % This is the space between the bar and the text.
- \hskip 12pt
- }%
- }%
-}
+\def\finalout{\overfullrule=0pt }
% Sometimes it is convenient to have everything in the transcript file
% and nothing on the terminal. We don't just call \tracingall here,
@@ -243,7 +220,7 @@
\tracingmacros2
\tracingrestores1
\showboxbreadth\maxdimen \showboxdepth\maxdimen
- \ifx\eTeXversion\undefined\else % etex gives us more logging
+ \ifx\eTeXversion\thisisundefined\else % etex gives us more logging
\tracingscantokens1
\tracingifs1
\tracinggroups1
@@ -254,6 +231,13 @@
\errorcontextlines16
}%
+% @errormsg{MSG}. Do the index-like expansions on MSG, but if things
+% aren't perfect, it's not the end of the world, being an error message,
+% after all.
+%
+\def\errormsg{\begingroup \indexnofonts \doerrormsg}
+\def\doerrormsg#1{\errmessage{#1}}
+
% add check for \lastpenalty to plain's definitions. If the last thing
% we did was a \nobreak, we don't want to insert more space.
%
@@ -264,7 +248,6 @@
\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount
\removelastskip\penalty-200\bigskip\fi\fi}
-% For @cropmarks command.
% Do @cropmarks to get crop marks.
%
\newif\ifcropmarks
@@ -298,9 +281,9 @@
\toks6=\expandafter{\prevsectiondefs}%
\toks8=\expandafter{\lastcolordefs}%
\mark{%
- \the\toks0 \the\toks2
- \noexpand\or \the\toks4 \the\toks6
- \noexpand\else \the\toks8
+ \the\toks0 \the\toks2 % 0: top marks (\last...)
+ \noexpand\or \the\toks4 \the\toks6 % 1: bottom marks (default, \prev...)
+ \noexpand\else \the\toks8 % 2: color marks
}%
}
% \topmark doesn't work for the very first chapter (after the title
@@ -339,10 +322,13 @@
%
% Do this outside of the \shipout so @code etc. will be expanded in
% the headline as they should be, not taken literally (outputting ''code).
+ \def\commmonheadfootline{\let\hsize=\pagewidth \texinfochars}
+ %
\ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
- \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+ \global\setbox\headlinebox = \vbox{\commmonheadfootline \makeheadline}%
+ %
\ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi
- \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
+ \global\setbox\footlinebox = \vbox{\commmonheadfootline \makefootline}%
%
{%
% Have to do this stuff outside the \shipout because we want it to
@@ -355,7 +341,7 @@
% We don't want .vr (or whatever) entries like this:
% \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}}
% "\acronym" won't work when it's read back in;
- % it needs to be
+ % it needs to be
% {\code {{\tt \backslashcurfont }acronym}
\shipout\vbox{%
% Do this early so pdf references go to the beginning of the page.
@@ -574,7 +560,7 @@
}
\def\inenvironment#1{%
\ifx#1\empty
- out of any environment%
+ outside of any environment%
\else
in environment \expandafter\string#1%
\fi
@@ -586,7 +572,7 @@
\parseargdef\end{%
\if 1\csname iscond.#1\endcsname
\else
- % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03
+ % The general wording of \badenverr may not be ideal.
\expandafter\checkenv\csname#1\endcsname
\csname E#1\endcsname
\endgroup
@@ -596,85 +582,6 @@
\newhelp\EMsimple{Press RETURN to continue.}
-%% Simple single-character @ commands
-
-% @@ prints an @
-% Kludge this until the fonts are right (grr).
-\def\@{{\tt\char64}}
-
-% This is turned off because it was never documented
-% and you can use @w{...} around a quote to suppress ligatures.
-%% Define @` and @' to be the same as ` and '
-%% but suppressing ligatures.
-%\def\`{{`}}
-%\def\'{{'}}
-
-% Used to generate quoted braces.
-\def\mylbrace {{\tt\char123}}
-\def\myrbrace {{\tt\char125}}
-\let\{=\mylbrace
-\let\}=\myrbrace
-\begingroup
- % Definitions to produce \{ and \} commands for indices,
- % and @{ and @} for the aux/toc files.
- \catcode`\{ = \other \catcode`\} = \other
- \catcode`\[ = 1 \catcode`\] = 2
- \catcode`\! = 0 \catcode`\\ = \other
- !gdef!lbracecmd[\{]%
- !gdef!rbracecmd[\}]%
- !gdef!lbraceatcmd[@{]%
- !gdef!rbraceatcmd[@}]%
-!endgroup
-
-% @comma{} to avoid , parsing problems.
-\let\comma = ,
-
-% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
-% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
-\let\, = \c
-\let\dotaccent = \.
-\def\ringaccent#1{{\accent23 #1}}
-\let\tieaccent = \t
-\let\ubaraccent = \b
-\let\udotaccent = \d
-
-% Other special characters: @questiondown @exclamdown @ordf @ordm
-% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
-\def\questiondown{?`}
-\def\exclamdown{!`}
-\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}}
-\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}}
-
-% Dotless i and dotless j, used for accents.
-\def\imacro{i}
-\def\jmacro{j}
-\def\dotless#1{%
- \def\temp{#1}%
- \ifx\temp\imacro \ifmmode\imath \else\ptexi \fi
- \else\ifx\temp\jmacro \ifmmode\jmath \else\j \fi
- \else \errmessage{@dotless can be used only with i or j}%
- \fi\fi
-}
-
-% The \TeX{} logo, as in plain, but resetting the spacing so that a
-% period following counts as ending a sentence. (Idea found in latex.)
-%
-\edef\TeX{\TeX \spacefactor=1000 }
-
-% @LaTeX{} logo. Not quite the same results as the definition in
-% latex.ltx, since we use a different font for the raised A; it's most
-% convenient for us to use an explicitly smaller font, rather than using
-% the \scriptstyle font (since we don't reset \scriptstyle and
-% \scriptscriptstyle).
-%
-\def\LaTeX{%
- L\kern-.36em
- {\setbox0=\hbox{T}%
- \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}%
- \kern-.15em
- \TeX
-}
-
% Be sure we're in horizontal mode when doing a tie, since we make space
% equivalent to this in @example-like environments. Otherwise, a space
% at the beginning of a line will start with \penalty -- and
@@ -691,7 +598,7 @@
\def\:{\spacefactor=1000 }
% @* forces a line break.
-\def\*{\hfil\break\hbox{}\ignorespaces}
+\def\*{\unskip\hfil\break\hbox{}\ignorespaces}
% @/ allows a line break.
\let\/=\allowbreak
@@ -706,7 +613,7 @@
\def\?{?\spacefactor=\endofsentencespacefactor\space}
% @frenchspacing on|off says whether to put extra space after punctuation.
-%
+%
\def\onword{on}
\def\offword{off}
%
@@ -716,7 +623,7 @@
\else\ifx\temp\offword \plainnonfrenchspacing
\else
\errhelp = \EMsimple
- \errmessage{Unknown @frenchspacing option `\temp', must be on/off}%
+ \errmessage{Unknown @frenchspacing option `\temp', must be on|off}%
\fi\fi
}
@@ -798,15 +705,6 @@ where each line of input produces a line of output.}
\newdimen\mil \mil=0.001in
-% Old definition--didn't work.
-%\parseargdef\need{\par %
-%% This method tries to make TeX break the page naturally
-%% if the depth of the box does not fit.
-%{\baselineskip=0pt%
-%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
-%\prevdepth=-1000pt
-%}}
-
\parseargdef\need{%
% Ensure vertical mode, so we don't make a big box in the middle of a
% paragraph.
@@ -870,7 +768,7 @@ where each line of input produces a line of output.}
% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current
% paragraph. For more general purposes, use the \margin insertion
-% class. WHICH is `l' or `r'.
+% class. WHICH is `l' or `r'. Not documented, written for gawk manual.
%
\newskip\inmarginspacing \inmarginspacing=1cm
\def\strutdepth{\dp\strutbox}
@@ -917,6 +815,36 @@ where each line of input produces a line of output.}
\temp
}
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change). This command
+% is not documented, not supported, and doesn't work.
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
% @include FILE -- \input text of FILE.
%
\def\include{\parseargusing\filenamecatcodes\includezzz}
@@ -926,6 +854,8 @@ where each line of input produces a line of output.}
{%
\makevalueexpandable % we want to expand any @value in FILE.
\turnoffactive % and allow special characters in the expansion
+ \indexnofonts % Allow `@@' and other weird things in file names.
+ \wlog{texinfo.tex: doing @include of #1^^J}%
\edef\temp{\noexpand\input #1 }%
%
% This trickery is to read FILE outside of a group, in case it makes
@@ -944,6 +874,8 @@ where each line of input produces a line of output.}
\catcode`>=\other
\catcode`+=\other
\catcode`-=\other
+ \catcode`\`=\other
+ \catcode`\'=\other
}
\def\pushthisfilestack{%
@@ -959,7 +891,7 @@ where each line of input produces a line of output.}
\def\popthisfilestack{\errthisfilestackempty}
\def\errthisfilestackempty{\errmessage{Internal error:
the stack of filenames is empty.}}
-
+%
\def\thisfile{}
% @center line
@@ -967,36 +899,46 @@ where each line of input produces a line of output.}
%
\parseargdef\center{%
\ifhmode
- \let\next\centerH
+ \let\centersub\centerH
\else
- \let\next\centerV
+ \let\centersub\centerV
\fi
- \next{\hfil \ignorespaces#1\unskip \hfil}%
+ \centersub{\hfil \ignorespaces#1\unskip \hfil}%
+ \let\centersub\relax % don't let the definition persist, just in case
}
-\def\centerH#1{%
- {%
- \hfil\break
- \advance\hsize by -\leftskip
- \advance\hsize by -\rightskip
- \line{#1}%
- \break
- }%
+\def\centerH#1{{%
+ \hfil\break
+ \advance\hsize by -\leftskip
+ \advance\hsize by -\rightskip
+ \line{#1}%
+ \break
+}}
+%
+\newcount\centerpenalty
+\def\centerV#1{%
+ % The idea here is the same as in \startdefun, \cartouche, etc.: if
+ % @center is the first thing after a section heading, we need to wipe
+ % out the negative parskip inserted by \sectionheading, but still
+ % prevent a page break here.
+ \centerpenalty = \lastpenalty
+ \ifnum\centerpenalty>10000 \vskip\parskip \fi
+ \ifnum\centerpenalty>9999 \penalty\centerpenalty \fi
+ \line{\kern\leftskip #1\kern\rightskip}%
}
-\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}}
% @sp n outputs n lines of vertical space
-
+%
\parseargdef\sp{\vskip #1\baselineskip}
% @comment ...line which is ignored...
% @c is the same as @comment
% @ignore ... @end ignore is another way to write a comment
-
+%
\def\comment{\begingroup \catcode`\^^M=\other%
\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
\commentxxx}
{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
-
+%
\let\c=\comment
% @paragraphindent NCHARS
@@ -1089,107 +1031,6 @@ where each line of input produces a line of output.}
}
-% @asis just yields its argument. Used with @table, for example.
-%
-\def\asis#1{#1}
-
-% @math outputs its argument in math mode.
-%
-% One complication: _ usually means subscripts, but it could also mean
-% an actual _ character, as in @math{@var{some_variable} + 1}. So make
-% _ active, and distinguish by seeing if the current family is \slfam,
-% which is what @var uses.
-{
- \catcode`\_ = \active
- \gdef\mathunderscore{%
- \catcode`\_=\active
- \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
- }
-}
-% Another complication: we want \\ (and @\) to output a \ character.
-% FYI, plain.tex uses \\ as a temporary control sequence (why?), but
-% this is not advertised and we don't care. Texinfo does not
-% otherwise define @\.
-%
-% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
-\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
-%
-\def\math{%
- \tex
- \mathunderscore
- \let\\ = \mathbackslash
- \mathactive
- % make the texinfo accent commands work in math mode
- \let\"=\ddot
- \let\'=\acute
- \let\==\bar
- \let\^=\hat
- \let\`=\grave
- \let\u=\breve
- \let\v=\check
- \let\~=\tilde
- \let\dotaccent=\dot
- $\finishmath
-}
-\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex.
-
-% Some active characters (such as <) are spaced differently in math.
-% We have to reset their definitions in case the @math was an argument
-% to a command which sets the catcodes (such as @item or @section).
-%
-{
- \catcode`^ = \active
- \catcode`< = \active
- \catcode`> = \active
- \catcode`+ = \active
- \gdef\mathactive{%
- \let^ = \ptexhat
- \let< = \ptexless
- \let> = \ptexgtr
- \let+ = \ptexplus
- }
-}
-
-% Some math mode symbols.
-\def\bullet{$\ptexbullet$}
-\def\geq{\ifmmode \ge\else $\ge$\fi}
-\def\leq{\ifmmode \le\else $\le$\fi}
-\def\minus{\ifmmode -\else $-$\fi}
-
-% @dots{} outputs an ellipsis using the current font.
-% We do .5em per period so that it has the same spacing in the cm
-% typewriter fonts as three actual period characters; on the other hand,
-% in other typewriter fonts three periods are wider than 1.5em. So do
-% whichever is larger.
-%
-\def\dots{%
- \leavevmode
- \setbox0=\hbox{...}% get width of three periods
- \ifdim\wd0 > 1.5em
- \dimen0 = \wd0
- \else
- \dimen0 = 1.5em
- \fi
- \hbox to \dimen0{%
- \hskip 0pt plus.25fil
- .\hskip 0pt plus1fil
- .\hskip 0pt plus1fil
- .\hskip 0pt plus.5fil
- }%
-}
-
-% @enddots{} is an end-of-sentence ellipsis.
-%
-\def\enddots{%
- \dots
- \spacefactor=\endofsentencespacefactor
-}
-
-% @comma{} is so commas can be inserted into text without messing up
-% Texinfo's parsing.
-%
-\let\comma = ,
-
% @refill is a no-op.
\let\refill=\relax
@@ -1254,9 +1095,8 @@ where each line of input produces a line of output.}
\newif\ifpdfmakepagedest
% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1
-% can be set). So we test for \relax and 0 as well as \undefined,
-% borrowed from ifpdf.sty.
-\ifx\pdfoutput\undefined
+% can be set). So we test for \relax and 0 as well as being undefined.
+\ifx\pdfoutput\thisisundefined
\else
\ifx\pdfoutput\relax
\else
@@ -1271,50 +1111,24 @@ where each line of input produces a line of output.}
% for display in the outlines, and in other places. Thus, we have to
% double any backslashes. Otherwise, a name like "\node" will be
% interpreted as a newline (\n), followed by o, d, e. Not good.
-% http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html
-% (and related messages, the final outcome is that it is up to the TeX
-% user to double the backslashes and otherwise make the string valid, so
-% that's what we do).
-
-% double active backslashes.
-%
-{\catcode`\@=0 \catcode`\\=\active
- @gdef@activebackslashdouble{%
- @catcode`@\=@active
- @let\=@doublebackslash}
-}
-
-% To handle parens, we must adopt a different approach, since parens are
-% not active characters. hyperref.dtx (which has the same problem as
-% us) handles it with this amazing macro to replace tokens, with minor
-% changes for Texinfo. It is included here under the GPL by permission
-% from the author, Heiko Oberdiek.
-%
-% #1 is the tokens to replace.
-% #2 is the replacement.
-% #3 is the control sequence with the string.
-%
-\def\HyPsdSubst#1#2#3{%
- \def\HyPsdReplace##1#1##2\END{%
- ##1%
- \ifx\\##2\\%
- \else
- #2%
- \HyReturnAfterFi{%
- \HyPsdReplace##2\END
- }%
- \fi
- }%
- \xdef#3{\expandafter\HyPsdReplace#3#1\END}%
-}
-\long\def\HyReturnAfterFi#1\fi{\fi#1}
-
-% #1 is a control sequence in which to do the replacements.
-\def\backslashparens#1{%
- \xdef#1{#1}% redefine it as its expansion; the definition is simply
- % \lastnode when called from \setref -> \pdfmkdest.
- \HyPsdSubst{(}{\realbackslash(}{#1}%
- \HyPsdSubst{)}{\realbackslash)}{#1}%
+%
+% See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and
+% related messages. The final outcome is that it is up to the TeX user
+% to double the backslashes and otherwise make the string valid, so
+% that's what we do. pdftex 1.30.0 (ca.2005) introduced a primitive to
+% do this reliably, so we use it.
+
+% #1 is a control sequence in which to do the replacements,
+% which we \xdef.
+\def\txiescapepdf#1{%
+ \ifx\pdfescapestring\thisisundefined
+ % No primitive available; should we give a warning or log?
+ % Many times it won't matter.
+ \else
+ % The expandable \pdfescapestring primitive escapes parentheses,
+ % backslashes, and other special chars.
+ \xdef#1{\pdfescapestring{#1}}%
+ \fi
}
\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images
@@ -1324,11 +1138,17 @@ output) for that.)}
\ifpdf
%
- % Color manipulation macros based on pdfcolor.tex.
- \def\cmykDarkRed{0.28 1 1 0.35}
- \def\cmykBlack{0 0 0 1}
+ % Color manipulation macros based on pdfcolor.tex,
+ % except using rgb instead of cmyk; the latter is said to render as a
+ % very dark gray on-screen and a very dark halftone in print, instead
+ % of actual black.
+ \def\rgbDarkRed{0.50 0.09 0.12}
+ \def\rgbBlack{0 0 0}
+ %
+ % k sets the color for filling (usual text, etc.);
+ % K sets the color for stroking (thin rules, e.g., normal _'s).
+ \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}}
%
- \def\pdfsetcolor#1{\pdfliteral{#1 k}}
% Set color, and create a mark which defines \thiscolor accordingly,
% so that \makeheadline knows which color to restore.
\def\setcolor#1{%
@@ -1337,7 +1157,7 @@ output) for that.)}
\pdfsetcolor{#1}%
}
%
- \def\maincolor{\cmykBlack}
+ \def\maincolor{\rgbBlack}
\pdfsetcolor{\maincolor}
\edef\thiscolor{\maincolor}
\def\lastcolordefs{}
@@ -1367,32 +1187,34 @@ output) for that.)}
%
% #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto).
\def\dopdfimage#1#2#3{%
- \def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}%
- \def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}%
+ \def\pdfimagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}%
+ \def\pdfimageheight{#3}\setbox2 = \hbox{\ignorespaces #3}%
%
- % pdftex (and the PDF format) support .png, .jpg, .pdf (among
- % others). Let's try in that order.
+ % pdftex (and the PDF format) support .pdf, .png, .jpg (among
+ % others). Let's try in that order, PDF first since if
+ % someone has a scalable image, presumably better to use that than a
+ % bitmap.
\let\pdfimgext=\empty
\begingroup
- \openin 1 #1.png \ifeof 1
- \openin 1 #1.jpg \ifeof 1
- \openin 1 #1.jpeg \ifeof 1
- \openin 1 #1.JPG \ifeof 1
- \openin 1 #1.pdf \ifeof 1
- \openin 1 #1.PDF \ifeof 1
+ \openin 1 #1.pdf \ifeof 1
+ \openin 1 #1.PDF \ifeof 1
+ \openin 1 #1.png \ifeof 1
+ \openin 1 #1.jpg \ifeof 1
+ \openin 1 #1.jpeg \ifeof 1
+ \openin 1 #1.JPG \ifeof 1
\errhelp = \nopdfimagehelp
\errmessage{Could not find image file #1 for pdf}%
- \else \gdef\pdfimgext{PDF}%
+ \else \gdef\pdfimgext{JPG}%
\fi
- \else \gdef\pdfimgext{pdf}%
+ \else \gdef\pdfimgext{jpeg}%
\fi
- \else \gdef\pdfimgext{JPG}%
+ \else \gdef\pdfimgext{jpg}%
\fi
- \else \gdef\pdfimgext{jpeg}%
+ \else \gdef\pdfimgext{png}%
\fi
- \else \gdef\pdfimgext{jpg}%
+ \else \gdef\pdfimgext{PDF}%
\fi
- \else \gdef\pdfimgext{png}%
+ \else \gdef\pdfimgext{pdf}%
\fi
\closein 1
\endgroup
@@ -1404,8 +1226,8 @@ output) for that.)}
\else
\immediate\pdfximage
\fi
- \ifdim \wd0 >0pt width \imagewidth \fi
- \ifdim \wd2 >0pt height \imageheight \fi
+ \ifdim \wd0 >0pt width \pdfimagewidth \fi
+ \ifdim \wd2 >0pt height \pdfimageheight \fi
\ifnum\pdftexversion<13
#1.\pdfimgext
\else
@@ -1420,10 +1242,9 @@ output) for that.)}
% such as \, aren't expanded when present in a section title.
\indexnofonts
\turnoffactive
- \activebackslashdouble
\makevalueexpandable
\def\pdfdestname{#1}%
- \backslashparens\pdfdestname
+ \txiescapepdf\pdfdestname
\safewhatsit{\pdfdest name{\pdfdestname} xyz}%
}}
%
@@ -1432,8 +1253,8 @@ output) for that.)}
%
% by default, use a color that is dark enough to print on paper as
% nearly black, but still distinguishable for online viewing.
- \def\urlcolor{\cmykDarkRed}
- \def\linkcolor{\cmykDarkRed}
+ \def\urlcolor{\rgbDarkRed}
+ \def\linkcolor{\rgbDarkRed}
\def\endlink{\setcolor{\maincolor}\pdfendlink}
%
% Adding outlines to PDF; macros for calculating structure of outlines
@@ -1455,29 +1276,24 @@ output) for that.)}
% page number. We could generate a destination for the section
% text in the case where a section has no node, but it doesn't
% seem worth the trouble, since most documents are normally structured.
- \def\pdfoutlinedest{#3}%
+ \edef\pdfoutlinedest{#3}%
\ifx\pdfoutlinedest\empty
\def\pdfoutlinedest{#4}%
\else
- % Doubled backslashes in the name.
- {\activebackslashdouble \xdef\pdfoutlinedest{#3}%
- \backslashparens\pdfoutlinedest}%
+ \txiescapepdf\pdfoutlinedest
\fi
%
- % Also double the backslashes in the display string.
- {\activebackslashdouble \xdef\pdfoutlinetext{#1}%
- \backslashparens\pdfoutlinetext}%
+ % Also escape PDF chars in the display string.
+ \edef\pdfoutlinetext{#1}%
+ \txiescapepdf\pdfoutlinetext
%
\pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}%
}
%
\def\pdfmakeoutlines{%
\begingroup
- % Thanh's hack / proper braces in bookmarks
- \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
- \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
- %
% Read toc silently, to get counts of subentries for \pdfoutline.
+ \def\partentry##1##2##3##4{}% ignore parts in the outlines
\def\numchapentry##1##2##3##4{%
\def\thischapnum{##2}%
\def\thissecnum{0}%
@@ -1531,25 +1347,41 @@ output) for that.)}
% Latin 2 (0xea) gets translated to a | character. Info from
% Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100.
%
- % xx to do this right, we have to translate 8-bit characters to
- % their "best" equivalent, based on the @documentencoding. Right
- % now, I guess we'll just let the pdf reader have its way.
+ % TODO this right, we have to translate 8-bit characters to
+ % their "best" equivalent, based on the @documentencoding. Too
+ % much work for too little return. Just use the ASCII equivalents
+ % we use for the index sort strings.
+ %
\indexnofonts
\setupdatafile
+ % We can have normal brace characters in the PDF outlines, unlike
+ % Texinfo index files. So set that up.
+ \def\{{\lbracecharliteral}%
+ \def\}{\rbracecharliteral}%
\catcode`\\=\active \otherbackslash
\input \tocreadfilename
\endgroup
}
+ {\catcode`[=1 \catcode`]=2
+ \catcode`{=\other \catcode`}=\other
+ \gdef\lbracecharliteral[{]%
+ \gdef\rbracecharliteral[}]%
+ ]
%
\def\skipspaces#1{\def\PP{#1}\def\D{|}%
\ifx\PP\D\let\nextsp\relax
\else\let\nextsp\skipspaces
- \ifx\p\space\else\addtokens{\filename}{\PP}%
- \advance\filenamelength by 1
- \fi
+ \addtokens{\filename}{\PP}%
+ \advance\filenamelength by 1
\fi
\nextsp}
- \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
+ \def\getfilename#1{%
+ \filenamelength=0
+ % If we don't expand the argument now, \skipspaces will get
+ % snagged on things like "@value{foo}".
+ \edef\temp{#1}%
+ \expandafter\skipspaces\temp|\relax
+ }
\ifnum\pdftexversion < 14
\let \startlink \pdfannotlink
\else
@@ -1562,11 +1394,15 @@ output) for that.)}
% tried to figure out what each command should do in the context
% of @url. for now, just make @/ a no-op, that's the only one
% people have actually reported a problem with.
- %
+ %
\normalturnoffactive
\def\@{@}%
\let\/=\empty
\makevalueexpandable
+ % do we want to go so far as to use \indexnofonts instead of just
+ % special-casing \var here?
+ \def\var##1{##1}%
+ %
\leavevmode\setcolor{\urlcolor}%
\startlink attr{/Border [0 0 0]}%
user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
@@ -1597,6 +1433,7 @@ output) for that.)}
\setcolor{\linkcolor}#1\endlink}
\def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
\else
+ % non-pdf mode
\let\pdfmkdest = \gobble
\let\pdfurl = \gobble
\let\endlink = \relax
@@ -1627,6 +1464,10 @@ output) for that.)}
\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf}
\def\tt{\fam=\ttfam \setfontstyle{tt}}
+% Unfortunately, we have to override this for titles and the like, since
+% in those cases "rm" is bold. Sigh.
+\def\rmisbold{\rm\def\curfontstyle{bf}}
+
% Texinfo sort of supports the sans serif font style, which plain TeX does not.
% So we set up a \sf.
\newfam\sffam
@@ -1637,9 +1478,6 @@ output) for that.)}
\def\ttsl{\setfontstyle{ttsl}}
-% Default leading.
-\newdimen\textleading \textleading = 13.2pt
-
% Set the baselineskip to #1, and the lineskip and strut size
% correspondingly. There is no deep meaning behind these magic numbers
% used as factors; they just match (closely enough) what Knuth defined.
@@ -1651,6 +1489,7 @@ output) for that.)}
% can get a sort of poor man's double spacing by redefining this.
\def\baselinefactor{1}
%
+\newdimen\textleading
\def\setleading#1{%
\dimen0 = #1\relax
\normalbaselineskip = \baselinefactor\dimen0
@@ -1672,7 +1511,7 @@ output) for that.)}
% if we are producing pdf, and we have \pdffontattr, then define cmaps.
% (\pdffontattr was introduced many years ago, but people still run
% older pdftex's; it's easy to conditionalize, so we do.)
-\ifpdf \ifx\pdffontattr\undefined \else
+\ifpdf \ifx\pdffontattr\thisisundefined \else
\begingroup
\catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
\catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
@@ -1923,28 +1762,34 @@ end
\fi\fi
-% Set the font macro #1 to the font named #2, adding on the
-% specified font prefix (normally `cm').
+% Set the font macro #1 to the font named \fontprefix#2.
% #3 is the font's design size, #4 is a scale factor, #5 is the CMap
-% encoding (currently only OT1, OT1IT and OT1TT are allowed, pass
-% empty to omit).
+% encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit).
+% Example:
+% #1 = \textrm
+% #2 = \rmshape
+% #3 = 10
+% #4 = \mainmagstep
+% #5 = OT1
+%
\def\setfont#1#2#3#4#5{%
\font#1=\fontprefix#2#3 scaled #4
\csname cmap#5\endcsname#1%
}
% This is what gets called when #5 of \setfont is empty.
\let\cmap\gobble
-% emacs-page end of cmaps
+%
+% (end of cmaps)
% Use cm as the default font prefix.
% To specify the font prefix, you must define \fontprefix
% before you read in texinfo.tex.
-\ifx\fontprefix\undefined
+\ifx\fontprefix\thisisundefined
\def\fontprefix{cm}
\fi
% Support font families that don't use the same naming scheme as CM.
\def\rmshape{r}
-\def\rmbshape{bx} %where the normal face is bold
+\def\rmbshape{bx} % where the normal face is bold
\def\bfshape{b}
\def\bxshape{bx}
\def\ttshape{tt}
@@ -1959,9 +1804,8 @@ end
\def\scshape{csc}
\def\scbshape{csc}
-% Definitions for a main text size of 11pt. This is the default in
-% Texinfo.
-%
+% Definitions for a main text size of 11pt. (The default in Texinfo.)
+%
\def\definetextfontsizexi{%
% Text fonts (11.2pt, magstep1).
\def\textnominalsize{11pt}
@@ -2024,8 +1868,6 @@ end
\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
\font\titlei=cmmi12 scaled \magstep3
\font\titlesy=cmsy10 scaled \magstep4
-\def\authorrm{\secrm}
-\def\authortt{\sectt}
\def\titleecsize{2074}
% Chapter (and unnumbered) fonts (17.28pt).
@@ -2084,17 +1926,17 @@ end
\font\reducedsy=cmsy10
\def\reducedecsize{1000}
-% reset the current fonts
-\textfonts
+\textleading = 13.2pt % line spacing for 11pt CM
+\textfonts % reset the current fonts
\rm
-} % end of 11pt text font size definitions
+} % end of 11pt text font size definitions, \definetextfontsizexi
% Definitions to make the main text be 10pt Computer Modern, with
% section, chapter, etc., sizes following suit. This is for the GNU
% Press printing of the Emacs 22 manual. Maybe other manuals in the
% future. Used with @smallbook, which sets the leading to 12pt.
-%
+%
\def\definetextfontsizex{%
% Text fonts (10pt).
\def\textnominalsize{10pt}
@@ -2157,8 +1999,6 @@ end
\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
\font\titlei=cmmi12 scaled \magstep3
\font\titlesy=cmsy10 scaled \magstep4
-\def\authorrm{\secrm}
-\def\authortt{\sectt}
\def\titleecsize{2074}
% Chapter fonts (14.4pt).
@@ -2185,7 +2025,7 @@ end
\setfont\secsf\sfbshape{12}{1000}{OT1}
\let\secbf\secrm
\setfont\secsc\scbshape{10}{\magstep1}{OT1}
-\font\seci=cmmi12
+\font\seci=cmmi12
\font\secsy=cmsy10 scaled \magstep1
\def\sececsize{1200}
@@ -2217,29 +2057,28 @@ end
\font\reducedsy=cmsy9
\def\reducedecsize{0900}
-% reduce space between paragraphs
-\divide\parskip by 2
-
-% reset the current fonts
-\textfonts
+\divide\parskip by 2 % reduce space between paragraphs
+\textleading = 12pt % line spacing for 10pt CM
+\textfonts % reset the current fonts
\rm
-} % end of 10pt text font size definitions
+} % end of 10pt text font size definitions, \definetextfontsizex
% We provide the user-level command
% @fonttextsize 10
% (or 11) to redefine the text font size. pt is assumed.
-%
-\def\xword{10}
+%
\def\xiword{11}
+\def\xword{10}
+\def\xwordpt{10pt}
%
\parseargdef\fonttextsize{%
\def\textsizearg{#1}%
- \wlog{doing @fonttextsize \textsizearg}%
+ %\wlog{doing @fonttextsize \textsizearg}%
%
% Set \globaldefs so that documents can use this inside @tex, since
% makeinfo 4.8 does not support it, but we need it nonetheless.
- %
+ %
\begingroup \globaldefs=1
\ifx\textsizearg\xword \definetextfontsizex
\else \ifx\textsizearg\xiword \definetextfontsizexi
@@ -2289,8 +2128,8 @@ end
\let\tenttsl=\titlettsl
\def\curfontsize{title}%
\def\lsize{chap}\def\lllsize{subsec}%
- \resetmathfonts \setleading{25pt}}
-\def\titlefont#1{{\titlefonts\rm #1}}
+ \resetmathfonts \setleading{27pt}}
+\def\titlefont#1{{\titlefonts\rmisbold #1}}
\def\chapfonts{%
\let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
\let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
@@ -2341,6 +2180,16 @@ end
\def\lsize{smaller}\def\lllsize{smaller}%
\resetmathfonts \setleading{9.5pt}}
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}{OT1}
+\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12
+\setfont\shortcontsl\slshape{12}{1000}{OT1}
+\setfont\shortconttt\ttshape{12}{1000}{OT1TT}
+
+% Define these just so they can be easily changed for other fonts.
+\def\angleleft{$\langle$}
+\def\angleright{$\rangle$}
+
% Set the fonts to use with the @small... environments.
\let\smallexamplefonts = \smallfonts
@@ -2354,53 +2203,215 @@ end
%
% By the way, for comparison, here's what fits with @example (10pt):
% 8.5x11=71 smallbook=60 a4=75 a5=58
-%
-% I wish the USA used A4 paper.
% --karl, 24jan03.
-
% Set up the default fonts, so we can use them for creating boxes.
%
\definetextfontsizexi
-% Define these so they can be easily changed for other fonts.
-\def\angleleft{$\langle$}
-\def\angleright{$\rangle$}
+
+\message{markup,}
+
+% Check if we are currently using a typewriter font. Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Markup style infrastructure. \defmarkupstylesetup\INITMACRO will
+% define and register \INITMACRO to be called on markup style changes.
+% \INITMACRO can check \currentmarkupstyle for the innermost
+% style and the set of \ifmarkupSTYLE switches for all styles
+% currently in effect.
+\newif\ifmarkupvar
+\newif\ifmarkupsamp
+\newif\ifmarkupkey
+%\newif\ifmarkupfile % @file == @samp.
+%\newif\ifmarkupoption % @option == @samp.
+\newif\ifmarkupcode
+\newif\ifmarkupkbd
+%\newif\ifmarkupenv % @env == @code.
+%\newif\ifmarkupcommand % @command == @code.
+\newif\ifmarkuptex % @tex (and part of @math, for now).
+\newif\ifmarkupexample
+\newif\ifmarkupverb
+\newif\ifmarkupverbatim
+
+\let\currentmarkupstyle\empty
+
+\def\setupmarkupstyle#1{%
+ \csname markup#1true\endcsname
+ \def\currentmarkupstyle{#1}%
+ \markupstylesetup
+}
+
+\let\markupstylesetup\empty
+
+\def\defmarkupstylesetup#1{%
+ \expandafter\def\expandafter\markupstylesetup
+ \expandafter{\markupstylesetup #1}%
+ \def#1%
+}
+
+% Markup style setup for left and right quotes.
+\defmarkupstylesetup\markupsetuplq{%
+ \expandafter\let\expandafter \temp
+ \csname markupsetuplq\currentmarkupstyle\endcsname
+ \ifx\temp\relax \markupsetuplqdefault \else \temp \fi
+}
+
+\defmarkupstylesetup\markupsetuprq{%
+ \expandafter\let\expandafter \temp
+ \csname markupsetuprq\currentmarkupstyle\endcsname
+ \ifx\temp\relax \markupsetuprqdefault \else \temp \fi
+}
+
+{
+\catcode`\'=\active
+\catcode`\`=\active
+
+\gdef\markupsetuplqdefault{\let`\lq}
+\gdef\markupsetuprqdefault{\let'\rq}
+
+\gdef\markupsetcodequoteleft{\let`\codequoteleft}
+\gdef\markupsetcodequoteright{\let'\codequoteright}
+}
+
+\let\markupsetuplqcode \markupsetcodequoteleft
+\let\markupsetuprqcode \markupsetcodequoteright
+%
+\let\markupsetuplqexample \markupsetcodequoteleft
+\let\markupsetuprqexample \markupsetcodequoteright
+%
+\let\markupsetuplqkbd \markupsetcodequoteleft
+\let\markupsetuprqkbd \markupsetcodequoteright
+%
+\let\markupsetuplqsamp \markupsetcodequoteleft
+\let\markupsetuprqsamp \markupsetcodequoteright
+%
+\let\markupsetuplqverb \markupsetcodequoteleft
+\let\markupsetuprqverb \markupsetcodequoteright
+%
+\let\markupsetuplqverbatim \markupsetcodequoteleft
+\let\markupsetuprqverbatim \markupsetcodequoteright
+
+% Allow an option to not use regular directed right quote/apostrophe
+% (char 0x27), but instead the undirected quote from cmtt (char 0x0d).
+% The undirected quote is ugly, so don't make it the default, but it
+% works for pasting with more pdf viewers (at least evince), the
+% lilypond developers report. xpdf does work with the regular 0x27.
+%
+\def\codequoteright{%
+ \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax
+ \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax
+ '%
+ \else \char'15 \fi
+ \else \char'15 \fi
+}
+%
+% and a similar option for the left quote char vs. a grave accent.
+% Modern fonts display ASCII 0x60 as a grave accent, so some people like
+% the code environments to do likewise.
+%
+\def\codequoteleft{%
+ \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax
+ \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax
+ % [Knuth] pp. 380,381,391
+ % \relax disables Spanish ligatures ?` and !` of \tt font.
+ \relax`%
+ \else \char'22 \fi
+ \else \char'22 \fi
+}
+
+% Commands to set the quote options.
+%
+\parseargdef\codequoteundirected{%
+ \def\temp{#1}%
+ \ifx\temp\onword
+ \expandafter\let\csname SETtxicodequoteundirected\endcsname
+ = t%
+ \else\ifx\temp\offword
+ \expandafter\let\csname SETtxicodequoteundirected\endcsname
+ = \relax
+ \else
+ \errhelp = \EMsimple
+ \errmessage{Unknown @codequoteundirected value `\temp', must be on|off}%
+ \fi\fi
+}
+%
+\parseargdef\codequotebacktick{%
+ \def\temp{#1}%
+ \ifx\temp\onword
+ \expandafter\let\csname SETtxicodequotebacktick\endcsname
+ = t%
+ \else\ifx\temp\offword
+ \expandafter\let\csname SETtxicodequotebacktick\endcsname
+ = \relax
+ \else
+ \errhelp = \EMsimple
+ \errmessage{Unknown @codequotebacktick value `\temp', must be on|off}%
+ \fi\fi
+}
+
+% [Knuth] pp. 380,381,391, disable Spanish ligatures ?` and !` of \tt font.
+\def\noligaturesquoteleft{\relax\lq}
% Count depth in font-changes, for error checks
\newcount\fontdepth \fontdepth=0
-% Fonts for short table of contents.
-\setfont\shortcontrm\rmshape{12}{1000}{OT1}
-\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12
-\setfont\shortcontsl\slshape{12}{1000}{OT1}
-\setfont\shortconttt\ttshape{12}{1000}{OT1TT}
+% Font commands.
-%% Add scribe-like font environments, plus @l for inline lisp (usually sans
-%% serif) and @ii for TeX italic
+% #1 is the font command (\sl or \it), #2 is the text to slant.
+% If we are in a monospaced environment, however, 1) always use \ttsl,
+% and 2) do not add an italic correction.
+\def\dosmartslant#1#2{%
+ \ifusingtt
+ {{\ttsl #2}\let\next=\relax}%
+ {\def\next{{#1#2}\futurelet\next\smartitaliccorrection}}%
+ \next
+}
+\def\smartslanted{\dosmartslant\sl}
+\def\smartitalic{\dosmartslant\it}
-% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
-% unless the following character is such as not to need one.
-\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else
- \ptexslash\fi\fi\fi}
-\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx}
-\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx}
+% Output an italic correction unless \next (presumed to be the following
+% character) is such as not to need one.
+\def\smartitaliccorrection{%
+ \ifx\next,%
+ \else\ifx\next-%
+ \else\ifx\next.%
+ \else\ifx\next\.%
+ \else\ifx\next\comma%
+ \else\ptexslash
+ \fi\fi\fi\fi\fi
+ \aftersmartic
+}
-% like \smartslanted except unconditionally uses \ttsl.
-% @var is set to this for defun arguments.
-\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx}
+% Unconditional use \ttsl, and no ic. @var is set to this for defuns.
+\def\ttslanted#1{{\ttsl #1}}
-% like \smartslanted except unconditionally use \sl. We never want
+% @cite is like \smartslanted except unconditionally use \sl. We never want
% ttsl for book titles, do we?
-\def\cite#1{{\sl #1}\futurelet\next\smartitalicx}
+\def\cite#1{{\sl #1}\futurelet\next\smartitaliccorrection}
+
+\def\aftersmartic{}
+\def\var#1{%
+ \let\saveaftersmartic = \aftersmartic
+ \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}%
+ \smartslanted{#1}%
+}
\let\i=\smartitalic
\let\slanted=\smartslanted
-\let\var=\smartslanted
\let\dfn=\smartslanted
\let\emph=\smartitalic
-% @b, explicit bold.
+% Explicit font changes: @r, @sc, undocumented @ii.
+\def\r#1{{\rm #1}} % roman font
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+% @b, explicit bold. Also @strong.
\def\b#1{{\bf #1}}
\let\strong=\b
@@ -2432,30 +2443,21 @@ end
\catcode`@=\other
\def\endofsentencespacefactor{3000}% default
+% @t, explicit typewriter.
\def\t#1{%
{\tt \rawbackslash \plainfrenchspacing #1}%
\null
}
-\def\samp#1{`\tclose{#1}'\null}
-\setfont\keyrm\rmshape{8}{1000}{OT1}
-\font\keysy=cmsy9
-\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
- \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
- \vbox{\hrule\kern-0.4pt
- \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
- \kern-0.4pt\hrule}%
- \kern-.06em\raise0.4pt\hbox{\angleright}}}}
-\def\key #1{{\nohyphenation \uppercase{#1}}\null}
-% The old definition, with no lozenge:
-%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
-\def\ctrl #1{{\tt \rawbackslash \hat}#1}
-% @file, @option are the same as @samp.
-\let\file=\samp
-\let\option=\samp
+% @samp.
+\def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}}
+
+% @indicateurl is \samp, that is, with quotes.
+\let\indicateurl=\samp
-% @code is a modification of @t,
-% which makes spaces the same size as normal in the surrounding text.
+% @code (and similar) prints in typewriter, but with spaces the same
+% size as normal in the surrounding text, without hyphenation, etc.
+% This is a subroutine for that.
\def\tclose#1{%
{%
% Change normal interword space to be same as for the current font.
@@ -2474,40 +2476,63 @@ end
\plainfrenchspacing
#1%
}%
- \null
+ \null % reset spacefactor to 1000
}
% We *must* turn on hyphenation at `-' and `_' in @code.
+% (But see \codedashfinish below.)
% Otherwise, it is too hard to avoid overfull hboxes
% in the Emacs manual, the Library manual, etc.
-
+%
% Unfortunately, TeX uses one parameter (\hyphenchar) to control
% both hyphenation at - and hyphenation within words.
% We must therefore turn them both off (\tclose does that)
-% and arrange explicitly to hyphenate at a dash.
-% -- rms.
+% and arrange explicitly to hyphenate at a dash. -- rms.
{
\catcode`\-=\active \catcode`\_=\active
\catcode`\'=\active \catcode`\`=\active
+ \global\let'=\rq \global\let`=\lq % default definitions
%
\global\def\code{\begingroup
- \catcode\rquoteChar=\active \catcode\lquoteChar=\active
- \let'\codequoteright \let`\codequoteleft
- %
+ \setupmarkupstyle{code}%
+ % The following should really be moved into \setupmarkupstyle handlers.
\catcode\dashChar=\active \catcode\underChar=\active
\ifallowcodebreaks
\let-\codedash
\let_\codeunder
\else
- \let-\realdash
+ \let-\normaldash
\let_\realunder
\fi
+ % Given -foo (with a single dash), we do not want to allow a break
+ % after the hyphen.
+ \global\let\codedashprev=\codedash
+ %
\codex
}
+ %
+ \gdef\codedash{\futurelet\next\codedashfinish}
+ \gdef\codedashfinish{%