summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Dominik <carsten.dominik@gmail.com>2010-09-16 17:20:02 +0200
committerCarsten Dominik <carsten.dominik@gmail.com>2010-09-16 17:20:02 +0200
commita1dc916be66500dddbc49ef05bdddc2cbfde84da (patch)
treed0f97f2c165a48960f8c7e0ce9d1d528d1510611
parent6a92dd424353e513f5c9266d22c8d5be7db8a14d (diff)
parent0e24c574ac96292cb2684a4ddb4717d81303a7a4 (diff)
downloadorg-mode-a1dc916be66500dddbc49ef05bdddc2cbfde84da.tar.gz
Merge branch 'master' of git+ssh://repo.or.cz/srv/git/org-mode
-rw-r--r--.gitignore6
-rw-r--r--EXPERIMENTAL/find-links-to-local.el3
-rw-r--r--Makefile17
-rw-r--r--ORGWEBPAGE/index.org2
-rw-r--r--README6
-rw-r--r--README_DIST6
-rwxr-xr-xUTILITIES/pw6
-rw-r--r--contrib/README2
-rw-r--r--contrib/lisp/org-drill.el775
-rw-r--r--contrib/lisp/org-export-generic.el132
-rw-r--r--contrib/lisp/org-static-mathjax.el171
-rw-r--r--contrib/lisp/org-wikinodes.el6
-rw-r--r--contrib/lisp/test-org-export-preproc.el39
-rw-r--r--contrib/scripts/.gitignore1
-rwxr-xr-xcontrib/scripts/org2hpda7
-rw-r--r--contrib/scripts/staticmathjax/.gitignore1
-rw-r--r--contrib/scripts/staticmathjax/README.org79
-rw-r--r--contrib/scripts/staticmathjax/README.txt91
-rw-r--r--contrib/scripts/staticmathjax/application.ini11
-rw-r--r--contrib/scripts/staticmathjax/chrome/chrome.manifest1
-rw-r--r--contrib/scripts/staticmathjax/chrome/content/main.js198
-rw-r--r--contrib/scripts/staticmathjax/chrome/content/main.xul11
-rw-r--r--contrib/scripts/staticmathjax/defaults/preferences/prefs.js1
-rw-r--r--doc/org.texi1239
-rw-r--r--doc/orgcard.tex2
-rw-r--r--lisp/ob-C.el16
-rw-r--r--lisp/ob-R.el148
-rw-r--r--lisp/ob-asymptote.el2
-rw-r--r--lisp/ob-clojure.el2
-rw-r--r--lisp/ob-comint.el20
-rw-r--r--lisp/ob-ditaa.el15
-rw-r--r--lisp/ob-dot.el2
-rw-r--r--lisp/ob-emacs-lisp.el5
-rw-r--r--lisp/ob-exp.el5
-rw-r--r--lisp/ob-gnuplot.el4
-rw-r--r--lisp/ob-haskell.el4
-rw-r--r--lisp/ob-js.el170
-rw-r--r--lisp/ob-keys.el8
-rw-r--r--lisp/ob-latex.el143
-rw-r--r--lisp/ob-ledger.el5
-rw-r--r--lisp/ob-lisp.el2
-rw-r--r--lisp/ob-lob.el9
-rw-r--r--lisp/ob-octave.el8
-rw-r--r--lisp/ob-org.el81
-rw-r--r--lisp/ob-perl.el2
-rw-r--r--lisp/ob-plantuml.el86
-rw-r--r--lisp/ob-python.el152
-rw-r--r--lisp/ob-ruby.el5
-rw-r--r--lisp/ob-sass.el4
-rw-r--r--lisp/ob-scheme.el138
-rw-r--r--lisp/ob-sh.el4
-rw-r--r--lisp/ob-sql.el4
-rw-r--r--lisp/ob-sqlite.el4
-rw-r--r--lisp/ob-tangle.el152
-rw-r--r--lisp/ob.el507
-rw-r--r--lisp/org-agenda.el59
-rw-r--r--lisp/org-archive.el4
-rw-r--r--lisp/org-ascii.el51
-rw-r--r--lisp/org-capture.el21
-rw-r--r--lisp/org-clock.el31
-rw-r--r--lisp/org-colview-xemacs.el2
-rw-r--r--lisp/org-colview.el2
-rw-r--r--lisp/org-compat.el2
-rw-r--r--lisp/org-docbook.el123
-rw-r--r--lisp/org-docview.el9
-rw-r--r--lisp/org-exp-blocks.el3
-rw-r--r--lisp/org-exp.el35
-rw-r--r--lisp/org-feed.el27
-rw-r--r--lisp/org-gnus.el39
-rw-r--r--lisp/org-habit.el10
-rw-r--r--lisp/org-html.el469
-rw-r--r--lisp/org-icalendar.el22
-rw-r--r--lisp/org-latex.el42
-rw-r--r--lisp/org-list.el2765
-rw-r--r--lisp/org-macs.el19
-rw-r--r--lisp/org-mhe.el2
-rw-r--r--lisp/org-mouse.el14
-rw-r--r--lisp/org-protocol.el2
-rw-r--r--lisp/org-publish.el23
-rw-r--r--lisp/org-remember.el2
-rw-r--r--lisp/org-src.el145
-rw-r--r--lisp/org-table.el5
-rw-r--r--lisp/org-timer.el80
-rw-r--r--lisp/org-wl.el15
-rw-r--r--lisp/org.el632
-rw-r--r--xemacs/README15
-rw-r--r--xemacs/noutline.el1051
-rw-r--r--xemacs/ps-print-invisible.el225
88 files changed, 6282 insertions, 4184 deletions
diff --git a/.gitignore b/.gitignore
index ba75c2a..374f45e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,23 +8,25 @@
*.bak
*.cp
*.cps
+*.diff
*.dvi
*.elc
*.fn
*.fns
*.html
+*.info
*.ky
*.kys
*.log
+*.patch
*.pdf
*.pg
*.pgs
+*.ps
*.toc
*.tp
*.vr
*.vrs
-*.dvi
-*.ps
orgcard_letter.tex
orgcard.txt
org
diff --git a/EXPERIMENTAL/find-links-to-local.el b/EXPERIMENTAL/find-links-to-local.el
deleted file mode 100644
index d9a94c1..0000000
--- a/EXPERIMENTAL/find-links-to-local.el
+++ /dev/null
@@ -1,3 +0,0 @@
-(defun org-find-links ()
- (let* ((file (buffer-file-name))
- (tname (file-truename file)))
diff --git a/Makefile b/Makefile
index e93f127..1c1f317 100644
--- a/Makefile
+++ b/Makefile
@@ -147,7 +147,11 @@ LISPF = org.el \
ob-css.el \
ob-gnuplot.el \
ob-octave.el \
- ob-screen.el
+ ob-screen.el \
+ ob-plantuml.el \
+ ob-org.el \
+ ob-js.el \
+ ob-scheme.el
LISPFILES0 = $(LISPF:%=lisp/%)
LISPFILES = $(LISPFILES0) lisp/org-install.el
@@ -166,7 +170,6 @@ SHELL = /bin/sh
# Additional distribution files
DISTFILES_extra= Makefile request-assign-future.txt contrib
-DISTFILES_xemacs= xemacs/noutline.el xemacs/ps-print-invisible.el xemacs/README
default: $(ELCFILES) $(ELCBFILES)
@@ -205,10 +208,6 @@ install-info: $(INFOFILES)
install-info-debian: $(INFOFILES)
$(INSTALL_INFO) --infodir=$(infodir) $(INFOFILES)
-install-noutline: xemacs/noutline.elc
- if [ ! -d $(lispdir) ]; then $(MKDIR) $(lispdir); else true; fi ;
- $(CP) xemacs/noutline.el xemacs/noutline.elc $(lispdir)
-
autoloads: lisp/org-install.el
lisp/org-install.el: $(LISPFILES0) Makefile
@@ -220,8 +219,6 @@ lisp/org-install.el: $(LISPFILES0) Makefile
--eval '(save-buffer)'
mv org-install.el lisp
-xemacs/noutline.elc: xemacs/noutline.el
-
doc/org: doc/org.texi
(cd doc; $(MAKEINFO) --no-split org.texi -o org)
@@ -318,7 +315,6 @@ distfile:
${MAKE} lisp/org-install.el
rm -rf org-$(TAG) org-$(TAG).zip
$(MKDIR) org-$(TAG)
- $(MKDIR) org-$(TAG)/xemacs
$(MKDIR) org-$(TAG)/doc
$(MKDIR) org-$(TAG)/lisp
cp -r $(LISPFILES) org-$(TAG)/lisp
@@ -326,7 +322,6 @@ distfile:
cp -r $(DISTFILES_extra) org-$(TAG)/
cp -r README_DIST org-$(TAG)/README
cp -r ORGWEBPAGE/Changes.org org-$(TAG)/
- cp -r $(DISTFILES_xemacs) org-$(TAG)/xemacs/
zip -r org-$(TAG).zip org-$(TAG)
gtar zcvf org-$(TAG).tar.gz org-$(TAG)
@@ -453,4 +448,4 @@ lisp/org-timer.elc: lisp/org.el
lisp/org-vm.elc: lisp/org.el
lisp/org-w3m.elc: lisp/org.el
lisp/org-wl.elc: lisp/org.el
-lisp/org-xoxo.elc: lisp/org-exp.el \ No newline at end of file
+lisp/org-xoxo.elc: lisp/org-exp.el
diff --git a/ORGWEBPAGE/index.org b/ORGWEBPAGE/index.org
index aa8f276..559d7b5 100644
--- a/ORGWEBPAGE/index.org
+++ b/ORGWEBPAGE/index.org
@@ -152,7 +152,7 @@ the command line....):
Some more information about this can be found in the [[http://orgmode.org/worg/org-faq.php][FAQ]], under [[http://orgmode.org/worg/org-faq.php#keeping-current-with-Org-mode-development][How do
I keep current with Org mode development?]]. For people who cannot use
-git, we provide [[file:org-latest.zip][zip]] or [[file:org-latest.tar.gz][tar.gz]] snapshot release files updated each hour
+git, we provide [[file:org-latest.zip][zip]] or [[file:org-latest.tar.gz][tar.gz]] snapshot release files updated each day
and corresponding to the latest git version.
** Alternative distributions
diff --git a/README b/README
index 6e2a0ac..a9d0003 100644
--- a/README
+++ b/README
@@ -21,12 +21,6 @@ doc/
The documentation files. org.texi is the source of the
documentation, org.html and org.pdf are formatted versions of it.
-xemacs/
- The xemacs directory contains special code for XEmacs users, in
- particular a port of the GNU Emacs outline.el to XEmacs. Org-mode
- does not work under XEmacs without this file installed. It did
- until version 4.37, but no longer.
-
contrib/
A directory with third-party additions for Org. Some really cool
stuff is in there.
diff --git a/README_DIST b/README_DIST
index 0e82727..a687b1a 100644
--- a/README_DIST
+++ b/README_DIST
@@ -17,12 +17,6 @@ doc/
The documentation files. org.texi is the source of the
documentation, org.html and org.pdf are formatted versions of it.
-xemacs/
- The xemacs directory contains special code for XEmacs users, in
- particular a port of the GNU Emacs outline.el to XEmacs. Org-mode
- does not work under XEmacs without this file installed. It did
- until version 4.37, but no longer.
-
contrib/
A directory with third-party additions for Org. Some really cool
stuff is in there.
diff --git a/UTILITIES/pw b/UTILITIES/pw
index cc1244a..0cf4bfa 100755
--- a/UTILITIES/pw
+++ b/UTILITIES/pw
@@ -285,7 +285,8 @@ def action_apply(rpc, patch_id):
sys.exit(1)
def action_update_patch(rpc, patch_id, state = None, commit = None,
- delegate_str = "", comment_str, archived = False):
+ delegate_str = "", comment_str = "None",
+ archived = False):
patch = rpc.patch_get(patch_id)
if patch == {}:
sys.stderr.write("Error getting information on patch ID %d\n" % \
@@ -471,7 +472,8 @@ def merge_with(patch_id, rpc, delegate_str, comment_str):
# If it succeeded this far, mark the patch as "Accepted" by the invoking
# user.
action_update_patch(rpc, patch_id, state = 'Accepted', commit = sha,
- delegate_str = delegate_str, archived = True)
+ delegate_str = delegate_str, comment_str = comment_str,
+ archived = True)
print sha
diff --git a/contrib/README b/contrib/README
index 4a18790..6a15821 100644
--- a/contrib/README
+++ b/contrib/README
@@ -18,6 +18,8 @@ org-choose.el --- Use TODO keywords to mark decision states
org-collector.el --- Collect properties into tables
org-contribdir.el --- Dummy file to mark the org contrib Lisp directory
org-depend.el --- TODO dependencies for Org-mode
+org-drill.el --- Self-testing with org-learn
+org-depend.el --- TODO dependencies for Org-mode
org-elisp-symbol.el --- Org links to emacs-lisp symbols
org-eval.el --- The <lisp> tag, adapted from Muse
org-eval-light.el --- Evaluate in-buffer code on demand
diff --git a/contrib/lisp/org-drill.el b/contrib/lisp/org-drill.el
new file mode 100644
index 0000000..a96916e
--- /dev/null
+++ b/contrib/lisp/org-drill.el
@@ -0,0 +1,775 @@
+;;; org-drill.el - Self-testing with org-learn
+;;;
+;;; Author: Paul Sexton <eeeickythump@gmail.com>
+;;; Version: 1.0
+;;; Repository at http://bitbucket.org/eeeickythump/org-drill/
+;;;
+;;;
+;;; Synopsis
+;;; ========
+;;;
+;;; Uses the spaced repetition algorithm in `org-learn' to conduct interactive
+;;; "drill sessions", where the material to be remembered is presented to the
+;;; student in random order. The student rates his or her recall of each item,
+;;; and this information is fed back to `org-learn' to schedule the item for
+;;; later revision.
+;;;
+;;; Each drill session can be restricted to topics in the current buffer
+;;; (default), one or several files, all agenda files, or a subtree. A single
+;;; topic can also be drilled.
+;;;
+;;; Different "card types" can be defined, which present their information to
+;;; the student in different ways.
+;;;
+;;; See the file README.org for more detailed documentation.
+
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'hi-lock))
+(require 'org)
+(require 'org-learn)
+
+
+(defgroup org-drill nil
+ "Options concerning interactive drill sessions in Org mode (org-drill)."
+ :tag "Org-Drill"
+ :group 'org-link)
+
+
+
+(defcustom org-drill-question-tag
+ "drill"
+ "Tag which topics must possess in order to be identified as review topics
+by `org-drill'."
+ :group 'org-drill
+ :type 'string)
+
+
+
+(defcustom org-drill-maximum-items-per-session
+ 30
+ "Each drill session will present at most this many topics for review.
+Nil means unlimited."
+ :group 'org-drill
+ :type '(choice integer (const nil)))
+
+
+
+(defcustom org-drill-maximum-duration
+ 20
+ "Maximum duration of a drill session, in minutes.
+Nil means unlimited."
+ :group 'org-drill
+ :type '(choice integer (const nil)))
+
+
+(defcustom org-drill-failure-quality
+ 2
+ "If the quality of recall for an item is this number or lower,
+it is regarded as an unambiguous failure, and the repetition
+interval for the card is reset to 0 days. By default this is
+2. For Mnemosyne-like behaviour, set it to 1. Other values are
+not really sensible."
+ :group 'org-drill
+ :type '(choice (const 2) (const 1)))
+
+
+(defcustom org-drill-leech-failure-threshold
+ 15
+ "If an item is forgotten more than this many times, it is tagged
+as a 'leech' item."
+ :group 'org-drill
+ :type '(choice integer (const nil)))
+
+
+(defcustom org-drill-leech-method
+ 'skip
+ "How should 'leech items' be handled during drill sessions?
+Possible values:
+- nil :: Leech items are treated the same as normal items.
+- skip :: Leech items are not included in drill sessions.
+- warn :: Leech items are still included in drill sessions,
+ but a warning message is printed when each leech item is
+ presented."
+ :group 'org-drill
+ :type '(choice (const 'warn) (const 'skip) (const nil)))
+
+
+(defface org-drill-visible-cloze-face
+ '((t (:foreground "dark slate blue")))
+ "The face used to hide the contents of cloze phrases."
+ :group 'org-drill)
+
+
+(defcustom org-drill-use-visible-cloze-face-p
+ nil
+ "Use a special face to highlight cloze-deleted text in org mode
+buffers?"
+ :group 'org-drill
+ :type 'boolean)
+
+
+(defface org-drill-hidden-cloze-face
+ '((t (:foreground "deep sky blue" :background "blue")))
+ "The face used to hide the contents of cloze phrases."
+ :group 'org-drill)
+
+
+(setplist 'org-drill-cloze-overlay-defaults
+ '(display "[...]"
+ face org-drill-hidden-cloze-face
+ window t))
+
+
+(defvar org-drill-cloze-regexp
+ ;; ver 1 "[^][]\\(\\[[^][][^]]*\\]\\)"
+ ;; ver 2 "\\(\\[.*?\\]\\|^[^[[:cntrl:]]*?\\]\\|\\[.*?$\\)"
+ "\\(\\[.*?\\]\\|\\[.*?[[:cntrl:]]+.*?\\]\\)")
+
+
+(defcustom org-drill-card-type-alist
+ '((nil . org-drill-present-simple-card)
+ ("simple" . org-drill-present-simple-card)
+ ("twosided" . org-drill-present-two-sided-card)
+ ("multisided" . org-drill-present-multi-sided-card)
+ ("spanish_verb" . org-drill-present-spanish-verb))
+ "Alist associating card types with presentation functions. Each entry in the
+alist takes the form (CARDTYPE . FUNCTION), where CARDTYPE is a string
+or nil, and FUNCTION is a function which takes no arguments and returns a
+boolean value."
+ :group 'org-drill
+ :type '(alist :key-type (choice string (const nil)) :value-type function))
+
+
+(defcustom org-drill-spaced-repetition-algorithm
+ 'sm5
+ "Which SuperMemo spaced repetition algorithm to use for scheduling items.
+Available choices are SM2 and SM5."
+ :group 'org-drill
+ :type '(choice (const 'sm2) (const 'sm5)))
+
+(defcustom org-drill-add-random-noise-to-intervals-p
+ nil
+ "If true, the number of days until an item's next repetition
+will vary slightly from the interval calculated by the SM2
+algorithm. The variation is very small when the interval is
+small, and scales up with the interval. The code for calculating
+random noise is adapted from Mnemosyne."
+ :group 'org-drill
+ :type 'boolean)
+
+
+(defvar *org-drill-done-entry-count* 0)
+(defvar *org-drill-pending-entry-count* 0)
+(defvar *org-drill-session-qualities* nil)
+(defvar *org-drill-start-time* 0)
+
+
+(defun shuffle-list (list)
+ "Randomly permute the elements of LIST (all permutations equally likely)."
+ ;; Adapted from 'shuffle-vector' in cookie1.el
+ (let ((i 0)
+ j
+ temp
+ (len (length list)))
+ (while (< i len)
+ (setq j (+ i (random (- len i))))
+ (setq temp (nth i list))
+ (setf (nth i list) (nth j list))
+ (setf (nth j list) temp)
+ (setq i (1+ i))))
+ list)
+
+
+
+(defun org-drill-entry-p ()
+ "Is the current entry a 'drill item'?"
+ (or (assoc "LEARN_DATA" (org-entry-properties nil))
+ (member org-drill-question-tag (org-get-local-tags))))
+
+
+(defun org-part-of-drill-entry-p ()
+ "Is the current entry either the main heading of a 'drill item',
+or a subheading within a drill item?"
+ (or (org-drill-entry-p)
+ ;; Does this heading INHERIT the drill tag
+ (member org-drill-question-tag (org-get-tags-at))))
+
+
+(defun org-drill-entry-leech-p ()
+ "Is the current entry a 'leech item'?"
+ (and (org-drill-entry-p)
+ (member "leech" (org-get-local-tags))))
+
+
+(defun org-drill-entry-due-p ()
+ (let ((item-time (org-get-scheduled-time (point))))
+ (and (org-drill-entry-p)
+ (or (not (eql 'skip org-drill-leech-method))
+ (not (org-drill-entry-leech-p)))
+ (or (null item-time)
+ (not (minusp ; scheduled for today/in future
+ (- (time-to-days (current-time))
+ (time-to-days item-time))))))))
+
+
+(defun org-drill-entry-new-p ()
+ (let ((item-time (org-get-scheduled-time (point))))
+ (and (org-drill-entry-p)
+ (null item-time))))
+
+
+
+(defun org-drill-entry-last-quality ()
+ (let ((quality (cdr (assoc "DRILL_LAST_QUALITY" (org-entry-properties nil)))))
+ (if quality
+ (string-to-number quality)
+ nil)))
+
+
+;;; SM2 Algorithm =============================================================
+
+
+(defun determine-next-interval-sm2 (last-interval n ef quality of-matrix)
+ "Arguments:
+- LAST-INTERVAL -- the number of days since the item was last reviewed.
+- N -- the number of times the item has been successfully reviewed
+- EF -- the 'easiness factor'
+- QUALITY -- 0 to 5
+- OF-MATRIX -- a matrix of values, used by SM5 but not by SM2.
+
+Returns a list: (INTERVAL N EF OFMATRIX), where:
+- INTERVAL is the number of days until the item should next be reviewed
+- N is incremented by 1.
+- EF is modified based on the recall quality for the item.
+- OF-MATRIX is not modified."
+ (assert (> n 0))
+ (assert (and (>= quality 0) (<= quality 5)))
+ (if (<= quality org-drill-failure-quality)
+ ;; When an item is failed, its interval is reset to 0,
+ ;; but its EF is unchanged
+ (list -1 1 ef of-matrix)
+ ;; else:
+ (let* ((next-ef (modify-e-factor ef quality))
+ (interval
+ (cond
+ ((<= n 1) 1)
+ ((= n 2)
+ (cond
+ (org-drill-add-random-noise-to-intervals-p
+ (case quality
+ (5 6)
+ (4 4)
+ (3 3)
+ (2 1)
+ (t -1)))
+ (t 6)))
+ (t (ceiling (* last-interval next-ef))))))
+ (list (round
+ (if org-drill-add-random-noise-to-intervals-p
+ (+ last-interval (* (- interval last-interval)
+ (org-drill-random-dispersal-factor)))
+ interval))
+ (1+ n) next-ef of-matrix))))
+
+
+;;; SM5 Algorithm =============================================================
+
+;;; From http://www.supermemo.com/english/ol/sm5.htm
+(defun org-drill-random-dispersal-factor ()
+ (let ((a 0.047)
+ (b 0.092)
+ (p (- (random* 1.0) 0.5)))
+ (flet ((sign (n)
+ (cond ((zerop n) 0)
+ ((plusp n) 1)
+ (t -1))))
+ (/ (+ 100 (* (* (/ -1 b) (log (- 1 (* (/ b a ) (abs p)))))
+ (sign p)))
+ 100))))
+
+
+(defun inter-repetition-interval-sm5 (last-interval n ef &optional of-matrix)
+ (let ((of (get-optimal-factor n ef of-matrix)))
+ (if (= 1 n)
+ of
+ (* of last-interval))))
+
+
+(defun determine-next-interval-sm5 (last-interval n ef quality of-matrix)
+ (assert (> n 0))
+ (assert (and (>= quality 0) (<= quality 5)))
+ (let ((next-ef (modify-e-factor ef quality))
+ (interval nil))
+ (setq of-matrix
+ (set-optimal-factor n next-ef of-matrix
+ (modify-of (get-optimal-factor n ef of-matrix)
+ quality org-learn-fraction))
+ ef next-ef)
+
+ (cond
+ ;; "Failed" -- reset repetitions to 0,
+ ((<= quality org-drill-failure-quality)
+ (list -1 1 ef of-matrix)) ; Not clear if OF matrix is supposed to be
+ ; preserved
+ ;; For a zero-based quality of 4 or 5, don't repeat
+ ((and (>= quality 4)
+ (not org-learn-always-reschedule))
+ (list 0 (1+ n) ef of-matrix)) ; 0 interval = unschedule
+ (t
+ (setq interval (inter-repetition-interval-sm5
+ last-interval n ef of-matrix))
+ (if org-drill-add-random-noise-to-intervals-p
+ (setq interval (+ last-interval
+ (* (- interval last-interval)
+ (org-drill-random-dispersal-factor)))))
+ (list (round interval) (1+ n) ef of-matrix)))))
+
+
+;;; Essentially copied from `org-learn.el', but modified to
+;;; optionally call the SM2 function above.
+(defun org-drill-smart-reschedule (quality)
+ (interactive "nHow well did you remember the information (on a scale of 0-5)? ")
+ (let* ((learn-str (org-entry-get (point) "LEARN_DATA"))
+ (learn-data (or (and learn-str
+ (read learn-str))
+ (copy-list initial-repetition-state)))
+ closed-dates)
+ (setq learn-data
+ (case org-drill-spaced-repetition-algorithm
+ (sm5 (determine-next-interval-sm5 (nth 0 learn-data)
+ (nth 1 learn-data)
+ (nth 2 learn-data)
+ quality
+ (nth 3 learn-data)))
+ (sm2 (determine-next-interval-sm2 (nth 0 learn-data)
+ (nth 1 learn-data)
+ (nth 2 learn-data)
+ quality
+ (nth 3 learn-data)))))
+ (org-entry-put (point) "LEARN_DATA" (prin1-to-string learn-data))
+ (cond
+ ((= 0 (nth 0 learn-data))
+ (org-schedule t))
+ (t
+ (org-schedule nil (time-add (current-time)
+ (days-to-time (nth 0 learn-data))))))))
+
+
+(defun org-drill-reschedule ()
+ "Returns quality rating (0-5), or nil if the user quit."
+ (let ((ch nil))
+ (while (not (memq ch '(?q ?0 ?1 ?2 ?3 ?4 ?5)))
+ (setq ch (read-char
+ (if (eq ch ??)
+ "0-2 Means you have forgotten the item.
+3-5 Means you have remembered the item.
+
+0 - Completely forgot.
+1 - Even after seeing the answer, it still took a bit to sink in.
+2 - After seeing the answer, you remembered it.
+3 - It took you awhile, but you finally remembered.
+4 - After a little bit of thought you remembered.
+5 - You remembered the item really easily.
+
+How well did you do? (0-5, ?=help, q=quit)"
+ "How well did you do? (0-5, ?=help, q=quit)"))))
+ (cond
+ ((and (>= ch ?0) (<= ch ?5))
+ (let ((quality (- ch ?0))
+ (failures (cdr (assoc "DRILL_FAILURE_COUNT" (org-entry-properties nil)))))
+ (save-excursion
+ (org-drill-smart-reschedule quality))
+ (push quality *org-drill-session-qualities*)
+ (cond
+ ((<= quality org-drill-failure-quality)
+ (when org-drill-leech-failure-threshold
+ (setq failures (if failures (string-to-number failures) 0))
+ (org-set-property "DRILL_FAILURE_COUNT"
+ (format "%d" (1+ failures)))
+ (if (> (1+ failures) org-drill-leech-failure-threshold)
+ (org-toggle-tag "leech" 'on)))))
+ (org-set-property "DRILL_LAST_QUALITY" (format "%d" quality))
+ quality))
+ (t
+ nil))))
+
+
+(defun org-drill-hide-all-subheadings-except (heading-list)
+ "Returns a list containing the position of each immediate subheading of
+the current topic."
+ (let ((drill-entry-level (org-current-level))
+ (drill-sections nil)
+ (drill-heading nil))
+ (org-show-subtree)
+ (save-excursion
+ (org-map-entries
+ (lambda ()
+ (when (= (org-current-level) (1+ drill-entry-level))
+ (setq drill-heading (org-get-heading t))
+ (unless (member drill-heading heading-list)
+ (hide-subtree))
+ (push (point) drill-sections)))
+ "" 'tree))
+ (reverse drill-sections)))
+
+
+
+(defun org-drill-presentation-prompt (&rest fmt-and-args)
+ (let ((ch nil)
+ (prompt
+ (if fmt-and-args
+ (apply 'format
+ (first fmt-and-args)
+ (rest fmt-and-args))
+ "Press any key to see the answer, 'e' to edit, 'q' to quit.")))
+ (setq prompt
+ (format "(%d) %s" *org-drill-pending-entry-count* prompt))
+ (if (and (eql 'warn org-drill-leech-method)
+ (org-drill-entry-leech-p))
+ (setq prompt (concat "!!! LEECH ITEM !!!
+You seem to be having a lot of trouble memorising this item.
+Consider reformulating the item to make it easier to remember.\n" prompt)))
+ (setq ch (read-char prompt))
+ (case ch
+ (?q nil)
+ (?e 'edit)
+ (otherwise t))))
+
+
+(defun org-drill-hide-clozed-text ()
+ (let ((ovl nil))
+ (save-excursion
+ (while (re-search-forward org-drill-cloze-regexp nil t)
+ (setf ovl (make-overlay (match-beginning 0) (match-end 0)))
+ (overlay-put ovl 'category
+ 'org-drill-cloze-overlay-defaults)
+ (when (find ?| (match-string 0))
+ (overlay-put ovl
+ 'display
+ (format "[...%s]"
+ (substring-no-properties
+ (match-string 0)
+ (1+ (position ?| (match-string 0)))
+ (1- (length (match-string 0)))))))))))
+
+
+(defun org-drill-unhide-clozed-text ()
+ (save-excursion
+ (dolist (ovl (overlays-in (point-min) (point-max)))
+ (when (eql 'org-drill-cloze-overlay-defaults (overlay-get ovl 'category))
+ (delete-overlay ovl)))))
+
+
+
+;;; Presentation functions ====================================================
+
+;; Each of these is called with point on topic heading. Each needs to show the
+;; topic in the form of a 'question' or with some information 'hidden', as
+;; appropriate for the card type. The user should then be prompted to press a
+;; key. The function should then reveal either the 'answer' or the entire
+;; 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 ()
+ (org-drill-hide-all-subheadings-except nil)
+ (prog1 (org-drill-presentation-prompt)
+ (org-show-subtree)))
+
+
+(defun org-drill-present-two-sided-card ()
+ (let ((drill-sections (org-drill-hide-all-subheadings-except nil)))
+ (when drill-sections
+ (save-excursion
+ (goto-char (nth (random (min 2 (length drill-sections))) drill-sections))
+ (org-show-subtree)))
+ (prog1
+ (org-drill-presentation-prompt)
+ (org-show-subtree))))
+
+
+
+(defun org-drill-present-multi-sided-card ()
+ (let ((drill-sections (org-drill-hide-all-subheadings-except nil)))
+ (when drill-sections
+ (save-excursion
+ (goto-char (nth (random (length drill-sections)) drill-sections))
+ (org-show-subtree)))
+ (prog1
+ (org-drill-presentation-prompt)
+ (org-show-subtree))))
+
+
+
+(defun org-drill-present-spanish-verb ()
+ (case (random 6)
+ (0
+ (org-drill-hide-all-subheadings-except '("Infinitive"))
+ (prog1
+ (org-drill-presentation-prompt
+ "Translate this Spanish verb, and conjugate it for the *present* tense.")
+ (org-drill-hide-all-subheadings-except '("English" "Present Tense"
+ "Notes"))))
+ (1
+ (org-drill-hide-all-subheadings-except '("English"))
+ (prog1
+ (org-drill-presentation-prompt
+ "For the *present* tense, conjugate the Spanish translation of this English verb.")
+ (org-drill-hide-all-subheadings-except '("Infinitive" "Present Tense"
+ "Notes"))))
+ (2
+ (org-drill-hide-all-subheadings-except '("Infinitive"))
+ (prog1
+ (org-drill-presentation-prompt
+ "Translate this Spanish verb, and conjugate it for the *past* tense.")
+ (org-drill-hide-all-subheadings-except '("English" "Past Tense"
+ "Notes"))))
+ (3
+ (org-drill-hide-all-subheadings-except '("English"))
+ (prog1
+ (org-drill-presentation-prompt
+ "For the *past* tense, conjugate the Spanish translation of this English verb.")
+ (org-drill-hide-all-subheadings-except '("Infinitive" "Past Tense"
+ "Notes"))))
+ (4
+ (org-drill-hide-all-subheadings-except '("Infinitive"))
+ (prog1
+ (org-drill-presentation-prompt
+ "Translate this Spanish verb, and conjugate it for the *future perfect* tense.")
+ (org-drill-hide-all-subheadings-except '("English" "Future Perfect Tense"
+ "Notes"))))
+ (5
+ (org-drill-hide-all-subheadings-except '("English"))
+ (prog1
+ (org-drill-presentation-prompt
+ "For the *future perfect* tense, conjugate the Spanish translation of this English verb.")
+ (org-drill-hide-all-subheadings-except '("Infinitive" "Future Perfect Tense"
+ "Notes"))))))
+
+
+
+
+(defun org-drill-entry ()
+ "Present the current topic for interactive review, as in `org-drill'.
+Review will occur regardless of whether the topic is due for review or whether
+it meets the definition of a 'review topic' used by `org-drill'.
+
+Returns a quality rating from 0 to 5, or nil if the user quit, or the symbol
+EDIT if the user chose to exit the drill and edit the current item.
+
+See `org-drill' for more details."
+ (interactive)
+ (unless (org-at-heading-p)
+ (org-back-to-heading))
+ (let ((card-type (cdr (assoc "DRILL_CARD_TYPE" (org-entry-properties nil))))
+ (cont nil))
+ (save-restriction
+ (org-narrow-to-subtree)
+ (org-show-subtree)
+ (org-cycle-hide-drawers 'all)
+
+ (let ((presentation-fn (cdr (assoc card-type org-drill-card-type-alist))))
+ (cond
+ (presentation-fn
+ (org-drill-hide-clozed-text)
+ ;;(highlight-regexp org-drill-cloze-regexp
+ ;; 'org-drill-hidden-cloze-face)
+ (unwind-protect
+ (progn
+ (setq cont (funcall presentation-fn)))
+ (org-drill-unhide-clozed-text))
+ ;;(unhighlight-regexp org-drill-cloze-regexp)
+ )
+ (t
+ (error "Unknown card type: '%s'" card-type))))
+
+ (cond
+ ((not cont)
+ (message "Quit")
+ nil)
+ ((eql cont 'edit)
+ 'edit)
+ (t
+ (save-excursion
+ (org-drill-reschedule)))))))
+
+
+(defun org-drill-entries (entries)
+ "Returns nil, t, or a list of markers representing entries that were
+'failed' and need to be presented again before the session ends."
+ (let ((again-entries nil)
+ (*org-drill-done-entry-count* 0)
+ (*org-drill-pending-entry-count* (length entries)))
+ (if (and org-drill-maximum-items-per-session
+ (> (length entries)
+ org-drill-maximum-items-per-session))
+ (setq entries (subseq entries 0
+ org-drill-maximum-items-per-session)))
+ (block org-drill-entries
+ (dolist (m entries)
+ (save-restriction
+ (switch-to-buffer (marker-buffer m))
+ (goto-char (marker-position m))
+ (setq result (org-drill-entry))
+ (cond
+ ((null result)
+ (message "Quit")
+ (return-from org-drill-entries nil))
+ ((eql result 'edit)
+ (setq end-pos (point-marker))
+ (return-from org-drill-entries nil))
+ (t
+ (cond
+ ((< result 3)
+ (push m again-entries))
+ (t
+ (decf *org-drill-pending-entry-count*)
+ (incf *org-drill-done-entry-count*)))
+ (when (and org-drill-maximum-duration
+ (> (- (float-time (current-time)) *org-drill-start-time*)
+ (* org-drill-maximum-duration 60)))
+ (message "This drill session has reached its maximum duration.")
+ (return-from org-drill-entries nil))))))
+ (or again-entries
+ t))))
+
+
+(defun org-drill-final-report ()
+ (read-char
+(format
+ "%d items reviewed, %d items awaiting review
+Session duration %s
+
+Recall of reviewed items:
+ Excellent (5): %3d%%
+ Good (4): %3d%%
+ Hard (3): %3d%%
+ Near miss (2): %3d%%
+ Failure (1): %3d%%
+ Total failure (0): %3d%%
+
+Session finished. Press a key to continue..."
+ *org-drill-done-entry-count*
+ *org-drill-pending-entry-count*
+ (format-seconds "%h:%.2m:%.2s"
+ (- (float-time (current-time)) *org-drill-start-time*))
+ (round (* 100 (count 5 *org-drill-session-qualities*))
+ (max 1 (length *org-drill-session-qualities*)))
+ (round (* 100 (count 4 *org-drill-session-qualities*))
+ (max 1 (length *org-drill-session-qualities*)))
+ (round (* 100 (count 3 *org-drill-session-qualities*))
+ (max 1 (length *org-drill-session-qualities*)))
+ (round (* 100 (count 2 *org-drill-session-qualities*))
+ (max 1 (length *org-drill-session-qualities*)))
+ (round (* 100 (count 1 *org-drill-session-qualities*))
+ (max 1 (length *org-drill-session-qualities*)))
+ (round (* 100 (count 0 *org-drill-session-qualities*))
+ (max 1 (length *org-drill-session-qualities*)))
+ )))
+
+
+
+(defun org-drill (&optional scope)
+ "Begin an interactive 'drill session'. The user is asked to
+review a series of topics (headers). Each topic is initially
+presented as a 'question', often with part of the topic content
+hidden. The user attempts to recall the hidden information or
+answer the question, then presses a key to reveal the answer. The
+user then rates his or her recall or performance on that
+topic. This rating information is used to reschedule the topic
+for future review using the `org-learn' library.
+
+Org-drill proceeds by:
+
+- Finding all topics (headings) in SCOPE which have either been
+ used and rescheduled by org-learn before (i.e. the LEARN_DATA
+ property is set), or which have a tag that matches
+ `org-drill-question-tag'.
+
+- All matching topics which are either unscheduled, or are
+ scheduled for the current date or a date in the past, are
+ considered to be candidates for the drill session.
+
+- If `org-drill-maximum-items-per-session' is set, a random
+ subset of these topics is presented. Otherwise, all of the
+ eligible topics will be presented.
+
+SCOPE determines the scope in which to search for
+questions. It is passed to `org-map-entries', and can be any of:
+
+nil The current buffer, respecting the restriction if any.
+ This is the default.
+tree The subtree started with the entry at point
+file The current buffer, without restriction
+file-with-archives
+ The current buffer, and any archives associated with it
+agenda All agenda files
+agenda-with-archives
+ All agenda files with any archive files associated with them
+ (file1 file2 ...)
+ If this is a list, all files in the list will be scanned."
+
+ (interactive)
+ (let ((entries nil)
+ (failed-entries nil)
+ (new-entries nil)
+ (old-entries nil)
+ (result nil)
+ (results nil)
+ (end-pos nil))
+ (block org-drill
+ (setq *org-drill-session-qualities* nil)
+ (setq *org-drill-start-time* (float-time (current-time)))
+ (save-excursion
+ (org-map-entries
+ (lambda () (when (org-drill-entry-due-p)
+ (cond
+ ((org-drill-entry-new-p)
+ (push (point-marker) new-entries))
+ ((<= (org-drill-entry-last-quality)
+ org-drill-failure-quality)
+ (push (point-marker) failed-entries))
+ (t
+ (push (point-marker) old-entries)))))
+ "" scope)
+ ;; Failed first, then random mix of old + new
+ (setq entries (append (shuffle-list failed-entries)
+ (shuffle-list (append old-entries
+ new-entries))))
+ (cond
+ ((null entries)
+ (message "I did not find any pending drill items."))
+ (t
+ (let ((again t))
+ (while again
+ (when (listp again)
+ (setq entries (shuffle-list again)))
+ (setq again (org-drill-entries entries))
+ (cond
+ ((null again)
+ (return-from org-drill nil))
+ ((eql t again)
+ (setq again nil))))
+ (message "Drill session finished!")
+ )))))
+ (cond
+ (end-pos
+ (switch-to-buffer (marker-buffer end-pos))
+ (goto-char (marker-position end-pos))
+ (message "Edit topic."))
+ (t
+ (org-drill-final-report)))))
+
+
+
+(add-hook 'org-mode-hook
+ (lambda ()
+ (if org-drill-use-visible-cloze-face-p
+ (font-lock-add-keywords
+ 'org-mode
+ `((,org-drill-cloze-regexp
+ (0 'org-drill-visible-cloze-face nil)))
+ t))))
+
+
+(provide 'org-drill)
diff --git a/contrib/lisp/org-export-generic.el b/contrib/lisp/org-export-generic.el
index 1b099dd..f8e8c4a 100644
--- a/contrib/lisp/org-export-generic.el
+++ b/contrib/lisp/org-export-generic.el
@@ -1,4 +1,4 @@
-;;; org-export-generic.el --- Export frameworg with custom backends
+;; org-export-generic.el --- Export frameworg with custom backends
;; Copyright (C) 2009 Free Software Foundation, Inc.
@@ -444,6 +444,40 @@ in this way, it will be wrapped."
export definitions."
(aput 'org-generic-alist type definition))
+;;; helper functions for org-set-generic-type
+(defvar org-export-generic-keywords nil)
+(defmacro* def-org-export-generic-keyword (keyword
+ &key documentation
+ type)
+ "Define KEYWORD as a legitimate element for inclusion in
+the body of an org-set-generic-type definition."
+ `(progn
+ (pushnew ,keyword org-export-generic-keywords)
+ ;; TODO: push the documentation and type information
+ ;; somewhere where it will do us some good.
+ ))
+
+(def-org-export-generic-keyword :body-newline-paragraph
+ :documentation "Bound either to NIL or to a pattern to be
+inserted in the output for every blank line in the input.
+ The intention is to handle formats where text is flowed, and
+newlines are interpreted as significant \(e.g., as indicating
+preformatted text\). A common non-nil value for this keyword
+is \"\\n\". Should typically be combined with a value for
+:body-line-format that does NOT end with a newline."
+ :type string)
+
+;;; fontification keywords
+(def-org-export-generic-keyword :bold-format)
+(def-org-export-generic-keyword :italic-format)
+(def-org-export-generic-keyword :underline-format)
+(def-org-export-generic-keyword :strikethrough-format)
+(def-org-export-generic-keyword :code-format)
+(def-org-export-generic-keyword :verbatim-format)
+
+
+
+
(defun org-export-generic-remember-section (type suffix &optional prefix)
(setq org-export-generic-section-type type)
(setq org-export-generic-section-suffix suffix)
@@ -598,6 +632,7 @@ underlined headlines. The default is 3."
:verbatim-multiline t
:select-tags (plist-get export-plist :select-tags-export)
:exclude-tags (plist-get export-plist :exclude-tags-export)
+ :emph-multiline t
:archived-trees
(plist-get export-plist :archived-trees-export)
:add-text (plist-get opt-plist :text))
@@ -646,6 +681,16 @@ underlined headlines. The default is 3."
(bodylineform (or (plist-get export-plist :body-line-format) "%s"))
(blockquotestart (or (plist-get export-plist :blockquote-start) "\n\n\t"))
(blockquoteend (or (plist-get export-plist :blockquote-end) "\n\n"))
+
+ ;; dynamic variables used heinously in fontification
+ ;; not referenced locally...
+ (format-boldify (plist-get export-plist :bold-format))
+ (format-italicize (plist-get export-plist :italic-format))
+ (format-underline (plist-get export-plist :underline-format))
+ (format-strikethrough (plist-get export-plist :strikethrough-format))
+ (format-code (plist-get export-plist :code-format))
+ (format-verbatim (plist-get export-plist :verbatim-format))
+
thetoc toctags have-headings first-heading-pos
@@ -829,7 +874,7 @@ underlined headlines. The default is 3."
(if org-export-generic-links-to-notes
(push (cons desc0 link) link-buffer)
(setq rpl (concat rpl " (" link ")")
- wrap (+ (length line) (- (length (match-string 0) line))
+ wrap (+ (length line) (- (length (match-string 0 line)))
(length desc)))))
(setq line (replace-match rpl t t line))))
(when custom-times
@@ -887,9 +932,13 @@ underlined headlines. The default is 3."
(string-match "^\\([ \t]+\\)\\(\\*[ \t]*\\)" line))
;;
;; plain list item
- ;;
;; TODO: nested lists
;;
+ ;; first add a line break between any previous paragraph or line item and this
+ ;; one
+ (when bodynewline-paragraph
+ (insert bodynewline-paragraph))
+
;; I believe this gets rid of leading whitespace.
(setq line (replace-match "" nil nil line))
@@ -911,7 +960,7 @@ underlined headlines. The default is 3."
listcheckhalfend)))
)
- (insert (format listformat line)))
+ (insert (format listformat (org-export-generic-fontify line))))
((string-match "^\\([ \t]+\\)\\([0-9]+\\.[ \t]*\\)" line)
;;
;; numbered list item
@@ -937,7 +986,7 @@ underlined headlines. The default is 3."
listcheckhalfend)))
)
- (insert (format numlistformat line)))
+ (insert (format numlistformat (org-export-generic-fontify line))))
((equal line "ORG-BLOCKQUOTE-START")
(setq line blockquotestart))
@@ -946,13 +995,16 @@ underlined headlines. The default is 3."
((string-match "^\\s-*$" line)
;; blank line
(if bodynewline-paragraph
- (insert "\n")))
+ (insert bodynewline-paragraph)))
(t
;;
;; body
;;
(org-export-generic-check-section "body" bodytextpre bodytextsuf)
+ (setq line
+ (org-export-generic-fontify line))
+
;; XXX: properties? list?
(if (string-match "^\\([ \t]*\\)\\([-+*][ \t]+\\)\\(.*?\\)\\( ::\\)" line)
(setq line (replace-match "\\1\\3:" t nil line)))
@@ -1259,6 +1311,74 @@ REVERSE means to reverse the list if the plist match is a list
(and vl (setcar vl nil))
vl))
+
+;;; FIXME: this should probably turn into a defconstant later [2010/05/20:rpg]
+(defvar org-export-generic-emphasis-alist
+ '(("*" format-boldify nil)
+ ("/" format-italicize nil)
+ ("_" format-underline nil)
+ ("+" format-strikethrough nil)
+ ("=" format-code t)
+ ("~" format-verbatim t))
+ "Alist of org format -> formatting variables for fontification.
+Each element of the list is a list of three elements.
+The first element is the character used as a marker for fontification.
+The second element is a variable name, set in org-export-generic. That
+variable will be dereferenced to obtain a formatting string to wrap
+fontified text with.
+The third element decides whether to protect converted text from other
+conversions.")
+
+;;; Cargo-culted from the latex translation. I couldn't figure out how
+;;; to keep the structure since the generic export operates on lines, rather
+;;; than on a buffer as in the latex export, meaning that none of the
+;;; search forward code could be kept. This led me to rewrite the
+;;; whole thing recursively. A huge lose for efficiency (potentially),
+;;; but I couldn't figure out how to make the looping work.
+;;; Worse, it's /doubly/ recursive, because this function calls
+;;; org-export-generic-emph-format, which can call it recursively...
+;;; [2010/05/20:rpg]
+(defun org-export-generic-fontify (string)
+ "Convert fontification according to generic rules."
+ (if (string-match org-emph-re string)
+ ;; The match goes one char after the *string*, except at the end of a line
+ (let ((emph (assoc (match-string 3 string)
+ org-export-generic-emphasis-alist))
+ (beg (match-beginning 0))
+ (end (match-end 0)))
+ (unless emph
+ (message "`org-export-generic-emphasis-alist' has no entry for formatting triggered by \"%s\""
+ (match-string 3 string)))
+ ;; now we need to determine whether we have strikethrough or
+ ;; a list, which is a bit nasty
+ (if (and (equal (match-string 3 string) "+")
+ (save-match-data
+ (string-match "\\`-+\\'" (match-string 4 string))))
+ ;; a list --- skip this match and recurse on the point after the
+ ;; first emph char...
+ (concat (substring string 0 (1+ (match-beginning 3)))
+ (org-export-generic-fontify (substring string (match-beginning 3))))
+ (concat (substring string 0 beg) ;; part before the match
+ (match-string 1 string)
+ (org-export-generic-emph-format (second emph)
+ (match-string 4 string)
+ (third emph))
+ (or (match-string 5 string) "")
+ (org-export-generic-fontify (substring string end)))))
+ string))
+
+(defun org-export-generic-emph-format (format-varname string protect)
+ "Return a string that results from applying the markup indicated by
+FORMAT-VARNAME to STRING."
+ (let ((format (symbol-value format-varname)))
+ (let ((string-to-emphasize
+ (if protect
+ string
+ (org-export-generic-fontify string))))
+ (if format
+ (format format string-to-emphasize)
+ string-to-emphasize))))
+
(provide 'org-generic)
(provide 'org-export-generic)
diff --git a/contrib/lisp/org-static-mathjax.el b/contrib/lisp/org-static-mathjax.el
new file mode 100644
index 0000000..6a9f0ec
--- /dev/null
+++ b/contrib/lisp/org-static-mathjax.el
@@ -0,0 +1,171 @@
+;;; org-static-mathjax.el --- Muse-like tags in Org-mode
+;;
+;; Author: Jan Böker <jan dot boecker at jboecker dot de>
+
+;; This elisp code integrates Static MathJax into the
+;; HTML export process of Org-mode.
+;;
+;; The supporting files for this package are in contrib/scripts/staticmathjax
+;; Please read the README.org file in that directory for more information.
+
+;; To use it, evaluate it on startup, add the following to your .emacs:
+
+;; (require 'org-static-mathjax)
+;;
+;; You will then have to customize the following two variables:
+;; - org-static-mathjax-app-ini-path
+;; - org-static-mathjax-local-mathjax-path
+;;
+;; If xulrunner is not in your $PATH, you will also need to customize
+;; org-static-mathjax-xulrunner-path.
+;;
+;; If everything is setup correctly, you can trigger Static MathJax on
+;; export to HTML by adding the following line to your Org file:
+;; #+StaticMathJax: embed-fonts:nil output-file-name:"embedded-math.html"
+;;
+;; You can omit either argument.
+;; embed-fonts defaults to nil. If you do not specify output-file-name,
+;; the exported file is overwritten with the static version.
+;;
+;; If embed-fonts is non-nil, the fonts are embedded directly into the
+;; output file using data: URIs.
+;;
+;; output-file-name specifies the file name of the static version. You
+;; can use any arbitrary lisp form here, for example:
+;; output-file-name:(concat (file-name-sans-extension buffer-file-name) "-static.html")
+;;
+;; The StaticMathJax XULRunner application expects a UTF-8 encoded
+;; input file. If the static version displays random characters instead
+;; of your math, add the following line at the top of your Org file:
+;; -*- coding: utf-8; -*-
+;;
+;; License: GPL v2 or later
+
+(defcustom org-static-mathjax-app-ini-path
+ (or (expand-file-name
+ "../scripts/staticmatchjax/application.ini"
+ (file-name-directory (or load-file-name buffer-file-name)))
+ "")
+ "Path to \"application.ini\" of the Static MathJax XULRunner application.
+If you have extracted StaticMathJax to e.g. ~/.local/staticmathjax, set
+this to ~/.local/staticmathjax/application.ini"
+ :type 'string)
+
+(defcustom org-static-mathjax-xulrunner-path
+ "xulrunner"
+ "Path to your xulrunner binary"
+ :type 'string)
+
+(defcustom org-static-mathjax-local-mathjax-path
+ ""
+ "Extract the MathJax zip file somewhere on your local
+hard drive and specify the path here.
+
+The directory has to be writeable, as org-static-mathjax
+creates a temporary file there during export."
+ :type 'string)
+
+(defvar org-static-mathjax-debug
+ nil
+ "If non-nil, org-static-mathjax will print some debug messages")
+
+(defun org-static-mathjax-hook-installer ()
+ "Installs org-static-mathjax-process in after-save-hook.
+
+Sets the following buffer-local variables for org-static-mathjax-process to pick up:
+org-static-mathjax-mathjax-path: The path to MathJax.js as used by Org HTML export
+org-static-mathjax-options: The string given with #+STATICMATHJAX: in the file"
+ (let ((static-mathjax-option-string (plist-get opt-plist :static-mathjax)))
+ (if static-mathjax-option-string
+ (progn (set (make-local-variable 'org-static-mathjax-options) static-mathjax-option-string)
+ (set (make-local-variable 'org-static-mathjax-mathjax-path)
+ (nth 1 (assq 'path org-export-html-mathjax-options)))
+ (let ((mathjax-options (plist-get opt-plist :mathjax)))
+ (if mathjax-options
+ (if (string-match "\\<path:" mathjax-options)
+ (set 'org-static-mathjax-mathjax-path
+ (car (read-from-string
+ (substring mathjax-options (match-end 0))))))))
+ (add-hook 'after-save-hook
+ 'org-static-mathjax-process
+ nil t)))))
+
+
+(defun org-static-mathjax-process ()
+ (save-excursion
+ ; some sanity checking
+ (if (or (string= org-static-mathjax-app-ini-path "")
+ (not (file-exists-p org-static-mathjax-app-ini-path)))
+ (error "Static MathJax: You must customize org-static-mathjax-app-ini-path!"))
+ (if (or (string= org-static-mathjax-local-mathjax-path "")
+ (not (file-exists-p org-static-mathjax-local-mathjax-path)))
+ (error "Static MathJax: You must customize org-static-mathjax-local-mathjax-path!"))
+
+ ; define variables
+ (let* ((options org-static-mathjax-options)
+ (output-file-name buffer-file-name)
+ (input-file-name (let ((temporary-file-directory (file-name-directory org-static-mathjax-local-mathjax-path)))
+ (make-temp-file "org-static-mathjax-" nil ".html")))
+ (html-code (buffer-string))
+ (mathjax-oldpath (concat "src=\"" org-static-mathjax-mathjax-path))
+ (mathjax-newpath (concat "src=\"" org-static-mathjax-local-mathjax-path))
+ embed-fonts)
+ ; read file-local options
+ (mapc
+ (lambda (symbol)
+ (if (string-match (concat "\\<" (symbol-name symbol) ":") options)
+ (set symbol (eval (car (read-from-string
+ (substring options (match-end 0))))))))
+ '(embed-fonts output-file-name))
+
+ ; debug
+ (when org-static-mathjax-debug
+ (message "output file name, embed-fonts")
+ (print output-file-name)
+ (print embed-fonts))
+
+ ; open (temporary) input file, copy contents there, replace MathJax path with local installation
+ (with-temp-buffer
+ (insert html-code)
+ (goto-char 1)
+ (replace-regexp mathjax-oldpath mathjax-newpath)
+ (write-file input-file-name))
+
+ ; prepare argument list for call-process
+ (let ((call-process-args (list org-static-mathjax-xulrunner-path
+ nil nil nil
+ org-static-mathjax-app-ini-path
+ input-file-name
+ output-file-name)))
+ ; if fonts are embedded, just append the --embed-fonts flag
+ (if embed-fonts
+ (add-to-list 'call-process-args "--embed-fonts" t))
+ ; if fonts are not embedded, the XULRunner app must replace all references
+ ; to the font files with the real location (Firefox inserts file:// URLs there,
+ ; because we are using a local MathJax installation here)
+ (if (not embed-fonts)
+ (progn
+ (add-to-list 'call-process-args "--final-mathjax-url" t)
+ (add-to-list 'call-process-args
+ (file-name-directory org-static-mathjax-mathjax-path)
+ t)))
+
+ ; debug
+ (when org-static-mathjax-debug
+ (print call-process-args))
+ ; call it
+ (apply 'call-process call-process-args)
+ ; delete our temporary input file
+ (kill-buffer)
+ (delete-file input-file-name)
+ (let ((backup-file (concat input-file-name "~")))
+ (if (file-exists-p backup-file)
+ (delete-file backup-file)))))))
+
+(add-to-list 'org-export-inbuffer-options-extra
+'("STATICMATHJAX" :static-mathjax))
+
+(add-hook 'org-export-html-final-hook 'org-static-mathjax-hook-installer)
+
+
+(provide 'org-static-mathjax)
diff --git a/contrib/lisp/org-wikinodes.el b/contrib/lisp/org-wikinodes.el
index 0a00052..85c32f6 100644
--- a/contrib/lisp/org-wikinodes.el
+++ b/contrib/lisp/org-wikinodes.el
@@ -119,10 +119,10 @@ setting of `org-wikinodes-create-targets'."
(let ((create org-wikinodes-create-targets)
visiting buffer m pos file rpl)
(setq pos
- (or (org-find-exact-headling-in-buffer target (current-buffer))
+ (or (org-find-exact-headline-in-buffer target (current-buffer))
(and (eq org-wikinodes-scope 'directory)
(setq file (org-wikinodes-which-file target))
- (org-find-exact-headling-in-buffer
+ (org-find-exact-headline-in-buffer
target (or (get-file-buffer file)
(find-file-noselect file))))))
(if pos
@@ -288,7 +288,7 @@ with working links."
(delete-region (match-beginning 0) (match-end 0))
(save-match-data
(cond
- ((org-find-exact-headling-in-buffer link (current-buffer))
+ ((org-find-exact-headline-in-buffer link (current-buffer))
;; Found in current buffer
(insert (format "[[#%s][%s]]" link link)))
((eq org-wikinodes-scope 'file)
diff --git a/contrib/lisp/test-org-export-preproc.el b/contrib/lisp/test-org-export-preproc.el
new file mode 100644
index 0000000..3af8461
--- /dev/null
+++ b/contrib/lisp/test-org-export-preproc.el
@@ -0,0 +1,39 @@
+(require 'org-export-generic)
+
+(defun test-preproc ()
+ (interactive)
+ (let ((string
+ (let ((region
+ (buffer-substring
+ (if (org-region-active-p) (region-beginning) (point-min))
+ (if (org-region-active-p) (region-end) (point-max))))
+ (opt-plist (org-combine-plists (org-default-export-plist)
+ (org-infile-export-plist)))
+ (export-plist '("tikiwiki" :file-suffix ".txt" :key-binding 85 :header-prefix "" :header-suffix "" :title-format "-= %s =-\n" :date-export nil :toc-export nil :body-header-section-numbers nil :body-section-prefix "\n" :body-section-header-prefix
+ ("! " "!! " "!!! " "!!!! " "!!!!! " "!!!!!! " "!!!!!!! ")
+ :body-section-header-suffix
+ (" \n" " \n" " \n" " \n" " \n" " \n")
+ :body-line-export-preformated t :body-line-format "%s " :body-line-wrap nil :body-line-fixed-format " %s\n" :body-list-format "* %s\n" :body-number-list-format "# %s\n" :blockquote-start "\n^\n" :blockquote-end "^\n\n" :body-newline-paragraph "\n" :bold-format "__%s__" :italic-format "''%s''" :underline-format "===%s===" :strikethrough-format "--%s--" :code-format "-+%s+-" :verbatim-format "~pp~%s~/pp~")))
+ (org-export-preprocess-string
+ region
+ :for-ascii t
+ :skip-before-1st-heading
+ (plist-get opt-plist :skip-before-1st-heading)
+ :drawers (plist-get export-plist :drawers-export)
+ :tags (plist-get export-plist :tags-export)
+ :priority (plist-get export-plist :priority-export)
+ :footnotes (plist-get export-plist :footnotes-export)
+ :timestamps (plist-get export-plist :timestamps-export)
+ :todo-keywords (plist-get export-plist :todo-keywords-export)
+ :verbatim-multiline t
+ :select-tags (plist-get export-plist :select-tags-export)
+ :exclude-tags (plist-get export-plist :exclude-tags-export)
+ :emph-multiline t
+ :archived-trees
+ (plist-get export-plist :archived-trees-export)
+ :add-text (plist-get opt-plist :text)))))
+ (save-excursion
+ (switch-to-buffer "*preproc-temp*")
+ (point-max)
+ (insert string))))
+
diff --git a/contrib/scripts/.gitignore b/contrib/scripts/.gitignore
new file mode 100644
index 0000000..20d5925
--- /dev/null
+++ b/contrib/scripts/.gitignore
@@ -0,0 +1 @@
+plantuml.jar
diff --git a/contrib/scripts/org2hpda b/contrib/scripts/org2hpda
index 1957aa9..6b308f3 100755
--- a/contrib/scripts/org2hpda
+++ b/contrib/scripts/org2hpda
@@ -44,6 +44,11 @@ EMACS = emacs -batch -l ~/.emacs
LATEX = latex
DIARY = $($(EMACS) -eval "diary-file")
+# Number of weeks to be printed. Should be a multiple of 4, because 4
+# of them are merged on one page. Can be set when invoking the script
+# as follows: make NUMBER_OF_WEEKS=8 -f org2hpda
+NUMBER_OF_WEEKS = 4
+
hipsterFiles = weekCalendar.pdf yearCalendar.pdf monthCalendar3.pdf monthCalendar2.pdf monthCalendar1.pdf
pocketModFiles = weekCalendar.pdf yearCalendar-rotated.pdf \
monthCalendar3-rotated.pdf monthCalendar2-rotated.pdf monthCalendar1-rotated.pdf
@@ -73,7 +78,7 @@ all: pocketMod.pdf hipsterPDA.pdf
done
weekCalendar.tex: $(DIARY)
- $(EMACS) -eval "(progn (calendar) (cal-tex-cursor-week-iso 4) (with-current-buffer cal-tex-buffer (write-file \"$@\")))"
+ $(EMACS) -eval "(progn (calendar) (cal-tex-cursor-week-iso $(NUMBER_OF_WEEKS)) (with-current-buffer cal-tex-buffer (write-file \"$@\")))"
monthCalendar1.tex: $(DIARY)
$(EMACS) -eval "(progn (calendar) (cal-tex-cursor-month-landscape 1) (with-current-buffer cal-tex-buffer (write-file \"$@\")))"
diff --git a/contrib/scripts/staticmathjax/.gitignore b/contrib/scripts/staticmathjax/.gitignore
new file mode 100644
index 0000000..b25c15b
--- /dev/null
+++ b/contrib/scripts/staticmathjax/.gitignore
@@ -0,0 +1 @@
+*~
diff --git a/contrib/scripts/staticmathjax/README.org b/contrib/scripts/staticmathjax/README.org
new file mode 100644
index 0000000..d28fc90
--- /dev/null
+++ b/contrib/scripts/staticmathjax/README.org
@@ -0,0 +1,79 @@
+Static MathJax v0.1 README
+#+AUTHOR: Jan Böcker <jan.boecker@jboecker.de>
+
+Static MathJax is a XULRunner application which loads a HTML input
+file that uses MathJax into a browser, waits until MathJax is done
+processing, and then writes the formatted result to an output HTML
+file.
+
+I have only tested exports from Emacs Org-mode as input files. (As of
+2010-08-14, MathJax is used by default with HTML exports in the
+current Org development version.)
+
+Optionally, references to the math fonts used will be converted to
+"data:" URIs, thus embedding the font data into the HTML file itself.
+(see [[http://en.wikipedia.org/wiki/Data_URI_scheme]])
+
+The code is licensed under the GNU General Public License version
+2, or, at your option, any later version.
+
+
+* Usage
+ To run Static MathJax, an existing XULRunner installation is
+ required. From the directory to which you unpacked Static MathJax,
+ run:
+
+ xulrunner application.ini <--embed-fonts | --final-mathjax-url <URL>>
+ <input file> <output file>
+
+ If you prefer to call "staticmathjax" instead of "xulrunner
+ application.ini", link xulrunner-stub into the directory:
+ ln /usr/lib/xulrunner-1.9.2.8/xulrunner-stub ./staticmathjax
+
+ - input file ::
+ name of the input file (the result of a HTML export
+ from Org-mode). It is assumed that this file uses the
+ UTF-8 character encoding.
+
+ - output file ::
+ name of the output file.
+
+ - --embed-fonts ::
+ if specified, the math fonts will be embedded into
+ the output file using data: URIs
+
+ - --final-mathjax-url <URL> ::
+ if --embed-fonts is not specified, this
+ must be the URL to a MathJax installation folder (e.g. "MathJax"
+ if MathJax is installed in a subdirectory, or
+ "http://orgmode.org/mathjax" to use the version hosted on the Org
+ website.
+
+ All references to math fonts in the output file will point to
+ this directory.
+
+* Caveats
+
+ The input file must not use a MathJax installation on the
+ web. Otherwise, due to a security feature of Firefox, MathJax will
+ fallback to image fonts. If you have unpacked MathJax to a
+ subdirectory "MathJax", specify the following in your Org file:
+
+ #+MathJax: path:"MathJax"
+
+ The math is rendered in Firefox, so MathJax applies its
+ Firefox-specific settings. When viewing the output files in other
+ browsers, it will look slightly different than the result that
+ running MathJax in that browser would produce.
+
+ Internet Explorer does not use the correct font, because it only
+ supports the EOT font format. For all other browsers (including
+ Firefox), MathJax uses the OTF font format.
+
+ Embedding fonts into the HTML file wastes some space due to the
+ base64 encoding used in data: URIs.
+
+ I have found no way to access stdout or set an exit code in an
+ XULRunner app, so any code which calls Static MathJax has no idea if
+ processing was successful and when an error occurs, graphical
+ message boxes are displayed.
diff --git a/contrib/scripts/staticmathjax/README.txt b/contrib/scripts/staticmathjax/README.txt
new file mode 100644
index 0000000..cbcaea1
--- /dev/null
+++ b/contrib/scripts/staticmathjax/README.txt
@@ -0,0 +1,91 @@
+ Static MathJax v0.1 README
+ ==========================
+
+Author: Jan Böcker <jan.boecker@jboecker.de>
+Date: 2010-08-15 13:53:39 CEST
+
+
+Static MathJax is a XULRunner application which loads a HTML input
+file that uses MathJax into a browser, waits until MathJax is done
+processing, and then writes the formatted result to an output HTML
+file.
+
+I have only tested exports from Emacs Org-mode as input files. (As of
+2010-08-14, MathJax is used by default with HTML exports in the
+current Org development version.)
+
+Optionally, references to the math fonts used will be converted to
+"data:" URIs, thus embedding the font data into the HTML file itself.
+(see [http://en.wikipedia.org/wiki/Data_URI_scheme])
+
+The code is licensed under the GNU General Public License version
+2, or, at your option, any later version.
+
+
+Table of Contents
+=================
+1 Usage
+2 Caveats
+
+
+1 Usage
+~~~~~~~~
+ To run Static MathJax, an existing XULRunner installation is
+ required. From the directory to which you unpacked Static MathJax,
+ run:
+
+ xulrunner application.ini <--embed-fonts | --final-mathjax-url <URL>>
+ <input file> <output file>
+
+ If you prefer to call "staticmathjax" instead of "xulrunner
+ application.ini", link xulrunner-stub into the directory:
+ ln /usr/lib/xulrunner-1.9.2.8/xulrunner-stub ./staticmathjax
+
+ input file:
+ name of the input file (the result of a HTML export
+ from Org-mode). It is assumed that this file uses the
+ UTF-8 character encoding.
+
+ output file:
+ name of the output file.
+
+ --embed-fonts:
+ if specified, the math fonts will be embedded into
+ the output file using data: URIs
+
+ --final-mathjax-url <URL>:
+ if --embed-fonts is not specified, this
+ must be the URL to a MathJax installation folder (e.g. "MathJax"
+ if MathJax is installed in a subdirectory, or
+ "[http://orgmode.org/mathjax]" to use the version hosted on the Org
+ website.
+
+ All references to math fonts in the output file will point to
+ this directory.
+
+2 Caveats
+~~~~~~~~~~
+
+ The input file must not use a MathJax installation on the
+ web. Otherwise, due to a security feature of Firefox, MathJax will
+ fallback to image fonts. If you have unpacked MathJax to a
+ subdirectory "MathJax", specify the following in your Org file:
+
+ #+MathJax: path:"MathJax"
+
+ The math is rendered in Firefox, so MathJax applies its
+ Firefox-specific settings. When viewing the output files in other
+ browsers, it will look slightly different than the result that
+ running MathJax in that browser would produce.
+
+ Internet Explorer does not use the correct font, because it only
+ supports the EOT font format. For all other browsers (including
+ Firefox), MathJax uses the OTF font format.
+
+ Embedding fonts into the HTML file wastes some space due to the
+ base64 encoding used in data: URIs.
+
+ I have found no way to access stdout or set an exit code in an
+ XULRunner app, so any code which calls Static MathJax has no idea if
+ processing was successful and when an error occurs, graphical
+ message boxes are displayed.
diff --git a/contrib/scripts/staticmathjax/application.ini b/contrib/scripts/staticmathjax/application.ini
new file mode 100644
index 0000000..d7957b0
--- /dev/null
+++ b/contrib/scripts/staticmathjax/application.ini
@@ -0,0 +1,11 @@
+[App]
+Vendor=Jan Boecker
+Name=StaticMathJax
+Version=0.2
+BuildID=2
+Copyright=Copyright (c) 2010 Jan Boecker
+ID=xulapp@jboecker.de
+
+[Gecko]
+MinVersion=1.8
+
diff --git a/contrib/scripts/staticmathjax/chrome/chrome.manifest b/contrib/scripts/staticmathjax/chrome/chrome.manifest
new file mode 100644
index 0000000..a05d8c8
--- /dev/null
+++ b/contrib/scripts/staticmathjax/chrome/chrome.manifest
@@ -0,0 +1 @@
+content staticmathjax file:content/
diff --git a/contrib/scripts/staticmathjax/chrome/content/main.js b/contrib/scripts/staticmathjax/chrome/content/main.js
new file mode 100644
index 0000000..2e71f3b
--- /dev/null
+++ b/contrib/scripts/staticmathjax/chrome/content/main.js
@@ -0,0 +1,198 @@
+var docFrame;
+var logtextbox;
+var destFile;
+var embedFonts = false;
+var finalMathJaxURL = null;
+
+function log(text)
+{
+ logtextbox.setAttribute("value", logtextbox.getAttribute("value") + "\n" + text);
+}
+
+function init()
+{
+ try {
+ docFrame = document.getElementById("docFrame");
+ logtextbox = document.getElementById("logtextbox");
+
+ // parse command line arguments
+ var cmdLine = window.arguments[0];
+ cmdLine = cmdLine.QueryInterface(Components.interfaces.nsICommandLine);
+
+ embedFonts = cmdLine.handleFlag("embed-fonts", false);
+ finalMathJaxURL = cmdLine.handleFlagWithParam("final-mathjax-url", false);
+
+ if (!embedFonts && !finalMathJaxURL) {
+ alert("You must eiher specify --embed-fonts or --final-mathjax-url");
+ window.close();
+ return;
+ }
+
+ sourceFilePath = cmdLine.getArgument(0);
+ destFilePath = cmdLine.getArgument(1);
+ if ( !sourceFilePath || !destFilePath ) {
+ alert("Not enough parameters, expecting two arguments:\nInput file, output file");
+ window.close();
+ return;
+ }
+
+ sourceFile = cmdLine.resolveFile(sourceFilePath);
+ if (! (sourceFile.exists() && sourceFile.isFile()) ) {
+ alert("Invalid source file path.");
+ window.close();
+ return;
+ }
+ sourceURI = cmdLine.resolveURI(sourceFilePath);
+
+ // create a nsIFile object for the output file
+ try{
+ destFile = cmdLine.resolveURI(destFilePath).QueryInterface(Components.interfaces.nsIFileURL).file;
+ }catch(e){
+ alert("Invalid destination file.\n\nException:\n" + e);
+ window.close();
+ return;
+ }
+
+ // add iframeLoaded() as an onload event handler, then navigate to the source file
+ docFrame.addEventListener("DOMContentLoaded", iframeLoaded, true);
+ docFrame.setAttribute("src", sourceURI.spec);
+
+ } catch (e) {
+ alert("Error in init():\n\n" + e);
+ window.close();
+ return;
+ }
+}
+
+function iframeLoaded()
+{
+ /*
+ // print every MathJax signal to the log
+ docFrame.contentWindow.MathJax.Hub.Startup.signal.Interest(
+ function (message) {log("Startup: "+message)}
+ );
+ docFrame.contentWindow.MathJax.Hub.signal.Interest(
+ function (message) {log("Hub: "+message)}
+ );
+ */
+
+ // tell MathJax to call serialize() when finished
+ docFrame.contentWindow.MathJax.Hub.Register.StartupHook("End", function() {serialize();});
+}
+
+function fileURLtoDataURI(url)
+{
+ var ios = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+ var url_object = ios.newURI(url, "", null);
+ var file = url_object.QueryInterface(Components.interfaces.nsIFileURL).file;
+
+ var data = "";
+ var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Components.interfaces.nsIFileInputStream);
+ fstream.init(file, -1, -1, false);
+ var bstream = Components.classes["@mozilla.org/binaryinputstream;1"].
+ createInstance(Components.interfaces.nsIBinaryInputStream);
+ bstream.setInputStream(fstream);
+
+ var bytes = bstream.readBytes(bstream.available());
+ b64bytes = btoa(bytes);
+
+ return "data:;base64," + b64bytes;
+
+}
+
+function serialize()
+{
+ var MathJaxURL = docFrame.contentWindow.MathJax.Hub.config.root;
+
+ var searchURIList = new Array();
+ var replacementURIList = new Array();
+
+ log("serialize: preprocessing");
+
+ // remove the MathJax status message window
+ msgdiv = docFrame.contentDocument.getElementById("MathJax_Message");
+ msgdiv.parentNode.removeChild(msgdiv);
+
+ /* Loop through all CSS rules to find all @font-face rules.
+ At this point, they refer to local absolute paths using file:// URLs.
+ Replace them either with appropriate URLs relative to finalMathJaxURL
+ or with data URIs. */
+
+ for (var i = 0; i<docFrame.contentDocument.styleSheets.length; i++) {
+ var stylesheet = docFrame.contentDocument.styleSheets[i];
+
+ for (var j=0; j< stylesheet.cssRules.length; j++) {
+ var rule = stylesheet.cssRules[j];
+ if (rule.cssText.match("font-face")) {
+
+ url = rule.style.getPropertyValue("src");
+ url = url.match(/url\(\"(.+)\"\)/)[1];
+
+ // Since the properties seem read-only here, we populate
+ // searchURIList and replacementURIList to do text substitution
+ // after serialization
+ searchURIList.push(url);
+ if (embedFonts) {
+ replacementURIList.push(fileURLtoDataURI(url));
+ } else {
+ replacementURIList.push(url.replace(MathJaxURL, finalMathJaxURL));
+ }
+ }
+ }
+ }
+
+
+ // find and remove the MathJax <script> tag
+ try{
+ var scriptTags = docFrame.contentDocument.getElementsByTagName("script");
+ for (var i=0; i<scriptTags.length; i++) {
+ if (scriptTags[i].getAttribute("src") && scriptTags[i].getAttribute("src").match(/MathJax.js/i))
+ scriptTags[i].parentNode.removeChild(scriptTags[i]);
+ }
+ }catch(e){alert(e);}
+
+ log("serialize: serializing");
+
+ var serializer = new XMLSerializer();
+ var xhtml = serializer.serializeToString(docFrame.contentDocument);
+
+ log("serialize: postprocessing");
+ // make the MathJax URL relative again
+ // xhtml = xhtml.replace(findMathJaxURL, "MathJax");
+
+ try{
+ r1 = RegExp("&lt;!--/\\*--&gt;&lt;!\\[CDATA\\[/\\*&gt;&lt;!--\\*/", "g");
+ xhtml = xhtml.replace(r1, "");
+ r2 = RegExp("/\\*\\]\\]&gt;\\*/--&gt;", "g");
+ xhtml = xhtml.replace(r2, "");
+ r3 = RegExp("/\\*\\]\\]&gt;\\*///--&gt;", "g");
+ xhtml = xhtml.replace(r3, "");
+ }catch(e){alert(e);}
+ for (var i=0; i<searchURIList.length; i++)
+ xhtml = xhtml.replace(searchURIList[i], replacementURIList[i]);
+
+ save(xhtml);
+ window.close();
+}
+
+function save(xhtml)
+{
+ try {
+ var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
+ createInstance(Components.interfaces.nsIFileOutputStream);
+
+ foStream.init(destFile, 0x02 | 0x08 | 0x20, 0666, 0);
+ // write, create, truncate
+
+ // write in UTF-8 encoding
+ var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
+ createInstance(Components.interfaces.nsIConverterOutputStream);
+ converter.init(foStream, "UTF-8", 0, 0);
+ converter.writeString(xhtml);
+ converter.close(); // this closes foStream
+ } catch (e) {
+ alert("Error in save():\n\n" + e);
+ }
+}
diff --git a/contrib/scripts/staticmathjax/chrome/content/main.xul b/contrib/scripts/staticmathjax/chrome/content/main.xul
new file mode 100644
index 0000000..35a00f2
--- /dev/null
+++ b/contrib/scripts/staticmathjax/chrome/content/main.xul
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window onload="init();" id="main" title="Static MathJax" width="300" height="300"
+xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script language="JavaScript" src="chrome://staticmathjax/content/main.js"/>
+
+ <browser flex="1" id="docFrame" src="" style="background-color:white;"/>
+ <textbox flex="1" id="logtextbox" multiline="true" style="display:none;"/>
+</window>
diff --git a/contrib/scripts/staticmathjax/defaults/preferences/prefs.js b/contrib/scripts/staticmathjax/defaults/preferences/prefs.js
new file mode 100644
index 0000000..0532ce0
--- /dev/null
+++ b/contrib/scripts/staticmathjax/defaults/preferences/prefs.js
@@ -0,0 +1 @@
+pref("toolkit.defaultChromeURI", "chrome://staticmathjax/content/main.xul");
diff --git a/doc/org.texi b/doc/org.texi
index bc83693..d6ea141 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -22,6 +22,24 @@
@finalout
@c Macro definitions
+@macro orgcmd{key,command}
+@iftex
+@kindex \key\
+@findex \command\
+@item @kbd{\key\} @hskip 0pt plus 1filll @code{\command\}
+@end iftex
+@ifnottex
+@kindex \key\
+@findex \command\
+@item @kbd{\key\} @tie{}@tie{}@tie{}@tie{}(@code{\command\})
+@end ifnottex
+@end macro
+
+@macro orgkey{key}
+@kindex \key\
+@item @kbd{\key\}
+@end macro
+
@iftex
@c @hyphenation{time-stamp time-stamps time-stamp-ing time-stamp-ed}
@end iftex
@@ -51,7 +69,8 @@ e.g.,
@copying
This manual is for Org version @value{VERSION}.
-Copyright @copyright{} 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation
+Copyright @copyright{} 2004, 2005, 2006, 2007, 2008, 2009, 2010
+Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -101,408 +120,409 @@ with contributions by David O'Toole, Bastien Guerry, Philip Rooke, Dan Davison,
@end ifnottex
@menu
-* Introduction:: Getting started
-* Document Structure:: A tree works like your brain
-* Tables:: Pure magic for quick formatting
-* Hyperlinks:: Notes in context
-* TODO Items:: Every tree branch can be a TODO item
-* Tags:: Tagging headlines and matching sets of tags
-* Properties and Columns:: Storing information about an entry
-* Dates and Times:: Making items useful for planning
-* Capture - Refile - Archive:: The ins and outs for projects
-* Agenda Views:: Collecting information into views
-* Markup:: Prepare text for rich export
-* Exporting:: Sharing and publishing of notes
-* Publishing:: Create a web site of linked Org files
-* Working With Source Code:: Export, evaluate, and tangle code blocks
-* Miscellaneous:: All the rest which did not fit elsewhere
-* Hacking:: How to hack your way around
-* MobileOrg:: Viewing and capture on a mobile device
-* History and Acknowledgments:: How Org came into being
-* Main Index:: An index of Org's concepts and features
-* Key Index:: Key bindings and where they are described
-* Variable Index:: Variables mentioned in the manual
+* Introduction:: Getting started
+* Document Structure:: A tree works like your brain
+* Tables:: Pure magic for quick formatting
+* Hyperlinks:: Notes in context
+* TODO Items:: Every tree branch can be a TODO item
+* Tags:: Tagging headlines and matching sets of tags
+* Properties and Columns:: Storing information about an entry
+* Dates and Times:: Making items useful for planning
+* Capture - Refile - Archive:: The ins and outs for projects
+* Agenda Views:: Collecting information into views
+* Markup:: Prepare text for rich export
+* Exporting:: Sharing and publishing of notes
+* Publishing:: Create a web site of linked Org files
+* Working With Source Code:: Export, evaluate, and tangle code blocks
+* Miscellaneous:: All the rest which did not fit elsewhere
+* Hacking:: How to hack your way around
+* MobileOrg:: Viewing and capture on a mobile device
+* History and Acknowledgments:: How Org came into being
+* Main Index:: An index of Org's concepts and features
+* Key Index:: Key bindings and where they are described
+* Command and Function Index:: Command names and some internal functions
+* Variable Index:: Variables mentioned in the manual
@detailmenu
--- The Detailed Node Listing ---
Introduction
-* Summary:: Brief summary of what Org does
-* Installation:: How to install a downloaded version of Org
-* Activation:: How to activate Org for certain buffers
-* Feedback:: Bug reports, ideas, patches etc.
-* Conventions:: Type-setting conventions in the manual
+* Summary:: Brief summary of what Org does
+* Installation:: How to install a downloaded version of Org
+* Activation:: How to activate Org for certain buffers
+* Feedback:: Bug reports, ideas, patches etc.
+* Conventions:: Type-setting conventions in the manual
Document structure
-* Outlines:: Org is based on Outline mode
-* Headlines:: How to typeset Org tree headlines
-* Visibility cycling:: Show and hide, much simplified
-* Motion:: Jumping to other headlines
-* Structure editing:: Changing sequence and level of headlines
-* Sparse trees:: Matches embedded in context
-* Plain lists:: Additional structure within an entry
-* Drawers:: Tucking stuff away
-* Blocks:: Folding blocks
-* Footnotes:: How footnotes are defined in Org's syntax
-* Orgstruct mode:: Structure editing outside Org
+* Outlines:: Org is based on Outline mode
+* Headlines:: How to typeset Org tree headlines
+* Visibility cycling:: Show and hide, much simplified
+* Motion:: Jumping to other headlines
+* Structure editing:: Changing sequence and level of headlines
+* Sparse trees:: Matches embedded in context
+* Plain lists:: Additional structure within an entry
+* Drawers:: Tucking stuff away
+* Blocks:: Folding blocks
+* Footnotes:: How footnotes are defined in Org's syntax
+* Orgstruct mode:: Structure editing outside Org
Tables
-* Built-in table editor:: Simple tables
-* Column width and alignment:: Overrule the automatic settings
-* Column groups:: Grouping to trigger vertical lines
-* Orgtbl mode:: The table editor as minor mode
-* The spreadsheet:: The table editor has spreadsheet capabilities
-* Org-Plot:: Plotting from org tables
+* Built-in table editor:: Simple tables
+* Column width and alignment:: Overrule the automatic settings
+* Column groups:: Grouping to trigger vertical lines
+* Orgtbl mode:: The table editor as minor mode
+* The spreadsheet:: The table editor has spreadsheet capabilities
+* Org-Plot:: Plotting from org tables
The spreadsheet
-* References:: How to refer to another field or range
-* Formula syntax for Calc:: Using Calc to compute stuff
-* Formula syntax for Lisp:: Writing formulas in Emacs Lisp
-* Field formulas:: Formulas valid for a single field
-* Column formulas:: Formulas valid for an entire column
+* References:: How to refer to another field or range
+* Formula syntax for Calc:: Using Calc to compute stuff
+* Formula syntax for Lisp:: Writing formulas in Emacs Lisp
+* Field formulas:: Formulas valid for a single field
+* Column formulas:: Formulas valid for an entire column
* Editing and debugging formulas:: Fixing formulas
-* Updating the table:: Recomputing all dependent fields
-* Advanced features:: Field names, parameters and automatic recalc
+* Updating the table:: Recomputing all dependent fields
+* Advanced features:: Field names, parameters and automatic recalc
Hyperlinks
-* Link format:: How links in Org are formatted
-* Internal links:: Links to other places in the current file
-* External links:: URL-like links to the world
-* Handling links:: Creating, inserting and following
-* Using links outside Org:: Linking from my C source code?
-* Link abbreviations:: Shortcuts for writing complex links
-* Search options:: Linking to a specific location
-* Custom searches:: When the default search is not enough
+* Link format:: How links in Org are formatted
+* Internal links:: Links to other places in the current file
+* External links:: URL-like links to the world
+* Handling links:: Creating, inserting and following
+* Using links outside Org:: Linking from my C source code?
+* Link abbreviations:: Shortcuts for writing complex links
+* Search options:: Linking to a specific location
+* Custom searches:: When the default search is not enough
Internal links
-* Radio targets:: Make targets trigger links in plain text
+* Radio targets:: Make targets trigger links in plain text
TODO items
-* TODO basics:: Marking and displaying TODO entries
-* TODO extensions:: Workflow and assignments
-* Progress logging:: Dates and notes for progress
-* Priorities:: Some things are more important than others
-* Breaking down tasks:: Splitting a task into manageable pieces
-* Checkboxes:: Tick-off lists
+* TODO basics:: Marking and displaying TODO entries
+* TODO extensions:: Workflow and assignments
+* Progress logging:: Dates and notes for progress
+* Priorities:: Some things are more important than others
+* Breaking down tasks:: Splitting a task into manageable pieces
+* Checkboxes:: Tick-off lists
Extended use of TODO keywords
-* Workflow states:: From TODO to DONE in steps
-* TODO types:: I do this, Fred does the rest
-* Multiple sets in one file:: Mixing it all, and still finding your way
-* Fast access to TODO states:: Single letter selection of a state
-* Per-file keywords:: Different files, different requirements
-* Faces for TODO keywords:: Highlighting states
-* TODO dependencies:: When one task needs to wait for others
+* Workflow states:: From TODO to DONE in steps
+* TODO types:: I do this, Fred does the rest
+* Multiple sets in one file:: Mixing it all, and still finding your way
+* Fast access to TODO states:: Single letter selection of a state
+* Per-file keywords:: Different files, different requirements
+* Faces for TODO keywords:: Highlighting states
+* TODO dependencies:: When one task needs to wait for others
Progress logging
-* Closing items:: When was this entry marked DONE?
-* Tracking TODO state changes:: When did the status change?
-* Tracking your habits:: How consistent have you been?
+* Closing items:: When was this entry marked DONE?
+* Tracking TODO state changes:: When did the status change?
+* Tracking your habits:: How consistent have you been?
Tags
-* Tag inheritance:: Tags use the tree structure of the outline
-* Setting tags:: How to assign tags to a headline
-* Tag searches:: Searching for combinations of tags
+* Tag inheritance:: Tags use the tree structure of the outline
+* Setting tags:: How to assign tags to a headline
+* Tag searches:: Searching for combinations of tags
Properties and columns
-* Property syntax:: How properties are spelled out
-* Special properties:: Access to other Org-mode features
-* Property searches:: Matching property values
-* Property inheritance:: Passing values down the tree
-* Column view:: Tabular viewing and editing
-* Property API:: Properties for Lisp programmers
+* Property syntax:: How properties are spelled out
+* Special properties:: Access to other Org-mode features
+* Property searches:: Matching property values
+* Property inheritance:: Passing values down the tree
+* Column view:: Tabular viewing and editing
+* Property API:: Properties for Lisp programmers
Column view
-* Defining columns:: The COLUMNS format property
-* Using column view:: How to create and use column view
-* Capturing column view:: A dynamic block for column view
+* Defining columns:: The COLUMNS format property
+* Using column view:: How to create and use column view
+* Capturing column view:: A dynamic block for column view
Defining columns
-* Scope of column definitions:: Where defined, where valid?
-* Column attributes:: Appearance and content of a column
+* Scope of column definitions:: Where defined, where valid?
+* Column attributes:: Appearance and content of a column
Dates and times
-* Timestamps:: Assigning a time to a tree entry
-* Creating timestamps:: Commands which insert timestamps
-* Deadlines and scheduling:: Planning your work
-* Clocking work time:: Tracking how long you spend on a task
-* Resolving idle time:: Resolving time if you've been idle
-* Effort estimates:: Planning work effort in advance
-* Relative timer:: Notes with a running timer
+* Timestamps:: Assigning a time to a tree entry
+* Creating timestamps:: Commands which insert timestamps
+* Deadlines and scheduling:: Planning your work
+* Clocking work time:: Tracking how long you spend on a task
+* Resolving idle time:: Resolving time if you've been idle
+* Effort estimates:: Planning work effort in advance
+* Relative timer:: Notes with a running timer
Creating timestamps
-* The date/time prompt:: How Org-mode helps you entering date and time
-* Custom time format:: Making dates look different
+* The date/time prompt:: How Org-mode helps you entering date and time
+* Custom time format:: Making dates look different
Deadlines and scheduling
-* Inserting deadline/schedule:: Planning items
-* Repeated tasks:: Items that show up again and again
+* Inserting deadline/schedule:: Planning items
+* Repeated tasks:: Items that show up again and again
Capture - Refile - Archive
-* Capture:: Capturing new stuff
-* Attachments:: Add files to tasks
-* RSS Feeds:: Getting input from RSS feeds
-* Protocols:: External (e.g. Browser) access to Emacs and Org
-* Refiling notes:: Moving a tree from one place to another
-* Archiving:: What to do with finished projects
+* Capture:: Capturing new stuff
+* Attachments:: Add files to tasks
+* RSS Feeds:: Getting input from RSS feeds
+* Protocols:: External (e.g. Browser) access to Emacs and Org
+* Refiling notes:: Moving a tree from one place to another
+* Archiving:: What to do with finished projects
Capture
-* Setting up capture:: Where notes will be stored
-* Using capture:: Commands to invoke and terminate capture
-* Capture templates:: Define the outline of different note types
+* Setting up capture:: Where notes will be stored
+* Using capture:: Commands to invoke and terminate capture
+* Capture templates:: Define the outline of different note types
Capture templates
-* Template elements:: What is needed for a complete template entry
-* Template expansion:: Filling in information about time and context
+* Template elements:: What is needed for a complete template entry
+* Template expansion:: Filling in information about time and context
Archiving
-* Moving subtrees:: Moving a tree to an archive file
-* Internal archiving:: Switch off a tree but keep it in the file
+* Moving subtrees:: Moving a tree to an archive file
+* Internal archiving:: Switch off a tree but keep it in the file
Agenda views
-* Agenda files:: Files being searched for agenda information
-* Agenda dispatcher:: Keyboard access to agenda views
-* Built-in agenda views:: What is available out of the box?
-* Presentation and sorting:: How agenda items are prepared for display
-* Agenda commands:: Remote editing of Org trees
-* Custom agenda views:: Defining special searches and views
-* Exporting Agenda Views:: Writing a view to a file
-* Agenda column view:: Using column view for collected entries
+* Agenda files:: Files being searched for agenda information
+* Agenda dispatcher:: Keyboard access to agenda views
+* Built-in agenda views:: What is available out of the box?
+* Presentation and sorting:: How agenda items are prepared for display
+* Agenda commands:: Remote editing of Org trees
+* Custom agenda views:: Defining special searches and views
+* Exporting Agenda Views:: Writing a view to a file
+* Agenda column view:: Using column view for collected entries
The built-in agenda views
-* Weekly/daily agenda:: The calendar page with current tasks
-* Global TODO list:: All unfinished action items
+* Weekly/daily agenda:: The calendar page with current tasks
+* Global TODO list:: All unfinished action items
* Matching tags and properties:: Structured information with fine-tuned search
-* Timeline:: Time-sorted view for single file
-* Search view:: Find entries by searching for text
-* Stuck projects:: Find projects you need to review
+* Timeline:: Time-sorted view for single file
+* Search view:: Find entries by searching for text
+* Stuck projects:: Find projects you need to review
Presentation and sorting
-* Categories:: Not all tasks are equal
-* Time-of-day specifications:: How the agenda knows the time
-* Sorting of agenda items:: The order of things
+* Categories:: Not all tasks are equal
+* Time-of-day specifications:: How the agenda knows the time
+* Sorting of agenda items:: The order of things
Custom agenda views
-* Storing searches:: Type once, use often
-* Block agenda:: All the stuff you need in a single buffer
-* Setting Options:: Changing the rules
+* Storing searches:: Type once, use often
+* Block agenda:: All the stuff you need in a single buffer
+* Setting Options:: Changing the rules
Markup for rich export
-* Structural markup elements:: The basic structure as seen by the exporter
-* Images and tables:: Tables and Images will be included
-* Literal examples:: Source code examples with special formatting
-* Include files:: Include additional files into a document
-* Index entries:: Making an index
-* Macro replacement:: Use macros to create complex output
-* Embedded LaTeX:: LaTeX can be freely used inside Org documents
+* Structural markup elements:: The basic structure as seen by the exporter
+* Images and tables:: Tables and Images will be included
+* Literal examples:: Source code examples with special formatting
+* Include files:: Include additional files into a document
+* Index entries:: Making an index
+* Macro replacement:: Use macros to create complex output
+* Embedded LaTeX:: LaTeX can be freely used inside Org documents
Structural markup elements
-* Document title:: Where the title is taken from
-* Headings and sections:: The document structure as seen by the exporter
-* Table of contents:: The if and where of the table of contents
-* Initial text:: Text before the first heading?
-* Lists:: Lists
-* Paragraphs:: Paragraphs
-* Footnote markup:: Footnotes
-* Emphasis and monospace:: Bold, italic, etc.
-* Horizontal rules:: Make a line
-* Comment lines:: What will *not* be exported
+* Document title:: Where the title is taken from
+* Headings and sections:: The document structure as seen by the exporter
+* Table of contents:: The if and where of the table of contents
+* Initial text:: Text before the first heading?
+* Lists:: Lists
+* Paragraphs:: Paragraphs
+* Footnote markup:: Footnotes
+* Emphasis and monospace:: Bold, italic, etc.
+* Horizontal rules:: Make a line
+* Comment lines:: What will *not* be exported
Embedded La@TeX{}
-* Special symbols:: Greek letters and other symbols
-* Subscripts and superscripts:: Simple syntax for raising/lowering text
-* LaTeX fragments:: Complex formulas made easy
-* Previewing LaTeX fragments:: What will this snippet look like?
-* CDLaTeX mode:: Speed up entering of formulas
+* Special symbols:: Greek letters and other symbols
+* Subscripts and superscripts:: Simple syntax for raising/lowering text
+* LaTeX fragments:: Complex formulas made easy
+* Previewing LaTeX fragments:: What will this snippet look like?
+* CDLaTeX mode:: Speed up entering of formulas
Exporting
-* Selective export:: Using tags to select and exclude trees
-* Export options:: Per-file export settings
-* The export dispatcher:: How to access exporter commands
-* ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding
-* HTML export:: Exporting to HTML
-* LaTeX and PDF export:: Exporting to La@TeX{}, and processing to PDF
-* DocBook export:: Exporting to DocBook
-* TaskJuggler export:: Exporting to TaskJuggler
-* Freemind export:: Exporting to Freemind mind maps
-* XOXO export:: Exporting to XOXO
-* iCalendar export:: Exporting in iCalendar format
+* Selective export:: Using tags to select and exclude trees
+* Export options:: Per-file export settings
+* The export dispatcher:: How to access exporter commands
+* ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding
+* HTML export:: Exporting to HTML
+* LaTeX and PDF export:: Exporting to La@TeX{}, and processing to PDF
+* DocBook export:: Exporting to DocBook
+* TaskJuggler export:: Exporting to TaskJuggler
+* Freemind export:: Exporting to Freemind mind maps
+* XOXO export:: Exporting to XOXO
+* iCalendar export:: Exporting in iCalendar format
HTML export
-* HTML Export commands:: How to invoke HTML export
-* Quoting HTML tags:: Using direct HTML in Org-mode
-* Links in HTML export:: How links will be interpreted and formatted
-* Tables in HTML export:: How to modify the formatting of tables
-* Images in HTML export:: How to insert figures into HTML output
+* HTML Export commands:: How to invoke HTML export
+* Quoting HTML tags:: Using direct HTML in Org-mode
+* Links in HTML export:: How links will be interpreted and formatted
+* Tables in HTML export:: How to modify the formatting of tables
+* Images in HTML export:: How to insert figures into HTML output
* Math formatting in HTML export:: Beautiful math also on the web
-* Text areas in HTML export:: An alternative way to show an example
-* CSS support:: Changing the appearance of the output
-* JavaScript support:: Info and Folding in a web browser
+* Text areas in HTML export:: An alternative way to show an example
+* CSS support:: Changing the appearance of the output
+* JavaScript support:: Info and Folding in a web browser
La@TeX{} and PDF export
-* LaTeX/PDF export commands:: Which key invokes which commands
-* Header and sectioning:: Setting up the export file structure
-* Quoting LaTeX code:: Incorporating literal La@TeX{} code
-* Tables in LaTeX export:: Options for exporting tables to La@TeX{}
-* Images in LaTeX export:: How to insert figures into La@TeX{} output
-* Beamer class export:: Turning the file into a presentation
+* LaTeX/PDF export commands:: Which key invokes which commands
+* Header and sectioning:: Setting up the export file structure
+* Quoting LaTeX code:: Incorporating literal La@TeX{} code
+* Tables in LaTeX export:: Options for exporting tables to La@TeX{}
+* Images in LaTeX export:: How to insert figures into La@TeX{} output
+* Beamer class export:: Turning the file into a presentation
DocBook export
-* DocBook export commands:: How to invoke DocBook export
-* Quoting DocBook code:: Incorporating DocBook code in Org files
-* Recursive sections:: Recursive sections in DocBook
-* Tables in DocBook export:: Tables are exported as HTML tables
-* Images in DocBook export:: How to insert figures into DocBook output
-* Special characters:: How to handle special characters
+* DocBook export commands:: How to invoke DocBook export
+* Quoting DocBook code:: Incorporating DocBook code in Org files
+* Recursive sections:: Recursive sections in DocBook
+* Tables in DocBook export:: Tables are exported as HTML tables
+* Images in DocBook export:: How to insert figures into DocBook output
+* Special characters:: How to handle special characters
Publishing
-* Configuration:: Defining projects
-* Uploading files:: How to get files up on the server
-* Sample configuration:: Example projects
-* Triggering publication:: Publication commands
+* Configuration:: Defining projects
+* Uploading files:: How to get files up on the server
+* Sample configuration:: Example projects
+* Triggering publication:: Publication commands
Configuration
-* Project alist:: The central configuration variable
-* Sources and destinations:: From here to there
-* Selecting files:: What files are part of the project?
-* Publishing action:: Setting the function doing the publishing
-* Publishing options:: Tweaking HTML export
-* Publishing links:: Which links keep working after publishing?
-* Sitemap:: Generating a list of all pages
-* Generating an index:: An index that reaches across pages
+* Project alist:: The central configuration variable
+* Sources and destinations:: From here to there
+* Selecting files:: What files are part of the project?
+* Publishing action:: Setting the function doing the publishing
+* Publishing options:: Tweaking HTML export
+* Publishing links:: Which links keep working after publishing?
+* Sitemap:: Generating a list of all pages
+* Generating an index:: An index that reaches across pages
Sample configuration
-* Simple example:: One-component publishing
-* Complex example:: A multi-component publishing example
+* Simple example:: One-component publishing
+* Complex example:: A multi-component publishing example
Working with source code
-* Structure of code blocks:: Code block syntax described
-* Editing source code:: Language major-mode editing
-* Exporting code blocks:: Export contents and/or results
-* Extracting source code:: Create pure source code files
-* Evaluating code blocks:: Place results of evaluation in the Org-mode buffer
-* Library of Babel:: Use and contribute to a library of useful code blocks
-* Languages:: List of supported code block languages
-* Header arguments:: Configure code block functionality
-* Results of evaluation:: How evaluation results are handled
-* Noweb reference syntax:: Literate programming in Org-mode
+* Structure of code blocks:: Code block syntax described
+* Editing source code:: Language major-mode editing
+* Exporting code blocks:: Export contents and/or results
+* Extracting source code:: Create pure source code files
+* Evaluating code blocks:: Place results of evaluation in the Org-mode buffer
+* Library of Babel:: Use and contribute to a library of useful code blocks
+* Languages:: List of supported code block languages
+* Header arguments:: Configure code block functionality
+* Results of evaluation:: How evaluation results are handled
+* Noweb reference syntax:: Literate programming in Org-mode
* Key bindings and useful functions:: Work quickly with code blocks
-* Batch execution:: Call functions from the command line
+* Batch execution:: Call functions from the command line
Header arguments
-* Using header arguments:: Different ways to set header arguments
-* Specific header arguments:: List of header arguments
+* Using header arguments:: Different ways to set header arguments
+* Specific header arguments:: List of header arguments
Using header arguments
* System-wide header arguments:: Set global default values
-* Language-specific header arguments:: Set default values by language
+* Language-specific header arguments:: Set default values by language
* Buffer-wide header arguments:: Set default values for a specific buffer
* Header arguments in Org-mode properties:: Set default values for a buffer or heading
* Code block specific header arguments:: The most common way to set values
Specific header arguments
-* var:: Pass arguments to code blocks
-* results:: Specify the type of results and how they will
+* var:: Pass arguments to code blocks
+* results:: Specify the type of results and how they will
be collected and handled
-* file:: Specify a path for file output
-* dir:: Specify the default (possibly remote)
+* file:: Specify a path for file output
+* dir:: Specify the default (possibly remote)
directory for code block execution
-* exports:: Export code and/or results
-* tangle:: Toggle tangling and specify file name
-* comments:: Toggle insertion of comments in tangled
+* exports:: Export code and/or results
+* tangle:: Toggle tangling and specify file name
+* comments:: Toggle insertion of comments in tangled
code files
-* no-expand:: Turn off variable assignment and noweb
+* no-expand:: Turn off variable assignment and noweb
expansion during tangling
-* session:: Preserve the state of code evaluation
-* noweb:: Toggle expansion of noweb references
-* cache:: Avoid re-evaluating unchanged code blocks
-* hlines:: Handle horizontal lines in tables
-* colnames:: Handle column names in tables
-* rownames:: Handle row names in tables
-* shebang:: Make tangled files executable
-* eval:: Limit evaluation of specific code blocks
+* session:: Preserve the state of code evaluation
+* noweb:: Toggle expansion of noweb references
+* cache:: Avoid re-evaluating unchanged code blocks
+* hlines:: Handle horizontal lines in tables
+* colnames:: Handle column names in tables
+* rownames:: Handle row names in tables
+* shebang:: Make tangled files executable
+* eval:: Limit evaluation of specific code blocks
Miscellaneous
-* Completion:: M-TAB knows what you need
-* Easy Templates::
-* Speed keys:: Electric commands at the beginning of a headline
-* Code evaluation security:: Org mode files evaluate inline code
-* Customization:: Adapting Org to your taste
-* In-buffer settings:: Overview of the #+KEYWORDS
-* The very busy C-c C-c key:: When in doubt, press C-c C-c
-* Clean view:: Getting rid of leading stars in the outline
-* TTY keys:: Using Org on a tty
-* Interaction:: Other Emacs packages
+* Completion:: M-TAB knows what you need
+* Easy Templates:: Quick insertion of structural elements
+* Speed keys:: Electric commands at the beginning of a headline
+* Code evaluation security:: Org mode files evaluate inline code
+* Customization:: Adapting Org to your taste
+* In-buffer settings:: Overview of the #+KEYWORDS
+* The very busy C-c C-c key:: When in doubt, press C-c C-c
+* Clean view:: Getting rid of leading stars in the outline
+* TTY keys:: Using Org on a tty
+* Interaction:: Other Emacs packages
Interaction with other packages
-* Cooperation:: Packages Org cooperates with
-* Conflicts:: Packages that lead to conflicts
+* Cooperation:: Packages Org cooperates with
+* Conflicts:: Packages that lead to conflicts
Hacking
-* Hooks:: Who to reach into Org's internals
-* Add-on packages:: Available extensions
-* Adding hyperlink types:: New custom link types
-* Context-sensitive commands:: How to add functionality to such commands
-* Tables in arbitrary syntax:: Orgtbl for La@TeX{} and other programs
-* Dynamic blocks:: Automatically filled blocks
-* Special agenda views:: Customized views
+* Hooks:: Who to reach into Org's internals
+* Add-on packages:: Available extensions
+* Adding hyperlink types:: New custom link types
+* Context-sensitive commands:: How to add functionality to such commands
+* Tables in arbitrary syntax:: Orgtbl for La@TeX{} and other programs
+* Dynamic blocks:: Automatically filled blocks
+* Special agenda views:: Customized views
* Extracting agenda information:: Postprocessing of agenda information
-* Using the property API:: Writing programs that use entry properties
-* Using the mapping API:: Mapping over all or selected entries
+* Using the property API:: Writing programs that use entry properties
+* Using the mapping API:: Mapping over all or selected entries
Tables and lists in arbitrary syntax
-* Radio tables:: Sending and receiving radio tables
-* A LaTeX example:: Step by step, almost a tutorial
-* Translator functions:: Copy and modify
-* Radio lists:: Doing the same for lists
+* Radio tables:: Sending and receiving radio tables
+* A LaTeX example:: Step by step, almost a tutorial
+* Translator functions:: Copy and modify
+* Radio lists:: Doing the same for lists
MobileOrg
-* Setting up the staging area:: Where to interact with the mobile device
-* Pushing to MobileOrg:: Uploading Org files and agendas
-* Pulling from MobileOrg:: Integrating captured and flagged items
+* Setting up the staging area:: Where to interact with the mobile device
+* Pushing to MobileOrg:: Uploading Org files and agendas
+* Pulling from MobileOrg:: Integrating captured and flagged items
@end detailmenu
@end menu
@@ -512,11 +532,11 @@ MobileOrg
@cindex introduction
@menu
-* Summary:: Brief summary of what Org does
-* Installation:: How to install a downloaded version of Org
-* Activation:: How to activate Org for certain buffers
-* Feedback:: Bug reports, ideas, patches etc.
-* Conventions:: Type-setting conventions in the manual
+* Summary:: Brief summary of what Org does
+* Installation:: How to install a downloaded version of Org
+* Activation:: How to activate Org for certain buffers
+* Feedback:: Bug reports, ideas, patches etc.
+* Conventions:: Type-setting conventions in the manual
@end menu
@node Summary, Installation, Introduction, Introduction
@@ -615,18 +635,6 @@ step for this directory:
(setq load-path (cons "~/path/to/orgdir/contrib/lisp" load-path))
@end example
-@sp 2
-@cartouche
-XEmacs users now need to install the file @file{noutline.el} from
-the @file{xemacs} sub-directory of the Org distribution. Use the
-command:
-
-@example
- make install-noutline
-@end example
-@end cartouche
-@sp 2
-
@noindent Now byte-compile the Lisp files with the shell command:
@example
@@ -727,10 +735,15 @@ 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}.
If you are not a member of the mailing list, your mail will be passed to the
-list after a moderator has approved it.
-
-For bug reports, please provide as much information as possible, including
-the version information of Emacs (@kbd{M-x emacs-version @key{RET}}) and Org
+list after a moderator has approved it@footnote{Please consider subscribing
+to the mailing list, in order to minimize the work the mailing list
+moderators have to do.}.
+
+For bug reports, please first try to reproduce the bug with the latest
+version of Org available - if you are running an outdated version, it is
+quite possible that the bug has been fixed already. If the bug persists,
+prepare a report and provide as much information as possible, including the
+version information of Emacs (@kbd{M-x emacs-version @key{RET}}) and Org
(@kbd{M-x org-version @key{RET}}), as well as the Org related setup in
@file{.emacs}. The easiest way to do this is to use the command
@example
@@ -749,7 +762,7 @@ about:
@item What did you expect to happen?
@item What happened instead?
@end enumerate
-@noindent Thank you for helping to improve this mode.
+@noindent Thank you for helping to improve this program.
@subsubheading How to create a useful backtrace
@@ -813,17 +826,17 @@ Org is based on Outline mode and provides flexible commands to
edit the structure of the document.
@menu
-* Outlines:: Org is based on Outline mode
-* Headlines:: How to typeset Org tree headlines
-* Visibility cycling:: Show and hide, much simplified
-* Motion:: Jumping to other headlines
-* Structure editing:: Changing sequence and level of headlines
-* Sparse trees:: Matches embedded in context
-* Plain lists:: Additional structure within an entry
-* Drawers:: Tucking stuff away
-* Blocks:: Folding blocks
-* Footnotes:: How footnotes are defined in Org's syntax
-* Orgstruct mode:: Structure editing outside Org
+* Outlines:: Org is based on Outline mode
+* Headlines:: How to typeset Org tree headlines
+* Visibility cycling:: Show and hide, much simplified
+* Motion:: Jumping to other headlines
+* Structure editing:: Changing sequence and level of headlines
+* Sparse trees:: Matches embedded in context
+* Plain lists:: Additional structure within an entry
+* Drawers:: Tucking stuff away
+* Blocks:: Folding blocks
+* Footnotes:: How footnotes are defined in Org's syntax
+* Orgstruct mode:: Structure editing outside Org
@end menu
@node Outlines, Headlines, Document Structure, Document Structure
@@ -893,9 +906,8 @@ Org uses just two commands, bound to @key{TAB} and
@cindex folded, subtree visibility state
@cindex children, subtree visibility state
@cindex subtree, subtree visibility state
-@table @kbd
-@kindex @key{TAB}
-@item @key{TAB}
+@table @asis
+@orgcmd{@key{TAB},org-cycle}
@emph{Subtree cycling}: Rotate current subtree among the states
@example
@@ -917,8 +929,7 @@ argument (@kbd{C-u @key{TAB}}), global cycling is invoked.
@cindex overview, global visibility state
@cindex contents, global visibility state
@cindex show all, global visibility state
-@kindex S-@key{TAB}
-@item S-@key{TAB}
+@orgcmd{S-@key{TAB},org-global-cycle}
@itemx C-u @key{TAB}
@emph{Global cycling}: Rotate the entire buffer among the states
@@ -932,22 +943,18 @@ CONTENTS view up to headlines of level N will be shown. Note that inside
tables, @kbd{S-@key{TAB}} jumps to the previous field.
@cindex show all, command
-@kindex C-u C-u C-u @key{TAB}
-@item C-u C-u C-u @key{TAB}
+@orgcmd{C-u C-u C-u @key{TAB},show-all}
Show all, including drawers.
-@kindex C-c C-r
-@item C-c C-r
+@orgcmd{C-c C-r,org-reveal}
Reveal context around point, showing the current entry, the following heading
and the hierarchy above. Useful for working near a location that has been
exposed by a sparse tree command (@pxref{Sparse trees}) or an agenda command
(@pxref{Agenda commands}). With a prefix argument show, on each
level, all sibling headings. With double prefix arg, also show the entire
subtree of the parent.
-@kindex C-c C-k
-@item C-c C-k
+@orgcmd{C-c C-k,show-branches}
Expose all the headings of the subtree, CONTENT view for just one subtree.
-@kindex C-c C-x b
-@item C-c C-x b
+@orgcmd{C-c C-x b,org-tree-to-indirect-buffer}
Show the current subtree in an indirect buffer@footnote{The indirect
buffer
@ifinfo
@@ -989,9 +996,8 @@ Furthermore, any entries with a @samp{VISIBILITY} property (@pxref{Properties
and Columns}) will get their visibility adapted accordingly. Allowed values
for this property are @code{folded}, @code{children}, @code{content}, and
@code{all}.
-@table @kbd
-@kindex C-u C-u @key{TAB}
-@item C-u C-u @key{TAB}
+@table @asis
+@orgcmd{C-u C-u @key{TAB},org-set-startup-visibility}
Switch back to the startup visibility of the buffer, i.e. whatever is
requested by startup options and @samp{VISIBILITY} properties in individual
entries.
@@ -1004,24 +1010,18 @@ entries.
@cindex headline navigation
The following commands jump to other headlines in the buffer.
-@table @kbd
-@kindex C-c C-n
-@item C-c C-n
+@table @asis
+@orgcmd{C-c C-n,outline-next-visible-heading}
Next heading.
-@kindex C-c C-p
-@item C-c C-p
+@orgcmd{C-c C-p,outline-previous-visible-heading}
Previous heading.
-@kindex C-c C-f
-@item C-c C-f
+@orgcmd{C-c C-f,org-forward-same-level}
Next heading same level.
-@kindex C-c C-b
-@item C-c C-b
+@orgcmd{C-c C-b,org-backward-same-level}
Previous heading same level.
-@kindex C-c C-u
-@item C-c C-u
+@orgcmd{C-c C-u,outline-up-heading}
Backward to higher level heading.
-@kindex C-c C-j
-@item C-c C-j
+@orgcmd{C-c C-j,org-goto}
Jump to a different place without changing the current outline
visibility. Shows the document structure in a temporary buffer, where
you can use the following keys to find your destination:
@@ -1056,9 +1056,8 @@ See also the variable @code{org-goto-interface}.
@cindex sorting, of subtrees
@cindex subtrees, cut and paste
-@table @kbd
-@kindex M-@key{RET}
-@item M-@key{RET}
+@table @asis
+@orgcmd{M-@key{RET},org-insert-heading}
@vindex org-M-RET-may-split-line
Insert new heading with same level as current. If the cursor is in a
plain list item, a new item is created (@pxref{Plain lists}). To force
@@ -1088,47 +1087,36 @@ variable @code{org-treat-insert-todo-heading-as-state-change}.
Insert new TODO entry with same level as current heading. Like
@kbd{C-@key{RET}}, the new headline will be inserted after the current
subtree.
-@kindex @key{TAB}
-@item @key{TAB} @r{in new, empty entry}
+@orgcmd{@key{TAB},org-cycle}
In a new entry with no text yet, the first @key{TAB} demotes the entry to
become a child of the previous one. The next @key{TAB} makes it a parent,
and so on, all the way to top level. Yet another @key{TAB}, and you are back
to the initial level.
-@kindex M-@key{left}
-@item M-@key{left}
+@orgcmd{M-@key{left},org-do-promote}
Promote current heading by one level.
-@kindex M-@key{right}
-@item M-@key{right}
+@orgcmd{M-@key{right},org-do-demote}
Demote current heading by one level.
-@kindex M-S-@key{left}
-@item M-S-@key{left}
+@orgcmd{M-S-@key{left},org-promote-subtree}
Promote the current subtree by one level.
-@kindex M-S-@key{right}
-@item M-S-@key{right}
+@orgcmd{M-S-@key{right},org-demote-subtree}
Demote the current subtree by one level.
-@kindex M-S-@key{up}
-@item M-S-@key{up}
+@orgcmd{M-S-@key{up},org-move-subtree-up}
Move subtree up (swap with previous subtree of same
level).
-@kindex M-S-@key{down}
-@item M-S-@key{down}
+@orgcmd{M-S-@key{down},org-move-subtree-down}
Move subtree down (swap with next subtree of same level).
-@kindex C-c C-x C-w
-@item C-c C-x C-w
+@orgcmd{C-c C-x C-w,org-cut-subtree}
Kill subtree, i.e. remove it from buffer but save in kill ring.
With a numeric prefix argument N, kill N sequential subtrees.
-@kindex C-c C-x M-w
-@item C-c C-x M-w
+@orgcmd{C-c C-x M-w,org-copy-subtree}
Copy subtree to kill ring. With a numeric prefix argument N, copy the N
sequential subtrees.
-@kindex C-c C-x C-y
-@item C-c C-x C-y
+@orgcmd{C-c C-x C-y,org-paste-subtree}
Yank subtree from kill ring. This does modify the level of the subtree to
make sure the tree fits in nicely at the yank position. The yank level can
also be specified with a numeric prefix argument, or by yanking after a
headline marker like @samp{****}.
-@kindex C-y
-@item C-y
+@orgcmd{C-y,org-yank}
@vindex org-yank-adjusted-subtrees
@vindex org-yank-folded-subtrees
Depending on the variables @code{org-yank-adjusted-subtrees} and
@@ -1141,19 +1129,16 @@ previously visible. Any prefix argument to this command will force a normal
force a normal yank is @kbd{C-u C-y}. If you use @code{yank-pop} after a
yank, it will yank previous kill items plainly, without adjustment and
folding.
-@kindex C-c C-x c
-@item C-c C-x c
+@orgcmd{C-c C-x c,org-clone-subtree-with-time-shift}
Clone a subtree by making a number of sibling copies of it. You will be
prompted for the number of copies to make, and you can also specify if any
timestamps in the entry should be shifted. This can be useful, for example,
to create a number of tasks related to a series of lectures to prepare. For
more details, see the docstring of the command
@code{org-clone-subtree-with-time-shift}.
-@kindex C-c C-w
-@item C-c C-w
+@orgcmd{C-c C-w,org-refile}
Refile entry or region to a different location. @xref{Refiling notes}.
-@kindex C-c ^
-@item C-c ^
+@orgcmd{C-c ^,org-sort-entries-or-items}
Sort same-level entries. When there is an active region, all entries in the
region will be sorted. Otherwise the children of the current headline are
sorted. The command prompts for the sorting method, which can be
@@ -1164,14 +1149,11 @@ of a property. Reverse sorting is possible as well. You can also supply
your own function to extract the sorting key. With a @kbd{C-u} prefix,
sorting will be case-sensitive. With two @kbd{C-u C-u} prefixes, duplicate
entries will also be removed.
-@kindex C-x n s
-@item C-x n s
+@orgcmd{C-x n s,org-narrow-to-subtree}
Narrow buffer to current subtree.
-@kindex C-x n w
-@item C-x n w
+@orgcmd{C-x n w,widen}
Widen buffer to remove narrowing.
-@kindex C-c *
-@item C-c *
+@orgcmd{C-c *,org-toggle-heading}
Turn a normal line or plain list item into a headline (so that it becomes a
subheading at its location). Also turn a headline into a normal line by
removing the stars. If there is an active region, turn all lines in the
@@ -1215,9 +1197,8 @@ 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:
-@table @kbd
-@kindex C-c /
-@item C-c /
+@table @asis
+@orgcmd{C-c /,org-sparse-tree}
This prompts for an extra key to select a sparse-tree creating command.
@kindex C-c / r
@item C-c / r
@@ -1342,9 +1323,8 @@ the current list-level) improves readability, customize the variable
The following commands act on items when the cursor is in the first line
of an item (the line with the bullet or number).
-@table @kbd
-@kindex @key{TAB}
-@item @key{TAB}
+@table @asis
+@orgcmd{@key{TAB},org-cycle}
@vindex org-cycle-include-plain-lists
Items can be folded just like headline levels. Normally this works only if
the cursor is on a plain list item. For more details, see the variable
@@ -1355,8 +1335,7 @@ headlines, however; the hierarchies remain completely separated.
If @code{org-cycle-include-plain-lists} has not been set, @key{TAB}
fixes the indentation of the current line in a heuristic way.
-@kindex M-@key{RET}
-@item M-@key{RET}
+@orgcmd{M-@key{RET},org-insert-heading}
@vindex org-M-RET-may-split-line
Insert new item at current level. With a prefix argument, force a new
heading (@pxref{Structure editing}). If this command is used in the middle
@@ -1370,13 +1349,11 @@ bullet, a bullet is added to the current line.
@kindex M-S-@key{RET}
@item M-S-@key{RET}
Insert a new item with a checkbox (@pxref{Checkboxes}).
-@kindex @key{TAB}
-@item @key{TAB} @r{in new, empty item}
+@orgcmd{@key{TAB},org-cycle}
In a new item with no text yet, the first @key{TAB} demotes the item to
become a child of the previous one. The next @key{TAB} makes it a parent,
and so on, all the way to the left margin. Yet another @key{TAB}, and you
are back to the initial level.
-@kindex S-@key{up}
@kindex S-@key{down}
@item S-@key{up}
@itemx S-@key{down}
@@ -1648,12 +1625,12 @@ calculator).
@end ifnotinfo
@menu
-* Built-in table editor:: Simple tables
-* Column width and alignment:: Overrule the automatic settings
-* Column groups:: Grouping to trigger vertical lines
-* Orgtbl mode:: The table editor as minor mode
-* The spreadsheet:: The table editor has spreadsheet capabilities
-* Org-Plot:: Plotting from org tables
+* Built-in table editor:: Simple tables
+* Column width and alignment:: Overrule the automatic settings
+* Column groups:: Grouping to trigger vertical lines
+* Orgtbl mode:: The table editor as minor mode
+* The spreadsheet:: The table editor has spreadsheet capabilities
+* Org-Plot:: Plotting from org tables
@end menu
@node Built-in table editor, Column width and alignment, Tables, Tables
@@ -2027,14 +2004,14 @@ fields in the table corresponding to the references at the point in the
formula, moving these references by arrow keys
@menu
-* References:: How to refer to another field or range
-* Formula syntax for Calc:: Using Calc to compute stuff
-* Formula syntax for Lisp:: Writing formulas in Emacs Lisp
-* Field formulas:: Formulas valid for a single field
-* Column formulas:: Formulas valid for an entire column
+* References:: How to refer to another field or range
+* Formula syntax for Calc:: Using Calc to compute stuff
+* Formula syntax for Lisp:: Writing formulas in Emacs Lisp
+* Field formulas:: Formulas valid for a single field
+* Column formulas:: Formulas valid for an entire column
* Editing and debugging formulas:: Fixing formulas
-* Updating the table:: Recomputing all dependent fields
-* Advanced features:: Field names, parameters and automatic recalc
+* Updating the table:: Recomputing all dependent fields
+* Advanced features:: Field names, parameters and automatic recalc
@end menu
@node References, Formula syntax for Calc, The spreadsheet, The spreadsheet
@@ -2738,14 +2715,14 @@ Like HTML, Org provides links inside a file, external links to
other files, Usenet articles, emails, and much more.
@menu
-* Link format:: How links in Org are formatted
-* Internal links:: Links to other places in the current file
-* External links:: URL-like links to the world
-* Handling links:: Creating, inserting and following
-* Using links outside Org:: Linking from my C source code?
-* Link abbreviations:: Shortcuts for writing complex links
-* Search options:: Linking to a specific location
-* Custom searches:: When the default search is not enough
+* Link format:: How links in Org are formatted
+* Internal links:: Links to other places in the current file
+* External links:: URL-like links to the world
+* Handling links:: Creating, inserting and following
+* Using links outside Org:: Linking from my C source code?
+* Link abbreviations:: Shortcuts for writing complex links
+* Search options:: Linking to a specific location
+* Custom searches:: When the default search is not enough
@end menu
@node Link format, Internal links, Hyperlinks, Hyperlinks
@@ -2828,7 +2805,7 @@ several times in direct succession goes back to positions recorded
earlier.
@menu
-* Radio targets:: Make targets trigger links in plain text
+* Radio targets:: Make targets trigger links in plain text
@end menu
@node Radio targets, , Internal links, Internal links
@@ -3283,12 +3260,12 @@ throughout your notes file. Org-mode compensates for this by providing
methods to give you an overview of all the things that you have to do.
@menu
-* TODO basics:: Marking and displaying TODO entries
-* TODO extensions:: Workflow and assignments
-* Progress logging:: Dates and notes for progress
-* Priorities:: Some things are more important than others
-* Breaking down tasks:: Splitting a task into manageable pieces
-* Checkboxes:: Tick-off lists
+* TODO basics:: Marking and displaying TODO entries
+* TODO extensions:: Workflow and assignments
+* Progress logging:: Dates and notes for progress
+* Priorities:: Some things are more important than others
+* Breaking down tasks:: Splitting a task into manageable pieces
+* Checkboxes:: Tick-off lists
@end menu
@node TODO basics, TODO extensions, TODO Items, TODO Items
@@ -3380,13 +3357,13 @@ Note that @i{tags} are another way to classify headlines in general and
TODO items in particular (@pxref{Tags}).
@menu
-* Workflow states:: From TODO to DONE in steps
-* TODO types:: I do this, Fred does the rest
-* Multiple sets in one file:: Mixing it all, and still finding your way
-* Fast access to TODO states:: Single letter selection of a state
-* Per-file keywords:: Different files, different requirements
-* Faces for TODO keywords:: Highlighting states
-* TODO dependencies:: When one task needs to wait for others
+* Workflow states:: From TODO to DONE in steps
+* TODO types:: I do this, Fred does the rest
+* Multiple sets in one file:: Mixing it all, and still finding your way
+* Fast access to TODO states:: Single letter selection of a state
+* Per-file keywords:: Different files, different requirements
+* Faces for TODO keywords:: Highlighting states
+* TODO dependencies:: When one task needs to wait for others
@end menu
@node Workflow states, TODO types, TODO extensions, TODO extensions
@@ -3677,9 +3654,9 @@ information on how to clock working time for a task, see @ref{Clocking
work time}.
@menu
-* Closing items:: When was this entry marked DONE?
-* Tracking TODO state changes:: When did the status change?
-* Tracking your habits:: How consistent have you been?
+* Closing items:: When was this entry marked DONE?
+* Tracking TODO state changes:: When did the status change?
+* Tracking your habits:: How consistent have you been?
@end menu
@node Closing items, Tracking TODO state changes, Progress logging, Progress logging
@@ -4141,9 +4118,9 @@ You may specify special faces for specific tags using the variable
(@pxref{Faces for TODO keywords}).
@menu
-* Tag inheritance:: Tags use the tree structure of the outline
-* Setting tags:: How to assign tags to a headline
-* Tag searches:: Searching for combinations of tags
+* Tag inheritance:: Tags use the tree structure of the outline
+* Setting tags:: How to assign tags to a headline
+* Tag searches:: Searching for combinations of tags
@end menu
@node Tag inheritance, Setting tags, Tags, Tags
@@ -4430,12 +4407,12 @@ Properties can be conveniently edited and viewed in column view
(@pxref{Column view}).
@menu
-* Property syntax:: How properties are spelled out
-* Special properties:: Access to other Org-mode features
-* Property searches:: Matching property values
-* Property inheritance:: Passing values down the tree
-* Column view:: Tabular viewing and editing
-* Property API:: Properties for Lisp programmers
+* Property syntax:: How properties are spelled out
+* Special properties:: Access to other Org-mode features
+* Property searches:: Matching property values
+* Property inheritance:: Passing values down the tree
+* Column view:: Tabular viewing and editing
+* Property API:: Properties for Lisp programmers
@end menu
@node Property syntax, Special properties, Properties and Columns, Properties and Columns
@@ -4671,9 +4648,9 @@ Column view also works in agenda buffers (@pxref{Agenda Views}) where
queries have collected selected items, possibly from a number of files.
@menu
-* Defining columns:: The COLUMNS format property
-* Using column view:: How to create and use column view
-* Capturing column view:: A dynamic block for column view
+* Defining columns:: The COLUMNS format property
+* Using column view:: How to create and use column view
+* Capturing column view:: A dynamic block for column view
@end menu
@node Defining columns, Using column view, Column view, Column view
@@ -4685,8 +4662,8 @@ Setting up a column view first requires defining the columns. This is
done by defining a column format line.
@menu
-* Scope of column definitions:: Where defined, where valid?
-* Column attributes:: Appearance and content of a column
+* Scope of column definitions:: Where defined, where valid?
+* Column attributes:: Appearance and content of a column
@end menu
@node Scope of column definitions, Column attributes, Defining columns, Defining columns
@@ -4785,7 +4762,7 @@ values.
@example
:COLUMNS: %25ITEM %9Approved(Approved?)@{X@} %Owner %11Status \@footnote{Please note that the COLUMNS definition must be on a single line---it is wrapped here only because of formatting constraints.}
- %10Time_Estimate@{:@} %CLOCKSUM
+ %10Time_Estimate@{:@} %CLOCKSUM
:Owner_ALL: Tammy Mark Karl Lisa Don
:Status_ALL: "In progress" "Not started yet" "Finished" ""
:Approved_ALL: "[ ]" "[X]"
@@ -4985,13 +4962,13 @@ something was created or last changed. However, in Org-mode this term
is used in a much wider sense.
@menu
-* Timestamps:: Assigning a time to a tree entry
-* Creating timestamps:: Commands which insert timestamps
-* Deadlines and scheduling:: Planning your work
-* Clocking work time:: Tracking how long you spend on a task
-* Resolving idle time:: Resolving time if you've been idle
-* Effort estimates:: Planning work effort in advance
-* Relative timer:: Notes with a running timer
+* Timestamps:: Assigning a time to a tree entry
+* Creating timestamps:: Commands which insert timestamps
+* Deadlines and scheduling:: Planning your work
+* Clocking work time:: Tracking how long you spend on a task
+* Resolving idle time:: Resolving time if you've been idle
+* Effort estimates:: Planning work effort in advance
+* Relative timer:: Notes with a running timer
@end menu
@@ -5147,8 +5124,8 @@ the following column).
@menu
-* The date/time prompt:: How Org-mode helps you entering date and time
-* Custom time format:: Making dates look different
+* The date/time prompt:: How Org-mode helps you entering date and time
+* Custom time format:: Making dates look different
@end menu
@node The date/time prompt, Custom time format, Creating timestamps, Creating timestamps
@@ -5390,8 +5367,8 @@ late warnings. However, it will show the item on each day where the
sexp entry matches.
@menu
-* Inserting deadline/schedule:: Planning items
-* Repeated tasks:: Items that show up again and again
+* Inserting deadline/schedule:: Planning items
+* Repeated tasks:: Items that show up again and again
@end menu
@node Inserting deadline/schedule, Repeated tasks, Deadlines and scheduling, Deadlines and scheduling
@@ -5912,12 +5889,12 @@ system, tasks and projects need to be moved around. Moving completed project
trees to an archive file keeps the system compact and fast.
@menu
-* Capture:: Capturing new stuff
-* Attachments:: Add files to tasks
-* RSS Feeds:: Getting input from RSS feeds
-* Protocols:: External (e.g. Browser) access to Emacs and Org
-* Refiling notes:: Moving a tree from one place to another
-* Archiving:: What to do with finished projects
+* Capture:: Capturing new stuff
+* Attachments:: Add files to tasks
+* RSS Feeds:: Getting input from RSS feeds
+* Protocols:: External (e.g. Browser) access to Emacs and Org
+* Refiling notes:: Moving a tree from one place to another
+* Archiving:: What to do with finished projects
@end menu
@node Capture, Attachments, Capture - Refile - Archive, Capture - Refile - Archive
@@ -5945,9 +5922,9 @@ flow. The basic process of capturing is very similar to remember, but Org
does enhance it with templates and more.
@menu
-* Setting up capture:: Where notes will be stored
-* Using capture:: Commands to invoke and terminate capture
-* Capture templates:: Define the outline of different note types
+* Setting up capture:: Where notes will be stored
+* Using capture:: Commands to invoke and terminate capture
+* Capture templates:: Define the outline of different note types
@end menu
@node Setting up capture, Using capture, Capture, Capture
@@ -6041,8 +6018,8 @@ place where you started the capture process.
@menu
-* Template elements:: What is needed for a complete template entry
-* Template expansion:: Filling in information about time and context
+* Template elements:: What is needed for a complete template entry
+* Template expansion:: Filling in information about time and context
@end menu
@node Template elements, Template expansion, Capture templates, Capture templates
@@ -6353,8 +6330,8 @@ information. Here is just an example:
@example
(setq org-feed-alist
'(("Slashdot"
- "http://rss.slashdot.org/Slashdot/slashdot"
- "~/txt/org/feeds.org" "Slashdot Entries")))
+ "http://rss.slashdot.org/Slashdot/slashdot"
+ "~/txt/org/feeds.org" "Slashdot Entries")))
@end example
@noindent
@@ -6467,8 +6444,8 @@ Archive the current entry using the command specified in the variable
@end table
@menu
-* Moving subtrees:: Moving a tree to an archive file
-* Internal archiving:: Switch off a tree but keep it in the file
+* Moving subtrees:: Moving a tree to an archive file
+* Internal archiving:: Switch off a tree but keep it in the file
@end menu
@node Moving subtrees, Internal archiving, Archiving, Archiving
@@ -6645,14 +6622,14 @@ window configuration is restored when the agenda exits:
@code{org-agenda-restore-windows-after-quit}.
@menu
-* Agenda files:: Files being searched for agenda information
-* Agenda dispatcher:: Keyboard access to agenda views
-* Built-in agenda views:: What is available out of the box?
-* Presentation and sorting:: How agenda items are prepared for display
-* Agenda commands:: Remote editing of Org trees
-* Custom agenda views:: Defining special searches and views
-* Exporting Agenda Views:: Writing a view to a file
-* Agenda column view:: Using column view for collected entries
+* Agenda files:: Files being searched for agenda information
+* Agenda dispatcher:: Keyboard access to agenda views
+* Built-in agenda views:: What is available out of the box?
+* Presentation and sorting:: How agenda items are prepared for display
+* Agenda commands:: Remote editing of Org trees
+* Custom agenda views:: Defining special searches and views
+* Exporting Agenda Views:: Writing a view to a file
+* Agenda column view:: Using column view for collected entries
@end menu
@node Agenda files, Agenda dispatcher, Agenda Views, Agenda Views
@@ -6794,12 +6771,12 @@ a number of special tags matches. @xref{Custom agenda views}.
In this section we describe the built-in views.
@menu
-* Weekly/daily agenda:: The calendar page with current tasks
-* Global TODO list:: All unfinished action items
+* Weekly/daily agenda:: The calendar page with current tasks
+* Global TODO list:: All unfinished action items
* Matching tags and properties:: Structured information with fine-tuned search
-* Timeline:: Time-sorted view for single file
-* Search view:: Find entries by searching for text
-* Stuck projects:: Find projects you need to review
+* Timeline:: Time-sorted view for single file
+* Search view:: Find entries by searching for text
+* Stuck projects:: Find projects you need to review
@end menu
@node Weekly/daily agenda, Global TODO list, Built-in agenda views, Built-in agenda views
@@ -7264,9 +7241,9 @@ The prefix is followed by a cleaned-up version of the outline headline
associated with the item.
@menu
-* Categories:: Not all tasks are equal
-* Time-of-day specifications:: How the agenda knows the time
-* Sorting of agenda items:: The order of things
+* Categories:: Not all tasks are equal
+* Time-of-day specifications:: How the agenda knows the time
+* Sorting of agenda items:: The order of things
@end menu
@node Categories, Time-of-day specifications, Presentation and sorting, Presentation and sorting
@@ -7661,12 +7638,12 @@ Internet, and outside of business hours, with something like this:
@group
(defun org-my-auto-exclude-function (tag)
(and (cond
- ((string= tag "Net")
- (/= 0 (call-process "/sbin/ping" nil nil nil
- "-c1" "-q" "-t1" "mail.gnu.org")))
- ((or (string= tag "Errand") (string= tag "Call"))
- (let ((hour (nth 2 (decode-time))))
- (or (< hour 8) (> hour 21)))))
+ ((string= tag "Net")
+ (/= 0 (call-process "/sbin/ping" nil nil nil
+ "-c1" "-q" "-t1" "mail.gnu.org")))
+ ((or (string= tag "Errand") (string= tag "Call"))
+ (let ((hour (nth 2 (decode-time))))
+ (or (< hour 8) (> hour 21)))))
(concat "-" tag)))
(setq org-agenda-auto-exclude-function 'org-my-auto-exclude-function)
@@ -7996,9 +7973,9 @@ agenda buffers. Custom agenda commands will be accessible through the
dispatcher (@pxref{Agenda dispatcher}), just like the default commands.
@menu
-* Storing searches:: Type once, use often
-* Block agenda:: All the stuff you need in a single buffer
-* Setting Options:: Changing the rules
+* Storing searches:: Type once, use often
+* Block agenda:: All the stuff you need in a single buffer
+* Setting Options:: Changing the rules
@end menu
@node Storing searches, Block agenda, Custom agenda views, Custom agenda views
@@ -8383,29 +8360,29 @@ Org-mode has rules on how to prepare text for rich export. This section
summarizes the markup rules used in an Org-mode buffer.
@menu
-* Structural markup elements:: The basic structure as seen by the exporter
-* Images and tables:: Tables and Images will be included
-* Literal examples:: Source code examples with special formatting
-* Include files:: Include additional files into a document
-* Index entries:: Making an index
-* Macro replacement:: Use macros to create complex output
-* Embedded LaTeX:: LaTeX can be freely used inside Org documents
+* Structural markup elements:: The basic structure as seen by the exporter
+* Images and tables:: Tables and Images will be included
+* Literal examples:: Source code examples with special formatting
+* Include files:: Include additional files into a document
+* Index entries:: Making an index
+* Macro replacement:: Use macros to create complex output
+* Embedded LaTeX:: LaTeX can be freely used inside Org documents
@end menu
@node Structural markup elements, Images and tables, Markup, Markup
@section Structural markup elements
@menu
-* Document title:: Where the title is taken from
-* Headings and sections:: The document structure as seen by the exporter
-* Table of contents:: The if and where of the table of contents
-* Initial text:: Text before the first heading?
-* Lists:: Lists
-* Paragraphs:: Paragraphs
-* Footnote markup:: Footnotes
-* Emphasis and monospace:: Bold, italic, etc.
-* Horizontal rules:: Make a line
-* Comment lines:: What will *not* be exported
+* Document title:: Where the title is taken from
+* Headings and sections:: The document structure as seen by the exporter
+* Table of contents:: The if and where of the table of contents
+* Initial text:: Text before the first heading?
+* Lists:: Lists
+* Paragraphs:: Paragraphs
+* Footnote markup:: Footnotes
+* Emphasis and monospace:: Bold, italic, etc.
+* Horizontal rules:: Make a line
+* Comment lines:: What will *not* be exported
@end menu
@node Document title, Headings and sections, Structural markup elements, Structural markup elements
@@ -8831,11 +8808,11 @@ code, and because it can be readily processed to produce pretty output for a
number of export backends.
@menu
-* Special symbols:: Greek letters and other symbols
-* Subscripts and superscripts:: Simple syntax for raising/lowering text
-* LaTeX fragments:: Complex formulas made easy
-* Previewing LaTeX fragments:: What will this snippet look like?
-* CDLaTeX mode:: Speed up entering of formulas
+* Special symbols:: Greek letters and other symbols
+* Subscripts and superscripts:: Simple syntax for raising/lowering text
+* LaTeX fragments:: Complex formulas made easy
+* Previewing LaTeX fragments:: What will this snippet look like?
+* CDLaTeX mode:: Speed up entering of formulas
@end menu
@node Special symbols, Subscripts and superscripts, Embedded LaTeX, Embedded LaTeX
@@ -9103,17 +9080,17 @@ Org supports export of selected regions when @code{transient-mark-mode} is
enabled (default in Emacs 23).
@menu
-* Selective export:: Using tags to select and exclude trees
-* Export options:: Per-file export settings
-* The export dispatcher:: How to access exporter commands
-* ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding
-* HTML export:: Exporting to HTML
-* LaTeX and PDF export:: Exporting to La@TeX{}, and processing to PDF
-* DocBook export:: Exporting to DocBook
-* TaskJuggler export:: Exporting to TaskJuggler
-* Freemind export:: Exporting to Freemind mind maps
-* XOXO export:: Exporting to XOXO
-* iCalendar export:: Exporting in iCalendar format
+* Selective export:: Using tags to select and exclude trees
+* Export options:: Per-file export settings
+* The export dispatcher:: How to access exporter commands
+* ASCII/Latin-1/UTF-8 export:: Exporting to flat files with encoding
+* HTML export:: Exporting to HTML
+* LaTeX and PDF export:: Exporting to La@TeX{}, and processing to PDF
+* DocBook export:: Exporting to DocBook
+* TaskJuggler export:: Exporting to TaskJuggler
+* Freemind export:: Exporting to Freemind mind maps
+* XOXO export:: Exporting to XOXO
+* iCalendar export:: Exporting in iCalendar format
@end menu
@node Selective export, Export options, Exporting, Exporting
@@ -9366,15 +9343,15 @@ HTML formatting, in ways similar to John Gruber's @emph{markdown}
language, but with additional support for tables.
@menu
-* HTML Export commands:: How to invoke HTML export
-* Quoting HTML tags:: Using direct HTML in Org-mode
-* Links in HTML export:: How links will be interpreted and formatted
-* Tables in HTML export:: How to modify the formatting of tables
-* Images in HTML export:: How to insert figures into HTML output
+* HTML Export commands:: How to invoke HTML export
+* Quoting HTML tags:: Using direct HTML in Org-mode
+* Links in HTML export:: How links will be interpreted and formatted
+* Tables in HTML export:: How to modify the formatting of tables
+* Images in HTML export:: How to insert figures into HTML output
* Math formatting in HTML export:: Beautiful math also on the web
-* Text areas in HTML export:: An alternative way to show an example
-* CSS support:: Changing the appearance of the output
-* JavaScript support:: Info and Folding in a web browser
+* Text areas in HTML export:: An alternative way to show an example
+* CSS support:: Changing the appearance of the output
+* JavaScript support:: Info and Folding in a web browser
@end menu
@node HTML Export commands, Quoting HTML tags, HTML export, HTML export
@@ -9755,12 +9732,12 @@ implement links and cross references, the PDF output file will be fully
linked.
@menu
-* LaTeX/PDF export commands:: Which key invokes which commands
-* Header and sectioning:: Setting up the export file structure
-* Quoting LaTeX code:: Incorporating literal La@TeX{} code
-* Tables in LaTeX export:: Options for exporting tables to La@TeX{}
-* Images in LaTeX export:: How to insert figures into La@TeX{} output
-* Beamer class export:: Turning the file into a presentation
+* LaTeX/PDF export commands:: Which key invokes which commands
+* Header and sectioning:: Setting up the export file structure
+* Quoting LaTeX code:: Incorporating literal La@TeX{} code
+* Tables in LaTeX export:: Options for exporting tables to La@TeX{}
+* Images in LaTeX export:: How to insert figures into La@TeX{} output
+* Beamer class export:: Turning the file into a presentation
@end menu
@node LaTeX/PDF export commands, Header and sectioning, LaTeX and PDF export, LaTeX and PDF export
@@ -10085,12 +10062,12 @@ tools and stylesheets.
Currently DocBook exporter only supports DocBook V5.0.
@menu
-* DocBook export commands:: How to invoke DocBook export
-* Quoting DocBook code:: Incorporating DocBook code in Org files
-* Recursive sections:: Recursive sections in DocBook
-* Tables in DocBook export:: Tables are exported as HTML tables
-* Images in DocBook export:: How to insert figures into DocBook output
-* Special characters:: How to handle special characters
+* DocBook export commands:: How to invoke DocBook export
+* Quoting DocBook code:: Incorporating DocBook code in Org files
+* Recursive sections:: Recursive sections in DocBook
+* Tables in DocBook export:: Tables are exported as HTML tables
+* Images in DocBook export:: How to insert figures into DocBook output
+* Special characters:: How to handle special characters
@end menu
@node DocBook export commands, Quoting DocBook code, DocBook export, DocBook export
@@ -10519,10 +10496,10 @@ conversion so that files are available in both formats on the server.
Publishing has been contributed to Org by David O'Toole.
@menu
-* Configuration:: Defining projects
-* Uploading files:: How to get files up on the server
-* Sample configuration:: Example projects
-* Triggering publication:: Publication commands
+* Configuration:: Defining projects
+* Uploading files:: How to get files up on the server
+* Sample configuration:: Example projects
+* Triggering publication:: Publication commands
@end menu
@node Configuration, Uploading files, Publishing, Publishing
@@ -10532,14 +10509,14 @@ Publishing needs significant configuration to specify files, destination
and many other properties of a project.
@menu
-* Project alist:: The central configuration variable
-* Sources and destinations:: From here to there
-* Selecting files:: What files are part of the project?
-* Publishing action:: Setting the function doing the publishing
-* Publishing options:: Tweaking HTML export
-* Publishing links:: Which links keep working after publishing?
-* Sitemap:: Generating a list of all pages
-* Generating an index:: An index that reaches across pages
+* Project alist:: The central configuration variable
+* Sources and destinations:: From here to there
+* Selecting files:: What files are part of the project?
+* Publishing action:: Setting the function doing the publishing
+* Publishing options:: Tweaking HTML export
+* Publishing links:: Which links keep working after publishing?
+* Sitemap:: Generating a list of all pages
+* Generating an index:: An index that reaches across pages
@end menu
@node Project alist, Sources and destinations, Configuration, Configuration
@@ -10913,8 +10890,8 @@ project publishing only a set of Org files. The second example is
more complex, with a multi-component project.
@menu
-* Simple example:: One-component publishing
-* Complex example:: A multi-component publishing example
+* Simple example:: One-component publishing
+* Complex example:: A multi-component publishing example
@end menu
@node Simple example, Complex example, Sample configuration, Sample configuration
@@ -11043,18 +11020,18 @@ Schulte and Dan Davison, and was originally named Org-babel.
The following sections describe Org-mode's code block handling facilities.
@menu
-* Structure of code blocks:: Code block syntax described
-* Editing source code:: Language major-mode editing
-* Exporting code blocks:: Export contents and/or results
-* Extracting source code:: Create pure source code files
-* Evaluating code blocks:: Place results of evaluation in the Org-mode buffer
-* Library of Babel:: Use and contribute to a library of useful code blocks
-* Languages:: List of supported code block languages
-* Header arguments:: Configure code block functionality
-* Results of evaluation:: How evaluation results are handled
-* Noweb reference syntax:: Literate programming in Org-mode
+* Structure of code blocks:: Code block syntax described
+* Editing source code:: Language major-mode editing
+* Exporting code blocks:: Export contents and/or results
+* Extracting source code:: Create pure source code files
+* Evaluating code blocks:: Place results of evaluation in the Org-mode buffer
+* Library of Babel:: Use and contribute to a library of useful code blocks
+* Languages:: List of supported code block languages
+* Header arguments:: Configure code block functionality
+* Results of evaluation:: How evaluation results are handled
+* Noweb reference syntax:: Literate programming in Org-mode
* Key bindings and useful functions:: Work quickly with code blocks
-* Batch execution:: Call functions from the command line
+* Batch execution:: Call functions from the command line
@end menu
@comment node-name, next, previous, up
@@ -11074,6 +11051,18 @@ The structure of code blocks is as follows:
#+end_src
@end example
+code blocks can also be embedded in text as so called inline code blocks as
+
+@example
+src_<language>@{<body>@}
+@end example
+
+or
+
+@example
+src_<language>[<header arguments>]@{<body>@}
+@end example
+
@table @code
@item <name>
This name is associated with the code block. This is similar to the
@@ -11200,10 +11189,10 @@ Include the code block in the tangled output to file @samp{filename}.
@kindex C-c C-v t
@subsubheading Functions
@table @code
-@item org-babel-tangle @kbd{C-c C-v t}
-Tangle the current file.
+@item org-babel-tangle
+Tangle the current file. Bound to @kbd{C-c C-v t}.
@item org-babel-tangle-file
-Choose a file to tangle.
+Choose a file to tangle. Bound to @kbd{C-c C-v f}.
@end table
@subsubheading Hooks
@@ -11348,8 +11337,8 @@ section provides an overview of the use of header arguments, and then
describes each header argument in detail.
@menu
-* Using header arguments:: Different ways to set header arguments
-* Specific header arguments:: List of header arguments
+* Using header arguments:: Different ways to set header arguments
+* Specific header arguments:: List of header arguments
@end menu
@node Using header arguments, Specific header arguments, Header arguments, Header arguments
@@ -11359,7 +11348,7 @@ The values of header arguments can be set in five different ways, each more
specific (and having higher priority) than the last.
@menu
* System-wide header arguments:: Set global default values
-* Language-specific header arguments:: Set default values by language
+* Language-specific header arguments:: Set default values by language
* Buffer-wide header arguments:: Set default values for a specific buffer
* Header arguments in Org-mode properties:: Set default values for a buffer or heading
* Code block specific header arguments:: The most common way to set values
@@ -11496,26 +11485,26 @@ Header arguments for ``Library of Babel'' or function call lines can be set as s
The following header arguments are defined:
@menu
-* var:: Pass arguments to code blocks
-* results:: Specify the type of results and how they will
+* var:: Pass arguments to code blocks
+* results:: Specify the type of results and how they will
be collected and handled
-* file:: Specify a path for file output
-* dir:: Specify the default (possibly remote)
+* file:: Specify a path for file output
+* dir:: Specify the default (possibly remote)
directory for code block execution
-* exports:: Export code and/or results
-* tangle:: Toggle tangling and specify file name
-* comments:: Toggle insertion of comments in tangled
+* exports:: Export code and/or results
+* tangle:: Toggle tangling and specify file name
+* comments:: Toggle insertion of comments in tangled
code files
-* no-expand:: Turn off variable assignment and noweb
+* no-expand:: Turn off variable assignment and noweb
expansion during tangling
-* session:: Preserve the state of code evaluation
-* noweb:: Toggle expansion of noweb references
-* cache:: Avoid re-evaluating unchanged code blocks
-* hlines:: Handle horizontal lines in tables
-* colnames:: Handle column names in tables
-* rownames:: Handle row names in tables
-* shebang:: Make tangled files executable
-* eval:: Limit evaluation of specific code blocks
+* session:: Preserve the state of code evaluation
+* noweb:: Toggle expansion of noweb references
+* cache:: Avoid re-evaluating unchanged code blocks
+* hlines:: Handle horizontal lines in tables
+* colnames:: Handle column names in tables
+* rownames:: Handle row names in tables
+* shebang:: Make tangled files executable
+* eval:: Limit evaluation of specific code blocks
@end menu
@node var, results, Specific header arguments, Specific header arguments
@@ -11918,10 +11907,25 @@ basename}.
@subsubsection @code{:comments}
By default code blocks are tangled to source-code files without any insertion
of comments beyond those which may already exist in the body of the code
-block. The @code{:comments} header argument can be set to ``yes''
-e.g. @code{:comments yes} to enable the insertion of comments around code
-blocks during tangling. The inserted comments contain pointers back to the
-original Org file from which the comment was tangled.
+block. The @code{:comments} header argument can be set as follows to control
+the insertion of extra comments into the tangled code file.
+
+@itemize @bullet
+@item @code{no}
+The default. No extra comments are inserted during tangling.
+@item @code{link}
+The code block is wrapped in comments which contain pointers back to the
+original Org file from which the code was tangled.
+@item @code{yes}
+A synonym for ``link'' to maintain backwards compatibility.
+@item @code{org}
+Include text from the org-mode file as a comment.
+
+The text is picked from the leading context of the tangled code and is
+limited by the nearest headline or source block as the case may be.
+@item @code{both}
+Turns on both the ``link'' and ``org'' comment options.
+@end itemize
@node no-expand, session, comments, Specific header arguments
@subsubsection @code{:no-expand}
@@ -12369,16 +12373,16 @@ emacsclient \
@chapter Miscellaneous
@menu
-* Completion:: M-TAB knows what you need
-* Easy Templates:: Quick insertion of structural elements
-* Speed keys:: Electric commands at the beginning of a headline
-* Code evaluation security:: Org mode files evaluate inline code
-* Customization:: Adapting Org to your taste
-* In-buffer settings:: Overview of the #+KEYWORDS
-* The very busy C-c C-c key:: When in doubt, press C-c C-c
-* Clean view:: Getting rid of leading stars in the outline
-* TTY keys:: Using Org on a tty
-* Interaction:: Other Emacs packages
+* Completion:: M-TAB knows what you need
+* Easy Templates:: Quick insertion of structural elements
+* Speed keys:: Electric commands at the beginning of a headline
+* Code evaluation security:: Org mode files evaluate inline code
+* Customization:: Adapting Org to your taste
+* In-buffer settings:: Overview of the #+KEYWORDS
+* The very busy C-c C-c key:: When in doubt, press C-c C-c
+* Clean view:: Getting rid of leading stars in the outline
+* TTY keys:: Using Org on a tty
+* Interaction:: Other Emacs packages
@end menu
@@ -13039,8 +13043,8 @@ Org lives in the world of GNU Emacs and interacts in various ways
with other code out there.
@menu
-* Cooperation:: Packages Org cooperates with
-* Conflicts:: Packages that lead to conflicts
+* Cooperation:: Packages Org cooperates with
+* Conflicts:: Packages that lead to conflicts
@end menu
@node Cooperation, Conflicts, Interaction, Interaction
@@ -13188,9 +13192,9 @@ fixed this problem:
@lisp
(add-hook 'org-mode-hook
- (lambda ()
- (org-set-local 'yas/trigger-key [tab])
- (define-key yas/keymap [tab] 'yas/next-field-group)))
+ (lambda ()
+ (org-set-local 'yas/trigger-key [tab])
+ (define-key yas/keymap [tab] 'yas/next-field-group)))
@end lisp
@item @file{windmove.el} by Hovav Shacham
@@ -13232,16 +13236,16 @@ This appendix covers some aspects where users can extend the functionality of
Org.
@menu
-* Hooks:: Who to reach into Org's internals
-* Add-on packages:: Available extensions
-* Adding hyperlink types:: New custom link types
-* Context-sensitive commands:: How to add functionality to such commands
-* Tables in arbitrary syntax:: Orgtbl for La@TeX{} and other programs
-* Dynamic blocks:: Automatically filled blocks
-* Special agenda views:: Customized views
+* Hooks:: Who to reach into Org's internals
+* Add-on packages:: Available extensions
+* Adding hyperlink types:: New custom link types
+* Context-sensitive commands:: How to add functionality to such commands
+* Tables in arbitrary syntax:: Orgtbl for La@TeX{} and other programs
+* Dynamic blocks:: Automatically filled blocks
+* Special agenda views:: Customized views
* Extracting agenda information:: Postprocessing of agenda information
-* Using the property API:: Writing programs that use entry properties
-* Using the mapping API:: Mapping over all or selected entries
+* Using the property API:: Writing programs that use entry properties
+* Using the mapping API:: Mapping over all or selected entries
@end menu
@node Hooks, Add-on packages, Hacking, Hacking
@@ -13435,10 +13439,10 @@ can use Org's facilities to edit and structure lists by turning
@menu
-* Radio tables:: Sending and receiving radio tables
-* A LaTeX example:: Step by step, almost a tutorial
-* Translator functions:: Copy and modify
-* Radio lists:: Doing the same for lists
+* Radio tables:: Sending and receiving radio tables
+* A LaTeX example:: Step by step, almost a tutorial
+* Translator functions:: Copy and modify
+* Radio lists:: Doing the same for lists
@end menu
@node Radio tables, A LaTeX example, Tables in arbitrary syntax, Tables in arbitrary syntax
@@ -13805,10 +13809,11 @@ written in a way such that it does nothing in buffers that are not in
@section Special agenda views
@cindex agenda views, user-defined
-Org provides a special hook that can be used to narrow down the
-selection made by any of the agenda views. You may specify a function
-that is used at each match to verify if the match should indeed be part
-of the agenda view, and if not, how much should be skipped.
+Org provides a special hook that can be used to narrow down the selection
+made by these agenda views: @code{todo}, @code{alltodo}, @code{tags}, @code{tags-todo},
+@code{tags-tree}. You may specify a function that is used at each match to verify
+if the match should indeed be part of the agenda view, and if not, how
+much should be skipped.
Let's say you want to produce a list of projects that contain a WAITING
tag anywhere in the project tree. Let's further assume that you have
@@ -14211,9 +14216,9 @@ in-buffer settings, but it will understand the logistics of TODO state
(@pxref{Setting tags}) only for those set in these variables.
@menu
-* Setting up the staging area:: Where to interact with the mobile device
-* Pushing to MobileOrg:: Uploading Org files and agendas
-* Pulling from MobileOrg:: Integrating captured and flagged items
+* Setting up the staging area:: Where to interact with the mobile device
+* Pushing to MobileOrg:: Uploading Org files and agendas
+* Pulling from MobileOrg:: Integrating captured and flagged items
@end menu
@node Setting up the staging area, Pushing to MobileOrg, MobileOrg, MobileOrg
@@ -14443,6 +14448,8 @@ around a match in a hidden outline tree.
@item
@i{Niels Giesen} had the idea to automatically archive DONE trees.
@item
+@i{Nicolas Goaziou} rewrote much of the plain list code.
+@item
@i{Kai Grossjohann} pointed out key-binding conflicts with other packages.
@item
@i{Bernt Hansen} has driven much of the support for auto-repeating tasks,
@@ -14594,12 +14601,17 @@ and contributed various ideas and code snippets.
@printindex cp
-@node Key Index, Variable Index, Main Index, Top
+@node Key Index, Command and Function Index, Main Index, Top
@unnumbered Key index
@printindex ky
-@node Variable Index, , Key Index, Top
+@node Command and Function Index, Variable Index, Key Index, Top
+@unnumbered Command and function index
+
+@printindex fn
+
+@node Variable Index, , Command and Function Index, Top
@unnumbered Variable index
This is not a complete index of variables and faces, only the ones that are
@@ -14616,6 +14628,7 @@ org-customize @key{RET}} and then click yourself through the tree.
@c Local variables:
@c fill-column: 77
+@c indent-tabs-mode: nil
@c End:
diff --git a/doc/orgcard.tex b/doc/orgcard.tex
index 810850e..2430c33 100644
--- a/doc/orgcard.tex
+++ b/doc/orgcard.tex
@@ -480,8 +480,10 @@ formula, \kbd{:=} a field formula.
\key{view expanded body of code block at point}{C-c C-v v}
\key{go to named code block}{C-c C-v g}
\key{go to named result}{C-c C-v r}
+\key{go to the head of the current code block}{C-c C-v u}
\key{go to the next code block}{C-c C-v n}
\key{go to the previous code block}{C-c C-v p}
+\key{execute the next key sequence in the code edit buffer}{C-c C-v x}
\key{execute all code blocks in current buffer}{C-c C-v b}
\key{execute all code blocks in current subtree}{C-c C-v s}
\key{tangle code blocks in current file}{C-c C-v t}
diff --git a/lisp/ob-C.el b/lisp/ob-C.el
index 24f5a51..9022932 100644
--- a/lisp/ob-C.el
+++ b/lisp/ob-C.el
@@ -33,7 +33,6 @@
;;; Code:
(require 'ob)
(require 'ob-eval)
-(require 'org)
(require 'cc-mode)
(declare-function org-entry-get "org"
@@ -84,12 +83,13 @@ header arguments (calls `org-babel-C-expand')."
"This function should only be called by `org-babel-execute:C'
or `org-babel-execute:c++'."
(let* ((processed-params (org-babel-process-params params))
- (tmp-src-file (make-temp-file "org-babel-C-src" nil
- (cond
- ((equal org-babel-c-variant 'c) ".c")
- ((equal org-babel-c-variant 'cpp) ".cpp"))))
- (tmp-bin-file (make-temp-file "org-babel-C-bin"))
- (tmp-out-file (make-temp-file "org-babel-C-out"))
+ (tmp-src-file (org-babel-temp-file
+ "C-src-"
+ (cond
+ ((equal org-babel-c-variant 'c) ".c")
+ ((equal org-babel-c-variant 'cpp) ".cpp"))))
+ (tmp-bin-file (org-babel-temp-file "C-bin-"))
+ (tmp-out-file (org-babel-temp-file "C-out-"))
(cmdline (cdr (assoc :cmdline params)))
(flags (cdr (assoc :flags params)))
(full-body (org-babel-C-expand body params))
@@ -108,7 +108,7 @@ or `org-babel-execute:c++'."
((lambda (results)
(org-babel-reassemble-table
(if (member "vector" (nth 2 processed-params))
- (let ((tmp-file (make-temp-file "ob-c")))
+ (let ((tmp-file (org-babel-temp-file "c-")))
(with-temp-file tmp-file (insert results))
(org-babel-import-elisp-from-file tmp-file))
(org-babel-read results))
diff --git a/lisp/ob-R.el b/lisp/ob-R.el
index e9633ae2..64bbba4 100644
--- a/lisp/ob-R.el
+++ b/lisp/ob-R.el
@@ -33,9 +33,11 @@
(require 'ob-eval)
(eval-when-compile (require 'cl))
-(declare-function orgtbl-to-tsv "ob-table" (table params))
+(declare-function orgtbl-to-tsv "org-table" (table params))
(declare-function R "ext:essd-r" (&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))
(defconst org-babel-header-arg-names:R
'(width height bg units pointsize antialias quality compression
@@ -139,7 +141,7 @@ This function is called by `org-babel-execute-src-block'."
(defun org-babel-R-assign-elisp (name value colnames-p rownames-p)
"Construct R code assigning the elisp VALUE to a variable named NAME."
(if (listp value)
- (let ((transition-file (make-temp-file "org-babel-R-import")))
+ (let ((transition-file (org-babel-temp-file "R-import-")))
;; ensure VALUE has an orgtbl structure (depth of at least 2)
(unless (listp (car value)) (setq value (list value)))
(with-temp-file (org-babel-maybe-remote-file transition-file)
@@ -151,11 +153,13 @@ This function is called by `org-babel-execute-src-block'."
(if rownames-p "1" "NULL")))
(format "%s <- %s" name (org-babel-R-quote-tsv-field value))))
+(defvar ess-ask-for-ess-directory nil)
(defun org-babel-R-initiate-session (session params)
"If there is not a current R process then create one."
(unless (string= session "none")
(let ((session (or session "*R*"))
- (ess-ask-for-ess-directory (not (cdr (assoc :dir params)))))
+ (ess-ask-for-ess-directory
+ (and ess-ask-for-ess-directory (not (cdr (assoc :dir params))))))
(if (org-babel-comint-buffer-livep session)
session
(save-window-excursion
@@ -168,6 +172,15 @@ This function is called by `org-babel-execute-src-block'."
(buffer-name))))
(current-buffer))))))
+(defvar ess-local-process-name nil)
+(defun org-babel-R-associate-session (session)
+ "Associate R code buffer with an R 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-R-construct-graphics-device-call (out-file params)
"Construct the call to the graphics device."
(let ((devices
@@ -205,69 +218,78 @@ This function is called by `org-babel-execute-src-block'."
(defvar org-babel-R-eoe-indicator "'org_babel_R_eoe'")
(defvar org-babel-R-eoe-output "[1] \"org_babel_R_eoe\"")
-(defvar org-babel-R-wrapper-method "main <- function ()\n{\n%s\n}
-write.table(main(), file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=%s, col.names=%s, quote=FALSE)")
-(defvar org-babel-R-wrapper-lastvar "write.table(.Last.value, file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=%s, col.names=%s, quote=FALSE)")
+(defvar org-babel-R-write-object-command "{function(object, transfer.file) {invisible(if(inherits(try(write.table(object, file=transfer.file, sep=\"\\t\", na=\"nil\",row.names=%s, col.names=%s, quote=FALSE), silent=TRUE),\"try-error\")) {if(!file.exists(transfer.file)) file.create(transfer.file)})}}(object=%s, transfer.file=\"%s\")")
(defun org-babel-R-evaluate
(session body result-type column-names-p row-names-p)
- "Pass BODY to the R process in SESSION.
-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."
- (if (not session)
- ;; external process evaluation
- (case result-type
- (output (org-babel-eval org-babel-R-command body))
- (value
- (let ((tmp-file (make-temp-file "org-babel-R-results-")))
- (org-babel-eval org-babel-R-command
- (format org-babel-R-wrapper-method
- body tmp-file
- (if row-names-p "TRUE" "FALSE")
- (if column-names-p
- (if row-names-p "NA" "TRUE")
- "FALSE")))
- (org-babel-R-process-value-result
- (org-babel-import-elisp-from-file
- (org-babel-maybe-remote-file tmp-file) '(16)) column-names-p))))
- ;; comint session evaluation
- (case result-type
- (value
- (let ((tmp-file (make-temp-file "org-babel-R"))
- broke)
- (org-babel-comint-with-output (session org-babel-R-eoe-output)
- (insert (mapconcat
- #'org-babel-chomp
- (list
- body
- (format org-babel-R-wrapper-lastvar
- tmp-file
- (if row-names-p "TRUE" "FALSE")
- (if column-names-p
- (if row-names-p "NA" "TRUE")
- "FALSE"))
- org-babel-R-eoe-indicator) "\n"))
- (inferior-ess-send-input))
- (org-babel-R-process-value-result
- (org-babel-import-elisp-from-file
- (org-babel-maybe-remote-file tmp-file) '(16)) column-names-p)))
- (output
- (mapconcat
- #'org-babel-chomp
- (butlast
- (delq nil
- (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-R-eoe-output)
- (insert (mapconcat #'org-babel-chomp
- (list body org-babel-R-eoe-indicator)
- "\n"))
- (inferior-ess-send-input)))) 2) "\n")))))
+ "Evaluate R code in BODY."
+ (if session
+ (org-babel-R-evaluate-session
+ session body result-type column-names-p row-names-p)
+ (org-babel-R-evaluate-external-process
+ body result-type column-names-p row-names-p)))
+
+(defun org-babel-R-evaluate-external-process
+ (body result-type column-names-p row-names-p)
+ "Evaluate BODY in external R 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 "R-")))
+ (org-babel-eval org-babel-R-command
+ (format org-babel-R-write-object-command
+ (if row-names-p "TRUE" "FALSE")
+ (if column-names-p
+ (if row-names-p "NA" "TRUE")
+ "FALSE")
+ (format "{function ()\n{\n%s\n}}()" body)
+ (org-babel-tramp-localname tmp-file)))
+ (org-babel-R-process-value-result
+ (org-babel-import-elisp-from-file tmp-file '(16)) column-names-p)))
+ (output (org-babel-eval org-babel-R-command body))))
+
+(defun org-babel-R-evaluate-session
+ (session body result-type 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-buffer nil)))
+ (let ((tmp-file (org-babel-temp-file "R-")))
+ (org-babel-comint-eval-invisibly-and-wait-for-file
+ session tmp-file
+ (format org-babel-R-write-object-command
+ (if row-names-p "TRUE" "FALSE")
+ (if column-names-p
+ (if row-names-p "NA" "TRUE")
+ "FALSE")
+ ".Last.value" (org-babel-tramp-localname tmp-file)))
+ (org-babel-R-process-value-result
+ (org-babel-import-elisp-from-file tmp-file '(16)) column-names-p)))
+ (output
+ (mapconcat
+ #'org-babel-chomp
+ (butlast
+ (delq nil
+ (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-R-eoe-output)
+ (insert (mapconcat #'org-babel-chomp
+ (list body org-babel-R-eoe-indicator)
+ "\n"))
+ (inferior-ess-send-input)))) 2) "\n"))))
(defun org-babel-R-process-value-result (result column-names-p)
"R-specific processing of return value.
diff --git a/lisp/ob-asymptote.el b/lisp/ob-asymptote.el
index df1f059..49ccc7c 100644
--- a/lisp/ob-asymptote.el
+++ b/lisp/ob-asymptote.el
@@ -73,7 +73,7 @@ This function is called by `org-babel-execute-src-block'."
(match-string 1 out-file))
"pdf"))
(cmdline (cdr (assoc :cmdline params)))
- (in-file (make-temp-file "org-babel-asymptote"))
+ (in-file (org-babel-temp-file "asymptote-"))
(cmd (concat "asy "
(if out-file
(concat "-globalwrite -f " format " -o " out-file)
diff --git a/lisp/ob-clojure.el b/lisp/ob-clojure.el
index cfb3b94..4311bb5 100644
--- a/lisp/ob-clojure.el
+++ b/lisp/ob-clojure.el
@@ -261,7 +261,7 @@ repl buffer."
" "))))
(case result-type
(output (org-babel-eval cmd body))
- (value (let* ((tmp-file (make-temp-file "org-babel-clojure-results-")))
+ (value (let* ((tmp-file (org-babel-temp-file "clojure-results-")))
(org-babel-eval cmd (format org-babel-clojure-wrapper-method
body tmp-file tmp-file))
(org-babel-clojure-table-or-string
diff --git a/lisp/ob-comint.el b/lisp/ob-comint.el
index c7d3d14..cef27ff 100644
--- a/lisp/ob-comint.el
+++ b/lisp/ob-comint.el
@@ -34,6 +34,8 @@
(require 'ob)
(require 'comint)
(eval-when-compile (require 'cl))
+(declare-function with-parsed-tramp-file-name "tramp" (filename var &rest body))
+(declare-function tramp-flush-directory-property "tramp" (vec directory))
(defun org-babel-comint-buffer-livep (buffer)
"Check if BUFFER is a comint buffer with a live process."
@@ -136,6 +138,24 @@ statement (not large blocks of code)."
"comint-highlight-prompt"))))
(accept-process-output (get-buffer-process buffer)))))
+(defun org-babel-comint-eval-invisibly-and-wait-for-file
+ (buffer file string &optional period)
+ "Evaluate STRING in BUFFER invisibly.
+Don't return until FILE exists. Code in STRING must ensure that
+FILE exists at end of evaluation."
+ (unless (org-babel-comint-buffer-livep buffer)
+ (error "buffer %s doesn't exist or has no process" buffer))
+ (if (file-exists-p file) (delete-file file))
+ (process-send-string
+ (get-buffer-process buffer)
+ (if (string-match "\n$" string) string (concat string "\n")))
+ ;; From Tramp 2.1.19 the following cache flush is not necessary
+ (if (file-remote-p default-directory)
+ (let (v)
+ (with-parsed-tramp-file-name default-directory nil
+ (tramp-flush-directory-property v ""))))
+ (while (not (file-exists-p file)) (sit-for (or period 0.25))))
+
(provide 'ob-comint)
;; arch-tag: 9adddce6-0864-4be3-b0b5-6c5157dc7889
diff --git a/lisp/ob-ditaa.el b/lisp/ob-ditaa.el
index f9a5bac..20cc192 100644
--- a/lisp/ob-ditaa.el
+++ b/lisp/ob-ditaa.el
@@ -50,15 +50,18 @@
(defun org-babel-execute:ditaa (body params)
"Execute a block of Ditaa code with org-babel.
This function is called by `org-babel-execute-src-block'."
- (let ((result-params (split-string (or (cdr (assoc :results params)) "")))
- (out-file (cdr (assoc :file params)))
- (cmdline (cdr (assoc :cmdline params)))
- (in-file (make-temp-file "org-babel-ditaa")))
+ (let* ((result-params (split-string (or (cdr (assoc :results params)) "")))
+ (out-file (cdr (assoc :file params)))
+ (cmdline (cdr (assoc :cmdline params)))
+ (in-file (org-babel-temp-file "ditaa-"))
+ (cmd (concat "java -jar "
+ (shell-quote-argument
+ (expand-file-name org-ditaa-jar-path))
+ " " cmdline " " in-file " " out-file)))
(unless (file-exists-p org-ditaa-jar-path)
(error "Could not find ditaa.jar at %s" org-ditaa-jar-path))
(with-temp-file in-file (insert body))
- (message (concat "java -jar " org-ditaa-jar-path " " cmdline " " in-file " " out-file))
- (shell-command (concat "java -jar " (shell-quote-argument org-ditaa-jar-path) " " cmdline " " in-file " " out-file))
+ (message cmd) (shell-command cmd)
out-file))
(defun org-babel-prep-session:ditaa (session params)
diff --git a/lisp/ob-dot.el b/lisp/ob-dot.el
index d19f075..8f2976e 100644
--- a/lisp/ob-dot.el
+++ b/lisp/ob-dot.el
@@ -70,7 +70,7 @@ This function is called by `org-babel-execute-src-block'."
(out-file (cdr (assoc :file params)))
(cmdline (cdr (assoc :cmdline params)))
(cmd (or (cdr (assoc :cmd params)) "dot"))
- (in-file (make-temp-file "org-babel-dot")))
+ (in-file (org-babel-temp-file "dot-")))
(with-temp-file in-file
(insert (org-babel-expand-body:dot body params processed-params)))
(org-babel-eval (concat cmd " " in-file " " cmdline " -o " out-file) "")
diff --git a/lisp/ob-emacs-lisp.el b/lisp/ob-emacs-lisp.el
index a93abb4..efa5a67 100644
--- a/lisp/ob-emacs-lisp.el
+++ b/lisp/ob-emacs-lisp.el
@@ -28,15 +28,12 @@
;;; Code:
(require 'ob)
+(eval-when-compile (require 'ob-comint))
(defvar org-babel-default-header-args:emacs-lisp
'((:hlines . "yes") (:colnames . "no"))
"Default arguments for evaluating an emacs-lisp source block.")
-(declare-function org-babel-comint-with-output "ob-comint" (&rest body))
-(declare-function org-babel-comint-buffer-livep "ob-comint" (buffer))
-(declare-function org-babel-comint-wait-for-output "ob-comint" (buffer))
-(declare-function org-babel-comint-in-buffer "ob-comint" (buffer &rest body))
(declare-function orgtbl-to-generic "org-table" (table params))
(defun org-babel-expand-body:emacs-lisp (body params &optional processed-params)
diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el
index 796812c..aec7d31 100644
--- a/lisp/ob-exp.el
+++ b/lisp/ob-exp.el
@@ -178,6 +178,8 @@ options are taken from `org-babel-default-header-args'."
(list "emacs-lisp" "results"
(org-babel-merge-params
org-babel-default-header-args
+ (org-babel-params-from-buffer)
+ (org-babel-params-from-properties)
(org-babel-parse-header-arguments
(org-babel-clean-text-properties
(concat ":var results="
@@ -193,8 +195,7 @@ options are taken from `org-babel-default-header-args'."
The function respects the value of the :exports header argument."
(flet ((silently () (let ((session (cdr (assoc :session (nth 2 info)))))
(when (and session
- (not (equal "none" session))
- (not (assoc :noeval (nth 2 info))))
+ (not (equal "none" session)))
(org-babel-exp-results info type 'silent))))
(clean () (org-babel-remove-result info)))
(case (intern (or (cdr (assoc :exports (nth 2 info))) "code"))
diff --git a/lisp/ob-gnuplot.el b/lisp/ob-gnuplot.el
index 5b5e82d..ff68ad7 100644
--- a/lisp/ob-gnuplot.el
+++ b/lisp/ob-gnuplot.el
@@ -68,7 +68,7 @@ code."
(car pair) ;; variable name
(if (listp (cdr pair)) ;; variable value
(org-babel-gnuplot-table-to-data
- (cdr pair) (make-temp-file "org-babel-gnuplot") params)
+ (cdr pair) (org-babel-temp-file "gnuplot") params)
(cdr pair))))
(org-babel-ref-variables params)))
@@ -141,7 +141,7 @@ This function is called by `org-babel-execute-src-block'."
(save-window-excursion
;; evaluate the code body with gnuplot
(if (string= session "none")
- (let ((script-file (make-temp-file "org-babel-gnuplot-script")))
+ (let ((script-file (org-babel-temp-file "gnuplot-script")))
(with-temp-file script-file
(insert (concat body "\n")))
(message "gnuplot \"%s\"" script-file)
diff --git a/lisp/ob-haskell.el b/lisp/ob-haskell.el
index 86efda9..9cfda96 100644
--- a/lisp/ob-haskell.el
+++ b/lisp/ob-haskell.el
@@ -116,7 +116,7 @@ then create one. Return the initialized session."
(save-window-excursion
(let* ((buffer (org-babel-prep-session:haskell
session params processed-params))
- (load-file (concat (make-temp-file "org-babel-haskell-load") ".hs")))
+ (load-file (concat (org-babel-temp-file "haskell-load-") ".hs")))
(with-temp-buffer
(insert body) (write-file load-file)
(haskell-mode) (inferior-haskell-load-file))
@@ -177,7 +177,7 @@ constructs (header arguments, no-web syntax etc...) are ignored."
(concat "^\\([ \t]*\\)#\\+begin_src[ \t]haskell*\\(.*\\)?[\r\n]"
"\\([^\000]*?\\)[\r\n][ \t]*#\\+end_src.*"))
(base-name (file-name-sans-extension (buffer-file-name)))
- (tmp-file (make-temp-file "ob-haskell"))
+ (tmp-file (org-babel-temp-file "haskell-"))
(tmp-org-file (concat tmp-file ".org"))
(tmp-tex-file (concat tmp-file ".tex"))
(lhs-file (concat base-name ".lhs"))
diff --git a/lisp/ob-js.el b/lisp/ob-js.el
new file mode 100644
index 0000000..a59a134
--- /dev/null
+++ b/lisp/ob-js.el
@@ -0,0 +1,170 @@
+;;; ob-js.el --- org-babel functions for Javascript
+
+;; Copyright (C) 2010 Free Software Foundation
+
+;; Author: Eric Schulte
+;; Keywords: literate programming, reproducible research, js
+;; Homepage: http://orgmode.org
+;; Version: 0.01
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Now working with SBCL for both session and external evaluation.
+;;
+;; This certainly isn't optimally robust, but it seems to be working
+;; for the basic use cases.
+
+;;; Requirements:
+
+;; - a non-browser javascript engine such as node.js http://nodejs.org/
+;; or mozrepl http://wiki.github.com/bard/mozrepl/
+;;
+;; - for session based evaluation mozrepl and moz.el are required see
+;; http://wiki.github.com/bard/mozrepl/emacs-integration for
+;; configuration instructions
+
+;;; Code:
+(require 'ob)
+(require 'ob-ref)
+(require 'ob-comint)
+(require 'ob-eval)
+(eval-when-compile (require 'cl))
+
+(declare-function run-mozilla "ext:moz" (arg))
+
+(defvar org-babel-default-header-args:js '()
+ "Default header arguments for js code blocks.")
+
+(defvar org-babel-js-eoe "org-babel-js-eoe"
+ "String to indicate that evaluation has completed.")
+
+(defcustom org-babel-js-cmd "node"
+ "Name of command used to evaluate js blocks."
+ :group 'org-babel
+ :type 'string)
+
+(defvar org-babel-js-function-wrapper
+ "require('sys').print(require('sys').inspect(function(){%s}()));"
+ "Javascript code to print value of body.")
+
+(defun org-babel-expand-body:js (body params &optional processed-params)
+ "Expand BODY according to PARAMS, return the expanded body."
+ (let ((vars (nth 1 (or processed-params (org-babel-process-params params)))))
+ (concat
+ (mapconcat ;; define any variables
+ (lambda (pair) (format "var %s=%s;"
+ (car pair) (org-babel-js-var-to-js (cdr pair))))
+ vars "\n") "\n" body "\n")))
+
+(defun org-babel-execute:js (body params)
+ "Execute a block of Javascript code with org-babel.
+This function is called by `org-babel-execute-src-block'"
+ (let* ((processed-params (org-babel-process-params params))
+ (org-babel-js-cmd (or (cdr (assoc :cmd params)) org-babel-js-cmd))
+ (result-type (nth 3 processed-params))
+ (full-body (org-babel-expand-body:js body params processed-params)))
+ (org-babel-js-read
+ (if (not (string= (nth 0 processed-params) "none"))
+ ;; session evaluation
+ (let ((session (org-babel-prep-session:js
+ (nth 0 processed-params) params)))
+ (nth 1
+ (org-babel-comint-with-output
+ (session (format "%S" org-babel-js-eoe) t body)
+ (mapc
+ (lambda (line)
+ (insert (org-babel-chomp line)) (comint-send-input nil t))
+ (list body (format "%S" org-babel-js-eoe))))))
+ ;; external evaluation
+ (let ((script-file (org-babel-temp-file "js-script-")))
+ (with-temp-file script-file
+ (insert
+ ;; return the value or the output
+ (if (string= result-type "value")
+ (format org-babel-js-function-wrapper full-body)
+ full-body)))
+ (org-babel-eval (format "%s %s" org-babel-js-cmd script-file) ""))))))
+
+(defun org-babel-js-read (results)
+ "Convert RESULTS into an appropriate elisp value.
+If RESULTS look like a table, then convert them into an
+Emacs-lisp table, otherwise return the results as a string."
+ (org-babel-read
+ (if (and (stringp results) (string-match "^\\[.+\\]$" results))
+ (org-babel-read
+ (concat "'"
+ (replace-regexp-in-string
+ "\\[" "(" (replace-regexp-in-string
+ "\\]" ")" (replace-regexp-in-string
+ ", " " " (replace-regexp-in-string
+ "'" "\"" results))))))
+ results)))
+
+(defun org-babel-js-var-to-js (var)
+ "Convert VAR into a js variable.
+Convert an elisp value into a string of js source code
+specifying a variable of the same value."
+ (if (listp var)
+ (concat "[" (mapconcat #'org-babel-js-var-to-js var ", ") "]")
+ (format "%S" var)))
+
+(defun org-babel-prep-session:js (session params)
+ "Prepare SESSION according to the header arguments specified in PARAMS."
+ (let* ((session (org-babel-js-initiate-session session))
+ (vars (org-babel-ref-variables params))
+ (var-lines
+ (mapcar
+ (lambda (pair) (format "var %s=%s;"
+ (car pair) (org-babel-js-var-to-js (cdr pair))))
+ vars)))
+ (when session
+ (org-babel-comint-in-buffer session
+ (sit-for .5) (goto-char (point-max))
+ (mapc (lambda (var)
+ (insert var) (comint-send-input nil t)
+ (org-babel-comint-wait-for-output session)
+ (sit-for .1) (goto-char (point-max))) var-lines)))
+ session))
+
+(defun org-babel-js-initiate-session (&optional session)
+ "If there is not a current inferior-process-buffer in SESSION
+then create. Return the initialized session."
+ (unless (string= session "none")
+ (cond
+ ((string= "mozrepl" org-babel-js-cmd)
+ (require 'moz)
+ (let ((session-buffer (save-window-excursion
+ (run-mozilla nil)
+ (rename-buffer session)
+ (current-buffer))))
+ (if (org-babel-comint-buffer-livep session-buffer)
+ (progn (sit-for .25) session-buffer)
+ (sit-for .5)
+ (org-babel-js-initiate-session session))))
+ ((string= "node" org-babel-js-cmd )
+ (error "session evaluation with node.js is not supported"))
+ (t
+ (error "sessions are only supported with mozrepl add \":cmd mozrepl\"")))))
+
+(provide 'ob-js)
+
+;; arch-tag: 84401fb3-b8d9-4bb6-9a90-cbe2d103d494
+
+;;; ob-js.el ends here
diff --git a/lisp/ob-keys.el b/lisp/ob-keys.el
index e9ba3d9..ff730c6 100644
--- a/lisp/ob-keys.el
+++ b/lisp/ob-keys.el
@@ -58,6 +58,8 @@ functions which are assigned key bindings, and see
("\C-o" . org-babel-open-src-block-result)
("\C-v" . org-babel-expand-src-block)
("v" . org-babel-expand-src-block)
+ ("u" . org-babel-goto-src-block-head)
+ ("\C-u" . org-babel-goto-src-block-head)
("g" . org-babel-goto-named-src-block)
("r" . org-babel-goto-named-result)
("\C-r" . org-babel-goto-named-result)
@@ -74,10 +76,12 @@ functions which are assigned key bindings, and see
("\C-i" . org-babel-lob-ingest)
("i" . org-babel-lob-ingest)
("\C-z" . org-babel-switch-to-session)
- ("z" . org-babel-switch-to-session)
+ ("z" . org-babel-switch-to-session-with-code)
("\C-a" . org-babel-sha1-hash)
("a" . org-babel-sha1-hash)
- ("h" . org-babel-describe-bindings))
+ ("h" . org-babel-describe-bindings)
+ ("\C-x" . org-babel-do-key-sequence-in-edit-buffer)
+ ("x" . org-babel-do-key-sequence-in-edit-buffer))
"Alist of key bindings and interactive Babel functions.
This list associates interactive Babel functions
with keys. Each element of this list will add an entry to the
diff --git a/lisp/ob-latex.el b/lisp/ob-latex.el
index 5451791..dde3eae 100644
--- a/lisp/ob-latex.el
+++ b/lisp/ob-latex.el
@@ -37,9 +37,18 @@
(declare-function org-splice-latex-header "org"
(tpl def-pkg pkg snippets-p &optional extra))
(declare-function org-export-latex-fix-inputenc "org-latex" ())
-
(add-to-list 'org-babel-tangle-lang-exts '("latex" . "tex"))
+(defvar org-format-latex-header)
+(defvar org-format-latex-header-extra)
+(defvar org-export-latex-packages-alist)
+(defvar org-export-latex-default-packages-alist)
+(defvar org-export-pdf-logfiles)
+(defvar org-latex-to-pdf-process)
+(defvar org-export-pdf-remove-logfiles)
+(defvar org-format-latex-options)
+(defvar org-export-latex-packages-alist)
+
(defvar org-babel-default-header-args:latex
'((:results . "latex") (:exports . "results"))
"Default arguments to use when evaluating a LaTeX source block.")
@@ -53,29 +62,54 @@
(if (stringp (cdr pair))
(cdr pair) (format "%S" (cdr pair)))
body))) (nth 1 (org-babel-process-params params)))
- body)
+ (org-babel-trim body))
-(defvar org-format-latex-options)
-(defvar org-export-latex-packages-alist)
(defun org-babel-execute:latex (body params)
"Execute a block of Latex code with Babel.
This function is called by `org-babel-execute-src-block'."
(setq body (org-babel-expand-body:latex body params))
(if (cdr (assoc :file params))
- (let ((out-file (cdr (assoc :file params)))
- (tex-file (make-temp-file "org-babel-latex" nil ".tex"))
- (pdfheight (cdr (assoc :pdfheight params)))
- (pdfwidth (cdr (assoc :pdfwidth params)))
- (in-buffer (not (string= "no" (cdr (assoc :buffer params)))))
- (org-export-latex-packages-alist
- (append (cdr (assoc :packages params))
- org-export-latex-packages-alist)))
+ (let* ((out-file (cdr (assoc :file params)))
+ (tex-file (org-babel-temp-file "latex-" ".tex"))
+ (border (cdr (assoc :border params)))
+ (fit (or (cdr (assoc :fit params)) border))
+ (height (and fit (cdr (assoc :pdfheight params))))
+ (width (and fit (cdr (assoc :pdfwidth params))))
+ (in-buffer (not (string= "no" (cdr (assoc :buffer params)))))
+ (org-export-latex-packages-alist
+ (append (cdr (assoc :packages params))
+ org-export-latex-packages-alist)))
(cond
((string-match "\\.png$" out-file)
(org-create-formula-image
body out-file org-format-latex-options in-buffer))
((string-match "\\.pdf$" out-file)
- (org-babel-latex-body-to-tex-file tex-file body pdfheight pdfwidth)
+ (require 'org-latex)
+ (with-temp-file tex-file
+ (insert
+ (org-splice-latex-header
+ org-format-latex-header
+ (delq
+ nil
+ (mapcar
+ (lambda (el)
+ (unless (and (listp el) (string= "hyperref" (cadr el)))
+ el))
+ org-export-latex-default-packages-alist))
+ org-export-latex-packages-alist
+ org-format-latex-header-extra)
+ (if fit "\n\\usepackage[active, tightpage]{preview}\n" "")
+ (if border (format "\\setlength{\\PreviewBorder}{%s}" border) "")
+ (if height (concat "\n" (format "\\pdfpageheight %s" height)) "")
+ (if width (concat "\n" (format "\\pdfpagewidth %s" width)) "")
+ (if org-format-latex-header-extra
+ (concat "\n" org-format-latex-header-extra)
+ "")
+ (if fit
+ (concat "\n\\begin{document}\n\\begin{preview}\n" body
+ "\n\\end{preview}\n\\end{document}\n")
+ (concat "\n\\begin{document}\n" body "\n\\end{document}\n")))
+ (org-export-latex-fix-inputenc))
(when (file-exists-p out-file) (delete-file out-file))
(rename-file (org-babel-latex-tex-to-pdf tex-file) out-file))
((string-match "\\.\\([^\\.]+\\)$" out-file)
@@ -84,67 +118,48 @@ This function is called by `org-babel-execute-src-block'."
out-file)
body))
-(defvar org-format-latex-header)
-(defvar org-format-latex-header-extra)
-(defvar org-export-latex-packages-alist)
-(defvar org-export-latex-default-packages-alist)
-(defun org-babel-latex-body-to-tex-file (tex-file body &optional height width)
- "Place the contents of BODY into TEX-FILE.
-Extracted from `org-create-formula-image' in org.el."
- (with-temp-file tex-file
- (insert (org-splice-latex-header
- org-format-latex-header
- (delq
- nil
- (mapcar
- (lambda (el) (unless (and (listp el) (string= "hyperref" (cadr el)))
- el))
- org-export-latex-default-packages-alist))
- org-export-latex-packages-alist
- org-format-latex-header-extra)
- (if height (concat "\n" (format "\\pdfpageheight %s" height)) "")
- (if width (concat "\n" (format "\\pdfpagewidth %s" width)) "")
- (if org-format-latex-header-extra
- (concat "\n" org-format-latex-header-extra)
- "")
- "\n\\begin{document}\n" body "\n\\end{document}\n")
- (org-export-latex-fix-inputenc)))
-
-(defvar org-export-pdf-logfiles)
-(defvar org-latex-to-pdf-process)
-(defvar org-export-pdf-remove-logfiles)
-(defun org-babel-latex-tex-to-pdf (tex-file)
- "Generate a pdf file according to the contents TEX-FILE.
+(defun org-babel-latex-tex-to-pdf (file)
+ "Generate a pdf file according to the contents FILE.
Extracted from `org-export-as-pdf' in org-latex.el."
(let* ((wconfig (current-window-configuration))
- (default-directory (file-name-directory tex-file))
- (base (file-name-sans-extension tex-file))
+ (default-directory (file-name-directory file))
+ (base (file-name-sans-extension file))
(pdffile (concat base ".pdf"))
(cmds org-latex-to-pdf-process)
(outbuf (get-buffer-create "*Org PDF LaTeX Output*"))
- cmd)
+ output-dir cmd)
+ (with-current-buffer outbuf (erase-buffer))
+ (message (concat "Processing LaTeX file " file "..."))
+ (setq output-dir (file-name-directory file))
(if (and cmds (symbolp cmds))
- (funcall cmds tex-file)
+ (funcall cmds (shell-quote-argument file))
(while cmds
- (setq cmd (pop cmds))
- (while (string-match "%b" cmd)
- (setq cmd (replace-match
- (save-match-data
- (shell-quote-argument base))
- t t cmd)))
- (while (string-match "%s" cmd)
- (setq cmd (replace-match
- (save-match-data
- (shell-quote-argument tex-file))
- t t cmd)))
- (shell-command cmd outbuf outbuf)))
+ (setq cmd (pop cmds))
+ (while (string-match "%b" cmd)
+ (setq cmd (replace-match
+ (save-match-data
+ (shell-quote-argument base))
+ t t cmd)))
+ (while (string-match "%f" cmd)
+ (setq cmd (replace-match
+ (save-match-data
+ (shell-quote-argument file))
+ t t cmd)))
+ (while (string-match "%o" cmd)
+ (setq cmd (replace-match
+ (save-match-data
+ (shell-quote-argument output-dir))
+ t t cmd)))
+ (shell-command cmd outbuf outbuf)))
+ (message (concat "Processing LaTeX file " file "...done"))
(if (not (file-exists-p pdffile))
- (error "PDF file was not produced from %s" tex-file)
+ (error (concat "PDF file " pdffile " was not produced"))
(set-window-configuration wconfig)
(when org-export-pdf-remove-logfiles
- (dolist (ext org-export-pdf-logfiles)
- (setq tex-file (concat base "." ext))
- (and (file-exists-p tex-file) (delete-file tex-file))))
+ (dolist (ext org-export-pdf-logfiles)
+ (setq file (concat base "." ext))
+ (and (file-exists-p file) (delete-file file))))
+ (message "Exporting to PDF...done")
pdffile)))
(defun org-babel-prep-session:latex (session params)
diff --git a/lisp/ob-ledger.el b/lisp/ob-ledger.el
index 1c48dad..111e3f9 100644
--- a/lisp/ob-ledger.el
+++ b/lisp/ob-ledger.el
@@ -38,7 +38,6 @@
;;; Code:
(require 'ob)
-(require 'org)
(defvar org-babel-default-header-args:ledger
'((:results . "output") (:cmdline . "bal"))
@@ -50,8 +49,8 @@ called by `org-babel-execute-src-block'."
(message "executing Ledger source code block")
(let ((result-params (split-string (or (cdr (assoc :results params)) "")))
(cmdline (cdr (assoc :cmdline params)))
- (in-file (make-temp-file "org-babel-ledger"))
- (out-file (make-temp-file "org-babel-ledger-output"))
+ (in-file (org-babel-temp-file "ledger-"))
+ (out-file (org-babel-temp-file "ledger-output-"))
)
(with-temp-file in-file (insert body))
(message (concat "ledger -f " in-file " " cmdline))
diff --git a/lisp/ob-lisp.el b/lisp/ob-lisp.el
index bad0d07..4216158 100644
--- a/lisp/ob-lisp.el
+++ b/lisp/ob-lisp.el
@@ -74,7 +74,7 @@ This function is called by `org-babel-execute-src-block'"
(save-window-excursion
(cadr (slime-eval `(swank:eval-and-grab-output ,full-body))))
;; external evaluation
- (let ((script-file (make-temp-file "ob-lisp-script")))
+ (let ((script-file (org-babel-temp-file "lisp-script-")))
(with-temp-file script-file
(insert
;; return the value or the output
diff --git a/lisp/ob-lob.el b/lisp/ob-lob.el
index 8c207f7..33a6989 100644
--- a/lisp/ob-lob.el
+++ b/lisp/ob-lob.el
@@ -79,14 +79,7 @@ if so then run the appropriate source block from the Library."
;;;###autoload
(defun org-babel-lob-get-info ()
- "Return a Library of Babel function call as a string.
-
-This function is analogous to org-babel-get-src-block-name. For
-both functions, after they are called, (match-string 1) matches
-the function name, and (match-string 2) matches the function
-arguments inside the parentheses. I think perhaps these functions
-should be renamed to bring out this similarity, perhaps involving
-the word 'call'."
+ "Return a Library of Babel function call as a string."
(let ((case-fold-search t))
(save-excursion
(beginning-of-line 1)
diff --git a/lisp/ob-octave.el b/lisp/ob-octave.el
index e0c2705..19174cd 100644
--- a/lisp/ob-octave.el
+++ b/lisp/ob-octave.el
@@ -178,7 +178,7 @@ value of the last statement in BODY, as elisp."
org-babel-octave-shell-command)))
(case result-type
(output (org-babel-eval cmd body))
- (value (let ((tmp-file (make-temp-file "org-babel-results-")))
+ (value (let ((tmp-file (org-babel-temp-file "results-")))
(org-babel-eval
cmd
(format org-babel-octave-wrapper-method body tmp-file tmp-file))
@@ -188,8 +188,8 @@ value of the last statement in BODY, as elisp."
(defun org-babel-octave-evaluate-session
(session body result-type &optional matlabp)
"Evaluate BODY in SESSION."
- (let* ((tmp-file (make-temp-file "org-babel-results-"))
- (wait-file (make-temp-file "org-babel-matlab-emacs-link-wait-signal-"))
+ (let* ((tmp-file (org-babel-temp-file "results-"))
+ (wait-file (org-babel-temp-file "matlab-emacs-link-wait-signal-"))
(full-body
(case result-type
(output
@@ -246,7 +246,7 @@ value of the last statement in BODY, as elisp."
"Import data from FILE-NAME.
This removes initial blank and comment lines and then calls
`org-babel-import-elisp-from-file'."
- (let ((temp-file (make-temp-file "org-babel-results-")) beg end)
+ (let ((temp-file (org-babel-temp-file "results-")) beg end)
(with-temp-file temp-file
(insert-file-contents file-name)
(re-search-forward "^[ \t]*[^# \t]" nil t)
diff --git a/lisp/ob-org.el b/lisp/ob-org.el
new file mode 100644
index 0000000..4d42246
--- /dev/null
+++ b/lisp/ob-org.el
@@ -0,0 +1,81 @@
+;;; ob-org.el --- org-babel functions for org code block evaluation
+
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+
+;; Author: Eric Schulte
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+;; Version: 7.01trans
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This is the simplest of code blocks, where upon evaluation the
+;; contents of the code block are returned in a raw result.
+
+;;; Code:
+(require 'ob)
+
+(declare-function org-load-modules-maybe "org" (&optional force))
+(declare-function org-get-local-variables "org" ())
+
+(defvar org-babel-default-header-args:org
+ '((:results . "raw silent") (:exports . "results"))
+ "Default arguments for evaluating a org source block.")
+
+(defvar org-babel-org-default-header
+ "#+TITLE: default empty header\n"
+ "Default header inserted during export of org blocks.")
+
+(defun org-babel-expand-body:org (body params &optional processed-params)
+ "Expand BODY according to PARAMS, return the expanded body." body)
+
+(defun org-babel-execute:org (body params)
+ "Execute a block of Org code with.
+This function is called by `org-babel-execute-src-block'."
+ (let ((result-params (split-string (or (cdr (assoc :results params)) ""))))
+ (cond
+ ((member "latex" result-params) (org-babel-org-export body "latex"))
+ ((member "html" result-params) (org-babel-org-export body "html"))
+ ((member "ascii" result-params) (org-babel-org-export body "ascii"))
+ (t body))))
+
+(defvar org-local-vars)
+(defun org-babel-org-export (body fmt)
+ "Export BODY to FMT using Org-mode's export facilities. "
+ (let ((tmp-file (org-babel-temp-file "org-")))
+ (with-temp-buffer
+ (insert org-babel-org-default-header)
+ (insert body)
+ (write-file tmp-file)
+ (org-load-modules-maybe)
+ (unless org-local-vars
+ (setq org-local-vars (org-get-local-variables)))
+ (eval ;; convert to fmt -- mimicing `org-run-like-in-org-mode'
+ (list 'let org-local-vars
+ (list (intern (concat "org-export-as-" fmt))
+ nil nil nil ''string t))))))
+
+(defun org-babel-prep-session:org (session params)
+ "Return an error because org does not support sessions."
+ (error "Org does not support sessions"))
+
+(provide 'ob-org)
+
+;; arch-tag: 130af5fe-cc56-46bd-9508-fa0ebd94cb1f
+
+;;; ob-org.el ends here
diff --git a/lisp/ob-perl.el b/lisp/ob-perl.el
index 6e83542..3e4873d 100644
--- a/lisp/ob-perl.el
+++ b/lisp/ob-perl.el
@@ -107,7 +107,7 @@ return the value of the last statement in BODY, as elisp."
(when session (error "Sessions are not supported for Perl."))
(case result-type
(output (org-babel-eval org-babel-perl-command body))
- (value (let ((tmp-file (make-temp-file "org-babel-perl-results-")))
+ (value (let ((tmp-file (org-babel-temp-file "perl-results-")))
(org-babel-eval
org-babel-perl-command
(format org-babel-perl-wrapper-method body tmp-file))
diff --git a/lisp/ob-plantuml.el b/lisp/ob-plantuml.el
new file mode 100644
index 0000000..b1814cf
--- /dev/null
+++ b/lisp/ob-plantuml.el
@@ -0,0 +1,86 @@
+;;; ob-plantuml.el --- org-babel functions for plantuml evaluation
+
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+
+;; Author: Zhang Weize
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+;; Version: 7.01trans
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Org-Babel support for evaluating plantuml script.
+;;
+;; Inspired by Ian Yang's org-export-blocks-format-plantuml
+;; http://www.emacswiki.org/emacs/org-export-blocks-format-plantuml.el
+
+;;; Requirements:
+
+;; plantuml | http://plantuml.sourceforge.net/
+;; plantuml.jar | `org-plantuml-jar-path' should point to the jar file
+
+;;; Code:
+(require 'ob)
+(require 'ob-eval)
+
+(defvar org-babel-default-header-args:plantuml
+ '((:results . "file") (:exports . "results"))
+ "Default arguments for evaluating a plantuml source block.")
+
+(defun org-babel-expand-body:plantuml (body params &optional processed-params)
+ "Expand BODY according to PARAMS, return the expanded body." body)
+
+(defcustom org-plantuml-jar-path nil
+ "Path to the plantuml.jar file."
+ :group 'org-babel
+ :type 'string)
+
+(defun org-babel-execute:plantuml (body params)
+ "Execute a block of plantuml code with org-babel.
+This function is called by `org-babel-execute-src-block'."
+ (let* ((result-params (split-string (or (cdr (assoc :results params)) "")))
+ (out-file (or (cdr (assoc :file params))
+ (error "plantuml requires a \":file\" header argument")))
+ (cmdline (cdr (assoc :cmdline params)))
+ (in-file (org-babel-temp-file "plantuml-"))
+ (cmd (if (not org-plantuml-jar-path)
+ (error "`org-plantuml-jar-path' is not set")
+ (concat "java -jar "
+ (shell-quote-argument
+ (expand-file-name org-plantuml-jar-path))
+ " -p " cmdline " < "
+ (shell-quote-argument
+ (expand-file-name in-file))
+ " > "
+ (shell-quote-argument
+ (expand-file-name out-file))))))
+ (unless (file-exists-p org-plantuml-jar-path)
+ (error "Could not find plantuml.jar at %s" org-plantuml-jar-path))
+ (with-temp-file in-file (insert (concat "@startuml\n" body "\n@enduml")))
+ (message "%s" cmd) (org-babel-eval cmd "")
+ out-file))
+
+(defun org-babel-prep-session:plantuml (session params)
+ "Return an error because plantuml does not support sessions."
+ (error "Plantuml does not support sessions"))
+
+(provide 'ob-plantuml)
+
+;; arch-tag: 451f50c5-e779-407e-ad64-70e0e8f161d1
+
+;;; ob-plantuml.el ends here
diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index e7101f0..1d2e8f5 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -150,10 +150,10 @@ then create. Return the initialized session."
(let* ((session (if session (intern session) :default))
(python-buffer (org-babel-python-session-buffer session)))
(cond
- ((and (equal 'python org-babel-python-mode)
+ ((and (eq 'python org-babel-python-mode)
(fboundp 'run-python)) ; python.el
(run-python))
- ((and (equal 'python-mode org-babel-python-mode)
+ ((and (eq 'python-mode org-babel-python-mode)
(fboundp 'py-shell)) ; python-mode.el
;; `py-shell' creates a buffer whose name is the value of
;; `py-which-bufname' with '*'s at the beginning and end
@@ -194,73 +194,87 @@ def main():
open('%s', 'w').write( pprint.pformat(main()) )")
(defun org-babel-python-evaluate
- (buffer body &optional result-type result-params)
- "Pass BODY to the Python process in BUFFER.
-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."
- (if (not buffer)
- ;; external process evaluation
- (case result-type
- (output (org-babel-eval org-babel-python-command body))
- (value (let ((tmp-file (make-temp-file "org-babel-python-results-")))
- (org-babel-eval org-babel-python-command
- (format
- (if (member "pp" result-params)
- org-babel-python-pp-wrapper-method
- org-babel-python-wrapper-method)
- (mapconcat
- (lambda (line) (format "\t%s" line))
- (split-string
- (org-remove-indentation
- (org-babel-trim body))
- "[\r\n]") "\n")
- tmp-file))
- ((lambda (raw)
- (if (or (member "code" result-params)
- (member "pp" result-params))
- raw
- (org-babel-python-table-or-string raw)))
- (org-babel-eval-read-file tmp-file)))))
- ;; comint session evaluation
- (flet ((dump-last-value (tmp-file pp)
- (mapc
- (lambda (statement) (insert statement) (comint-send-input))
- (if pp
- (list
- "import pp"
- (format "open('%s', 'w').write(pprint.pformat(_))" tmp-file))
- (list (format "open('%s', 'w').write(str(_))" tmp-file)))))
- (input-body (body)
- (mapc (lambda (statement) (insert statement) (comint-send-input))
- (split-string (org-babel-trim body) "[\r\n]+"))
- (comint-send-input) (comint-send-input)))
- (case result-type
- (output
- (mapconcat
- #'org-babel-trim
- (butlast
- (org-babel-comint-with-output
- (buffer org-babel-python-eoe-indicator t body)
- (let ((comint-process-echoes nil))
- (input-body body)
- (insert org-babel-python-eoe-indicator)
- (comint-send-input))) 2) "\n"))
- (value
- ((lambda (results)
- (if (or (member "code" result-params) (member "pp" result-params))
- results
- (org-babel-python-table-or-string results)))
- (let ((tmp-file (make-temp-file "org-babel-python-results-")))
- (org-babel-comint-with-output
- (buffer org-babel-python-eoe-indicator t body)
- (let ((comint-process-echoes nil))
- (input-body body)
- (dump-last-value tmp-file (member "pp" result-params))
- (comint-send-input) (comint-send-input)
- (insert org-babel-python-eoe-indicator)
- (comint-send-input)))
- (org-babel-eval-read-file tmp-file))))))))
+ (session body &optional result-type result-params)
+ "Evaluate BODY as python code."
+ (if session
+ (org-babel-python-evaluate-session
+ session body result-type result-params)
+ (org-babel-python-evaluate-external-process
+ body result-type result-params)))
+
+(defun org-babel-python-evaluate-external-process
+ (body &optional result-type result-params)
+ "Evaluate BODY in external python 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
+ (output (org-babel-eval org-babel-python-command body))
+ (value (let ((tmp-file (org-babel-temp-file "python-results-")))
+ (org-babel-eval org-babel-python-command
+ (format
+ (if (member "pp" result-params)
+ org-babel-python-pp-wrapper-method
+ org-babel-python-wrapper-method)
+ (mapconcat
+ (lambda (line) (format "\t%s" line))
+ (split-string
+ (org-remove-indentation
+ (org-babel-trim body))
+ "[\r\n]") "\n")
+ tmp-file))
+ ((lambda (raw)
+ (if (or (member "code" result-params)
+ (member "pp" result-params))
+ raw
+ (org-babel-python-table-or-string raw)))
+ (org-babel-eval-read-file tmp-file))))))
+
+(defun org-babel-python-evaluate-session
+ (session body &optional result-type result-params)
+ "Pass BODY to the Python process 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."
+ (flet ((dump-last-value
+ (tmp-file pp)
+ (mapc
+ (lambda (statement) (insert statement) (comint-send-input))
+ (if pp
+ (list
+ "import pp"
+ (format "open('%s', 'w').write(pprint.pformat(_))" tmp-file))
+ (list (format "open('%s', 'w').write(str(_))" tmp-file)))))
+ (input-body (body)
+ (mapc (lambda (statement) (insert statement) (comint-send-input))
+ (split-string (org-babel-trim body) "[\r\n]+"))
+ (comint-send-input) (comint-send-input)))
+ (case result-type
+ (output
+ (mapconcat
+ #'org-babel-trim
+ (butlast
+ (org-babel-comint-with-output
+ (session org-babel-python-eoe-indicator t body)
+ (let ((comint-process-echoes nil))
+ (input-body body)
+ (insert org-babel-python-eoe-indicator)
+ (comint-send-input))) 2) "\n"))
+ (value
+ ((lambda (results)
+ (if (or (member "code" result-params) (member "pp" result-params))
+ results
+ (org-babel-python-table-or-string results)))
+ (let ((tmp-file (org-babel-temp-file "python-results-")))
+ (org-babel-comint-with-output
+ (session org-babel-python-eoe-indicator t body)
+ (let ((comint-process-echoes nil))
+ (input-body body)
+ (dump-last-value tmp-file (member "pp" result-params))
+ (comint-send-input) (comint-send-input)
+ (insert org-babel-python-eoe-indicator)
+ (comint-send-input)))
+ (org-babel-eval-read-file tmp-file)))))))
(defun org-babel-python-read-string (string)
"Strip 's from around python string"
diff --git a/lisp/ob-ruby.el b/lisp/ob-ruby.el
index e5ee508..87df8d1 100644
--- a/lisp/ob-ruby.el
+++ b/lisp/ob-ruby.el
@@ -54,7 +54,6 @@
(defun org-babel-expand-body:ruby (body params &optional processed-params)
"Expand BODY according to PARAMS, return the expanded body."
- (require 'inf-ruby)
(let ((vars (nth 1 (or processed-params (org-babel-process-params params)))))
(concat
(mapconcat ;; define any variables
@@ -186,7 +185,7 @@ return the value of the last statement in BODY, as elisp."
;; external process evaluation
(case result-type
(output (org-babel-eval org-babel-ruby-command body))
- (value (let ((tmp-file (make-temp-file "org-babel-ruby-results-")))
+ (value (let ((tmp-file (org-babel-temp-file "ruby-results-")))
(org-babel-eval org-babel-ruby-command
(format (if (member "pp" result-params)
org-babel-ruby-pp-wrapper-method
@@ -221,7 +220,7 @@ return the value of the last statement in BODY, as elisp."
(if (or (member "code" result-params) (member "pp" result-params))
results
(org-babel-ruby-table-or-string results)))
- (let* ((tmp-file (make-temp-file "org-babel-ruby-results-"))
+ (let* ((tmp-file (org-babel-temp-file "ruby-results-"))
(ppp (or (member "code" result-params)
(member "pp" result-params))))
(org-babel-comint-with-output
diff --git a/lisp/ob-sass.el b/lisp/ob-sass.el
index b834a80..2e624f2 100644
--- a/lisp/ob-sass.el
+++ b/lisp/ob-sass.el
@@ -51,9 +51,9 @@
This function is called by `org-babel-execute-src-block'."
(let* ((result-params (split-string (or (cdr (assoc :results params)) "")))
(file (cdr (assoc :file params)))
- (out-file (or file (make-temp-file "org-babel-sass-out")))
+ (out-file (or file (org-babel-temp-file "sass-out-")))
(cmdline (cdr (assoc :cmdline params)))
- (in-file (make-temp-file "org-babel-sass-in"))
+ (in-file (org-babel-temp-file "sass-in-"))
(cmd (concat "sass " (or cmdline "") in-file " " out-file)))
(with-temp-file in-file
(insert (org-babel-expand-body:sass body params))) (shell-command cmd)
diff --git a/lisp/ob-scheme.el b/lisp/ob-scheme.el
new file mode 100644
index 0000000..38df35b
--- /dev/null
+++ b/lisp/ob-scheme.el
@@ -0,0 +1,138 @@
+;;; ob-scheme.el --- org-babel functions for Scheme
+
+;; Copyright (C) 2010 Free Software Foundation
+
+;; Author: Eric Schulte
+;; Keywords: literate programming, reproducible research, scheme
+;; Homepage: http://orgmode.org
+;; Version: 0.01
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Now working with SBCL for both session and external evaluation.
+;;
+;; This certainly isn't optimally robust, but it seems to be working
+;; for the basic use cases.
+
+;;; Requirements:
+
+;; - a working scheme implementation
+;; (e.g. guile http://www.gnu.org/software/guile/guile.html)
+;;
+;; - for session based evaluation cmuscheme.el is required which is
+;; included in Emacs
+
+;;; Code:
+(require 'ob)
+(require 'ob-ref)
+(require 'ob-comint)
+(require 'ob-eval)
+(eval-when-compile (require 'cl))
+
+(declare-function run-scheme "ext:cmuscheme" (cmd))
+
+(defvar org-babel-default-header-args:scheme '()
+ "Default header arguments for scheme code blocks.")
+
+(defvar org-babel-scheme-eoe "org-babel-scheme-eoe"
+ "String to indicate that evaluation has completed.")
+
+(defcustom org-babel-scheme-cmd "guile"
+ "Name of command used to evaluate scheme blocks."
+ :group 'org-babel
+ :type 'string)
+
+(defun org-babel-expand-body:scheme (body params &optional processed-params)
+ "Expand BODY according to PARAMS, return the expanded body."
+ (let ((vars (nth 1 (or processed-params (org-babel-process-params params)))))
+ (if (> (length vars) 0)
+ (concat "(let ("
+ (mapconcat
+ (lambda (var) (format "%S" (print `(,(car var) ',(cdr var)))))
+ vars "\n ")
+ ")\n" body ")")
+ body)))
+
+(defvar scheme-program-name)
+(defun org-babel-execute:scheme (body params)
+ "Execute a block of Scheme code with org-babel.
+This function is called by `org-babel-execute-src-block'"
+ (let* ((processed-params (org-babel-process-params params))
+ (result-type (nth 3 processed-params))
+ (org-babel-scheme-cmd (or (cdr (assoc :scheme params)) org-babel-scheme-cmd))
+ (full-body (org-babel-expand-body:scheme body params processed-params)))
+ (read
+ (if (not (string= (nth 0 processed-params) "none"))
+ ;; session evaluation
+ (let ((session (org-babel-prep-session:scheme
+ (nth 0 processed-params) params)))
+ (org-babel-comint-with-output
+ (session (format "%S" org-babel-scheme-eoe) t body)
+ (mapc
+ (lambda (line)
+ (insert (org-babel-chomp line)) (comint-send-input nil t))
+ (list body (format "%S" org-babel-scheme-eoe)))))
+ ;; external evaluation
+ (let ((script-file (org-babel-temp-file "lisp-script-")))
+ (with-temp-file script-file
+ (insert
+ ;; return the value or the output
+ (if (string= result-type "value")
+ (format "(display %s)" full-body)
+ full-body)))
+ (org-babel-eval
+ (format "%s %s" org-babel-scheme-cmd script-file) ""))))))
+
+(defun org-babel-prep-session:scheme (session params)
+ "Prepare SESSION according to the header arguments specified in PARAMS."
+ (let* ((session (org-babel-scheme-initiate-session session))
+ (vars (org-babel-ref-variables params))
+ (var-lines
+ (mapcar
+ (lambda (var) (format "%S" (print `(define ,(car var) ',(cdr var)))))
+ vars)))
+ (when session
+ (org-babel-comint-in-buffer session
+ (sit-for .5) (goto-char (point-max))
+ (mapc (lambda (var)
+ (insert var) (comint-send-input nil t)
+ (org-babel-comint-wait-for-output session)
+ (sit-for .1) (goto-char (point-max))) var-lines)))
+ session))
+
+(defun org-babel-scheme-initiate-session (&optional session)
+ "If there is not a current inferior-process-buffer in SESSION
+then create. Return the initialized session."
+ (require 'cmuscheme)
+ (unless (string= session "none")
+ (let ((session-buffer (save-window-excursion
+ (run-scheme org-babel-scheme-cmd)
+ (rename-buffer session)
+ (current-buffer))))
+ (if (org-babel-comint-buffer-livep session-buffer)
+ (progn (sit-for .25) session-buffer)
+ (sit-for .5)
+ (org-babel-scheme-initiate-session session)))))
+
+(provide 'ob-scheme)
+
+;; arch-tag: 6b2fe76f-4b25-4e87-ad1c-225b2f282a71
+
+;;; ob-scheme.el ends here
diff --git a/lisp/ob-sh.el b/lisp/ob-sh.el
index ced35c0..cf8f829 100644
--- a/lisp/ob-sh.el
+++ b/lisp/ob-sh.el
@@ -155,12 +155,12 @@ return the value of the last statement in BODY."
(if (or (member "scalar" result-params)
(member "output" result-params))
results
- (let ((tmp-file (make-temp-file "org-babel-sh")))
+ (let ((tmp-file (org-babel-temp-file "sh-")))
(with-temp-file tmp-file (insert results))
(org-babel-import-elisp-from-file tmp-file))))
(if (not session)
(org-babel-eval org-babel-sh-command (org-babel-trim body))
- (let ((tmp-file (make-temp-file "org-babel-sh")))
+ (let ((tmp-file (org-babel-temp-file "sh-")))
(mapconcat
#'org-babel-sh-strip-weird-long-prompt
(mapcar
diff --git a/lisp/ob-sql.el b/lisp/ob-sql.el
index 60907e3..4e1daa5 100644
--- a/lisp/ob-sql.el
+++ b/lisp/ob-sql.el
@@ -60,9 +60,9 @@ This function is called by `org-babel-execute-src-block'."
(processed-params (org-babel-process-params params))
(cmdline (cdr (assoc :cmdline params)))
(engine (cdr (assoc :engine params)))
- (in-file (make-temp-file "org-babel-sql-in"))
+ (in-file (org-babel-temp-file "sql-in-"))
(out-file (or (cdr (assoc :out-file params))
- (make-temp-file "org-babel-sql-out")))
+ (org-babel-temp-file "sql-out-")))
(command (case (intern engine)
('mysql (format "mysql %s -e \"source %s\" > %s"
(or cmdline "") in-file out-file))
diff --git a/lisp/ob-sqlite.el b/lisp/ob-sqlite.el
index 99ae51b..e53d074 100644
--- a/lisp/ob-sqlite.el
+++ b/lisp/ob-sqlite.el
@@ -73,7 +73,7 @@ This function is called by `org-babel-execute-src-block'."
(insert (org-babel-expand-body:sqlite
body nil (list nil vars))))
sql-file)
- (make-temp-file "ob-sqlite-sql")))
+ (org-babel-temp-file "sqlite-sql-")))
(cons "cmd" org-babel-sqlite3-command)
(cons "header" (if headers-p "-header" "-noheader"))
(cons "separator"
@@ -117,7 +117,7 @@ This function is called by `org-babel-execute-src-block'."
el
(format "%S" el)))))))
data-file)
- (make-temp-file "ob-sqlite-data"))
+ (org-babel-temp-file "sqlite-data-"))
(if (stringp val) val (format "%S" val))))
(cdr pair))
body)))
diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index a7ba072..88a6a56 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -34,7 +34,10 @@
(declare-function org-link-escape "org" (text &optional table))
(declare-function org-heading-components "org" ())
+(declare-function org-back-to-heading "org" (invisible-ok))
+(declare-function org-fill-template "org" (template alist))
+;;;###autoload
(defcustom org-babel-tangle-lang-exts
'(("emacs-lisp" . "el"))
"Alist mapping languages to their file extensions.
@@ -53,6 +56,38 @@ then the name of the language is used."
:group 'org-babel
:type 'hook)
+(defcustom org-babel-pre-tangle-hook '(save-buffer)
+ "Hook run at the beginning of `org-babel-tangle'."
+ :group 'org-babel
+ :type 'hook)
+
+(defcustom org-babel-tangle-pad-newline t
+ "Switch indicating whether to pad tangled code with newlines."
+ :group 'org-babel
+ :type 'boolean)
+
+(defcustom org-babel-tangle-comment-format-beg "[[%link][%sourcename]]"
+ "Format of inserted comments in tangled code files.
+The following format strings can be used to insert special
+information into the output using `org-fill-template'.
+%start-line --- the line number at the start of the code block
+%file --------- the file from which the code block was tangled
+%link --------- Org-mode style link to the code block
+%source-name -- name of the code block"
+ :group 'org-babel
+ :type 'string)
+
+(defcustom org-babel-tangle-comment-format-end "%sourcename ends here"
+ "Format of inserted comments in tangled code files.
+The following format strings can be used to insert special
+information into the output using `org-fill-template'.
+%start-line --- the line number at the start of the code block
+%file --------- the file from which the code block was tangled
+%link --------- Org-mode style link to the code block
+%source-name -- name of the code block"
+ :group 'org-babel
+ :type 'string)
+
(defun org-babel-find-file-noselect-refresh (file)
"Find file ensuring that the latest changes on disk are
represented in the file."
@@ -127,7 +162,7 @@ TARGET-FILE can be used to specify a default export file for all
source blocks. Optional argument LANG can be used to limit the
exported source code blocks by language."
(interactive)
- (save-buffer)
+ (run-hooks 'org-babel-pre-tangle-hook)
(save-excursion
(let ((block-counter 0)
(org-babel-default-header-args
@@ -152,7 +187,7 @@ exported source code blocks by language."
(mapc
(lambda (spec)
(flet ((get-spec (name)
- (cdr (assoc name (nth 2 spec)))))
+ (cdr (assoc name (nth 4 spec)))))
(let* ((tangle (get-spec :tangle))
(she-bang ((lambda (sheb) (when (> (length sheb) 0) sheb))
(get-spec :shebang)))
@@ -187,7 +222,7 @@ exported source code blocks by language."
(insert content)
(write-region nil nil file-name))))
;; if files contain she-bangs, then make the executable
- (when she-bang (set-file-modes file-name ?\755))
+ (when she-bang (set-file-modes file-name #o755))
;; update counter
(setq block-counter (+ 1 block-counter))
(add-to-list 'path-collector file-name)))))
@@ -219,7 +254,7 @@ references."
(save-excursion (end-of-line 1) (forward-char 1) (point)))))
(defvar org-stored-links)
-(defun org-babel-tangle-collect-blocks (&optional lang)
+(defun org-babel-tangle-collect-blocks (&optional language)
"Collect source blocks in the current Org-mode file.
Return an association list of source-code block specifications of
the form used by `org-babel-spec-to-string' grouped by language.
@@ -237,43 +272,53 @@ code blocks by language."
(condition-case nil
(nth 4 (org-heading-components))
(error (buffer-file-name)))))
- (let* ((link (progn (call-interactively 'org-store-link)
+ (let* ((start-line (save-restriction (widen)
+ (+ 1 (line-number-at-pos (point)))))
+ (file (buffer-file-name))
+ (link (progn (call-interactively 'org-store-link)
(org-babel-clean-text-properties
(car (pop org-stored-links)))))
(info (org-babel-get-src-block-info))
+ (params (nth 2 info))
(source-name (intern (or (nth 4 info)
(format "%s:%d"
current-heading block-counter))))
- (src-lang (nth 0 info))
+ (src-lang (nth 0 info))
(expand-cmd (intern (concat "org-babel-expand-body:" src-lang)))
- (params (nth 2 info))
+ (body ((lambda (body)
+ (if (assoc :no-expand params)
+ body
+ (funcall (if (fboundp expand-cmd)
+ expand-cmd
+ 'org-babel-expand-body:generic)
+ body params)))
+ (if (and (cdr (assoc :noweb params))
+ (string= "yes" (cdr (assoc :noweb params))))
+ (org-babel-expand-noweb-references info)
+ (nth 1 info))))
+ (comment (when (or (string= "both" (cdr (assoc :comments params)))
+ (string= "org" (cdr (assoc :comments params))))
+ ;; from the previous heading or code-block end
+ (buffer-substring
+ (max (condition-case nil
+ (save-excursion
+ (org-back-to-heading t) (point))
+ (error 0))
+ (save-excursion (re-search-backward
+ org-babel-src-block-regexp nil t)
+ (match-end 0)))
+ (point))))
by-lang)
- (unless (string= (cdr (assoc :tangle params)) "no") ;; skip
- (unless (and lang (not (string= lang src-lang))) ;; limit by language
+ (unless (string= (cdr (assoc :tangle params)) "no")
+ (unless (and language (not (string= language src-lang)))
;; add the spec for this block to blocks under it's language
(setq by-lang (cdr (assoc src-lang blocks)))
(setq blocks (delq (assoc src-lang blocks) blocks))
- (setq blocks
- (cons
- (cons src-lang
- (cons (list link source-name params
- ((lambda (body)
- (if (assoc :no-expand params)
- body
- (funcall
- (if (fboundp expand-cmd)
- expand-cmd
- 'org-babel-expand-body:generic)
- body
- params)))
- (if (and (cdr (assoc :noweb params))
- (string=
- "yes"
- (cdr (assoc :noweb params))))
- (org-babel-expand-noweb-references
- info)
- (nth 1 info))))
- by-lang)) blocks))))))
+ (setq blocks (cons
+ (cons src-lang
+ (cons (list start-line file link
+ source-name params body comment)
+ by-lang)) blocks))))))
;; ensure blocks in the correct order
(setq blocks
(mapcar
@@ -288,22 +333,39 @@ source code file. This function uses `comment-region' which
assumes that the appropriate major-mode is set. SPEC has the
form
- (link source-name params body)"
- (let ((link (nth 0 spec))
- (source-name (nth 1 spec))
- (body (nth 3 spec))
- (commentable (string= (cdr (assoc :comments (nth 2 spec))) "yes")))
+ (start-line file link source-name params body comment)"
+ (let* ((start-line (nth 0 spec))
+ (file (nth 1 spec))
+ (link (org-link-escape (nth 2 spec)))
+ (source-name (nth 3 spec))
+ (body (nth 5 spec))
+ (comment (nth 6 spec))
+ (comments (cdr (assoc :comments (nth 4 spec))))
+ (link-p (or (string= comments "both") (string= comments "link")
+ (string= comments "yes")))
+ (link-data (mapcar (lambda (el)
+ (cons (symbol-name el)
+ ((lambda (le)
+ (if (stringp le) le (format "%S" le)))
+ (eval el))))
+ '(start-line file link source-name))))
(flet ((insert-comment (text)
- (when commentable
- (insert "\n")
- (comment-region (point)
- (progn (insert text) (point)))
- (end-of-line nil)
- (insert "\n"))))
- (insert-comment (format "[[%s][%s]]" (org-link-escape link) source-name))
- (insert (format "\n%s\n" (replace-regexp-in-string
- "^," "" (org-babel-chomp body))))
- (insert-comment (format "%s ends here" source-name)))))
+ (let ((text (org-babel-trim text)))
+ (when (and comments (not (string= comments "no"))
+ (> (length text) 0))
+ (when org-babel-tangle-pad-newline (insert "\n"))
+ (comment-region (point) (progn (insert text) (point)))
+ (end-of-line nil) (insert "\n")))))
+ (when comment (insert-comment comment))
+ (when link-p
+ (insert-comment
+ (org-fill-template org-babel-tangle-comment-format-beg link-data)))
+ (when org-babel-tangle-pad-newline (insert "\n"))
+ (insert (format "%s\n" (replace-regexp-in-string
+ "^," "" (org-babel-trim body))))
+ (when link-p
+ (insert-comment
+ (org-fill-template org-babel-tangle-comment-format-end link-data))))))
(provide 'ob-tangle)
diff --git a/lisp/ob.el b/lisp/ob.el
index b5b9d8f..069ccfa 100644
--- a/lisp/ob.el
+++ b/lisp/ob.el
@@ -25,33 +25,39 @@
;;; Commentary:
;; See the online documentation for more information
-;;
+;;
;; http://orgmode.org/worg/org-contrib/babel/
;;; Code:
-(eval-when-compile (require 'cl))
+(eval-when-compile
+ (require 'cl))
(require 'org-macs)
(defvar org-babel-call-process-region-original)
(declare-function show-all "outline" ())
-(declare-function tramp-compat-make-temp-file "tramp" (filename &optional dir-flag))
+(declare-function tramp-compat-make-temp-file "tramp-compat"
+ (filename &optional dir-flag))
(declare-function tramp-dissect-file-name "tramp" (name &optional nodefault))
(declare-function tramp-file-name-user "tramp" (vec))
(declare-function tramp-file-name-host "tramp" (vec))
+(declare-function with-parsed-tramp-file-name "tramp" (filename var &rest body))
(declare-function org-icompleting-read "org" (&rest args))
-(declare-function org-edit-src-code "org" (context code edit-buffer-name))
+(declare-function org-edit-src-code "org-src"
+ (&optional context code edit-buffer-name quietp))
+(declare-function org-edit-src-exit "org-src" (&optional context))
(declare-function org-open-at-point "org" (&optional in-emacs reference-buffer))
(declare-function org-save-outline-visibility "org" (use-markers &rest body))
+(declare-function org-outline-overlay-data "org" (&optional use-markers))
+(declare-function org-set-outline-overlay-data "org" (data))
(declare-function org-narrow-to-subtree "org" ())
-(declare-function org-entry-get "org" (pom property &optional inherit))
+(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
(declare-function org-make-options-regexp "org" (kwds &optional extra))
-(declare-function org-match-string-no-properties "org" (num &optional string))
(declare-function org-do-remove-indentation "org" (&optional n))
(declare-function org-show-context "org" (&optional key))
(declare-function org-at-table-p "org" (&optional table-type))
(declare-function org-cycle "org" (&optional arg))
(declare-function org-uniquify "org" (list))
-(declare-function org-table-import "org" (file arg))
+(declare-function org-table-import "org-table" (file arg))
(declare-function org-add-hook "org-compat" (hook function &optional append local))
(declare-function org-table-align "org-table" ())
(declare-function org-table-end "org-table" (&optional table-type))
@@ -182,18 +188,20 @@ confirmation from the user.
Note disabling confirmation may result in accidental evaluation
of potentially harmful code."
- (let* ((eval (cdr (assoc :eval (nth 2 info))))
+ (let* ((eval (or (cdr (assoc :eval (nth 2 info)))
+ (when (assoc :noeval (nth 2 info)) "no")))
(query (or (equal eval "query")
(and (functionp org-confirm-babel-evaluate)
(funcall org-confirm-babel-evaluate
(nth 0 info) (nth 1 info)))
org-confirm-babel-evaluate)))
- (when (or (equal eval "never")
- (and query
- (not (yes-or-no-p
- (format "Evaluate this%scode on your system? "
- (if info (format " %s " (nth 0 info)) " "))))))
- (error "evaluation aborted"))))
+ (if (or (equal eval "never") (equal eval "no")
+ (and query
+ (not (yes-or-no-p
+ (format "Evaluate this%scode on your system? "
+ (if info (format " %s " (nth 0 info)) " "))))))
+ (prog1 nil (message "evaluation aborted"))
+ t)))
;;;###autoload
(defun org-babel-execute-safely-maybe ()
@@ -254,7 +262,7 @@ then run `org-babel-pop-to-session'."
(defconst org-babel-header-arg-names
'(cache cmdline colnames dir exports file noweb results
- session tangle var noeval comments)
+ session tangle var eval noeval comments)
"Common header arguments used by org-babel.
Note that individual languages may define their own language
specific header arguments as well.")
@@ -315,6 +323,10 @@ Insert the results of execution into the buffer. Source code
execution and the collection and formatting of results can be
controlled through a variety of header arguments.
+With prefix argument ARG, force re-execution even if a an
+existing result cached in the buffer would otherwise have been
+returned.
+
Optionally supply a value for INFO in the form returned by
`org-babel-get-src-block-info'.
@@ -322,66 +334,65 @@ Optionally supply a value for PARAMS which will be merged with
the header arguments specified at the front of the source code
block."
(interactive)
- (let* ((info (or info (org-babel-get-src-block-info)))
- ;; note the `evaluation-confirmed' variable is currently not
- ;; used, but could be used later to avoid the need for
- ;; chaining confirmations
- (evaluation-confirmed (org-babel-confirm-evaluate info))
- (lang (nth 0 info))
- (params (setf (nth 2 info)
- (sort (org-babel-merge-params (nth 2 info) params)
- (lambda (el1 el2) (string< (symbol-name (car el1))
- (symbol-name (car el2)))))))
- (new-hash
- (if (and (cdr (assoc :cache params))
- (string= "yes" (cdr (assoc :cache params))))
- (org-babel-sha1-hash info)))
- (old-hash (org-babel-result-hash info))
- (body (setf (nth 1 info)
- (if (and (cdr (assoc :noweb params))
- (string= "yes" (cdr (assoc :noweb params))))
- (org-babel-expand-noweb-references info)
- (nth 1 info))))
- (result-params (split-string (or (cdr (assoc :results params)) "")))
- (result-type (cond ((member "output" result-params) 'output)
- ((member "value" result-params) 'value)
- (t 'value)))
- (cmd (intern (concat "org-babel-execute:" lang)))
- (dir (cdr (assoc :dir params)))
- (default-directory
- (or (and dir (file-name-as-directory dir)) default-directory))
- (org-babel-call-process-region-original
- (if (boundp 'org-babel-call-process-region-original) org-babel-call-process-region-original
- (symbol-function 'call-process-region)))
- (indent (car (last info)))
- result)
- (unwind-protect
- (flet ((call-process-region (&rest args)
- (apply 'org-babel-tramp-handle-call-process-region args)))
- (unless (fboundp cmd)
- (error "No org-babel-execute function for %s!" lang))
- (if (and (not arg) new-hash (equal new-hash old-hash))
- (save-excursion ;; return cached result
- (goto-char (org-babel-where-is-src-block-result nil info))
- (end-of-line 1) (forward-char 1)
- (setq result (org-babel-read-result))
- (message (replace-regexp-in-string "%" "%%"
- (format "%S" result))) result)
- (message "executing %s code block%s..."
- (capitalize lang)
- (if (nth 4 info) (format " (%s)" (nth 4 info)) ""))
- (setq result (funcall cmd body params))
- (if (eq result-type 'value)
- (setq result (if (and (or (member "vector" result-params)
- (member "table" result-params))
- (not (listp result)))
- (list (list result))
- result)))
- (org-babel-insert-result
- result result-params info new-hash indent lang)
- (run-hooks 'org-babel-after-execute-hook)
- result))
- (setq call-process-region 'org-babel-call-process-region-original))))
+ (let ((info (or info (org-babel-get-src-block-info))))
+ (when (org-babel-confirm-evaluate info)
+ (let* ((lang (nth 0 info))
+ (params (setf
+ (nth 2 info)
+ (sort (org-babel-merge-params (nth 2 info) params)
+ (lambda (el1 el2) (string< (symbol-name (car el1))
+ (symbol-name (car el2)))))))
+ (new-hash
+ (if (and (cdr (assoc :cache params))
+ (string= "yes" (cdr (assoc :cache params))))
+ (org-babel-sha1-hash info)))
+ (old-hash (org-babel-result-hash info))
+ (body (setf (nth 1 info)
+ (if (and (cdr (assoc :noweb params))
+ (string= "yes" (cdr (assoc :noweb params))))
+ (org-babel-expand-noweb-references info)
+ (nth 1 info))))
+ (result-params (split-string (or (cdr (assoc :results params)) "")))
+ (result-type (cond ((member "output" result-params) 'output)
+ ((member "value" result-params) 'value)
+ (t 'value)))
+ (cmd (intern (concat "org-babel-execute:" lang)))
+ (dir (cdr (assoc :dir params)))
+ (default-directory
+ (or (and dir (file-name-as-directory dir)) default-directory))
+ (org-babel-call-process-region-original
+ (if (boundp 'org-babel-call-process-region-original)
+ org-babel-call-process-region-original
+ (symbol-function 'call-process-region)))
+ (indent (car (last info)))
+ result)
+ (unwind-protect
+ (flet ((call-process-region (&rest args)
+ (apply 'org-babel-tramp-handle-call-process-region args)))
+ (unless (fboundp cmd)
+ (error "No org-babel-execute function for %s!" lang))
+ (if (and (not arg) new-hash (equal new-hash old-hash))
+ (save-excursion ;; return cached result
+ (goto-char (org-babel-where-is-src-block-result nil info))
+ (end-of-line 1) (forward-char 1)
+ (setq result (org-babel-read-result))
+ (message (replace-regexp-in-string
+ "%" "%%" (format "%S" result))) result)
+ (message "executing %s code block%s..."
+ (capitalize lang)
+ (if (nth 4 info) (format " (%s)" (nth 4 info)) ""))
+ (setq result (funcall cmd body params))
+ (if (eq result-type 'value)
+ (setq result (if (and (or (member "vector" result-params)
+ (member "table" result-params))
+ (not (listp result)))
+ (list (list result))
+ result)))
+ (org-babel-insert-result
+ result result-params info new-hash indent lang)
+ (run-hooks 'org-babel-after-execute-hook)
+ result))
+ (setq call-process-region 'org-babel-call-process-region-original))))))
(defun org-babel-expand-body:generic (body params &optional processed-params)
"Expand BODY with PARAMS.
@@ -421,8 +432,12 @@ session."
(interactive)
(let* ((info (or info (org-babel-get-src-block-info)))
(lang (nth 0 info))
- (body (nth 1 info))
(params (nth 2 info))
+ (body (setf (nth 1 info)
+ (if (and (cdr (assoc :noweb params))
+ (string= "yes" (cdr (assoc :noweb params))))
+ (org-babel-expand-noweb-references info)
+ (nth 1 info))))
(session (cdr (assoc :session params)))
(dir (cdr (assoc :dir params)))
(default-directory
@@ -434,12 +449,12 @@ session."
(end-of-line 1)))
;;;###autoload
-(defun org-babel-switch-to-session (&optional arg info)
- "Switch to the session of the current source-code block.
+(defun org-babel-initiate-session (&optional arg info)
+ "Initiate session for current code block.
If called with a prefix argument then evaluate the header arguments
-for the source block before entering the session. Copy the body
-of the source block to the kill ring."
- (interactive)
+for the code block before entering the session. Copy the body
+of the code block to the kill ring."
+ (interactive "P")
(let* ((info (or info (org-babel-get-src-block-info)))
(lang (nth 0 info))
(body (nth 1 info))
@@ -450,21 +465,72 @@ of the source block to the kill ring."
(or (and dir (file-name-as-directory dir)) default-directory))
(cmd (intern (format "org-babel-%s-initiate-session" lang)))
(cmd2 (intern (concat "org-babel-prep-session:" lang))))
+ (if (and (stringp session) (string= session "none"))
+ (error "This block is not using a session!"))
(unless (fboundp cmd)
(error "No org-babel-initiate-session function for %s!" lang))
- ;; copy body to the kill ring
(with-temp-buffer (insert (org-babel-trim body))
(copy-region-as-kill (point-min) (point-max)))
- ;; if called with a prefix argument, then process header arguments
- (unless (fboundp cmd2)
- (error "No org-babel-prep-session function for %s!" lang))
- (when arg (funcall cmd2 session params))
- ;; just to the session using pop-to-buffer
- (pop-to-buffer (funcall cmd session params))
- (end-of-line 1)))
+ (when arg
+ (unless (fboundp cmd2)
+ (error "No org-babel-prep-session function for %s!" lang))
+ (funcall cmd2 session params))
+ (funcall cmd session params)))
+
+;;;###autoload
+(defun org-babel-switch-to-session (&optional arg info)
+ "Switch to the session of the current code block.
+Uses `org-babel-initiate-session' to start the session. If called
+with a prefix argument then this is passed on to
+`org-babel-initiate-session'."
+ (interactive "P")
+ (pop-to-buffer (org-babel-initiate-session arg info))
+ (end-of-line 1))
(defalias 'org-babel-pop-to-session 'org-babel-switch-to-session)
+;;;###autoload
+(defun org-babel-switch-to-session-with-code (&optional arg info)
+ "Switch to code buffer and display session."
+ (interactive "P")
+ (flet ((swap-windows
+ ()
+ (let ((other-window-buffer (window-buffer (next-window))))
+ (set-window-buffer (next-window) (current-buffer))
+ (set-window-buffer (selected-window) other-window-buffer))
+ (other-window 1)))
+ (let ((info (org-babel-get-src-block-info))
+ (org-src-window-setup 'reorganize-frame))
+ (save-excursion
+ (org-babel-switch-to-session arg info))
+ (org-edit-src-code))
+ (swap-windows)))
+
+(defmacro org-babel-do-in-edit-buffer (&rest body)
+ "Evaluate BODY in edit buffer if there is a code block at point.
+Return t if a code block was found at point, nil otherwise."
+ `(let ((org-src-window-setup 'switch-invisibly))
+ (when (and (org-babel-where-is-src-block-head)
+ (org-edit-src-code nil nil nil 'quietly))
+ (unwind-protect (progn ,@body)
+ (if (org-bound-and-true-p org-edit-src-from-org-mode)
+ (org-edit-src-exit)))
+ t)))
+
+(defun org-babel-do-key-sequence-in-edit-buffer (key)
+ "Read key sequence and execute the command in edit buffer.
+Enter a key sequence to be executed in the language major-mode
+edit buffer. For example, TAB will alter the contents of the
+Org-mode code block according to the effect of TAB in the
+language major-mode buffer. For languages that support
+interactive sessions, this can be used to send code from the Org
+buffer to the session for evaluation using the native major-mode
+evaluation mechanisms."
+ (interactive "kEnter key-sequence to execute in edit buffer: ")
+ (org-babel-do-in-edit-buffer
+ (call-interactively
+ (key-binding (or key (read-key-sequence nil))))))
+
(defvar org-bracket-link-regexp)
;;;###autoload
(defun org-babel-open-src-block-result (&optional re-run)
@@ -522,7 +588,7 @@ the current subtree."
(save-restriction
(save-excursion
(org-narrow-to-subtree)
- (org-babel-execute-buffer)
+ (org-babel-execute-buffer arg)
(widen))))
;;;###autoload
@@ -663,20 +729,56 @@ portions of results lines."
'org-babel-show-result-all 'append 'local)))
(defmacro org-babel-map-src-blocks (file &rest body)
- "Evaluate BODY forms on each source-block in FILE."
+ "Evaluate BODY forms on each source-block in FILE.
+If FILE is nil evaluate BODY forms on source blocks in current
+buffer. During evaluation of BODY the following local variables
+are set relative to the currently matched code block.
+
+full-block ------- string holding the entirety of the code block
+beg-block -------- point at the beginning of the code block
+end-block -------- point at the end of the matched code block
+lang ------------- string holding the language of the code block
+beg-lang --------- point at the beginning of the lang
+end-lang --------- point at the end of the lang
+switches --------- string holding the switches
+beg-switches ----- point at the beginning of the switches
+end-switches ----- point at the end of the switches
+header-args ------ string holding the header-args
+beg-header-args -- point at the beginning of the header-args
+end-header-args -- point at the end of the header-args
+body ------------- string holding the body of the code block
+beg-body --------- point at the beginning of the body
+end-body --------- point at the end of the body"
(declare (indent 1))
- `(let ((visited-p (get-file-buffer (expand-file-name ,file)))
- to-be-removed)
+ `(let ((visited-p (or (null ,file)
+ (get-file-buffer (expand-file-name ,file))))
+ (point (point)) to-be-removed)
(save-window-excursion
- (find-file ,file)
+ (when ,file (find-file ,file))
(setq to-be-removed (current-buffer))
(goto-char (point-min))
(while (re-search-forward org-babel-src-block-regexp nil t)
(goto-char (match-beginning 0))
- (save-match-data ,@body)
+ (let ((full-block (match-string 0))
+ (beg-block (match-beginning 0))
+ (end-block (match-beginning 0))
+ (lang (match-string 2))
+ (beg-lang (match-beginning 2))
+ (end-lang (match-end 2))
+ (switches (match-string 3))
+ (beg-switches (match-beginning 3))
+ (end-switches (match-end 3))
+ (header-args (match-string 4))
+ (beg-header-args (match-beginning 4))
+ (end-header-args (match-end 4))
+ (body (match-string 5))
+ (beg-body (match-beginning 5))
+ (end-body (match-end 5)))
+ (save-match-data ,@body))
(goto-char (match-end 0))))
(unless visited-p
- (kill-buffer to-be-removed))))
+ (kill-buffer to-be-removed))
+ (goto-char point)))
(defvar org-file-properties)
(defun org-babel-params-from-properties (&optional lang)
@@ -921,6 +1023,14 @@ If the point is not on a source block then return nil."
(point))))))
;;;###autoload
+(defun org-babel-goto-src-block-head ()
+ "Go to the beginning of the current code block."
+ (interactive)
+ ((lambda (head)
+ (if head (goto-char head) (error "not currently in a code block")))
+ (org-babel-where-is-src-block-head)))
+
+;;;###autoload
(defun org-babel-goto-named-src-block (name)
"Go to a named source-code block."
(interactive
@@ -996,7 +1106,9 @@ buffer or nil if no such result exists."
With optional prefix argument ARG, jump forward ARG many source blocks."
(interactive "P")
(when (looking-at org-babel-src-block-regexp) (forward-char 1))
- (re-search-forward org-babel-src-block-regexp nil nil (or arg 1))
+ (condition-case nil
+ (re-search-forward org-babel-src-block-regexp nil nil (or arg 1))
+ (error (error "No further code blocks")))
(goto-char (match-beginning 0)) (org-show-context))
;;;###autoload
@@ -1004,7 +1116,9 @@ With optional prefix argument ARG, jump forward ARG many source blocks."
"Jump to the previous source block.
With optional prefix argument ARG, jump backward ARG many source blocks."
(interactive "P")
- (re-search-backward org-babel-src-block-regexp nil nil (or arg 1))
+ (condition-case nil
+ (re-search-backward org-babel-src-block-regexp nil nil (or arg 1))
+ (error (error "No previous code blocks")))
(goto-char (match-beginning 0)) (org-show-context))
(defvar org-babel-lob-one-liner-regexp)
@@ -1148,7 +1262,12 @@ raw ----- results are added directly to the org-mode file. This
is a good option if you code block will output org-mode
formatted text.
-org ----- this is the same as the 'raw' option
+org ----- similar in effect to raw, only the results are wrapped
+ in an org code block. Similar to the raw option, on
+ export the results will be interpreted as org-formatted
+ text, however by wrapping the results in an org code
+ block they can be replaced upon re-execution of the
+ code block.
html ---- results are added inside of a #+BEGIN_HTML block. This
is a good option if you code block will output html
@@ -1169,74 +1288,79 @@ code ---- the results are extracted in the syntax of the source
(when (member "file" result-params)
(setq result (org-babel-result-to-file result))))
(unless (listp result) (setq result (format "%S" result))))
- (if (= (length result) 0)
- (if (member "value" result-params)
- (message "No result returned by source block")
- (message "Source block produced no output"))
- (if (and result-params (member "silent" result-params))
- (progn
- (message (replace-regexp-in-string "%" "%%" (format "%S" result)))
- result)
- (when (and (stringp result) ;; ensure results end in a newline
- (not (or (string-equal (substring result -1) "\n")
- (string-equal (substring result -1) "\r"))))
- (setq result (concat result "\n")))
- (save-excursion
- (let ((existing-result (org-babel-where-is-src-block-result
- t info hash indent))
- (results-switches
- (cdr (assoc :results_switches (nth 2 info))))
- beg end)
- (if (not existing-result)
- (setq beg (point))
- (goto-char existing-result)
- (save-excursion
- (re-search-forward "#" nil t)
- (setq indent (- (current-column) 1)))
- (forward-line 1)
+ (if (and result-params (member "silent" result-params))
+ (progn
+ (message (replace-regexp-in-string "%" "%%" (format "%S" result)))
+ result)
+ (when (and (stringp result) ;; ensure results end in a newline
+ (> (length result) 0)
+ (not (or (string-equal (substring result -1) "\n")
+ (string-equal (substring result -1) "\r"))))
+ (setq result (concat result "\n")))
+ (save-excursion
+ (let ((existing-result (org-babel-where-is-src-block-result
+ t info hash indent))
+ (results-switches
+ (cdr (assoc :results_switches (nth 2 info))))
+ beg end)
+ (if (not existing-result)
(setq beg (point))
- (cond
- ((member "replace" result-params)
- (delete-region (point) (org-babel-result-end)))
- ((member "append" result-params)
- (goto-char (org-babel-result-end)) (setq beg (point)))
- ((member "prepend" result-params) ;; already there
- )))
- (setq results-switches
- (if results-switches (concat " " results-switches) ""))
+ (goto-char existing-result)
+ (save-excursion
+ (re-search-forward "#" nil t)
+ (setq indent (- (current-column) 1)))
+ (forward-line 1)
+ (setq beg (point))
(cond
- ;; assume the result is a table if it's not a string
- ((not (stringp result))
- (insert (concat (orgtbl-to-orgtbl
- (if (or (eq 'hline (car result))
- (and (listp (car result))
- (listp (cdr (car result)))))
- result (list result))
- '(:fmt (lambda (cell) (format "%s" cell)))) "\n"))
- (goto-char beg) (when (org-at-table-p) (org-table-align)))
- ((member "file" result-params)
- (insert result))
- ((member "html" result-params)
- (insert (format "#+BEGIN_HTML%s\n%s#+END_HTML\n"
- results-switches result)))
- ((member "latex" result-params)
- (insert (format "#+BEGIN_LaTeX%s\n%s#+END_LaTeX\n"
- results-switches result)))
- ((member "code" result-params)
- (insert (format "#+BEGIN_SRC %s%s\n%s#+END_SRC\n"
- (or lang "none") results-switches result)))
- ((or (member "raw" result-params) (member "org" result-params))
- (save-excursion (insert result)) (if (org-at-table-p) (org-cycle)))
- (t
- (org-babel-examplize-region
- (point) (progn (insert result) (point)) results-switches)))
- ;; possibly indent the results to match the #+results line
- (setq end (if (listp result) (org-table-end) (point)))
- (when (and indent (> indent 0)
- ;; in this case `table-align' does the work for us
- (not (and (listp result)
- (member "append" result-params))))
- (indent-rigidly beg end indent))))
+ ((member "replace" result-params)
+ (delete-region (point) (org-babel-result-end)))
+ ((member "append" result-params)
+ (goto-char (org-babel-result-end)) (setq beg (point)))
+ ((member "prepend" result-params) ;; already there
+ )))
+ (setq results-switches
+ (if results-switches (concat " " results-switches) ""))
+ (cond
+ ;; do nothing for an empty result
+ ((= (length result) 0))
+ ;; assume the result is a table if it's not a string
+ ((not (stringp result))
+ (insert (concat (orgtbl-to-orgtbl
+ (if (or (eq 'hline (car result))
+ (and (listp (car result))
+ (listp (cdr (car result)))))
+ result (list result))
+ '(:fmt (lambda (cell) (format "%s" cell)))) "\n"))
+ (goto-char beg) (when (org-at-table-p) (org-table-align)))
+ ((member "file" result-params)
+ (insert result))
+ ((member "html" result-params)
+ (insert (format "#+BEGIN_HTML%s\n%s#+END_HTML\n"
+ results-switches result)))
+ ((member "latex" result-params)
+ (insert (format "#+BEGIN_LaTeX%s\n%s#+END_LaTeX\n"
+ results-switches result)))
+ ((member "code" result-params)
+ (insert (format "#+BEGIN_SRC %s%s\n%s#+END_SRC\n"
+ (or lang "none") results-switches result)))
+ ((member "org" result-params)
+ (insert (format "#+BEGIN_SRC org\n%s#+END_SRC\n" result)))
+ ((member "raw" result-params)
+ (save-excursion (insert result)) (if (org-at-table-p) (org-cycle)))
+ (t
+ (org-babel-examplize-region
+ (point) (progn (insert result) (point)) results-switches)))
+ ;; possibly indent the results to match the #+results line
+ (setq end (if (listp result) (org-table-end) (point)))
+ (when (and indent (> indent 0)
+ ;; in this case `table-align' does the work for us
+ (not (and (listp result)
+ (member "append" result-params))))
+ (indent-rigidly beg end indent))))
+ (if (= (length result) 0)
+ (if (member "value" result-params)
+ (message "No result returned by source block")
+ (message "Source block produced no output"))
(message "finished"))))
(defun org-babel-remove-result (&optional info)
@@ -1291,7 +1415,7 @@ file's directory then expand relative links."
(let ((size (count-lines beg end)))
(save-excursion
(cond ((= size 0)
- (error (concat "This should be impossible:"
+ (error (concat "This should not be impossible:"
"a newline was appended to result if missing")))
((< size org-babel-min-lines-for-block-output)
(goto-char beg)
@@ -1604,6 +1728,57 @@ the remote connection."
(concat "/" user (when user "@") host ":" file))
file))
+(defun org-babel-tramp-localname (file)
+ "Return the local name component of FILE."
+ (if (file-remote-p file)
+ (let (localname)
+ (with-parsed-tramp-file-name file nil
+ localname))
+ file))
+
+;; (defvar org-babel-temporary-directory
+;; (or (and (boundp 'org-babel-temporary-directory)
+;; org-babel-temporary-directory)
+;; (make-temp-file "babel-" t))
+;; "Directory to hold temporary files created to execute code blocks.
+;; Used by `org-babel-temp-file'. This directory will be removed on
+;; Emacs shutdown.")
+
+(defun org-babel-temp-file (prefix &optional suffix)
+ "Create a temporary file in the `org-babel-temporary-directory'.
+Passes PREFIX and SUFFIX directly to `make-temp-file' with the
+value of `temporary-file-directory' temporarily set to the value
+of `org-babel-temporary-directory'."
+ (if (file-remote-p default-directory)
+ (make-temp-file
+ (concat (file-remote-p default-directory)
+ (expand-file-name
+ prefix temporary-file-directory)
+ nil suffix))
+ ;; (let ((temporary-file-directory (expand-file-name
+ ;; org-babel-temporary-directory
+ ;; temporary-file-directory)))
+ ;; (make-temp-file prefix nil suffix))
+ (make-temp-file prefix nil suffix)))
+
+;; (defun org-babel-remove-temporary-directory ()
+;; "Remove `org-babel-temporary-directory' on Emacs shutdown."
+;; (when (boundp 'org-babel-temporary-directory)
+;; ;; taken from `delete-directory' in files.el
+;; (mapc (lambda (file)
+;; ;; This test is equivalent to
+;; ;; (and (file-directory-p fn) (not (file-symlink-p fn)))
+;; ;; but more efficient
+;; (if (eq t (car (file-attributes file)))
+;; (delete-directory file)
+;; (delete-file file)))
+;; ;; We do not want to delete "." and "..".
+;; (directory-files org-babel-temporary-directory 'full
+;; "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"))
+;; (delete-directory org-babel-temporary-directory)))
+
+;; (add-hook 'kill-emacs-hook 'org-babel-remove-temporary-directory)
+
(provide 'ob)
;; arch-tag: 01a7ebee-06c5-4ee4-a709-e660d28c0af1
diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index 30e8033..7458076 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -1488,6 +1488,18 @@ the lower-case version of all tags."
(require 'cl))
(require 'org)
+(defmacro org-agenda-with-point-at-orig-entry (string &rest body)
+ "Execute BODY with point at location given by `org-hd-marker' property.
+If STRING is non-nil, the text property will be fetched from position 0
+in that string. If STRING is nil, it will be fetched from the beginning
+of the current line."
+ `(let ((marker (get-text-property (if string 0 (point-at-bol))
+ 'org-hd-marker string)))
+ (with-current-buffer (marker-buffer marker)
+ (save-excursion
+ (goto-char marker)
+ ,@body))))
+
(defun org-add-agenda-custom-command (entry)
"Replace or add a command in `org-agenda-custom-commands'.
This is mostly for hacking and trying a new command - once the command
@@ -2503,16 +2515,15 @@ higher priority settings."
(interactive "FWrite agenda to file: \nP")
(if (not (file-writable-p file))
(error "Cannot write agenda to file %s" file))
- (cond
- ((string-match "\\.html?\\'" file) (require 'htmlize))
- ((string-match "\\.ps\\'" file) (require 'ps-print)))
(org-let (if nosettings nil org-agenda-exporter-settings)
- `(save-excursion
+ '(save-excursion
(save-window-excursion
(org-agenda-mark-filtered-text)
(let ((bs (copy-sequence (buffer-string))) beg)
(org-agenda-unmark-filtered-text)
(with-temp-buffer
+ (rename-buffer "Agenda View" t)
+ (set-buffer-modified-p nil)
(insert bs)
(org-agenda-remove-marked-text 'org-filtered)
(while (setq beg (text-property-any (point-min) (point-max)
@@ -2525,6 +2536,7 @@ higher priority settings."
((org-bound-and-true-p org-mobile-creating-agendas)
(org-mobile-write-agenda-for-mobile file))
((string-match "\\.html?\\'" file)
+ (require 'htmlize)
(set-buffer (htmlize-buffer (current-buffer)))
(when (and org-agenda-export-html-style
@@ -2539,18 +2551,17 @@ higher priority settings."
(message "HTML written to %s" file))
((string-match "\\.ps\\'" file)
(require 'ps-print)
- ,(flet ((ps-get-buffer-name () "Agenda View"))
- (ps-print-buffer-with-faces file))
+ (ps-print-buffer-with-faces file)
(message "Postscript written to %s" file))
((string-match "\\.pdf\\'" file)
(require 'ps-print)
- ,(flet ((ps-get-buffer-name () "Agenda View"))
- (ps-print-buffer-with-faces
- (concat (file-name-sans-extension file) ".ps")))
+ (ps-print-buffer-with-faces
+ (concat (file-name-sans-extension file) ".ps"))
(call-process "ps2pdf" nil nil nil
(expand-file-name
(concat (file-name-sans-extension file) ".ps"))
(expand-file-name file))
+ (delete-file (concat (file-name-sans-extension file) ".ps"))
(message "PDF written to %s" file))
((string-match "\\.ics\\'" file)
(require 'org-icalendar)
@@ -2616,7 +2627,9 @@ Drawers will be excluded, also the line with scheduling/deadline info."
(setq txt (org-agenda-get-some-entry-text
m org-agenda-add-entry-text-maxlines " > "))
(end-of-line 1)
- (if (string-match "\\S-" txt) (insert "\n" txt)))))))
+ (if (string-match "\\S-" txt)
+ (insert "\n" txt)
+ (or (eobp) (forward-char 1))))))))
(defun org-agenda-get-some-entry-text (marker n-lines &optional indent
&rest keep)
@@ -3993,8 +4006,7 @@ The remainder is either a list of TODO keywords, or a state symbol
"Create agenda view for projects that are stuck.
Stuck projects are project that have no next actions. For the definitions
of what a project is and how to check if it stuck, customize the variable
-`org-stuck-projects'.
-MATCH is being ignored."
+`org-stuck-projects'."
(interactive)
(let* ((org-agenda-skip-function
'org-agenda-skip-entry-when-regexp-matches-in-subtree)
@@ -4016,11 +4028,11 @@ MATCH is being ignored."
"\\)\\>"))
(tags (nth 2 org-stuck-projects))
(tags-re (if (member "*" tags)
- (org-re "^\\*+ .*:[[:alnum:]_@]+:[ \t]*$")
+ (org-re "^\\*+ .*:[[:alnum:]_@#%]+:[ \t]*$")
(if tags
(concat "^\\*+ .*:\\("
(mapconcat 'identity tags "\\|")
- (org-re "\\):[[:alnum:]_@:]*[ \t]*$")))))
+ (org-re "\\):[[:alnum:]_@#%:]*[ \t]*$")))))
(gen-re (nth 3 org-stuck-projects))
(re-list
(delq nil
@@ -4979,7 +4991,7 @@ Any match of REMOVE-RE will be removed from TXT."
(setq h (/ m 60) m (- m (* h 60)))
(setq s2 (format "%02d:%02d" h m))))
- (when (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$")
+ (when (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")
txt)
;; Tags are in the string
(if (or (eq org-agenda-remove-tags t)
@@ -5053,7 +5065,7 @@ Any match of REMOVE-RE will be removed from TXT."
The modified list may contain inherited tags, and tags matched by
`org-agenda-hide-tags-regexp' will be removed."
(when (or add-inherited hide-re)
- (if (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$") txt)
+ (if (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") txt)
(setq txt (substring txt 0 (match-beginning 0))))
(setq tags
(delq nil
@@ -5109,7 +5121,7 @@ The modified list may contain inherited tags, and tags matched by
(throw 'exit list))
(while (setq time (pop gridtimes))
(unless (and remove (member time have))
- (setq time (int-to-string time))
+ (setq time (replace-regexp-in-string " " "0" (format "%4s" time)))
(push (org-format-agenda-item
nil string "" nil
(concat (substring time 0 -2) ":" (substring time -2)))
@@ -5228,8 +5240,8 @@ could bind the variable in the options section of a custom command.")
(if nosort
list
(when org-agenda-before-sorting-filter-function
- (setq list (mapcar org-agenda-before-sorting-filter-function list)))
- (delq nil (mapconcat 'identity (sort list 'org-entries-lessp) "\n"))))
+ (setq list (delq nil (mapcar org-agenda-before-sorting-filter-function list))))
+ (mapconcat 'identity (sort list 'org-entries-lessp) "\n")))
(defun org-agenda-highlight-todo (x)
(let ((org-done-keywords org-done-keywords-for-agenda)
@@ -6719,7 +6731,7 @@ If FORCE-TAGS is non nil, the car of it returns the new tags."
(let ((inhibit-read-only t) l c)
(save-excursion
(goto-char (if line (point-at-bol) (point-min)))
- (while (re-search-forward (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$")
+ (while (re-search-forward (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")
(if line (point-at-eol) nil) t)
(add-text-properties
(match-beginning 2) (match-end 2)
@@ -7142,9 +7154,9 @@ The cursor may be at a date in the calendar, or in the Org agenda."
(setq newhead (org-get-heading)))
(org-agenda-change-all-lines newhead hdmarker)))))
-(defun org-agenda-clock-out (&optional arg)
+(defun org-agenda-clock-out ()
"Stop the currently running clock."
- (interactive "P")
+ (interactive)
(unless (marker-buffer org-clock-marker)
(error "No running clock"))
(let ((marker (make-marker)) newhead)
@@ -7271,7 +7283,8 @@ the resulting entry will not be shown. When TEXT is empty, switch to
(let ((calendar-date-display-form
(if (if (boundp 'calendar-date-style)
(eq calendar-date-style 'european)
- (org-bound-and-true-p european-calendar-style)) ; Emacs 22
+ (with-no-warnings ;; european-calendar-style is obsolete as of version 23.1
+ (org-bound-and-true-p european-calendar-style))) ; Emacs 22
'(day " " month " " year)
'(month " " day " " year))))
diff --git a/lisp/org-archive.el b/lisp/org-archive.el
index df6c68f..629da05 100644
--- a/lisp/org-archive.el
+++ b/lisp/org-archive.el
@@ -115,7 +115,7 @@ information."
((or (re-search-backward re nil t)
(re-search-forward re nil t))
(match-string 1))
- (t org-archive-location (match-string 1)))))))
+ (t org-archive-location))))))
(defun org-add-archive-files (files)
"Splice the archive files into the list of files.
@@ -268,7 +268,7 @@ this heading."
(progn
(if (re-search-forward
(concat "^" (regexp-quote heading)
- (org-re "[ \t]*\\(:[[:alnum:]_@:]+:\\)?[ \t]*\\($\\|\r\\)"))
+ (org-re "[ \t]*\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*\\($\\|\r\\)"))
nil t)
(goto-char (match-end 0))
;; Heading not found, just insert it at the end
diff --git a/lisp/org-ascii.el b/lisp/org-ascii.el
index 803770c..9978708 100644
--- a/lisp/org-ascii.el
+++ b/lisp/org-ascii.el
@@ -311,7 +311,7 @@ publishing directory."
:add-text (plist-get opt-plist :text))
"\n"))
thetoc have-headings first-heading-pos
- table-open table-buffer link-buffer link desc desc0 rpl wrap)
+ table-open table-buffer link-buffer link type path desc desc0 rpl wrap fnc)
(let ((inhibit-read-only t))
(org-unmodified
(remove-text-properties (point-min) (point-max)
@@ -347,7 +347,7 @@ publishing directory."
(if (and (or author email)
org-export-author-info)
- (insert(concat (nth 1 lang-words) ": " (or author "")
+ (insert (concat (nth 1 lang-words) ": " (or author "")
(if (and org-export-email-info
email (string-match "\\S-" email))
(concat " <" email ">") "")
@@ -400,7 +400,7 @@ publishing directory."
(if (and (memq org-export-with-tags '(not-in-toc nil))
(string-match
- (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
+ (org-re "[ \t]+:[[:alnum:]_@#%:]+:[ \t]*$")
txt))
(setq txt (replace-match "" t t txt)))
(if (string-match quote-re0 txt)
@@ -431,10 +431,12 @@ publishing directory."
;; Remove the quoted HTML tags.
(setq line (org-html-expand-for-ascii line))
;; Replace links with the description when possible
- (while (string-match org-bracket-link-regexp line)
- (setq link (match-string 1 line)
- desc0 (match-string 3 line)
- desc (or desc0 (match-string 1 line)))
+ (while (string-match org-bracket-link-analytic-regexp++ line)
+ (setq path (match-string 3 line)
+ link (concat (match-string 1 line) path)
+ type (match-string 1 line)
+ desc0 (match-string 5 line)
+ desc (or desc0 link))
(if (and (> (length link) 8)
(equal (substring link 0 8) "coderef:"))
(setq line (replace-match
@@ -443,15 +445,18 @@ publishing directory."
(substring link 8)
org-export-code-refs)))
t t line))
- (setq rpl (concat "["
- (or (match-string 3 line) (match-string 1 line))
- "]"))
- (when (and desc0 (not (equal desc0 link)))
- (if org-export-ascii-links-to-notes
- (push (cons desc0 link) link-buffer)
- (setq rpl (concat rpl " (" link ")")
- wrap (+ (length line) (- (length (match-string 0 line)))
- (length desc)))))
+ (setq rpl (concat "[" desc "]"))
+ (if (functionp (setq fnc (nth 2 (assoc type org-link-protocols))))
+ (setq rpl (or (save-match-data
+ (funcall fnc (org-link-unescape path)
+ desc0 'ascii))
+ rpl))
+ (when (and desc0 (not (equal desc0 link)))
+ (if org-export-ascii-links-to-notes
+ (push (cons desc0 link) link-buffer)
+ (setq rpl (concat rpl " (" link ")")
+ wrap (+ (length line) (- (length (match-string 0 line)))
+ (length desc))))))
(setq line (replace-match rpl t t line))))
(when custom-times
(setq line (org-translate-time line)))
@@ -482,7 +487,8 @@ publishing directory."
(org-format-table-ascii table-buffer)
"\n") "\n")))
(t
- (if (string-match "^\\([ \t]*\\)\\([-+*][ \t]+\\)\\(.*?\\)\\( ::\\)" line)
+ (if (string-match "^\\([ \t]*\\)\\([-+*][ \t]+\\)\\(.*?\\)\\( ::\\)"
+ line)
(setq line (replace-match "\\1\\3:" t nil line)))
(setq line (org-fix-indentation line org-ascii-current-indentation))
;; Remove forced line breaks
@@ -571,9 +577,12 @@ publishing directory."
(replace-match "\\1\\2")))
;; Remove list start counters
(goto-char (point-min))
- (while (re-search-forward "\\[@start:[0-9]+\\] ?" nil t)
- (org-if-unprotected
- (replace-match ""))))
+ (while (org-search-forward-unenclosed
+ "\\[@\\(?:start:\\)?[0-9]+\\][ \t]*" nil t)
+ (replace-match ""))
+ (remove-text-properties
+ (point-min) (point-max)
+ '(face nil font-lock-fontified nil font-lock-multiline nil line-prefix nil wrap-prefix nil)))
(defun org-html-expand-for-ascii (line)
"Handle quoted HTML for ASCII export."
@@ -645,7 +654,7 @@ publishing directory."
(insert "\n"))
(setq char (nth (- umax level) (reverse org-export-ascii-underline)))
(unless org-export-with-tags
- (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
+ (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") title)
(setq title (replace-match "" t t title))))
(if org-export-with-section-numbers
(setq title (concat (org-section-number level) " " title)))
diff --git a/lisp/org-capture.el b/lisp/org-capture.el
index c0e41f3..5b917d8 100644
--- a/lisp/org-capture.el
+++ b/lisp/org-capture.el
@@ -76,6 +76,7 @@
:tag "Org Capture"
:group 'org)
+;;;###autoload
(defcustom org-capture-templates nil
"Templates for the creation of new entries.
@@ -220,7 +221,7 @@ Furthermore, the following %-escapes will be replaced with content:
Apart from these general escapes, you can access information specific to the
link type that is created. For example, calling `org-capture' in emails
or gnus will record the author and the subject of the message, which you
-can access with \"%:author\" and \"%:subject\", respectively. Here is a
+can access with \"%:from\" and \"%:subject\", respectively. Here is a
complete list of what is recorded for each link type.
Link type | Available information
@@ -382,6 +383,11 @@ bypassed."
(initial (and (org-region-active-p)
(buffer-substring (point) (mark))))
(entry (org-capture-select-template keys)))
+ (when (stringp initial)
+ (remove-text-properties 0 (length initial) '(read-only t) initial))
+ (when (stringp annotation)
+ (remove-text-properties 0 (length annotation)
+ '(read-only t) annotation))
(cond
((equal entry "C")
(customize-variable 'org-capture-templates))
@@ -589,6 +595,8 @@ already gone."
(set-buffer (org-capture-target-buffer (nth 1 target)))
(let ((hd (nth 2 target)))
(goto-char (point-min))
+ (unless (org-mode-p)
+ (error "Target buffer for file+headline should be in Org mode"))
(if (re-search-forward
(format org-complex-heading-regexp-format (regexp-quote hd))
nil t)
@@ -743,14 +751,14 @@ already gone."
(if (org-capture-get :prepend)
(progn
(goto-char beg)
- (if (re-search-forward (concat "^" (org-item-re)) end t)
+ (if (org-search-forward-unenclosed org-item-beginning-re end t)
(progn
(goto-char (match-beginning 0))
(setq ind (org-get-indentation)))
(goto-char end)
(setq ind 0)))
(goto-char end)
- (if (re-search-backward (concat "^" (org-item-re)) beg t)
+ (if (org-search-backward-unenclosed org-item-beginning-re beg t)
(progn
(setq ind (org-get-indentation))
(org-end-of-item))
@@ -972,7 +980,7 @@ Point will remain at the first line after the inserted text."
(insert template)
(org-capture-empty-lines-after)
(goto-char beg)
- (org-maybe-renumber-ordered-list)
+ (org-list-repair)
(org-end-of-item)
(setq end (point)))
(t (insert template)))
@@ -1204,12 +1212,13 @@ The template may still contain \"%?\" for cursor positioning."
'org-tags-history)))
(setq ins (mapconcat 'identity
(org-split-string
- ins (org-re "[^[:alnum:]_@]+"))
+ ins (org-re "[^[:alnum:]_@#%]+"))
":"))
(when (string-match "\\S-" ins)
(or (equal (char-before) ?:) (insert ":"))
(insert ins)
- (or (equal (char-after) ?:) (insert ":")))))
+ (or (equal (char-after) ?:) (insert ":"))
+ (and (org-on-heading-p) (org-set-tags nil 'align)))))
((equal char "C")
(cond ((= (length clipboards) 1) (insert (car clipboards)))
((> (length clipboards) 1)
diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index 4fa0397..8979396 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -35,6 +35,7 @@
(require 'cl))
(declare-function calendar-absolute-from-iso "cal-iso" (&optional date))
+(declare-function notifications-notify "notifications" (&rest params))
(defvar org-time-stamp-formats)
(defgroup org-clock nil
@@ -557,6 +558,14 @@ use libnotify if available, or fall back on a message."
((stringp org-show-notification-handler)
(start-process "emacs-timer-notification" nil
org-show-notification-handler notification))
+ ((featurep 'notifications)
+ (require 'notifications)
+ (notifications-notify
+ :title "Org-mode message"
+ :body notification
+ ;; FIXME how to link to the Org icon?
+ ;; :app-icon "~/.emacs.d/icons/mail.png"
+ :urgency 'low))
((org-program-exists "notify-send")
(start-process "emacs-timer-notification" nil
"notify-send" notification))
@@ -1863,7 +1872,7 @@ the currently selected interval size."
(when (setq time (get-text-property p :org-clock-minutes))
(save-excursion
(beginning-of-line 1)
- (when (and (looking-at (org-re "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ \t]+:[[:alnum:]_@:]+:\\)?[ \t]*$"))
+ (when (and (looking-at (org-re "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ \t]+:[[:alnum:]_@#%:]+:\\)?[ \t]*$"))
(setq level (org-reduced-level
(- (match-end 1) (match-beginning 1))))
(<= level maxlevel))
@@ -1971,10 +1980,22 @@ the currently selected interval size."
(when block
(setq cc (org-clock-special-range block nil t)
ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
- (if ts (setq ts (org-float-time
- (apply 'encode-time (org-parse-time-string ts)))))
- (if te (setq te (org-float-time
- (apply 'encode-time (org-parse-time-string te)))))
+ (cond
+ ((numberp ts)
+ ;; If ts is a number, it's an absolute day number from org-agenda.
+ (destructuring-bind (month day year) (calendar-gregorian-from-absolute ts)
+ (setq ts (org-float-time (encode-time 0 0 0 day month year)))))
+ (ts
+ (setq ts (org-float-time
+ (apply 'encode-time (org-parse-time-string ts))))))
+ (cond
+ ((numberp te)
+ ;; Likewise for te.
+ (destructuring-bind (month day year) (calendar-gregorian-from-absolute te)
+ (setq te (org-float-time (encode-time 0 0 0 day month year)))))
+ (te
+ (setq te (org-float-time
+ (apply 'encode-time (org-parse-time-string te))))))
(setq p1 (plist-put p1 :header ""))
(setq p1 (plist-put p1 :step nil))
(setq p1 (plist-put p1 :block nil))
diff --git a/lisp/org-colview-xemacs.el b/lisp/org-colview-xemacs.el
index 35e55f8..e2bf811 100644
--- a/lisp/org-colview-xemacs.el
+++ b/lisp/org-colview-xemacs.el
@@ -685,7 +685,7 @@ Where possible, use the standard interface for changing this line."
(txt (match-string 3))
(post "")
txt2)
- (if (string-match (org-re "[ \t]+:[[:alnum:]:_@]+:[ \t]*$") txt)
+ (if (string-match (org-re "[ \t]+:[[:alnum:]:_@#%]+:[ \t]*$") txt)
(setq post (match-string 0 txt)
txt (substring txt 0 (match-beginning 0))))
(setq txt2 (read-string "Edit: " txt))
diff --git a/lisp/org-colview.el b/lisp/org-colview.el
index dc0ab04..5303e71 100644
--- a/lisp/org-colview.el
+++ b/lisp/org-colview.el
@@ -519,7 +519,7 @@ Where possible, use the standard interface for changing this line."
(txt (match-string 3))
(post "")
txt2)
- (if (string-match (org-re "[ \t]+:[[:alnum:]:_@]+:[ \t]*$") txt)
+ (if (string-match (org-re "[ \t]+:[[:alnum:]:_@#%]+:[ \t]*$") txt)
(setq post (match-string 0 txt)
txt (substring txt 0 (match-beginning 0))))
(setq txt2 (read-string "Edit: " txt))
diff --git a/lisp/org-compat.el b/lisp/org-compat.el
index 4fde94c..4383bec 100644
--- a/lisp/org-compat.el
+++ b/lisp/org-compat.el
@@ -353,7 +353,7 @@ TIME defaults to the current time."
(if (fboundp 'looking-at-p)
(apply 'looking-at-p args)
(save-match-data
- (apply 'looking-at-p args))))
+ (apply 'looking-at args))))
; XEmacs does not have `looking-back'.
(if (fboundp 'looking-back)
diff --git a/lisp/org-docbook.el b/lisp/org-docbook.el
index 7bb7565..d4668cb 100644
--- a/lisp/org-docbook.el
+++ b/lisp/org-docbook.el
@@ -552,9 +552,9 @@ publishing directory."
(nth 2 (assoc "=" org-export-docbook-emphasis-alist)))
table-open type
table-buffer table-orig-buffer
- ind item-type starter didclose
+ ind item-type starter
rpl path attr caption label desc descp desc1 desc2 link
- fnc item-tag initial-number
+ fnc item-tag item-number
footref-seen footnote-list
id-file
)
@@ -671,7 +671,21 @@ publishing directory."
(org-export-docbook-open-para))
(throw 'nextline nil))
- (org-export-docbook-close-lists-maybe line)
+ ;; List ender: close every open list.
+ (when (equal "ORG-LIST-END" line)
+ (while local-list-type
+ (let ((listtype (car local-list-type)))
+ (org-export-docbook-close-li listtype)
+ (insert (cond
+ ((equal listtype "o") "</orderedlist>\n")
+ ((equal listtype "u") "</itemizedlist>\n")
+ ((equal listtype "d") "</variablelist>\n"))))
+ (pop local-list-type))
+ ;; We did close a list, normal text follows: need <para>
+ (org-export-docbook-open-para)
+ (setq local-list-indent nil
+ in-local-list nil)
+ (throw 'nextline nil))
;; Protected HTML
(when (get-text-property 0 'org-protected line)
@@ -963,18 +977,6 @@ publishing directory."
txt (match-string 2 line))
(if (string-match quote-re0 txt)
(setq txt (replace-match "" t t txt)))
- (when in-local-list
- ;; Close any local lists before inserting a new header line
- (while local-list-type
- (let ((listtype (car local-list-type)))
- (org-export-docbook-close-li listtype)
- (insert (cond
- ((equal listtype "o") "</orderedlist>\n")
- ((equal listtype "u") "</itemizedlist>\n")
- ((equal listtype "d") "</variablelist>\n"))))
- (pop local-list-type))
- (setq local-list-indent nil
- in-local-list nil))
(org-export-docbook-level-start level txt)
;; QUOTES
(when (string-match quote-re line)
@@ -1004,6 +1006,7 @@ publishing directory."
(org-export-docbook-close-para-maybe)
(insert (org-export-docbook-finalize-table
(org-format-table-html table-buffer table-orig-buffer)))))
+
(t
;; Normal lines
(when (string-match
@@ -1020,34 +1023,14 @@ publishing directory."
(substring (match-string 2 line) 0 -1))
line (substring line (match-beginning 5))
item-tag nil
- initial-number nil)
- (if (string-match "\\`\\[@start:\\([0-9]+\\)\\][ \t]?" line)
- (setq initial-number (match-string 1 line)
+ item-number nil)
+ (if (string-match "\\[@\\(?:start:\\)?\\([0-9]+\\)\\][ \t]?" line)
+ (setq item-number (match-string 1 line)
line (replace-match "" t t line)))
(if (and starter (string-match "\\(.*?\\) ::[ \t]*" line))
(setq item-type "d"
item-tag (match-string 1 line)
line (substring line (match-end 0))))
- (when (and (not (equal item-type "d"))
- (not (string-match "[^ \t]" line)))
- ;; Empty line. Pretend indentation is large.
- (setq ind (if org-empty-line-terminates-plain-lists
- 0
- (1+ (or (car local-list-indent) 1)))))
- (setq didclose nil)
- (while (and in-local-list
- (or (and (= ind (car local-list-indent))
- (not starter))
- (< ind (car local-list-indent))))
- (setq didclose t)
- (let ((listtype (car local-list-type)))
- (org-export-docbook-close-li listtype)
- (insert (cond
- ((equal listtype "o") "</orderedlist>\n")
- ((equal listtype "u") "</itemizedlist>\n")
- ((equal listtype "d") "</variablelist>\n"))))
- (pop local-list-type) (pop local-list-indent)
- (setq in-local-list local-list-indent))
(cond
((and starter
(or (not in-local-list)
@@ -1056,7 +1039,7 @@ publishing directory."
(org-export-docbook-close-para-maybe)
(insert (cond
((equal item-type "u") "<itemizedlist>\n<listitem>\n")
- ((equal item-type "o")
+ ((and (equal item-type "o") item-number)
;; Check for a specific start number. If it
;; is specified, we use the ``override''
;; attribute of element <listitem> to pass the
@@ -1064,10 +1047,8 @@ publishing directory."
;; ``startingnumber'' attribute of element
;; <orderedlist>, but the former works on both
;; DocBook 5.0 and prior versions.
- (if initial-number
- (format "<orderedlist>\n<listitem override=\"%s\">\n"
- initial-number)
- "<orderedlist>\n<listitem>\n"))
+ (format "<orderedlist>\n<listitem override=\"%s\">\n" item-number))
+ ((equal item-type "o") "<orderedlist>\n<listitem>\n")
((equal item-type "d")
(format "<variablelist>\n<varlistentry><term>%s</term><listitem>\n" item-tag))))
;; For DocBook, we need to open a para right after tag
@@ -1076,11 +1057,27 @@ publishing directory."
(push item-type local-list-type)
(push ind local-list-indent)
(setq in-local-list t))
- (starter
;; Continue current list
+ (starter
+ ;; terminate any previous sublist but first ensure
+ ;; list is not ill-formed
+ (let ((min-ind (apply 'min local-list-indent)))
+ (when (< ind min-ind) (setq ind min-ind)))
+ (while (< ind (car local-list-indent))
+ (let ((listtype (car local-list-type)))
+ (org-export-docbook-close-li listtype)
+ (insert (cond
+ ((equal listtype "o") "</orderedlist>\n")
+ ((equal listtype "u") "</itemizedlist>\n")
+ ((equal listtype "d") "</variablelist>\n"))))
+ (pop local-list-type) (pop local-list-indent)
+ (setq in-local-list local-list-indent))
+ ;; insert new item
(let ((listtype (car local-list-type)))
(org-export-docbook-close-li listtype)
(insert (cond
+ ((and (equal listtype "o") item-number)
+ (format "<listitem override=\"%s\">" item-number))
((equal listtype "o") "<listitem>")
((equal listtype "u") "<listitem>")
((equal listtype "d") (format
@@ -1089,9 +1086,6 @@ publishing directory."
"???"))))))
;; For DocBook, we need to open a para right after tag
;; <listitem>.
- (org-export-docbook-open-para))
- (didclose
- ;; We did close a list, normal text follows: need <para>
(org-export-docbook-open-para)))
;; Checkboxes.
(if (string-match "^[ \t]*\\(\\[[X -]\\]\\)" line)
@@ -1134,18 +1128,7 @@ publishing directory."
(when inquote
(insert "]]></programlisting>\n")
(org-export-docbook-open-para))
- (when in-local-list
- ;; Close any local lists before inserting a new header line
- (while local-list-type
- (let ((listtype (car local-list-type)))
- (org-export-docbook-close-li listtype)
- (insert (cond
- ((equal listtype "o") "</orderedlist>\n")
- ((equal listtype "u") "</itemizedlist>\n")
- ((equal listtype "d") "</variablelist>\n"))))
- (pop local-list-type))
- (setq local-list-indent nil
- in-local-list nil))
+
;; Close all open sections.
(org-export-docbook-level-start 1 nil)
@@ -1212,24 +1195,6 @@ publishing directory."
(defvar in-local-list)
(defvar local-list-indent)
(defvar local-list-type)
-(defun org-export-docbook-close-lists-maybe (line)
- (let ((ind (or (get-text-property 0 'original-indentation line)))
-; (and (string-match "\\S-" line)
-; (org-get-indentation line))))
- didclose)
- (when ind
- (while (and in-local-list
- (<= ind (car local-list-indent)))
- (setq didclose t)
- (let ((listtype (car local-list-type)))
- (org-export-docbook-close-li listtype)
- (insert (cond
- ((equal listtype "o") "</orderedlist>\n")
- ((equal listtype "u") "</itemizedlist>\n")
- ((equal listtype "d") "</variablelist>\n"))))
- (pop local-list-type) (pop local-list-indent)
- (setq in-local-list local-list-indent))
- (and didclose (org-export-docbook-open-para)))))
(defun org-export-docbook-level-start (level title)
"Insert a new level in DocBook export.
@@ -1249,7 +1214,7 @@ When TITLE is nil, just close all open levels."
;; all levels, so the rest is done only if title is given.
;;
;; Format tags: put them into a superscript like format.
- (when (string-match (org-re "\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
+ (when (string-match (org-re "\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") title)
(setq title
(replace-match
(if org-export-with-tags
@@ -1273,7 +1238,7 @@ When TITLE is nil, just close all open levels."
Applies all active conversions. If there are links in the
string, don't modify these."
(let* ((re (concat org-bracket-link-regexp "\\|"
- (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$")))
+ (org-re "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")))
m s l res)
(while (setq m (string-match re string))
(setq s (substring string 0 m)
diff --git a/lisp/org-docview.el b/lisp/org-docview.el
index f1e465e..360c1fe 100644
--- a/lisp/org-docview.el
+++ b/lisp/org-docview.el
@@ -46,8 +46,11 @@
(require 'org)
-(declare-function doc-view-goto-page "doc-view" (page))
-(declare-function doc-view-current-page "doc-view" (&optional win))
+(declare-function doc-view-goto-page "ext:doc-view" (page))
+(declare-function image-mode-window-get "ext:image-mode"
+ (prop &optional winprops))
+
+(autoload 'doc-view-goto-page "doc-view")
(org-add-link-type "docview" 'org-docview-open)
(add-hook 'org-store-link-functions 'org-docview-store-link)
@@ -66,7 +69,7 @@
(when (eq major-mode 'doc-view-mode)
;; This buffer is in doc-view-mode
(let* ((path buffer-file-name)
- (page (doc-view-current-page))
+ (page (image-mode-window-get 'page))
(link (concat "docview:" path "::" (number-to-string page)))
(description ""))
(org-store-link-props
diff --git a/lisp/org-exp-blocks.el b/lisp/org-exp-blocks.el
index b9c6fc1..430d7d5 100644
--- a/lisp/org-exp-blocks.el
+++ b/lisp/org-exp-blocks.el
@@ -201,7 +201,8 @@ which defaults to the value of `org-export-blocks-witheld'."
(interblock start (point-max))
(run-hooks 'org-export-blocks-postblock-hook)))))
-(add-hook 'org-export-preprocess-hook 'org-export-blocks-preprocess)
+(add-hook 'org-export-preprocess-after-include-files-hook
+ 'org-export-blocks-preprocess)
;;================================================================================
;; type specific functions
diff --git a/lisp/org-exp.el b/lisp/org-exp.el
index 1f6ebf2..28157a8 100644
--- a/lisp/org-exp.el
+++ b/lisp/org-exp.el
@@ -695,6 +695,7 @@ modified) list.")
"EXPORT_SELECT_TAGS" "EXPORT_EXCLUDE_TAGS"
"KEYWORDS" "DESCRIPTION" "MACRO" "BIND" "XSLT")
(mapcar 'car org-export-inbuffer-options-extra))))
+ (case-fold-search t)
p key val text options mathjax a pr style
latex-header latex-class macros letbind
ext-setup-or-nil setup-contents (start 0))
@@ -1076,6 +1077,9 @@ on this string to produce the exported version."
(plist-get parameters :exclude-tags))
(run-hooks 'org-export-preprocess-after-tree-selection-hook)
+ ;; Mark end of lists
+ (org-export-mark-list-ending backend)
+
;; Handle source code snippets
(org-export-replace-src-segments-and-examples backend)
@@ -1626,6 +1630,31 @@ These special cookies will later be interpreted by the backend."
(delete-region beg end)
(insert (org-add-props content nil 'original-indentation ind))))))
+(defun org-export-mark-list-ending (backend)
+ "Mark list endings with special cookies.
+These special cookies will later be interpreted by the backend.
+`org-list-end-re' is replaced by a blank line in the process."
+ (let ((process-buffer
+ (lambda (end-list-marker)
+ (goto-char (point-min))
+ (while (org-search-forward-unenclosed org-item-beginning-re nil t)
+ (goto-char (org-list-bottom-point))
+ (when (and (not (eq org-list-ending-method 'indent))
+ (looking-at (org-list-end-re)))
+ (replace-match "\n"))
+ (insert end-list-marker)))))
+ ;; We need to divide backends into 3 categories.
+ (cond
+ ;; 1. Backends using `org-list-parse-list' do not need markers.
+ ((memq backend '(latex))
+ nil)
+ ;; 2. Line-processing backends need to be told where lists end.
+ ((memq backend '(html docbook))
+ (funcall process-buffer "ORG-LIST-END\n"))
+ ;; 3. Others backends do not need to know this: clean list enders.
+ (t
+ (funcall process-buffer "")))))
+
(defun org-export-attach-captions-and-attributes (backend target-alist)
"Move #+CAPTION, #+ATTR_BACKEND, and #+LABEL text into text properties.
If the next thing following is a table, add the text properties to the first
@@ -1838,7 +1867,9 @@ can work correctly."
(if (and (not (= (char-after (match-beginning 3))
(char-after (match-beginning 4))))
(save-excursion (goto-char (match-beginning 0))
- (save-match-data (not (org-at-table-p)))))
+ (save-match-data
+ (and (not (org-at-table-p))
+ (not (org-at-heading-p))))))
(org-if-unprotected
(subst-char-in-region (match-beginning 0) (match-end 0)
?\n ?\ t)
@@ -2794,7 +2825,7 @@ If yes remove the column and the special lines."
(defun org-export-cleanup-toc-line (s)
"Remove tags and timestamps from lines going into the toc."
(when (memq org-export-with-tags '(not-in-toc nil))
- (if (string-match (org-re " +:[[:alnum:]_@:]+: *$") s)
+ (if (string-match (org-re " +:[[:alnum:]_@#%:]+: *$") s)
(setq s (replace-match "" t t s))))
(when org-export-remove-timestamps-from-toc
(while (string-match org-maybe-keyword-time-regexp s)
diff --git a/lisp/org-feed.el b/lisp/org-feed.el
index 073d344..e06dac5 100644
--- a/lisp/org-feed.el
+++ b/lisp/org-feed.el
@@ -99,11 +99,11 @@
(declare-function xml-get-children "xml" (node child-name))
(declare-function xml-get-attribute "xml" (node attribute))
(declare-function xml-get-attribute-or-nil "xml" (node attribute))
-(defvar xml-entity-alist)
+(declare-function xml-substitute-special "xml" (string))
(defgroup org-feed nil
"Options concerning RSS feeds as inputs for Org files."
- :tag "Org ID"
+ :tag "Org Feed"
:group 'org)
(defcustom org-feed-alist nil
@@ -269,17 +269,6 @@ have been saved."
(defvar org-feed-buffer "*Org feed*"
"The buffer used to retrieve a feed.")
-(defun org-feed-unescape (s)
- "Unescape protected entities in S."
- (require 'xml)
- (let ((re (concat "&\\("
- (mapconcat 'car xml-entity-alist "\\|")
- "\\);")))
- (while (string-match re s)
- (setq s (replace-match
- (cdr (assoc (match-string 1 s) xml-entity-alist)) nil nil s)))
- s))
-
;;;###autoload
(defun org-feed-update-all ()
"Get inbox items from all feeds in `org-feed-alist'."
@@ -553,7 +542,8 @@ If that property is already present, nothing changes."
(setq tmp (org-feed-make-indented-block
tmp (org-get-indentation))))))
(replace-match tmp t t))))
- (buffer-string)))))
+ (decode-coding-string
+ (buffer-string) (detect-coding-region (point-min) (point-max) t))))))
(defun org-feed-make-indented-block (s n)
"Add indentation of N spaces to a multiline string S."
@@ -613,6 +603,7 @@ containing the properties `:guid' and `:item-full-text'."
(defun org-feed-parse-rss-entry (entry)
"Parse the `:item-full-text' field for xml tags and create new properties."
+ (require 'xml)
(with-temp-buffer
(insert (plist-get entry :item-full-text))
(goto-char (point-min))
@@ -620,7 +611,7 @@ containing the properties `:guid' and `:item-full-text'."
nil t)
(setq entry (plist-put entry
(intern (concat ":" (match-string 1)))
- (org-feed-unescape (match-string 2)))))
+ (xml-substitute-special (match-string 2)))))
(goto-char (point-min))
(unless (re-search-forward "isPermaLink[ \t]*=[ \t]*\"false\"" nil t)
(setq entry (plist-put entry :guid-permalink t))))
@@ -654,7 +645,7 @@ formatted as a string, not the original XML data."
'href)))
;; Add <title/> as :title.
(setq entry (plist-put entry :title
- (org-feed-unescape
+ (xml-substitute-special
(car (xml-node-children
(car (xml-get-children xml 'title)))))))
(let* ((content (car (xml-get-children xml 'content)))
@@ -664,12 +655,12 @@ formatted as a string, not the original XML data."
((string= type "text")
;; We like plain text.
(setq entry (plist-put entry :description
- (org-feed-unescape
+ (xml-substitute-special
(car (xml-node-children content))))))
((string= type "html")
;; TODO: convert HTML to Org markup.
(setq entry (plist-put entry :description
- (org-feed-unescape
+ (xml-substitute-special
(car (xml-node-children content))))))
((string= type "xhtml")
;; TODO: convert XHTML to Org markup.
diff --git a/lisp/org-gnus.el b/lisp/org-gnus.el
index 10a0426..0206188 100644
--- a/lisp/org-gnus.el
+++ b/lisp/org-gnus.el
@@ -39,6 +39,7 @@
;; Declare external functions and variables
(declare-function message-fetch-field "message" (header &optional not-all))
(declare-function message-narrow-to-head-1 "message" nil)
+(declare-function nnimap-group-overview-filename "nnimap" (group server))
;; The following line suppresses a compiler warning stemming from gnus-sum.el
(declare-function gnus-summary-last-subject "gnus-sum" nil)
;; Customization variables
@@ -54,12 +55,40 @@ negates this setting for the duration of the command."
:group 'org-link-store
:type 'boolean)
+(defcustom org-gnus-nnimap-query-article-no-from-file t
+ "If non-nil, `org-gnus-follow-link' will try to translate
+Message-Ids to article numbers by querying the .overview file.
+Normally, this translation is done by querying the IMAP server,
+which is usually very fast. Unfortunately, some (maybe badly
+configured) IMAP servers don't support this operation quickly.
+So if following a link to a Gnus article takes ages, try setting
+this variable to `t'."
+ :group 'org-link-store
+ :type 'boolean)
+
+
;; Install the link type
(org-add-link-type "gnus" 'org-gnus-open)
(add-hook 'org-store-link-functions 'org-gnus-store-link)
;; Implementation
+(defun org-gnus-nnimap-cached-article-number (group server message-id)
+ "Return cached article number (uid) of message in GROUP on SERVER.
+MESSAGE-ID is the message-id header field that identifies the
+message. If the uid is not cached, return nil."
+ (with-temp-buffer
+ (let ((nov (nnimap-group-overview-filename group server)))
+ (when (file-exists-p nov)
+ (mm-insert-file-contents nov)
+ (set-buffer-modified-p nil)
+ (goto-char (point-min))
+ (catch 'found
+ (while (search-forward message-id nil t)
+ (let ((hdr (split-string (thing-at-point 'line) "\t")))
+ (if (string= (nth 4 hdr) message-id)
+ (throw 'found (nth 0 hdr))))))))))
+
(defun org-gnus-group-link (group)
"Create a link to the Gnus group GROUP.
If GROUP is a newsgroup and `org-gnus-prefer-web-links' is
@@ -171,7 +200,9 @@ If `org-store-link' was called with a prefix arg the meaning of
(cond ((and group article)
(gnus-activate-group group t)
(condition-case nil
- (let ((backend (car (gnus-find-method-for-group group))))
+ (let* ((method (gnus-find-method-for-group group))
+ (backend (car method))
+ (server (cadr method)))
(cond
((eq backend 'nndoc)
(if (gnus-group-read-group t nil group)
@@ -181,6 +212,12 @@ If `org-store-link' was called with a prefix arg the meaning of
(t
(let ((articles 1)
group-opened)
+ (when (and (eq backend 'nnimap)
+ org-gnus-nnimap-query-article-no-from-file)
+ (setq article
+ (or (org-gnus-nnimap-cached-article-number
+ (nth 1 (split-string group ":"))
+ server (concat "<" article ">")) article)))
(while (and (not group-opened)
;; stop on integer overflows
(> articles 0))
diff --git a/lisp/org-habit.el b/lisp/org-habit.el
index 2fa352f..f44d0fa 100644
--- a/lisp/org-habit.el
+++ b/lisp/org-habit.el
@@ -149,15 +149,17 @@ This list represents a \"habit\" for the rest of this module."
(assert (org-is-habit-p (point)))
(let* ((scheduled (org-get-scheduled-time (point)))
(scheduled-repeat (org-get-repeat org-scheduled-string))
- (sr-days (org-habit-duration-to-days scheduled-repeat))
(end (org-entry-end-position))
- (habit-entry (org-no-properties (nth 5 (org-heading-components))))
- closed-dates deadline dr-days)
+ (habit-entry (org-no-properties (nth 4 (org-heading-components))))
+ closed-dates deadline dr-days sr-days)
(if scheduled
(setq scheduled (time-to-days scheduled))
(error "Habit %s has no scheduled date" habit-entry))
(unless scheduled-repeat
- (error "Habit %s has no scheduled repeat period" habit-entry))
+ (error
+ "Habit '%s' has no scheduled repeat period or has an incorrect one"
+ habit-entry))
+ (setq sr-days (org-habit-duration-to-days scheduled-repeat))
(unless (> sr-days 0)
(error "Habit %s scheduled repeat period is less than 1d" habit-entry))
(when (string-match "/\\([0-9]+[dwmy]\\)" scheduled-repeat)
diff --git a/lisp/org-html.el b/lisp/org-html.el
index 450a9de..1a96fa1 100644
--- a/lisp/org-html.el
+++ b/lisp/org-html.el
@@ -674,7 +674,7 @@ See variable `org-export-html-link-org-files-as-html'"
(string-match "\\.org$" path)
(progn
(list
- "http"
+ "file"
(concat
(substring path 0 (match-beginning 0))
"."
@@ -720,7 +720,7 @@ MAY-INLINE-P allows inlining it as an image."
;;Substitute just if original path was absolute.
;;(Otherwise path must remain relative)
(if (file-name-absolute-p path)
- (expand-file-name path)
+ (concat "file://" (expand-file-name path))
path)))
((string= type "")
(list nil path))
@@ -756,8 +756,7 @@ MAY-INLINE-P allows inlining it as an image."
(setq thefile
(let
((str (org-export-html-format-href thefile)))
- (if (and type (not (string= "file" type))
- (org-string-match-p "^//" str))
+ (if (and type (not (string= "file" type)))
(concat type ":" str)
str)))
@@ -890,8 +889,8 @@ PUB-DIR is set, use this as the publishing directory."
(string-match "\\S-" (plist-get opt-plist :link-up))
(plist-get opt-plist :link-up)))
(link-home (and (plist-get opt-plist :link-home)
- (string-match "\\S-" (plist-get opt-plist :link-home))
- (plist-get opt-plist :link-home)))
+ (string-match "\\S-" (plist-get opt-plist :link-home))
+ (plist-get opt-plist :link-home)))
(dummy (setq opt-plist (plist-put opt-plist :title title)))
(html-table-tag (plist-get opt-plist :html-table-tag))
(quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
@@ -960,9 +959,9 @@ PUB-DIR is set, use this as the publishing directory."
""))
table-open type
table-buffer table-orig-buffer
- ind item-type starter didclose
+ ind item-type starter
rpl path attr desc descp desc1 desc2 link
- snumber fnc item-tag initial-number
+ snumber fnc item-tag item-number
footnotes footref-seen
id-file href
)
@@ -1072,73 +1071,73 @@ lang=\"%s\" xml:lang=\"%s\">
(push "<ul>\n<li>" thetoc)
(setq lines
(mapcar '(lambda (line)
- (if (and (string-match org-todo-line-regexp line)
- (not (get-text-property 0 'org-protected line)))
- ;; This is a headline
- (progn
- (setq have-headings t)
- (setq level (- (match-end 1) (match-beginning 1)
- level-offset)
- level (org-tr-level level)
- txt (save-match-data
- (org-html-expand
- (org-export-cleanup-toc-line
- (match-string 3 line))))
- todo
- (or (and org-export-mark-todo-in-toc
- (match-beginning 2)
- (not (member (match-string 2 line)
- org-done-keywords)))
+ (if (and (string-match org-todo-line-regexp line)
+ (not (get-text-property 0 'org-protected line)))
+ ;; This is a headline
+ (progn
+ (setq have-headings t)
+ (setq level (- (match-end 1) (match-beginning 1)
+ level-offset)
+ level (org-tr-level level)
+ txt (save-match-data
+ (org-html-expand
+ (org-export-cleanup-toc-line
+ (match-string 3 line))))
+ todo
+ (or (and org-export-mark-todo-in-toc
+ (match-beginning 2)
+ (not (member (match-string 2 line)
+ org-done-keywords)))
; TODO, not DONE
- (and org-export-mark-todo-in-toc
- (= level umax-toc)
- (org-search-todo-below
- line lines level))))
- (if (string-match
- (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") txt)
- (setq txt (replace-match "&nbsp;&nbsp;&nbsp;<span class=\"tag\"> \\1</span>" t nil txt)))
- (if (string-match quote-re0 txt)
- (setq txt (replace-match "" t t txt)))
- (setq snumber (org-section-number level))
- (if org-export-with-section-numbers
- (setq txt (concat snumber " " txt)))
- (if (<= level (max umax umax-toc))
- (setq head-count (+ head-count 1)))
- (if (<= level umax-toc)
- (progn
- (if (> level org-last-level)
- (progn
- (setq cnt (- level org-last-level))
- (while (>= (setq cnt (1- cnt)) 0)
- (push "\n<ul>\n<li>" thetoc))
- (push "\n" thetoc)))
- (if (< level org-last-level)
- (progn
- (setq cnt (- org-last-level level))
- (while (>= (setq cnt (1- cnt)) 0)
- (push "</li>\n</ul>" thetoc))
- (push "\n" thetoc)))
- ;; Check for targets
- (while (string-match org-any-target-regexp line)
- (setq line (replace-match
- (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
- t t line)))
- (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
- (setq txt (replace-match "" t t txt)))
- (setq href
- (replace-regexp-in-string
- "\\." "_" (format "sec-%s" snumber)))
- (setq href (or (cdr (assoc href org-export-preferred-target-alist)) href))
- (push
- (format
- (if todo
- "</li>\n<li><a href=\"#%s\"><span class=\"todo\">%s</span></a>"
- "</li>\n<li><a href=\"#%s\">%s</a>")
- href txt) thetoc)
-
- (setq org-last-level level))
- )))
- line)
+ (and org-export-mark-todo-in-toc
+ (= level umax-toc)
+ (org-search-todo-below
+ line lines level))))
+ (if (string-match
+ (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") txt)
+ (setq txt (replace-match "&nbsp;&nbsp;&nbsp;<span class=\"tag\"> \\1</span>" t nil txt)))
+ (if (string-match quote-re0 txt)
+ (setq txt (replace-match "" t t txt)))
+ (setq snumber (org-section-number level))
+ (if org-export-with-section-numbers
+ (setq txt (concat snumber " " txt)))
+ (if (<= level (max umax umax-toc))
+ (setq head-count (+ head-count 1)))
+ (if (<= level umax-toc)
+ (progn
+ (if (> level org-last-level)
+ (progn
+ (setq cnt (- level org-last-level))
+ (while (>= (setq cnt (1- cnt)) 0)
+ (push "\n<ul>\n<li>" thetoc))
+ (push "\n" thetoc)))
+ (if (< level org-last-level)
+ (progn
+ (setq cnt (- org-last-level level))
+ (while (>= (setq cnt (1- cnt)) 0)
+ (push "</li>\n</ul>" thetoc))
+ (push "\n" thetoc)))
+ ;; Check for targets
+ (while (string-match org-any-target-regexp line)
+ (setq line (replace-match
+ (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
+ t t line)))
+ (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
+ (setq txt (replace-match "" t t txt)))
+ (setq href
+ (replace-regexp-in-string
+ "\\." "_" (format "sec-%s" snumber)))
+ (setq href (or (cdr (assoc href org-export-preferred-target-alist)) href))
+ (push
+ (format
+ (if todo
+ "</li>\n<li><a href=\"#%s\"><span class=\"todo\">%s</span></a>"
+ "</li>\n<li><a href=\"#%s\">%s</a>")
+ href txt) thetoc)
+
+ (setq org-last-level level))
+ )))
+ line)
lines))
(while (> org-last-level (1- org-min-level))
(setq org-last-level (1- org-last-level))
@@ -1181,7 +1180,16 @@ lang=\"%s\" xml:lang=\"%s\">
(org-open-par))
(throw 'nextline nil))
- (org-export-html-close-lists-maybe line)
+ ;; Explicit list closure
+ (when (equal "ORG-LIST-END" line)
+ (while local-list-indent
+ (org-close-li (car local-list-type))
+ (insert (format "</%sl>\n" (car local-list-type)))
+ (pop local-list-type)
+ (pop local-list-indent))
+ (setq in-local-list nil)
+ (org-open-par)
+ (throw 'nextline nil))
;; Protected HTML
(when (get-text-property 0 'org-protected line)
@@ -1300,79 +1308,79 @@ lang=\"%s\" xml:lang=\"%s\">
desc2 (if (match-end 2) (concat type ":" path) path)
descp (and desc1 (not (equal desc1 desc2)))
desc (or desc1 desc2))
- ;; Make an image out of the description if that is so wanted
+ ;; Make an image out of the description if that is so wanted
(when (and descp (org-file-image-p
- desc org-export-html-inline-image-extensions))
- (save-match-data
- (if (string-match "^file:" desc)
- (setq desc (substring desc (match-end 0)))))
- (setq desc (org-add-props
+ desc org-export-html-inline-image-extensions))
+ (save-match-data
+ (if (string-match "^file:" desc)
+ (setq desc (substring desc (match-end 0)))))
+ (setq desc (org-add-props
(concat "<img src=\"" desc "\"/>")
'(org-protected t))))
(cond
((equal type "internal")
- (let
- ((frag-0
- (if (= (string-to-char path) ?#)
- (substring path 1)
- path)))
- (setq rpl
+ (let
+ ((frag-0
+ (if (= (string-to-char path) ?#)
+ (substring path 1)
+ path)))
+ (setq rpl
(org-html-make-link
- opt-plist
- ""
- ""
- (org-solidify-link-text
- (save-match-data (org-link-unescape frag-0))
- nil)
- desc attr nil))))
+ opt-plist
+ ""
+ ""
+ (org-solidify-link-text
+ (save-match-data (org-link-unescape frag-0))
+ nil)
+ desc attr nil))))
((and (equal type "id")
(setq id-file (org-id-find-id-file path)))
;; This is an id: link to another file (if it was the same file,
;; it would have become an internal link...)
(save-match-data
(setq id-file (file-relative-name
- id-file
- (file-name-directory org-current-export-file)))
+ id-file
+ (file-name-directory org-current-export-file)))
(setq rpl
- (org-html-make-link opt-plist
- "file" id-file
- (concat (if (org-uuidgen-p path) "ID-") path)
- desc
- attr
- nil))))
+ (org-html-make-link opt-plist
+ "file" id-file
+ (concat (if (org-uuidgen-p path) "ID-") path)
+ desc
+ attr
+ nil))))
((member type '("http" "https"))
- ;; standard URL, can inline as image
- (setq rpl
- (org-html-make-link opt-plist
- type path nil
- desc
- attr
- (org-html-should-inline-p path descp))))
+ ;; standard URL, can inline as image
+ (setq rpl
+ (org-html-make-link opt-plist
+ type path nil
+ desc
+ attr
+ (org-html-should-inline-p path descp))))
((member type '("ftp" "mailto" "news"))
- ;; standard URL, can't inline as image
- (setq rpl
- (org-html-make-link opt-plist
- type path nil
- desc
- attr
- nil)))
+ ;; standard URL, can't inline as image
+ (setq rpl
+ (org-html-make-link opt-plist
+ type path nil
+ desc
+ attr
+ nil)))
((string= type "coderef")
- (let*
- ((coderef-str (format "coderef-%s" path))
- (attr-1
- (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, '%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\""
+ (let*
+ ((coderef-str (format "coderef-%s" path))
+ (attr-1
+ (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, '%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\""
coderef-str coderef-str)))
- (setq rpl
+ (setq rpl
(org-html-make-link opt-plist
- type "" coderef-str
- (format
- (org-export-get-coderef-format
- path
- (and descp desc))
- (cdr (assoc path org-export-code-refs)))
- attr-1
- nil))))
+ type "" coderef-str
+ (format
+ (org-export-get-coderef-format
+ path
+ (and descp desc))
+ (cdr (assoc path org-export-code-refs)))
+ attr-1
+ nil))))
((functionp (setq fnc (nth 2 (assoc type org-link-protocols))))
;; The link protocol has a function for format the link
@@ -1381,55 +1389,55 @@ lang=\"%s\" xml:lang=\"%s\">
(funcall fnc (org-link-unescape path) desc1 'html))))
((string= type "file")
- ;; FILE link
- (save-match-data
- (let*
- ((components
- (if
- (string-match "::\\(.*\\)" path)
- (list
- (replace-match "" t nil path)
- (match-string 1 path))
- (list path nil)))
-
- ;;The proper path, without a fragment
- (path-1
- (first components))
-
- ;;The raw fragment
- (fragment-0
- (second components))
-
- ;;Check the fragment. If it can't be used as
- ;;target fragment we'll pass nil instead.
- (fragment-1
- (if
- (and fragment-0
- (not (string-match "^[0-9]*$" fragment-0))
- (not (string-match "^\\*" fragment-0))
- (not (string-match "^/.*/$" fragment-0)))
- (org-solidify-link-text
- (org-link-unescape fragment-0))
- nil))
- (desc-2
- ;;Description minus "file:" and ".org"
- (if (string-match "^file:" desc)
- (let
- ((desc-1 (replace-match "" t t desc)))
- (if (string-match "\\.org$" desc-1)
- (replace-match "" t t desc-1)
- desc-1))
- desc)))
-
- (setq rpl
- (if
+ ;; FILE link
+ (save-match-data
+ (let*
+ ((components
+ (if
+ (string-match "::\\(.*\\)" path)
+ (list
+ (replace-match "" t nil path)
+ (match-string 1 path))
+ (list path nil)))
+
+ ;;The proper path, without a fragment
+ (path-1
+ (first components))
+
+ ;;The raw fragment
+ (fragment-0
+ (second components))
+
+ ;;Check the fragment. If it can't be used as
+ ;;target fragment we'll pass nil instead.
+ (fragment-1
+ (if
+ (and fragment-0
+ (not (string-match "^[0-9]*$" fragment-0))
+ (not (string-match "^\\*" fragment-0))
+ (not (string-match "^/.*/$" fragment-0)))
+ (org-solidify-link-text
+ (org-link-unescape fragment-0))
+ nil))
+ (desc-2
+ ;;Description minus "file:" and ".org"
+ (if (string-match "^file:" desc)
+ (let
+ ((desc-1 (replace-match "" t t desc)))
+ (if (string-match "\\.org$" desc-1)
+ (replace-match "" t t desc-1)
+ desc-1))
+ desc)))
+
+ (setq rpl
+ (if
(and
- (functionp link-validate)
- (not (funcall link-validate path-1 current-dir)))
+ (functionp link-validate)
+ (not (funcall link-validate path-1 current-dir)))
desc
- (org-html-make-link opt-plist
- "file" path-1 fragment-1 desc-2 attr
- (org-html-should-inline-p path-1 descp)))))))
+ (org-html-make-link opt-plist
+ "file" path-1 fragment-1 desc-2 attr
+ (org-html-should-inline-p path-1 descp)))))))
(t
;; just publish the path, as default
@@ -1486,14 +1494,6 @@ lang=\"%s\" xml:lang=\"%s\">
(setq txt (replace-match "" t t txt)))
(if (<= level (max umax umax-toc))
(setq head-count (+ head-count 1)))
- (when in-local-list
- ;; Close any local lists before inserting a new header line
- (while local-list-type
- (org-close-li (car local-list-type))
- (insert (format "</%sl>\n" (car local-list-type)))
- (pop local-list-type))
- (setq local-list-indent nil
- in-local-list nil))
(setq first-heading-pos (or first-heading-pos (point)))
(org-html-level-start level txt umax
(and org-export-with-toc (<= level umax))
@@ -1505,19 +1505,6 @@ lang=\"%s\" xml:lang=\"%s\">
(insert "<pre>")
(setq inquote t)))
- ((string-match "^[ \t]*- __+[ \t]*$" line)
- ;; Explicit list closure
- (when local-list-type
- (let ((ind (org-get-indentation line)))
- (while (and local-list-indent
- (<= ind (car local-list-indent)))
- (org-close-li (car local-list-type))
- (insert (format "</%sl>\n" (car local-list-type)))
- (pop local-list-type)
- (pop local-list-indent))
- (or local-list-indent (setq in-local-list nil))))
- (throw 'nextline nil))
-
((and org-export-with-tables
(string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
(when (not table-open)
@@ -1550,66 +1537,57 @@ lang=\"%s\" xml:lang=\"%s\">
starter (if (match-beginning 2)
(substring (match-string 2 line) 0 -1))
line (substring line (match-beginning 5))
- initial-number nil
+ item-number nil
item-tag nil)
- (if (string-match "\\`\\[@start:\\([0-9]+\\)\\][ \t]?" line)
- (setq initial-number (match-string 1 line)
+ (if (string-match "\\[@\\(?:start:\\)?\\([0-9]+\\)\\][ \t]?" line)
+ (setq item-number (match-string 1 line)
line (replace-match "" t t line)))
(if (and starter (string-match "\\(.*?\\) ::[ \t]*" line))
(setq item-type "d"
item-tag (match-string 1 line)
line (substring line (match-end 0))))
- (when (and (not (equal item-type "d"))
- (not (string-match "[^ \t]" line)))
- ;; empty line. Pretend indentation is large.
- (setq ind (if org-empty-line-terminates-plain-lists
- 0
- (1+ (or (car local-list-indent) 1)))))
- (setq didclose nil)
- (while (and in-local-list
- (or (and (= ind (car local-list-indent))
- (not starter))
- (< ind (car local-list-indent))))
- (setq didclose t)
- (org-close-li (car local-list-type))
- (insert (format "</%sl>\n" (car local-list-type)))
- (pop local-list-type) (pop local-list-indent)
- (setq in-local-list local-list-indent))
(cond
((and starter
(or (not in-local-list)
(> ind (car local-list-indent))))
- ;; check for a specified start number
;; Start new (level of) list
(org-close-par-maybe)
(insert (cond
((equal item-type "u") "<ul>\n<li>\n")
- ((equal item-type "o")
- (if initial-number
- (format "<ol start=%s>\n<li>\n" initial-number)
- "<ol>\n<li>\n"))
+ ((and (equal item-type "o") item-number)
+ (format "<ol>\n<li value=\"%s\">\n" item-number))
+ ((equal item-type "o") "<ol>\n<li>\n")
((equal item-type "d")
(format "<dl>\n<dt>%s</dt><dd>\n" item-tag))))
(push item-type local-list-type)
(push ind local-list-indent)
(setq in-local-list t))
+ ;; Continue list
(starter
- ;; continue current list
+ ;; terminate any previous sublist but first ensure
+ ;; list is not ill-formed.
+ (let ((min-ind (apply 'min local-list-indent)))
+ (when (< ind min-ind) (setq ind min-ind)))
+ (while (< ind (car local-list-indent))
+ (org-close-li (car local-list-type))
+ (insert (format "</%sl>\n" (car local-list-type)))
+ (pop local-list-type) (pop local-list-indent)
+ (setq in-local-list local-list-indent))
+ ;; insert new item
(org-close-li (car local-list-type))
(insert (cond
((equal (car local-list-type) "d")
(format "<dt>%s</dt><dd>\n" (or item-tag "???")))
- (t "<li>\n"))))
- (didclose
- ;; we did close a list, normal text follows: need <p>
- (org-open-par)))
+ ((and (equal item-type "o") item-number)
+ (format "<li value=\"%s\">\n" item-number))
+ (t "<li>\n")))))
(if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
(setq line
(replace-match
(if (equal (match-string 1 line) "X")
"<b>[X]</b>"
"<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
- t t line))))
+ t t line))))
;; Horizontal line
(when (string-match "^[ \t]*-\\{5,\\}[ \t]*$" line)
@@ -1664,14 +1642,7 @@ lang=\"%s\" xml:lang=\"%s\">
(when inquote
(insert "</pre>\n")
(org-open-par))
- (when in-local-list
- ;; Close any local lists before inserting a new header line
- (while local-list-type
- (org-close-li (car local-list-type))
- (insert (format "</%sl>\n" (car local-list-type)))
- (pop local-list-type))
- (setq local-list-indent nil
- in-local-list nil))
+
(org-html-level-start 1 nil umax
(and org-export-with-toc (<= level umax))
head-count)
@@ -1752,8 +1723,6 @@ lang=\"%s\" xml:lang=\"%s\">
(while (re-search-forward "<li>[ \r\n\t]*</li>\n?" nil t)
(replace-match ""))
(goto-char (point-min))
- (while (re-search-forward "</ul>\\s-*<ul>\n?" nil t)
- (replace-match ""))
;; Convert whitespace place holders
(goto-char (point-min))
(let (beg end n)
@@ -2164,7 +2133,7 @@ that uses these same face definitions."
"Prepare STRING for HTML export. Apply all active conversions.
If there are links in the string, don't modify these."
(let* ((re (concat org-bracket-link-regexp "\\|"
- (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$")))
+ (org-re "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")))
m s l res)
(if (string-match "^[ \t]*\\+-[-+]*\\+[ \t]*$" string)
string
@@ -2274,28 +2243,6 @@ If there are links in the string, don't modify these."
(defvar in-local-list)
(defvar local-list-indent)
(defvar local-list-type)
-(defun org-export-html-close-lists-maybe (line)
- "Close local lists based on the original indentation of the line."
- (let* ((rawhtml (and in-local-list
- (get-text-property 0 'org-protected line)
- (not (get-text-property 0 'org-example line))))
- ;; rawhtml means: This was between #+begin_html..#+end_html
- ;; originally, thus it excludes stuff that was a source code example
- ;; Actually, this code seems wrong, I don't know why it works, but
- ;; it seems to work.... So keep it like this for now.
- (ind (if rawhtml
- (org-get-indentation line)
- (get-text-property 0 'original-indentation line)))
- didclose)
- (when ind
- (while (and in-local-list
- (<= ind (car local-list-indent)))
- (setq didclose t)
- (org-close-li (car local-list-type))
- (insert (format "</%sl>\n" (car local-list-type)))
- (pop local-list-type) (pop local-list-indent)
- (setq in-local-list local-list-indent))
- (and didclose (org-open-par)))))
(defvar body-only) ; dynamically scoped into this.
(defun org-html-level-start (level title umax with-toc head-count)
@@ -2328,7 +2275,7 @@ When TITLE is nil, just close all open levels."
(when title
;; If title is nil, this means this function is called to close
;; all levels, so the rest is done only if title is given
- (when (string-match (org-re "\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
+ (when (string-match (org-re "\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") title)
(setq title (replace-match
(if org-export-with-tags
(save-match-data
diff --git a/lisp/org-icalendar.el b/lisp/org-icalendar.el
index 4f307c4..1e3c798 100644
--- a/lisp/org-icalendar.el
+++ b/lisp/org-icalendar.el
@@ -194,6 +194,13 @@ When nil of the empty string, use the abbreviation retrieved from Emacs."
(const :tag "Unspecified" nil)
(string :tag "Time zone")))
+(defcustom org-icalendar-use-UTC-date-time ()
+ "Non-nil force the use of the universal time for iCalendar DATE-TIME.
+The iCalendar DATE-TIME can be expressed with local time or universal Time,
+universal time could be more compatible with some external tools."
+ :group 'org-export-icalendar
+ :type 'boolean)
+
;;; iCalendar export
;;;###autoload
@@ -311,7 +318,7 @@ When COMBINE is non nil, add the category to each line."
inc t
hd (condition-case nil
(org-icalendar-cleanup-string
- (org-get-heading))
+ (org-get-heading t))
(error (throw :skip nil)))
summary (org-icalendar-cleanup-string
(org-entry-get nil "SUMMARY"))
@@ -439,7 +446,7 @@ END:VEVENT\n"
(when org-icalendar-include-todo
(setq prefix "TODO-")
(goto-char (point-min))
- (while (re-search-forward org-todo-line-regexp nil t)
+ (while (re-search-forward org-complex-heading-regexp nil t)
(catch :skip
(org-agenda-skip)
(when org-icalendar-verify-function
@@ -471,7 +478,7 @@ END:VEVENT\n"
((eq org-icalendar-include-todo t)
;; include everything that is not done
(member state org-not-done-keywords))))
- (setq hd (match-string 3)
+ (setq hd (match-string 4)
summary (org-icalendar-cleanup-string
(org-entry-get nil "SUMMARY"))
desc (org-icalendar-cleanup-string
@@ -634,8 +641,13 @@ a time), or the day by one (if it does not contain a time)."
(setq h (+ 2 h)))
(setq d (1+ d))))
(setq time (encode-time s mi h d m y)))
- (setq fmt (if have-time ":%Y%m%dT%H%M%S" ";VALUE=DATE:%Y%m%d"))
- (concat keyword (format-time-string fmt time)))))
+ (setq fmt (if have-time (if org-icalendar-use-UTC-date-time
+ ":%Y%m%dT%H%M%SZ"
+ ":%Y%m%dT%H%M%S")
+ ";VALUE=DATE:%Y%m%d"))
+ (concat keyword (format-time-string fmt time
+ (and org-icalendar-use-UTC-date-time
+ have-time))))))
(provide 'org-icalendar)
diff --git a/lisp/org-latex.el b/lisp/org-latex.el
index 4f27f42..9a62457 100644
--- a/lisp/org-latex.el
+++ b/lisp/org-latex.el
@@ -280,6 +280,11 @@ markup defined, the first one in the association list will be used."
(string :tag "Keyword")
(string :tag "Markup")))))
+(defcustom org-export-latex-tag-markup "\\textbf{%s}"
+ "Markup for tags, as a printf format."
+ :group 'org-export-latex
+ :type 'string)
+
(defcustom org-export-latex-timestamp-markup "\\textit{%s}"
"A printf format string to be applied to time stamps."
:group 'org-export-latex
@@ -952,28 +957,13 @@ Return a list reflecting the document structure."
(defun org-export-latex-parse-subcontent (level odd)
"Extract the subcontent of a section at LEVEL.
If ODD Is non-nil, assume subcontent only contains odd sections."
-
- (let (nstars new-level)
- ;; In the search, we should not assume there will be exactly
- ;; LEVEL+1 stars in the next heading, as there may be more than
- ;; that number of stars. hence the regexp should be \\*{N,}
- ;; rather than just \\*{N} (i.e. no upper bound, but N is minimum
- ;; number of stars to expect.)
- ;; We then have to check how many stars were found, rather than
- ;; assuming there were exactly N.
- (when (org-re-search-forward-unprotected
- (concat "^\\(\\(?:\\*\\)\\{"
- (number-to-string (+ (if odd 4 2) level))
- ",\\}\\) \\(.*\\)$")
- nil t)
- (setq nstars (1- (- (match-end 1) (match-beginning 1))))
- (setq new-level (if odd
- (/ (+ 3 nstars) 2);; not entirely sure why +3!
- nstars)))
- (if nstars
- (org-export-latex-parse-global new-level odd)
- nil) ; subcontent is nil
- ))
+ (if (not (org-re-search-forward-unprotected
+ (concat "^\\(\\(?:\\*\\)\\{"
+ (number-to-string (+ (if odd 4 2) level))
+ "\\}\\) \\(.*\\)$")
+ nil t))
+ nil ; subcontent is nil
+ (org-export-latex-parse-global (+ (if odd 2 1) level) odd)))
;;; Rendering functions:
(defun org-export-latex-global (content)
@@ -1344,13 +1334,13 @@ links, keywords, lists, tables, fixed-width"
(replace-match "")
(replace-match (format "\\textbf{%s}" (match-string 0)) t t)))
;; convert tags
- (when (re-search-forward "\\(:[a-zA-Z0-9_@]+\\)+:" nil t)
+ (when (re-search-forward "\\(:[a-zA-Z0-9_@#%]+\\)+:" nil t)
(if (or (not org-export-with-tags)
(plist-get remove-list :tags))
(replace-match "")
(replace-match
(org-export-latex-protect-string
- (format "\\textbf{%s}"
+ (format org-export-latex-tag-markup
(save-match-data
(replace-regexp-in-string
"_" "\\\\_" (match-string 0)))))
@@ -2253,11 +2243,11 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
"Convert plain text lists in current buffer into LaTeX lists."
(let (res)
(goto-char (point-min))
- (while (org-re-search-forward-unprotected org-list-beginning-re nil t)
+ (while (org-search-forward-unenclosed org-item-beginning-re nil t)
(beginning-of-line)
(setq res (org-list-to-latex (org-list-parse-list t)
org-export-latex-list-parameters))
- (while (string-match "^\\(\\\\item[ \t]+\\)\\[@start:\\([0-9]+\\)\\]"
+ (while (string-match "^\\(\\\\item[ \t]+\\)\\[@\\(?:start:\\)?\\([0-9]+\\)\\]"
res)
(setq res (replace-match
(concat (format "\\setcounter{enumi}{%d}"
diff --git a/lisp/org-list.el b/lisp/org-list.el
index cdfd2c5..d9fc24e 100644
--- a/lisp/org-list.el
+++ b/lisp/org-list.el
@@ -40,20 +40,31 @@
(defvar org-M-RET-may-split-line)
(defvar org-complex-heading-regexp)
(defvar org-odd-levels-only)
+(defvar org-outline-regexp)
+(defvar org-ts-regexp)
+(defvar org-ts-regexp-both)
(declare-function org-invisible-p "org" ())
(declare-function org-on-heading-p "org" (&optional invisible-ok))
(declare-function outline-next-heading "outline" ())
(declare-function org-back-to-heading "org" (&optional invisible-ok))
(declare-function org-back-over-empty-lines "org" ())
-(declare-function org-skip-whitespace "org" ())
(declare-function org-trim "org" (s))
(declare-function org-get-indentation "org" (&optional line))
(declare-function org-timer-item "org-timer" (&optional arg))
+(declare-function org-timer-hms-to-secs "org-timer" (hms))
(declare-function org-combine-plists "org" (&rest plists))
-(declare-function org-entry-get "org" (pom property &optional inherit))
+(declare-function org-entry-get "org"
+ (pom property &optional inherit literal-nil))
(declare-function org-narrow-to-subtree "org" ())
(declare-function org-show-subtree "org" ())
+(declare-function org-in-regexps-block-p "org"
+ (start-re end-re &optional bound))
+(declare-function org-level-increment "org" ())
+(declare-function org-at-heading-p "org" (&optional ignored))
+(declare-function outline-previous-heading "outline" ())
+(declare-function org-icompleting-read "org" (&rest args))
+(declare-function org-time-string-to-seconds "org" (s))
(defgroup org-plain-lists nil
"Options concerning plain lists in Org-mode."
@@ -62,7 +73,6 @@
(defcustom org-cycle-include-plain-lists t
"When t, make TAB cycle visibility on plain list items.
-
Cycling plain lists works only when the cursor is on a plain list
item. When the cursor is on an outline heading, plain lists are
treated as text. This is the most stable way of handling this,
@@ -139,38 +149,88 @@ the safe choice."
(defcustom org-list-two-spaces-after-bullet-regexp nil
"A regular expression matching bullets that should have 2 spaces after them.
When nil, no bullet will have two spaces after them.
-When a string, it will be used as a regular expression. When the bullet
-type of a list is changed, the new bullet type will be matched against this
-regexp. If it matches, there will be two spaces instead of one after
-the bullet in each item of he list."
+When a string, it will be used as a regular expression. When the
+bullet type of a list is changed, the new bullet type will be
+matched against this regexp. If it matches, there will be two
+spaces instead of one after the bullet in each item of the list."
:group 'org-plain-lists
:type '(choice
(const :tag "never" nil)
(regexp)))
-(defcustom org-empty-line-terminates-plain-lists nil
- "Non-nil means an empty line ends all plain list levels.
-This is currently effective only during export. It should also have
-an effect for indentation and plain list folding, but it does not.
-When nil, empty lines are part of the preceding item."
+(defcustom org-list-ending-method 'both
+ "Determine where plain lists should end.
+Valid values are: `regexp', `indent' or `both'.
+
+When set to `regexp', Org will look into two variables,
+`org-empty-line-terminates-plain-lists' and the more general
+`org-list-end-regexp', to determine what will end lists. This is
+the fastest method.
+
+When set to `indent', a list will end whenever a line following
+an item, but not starting one, is less or equally indented than
+it.
+
+When set to `both', each of the preceding methods is applied to
+determine lists endings. This is the default method."
:group 'org-plain-lists
- :type 'boolean)
+ :type '(choice
+ (const :tag "With a regexp defining ending" regexp)
+ (const :tag "With indentation of regular (no bullet) text" indent)
+ (const :tag "With both methods" both)))
-(defcustom org-auto-renumber-ordered-lists t
- "Non-nil means automatically renumber ordered plain lists.
-Renumbering happens when the sequence have been changed with
-\\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands,
-use \\[org-ctrl-c-ctrl-c] to trigger renumbering."
+(defcustom org-empty-line-terminates-plain-lists nil
+ "Non-nil means an empty line ends all plain list levels.
+This variable only makes sense if `org-list-ending-method' is set
+to `regexp' or `both'. This is then equivalent to set
+`org-list-end-regexp' to \"^[ \\t]*$\"."
:group 'org-plain-lists
:type 'boolean)
-(defcustom org-provide-checkbox-statistics t
- "Non-nil means update checkbox statistics after insert and toggle.
-When this is set, checkbox statistics is updated each time you
-either insert a new checkbox with \\[org-insert-todo-heading] or
-toggle a checkbox with \\[org-ctrl-c-ctrl-c]."
+(defcustom org-list-end-regexp "^[ \t]*\n[ \t]*\n"
+ "Regexp matching the end of all plain list levels.
+It must start with \"^\" and end with \"\\n\". It defaults to 2
+blank lines. `org-empty-line-terminates-plain-lists' has
+precedence over it."
:group 'org-plain-lists
- :type 'boolean)
+ :type 'string)
+
+(defcustom org-list-automatic-rules '((bullet . t)
+ (checkbox . t)
+ (indent . t)
+ (insert . t))
+ "Non-nil means apply set of rules when acting on lists.
+By default, automatic actions are taken when using
+ \\[org-meta-return], \\[org-metaright], \\[org-metaleft],
+ \\[org-shiftmetaright], \\[org-shiftmetaleft],
+ \\[org-ctrl-c-minus], \\[org-toggle-checkbox] or
+ \\[org-insert-todo-heading]. You can disable individually these
+ rules by setting them to nil. Valid rules are:
+
+bullet when non-nil, cycling bullet do not allow lists at
+ column 0 to have * as a bullet and descriptions lists
+ to be numbered.
+checkbox when non-nil, checkbox statistics is updated each time
+ you either insert a new checkbox or toggle a checkbox.
+ It also prevents from inserting a checkbox in a
+ description item.
+indent when non-nil, indenting or outdenting list top-item
+ with its subtree will move the whole list and
+ outdenting a list whose bullet is * to column 0 will
+ change that bullet to -
+insert when non-nil, trying to insert an item inside a block
+ will insert it right before the block instead of
+ throwing an error."
+ :group 'org-plain-lists
+ :type '(alist :tag "Sets of rules"
+ :key-type
+ (choice
+ (const :tag "Bullet" bullet)
+ (const :tag "Checkbox" checkbox)
+ (const :tag "Indent" indent)
+ (const :tag "Insert" insert))
+ :value-type
+ (boolean :tag "Activate" :value t)))
(defcustom org-hierarchical-checkbox-statistics t
"Non-nil means checkbox statistics counts only the state of direct children.
@@ -187,9 +247,6 @@ When the indentation would be larger than this, it will become
:group 'org-plain-lists
:type 'integer)
-(defvar org-list-beginning-re
- "^\\([ \t]*\\)\\([-+]\\|[0-9]+[.)]\\) +\\(.*\\)$")
-
(defcustom org-list-radio-list-templates
'((latex-mode "% BEGIN RECEIVE ORGLST %n
% END RECEIVE ORGLST %n
@@ -217,9 +274,14 @@ list, obtained by prompting the user."
(list (symbol :tag "Major mode")
(string :tag "Format"))))
-;;;; Plain list items, including checkboxes
+;;; Internal functions
-;;; Plain list items
+(defun org-list-end-re ()
+ "Return the regex corresponding to the end of a list.
+It depends on `org-empty-line-terminates-plain-lists'."
+ (if org-empty-line-terminates-plain-lists
+ "^[ \t]*\n"
+ org-list-end-regexp))
(defun org-item-re (&optional general)
"Return the correct regular expression for plain lists.
@@ -227,19 +289,526 @@ If GENERAL is non-nil, return the general regexp independent of the value
of `org-plain-list-ordered-item-terminator'."
(cond
((or general (eq org-plain-list-ordered-item-terminator t))
- "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
+ "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\([ \t]+\\|$\\)")
((= org-plain-list-ordered-item-terminator ?.)
- "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
+ "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\([ \t]+\\|$\\)")
((= org-plain-list-ordered-item-terminator ?\))
- "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
+ "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\([ \t]+\\|$\\)")
(t (error "Invalid value of `org-plain-list-ordered-item-terminator'"))))
+(defconst org-item-beginning-re (concat "^" (org-item-re))
+ "Regexp matching the beginning of a plain list item.")
+
+(defun org-list-ending-between (min max &optional firstp)
+ "Find the position of a list ending between MIN and MAX, or nil.
+This function looks for `org-list-end-re' outside a block.
+
+If FIRSTP in non-nil, return the point at the beginning of the
+nearest valid terminator from MIN. Otherwise, return the point at
+the end of the nearest terminator from MAX."
+ (save-excursion
+ (let* ((start (if firstp min max))
+ (end (if firstp max min))
+ (search-fun (if firstp
+ #'org-search-forward-unenclosed
+ #'org-search-backward-unenclosed))
+ (list-end-p (progn
+ (goto-char start)
+ (funcall search-fun (org-list-end-re) end t))))
+ ;; Is there a valid list ending somewhere ?
+ (and list-end-p
+ ;; we want to be on the first line of the list ender
+ (match-beginning 0)))))
+
+(defun org-list-maybe-skip-block (search limit)
+ "Return non-nil value if point is in a block, skipping it on the way.
+It looks for the boundary of the block in SEARCH direction,
+stopping at LIMIT."
+ (save-match-data
+ (let ((case-fold-search t)
+ (boundary (if (eq search 're-search-forward) 3 5)))
+ (when (save-excursion
+ (and (funcall search "^[ \t]*#\\+\\(begin\\|end\\)_" limit t)
+ (= (length (match-string 1)) boundary)))
+ ;; We're in a block: get out of it
+ (goto-char (match-beginning 0))))))
+
+(defun org-list-search-unenclosed-generic (search re bound noerr)
+ "Search a string outside blocks and protected places.
+Arguments SEARCH, RE, BOUND and NOERR are similar to those in
+`search-forward', `search-backward', `re-search-forward' and
+`re-search-backward'."
+ (catch 'exit
+ (let ((origin (point)))
+ (while t
+ ;; 1. No match: return to origin or bound, depending on NOERR.
+ (unless (funcall search re bound noerr)
+ (throw 'exit (and (goto-char (if (booleanp noerr) origin bound))
+ nil)))
+ ;; 2. Match not in block or protected: return point. Else
+ ;; skip the block and carry on.
+ (unless (or (get-text-property (match-beginning 0) 'org-protected)
+ (org-list-maybe-skip-block search bound))
+ (throw 'exit (point)))))))
+
+(defun org-search-backward-unenclosed (regexp &optional bound noerror)
+ "Like `re-search-backward' but don't stop inside blocks or protected places.
+Arguments REGEXP, BOUND and NOERROR are similar to those used in
+`re-search-backward'."
+ (org-list-search-unenclosed-generic
+ #'re-search-backward regexp (or bound (point-min)) noerror))
+
+(defun org-search-forward-unenclosed (regexp &optional bound noerror)
+ "Like `re-search-forward' but don't stop inside blocks or protected places.
+Arguments REGEXP, BOUND and NOERROR are similar to those used in
+`re-search-forward'."
+ (org-list-search-unenclosed-generic
+ #'re-search-forward regexp (or bound (point-max)) noerror))
+
+(defun org-list-in-item-p-with-indent (limit)
+ "Is the cursor inside a plain list?
+Plain lists are considered ending when a non-blank line is less
+indented than the previous item within LIMIT."
+ (save-excursion
+ (beginning-of-line)
+ (cond
+ ;; do not start searching inside a block...
+ ((org-list-maybe-skip-block #'re-search-backward limit))
+ ;; ... or at a blank line
+ ((looking-at "^[ \t]*$")
+ (skip-chars-backward " \r\t\n")
+ (beginning-of-line)))
+ (beginning-of-line)
+ (or (org-at-item-p)
+ (let* ((case-fold-search t)
+ (ind-ref (org-get-indentation))
+ ;; Ensure there is at least an item above
+ (up-item-p (save-excursion
+ (org-search-backward-unenclosed
+ org-item-beginning-re limit t))))
+ (and up-item-p
+ (catch 'exit
+ (while t
+ (cond
+ ((org-at-item-p)
+ (throw 'exit (< (org-get-indentation) ind-ref)))
+ ((looking-at "^[ \t]*$")
+ (skip-chars-backward " \r\t\n")
+ (beginning-of-line))
+ ((looking-at "^[ \t]*#\\+end_")
+ (re-search-backward "^[ \t]*#\\+begin_"))
+ (t
+ (setq ind-ref (min (org-get-indentation) ind-ref))
+ (forward-line -1))))))))))
+
+(defun org-list-in-item-p-with-regexp (limit)
+ "Is the cursor inside a plain list?
+Plain lists end when `org-list-end-regexp' is matched, or at a
+blank line if `org-empty-line-terminates-plain-lists' is true.
+
+Argument LIMIT specifies the upper-bound of the search."
+ (save-excursion
+ (let* ((actual-pos (goto-char (point-at-eol)))
+ ;; Moved to eol so current line can be matched by
+ ;; `org-item-re'.
+ (last-item-start (save-excursion
+ (org-search-backward-unenclosed
+ org-item-beginning-re limit t)))
+ (list-ender (org-list-ending-between
+ last-item-start actual-pos)))
+ ;; We are in a list when we are on an item line or when we can
+ ;; find an item before point and there is no valid list ender
+ ;; between it and the point.
+ (and last-item-start (not list-ender)))))
+
+(defun org-list-top-point-with-regexp (limit)
+ "Return point at the top level item in a list.
+Argument LIMIT specifies the upper-bound of the search.
+
+List ending is determined by regexp. See
+`org-list-ending-method'. for more information."
+ (save-excursion
+ (let ((pos (point-at-eol)))
+ ;; Is there some list above this one ? If so, go to its ending.
+ ;; Otherwise, go back to the heading above or bob.
+ (goto-char (or (org-list-ending-between limit pos) limit))
+ ;; From there, search down our list.
+ (org-search-forward-unenclosed org-item-beginning-re pos t)
+ (point-at-bol))))
+
+(defun org-list-bottom-point-with-regexp (limit)
+ "Return point just before list ending.
+Argument LIMIT specifies the lower-bound of the search.
+
+List ending is determined by regexp. See
+`org-list-ending-method'. for more information."
+ (save-excursion
+ (let ((pos (org-get-item-beginning)))
+ ;; The list ending is either first point matching
+ ;; `org-list-end-re', point at first white-line before next
+ ;; heading, or eob.
+ (or (org-list-ending-between (min pos limit) limit t) limit))))
+
+(defun org-list-top-point-with-indent (limit)
+ "Return point at the top level in a list.
+Argument LIMIT specifies the upper-bound of the search.
+
+List ending is determined by indentation of text. See
+`org-list-ending-method'. for more information."
+ (save-excursion
+ (let ((case-fold-search t))
+ (let ((item-ref (goto-char (org-get-item-beginning)))
+ (ind-ref 10000))
+ (forward-line -1)
+ (catch 'exit
+ (while t
+ (let ((ind (org-get-indentation)))
+ (cond
+ ((looking-at "^[ \t]*:END:")
+ (throw 'exit item-ref))
+ ((<= (point) limit)
+ (throw 'exit
+ (if (and (org-at-item-p) (< ind ind-ref))
+ (point-at-bol)
+ item-ref)))
+ ((looking-at "^[ \t]*$")
+ (skip-chars-backward " \r\t\n")
+ (beginning-of-line))
+ ((looking-at "^[ \t]*#\\+end_")
+ (re-search-backward "^[ \t]*#\\+begin_"))
+ ((not (org-at-item-p))
+ (setq ind-ref (min ind ind-ref))
+ (forward-line -1))
+ ((>= ind ind-ref)
+ (throw 'exit item-ref))
+ (t
+ (setq item-ref (point-at-bol) ind-ref 10000)
+ (forward-line -1))))))))))
+
+(defun org-list-bottom-point-with-indent (limit)
+ "Return point just before list ending or nil if not in a list.
+Argument LIMIT specifies the lower-bound of the search.
+
+List ending is determined by the indentation of text. See
+`org-list-ending-method' for more information."
+ (save-excursion
+ (let ((ind-ref (progn
+ (goto-char (org-get-item-beginning))
+ (org-get-indentation)))
+ (case-fold-search t))
+ ;; do not start inside a block
+ (org-list-maybe-skip-block #'re-search-forward limit)
+ (beginning-of-line)
+ (catch 'exit
+ (skip-chars-forward " \t")
+ (while t
+ (let ((ind (org-get-indentation)))
+ (cond
+ ((or (>= (point) limit)
+ (looking-at ":END:"))
+ (throw 'exit (progn
+ ;; Ensure bottom is just after a
+ ;; non-blank line.
+ (skip-chars-backward " \r\t\n")
+ (min (point-max) (1+ (point-at-eol))))))
+ ((= (point) (point-at-eol))
+ (skip-chars-forward " \r\t\n")
+ (beginning-of-line))
+ ((org-at-item-p)
+ (setq ind-ref (min ind ind-ref))
+ (forward-line 1))
+ ((<= ind ind-ref)
+ (throw 'exit (point-at-bol)))
+ ((looking-at "#\\+begin_")
+ (re-search-forward "[ \t]*#\\+end_")
+ (forward-line 1))
+ (t (forward-line 1)))))))))
+
+(defun org-list-at-regexp-after-bullet-p (regexp)
+ "Is point at a list item with REGEXP after bullet?"
+ (and (org-at-item-p)
+ (save-excursion
+ (goto-char (match-end 0))
+ ;; Ignore counter if any
+ (when (looking-at "\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?")
+ (goto-char (match-end 0)))
+ (looking-at regexp))))
+
+(defun org-list-get-item-same-level (search-fun pos limit pre-move)
+ "Return point at the beginning of next item at the same level.
+Search items using function SEARCH-FUN, from POS to LIMIT. It
+uses PRE-MOVE before search. Return nil if no item was found."
+ (save-excursion
+ (goto-char pos)
+ (let* ((start (org-get-item-beginning))
+ (ind (progn (goto-char start) (org-get-indentation))))
+ ;; We don't want to match the current line.
+ (funcall pre-move)
+ ;; Skip any sublist on the way
+ (while (and (funcall search-fun org-item-beginning-re limit t)
+ (> (org-get-indentation) ind)))
+ (when (and (/= (point-at-bol) start) ; Have we moved ?
+ (= (org-get-indentation) ind))
+ (point-at-bol)))))
+
+(defun org-list-separating-blank-lines-number (pos top bottom)
+ "Return number of blank lines that should separate items in list.
+POS is the position of point to be considered.
+
+TOP and BOTTOM are respectively position of list beginning and
+list ending.
+
+Assume point is at item's beginning. If the item is alone, apply
+some heuristics to guess the result."
+ (save-excursion
+ (let ((insert-blank-p
+ (cdr (assq 'plain-list-item org-blank-before-new-entry)))
+ usr-blank)
+ (cond
+ ;; Trivial cases where there should be none.
+ ((or (and (not (eq org-list-ending-method 'indent))
+ org-empty-line-terminates-plain-lists)
+ (not insert-blank-p)) 0)
+ ;; When `org-blank-before-new-entry' says so, it is 1.
+ ((eq insert-blank-p t) 1)
+ ;; plain-list-item is 'auto. Count blank lines separating
+ ;; neighbours items in list.
+ (t (let ((next-p (org-get-next-item (point) bottom)))
+ (cond
+ ;; Is there a next item?
+ (next-p (goto-char next-p)
+ (org-back-over-empty-lines))
+ ;; Is there a previous item?
+ ((org-get-previous-item (point) top)
+ (org-back-over-empty-lines))
+ ;; User inserted blank lines, trust him
+ ((and (> pos (org-end-of-item-before-blank bottom))
+ (> (save-excursion
+ (goto-char pos)
+ (skip-chars-backward " \t")
+ (setq usr-blank (org-back-over-empty-lines))) 0))
+ usr-blank)
+ ;; Are there blank lines inside the item ?
+ ((save-excursion
+ (org-search-forward-unenclosed
+ "^[ \t]*$" (org-end-of-item-before-blank bottom) t)) 1)
+ ;; No parent: no blank line.
+ (t 0))))))))
+
+(defun org-list-insert-item-generic (pos &optional checkbox after-bullet)
+ "Insert a new list item at POS.
+If POS is before first character after bullet of the item, the
+new item will be created before the current one.
+
+Insert a checkbox if CHECKBOX is non-nil, and string AFTER-BULLET
+after the bullet. Cursor will be after this text once the
+function ends."
+ (goto-char pos)
+ ;; Is point in a special block?
+ (when (org-in-regexps-block-p
+ "^[ \t]*#\\+\\(begin\\|BEGIN\\)_\\([a-zA-Z0-9_]+\\)"
+ '(concat "^[ \t]*#\\+\\(end\\|END\\)_" (match-string 2)))
+ (if (not (cdr (assq 'insert org-list-automatic-rules)))
+ ;; Rule in `org-list-automatic-rules' forbids insertion.
+ (error "Cannot insert item inside a block")
+ ;; Else, move before it prior to add a new item.
+ (end-of-line)
+ (re-search-backward "^[ \t]*#\\+\\(begin\\|BEGIN\\)_" nil t)
+ (end-of-line 0)))
+ (let* ((true-pos (point))
+ (top (org-list-top-point))
+ (bottom (copy-marker (org-list-bottom-point)))
+ (bullet (and (goto-char (org-get-item-beginning))
+ (org-list-bullet-string (org-get-bullet))))
+ (ind (org-get-indentation))
+ (before-p (progn
+ ;; Description item: text starts after colons.
+ (or (org-at-item-description-p)
+ ;; At a checkbox: text starts after it.
+ (org-at-item-checkbox-p)
+ ;; Otherwise, text starts after bullet.
+ (org-at-item-p))
+ (<= true-pos (match-end 0))))
+ (blank-lines-nb (org-list-separating-blank-lines-number
+ true-pos top bottom))
+ (insert-fun
+ (lambda (text)
+ ;; insert bullet above item in order to avoid bothering
+ ;; with possible blank lines ending last item.
+ (goto-char (org-get-item-beginning))
+ (indent-to-column ind)
+ (insert (concat bullet (when checkbox "[ ] ") after-bullet))
+ ;; Stay between after-bullet and before text.
+ (save-excursion
+ (insert (concat text (make-string (1+ blank-lines-nb) ?\n))))
+ (unless before-p
+ ;; store bottom: exchanging items doesn't change list
+ ;; bottom point but will modify marker anyway
+ (setq bottom (marker-position bottom))
+ (let ((col (current-column)))
+ (org-list-exchange-items
+ (org-get-item-beginning) (org-get-next-item (point) bottom)
+ bottom)
+ ;; recompute next-item: last sexp modified list
+ (goto-char (org-get-next-item (point) bottom))
+ (org-move-to-column col)))
+ ;; checkbox update might modify bottom point, so use a
+ ;; marker here
+ (setq bottom (copy-marker bottom))
+ (when checkbox (org-update-checkbox-count-maybe))
+ (org-list-repair nil top bottom))))
+ (goto-char true-pos)
+ (cond
+ (before-p (funcall insert-fun nil) t)
+ ;; Can't split item: insert bullet at the end of item.
+ ((not (org-get-alist-option org-M-RET-may-split-line 'item))
+ (funcall insert-fun nil) t)
+ ;; else, insert a new bullet along with everything from point
+ ;; down to last non-blank line of item.
+ (t
+ (delete-horizontal-space)
+ ;; Get pos again in case previous command modified line.
+ (let* ((pos (point))
+ (end-before-blank (org-end-of-item-before-blank bottom))
+ (after-text
+ (when (< pos end-before-blank)
+ (prog1
+ (delete-and-extract-region pos end-before-blank)
+ ;; delete any blank line at and before point.
+ (beginning-of-line)
+ (while (looking-at "^[ \t]*$")
+ (delete-region (point-at-bol) (1+ (point-at-eol)))
+ (beginning-of-line 0))))))
+ (funcall insert-fun after-text) t)))))
+
+(defvar org-last-indent-begin-marker (make-marker))
+(defvar org-last-indent-end-marker (make-marker))
+
+(defun org-list-indent-item-generic (arg no-subtree top bottom)
+ "Indent a local list item including its children.
+When number ARG is a negative, item will be outdented, otherwise
+it will be indented.
+
+If a region is active, all items inside will be moved.
+
+If NO-SUBTREE is non-nil, only indent the item itself, not its
+children.
+
+TOP and BOTTOM are respectively position at item beginning and at
+item ending.
+
+Return t if successful."
+ (let* ((regionp (org-region-active-p))
+ (rbeg (and regionp (region-beginning)))
+ (rend (and regionp (region-end))))
+ (cond
+ ((and regionp
+ (goto-char rbeg)
+ (not (org-search-forward-unenclosed org-item-beginning-re rend t)))
+ (error "No item in region"))
+ ((not (org-at-item-p))
+ (error "Not on an item"))
+ (t
+ ;; Are we going to move the whole list?
+ (let* ((specialp (and (cdr (assq 'indent org-list-automatic-rules))
+ (not no-subtree)
+ (= top (point-at-bol)))))
+ ;; Determine begin and end points of zone to indent. If moving
+ ;; more than one item, ensure we keep them on subsequent moves.
+ (unless (and (memq last-command '(org-shiftmetaright org-shiftmetaleft))
+ (memq this-command '(org-shiftmetaright org-shiftmetaleft)))
+ (if regionp
+ (progn
+ (set-marker org-last-indent-begin-marker rbeg)
+ (set-marker org-last-indent-end-marker rend))
+ (set-marker org-last-indent-begin-marker (point-at-bol))
+ (set-marker org-last-indent-end-marker
+ (save-excursion
+ (cond
+ (specialp bottom)
+ (no-subtree (org-end-of-item-or-at-child bottom))
+ (t (org-get-end-of-item bottom)))))))
+ ;; Get everything ready
+ (let* ((beg (marker-position org-last-indent-begin-marker))
+ (end (marker-position org-last-indent-end-marker))
+ (struct (org-list-struct
+ beg end top (if specialp end bottom) (< arg 0)))
+ (origins (org-list-struct-origins struct))
+ (beg-item (assq beg struct)))
+ (cond
+ ;; Special case: moving top-item with indent rule
+ (specialp
+ (let* ((level-skip (org-level-increment))
+ (offset (if (< arg 0) (- level-skip) level-skip))
+ (top-ind (nth 1 beg-item)))
+ (if (< (+ top-ind offset) 0)
+ (error "Cannot outdent beyond margin")
+ ;; Change bullet if necessary
+ (when (and (= (+ top-ind offset) 0)
+ (string-match "*" (nth 2 beg-item)))
+ (setcdr beg-item (list (nth 1 beg-item)
+ (org-list-bullet-string "-"))))
+ ;; Shift ancestor
+ (let ((anc (car struct)))
+ (setcdr anc (list (+ (nth 1 anc) offset) "" nil)))
+ (org-list-struct-fix-struct struct origins)
+ (org-list-struct-apply-struct struct end))))
+ ;; Forbidden move
+ ((and (< arg 0)
+ (or (and no-subtree
+ (not regionp)
+ (org-list-struct-get-child beg-item struct))
+ (let ((last-item (save-excursion
+ (goto-char end)
+ (skip-chars-backward " \r\t\n")
+ (goto-char (org-get-item-beginning))
+ (org-list-struct-assoc-at-point))))
+ (org-list-struct-get-child last-item struct))))
+ (error "Cannot outdent an item without its children"))
+ ;; Normal shifting
+ (t
+ (let* ((shifted-ori (if (< arg 0)
+ (org-list-struct-outdent beg end origins)
+ (org-list-struct-indent beg end origins struct))))
+ (org-list-struct-fix-struct struct shifted-ori)
+ (org-list-struct-apply-struct struct bottom))))))))))
+
+;;; Predicates
+
+(defun org-in-item-p ()
+ "Is the cursor inside a plain list?
+This checks `org-list-ending-method'."
+ (unless (let ((outline-regexp org-outline-regexp)) (org-at-heading-p))
+ (let* ((prev-head (save-excursion (outline-previous-heading)))
+ (bound (if prev-head
+ (or (save-excursion
+ (let ((case-fold-search t))
+ (re-search-backward "^[ \t]*:END:" prev-head t)))
+ prev-head)
+ (point-min))))
+ (cond
+ ((eq org-list-ending-method 'regexp)
+ (org-list-in-item-p-with-regexp bound))
+ ((eq org-list-ending-method 'indent)
+ (org-list-in-item-p-with-indent bound))
+ (t (and (org-list-in-item-p-with-regexp bound)
+ (org-list-in-item-p-with-indent bound)))))))
+
+(defun org-list-first-item-p (top)
+ "Is this item the first item in a plain list?
+Assume point is at an item.
+
+TOP is the position of list's top-item."
+ (save-excursion
+ (beginning-of-line)
+ (let ((ind (org-get-indentation)))
+ (or (not (org-search-backward-unenclosed org-item-beginning-re top t))
+ (< (org-get-indentation) ind)))))
+
(defun org-at-item-p ()
"Is point in a line starting a hand-formatted item?"
-
(save-excursion
- (goto-char (point-at-bol))
- (looking-at (org-item-re))))
+ (beginning-of-line) (looking-at org-item-beginning-re)))
(defun org-at-item-bullet-p ()
"Is point at the bullet of a plain list item?"
@@ -247,170 +816,18 @@ of `org-plain-list-ordered-item-terminator'."
(not (member (char-after) '(?\ ?\t)))
(< (point) (match-end 0))))
-(defun org-in-item-p ()
- "Is the cursor inside a plain list item.
-Does not have to be the first line."
- (save-excursion
- (condition-case nil
- (progn
- (org-beginning-of-item)
- (org-at-item-p)
- t)
- (error nil))))
-
-(defun org-insert-item (&optional checkbox)
- "Insert a new item at the current level.
-Return t when things worked, nil when we are not in an item."
- (when (save-excursion
- (condition-case nil
- (progn
- (org-beginning-of-item)
- (org-at-item-p)
- (if (org-invisible-p) (error "Invisible item"))
- t)
- (error nil)))
- (let* ((bul (match-string 0))
- (descp (save-excursion (goto-char (match-beginning 0))
- (beginning-of-line 1)
- (save-match-data
- (and (looking-at "[ \t]*\\(.*?\\) ::")
- (match-string 1)))))
- (empty-line-p (save-excursion
- (goto-char (match-beginning 0))
- (and (not (bobp))
- (or (beginning-of-line 0) t)
- (save-match-data
- (looking-at "[ \t]*$")))))
- (timerp (and descp
- (save-match-data
- (string-match "^[-+*][ \t]+[0-9]+:[0-9]+:[0-9]+$"
- descp))))
- (eow (save-excursion (beginning-of-line 1) (looking-at "[ \t]*")
- (match-end 0)))
- (blank-a (if org-empty-line-terminates-plain-lists
- nil
- (cdr (assq 'plain-list-item org-blank-before-new-entry))))
- (blank (if (eq blank-a 'auto) empty-line-p blank-a))
- pos)
- (if descp (setq checkbox nil))
- (if timerp
- (progn (org-timer-item) t)
- (cond
- ((and (org-at-item-p) (<= (point) eow))
- ;; before the bullet
- (beginning-of-line 1)
- (open-line (if blank 2 1)))
- ((<= (point) eow)
- (beginning-of-line 1))
- (t
- (unless (org-get-alist-option org-M-RET-may-split-line 'item)
- (end-of-line 1)
- (delete-horizontal-space))
- (newline (if blank 2 1))))
- (insert bul
- (if checkbox "[ ]" "")
- (if descp (concat (if checkbox " " "")
- (read-string "Term: ") " :: ") ""))
- (just-one-space)
- (setq pos (point))
- (end-of-line 1)
- (unless (= (point) pos) (just-one-space) (backward-delete-char 1)))
- (org-maybe-renumber-ordered-list)
- (and checkbox (org-update-checkbox-count-maybe))
- t)))
+(defun org-at-item-timer-p ()
+ "Is point at a line starting a plain list item with a timer?"
+ (org-list-at-regexp-after-bullet-p
+ "\\([0-9]+:[0-9]+:[0-9]+\\)[ \t]+::[ \t]+"))
-;;; Checkboxes
+(defun org-at-item-description-p ()
+ "Is point at a description list item?"
+ (org-list-at-regexp-after-bullet-p "\\(\\S-.+\\)[ \t]+::[ \t]+"))
(defun org-at-item-checkbox-p ()
"Is point at a line starting a plain-list item with a checklet?"
- (and (org-at-item-p)
- (save-excursion
- (goto-char (match-end 0))
- (skip-chars-forward " \t")
- (looking-at "\\[[- X]\\]"))))
-
-(defun org-toggle-checkbox (&optional toggle-presence)
- "Toggle the checkbox in the current line.
-With prefix arg TOGGLE-PRESENCE, add or remove checkboxes.
-With double prefix, set checkbox to [-].
-When there is an active region, toggle status or presence of the checkbox
-in the first line, and make every item in the region have the same
-status or presence, respectively.
-If the cursor is in a headline, apply this to all checkbox items in the
-text below the heading."
- (interactive "P")
- (catch 'exit
- (let (beg end status first-present first-status blocked)
- (cond
- ((org-region-active-p)
- (setq beg (region-beginning) end (region-end)))
- ((org-on-heading-p)
- (setq beg (point) end (save-excursion (outline-next-heading) (point))))
- ((org-at-item-checkbox-p)
- (save-excursion
- (if (equal toggle-presence '(4))
- (progn
- (replace-match "")
- (goto-char (match-beginning 0))
- (just-one-space))
- (when (setq blocked (org-checkbox-blocked-p))
- (error "Checkbox blocked because of unchecked box in line %d"
- blocked))
- (replace-match
- (cond ((equal toggle-presence '(16)) "[-]")
- ((member (match-string 0) '("[ ]" "[-]")) "[X]")
- (t "[ ]"))
- t t)))
- (throw 'exit t))
- ((org-at-item-p)
- ;; add a checkbox
- (save-excursion
- (goto-char (match-end 0))
- (insert "[ ] "))
- (throw 'exit t))
- (t (error "Not at a checkbox or heading, and no active region")))
- (setq end (move-marker (make-marker) end))
- (save-excursion
- (goto-char beg)
- (setq first-present (org-at-item-checkbox-p)
- first-status
- (save-excursion
- (and (re-search-forward "[ \t]\\(\\[[ X]\\]\\)" end t)
- (equal (match-string 1) "[X]"))))
- (while (< (point) end)
- (if toggle-presence
- (cond
- ((and first-present (org-at-item-checkbox-p))
- (save-excursion
- (replace-match "")
- (goto-char (match-beginning 0))
- (just-one-space)))
- ((and (not first-present) (not (org-at-item-checkbox-p))
- (org-at-item-p))
- (save-excursion
- (goto-char (match-end 0))
- (insert "[ ] "))))
- (when (org-at-item-checkbox-p)
- (setq status (equal (match-string 0) "[X]"))
- (replace-match
- (if first-status "[ ]" "[X]") t t)))
- (beginning-of-line 2)))))
- (org-update-checkbox-count-maybe))
-
-(defun org-reset-checkbox-state-subtree ()
- "Reset all checkboxes in an entry subtree."
- (interactive "*")
- (save-restriction
- (save-excursion
- (org-narrow-to-subtree)
- (org-show-subtree)
- (goto-char (point-min))
- (let ((end (point-max)))
- (while (< (point) end)
- (when (org-at-item-checkbox-p)
- (replace-match "[ ]" t t))
- (beginning-of-line 2))))
- (org-update-checkbox-count-maybe)))
+ (org-list-at-regexp-after-bullet-p "\\(\\[[- X]\\]\\)[ \t]+"))
(defun org-checkbox-blocked-p ()
"Is the current checkbox blocked from for being checked now?
@@ -423,417 +840,621 @@ A checkbox is blocked if all of the following conditions are fulfilled:
(save-match-data
(save-excursion
(unless (org-at-item-checkbox-p) (throw 'exit nil))
- (when (equal (match-string 0) "[X]")
+ (when (equal (match-string 1) "[X]")
;; the box is already checked!
(throw 'exit nil))
(let ((end (point-at-bol)))
(condition-case nil (org-back-to-heading t)
(error (throw 'exit nil)))
(unless (org-entry-get nil "ORDERED") (throw 'exit nil))
- (if (re-search-forward "^[ \t]*[-+*0-9.)] \\[[- ]\\]" end t)
- (org-current-line)
- nil))))))
+ (when (org-search-forward-unenclosed
+ "^[ \t]*[-+*0-9.)]+[ \t]+\\(\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[[- ]\\]" end t)
+ (org-current-line)))))))
+
+;;; Navigate
+
+;; Every interactive navigation function is derived from a
+;; non-interactive one, which doesn't move point, assumes point is
+;; already in a list and doesn't compute list boundaries.
+
+;; If you plan to use more than one org-list function is some code,
+;; you should therefore first check if point is in a list with
+;; `org-in-item-p' or `org-at-item-p', then compute list boundaries
+;; with `org-list-top-point' and `org-list-bottom-point', and make use
+;; of non-interactive forms.
+
+(defun org-list-top-point ()
+ "Return point at the top level in a list.
+Assume point is in a list."
+ (let* ((prev-head (save-excursion (outline-previous-heading)))
+ (bound (if prev-head
+ (or (save-excursion
+ (let ((case-fold-search t))
+ (re-search-backward "^[ \t]*:END:" prev-head t)))
+ prev-head)
+ (point-min))))
+ (cond
+ ((eq org-list-ending-method 'regexp)
+ (org-list-top-point-with-regexp bound))
+ ((eq org-list-ending-method 'indent)
+ (org-list-top-point-with-indent bound))
+ (t (let ((top-re (org-list-top-point-with-regexp bound)))
+ (org-list-top-point-with-indent (or top-re bound)))))))
+
+(defun org-list-bottom-point ()
+ "Return point just before list ending.
+Assume point is in a list."
+ (let* ((next-head (save-excursion
+ (and (let ((outline-regexp org-outline-regexp))
+ ;; Use default regexp because folding
+ ;; changes OUTLINE-REGEXP.
+ (outline-next-heading)))))
+ (limit (or (save-excursion
+ (and (re-search-forward "^[ \t]*:END:" next-head t)
+ (point-at-bol)))
+ next-head
+ (point-max))))
+ (cond
+ ((eq org-list-ending-method 'regexp)
+ (org-list-bottom-point-with-regexp limit))
+ ((eq org-list-ending-method 'indent)
+ (org-list-bottom-point-with-indent limit))
+ (t (let ((bottom-re (org-list-bottom-point-with-regexp limit)))
+ (org-list-bottom-point-with-indent (or bottom-re limit)))))))
+
+(defun org-get-item-beginning ()
+ "Return position of current item beginning."
+ (save-excursion
+ ;; possibly match current line
+ (end-of-line)
+ (org-search-backward-unenclosed org-item-beginning-re nil t)
+ (point-at-bol)))
-(defvar org-checkbox-statistics-hook nil
- "Hook that is run whenever Org thinks checkbox statistics should be updated.
-This hook runs even if `org-provide-checkbox-statistics' is nil, to it can
-be used to implement alternative ways of collecting statistics information.")
+(defun org-beginning-of-item ()
+ "Go to the beginning of the current hand-formatted item.
+If the cursor is not in an item, throw an error."
+ (interactive)
+ (if (org-in-item-p)
+ (goto-char (org-get-item-beginning))
+ (error "Not in an item")))
-(defun org-update-checkbox-count-maybe ()
- "Update checkbox statistics unless turned off by user."
- (when org-provide-checkbox-statistics
- (org-update-checkbox-count))
- (run-hooks 'org-checkbox-statistics-hook))
+(defun org-get-beginning-of-list (top)
+ "Return position of the first item of the current list or sublist.
+TOP is the position at list beginning."
+ (save-excursion
+ (let (prev-p)
+ (while (setq prev-p (org-get-previous-item (point) top))
+ (goto-char prev-p))
+ (point-at-bol))))
-(defun org-update-checkbox-count (&optional all)
- "Update the checkbox statistics in the current section.
-This will find all statistic cookies like [57%] and [6/12] and update them
-with the current numbers. With optional prefix argument ALL, do this for
-the whole buffer."
- (interactive "P")
- (save-excursion
- (let* ((buffer-invisibility-spec (org-inhibit-invisibility)) ; Emacs 21
- (beg (condition-case nil
- (progn (org-back-to-heading) (point))
- (error (point-min))))
- (end (move-marker (make-marker)
- (progn (outline-next-heading) (point))))
- (re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)")
- (re-box "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[- X]\\]\\)")
- (re-find (concat re "\\|" re-box))
- beg-cookie end-cookie is-percent c-on c-off lim new
- eline curr-ind next-ind continue-from startsearch
- (recursive
- (or (not org-hierarchical-checkbox-statistics)
- (string-match "\\<recursive\\>"
- (or (ignore-errors
- (org-entry-get nil "COOKIE_DATA"))
- ""))))
- (cstat 0)
- )
- (when all
- (goto-char (point-min))
- (outline-next-heading)
- (setq beg (point) end (point-max)))
- (goto-char end)
- ;; find each statistics cookie
- (while (and (re-search-backward re-find beg t)
- (not (save-match-data
- (and (org-on-heading-p)
- (string-match "\\<todo\\>"
- (downcase
- (or (org-entry-get
- nil "COOKIE_DATA")
- "")))))))
- (setq beg-cookie (match-beginning 1)
- end-cookie (match-end 1)
- cstat (+ cstat (if end-cookie 1 0))
- startsearch (point-at-eol)
- continue-from (match-beginning 0)
- is-percent (match-beginning 2)
- lim (cond
- ((org-on-heading-p) (outline-next-heading) (point))
- ((org-at-item-p) (org-end-of-item) (point))
- (t nil))
- c-on 0
- c-off 0)
- (when lim
- ;; find first checkbox for this cookie and gather
- ;; statistics from all that are at this indentation level
- (goto-char startsearch)
- (if (re-search-forward re-box lim t)
- (progn
- (org-beginning-of-item)
- (setq curr-ind (org-get-indentation))
- (setq next-ind curr-ind)
- (while (and (bolp) (org-at-item-p)
- (if recursive
- (<= curr-ind next-ind)
- (= curr-ind next-ind)))
- (save-excursion (end-of-line) (setq eline (point)))
- (if (re-search-forward re-box eline t)
- (if (member (match-string 2) '("[ ]" "[-]"))
- (setq c-off (1+ c-off))
- (setq c-on (1+ c-on))))
- (if (not recursive)
- (org-end-of-item)
- (end-of-line)
- (when (re-search-forward org-list-beginning-re lim t)
- (beginning-of-line)))
- (setq next-ind (org-get-indentation)))))
- (goto-char continue-from)
- ;; update cookie
- (when end-cookie
- (setq new (if is-percent
- (format "[%d%%]" (/ (* 100 c-on) (max 1 (+ c-on c-off))))
- (format "[%d/%d]" c-on (+ c-on c-off))))
- (goto-char beg-cookie)
- (insert new)
- (delete-region (point) (+ (point) (- end-cookie beg-cookie))))
- ;; update items checkbox if it has one
- (when (org-at-item-p)
- (org-beginning-of-item)
- (when (and (> (+ c-on c-off) 0)
- (re-search-forward re-box (point-at-eol) t))
- (setq beg-cookie (match-beginning 2)
- end-cookie (match-end 2))
- (delete-region beg-cookie end-cookie)
- (goto-char beg-cookie)
- (cond ((= c-off 0) (insert "[X]"))
- ((= c-on 0) (insert "[ ]"))
- (t (insert "[-]")))
- )))
- (goto-char continue-from))
- (when (interactive-p)
- (message "Checkbox statistics updated %s (%d places)"
- (if all "in entire file" "in current outline entry") cstat)))))
+(defun org-beginning-of-item-list ()
+ "Go to the beginning item of the current list or sublist.
+Return an error if not in a list."
+ (interactive)
+ (if (org-in-item-p)
+ (goto-char (org-get-beginning-of-list (org-list-top-point)))
+ (error "Not in an item")))
-(defun org-get-checkbox-statistics-face ()
- "Select the face for checkbox statistics.
-The face will be `org-done' when all relevant boxes are checked. Otherwise
-it will be `org-todo'."
- (if (match-end 1)
- (if (equal (match-string 1) "100%")
- 'org-checkbox-statistics-done
- 'org-checkbox-statistics-todo)
- (if (and (> (match-end 2) (match-beginning 2))
- (equal (match-string 2) (match-string 3)))
- 'org-checkbox-statistics-done
- 'org-checkbox-statistics-todo)))
+(defun org-get-end-of-list (bottom)
+ "Return position at the end of the current list or sublist.
+BOTTOM is the position at list ending."
+ (save-excursion
+ (goto-char (org-get-item-beginning))
+ (let ((ind (org-get-indentation)))
+ (while (and (/= (point) bottom)
+ (>= (org-get-indentation) ind))
+ (org-search-forward-unenclosed org-item-beginning-re bottom 'move))
+ (if (= (point) bottom) bottom (point-at-bol)))))
-(defun org-beginning-of-item ()
- "Go to the beginning of the current hand-formatted item.
-If the cursor is not in an item, throw an error."
+(defun org-end-of-item-list ()
+ "Go to the end of the current list or sublist.
+If the cursor in not in an item, throw an error."
(interactive)
- (let ((pos (point))
- (limit (save-excursion
- (condition-case nil
- (progn
- (org-back-to-heading)
- (beginning-of-line 2) (point))
- (error (point-min)))))
- (ind-empty (if org-empty-line-terminates-plain-lists 0 10000))
- ind ind1)
- (if (org-at-item-p)
- (beginning-of-line 1)
- (beginning-of-line 1)
- (skip-chars-forward " \t")
- (setq ind (current-column))
- (if (catch 'exit
- (while t
- (beginning-of-line 0)
- (if (or (bobp) (< (point) limit)) (throw 'exit nil))
-
- (if (looking-at "[ \t]*$")
- (setq ind1 ind-empty)
- (skip-chars-forward " \t")
- (setq ind1 (current-column)))
- (if (< ind1 ind)
- (progn (beginning-of-line 1) (throw 'exit (org-at-item-p))))))
- nil
- (goto-char pos)
- (error "Not in an item")))))
+ (if (org-in-item-p)
+ (goto-char (org-get-end-of-list (org-list-bottom-point)))
+ (error "Not in an item")))
+
+(defun org-get-end-of-item (bottom)
+ "Return position at the end of the current item.
+BOTTOM is the position at list ending."
+ (or (org-get-next-item (point) bottom)
+ (org-get-end-of-list bottom)))
(defun org-end-of-item ()
"Go to the end of the current hand-formatted item.
If the cursor is not in an item, throw an error."
(interactive)
- (let* ((pos (point))
- ind1
- (ind-empty (if org-empty-line-terminates-plain-lists 0 10000))
- (limit (save-excursion (outline-next-heading) (point)))
- (ind (save-excursion
- (org-beginning-of-item)
- (skip-chars-forward " \t")
- (current-column)))
- (end (catch 'exit
- (while t
- (beginning-of-line 2)
- (if (eobp) (throw 'exit (point)))
- (if (>= (point) limit) (throw 'exit (point-at-bol)))
- (if (looking-at "[ \t]*$")
- (setq ind1 ind-empty)
- (skip-chars-forward " \t")
- (setq ind1 (current-column)))
- (if (<= ind1 ind)
- (throw 'exit (point-at-bol)))))))
- (if end
- (goto-char end)
- (goto-char pos)
- (error "Not in an item"))))
-
-(defun org-end-of-item-text-before-children ()
- "Move to the end of the item text, stops before the first child if any.
-Assumes that the cursor is in the first line of an item."
+ (if (org-in-item-p)
+ (goto-char (org-get-end-of-item (org-list-bottom-point)))
+ (error "Not in an item")))
+
+(defun org-end-of-item-or-at-child (bottom)
+ "Move to the end of the item, stops before the first child if any.
+BOTTOM is the position at list ending."
+ (end-of-line)
(goto-char
- (min (save-excursion (org-end-of-item) (point))
- (save-excursion
- (goto-char (point-at-eol))
- (if (re-search-forward (concat "^" (org-item-re t)) nil 'move)
- (match-beginning 0)
- (point-max))))))
+ (if (org-search-forward-unenclosed org-item-beginning-re bottom t)
+ (point-at-bol)
+ (org-get-end-of-item bottom))))
-(defun org-next-item ()
- "Move to the beginning of the next item in the current plain list.
-Error if not at a plain list, or if this is the last item in the list."
- (interactive)
- (let (ind ind1 (pos (point)))
- (org-beginning-of-item)
- (setq ind (org-get-indentation))
- (org-end-of-item)
- (setq ind1 (org-get-indentation))
- (unless (and (org-at-item-p) (= ind ind1))
- (goto-char pos)
- (error "On last item"))))
+(defun org-end-of-item-before-blank (bottom)
+ "Return point at end of item, before any blank line.
+Point returned is at eol.
+
+BOTTOM is the position at list ending."
+ (save-excursion
+ (goto-char (org-get-end-of-item bottom))
+ (skip-chars-backward " \r\t\n")
+ (point-at-eol)))
+
+(defun org-get-previous-item (pos limit)
+ "Return point of the previous item at the same level as POS.
+Stop searching at LIMIT. Return nil if no item is found."
+ (org-list-get-item-same-level
+ #'org-search-backward-unenclosed pos limit #'beginning-of-line))
(defun org-previous-item ()
- "Move to the beginning of the previous item in the current plain list.
-Error if not at a plain list, or if this is the first item in the list."
+ "Move to the beginning of the previous item.
+Item is at the same level in the current plain list. Error if not
+in a plain list, or if this is the first item in the list."
(interactive)
- (let (beg ind ind1 (pos (point)))
- (org-beginning-of-item)
- (setq beg (point))
- (setq ind (org-get-indentation))
- (goto-char beg)
- (catch 'exit
- (while t
- (beginning-of-line 0)
- (if (looking-at "[ \t]*$")
- nil
- (if (<= (setq ind1 (org-get-indentation)) ind)
- (throw 'exit t)))
- (if (bobp) (throw 'exit t))))
- (condition-case nil
- (if (or (not (org-at-item-p))
- (< ind1 (1- ind)))
- (error "")
- (org-beginning-of-item))
- (error (goto-char pos)
- (error "On first item")))))
-
-(defun org-first-list-item-p ()
- "Is this heading the first item in a plain list?"
- (unless (org-at-item-p)
- (error "Not at a plain list item"))
+ (if (not (org-in-item-p))
+ (error "Not in an item")
+ (let ((prev-p (org-get-previous-item (point) (org-list-top-point))))
+ (if prev-p (goto-char prev-p) (error "On first item")))))
+
+(defun org-get-next-item (pos limit)
+ "Return point of the next item at the same level as POS.
+Stop searching at LIMIT. Return nil if no item is found."
+ (org-list-get-item-same-level
+ #'org-search-forward-unenclosed pos limit #'end-of-line))
+
+(defun org-next-item ()
+ "Move to the beginning of the next item.
+Item is at the same level in the current plain list. Error if not
+in a plain list, or if this is the last item in the list."
+ (interactive)
+ (if (not (org-in-item-p))
+ (error "Not in an item")
+ (let ((next-p (org-get-next-item (point) (org-list-bottom-point))))
+ (if next-p (goto-char next-p) (error "On last item")))))
+
+;;; Manipulate
+
+(defun org-list-exchange-items (beg-A beg-B bottom)
+ "Swap item starting at BEG-A with item starting at BEG-B.
+Blank lines at the end of items are left in place. Assume BEG-A
+is lesser than BEG-B.
+
+BOTTOM is the position at list ending."
(save-excursion
- (org-beginning-of-item)
- (= (point) (save-excursion (org-beginning-of-item-list)))))
+ (let* ((end-of-item-no-blank
+ (lambda (pos)
+ (goto-char pos)
+ (goto-char (org-end-of-item-before-blank bottom))))
+ (end-A-no-blank (funcall end-of-item-no-blank beg-A))
+ (end-B-no-blank (funcall end-of-item-no-blank beg-B))
+ (body-A (buffer-substring beg-A end-A-no-blank))
+ (body-B (buffer-substring beg-B end-B-no-blank))
+ (between-A-no-blank-and-B (buffer-substring end-A-no-blank beg-B)))
+ (goto-char beg-A)
+ (delete-region beg-A end-B-no-blank)
+ (insert (concat body-B between-A-no-blank-and-B body-A)))))
(defun org-move-item-down ()
"Move the plain list item at point down, i.e. swap with following item.
Subitems (items with larger indentation) are considered part of the item,
so this really moves item trees."
(interactive)
- (let ((col (current-column))
- (pos (point))
- beg beg0 end end0 ind ind1 txt ne-end ne-beg)
- (org-beginning-of-item)
- (setq beg0 (point))
- (save-excursion
- (setq ne-beg (org-back-over-empty-lines))
- (setq beg (point)))
- (goto-char beg0)
- (setq ind (org-get-indentation))
- (org-end-of-item)
- (setq end0 (point))
- (setq ind1 (org-get-indentation))
- (setq ne-end (org-back-over-empty-lines))
- (setq end (point))
- (goto-char beg0)
- (when (and (org-first-list-item-p) (< ne-end ne-beg))
- ;; include less whitespace
- (save-excursion
- (goto-char beg)
- (forward-line (- ne-beg ne-end))
- (setq beg (point))))
- (goto-char end0)
- (if (and (org-at-item-p) (= ind ind1))
- (progn
- (org-end-of-item)
- (org-back-over-empty-lines)
- (setq txt (buffer-substring beg end))
- (save-excursion
- (delete-region beg end))
- (setq pos (point))
- (insert txt)
- (goto-char pos) (org-skip-whitespace)
- (org-maybe-renumber-ordered-list)
- (move-to-column col))
- (goto-char pos)
- (move-to-column col)
- (error "Cannot move this item further down"))))
-
-(defun org-move-item-up (arg)
+ (if (not (org-at-item-p))
+ (error "Not at an item")
+ (let* ((pos (point))
+ (col (current-column))
+ (bottom (org-list-bottom-point))
+ (actual-item (goto-char (org-get-item-beginning)))
+ (next-item (org-get-next-item (point) bottom)))
+ (if (not next-item)
+ (progn
+ (goto-char pos)
+ (error "Cannot move this item further down"))
+ (org-list-exchange-items actual-item next-item bottom)
+ (org-list-repair nil nil bottom)
+ (goto-char (org-get-next-item (point) bottom))
+ (move-to-column col)))))
+
+(defun org-move-item-up ()
"Move the plain list item at point up, i.e. swap with previous item.
Subitems (items with larger indentation) are considered part of the item,
so this really moves item trees."
- (interactive "p")
- (let ((col (current-column)) (pos (point))
- beg beg0 end ind ind1 txt
- ne-beg ne-ins ins-end)
- (org-beginning-of-item)
- (setq beg0 (point))
- (setq ind (org-get-indentation))
- (save-excursion
- (setq ne-beg (org-back-over-empty-lines))
- (setq beg (point)))
- (goto-char beg0)
- (org-end-of-item)
- (org-back-over-empty-lines)
- (setq end (point))
- (goto-char beg0)
- (catch 'exit
- (while t
- (beginning-of-line 0)
- (if (looking-at "[ \t]*$")
- (if org-empty-line-terminates-plain-lists
- (progn
- (goto-char pos)
- (error "Cannot move this item further up"))
- nil)
- (if (<= (setq ind1 (org-get-indentation)) ind)
- (throw 'exit t)))))
- (condition-case nil
- (org-beginning-of-item)
- (error (goto-char beg0)
- (move-to-column col)
- (error "Cannot move this item further up")))
- (setq ind1 (org-get-indentation))
- (if (and (org-at-item-p) (= ind ind1))
- (progn
- (setq ne-ins (org-back-over-empty-lines))
- (setq txt (buffer-substring beg end))
- (save-excursion
- (delete-region beg end))
- (setq pos (point))
- (insert txt)
- (setq ins-end (point))
- (goto-char pos) (org-skip-whitespace)
-
- (when (and (org-first-list-item-p) (> ne-ins ne-beg))
- ;; Move whitespace back to beginning
- (save-excursion
- (goto-char ins-end)
- (let ((kill-whole-line t))
- (kill-line (- ne-ins ne-beg)) (point)))
- (insert (make-string (- ne-ins ne-beg) ?\n)))
-
- (org-maybe-renumber-ordered-list)
- (move-to-column col))
- (goto-char pos)
- (move-to-column col)
- (error "Cannot move this item further up"))))
-
-(defun org-maybe-renumber-ordered-list ()
- "Renumber the ordered list at point if setup allows it.
-This tests the user option `org-auto-renumber-ordered-lists' before
-doing the renumbering."
(interactive)
- (when (and org-auto-renumber-ordered-lists
- (org-at-item-p))
- (if (match-beginning 3)
- (org-renumber-ordered-list 1)
- (org-fix-bullet-type))))
-
-(defun org-maybe-renumber-ordered-list-safe ()
- (condition-case nil
- (save-excursion
- (org-maybe-renumber-ordered-list))
- (error nil)))
+ (if (not (org-at-item-p))
+ (error "Not at an item")
+ (let* ((pos (point))
+ (col (current-column))
+ (top (org-list-top-point))
+ (bottom (org-list-bottom-point))
+ (actual-item (goto-char (org-get-item-beginning)))
+ (prev-item (org-get-previous-item (point) top)))
+ (if (not prev-item)
+ (progn
+ (goto-char pos)
+ (error "Cannot move this item further up"))
+ (org-list-exchange-items prev-item actual-item bottom)
+ (org-list-repair nil top bottom)
+ (move-to-column col)))))
-(defun org-cycle-list-bullet (&optional which)
- "Cycle through the different itemize/enumerate bullets.
-This cycle the entire list level through the sequence:
+(defun org-insert-item (&optional checkbox)
+ "Insert a new item at the current level.
+If cursor is before first character after bullet of the item, the
+new item will be created before the current one.
- `-' -> `+' -> `*' -> `1.' -> `1)'
+If CHECKBOX is non-nil, add a checkbox next to the bullet.
-If WHICH is a string, use that as the new bullet. If WHICH is an integer,
-0 means `-', 1 means `+' etc."
- (interactive "P")
- (org-preserve-lc
- (org-beginning-of-item-list)
- (org-at-item-p)
- (beginning-of-line 1)
- (let ((current (match-string 0))
- (prevp (eq which 'previous))
- new old)
- (setq new (cond
- ((and (numberp which)
- (nth (1- which) '("-" "+" "*" "1." "1)"))))
- ((string-match "-" current) (if prevp "1)" "+"))
- ((string-match "\\+" current)
- (if prevp "-" (if (looking-at "\\S-") "1." "*")))
- ((string-match "\\*" current) (if prevp "+" "1."))
- ((string-match "\\." current)
- (if prevp (if (looking-at "\\S-") "+" "*") "1)"))
- ((string-match ")" current) (if prevp "1." "-"))
- (t (error "This should not happen"))))
- (and (looking-at "\\([ \t]*\\)\\(\\S-+\\)")
- (setq old (match-string 2))
- (replace-match (concat "\\1" new)))
- (org-shift-item-indentation (- (length new) (length old)))
- (org-fix-bullet-type)
- (org-maybe-renumber-ordered-list))))
+Return t when things worked, nil when we are not in an item, or
+item is invisible."
+ (unless (or (not (org-in-item-p))
+ (save-excursion
+ (goto-char (org-get-item-beginning))
+ (org-invisible-p)))
+ (if (save-excursion
+ (goto-char (org-get-item-beginning))
+ (org-at-item-timer-p))
+ ;; Timer list: delegate to `org-timer-item'.
+ (progn (org-timer-item) t)
+ ;; if we're in a description list, ask for the new term.
+ (let ((desc-text (when (save-excursion
+ (and (goto-char (org-get-item-beginning))
+ (org-at-item-description-p)))
+ (concat (read-string "Term: ") " :: "))))
+ ;; Don't insert a checkbox if checkbox rule is applied and it
+ ;; is a description item.
+ (org-list-insert-item-generic
+ (point) (and checkbox
+ (or (not desc-text)
+ (not (cdr (assq 'checkbox org-list-automatic-rules)))))
+ desc-text)))))
+
+;;; Structures
+
+;; The idea behind structures is to avoid moving back and forth in the
+;; buffer on costly operations like indenting or fixing bullets.
+
+;; It achieves this by taking a snapshot of an interesting part of the
+;; list, in the shape of an alist, using `org-list-struct'.
+
+;; It then proceeds to changes directly on the alist, with the help of
+;; and `org-list-struct-origins'. When those are done,
+;; `org-list-struct-apply-struct' applies the changes to the buffer.
+
+(defun org-list-struct-assoc-at-point ()
+ "Return the structure association at point.
+It is a cons-cell whose key is point and values are indentation,
+bullet string and bullet counter, if any."
+ (save-excursion
+ (beginning-of-line)
+ (list (point-at-bol)
+ (org-get-indentation)
+ (progn
+ (looking-at "^[ \t]*\\([-+*0-9.)]+[ \t]+\\)")
+ (match-string 1))
+ (progn
+ (goto-char (match-end 0))
+ (and (looking-at "\\[@\\(?:start:\\)?\\([0-9]+\\)\\]")
+ (match-string 1))))))
+
+(defun org-list-struct (begin end top bottom &optional outdent)
+ "Return the structure containing the list between BEGIN and END.
+A structure is an alist where key is point of item and values
+are, in that order, indentation, bullet string and value of
+counter, if any. A structure contains every list and sublist that
+has items between BEGIN and END along with their common ancestor.
+If no such ancestor can be found, the function will add a virtual
+ancestor at position 0.
+
+TOP and BOTTOM are respectively the position of list beginning
+and list ending.
+
+If OUTDENT is non-nil, it will also grab all of the parent list
+and the grand-parent. Setting OUTDENT to t is mandatory when next
+change is an outdent."
+ (save-excursion
+ (let* (struct
+ (extend
+ (lambda (struct)
+ (let* ((ind-min (apply 'min (mapcar 'cadr struct)))
+ (begin (caar struct))
+ (end (caar (last struct)))
+ pre-list post-list)
+ (goto-char begin)
+ ;; Find beginning of most outdented list (min list)
+ (while (and (org-search-backward-unenclosed
+ org-item-beginning-re top t)
+ (>= (org-get-indentation) ind-min))
+ (setq pre-list (cons (org-list-struct-assoc-at-point)
+ pre-list)))
+ ;; Now get the parent. If none, add a virtual ancestor
+ (if (< (org-get-indentation) ind-min)
+ (setq pre-list (cons (org-list-struct-assoc-at-point)
+ pre-list))
+ (setq pre-list (cons (list 0 (org-get-indentation) "" nil)
+ pre-list)))
+ ;; Find end of min list
+ (goto-char end)
+ (end-of-line)
+ (while (and (org-search-forward-unenclosed
+ org-item-beginning-re bottom 'move)
+ (>= (org-get-indentation) ind-min))
+ (setq post-list (cons (org-list-struct-assoc-at-point)
+ post-list)))
+ ;; Is list is malformed? If some items are less
+ ;; indented that top-item, add them anyhow.
+ (when (and (= (caar pre-list) 0) (< (point) bottom))
+ (beginning-of-line)
+ (while (org-search-forward-unenclosed
+ org-item-beginning-re bottom t)
+ (setq post-list (cons (org-list-struct-assoc-at-point)
+ post-list))))
+ (append pre-list struct (reverse post-list))))))
+ ;; Here we start: first get the core zone...
+ (goto-char end)
+ (while (org-search-backward-unenclosed org-item-beginning-re begin t)
+ (setq struct (cons (org-list-struct-assoc-at-point) struct)))
+ ;; ... then, extend it to make it a structure...
+ (let ((extended (funcall extend struct)))
+ ;; ... twice when OUTDENT is non-nil and struct still can be
+ ;; extended
+ (if (and outdent (> (caar extended) 0))
+ (funcall extend extended)
+ extended)))))
+
+(defun org-list-struct-origins (struct)
+ "Return an alist where key is item's position and value parent's.
+STRUCT is the list's structure looked up."
+ (let* ((struct-rev (reverse struct))
+ (acc (list (cons (nth 1 (car struct)) 0)))
+ (prev-item (lambda (item)
+ (car (nth 1 (member (assq item struct) struct-rev)))))
+ (get-origins
+ (lambda (item)
+ (let* ((item-pos (car item))
+ (ind (nth 1 item))
+ (prev-ind (caar acc)))
+ (cond
+ ;; List closing.
+ ((> prev-ind ind)
+ (let ((current-origin (or (member (assq ind acc) acc)
+ ;; needed if top-point is
+ ;; not the most outdented
+ (last acc))))
+ (setq acc current-origin)
+ (cons item-pos (cdar acc))))
+ ;; New list
+ ((< prev-ind ind)
+ (let ((origin (funcall prev-item item-pos)))
+ (setq acc (cons (cons ind origin) acc))
+ (cons item-pos origin)))
+ ;; Current list going on
+ (t (cons item-pos (cdar acc))))))))
+ (cons '(0 . 0) (mapcar get-origins (cdr struct)))))
+
+(defun org-list-struct-get-parent (item struct origins)
+ "Return parent association of ITEM in STRUCT or nil.
+ORIGINS is the alist of parents. See `org-list-struct-origins'."
+ (let* ((parent-pos (cdr (assq (car item) origins))))
+ (when (> parent-pos 0) (assq parent-pos struct))))
+
+(defun org-list-struct-get-child (item struct)
+ "Return child association of ITEM in STRUCT or nil."
+ (let ((ind (nth 1 item))
+ (next-item (cadr (member item struct))))
+ (when (and next-item (> (nth 1 next-item) ind)) next-item)))
+
+(defun org-list-struct-fix-bul (struct origins)
+ "Verify and correct bullets for every association in STRUCT.
+ORIGINS is the alist of parents. See `org-list-struct-origins'.
+
+This function modifies STRUCT."
+ (let* (acc
+ (init-bul (lambda (item)
+ (let ((counter (nth 3 item))
+ (bullet (org-list-bullet-string (nth 2 item))))
+ (cond
+ ((and (string-match "[0-9]+" bullet) counter)
+ (replace-match counter nil nil bullet))
+ ((string-match "[0-9]+" bullet)
+ (replace-match "1" nil nil bullet))
+ (t bullet)))))
+ (set-bul (lambda (item bullet)
+ (setcdr item (list (nth 1 item) bullet (nth 3 item)))))
+ (get-bul (lambda (item bullet)
+ (let* ((counter (nth 3 item)))
+ (if (and counter (string-match "[0-9]+" bullet))
+ (replace-match counter nil nil bullet)
+ bullet))))
+ (fix-bul
+ (lambda (item) struct
+ (let* ((parent (cdr (assq (car item) origins)))
+ (orig-ref (assq parent acc)))
+ (if orig-ref
+ ;; Continuing previous list
+ (let* ((prev-bul (cdr orig-ref))
+ (new-bul (funcall get-bul item prev-bul)))
+ (setcdr orig-ref (org-list-inc-bullet-maybe new-bul))
+ (funcall set-bul item new-bul))
+ ;; A new list is starting
+ (let ((new-bul (funcall init-bul item)))
+ (funcall set-bul item new-bul)
+ (setq acc (cons (cons parent
+ (org-list-inc-bullet-maybe new-bul))
+ acc))))))))
+ (mapc fix-bul (cdr struct))))
+
+(defun org-list-struct-fix-ind (struct origins)
+ "Verify and correct indentation for every association in STRUCT.
+ORIGINS is the alist of parents. See `org-list-struct-origins'.
+
+This function modifies STRUCT."
+ (let* ((headless (cdr struct))
+ (ancestor (car struct))
+ (top-ind (+ (nth 1 ancestor) (length (nth 2 ancestor))))
+ (new-ind
+ (lambda (item)
+ (let* ((parent (org-list-struct-get-parent item headless origins)))
+ (if parent
+ ;; Indent like parent + length of parent's bullet
+ (setcdr item (cons (+ (length (nth 2 parent)) (nth 1 parent))
+ (cddr item)))
+ ;; If no parent, indent like top-point
+ (setcdr item (cons top-ind (cddr item))))))))
+ (mapc new-ind headless)))
+
+(defun org-list-struct-fix-struct (struct origins)
+ "Return STRUCT with correct bullets and indentation.
+ORIGINS is the alist of parents. See `org-list-struct-origins'.
+
+Only elements of STRUCT that have changed are returned."
+ (let ((old (copy-alist struct)))
+ (org-list-struct-fix-bul struct origins)
+ (org-list-struct-fix-ind struct origins)
+ (delq nil (mapcar (lambda (e) (when (not (equal (pop old) e)) e)) struct))))
+
+(defun org-list-struct-outdent (start end origins)
+ "Outdent items in a structure.
+Items are indented when their key is between START, included, and
+END, excluded.
+
+ORIGINS is the alist of parents. See `org-list-struct-origins'.
+
+STRUCT is the concerned structure."
+ (let* (acc
+ (out (lambda (cell)
+ (let* ((item (car cell))
+ (parent (cdr cell)))
+ (cond
+ ;; Item not yet in zone: keep association
+ ((< item start) cell)
+ ;; Item out of zone: follow associations in acc
+ ((>= item end)
+ (let ((convert (assq parent acc)))
+ (if convert (cons item (cdr convert)) cell)))
+ ;; Item has no parent: error
+ ((<= parent 0)
+ (error "Cannot outdent top-level items"))
+ ;; Parent is outdented: keep association
+ ((>= parent start)
+ (setq acc (cons (cons parent item) acc)) cell)
+ (t
+ ;; Parent isn't outdented: reparent to grand-parent
+ (let ((grand-parent (cdr (assq parent origins))))
+ (setq acc (cons (cons parent item) acc))
+ (cons item grand-parent))))))))
+ (mapcar out origins)))
+
+(defun org-list-struct-indent (start end origins struct)
+ "Indent items in a structure.
+Items are indented when their key is between START, included, and
+END, excluded.
+
+ORIGINS is the alist of parents. See `org-list-struct-origins'.
+
+STRUCT is the concerned structure. It may be modified if
+`org-list-demote-modify-bullet' matches bullets between START and
+END."
+ (let* (acc
+ (orig-rev (reverse origins))
+ (get-prev-item
+ (lambda (cell parent)
+ (car (rassq parent (cdr (memq cell orig-rev))))))
+ (set-assoc
+ (lambda (cell)
+ (setq acc (cons cell acc)) cell))
+ (change-bullet-maybe
+ (lambda (item)
+ (let* ((full-item (assq item struct))
+ (item-bul (org-trim (nth 2 full-item)))
+ (new-bul-p (cdr (assoc item-bul org-list-demote-modify-bullet))))
+ (when new-bul-p
+ ;; new bullet is stored without space to ensure item
+ ;; will be modified
+ (setcdr full-item
+ (list (nth 1 full-item)
+ new-bul-p
+ (nth 3 full-item)))))))
+ (ind
+ (lambda (cell)
+ (let* ((item (car cell))
+ (parent (cdr cell)))
+ (cond
+ ;; Item not yet in zone: keep association
+ ((< item start) cell)
+ ((>= item end)
+ ;; Item out of zone: follow associations in acc
+ (let ((convert (assq parent acc)))
+ (if convert (cons item (cdr convert)) cell)))
+ (t
+ ;; Item is in zone...
+ (let ((prev (funcall get-prev-item cell parent)))
+ ;; Check if bullet needs to be changed
+ (funcall change-bullet-maybe item)
+ (cond
+ ;; First item indented but not parent: error
+ ((and (or (not prev) (= prev 0)) (< parent start))
+ (error "Cannot indent the first item of a list"))
+ ;; First item and parent indented: keep same parent
+ ((or (not prev) (= prev 0))
+ (funcall set-assoc cell))
+ ;; Previous item not indented: reparent to it
+ ((< prev start)
+ (funcall set-assoc (cons item prev)))
+ ;; Previous item indented: reparent like it
+ (t
+ (funcall set-assoc (cons item
+ (cdr (assq prev acc)))))))))))))
+ (mapcar ind origins)))
+
+(defun org-list-struct-apply-struct (struct bottom)
+ "Apply modifications to list so it mirrors STRUCT.
+BOTTOM is position at list ending.
+
+Initial position is restored after the changes."
+ (let* ((pos (copy-marker (point)))
+ (ancestor (caar struct))
+ (modify
+ (lambda (item)
+ (goto-char (car item))
+ (let* ((new-ind (nth 1 item))
+ (new-bul (org-list-bullet-string (nth 2 item)))
+ (old-ind (org-get-indentation))
+ (old-bul (progn
+ (looking-at "[ \t]*\\(\\S-+[ \t]*\\)")
+ (match-string 1)))
+ (old-body-ind (+ (length old-bul) old-ind))
+ (new-body-ind (+ (length new-bul) new-ind)))
+ ;; 1. Shift item's body
+ (unless (= old-body-ind new-body-ind)
+ (org-shift-item-indentation
+ (- new-body-ind old-body-ind) bottom))
+ ;; 2. Replace bullet
+ (unless (equal new-bul old-bul)
+ (save-excursion
+ (looking-at "[ \t]*\\(\\S-+[ \t]*\\)")
+ (replace-match new-bul nil nil nil 1)))
+ ;; 3. Indent item to appropriate column
+ (unless (= new-ind old-ind)
+ (delete-region (point-at-bol)
+ (progn
+ (skip-chars-forward " \t")
+ (point)))
+ (indent-to new-ind)))))
+ ;; Remove ancestor if it is left.
+ (struct-to-apply (if (or (not ancestor) (= 0 ancestor))
+ (cdr struct)
+ struct)))
+ ;; Apply changes from bottom to top
+ (mapc modify (nreverse struct-to-apply))
+ (goto-char pos)))
+
+;;; Indentation
(defun org-get-string-indentation (s)
"What indentation has S due to SPACE and TAB at the beginning of the string?"
@@ -846,299 +1467,554 @@ If WHICH is a string, use that as the new bullet. If WHICH is an integer,
(t (throw 'exit t)))))
i))
-(defun org-renumber-ordered-list (arg)
- "Renumber an ordered plain list.
-Cursor needs to be in the first line of an item, the line that starts
-with something like \"1.\" or \"2)\"."
- (interactive "p")
- (unless (and (org-at-item-p)
- (match-beginning 3))
- (error "This is not an ordered list"))
- (let ((line (org-current-line))
- (col (current-column))
- (ind (org-get-string-indentation
- (buffer-substring (point-at-bol) (match-beginning 3))))
- ;; (term (substring (match-string 3) -1))
- ind1 (n (1- arg))
- fmt bobp old new delta)
- ;; find where this list begins
- (org-beginning-of-item-list)
- (setq bobp (bobp))
- (looking-at "[ \t]*[0-9]+\\([.)]\\)")
- (setq fmt (concat "%d" (or (match-string 1) ".")))
- (save-excursion
- (goto-char (match-end 0))
- (if (looking-at "[ \t]*\\[@start:\\([0-9]+\\)")
- (setq n (1- (string-to-number (match-string 1))))))
- (beginning-of-line 0)
- ;; walk forward and replace these numbers
- (catch 'exit
- (while t
- (catch 'next
- (if bobp (setq bobp nil) (beginning-of-line 2))
- (if (eobp) (throw 'exit nil))
- (if (looking-at "[ \t]*$") (throw 'next nil))
- (skip-chars-forward " \t") (setq ind1 (current-column))
- (if (> ind1 ind) (throw 'next t))
- (if (< ind1 ind) (throw 'exit t))
- (if (not (org-at-item-p)) (throw 'exit nil))
- (setq old (match-string 2))
- (delete-region (match-beginning 2) (match-end 2))
- (goto-char (match-beginning 2))
- (insert (setq new (format fmt (setq n (1+ n)))))
- (setq delta (- (length new) (length old)))
- (org-shift-item-indentation delta)
- (if (= (org-current-line) line) (setq col (+ col delta))))))
- (org-goto-line line)
- (org-move-to-column col)))
-
-(defvar org-suppress-item-indentation) ; dynamically scoped parameter
-(defun org-fix-bullet-type (&optional force-bullet)
- "Make sure all items in this list have the same bullet as the first item.
-Also, fix the indentation."
+(defun org-shift-item-indentation (delta bottom)
+ "Shift the indentation in current item by DELTA.
+Sub-items are not moved.
+
+BOTTOM is position at list ending."
+ (save-excursion
+ (let ((beg (point-at-bol))
+ (end (org-end-of-item-or-at-child bottom)))
+ (beginning-of-line (unless (eolp) 0))
+ (while (> (point) beg)
+ (when (looking-at "[ \t]*\\S-")
+ ;; this is not an empty line
+ (let ((i (org-get-indentation)))
+ (when (and (> i 0) (> (+ i delta) 0))
+ (indent-line-to (+ i delta)))))
+ (beginning-of-line 0)))))
+
+(defun org-outdent-item ()
+ "Outdent a local list item, but not its children.
+If a region is active, all items inside will be moved."
(interactive)
- (unless (org-at-item-p) (error "This is not a list"))
- (let ((line (org-current-line))
- (chars-from-eol (- (point-at-eol) (point)))
- (ind (current-indentation))
- ind1 bullet oldbullet)
- ;; find where this list begins
- (org-beginning-of-item-list)
- (beginning-of-line 1)
- ;; find out what the bullet type is
- (looking-at "[ \t]*\\(\\S-+\\)")
- (setq bullet (concat (or force-bullet (match-string 1)) " "))
- (if (and org-list-two-spaces-after-bullet-regexp
- (string-match org-list-two-spaces-after-bullet-regexp bullet))
- (setq bullet (concat bullet " ")))
- ;; walk forward and replace these numbers
- (beginning-of-line 0)
- (catch 'exit
- (while t
- (catch 'next
- (beginning-of-line 2)
- (if (eobp) (throw 'exit nil))
- (if (looking-at "[ \t]*$") (throw 'next nil))
- (skip-chars-forward " \t") (setq ind1 (current-column))
- (if (> ind1 ind) (throw 'next t))
- (if (< ind1 ind) (throw 'exit t))
- (if (not (org-at-item-p)) (throw 'exit nil))
- (skip-chars-forward " \t")
- (looking-at "\\S-+ *")
- (setq oldbullet (match-string 0))
- (unless (equal bullet oldbullet) (replace-match bullet))
- (org-shift-item-indentation (- (length bullet)
- (length oldbullet))))))
- (org-goto-line line)
- (goto-char (max (point-at-bol) (- (point-at-eol) chars-from-eol)))
- (if (string-match "[0-9]" bullet)
- (org-renumber-ordered-list 1))))
-
-(defun org-shift-item-indentation (delta)
- "Shift the indentation in current item by DELTA."
- (unless (org-bound-and-true-p org-suppress-item-indentation)
- (save-excursion
- (let ((beg (point-at-bol))
- (end (progn (org-end-of-item) (point)))
- i)
- (goto-char end)
- (beginning-of-line 0)
- (while (> (point) beg)
- (when (looking-at "[ \t]*\\S-")
- ;; this is not an empty line
- (setq i (org-get-indentation))
- (if (and (> i 0) (> (setq i (+ i delta)) 0))
- (indent-line-to i)))
- (beginning-of-line 0))))))
+ (org-list-indent-item-generic
+ -1 t (org-list-top-point) (org-list-bottom-point)))
-(defun org-beginning-of-item-list ()
- "Go to the beginning of the current item list.
-I.e. to the first item in this list."
+(defun org-indent-item ()
+ "Indent a local list item, but not its children.
+If a region is active, all items inside will be moved."
(interactive)
- (org-beginning-of-item)
- (let ((pos (point-at-bol))
- (ind (org-get-indentation))
- ind1)
- ;; find where this list begins
- (catch 'exit
- (while t
- (catch 'next
- (beginning-of-line 0)
- (if (looking-at "[ \t]*$")
- (throw (if (bobp) 'exit 'next) t))
- (skip-chars-forward " \t") (setq ind1 (current-column))
- (if (or (< ind1 ind)
- (and (= ind1 ind)
- (not (org-at-item-p)))
- (and (= (point-at-bol) (point-min))
- (setq pos (point-min))))
- (throw 'exit t)
- (when (org-at-item-p) (setq pos (point-at-bol)))))))
- (goto-char pos)))
+ (org-list-indent-item-generic
+ 1 t (org-list-top-point) (org-list-bottom-point)))
-(defun org-end-of-item-list ()
- "Go to the end of the current item list.
-I.e. to the text after the last item."
+(defun org-outdent-item-tree ()
+ "Outdent a local list item including its children.
+If a region is active, all items inside will be moved."
(interactive)
- (org-beginning-of-item)
- (let ((pos (point-at-bol))
+ (org-list-indent-item-generic
+ -1 nil (org-list-top-point) (org-list-bottom-point)))
+
+(defun org-indent-item-tree ()
+ "Indent a local list item including its children.
+If a region is active, all items inside will be moved."
+ (interactive)
+ (org-list-indent-item-generic
+ 1 nil (org-list-top-point) (org-list-bottom-point)))
+
+(defvar org-tab-ind-state)
+(defun org-cycle-item-indentation ()
+ "Cycle levels of indentation of an empty item.
+The first run indent the item, if applicable. Subsequents runs
+outdent it at meaningful levels in the list. When done, item is
+put back at its original position with its original bullet.
+
+Return t at each successful move."
+ (let ((org-adapt-indentation nil)
(ind (org-get-indentation))
- ind1)
- ;; find where this list begins
- (catch 'exit
- (while t
- (catch 'next
- (beginning-of-line 2)
- (if (looking-at "[ \t]*$")
- (if (eobp)
- (progn (setq pos (point)) (throw 'exit t))
- (throw 'next t)))
- (skip-chars-forward " \t") (setq ind1 (current-column))
- (if (or (< ind1 ind)
- (and (= ind1 ind)
- (not (org-at-item-p)))
- (eobp))
- (progn
- (setq pos (point-at-bol))
- (throw 'exit t))))))
- (goto-char pos)))
+ (bottom (and (org-at-item-p) (org-list-bottom-point))))
+ (when (and (or (org-at-item-description-p)
+ (org-at-item-checkbox-p)
+ (org-at-item-p))
+ ;; Check that item is really empty
+ (>= (match-end 0) (save-excursion
+ (org-end-of-item-or-at-child bottom)
+ (skip-chars-backward " \r\t\n")
+ (point))))
+ (setq this-command 'org-cycle-item-indentation)
+ (let ((top (org-list-top-point)))
+ ;; When in the middle of the cycle, try to outdent first. If it
+ ;; fails, and point is still at initial position, indent. Else,
+ ;; go back to original position.
+ (if (eq last-command 'org-cycle-item-indentation)
+ (cond
+ ((ignore-errors (org-list-indent-item-generic -1 t top bottom)))
+ ((and (= (org-get-indentation) (car org-tab-ind-state))
+ (ignore-errors
+ (org-list-indent-item-generic 1 t top bottom))))
+ (t (back-to-indentation)
+ (indent-to-column (car org-tab-ind-state))
+ (end-of-line)
+ (org-list-repair (cdr org-tab-ind-state))
+ ;; Break cycle
+ (setq this-command 'identity)))
+ ;; If a cycle is starting, remember indentation and bullet,
+ ;; then try to indent. If it fails, try to outdent.
+ (setq org-tab-ind-state (cons ind (org-get-bullet)))
+ (cond
+ ((ignore-errors (org-list-indent-item-generic 1 t top bottom)))
+ ((ignore-errors (org-list-indent-item-generic -1 t top bottom)))
+ (t (error "Cannot move item")))))
+ t)))
+;;; Bullets
-(defvar org-last-indent-begin-marker (make-marker))
-(defvar org-last-indent-end-marker (make-marker))
+(defun org-get-bullet ()
+ "Return the bullet of the item at point.
+Assume cursor is at an item."
+ (save-excursion
+ (beginning-of-line)
+ (and (looking-at "[ \t]*\\(\\S-+\\)") (match-string 1))))
+
+(defun org-list-bullet-string (bullet)
+ "Return BULLET with the correct number of whitespaces.
+It determines the number of whitespaces to append by looking at
+`org-list-two-spaces-after-bullet-regexp'."
+ (save-match-data
+ (string-match "\\S-+\\([ \t]*\\)" bullet)
+ (replace-match
+ (save-match-data
+ (concat
+ " "
+ ;; Do we need to concat another white space ?
+ (when (and org-list-two-spaces-after-bullet-regexp
+ (string-match org-list-two-spaces-after-bullet-regexp bullet))
+ " ")))
+ nil nil bullet 1)))
+
+(defun org-list-inc-bullet-maybe (bullet)
+ "Increment BULLET if applicable."
+ (if (string-match "[0-9]+" bullet)
+ (replace-match
+ (number-to-string (1+ (string-to-number (match-string 0 bullet))))
+ nil nil bullet)
+ bullet))
+
+(defun org-list-repair (&optional force-bullet top bottom)
+ "Make sure all items are correctly indented, with the right bullet.
+This function scans the list at point, along with any sublist.
+
+If FORCE-BULLET is a string, ensure all items in list share this
+bullet, or a logical successor in the case of an ordered list.
+
+When non-nil, TOP and BOTTOM specify respectively position of
+list beginning and list ending.
+
+Item's body is not indented, only shifted with the bullet."
+ (interactive)
+ (unless (org-at-item-p) (error "This is not a list"))
+ (let* ((bottom (or bottom (org-list-bottom-point)))
+ (struct (org-list-struct
+ (point-at-bol) (point-at-eol)
+ (or top (org-list-top-point)) bottom))
+ (origins (org-list-struct-origins struct))
+ fixed-struct)
+ (if (stringp force-bullet)
+ (let ((begin (nth 1 struct)))
+ (setcdr begin (list (nth 1 begin)
+ (org-list-bullet-string force-bullet)
+ (nth 3 begin)))
+ (setq fixed-struct
+ (cons begin (org-list-struct-fix-struct struct origins))))
+ (setq fixed-struct (org-list-struct-fix-struct struct origins)))
+ (org-list-struct-apply-struct fixed-struct bottom)))
-(defun org-outdent-item (arg)
- "Outdent a local list item, but not its children."
- (interactive "p")
- (org-indent-item-tree (- arg) 'no-subtree))
+(defun org-cycle-list-bullet (&optional which)
+ "Cycle through the different itemize/enumerate bullets.
+This cycle the entire list level through the sequence:
-(defun org-indent-item (arg)
- "Indent a local list item, but not its children."
- (interactive "p")
- (org-indent-item-tree arg 'no-subtree))
+ `-' -> `+' -> `*' -> `1.' -> `1)'
-(defun org-outdent-item-tree (arg &optional no-subtree)
- "Outdent a local list item including its children.
-If NO-SUBTREE is set, only outdent the item itself, not its children."
- (interactive "p")
- (org-indent-item-tree (- arg) no-subtree))
+If WHICH is a valid string, use that as the new bullet. If WHICH
+is an integer, 0 means `-', 1 means `+' etc. If WHICH is
+'previous, cycle backwards."
+ (interactive "P")
+ (let* ((top (org-list-top-point))
+ (bullet (save-excursion
+ (goto-char (org-get-beginning-of-list top))
+ (org-get-bullet)))
+ (current (cond
+ ((string-match "\\." bullet) "1.")
+ ((string-match ")" bullet) "1)")
+ (t bullet)))
+ (bullet-rule-p (cdr (assq 'bullet org-list-automatic-rules)))
+ (bullet-list (append '("-" "+" )
+ ;; *-bullets are not allowed at column 0
+ (unless (and bullet-rule-p
+ (looking-at "\\S-")) '("*"))
+ ;; Description items cannot be numbered
+ (unless (and bullet-rule-p
+ (or (eq org-plain-list-ordered-item-terminator ?.)
+ (org-at-item-description-p))) '("1)"))
+ (unless (and bullet-rule-p
+ (or (eq org-plain-list-ordered-item-terminator ?\))
+ (org-at-item-description-p))) '("1."))))
+ (len (length bullet-list))
+ (item-index (- len (length (member current bullet-list))))
+ (get-value (lambda (index) (nth (mod index len) bullet-list)))
+ (new (cond
+ ((member which bullet-list) which)
+ ((numberp which) (funcall get-value which))
+ ((eq 'previous which) (funcall get-value (1- item-index)))
+ (t (funcall get-value (1+ item-index))))))
+ (org-list-repair new top)))
-(defun org-indent-item-tree (arg &optional no-subtree)
- "Indent a local list item including its children.
-If NO-SUBTREE is set, only indent the item itself, not its children."
- (interactive "p")
- (and (org-region-active-p) (org-cursor-to-region-beginning))
- (unless (org-at-item-p)
- (error "Not on an item"))
- (let (beg end ind ind1 ind-bul delta ind-down ind-up firstp)
- (setq firstp (org-first-list-item-p))
+;;; Checkboxes
+
+(defun org-toggle-checkbox (&optional toggle-presence)
+ "Toggle the checkbox in the current line.
+With prefix arg TOGGLE-PRESENCE, add or remove checkboxes. With
+double prefix, set checkbox to [-].
+
+When there is an active region, toggle status or presence of the
+first checkbox there, and make every item inside have the
+same status or presence, respectively.
+
+If the cursor is in a headline, apply this to all checkbox items
+in the text below the heading, taking as reference the first item
+in subtree, ignoring drawers."
+ (interactive "P")
+ ;; Bounds is a list of type (beg end single-p) where single-p is t
+ ;; when `org-toggle-checkbox' is applied to a single item. Only
+ ;; toggles on single items will return errors.
+ (let* ((bounds
+ (cond
+ ((org-region-active-p)
+ (let ((rbeg (region-beginning))
+ (rend (region-end)))
+ (save-excursion
+ (goto-char rbeg)
+ (if (org-search-forward-unenclosed org-item-beginning-re rend 'move)
+ (list (point-at-bol) rend nil)
+ (error "No item in region")))))
+ ((org-on-heading-p)
+ ;; In this case, reference line is the first item in
+ ;; subtree outside drawers
+ (let ((pos (point))
+ (limit (save-excursion (outline-next-heading) (point))))
+ (save-excursion
+ (goto-char limit)
+ (org-search-backward-unenclosed ":END:" pos 'move)
+ (org-search-forward-unenclosed
+ org-item-beginning-re limit 'move)
+ (list (point) limit nil))))
+ ((org-at-item-p)
+ (list (point-at-bol) (point-at-eol) t))
+ (t (error "Not at an item or heading, and no active region"))))
+ (beg (car bounds))
+ ;; marker is needed because deleting or inserting checkboxes
+ ;; will change bottom point
+ (end (copy-marker (nth 1 bounds)))
+ (single-p (nth 2 bounds))
+ (ref-presence (save-excursion
+ (goto-char beg)
+ (org-at-item-checkbox-p)))
+ (ref-status (equal (match-string 1) "[X]"))
+ (act-on-item
+ (lambda (ref-pres ref-stat)
+ (if (equal toggle-presence '(4))
+ (cond
+ ((and ref-pres (org-at-item-checkbox-p))
+ (replace-match ""))
+ ((and (not ref-pres)
+ (not (org-at-item-checkbox-p))
+ (org-at-item-p))
+ (goto-char (match-end 0))
+ ;; Ignore counter, if any
+ (when (looking-at "\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?")
+ (goto-char (match-end 0)))
+ (let ((desc-p (and (org-at-item-description-p)
+ (cdr (assq 'checkbox org-list-automatic-rules)))))
+ (cond
+ ((and single-p desc-p)
+ (error "Cannot add a checkbox in a description list"))
+ ((not desc-p) (insert "[ ] "))))))
+ (let ((blocked (org-checkbox-blocked-p)))
+ (cond
+ ((and blocked single-p)
+ (error "Checkbox blocked because of unchecked box in line %d" blocked))
+ (blocked nil)
+ ((org-at-item-checkbox-p)
+ (replace-match
+ (cond ((equal toggle-presence '(16)) "[-]")
+ (ref-stat "[ ]")
+ (t "[X]"))
+ t t nil 1))))))))
(save-excursion
- (setq end (and (org-region-active-p) (region-end)))
- (if (and (memq last-command '(org-shiftmetaright org-shiftmetaleft))
- (memq this-command '(org-shiftmetaright org-shiftmetaleft)))
- (setq beg org-last-indent-begin-marker
- end org-last-indent-end-marker)
- (org-beginning-of-item)
- (setq beg (move-marker org-last-indent-begin-marker (point)))
- (if no-subtree
- (org-end-of-item-text-before-children)
- (org-end-of-item))
- (setq end (move-marker org-last-indent-end-marker (or end (point)))))
(goto-char beg)
- (setq ind-bul (org-item-indent-positions)
- ind (caar ind-bul)
- ind-down (car (nth 2 ind-bul))
- ind-up (car (nth 1 ind-bul))
- delta (if (> arg 0)
- (if ind-down (- ind-down ind) 2)
- (if ind-up (- ind-up ind) -2)))
- (if (< (+ delta ind) 0) (error "Cannot outdent beyond margin"))
(while (< (point) end)
- (beginning-of-line 1)
- (skip-chars-forward " \t") (setq ind1 (current-column))
- (delete-region (point-at-bol) (point))
- (or (eolp) (org-indent-to-column (+ ind1 delta)))
- (beginning-of-line 2)))
- (org-fix-bullet-type
- (and (> arg 0)
- (not firstp)
- (cdr (assoc (cdr (nth 0 ind-bul)) org-list-demote-modify-bullet))))
- (org-maybe-renumber-ordered-list-safe)
- (save-excursion
- (beginning-of-line 0)
- (condition-case nil (org-beginning-of-item) (error nil))
- (org-maybe-renumber-ordered-list-safe))))
-
-(defun org-item-indent-positions ()
- "Return indentation for plain list items.
-This returns a list with three values: The current indentation, the
-parent indentation and the indentation a child should have.
-Assumes cursor in item line."
- (let* ((bolpos (point-at-bol))
- (ind (org-get-indentation))
- (bullet (org-get-bullet))
- ind-down ind-up bullet-up bullet-down pos)
- (save-excursion
- (org-beginning-of-item-list)
- (skip-chars-backward "\n\r \t")
- (when (org-in-item-p)
- (org-beginning-of-item)
- (setq ind-up (org-get-indentation))
- (setq bullet-up (org-get-bullet))))
- (setq pos (point))
+ (funcall act-on-item ref-presence ref-status)
+ (org-search-forward-unenclosed org-item-beginning-re end 'move)))
+ (org-update-checkbox-count-maybe)))
+
+(defun org-reset-checkbox-state-subtree ()
+ "Reset all checkboxes in an entry subtree."
+ (interactive "*")
+ (save-restriction
(save-excursion
- (cond
- ((and (condition-case nil (progn (org-previous-item) t)
- (error nil))
- (or (forward-char 1) t)
- (re-search-forward "^\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)" bolpos t))
- (setq ind-down (org-get-indentation)
- bullet-down (org-get-bullet)))
- ((and (goto-char pos)
- (org-at-item-p))
- (goto-char (match-end 0))
- (skip-chars-forward " \t")
- (setq ind-down (current-column)
- bullet-down (org-get-bullet)))))
- (if (and bullet-down (string-match "\\`[0-9]+\\(\\.\\|)\\)\\'" bullet-down))
- (setq bullet-down (concat "1" (match-string 1 bullet-down))))
- (if (and bullet-up (string-match "\\`[0-9]+\\(\\.\\|)\\)\\'" bullet-up))
- (setq bullet-up (concat "1" (match-string 1 bullet-up))))
- (if (and bullet (string-match "\\`[0-9]+\\(\\.\\|)\\)\\'" bullet))
- (setq bullet (concat "1" (match-string 1 bullet))))
- (list (cons ind bullet)
- (cons ind-up bullet-up)
- (cons ind-down bullet-down))))
-
-(defvar org-tab-ind-state) ; defined in org.el
-(defun org-cycle-item-indentation ()
- (let ((org-suppress-item-indentation t)
- (org-adapt-indentation nil))
- (cond
- ((and (looking-at "[ \t]*$")
- (org-looking-back "^\\([ \t]*\\)\\([-+*]\\|[0-9]+[).]\\)[ \t]+"))
- (setq this-command 'org-cycle-item-indentation)
- (if (eq last-command 'org-cycle-item-indentation)
- (condition-case nil
- (progn (org-outdent-item 1)
- (if (equal org-tab-ind-state (org-get-indentation))
- (org-outdent-item 1))
- (end-of-line 1))
- (error
- (progn
- (while (< (org-get-indentation) org-tab-ind-state)
- (progn (org-indent-item 1) (end-of-line 1)))
- (setq this-command 'org-cycle))))
- (setq org-tab-ind-state (org-get-indentation))
- (org-indent-item 1))
- t))))
+ (org-narrow-to-subtree)
+ (org-show-subtree)
+ (goto-char (point-min))
+ (let ((end (point-max)))
+ (while (< (point) end)
+ (when (org-at-item-checkbox-p)
+ (replace-match "[ ]" t t nil 1))
+ (beginning-of-line 2))))
+ (org-update-checkbox-count-maybe)))
-(defun org-get-bullet ()
+(defvar org-checkbox-statistics-hook nil
+ "Hook that is run whenever Org thinks checkbox statistics should be updated.
+This hook runs even if checkbox rule in
+`org-list-automatic-rules' does not apply, so it can be used to
+implement alternative ways of collecting statistics
+information.")
+
+(defun org-update-checkbox-count-maybe ()
+ "Update checkbox statistics unless turned off by user."
+ (when (cdr (assq 'checkbox org-list-automatic-rules))
+ (org-update-checkbox-count))
+ (run-hooks 'org-checkbox-statistics-hook))
+
+(defun org-update-checkbox-count (&optional all)
+ "Update the checkbox statistics in the current section.
+This will find all statistic cookies like [57%] and [6/12] and update them
+with the current numbers. With optional prefix argument ALL, do this for
+the whole buffer."
+ (interactive "P")
(save-excursion
- (goto-char (point-at-bol))
- (and (looking-at
- "^\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\(\\*\\)\\)\\( \\|$\\)")
- (or (match-string 2) (match-string 4)))))
+ (let ((cstat 0))
+ (catch 'exit
+ (while t
+ (let* ((buffer-invisibility-spec (org-inhibit-invisibility)) ; Emacs 21
+ (beg (condition-case nil
+ (progn (org-back-to-heading) (point))
+ (error (point-min))))
+ (end (copy-marker (save-excursion
+ (outline-next-heading) (point))))
+ (re-cookie "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)")
+ (re-box "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\)[ \t]+\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\(\\[[- X]\\]\\)")
+ beg-cookie end-cookie is-percent c-on c-off lim new
+ curr-ind next-ind continue-from startsearch list-beg list-end
+ (recursive
+ (or (not org-hierarchical-checkbox-statistics)
+ (string-match "\\<recursive\\>"
+ (or (ignore-errors
+ (org-entry-get nil "COOKIE_DATA"))
+ "")))))
+ (goto-char end)
+ ;; find each statistics cookie
+ (while (and (org-search-backward-unenclosed re-cookie beg 'move)
+ (not (save-match-data
+ (and (org-on-heading-p)
+ (string-match "\\<todo\\>"
+ (downcase
+ (or (org-entry-get
+ nil "COOKIE_DATA")
+ "")))))))
+ (setq beg-cookie (match-beginning 1)
+ end-cookie (match-end 1)
+ cstat (+ cstat (if end-cookie 1 0))
+ startsearch (point-at-eol)
+ continue-from (match-beginning 0)
+ is-percent (match-beginning 2)
+ lim (cond
+ ((org-on-heading-p) (outline-next-heading) (point))
+ ;; Ensure many cookies in the same list won't imply
+ ;; computing list boundaries as many times.
+ ((org-at-item-p)
+ (unless (and list-beg (>= (point) list-beg))
+ (setq list-beg (org-list-top-point)
+ list-end (copy-marker
+ (org-list-bottom-point))))
+ (org-get-end-of-item list-end))
+ (t nil))
+ c-on 0
+ c-off 0)
+ (when lim
+ ;; find first checkbox for this cookie and gather
+ ;; statistics from all that are at this indentation level
+ (goto-char startsearch)
+ (if (org-search-forward-unenclosed re-box lim t)
+ (progn
+ (beginning-of-line)
+ (setq curr-ind (org-get-indentation))
+ (setq next-ind curr-ind)
+ (while (and (bolp) (org-at-item-p)
+ (if recursive
+ (<= curr-ind next-ind)
+ (= curr-ind next-ind)))
+ (when (org-at-item-checkbox-p)
+ (if (member (match-string 1) '("[ ]" "[-]"))
+ (setq c-off (1+ c-off))
+ (setq c-on (1+ c-on))))
+ (if (not recursive)
+ ;; org-get-next-item goes through list-enders
+ ;; with proper limit.
+ (goto-char (or (org-get-next-item (point) lim) lim))
+ (end-of-line)
+ (when (org-search-forward-unenclosed
+ org-item-beginning-re lim t)
+ (beginning-of-line)))
+ (setq next-ind (org-get-indentation)))))
+ (goto-char continue-from)
+ ;; update cookie
+ (when end-cookie
+ (setq new (if is-percent
+ (format "[%d%%]" (/ (* 100 c-on)
+ (max 1 (+ c-on c-off))))
+ (format "[%d/%d]" c-on (+ c-on c-off))))
+ (goto-char beg-cookie)
+ (insert new)
+ (delete-region (point) (+ (point) (- end-cookie beg-cookie))))
+ ;; update items checkbox if it has one
+ (when (and (org-at-item-checkbox-p)
+ (> (+ c-on c-off) 0))
+ (setq beg-cookie (match-beginning 1)
+ end-cookie (match-end 1))
+ (delete-region beg-cookie end-cookie)
+ (goto-char beg-cookie)
+ (cond ((= c-off 0) (insert "[X]"))
+ ((= c-on 0) (insert "[ ]"))
+ (t (insert "[-]")))))
+ (goto-char continue-from)))
+ (unless (and all (outline-next-heading)) (throw 'exit nil))))
+ (when (interactive-p)
+ (message "Checkbox statistics updated %s (%d places)"
+ (if all "in entire file" "in current outline entry") cstat)))))
+
+(defun org-get-checkbox-statistics-face ()
+ "Select the face for checkbox statistics.
+The face will be `org-done' when all relevant boxes are checked.
+Otherwise it will be `org-todo'."
+ (if (match-end 1)
+ (if (equal (match-string 1) "100%")
+ 'org-checkbox-statistics-done
+ 'org-checkbox-statistics-todo)
+ (if (and (> (match-end 2) (match-beginning 2))
+ (equal (match-string 2) (match-string 3)))
+ 'org-checkbox-statistics-done
+ 'org-checkbox-statistics-todo)))
+
+;;; Misc Tools
+
+(defun org-apply-on-list (function init-value &rest args)
+ "Call FUNCTION on each item of the list at point.
+FUNCTION must be called with at least one argument: INIT-VALUE,
+that will contain the value returned by the function at the
+previous item, plus ARGS extra arguments.
+
+As an example, (org-apply-on-list (lambda (result) (1+ result)) 0)
+will return the number of items in the current list.
+
+Sublists of the list are skipped. Cursor is always at the
+beginning of the item."
+ (let* ((pos (copy-marker (point)))
+ (end (copy-marker (org-list-bottom-point)))
+ (next-p (copy-marker (org-get-beginning-of-list (org-list-top-point))))
+ (value init-value))
+ (while (< next-p end)
+ (goto-char next-p)
+ (set-marker next-p (or (org-get-next-item (point) end) end))
+ (setq value (apply function value args)))
+ (goto-char pos)
+ value))
+
+(defun org-sort-list (&optional with-case sorting-type getkey-func compare-func)
+ "Sort plain list items.
+The cursor may be at any item of the list that should be sorted.
+Sublists are not sorted. Checkboxes, if any, are ignored.
+
+Sorting can be alphabetically, numerically, by date/time as given by
+a time stamp, by a property or by priority.
+
+Comparing entries ignores case by default. However, with an
+optional argument WITH-CASE, the sorting considers case as well.
+
+The command prompts for the sorting type unless it has been given
+to the function through the SORTING-TYPE argument, which needs to
+be a character, \(?n ?N ?a ?A ?t ?T ?f ?F). Here is the precise
+meaning of each character:
+
+n Numerically, by converting the beginning of the item to a number.
+a Alphabetically. Only the first line of item is checked.
+t By date/time, either the first active time stamp in the entry, if
+ any, or by the first inactive one. In a timer list, sort the timers.
+
+Capital letters will reverse the sort order.
+
+If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies a
+function to be called with point at the beginning of the record.
+It must return either a string or a number that should serve as
+the sorting key for that record. It will then use COMPARE-FUNC to
+compare entries."
+ (interactive "P")
+ (let* ((case-func (if with-case 'identity 'downcase))
+ (top (org-list-top-point))
+ (bottom (org-list-bottom-point))
+ (start (org-get-beginning-of-list top))
+ (end (org-get-end-of-list bottom))
+ (sorting-type
+ (progn
+ (message
+ "Sort plain list: [a]lpha [n]umeric [t]ime [f]unc A/N/T/F means reversed:")
+ (read-char-exclusive)))
+ (getkey-func (and (= (downcase sorting-type) ?f)
+ (org-icompleting-read "Sort using function: "
+ obarray 'fboundp t nil nil)
+ (intern getkey-func))))
+ (message "Sorting items...")
+ (save-restriction
+ (narrow-to-region start end)
+ (let* ((dcst (downcase sorting-type))
+ (case-fold-search nil)
+ (now (current-time))
+ (sort-func (cond
+ ((= dcst ?a) 'string<)
+ ((= dcst ?f) compare-func)
+ ((= dcst ?t) '<)
+ (t nil)))
+ (begin-record (lambda ()
+ (skip-chars-forward " \r\t\n")
+ (beginning-of-line)))
+ (end-record (lambda ()
+ (goto-char (org-end-of-item-before-blank end))))
+ (value-to-sort
+ (lambda ()
+ (when (looking-at "[ \t]*[-+*0-9.)]+\\([ \t]+\\[[- X]\\]\\)?[ \t]+")
+ (cond
+ ((= dcst ?n)
+ (string-to-number (buffer-substring (match-end 0)
+ (point-at-eol))))
+ ((= dcst ?a)
+ (buffer-substring (match-end 0) (point-at-eol)))
+ ((= dcst ?t)
+ (cond
+ ;; If it is a timer list, convert timer to seconds
+ ((org-at-item-timer-p)
+ (org-timer-hms-to-secs (match-string 1)))
+ ((or (org-search-forward-unenclosed org-ts-regexp
+ (point-at-eol) t)
+ (org-search-forward-unenclosed org-ts-regexp-both
+ (point-at-eol) t))
+ (org-time-string-to-seconds (match-string 0)))
+ (t (org-float-time now))))
+ ((= dcst ?f)
+ (if getkey-func
+ (let ((value (funcall getkey-func)))
+ (if (stringp value)
+ (funcall case-func value)
+ value))
+ (error "Invalid key function `%s'" getkey-func)))
+ (t (error "Invalid sorting type `%c'" sorting-type)))))))
+ (sort-subr (/= dcst sorting-type)
+ begin-record
+ end-record
+ value-to-sort
+ nil
+ sort-func)
+ (org-list-repair nil top bottom)
+ (run-hooks 'org-after-sorting-entries-or-items-hook)
+ (message "Sorting items...done")))))
;;; Send and receive lists
@@ -1146,85 +2022,55 @@ Assumes cursor in item line."
"Parse the list at point and maybe DELETE it.
Return a list containing first level items as strings and
sublevels as a list of strings."
- (let* ((item-beginning (org-list-item-beginning))
- (start (car item-beginning))
- (end (save-excursion
- (goto-char (org-list-end (cdr item-beginning)))
- (org-back-over-empty-lines)
- (point)))
+ (let* ((start (goto-char (org-list-top-point)))
+ (end (org-list-bottom-point))
output itemsep ltype)
- (while (re-search-forward org-list-beginning-re end t)
- (goto-char (match-beginning 3))
- (save-match-data
- (cond ((string-match "[0-9]" (match-string 2))
- (setq itemsep "[0-9]+\\(?:\\.\\|)\\)"
- ltype 'ordered))
- ((string-match "^.*::" (match-string 0))
- (setq itemsep "[-+]" ltype 'descriptive))
- (t (setq itemsep "[-+]" ltype 'unordered))))
- (let* ((indent1 (match-string 1))
- (nextitem (save-excursion
- (save-match-data
- (or (and (re-search-forward
- (concat "^" indent1 itemsep " *?") end t)
- (match-beginning 0)) end))))
- (item (buffer-substring
- (point)
- (or (and (org-re-search-forward-unprotected
- org-list-beginning-re end t)
- (goto-char (match-beginning 0)))
- (goto-char end))))
- (nextindent (match-string 1))
- (item (org-trim item))
- (item (if (string-match "^\\[\\([xX ]\\)\\]" item)
+ (while (org-search-forward-unenclosed org-item-beginning-re end t)
+ (save-excursion
+ (beginning-of-line)
+ (setq ltype (cond ((looking-at-p "^[ \t]*[0-9]") 'ordered)
+ ((org-at-item-description-p) 'descriptive)
+ (t 'unordered))))
+ (let* ((indent1 (org-get-indentation))
+ (nextitem (or (org-get-next-item (point) end) end))
+ (item (org-trim (buffer-substring (point)
+ (org-end-of-item-or-at-child end))))
+ (nextindent (if (= (point) end) 0 (org-get-indentation)))
+ (item (if (string-match
+ "^\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\([xX ]\\)\\]"
+ item)
(replace-match (if (equal (match-string 1 item) " ")
- "[CBOFF]"
- "[CBON]")
- t nil item)
+ "CBOFF"
+ "CBON")
+ t nil item 1)
item)))
(push item output)
- (when (> (length nextindent)
- (length indent1))
- (narrow-to-region (point) nextitem)
- (push (org-list-parse-list) output)
- (widen))))
- (when delete (delete-region start end))
+ (when (> nextindent indent1)
+ (save-restriction
+ (narrow-to-region (point) nextitem)
+ (push (org-list-parse-list) output)))))
+ (when delete
+ (delete-region start end)
+ (save-match-data
+ (when (and (not (eq org-list-ending-method 'indent))
+ (looking-at (org-list-end-re)))
+ (replace-match "\n"))))
(setq output (nreverse output))
(push ltype output)))
-(defun org-list-item-beginning ()
- "Find the beginning of the list item.
-Return a cons which car is the beginning position of the item and
-cdr is the indentation string."
- (save-excursion
- (if (not (or (looking-at org-list-beginning-re)
- (re-search-backward
- org-list-beginning-re nil t)))
- (progn (goto-char (point-min)) (point))
- (cons (match-beginning 0) (match-string 1)))))
-
-(defun org-list-goto-true-beginning ()
- "Go to the beginning of the list at point."
- (beginning-of-line 1)
- (while (looking-at org-list-beginning-re)
- (beginning-of-line 0))
- (progn
- (re-search-forward org-list-beginning-re nil t)
- (goto-char (match-beginning 0))))
-
(defun org-list-make-subtree ()
"Convert the plain list at point into a subtree."
(interactive)
- (org-list-goto-true-beginning)
- (let ((list (org-list-parse-list t)) nstars)
- (save-excursion
- (if (condition-case nil
- (org-back-to-heading)
- (error nil))
- (progn (re-search-forward org-complex-heading-regexp nil t)
- (setq nstars (length (match-string 1))))
- (setq nstars 0)))
- (org-list-make-subtrees list (1+ nstars))))
+ (if (not (org-in-item-p))
+ (error "Not in a list")
+ (let ((list (org-list-parse-list t)) nstars)
+ (save-excursion
+ (if (ignore-errors
+ (org-back-to-heading))
+ (progn (looking-at org-complex-heading-regexp)
+ (setq nstars (length (match-string 1))))
+ (setq nstars 0)))
+ (org-list-make-subtrees list (1+ nstars)))))
(defun org-list-make-subtrees (list level)
"Convert LIST into subtrees starting at LEVEL."
@@ -1238,20 +2084,6 @@ cdr is the indentation string."
(org-list-make-subtrees item (1+ level))))
list)))
-(defun org-list-end (indent)
- "Return the position of the end of the list.
-INDENT is the indentation of the list, as a string."
- (save-excursion
- (catch 'exit
- (while (or (looking-at org-list-beginning-re)
- (looking-at (concat "^" indent "[ \t]+\\|^$"))
- (> (or (get-text-property (point) 'original-indentation) -1)
- (length indent)))
- (if (eq (point) (point-max))
- (throw 'exit (point-max)))
- (forward-line 1)))
- (point)))
-
(defun org-list-insert-radio-list ()
"Insert a radio list template appropriate for this major mode."
(interactive)
@@ -1273,20 +2105,29 @@ With argument MAYBE, fail quietly if no transformation is defined for
this list."
(interactive)
(catch 'exit
- (unless (org-at-item-p) (error "Not at a list"))
+ (unless (org-at-item-p) (error "Not at a list item"))
(save-excursion
- (org-list-goto-true-beginning)
- (beginning-of-line 0)
+ (re-search-backward "#\\+ORGLST" nil t)
(unless (looking-at "[ \t]*#\\+ORGLST[: \t][ \t]*SEND[ \t]+\\([^ \t\r\n]+\\)[ \t]+\\([^ \t\r\n]+\\)\\([ \t]+.*\\)?")
(if maybe
(throw 'exit nil)
(error "Don't know how to transform this list"))))
(let* ((name (match-string 1))
(transform (intern (match-string 2)))
- (item-beginning (org-list-item-beginning))
- (list (save-excursion (org-list-goto-true-beginning)
- (org-list-parse-list)))
- txt beg)
+ (bottom-point
+ (save-excursion
+ (re-search-forward
+ "\\(\\\\end{comment}\\|@end ignore\\|-->\\)" nil t)
+ (match-beginning 0)))
+ (top-point
+ (progn
+ (re-search-backward "#\\+ORGLST" nil t)
+ (re-search-forward org-item-beginning-re bottom-point t)
+ (match-beginning 0)))
+ (list (save-restriction
+ (narrow-to-region top-point bottom-point)
+ (org-list-parse-list)))
+ beg txt)
(unless (fboundp transform)
(error "No such transformation function %s" transform))
(let ((txt (funcall transform list)))
@@ -1294,22 +2135,22 @@ this list."
(save-excursion
(goto-char (point-min))
(unless (re-search-forward
- (concat "BEGIN RECEIVE ORGLST +" name "\\([ \t]\\|$\\)") nil t)
+ (concat "BEGIN RECEIVE ORGLST +"
+ name
+ "\\([ \t]\\|$\\)") nil t)
(error "Don't know where to insert translated list"))
(goto-char (match-beginning 0))
(beginning-of-line 2)
(setq beg (point))
(unless (re-search-forward (concat "END RECEIVE ORGLST +" name) nil t)
(error "Cannot find end of insertion region"))
- (beginning-of-line 1)
- (delete-region beg (point))
+ (delete-region beg (point-at-bol))
(goto-char beg)
(insert txt "\n")))
(message "List converted and installed at receiver location"))))
(defun org-list-to-generic (list params)
"Convert a LIST parsed through `org-list-parse-list' to other formats.
-
Valid parameters PARAMS are
:ustart String to start an unordered list
@@ -1338,21 +2179,21 @@ Valid parameters PARAMS are
(interactive)
(let* ((p params) sublist
(splicep (plist-get p :splice))
- (ostart (plist-get p :ostart))
- (oend (plist-get p :oend))
- (ustart (plist-get p :ustart))
- (uend (plist-get p :uend))
- (dstart (plist-get p :dstart))
- (dend (plist-get p :dend))
- (dtstart (plist-get p :dtstart))
- (dtend (plist-get p :dtend))
- (ddstart (plist-get p :ddstart))
- (ddend (plist-get p :ddend))
- (istart (plist-get p :istart))
- (iend (plist-get p :iend))
- (isep (plist-get p :isep))
- (lsep (plist-get p :lsep))
- (cbon (plist-get p :cbon))
+ (ostart (plist-get p :ostart))
+ (oend (plist-get p :oend))
+ (ustart (plist-get p :ustart))
+ (uend (plist-get p :uend))
+ (dstart (plist-get p :dstart))
+ (dend (plist-get p :dend))
+ (dtstart (plist-get p :dtstart))
+ (dtend (plist-get p :dtend))
+ (ddstart (plist-get p :ddstart))
+ (ddend (plist-get p :ddend))
+ (istart (plist-get p :istart))
+ (iend (plist-get p :iend))
+ (isep (plist-get p :isep))
+ (lsep (plist-get p :lsep))
+ (cbon (plist-get p :cbon))
(cboff (plist-get p :cboff)))
(let ((wrapper
(cond ((eq (car list) 'ordered)
@@ -1365,22 +2206,24 @@ Valid parameters PARAMS are
(while (setq sublist (pop list))
(cond ((symbolp sublist) nil)
((stringp sublist)
- (when (string-match "^\\(.*\\) ::" sublist)
+ (when (string-match "^\\(.*\\)[ \t]+::" sublist)
(setq term (org-trim (format (concat dtstart "%s" dtend)
(match-string 1 sublist))))
- (setq sublist (substring sublist (1+ (length term)))))
+ (setq sublist (concat ddstart
+ (org-trim (substring sublist
+ (match-end 0)))
+ ddend)))
(if (string-match "\\[CBON\\]" sublist)
(setq sublist (replace-match cbon t t sublist)))
(if (string-match "\\[CBOFF\\]" sublist)
(setq sublist (replace-match cboff t t sublist)))
(if (string-match "\\[-\\]" sublist)
(setq sublist (replace-match "$\\boxminus$" t t sublist)))
- (setq rtn (concat rtn istart term ddstart
- sublist ddend iend isep)))
- (t (setq rtn (concat rtn ;; previous list
- lsep ;; list separator
+ (setq rtn (concat rtn istart term sublist iend isep)))
+ (t (setq rtn (concat rtn ;; previous list
+ lsep ;; list separator
(org-list-to-generic sublist p)
- lsep ;; list separator
+ lsep ;; list separator
)))))
(format wrapper rtn))))
diff --git a/lisp/org-macs.el b/lisp/org-macs.el
index 77527d2..8136ff4 100644
--- a/lisp/org-macs.el
+++ b/lisp/org-macs.el
@@ -290,6 +290,25 @@ This is in contrast to merely setting it to 0."
(match-beginning 0) string)))
(replace-match newtext fixedcase literal string))
+(defmacro org-save-outline-visibility (use-markers &rest body)
+ "Save and restore outline visibility around BODY.
+If USE-MARKERS is non-nil, use markers for the positions.
+This means that the buffer may change while running BODY,
+but it also means that the buffer should stay alive
+during the operation, because otherwise all these markers will
+point nowhere."
+ (declare (indent 1))
+ `(let ((data (org-outline-overlay-data ,use-markers)))
+ (unwind-protect
+ (progn
+ ,@body
+ (org-set-outline-overlay-data data))
+ (when ,use-markers
+ (mapc (lambda (c)
+ (and (markerp (car c)) (move-marker (car c) nil))
+ (and (markerp (cdr c)) (move-marker (cdr c) nil)))
+ data)))))
+
(defmacro org-with-limited-levels (&rest body)
"Execute BODY with limited number of outline levels."
`(let* ((outline-regexp (org-get-limited-outline-regexp)))
diff --git a/lisp/org-mhe.el b/lisp/org-mhe.el
index 46340be..fe31513 100644
--- a/lisp/org-mhe.el
+++ b/lisp/org-mhe.el
@@ -181,7 +181,7 @@ you have a better idea of how to do this then please let us know."
(if (equal major-mode 'mh-folder-mode)
(mh-show)
(mh-show-show))
- header-field)))
+ (org-trim header-field))))
(defun org-mhe-follow-link (folder article)
"Follow an MH-E link to FOLDER and ARTICLE.
diff --git a/lisp/org-mouse.el b/lisp/org-mouse.el
index c47d197..3a5a403 100644
--- a/lisp/org-mouse.el
+++ b/lisp/org-mouse.el
@@ -148,6 +148,7 @@
(declare-function org-agenda-change-all-lines "org-agenda"
(newhead hdmarker &optional fixface just-this))
(declare-function org-verify-change-for-undo "org-agenda" (l1 l2))
+(declare-function org-apply-on-list "org-list" (function init-value &rest args))
(defvar org-mouse-plain-list-regexp "\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) "
"Regular expression that matches a plain list.")
@@ -576,14 +577,11 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
(goto-char (second contextdata))
(re-search-forward ".*" (third contextdata))))))
-(defun org-mouse-for-each-item (function)
- (save-excursion
- (ignore-errors
- (while t (org-previous-item)))
- (ignore-errors
- (while t
- (funcall function)
- (org-next-item)))))
+(defun org-mouse-for-each-item (funct)
+ ;; Functions called by `org-apply-on-list' need an argument
+ (let ((wrap-fun (lambda (c) (funcall funct))))
+ (when (org-in-item-p)
+ (org-apply-on-list wrap-fun nil))))
(defun org-mouse-bolp ()
"Return true if there only spaces, tabs, and '*' before point.
diff --git a/lisp/org-protocol.el b/lisp/org-protocol.el
index 3f240fd..21f28e7 100644
--- a/lisp/org-protocol.el
+++ b/lisp/org-protocol.el
@@ -260,7 +260,7 @@ Here is an example:
:group 'org-protocol
:type '(alist))
-(defcustom org-protocol-default-template-key "w"
+(defcustom org-protocol-default-template-key nil
"The default org-remember-templates key to use."
:group 'org-protocol
:type 'string)
diff --git a/lisp/org-publish.el b/lisp/org-publish.el
index 6324eba..de52410 100644
--- a/lisp/org-publish.el
+++ b/lisp/org-publish.el
@@ -189,7 +189,14 @@ sitemap of files or summary page for a given project.
The following properties control the creation of a concept index.
- :makeindex Create a concept index."
+ :makeindex Create a concept index.
+
+Other properties affecting publication.
+
+ :body-only Set this to 't' to publish only the body of the
+ documents, excluding everything outside and
+ including the <body> tags in HTML, or
+ \begin{document}..\end{document} in LaTeX."
:group 'org-publish
:type 'alist)
@@ -465,13 +472,19 @@ matching filenames."
(unless (plist-get (cdr prj) :components)
;; [[info:org:Selecting%20files]] shows how this is supposed to work:
(let* ((r (plist-get (cdr prj) :recursive))
- (b (expand-file-name (plist-get (cdr prj) :base-directory)))
+ (b (expand-file-name (file-name-as-directory
+ (plist-get (cdr prj) :base-directory))))
(x (or (plist-get (cdr prj) :base-extension) "org"))
(e (plist-get (cdr prj) :exclude))
(i (plist-get (cdr prj) :include))
(xm (concat "^" b (if r ".+" "[^/]+") "\\.\\(" x "\\)$")))
(when (or
- (and i (string-match i filename))
+ (and
+ i
+ (member filename
+ (mapcar
+ (lambda (file) (expand-file-name file b))
+ i)))
(and
(not (and e (string-match e filename)))
(string-match xm filename)))
@@ -508,7 +521,9 @@ PUB-DIR is the publishing directory."
(setq export-buf-or-file
(funcall (intern (concat "org-export-as-" format))
(plist-get plist :headline-levels)
- nil plist nil nil pub-dir))
+ nil plist nil
+ (plist-get plist :body-only)
+ pub-dir))
(when (and (bufferp export-buf-or-file)
(buffer-live-p export-buf-or-file))
(set-buffer export-buf-or-file)
diff --git a/lisp/org-remember.el b/lisp/org-remember.el
index ee464fe..a9cc11f 100644
--- a/lisp/org-remember.el
+++ b/lisp/org-remember.el
@@ -574,7 +574,7 @@ to be run from that hook to function properly."
'org-tags-completion-function nil nil nil
'org-tags-history)))
(setq ins (mapconcat 'identity
- (org-split-string ins (org-re "[^[:alnum:]_@]+"))
+ (org-split-string ins (org-re "[^[:alnum:]_@#%]+"))
":"))
(when (string-match "\\S-" ins)
(or (equal (char-before) ?:) (insert ":"))
diff --git a/lisp/org-src.el b/lisp/org-src.el
index baa2b11..233058a 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -34,6 +34,8 @@
(require 'org-macs)
(require 'org-compat)
+(require 'ob-keys)
+(require 'ob-comint)
(eval-when-compile
(require 'cl))
@@ -165,6 +167,7 @@ For example, there is no ocaml-mode in Emacs, but the mode to use is
(defvar org-src-mode-map (make-sparse-keymap))
(define-key org-src-mode-map "\C-c'" 'org-edit-src-exit)
+
(defvar org-edit-src-force-single-line nil)
(defvar org-edit-src-from-org-mode nil)
(defvar org-edit-src-allow-write-back-p t)
@@ -181,6 +184,8 @@ For example, there is no ocaml-mode in Emacs, but the mode to use is
immediately; otherwise it will ask whether you want to return
to the existing edit buffer.")
+(defvar org-src-babel-info nil)
+
(define-minor-mode org-src-mode
"Minor mode for language major mode buffers generated by org.
This minor mode is turned on in two situations:
@@ -189,13 +194,16 @@ This minor mode is turned on in two situations:
There is a mode hook, and keybindings for `org-edit-src-exit' and
`org-edit-src-save'")
-(defun org-edit-src-code (&optional context code edit-buffer-name)
+(defun org-edit-src-code (&optional context code edit-buffer-name quietp)
"Edit the source code example at point.
-The example is copied to a separate buffer, and that buffer is switched
-to the correct language mode. When done, exit with \\[org-edit-src-exit].
-This will remove the original code in the Org buffer, and replace it with
-the edited version. Optional argument CONTEXT is used by
-\\[org-edit-src-save] when calling this function."
+The example is copied to a separate buffer, and that buffer is
+switched to the correct language mode. When done, exit with
+\\[org-edit-src-exit]. This will remove the original code in the
+Org buffer, and replace it with the edited version. Optional
+argument CONTEXT is used by \\[org-edit-src-save] when calling
+this function. See \\[org-src-window-setup] to configure the
+display of windows containing the Org buffer and the code
+buffer."
(interactive)
(unless (eq context 'save)
(setq org-edit-src-saved-temp-window-config (current-window-configuration)))
@@ -203,6 +211,7 @@ the edited version. Optional argument CONTEXT is used by
(col (current-column))
(case-fold-search t)
(info (org-edit-src-find-region-and-lang))
+ (babel-info (org-babel-get-src-block-info))
(org-mode-p (eq major-mode 'org-mode))
(beg (make-marker))
(end (make-marker))
@@ -267,11 +276,16 @@ the edited version. Optional argument CONTEXT is used by
(unless preserve-indentation
(setq total-nindent (or (org-do-remove-indentation) 0)))
(let ((org-inhibit-startup t))
- (funcall lang-f))
+ (condition-case e
+ (funcall lang-f)
+ (error
+ (error "Language mode `%s' fails with: %S" lang-f (nth 1 e)))))
(set (make-local-variable 'org-edit-src-force-single-line) single)
(set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
(set (make-local-variable 'org-edit-src-allow-write-back-p) allow-write-back-p)
(set (make-local-variable 'org-src-preserve-indentation) preserve-indentation)
+ (when babel-info
+ (set (make-local-variable 'org-src-babel-info) babel-info))
(when lfmt
(set (make-local-variable 'org-coderef-label-format) lfmt))
(when org-mode-p
@@ -290,7 +304,7 @@ the edited version. Optional argument CONTEXT is used by
(set-buffer-modified-p nil)
(and org-edit-src-persistent-message
(org-set-local 'header-line-format msg)))
- (message "%s" msg)
+ (unless quietp (message "%s" msg))
t)))
(defun org-edit-src-continue (e)
@@ -321,6 +335,8 @@ the edited version. Optional argument CONTEXT is used by
(if (eq context 'edit) (delete-other-windows))
(org-switch-to-buffer-other-window buffer)
(if (eq context 'exit) (delete-other-windows)))
+ ('switch-invisibly
+ (set-buffer buffer))
(t
(message "Invalid value %s for org-src-window-setup"
(symbol-name org-src-window-setup))
@@ -654,6 +670,119 @@ the language, a switch telling if the content should be in a single line."
(org-add-hook 'org-src-mode-hook 'org-src-mode-configure-edit-buffer)
+
+(defun org-src-associate-babel-session (info)
+ "Associate edit buffer with comint session."
+ (interactive)
+ (let ((session (cdr (assoc :session (nth 2 info)))))
+ (and session (not (string= session "none"))
+ (org-babel-comint-buffer-livep session)
+ ((lambda (f) (and (fboundp f) (funcall f session)))
+ (intern (format "org-babel-%s-associate-session" (nth 0 info)))))))
+
+(defun org-src-babel-configure-edit-buffer ()
+ (when org-src-babel-info
+ (org-src-associate-babel-session org-src-babel-info)))
+
+(org-add-hook 'org-src-mode-hook 'org-src-babel-configure-edit-buffer)
+(defmacro org-src-do-at-code-block (&rest body)
+ "Execute a command from an edit buffer in the Org-mode buffer."
+ `(let ((beg-marker org-edit-src-beg-marker))
+ (if beg-marker
+ (with-current-buffer (marker-buffer beg-marker)
+ (goto-char (marker-position beg-marker))
+ ,@body))))
+
+(defun org-src-do-key-sequence-at-code-block (&optional key)
+ "Execute key sequence at code block in the source Org buffer.
+The command bound to KEY in the Org-babel key map is executed
+remotely with point temporarily at the start of the code block in
+the Org buffer.
+
+This command is not bound to a key by default, to avoid conflicts
+with language major mode bindings. To bind it to C-c @ in all
+language major modes, you could use
+
+ (add-hook 'org-src-mode-hook
+ (lambda () (define-key org-src-mode-map \"\\C-c@\"
+ 'org-src-do-key-sequence-at-code-block)))
+
+In that case, for example, C-c @ t issued in code edit buffers
+would tangle the current Org code block, C-c @ e would execute
+the block and C-c @ h would display the other available
+Org-babel commands."
+ (interactive "kOrg-babel key: ")
+ (if (equal key (kbd "C-g")) (keyboard-quit)
+ (org-edit-src-save)
+ (org-src-do-at-code-block
+ (call-interactively
+ (lookup-key org-babel-map key)))))
+
+(defvar org-src-tab-acts-natively nil
+ "If non-nil, the effect of TAB in a code block is as if it were
+issued in the language major mode buffer.")
+
+(defun org-src-native-tab-command-maybe ()
+ "Perform language-specific TAB action.
+Alter code block according to effect of TAB in the language major
+mode."
+ (and org-src-tab-acts-natively
+ (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB"))))
+
+(add-hook 'org-tab-first-hook 'org-src-native-tab-command-maybe)
+
+(defun org-src-font-lock-fontify-block (lang start end)
+ "Fontify code block.
+This function is called by emacs automatic fontification, as long
+as `org-src-fontify-natively' is non-nil. For manual
+fontification of code blocks see `org-src-fontify-block' and
+`org-src-fontify-buffer'"
+ (let* ((lang-mode (org-src-get-lang-mode lang))
+ (string (buffer-substring-no-properties start end))
+ (modified (buffer-modified-p))
+ (org-buffer (current-buffer)) pos next)
+ (remove-text-properties start end '(face nil))
+ (with-current-buffer
+ (get-buffer-create
+ (concat " org-src-fontification:" (symbol-name lang-mode)))
+ (delete-region (point-min) (point-max))
+ (insert string)
+ (unless (eq major-mode lang-mode) (funcall lang-mode))
+ (font-lock-fontify-buffer)
+ (setq pos (point-min))
+ (while (setq next (next-single-property-change pos 'face))
+ (put-text-property
+ (+ start (1- pos)) (+ start next) 'face
+ (get-text-property pos 'face) org-buffer)
+ (setq pos next)))
+ (add-text-properties
+ start end
+ '(font-lock-fontified t fontified t font-lock-multiline t))
+ (set-buffer-modified-p modified))
+ t) ;; Tell `org-fontify-meta-lines-and-blocks' that we fontified
+
+(defun org-src-fontify-block ()
+ "Fontify code block at point."
+ (interactive)
+ (save-excursion
+ (let ((org-src-fontify-natively t)
+ (info (org-edit-src-find-region-and-lang)))
+ (font-lock-fontify-region (nth 0 info) (nth 1 info)))))
+
+(defun org-src-fontify-buffer ()
+ "Fontify all code blocks in the current buffer"
+ (interactive)
+ (org-babel-map-src-blocks nil
+ (org-src-fontify-block)))
+
+(defun org-src-get-lang-mode (lang)
+ "Return major mode that should be used for LANG.
+LANG is a string, and the returned major mode is a symbol."
+ (intern
+ (concat
+ ((lambda (l) (if (symbolp l) (symbol-name l) l))
+ (or (cdr (assoc lang org-src-lang-modes)) lang)) "-mode")))
+
(provide 'org-src)
;; arch-tag: 6a1fc84f-dec7-47be-a416-64be56bea5d8
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 6172e1c..a6f7ac4 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -369,8 +369,9 @@ and table.el tables."
(if (y-or-n-p "Convert table to Org-mode table? ")
(org-table-convert)))
((org-at-table-p)
- (if (y-or-n-p "Convert table to table.el table? ")
- (org-table-convert)))
+ (when (y-or-n-p "Convert table to table.el table? ")
+ (org-table-align)
+ (org-table-convert)))
(t (call-interactively 'table-insert))))
(defun org-table-create-or-convert-from-region (arg)
diff --git a/lisp/org-timer.el b/lisp/org-timer.el
index 2e70fdf..b3fd6bf 100644
--- a/lisp/org-timer.el
+++ b/lisp/org-timer.el
@@ -31,7 +31,7 @@
(require 'org)
-(declare-function org-show-notification "org-clock" (parameters))
+(declare-function org-notify "org-clock" (notification &optional play-sound))
(declare-function org-agenda-error "org-agenda" ())
(defvar org-timer-start-time nil
@@ -145,25 +145,33 @@ With prefix arg STOP, stop it entirely."
(org-timer-set-mode-line 'off))
;;;###autoload
-(defun org-timer (&optional restart)
+(defun org-timer (&optional restart no-insert-p)
"Insert a H:MM:SS string from the timer into the buffer.
The first time this command is used, the timer is started. When used with
a \\[universal-argument] prefix, force restarting the timer.
-When used with a double prefix argument \
-\\[universal-argument] \\universal-argument], change all the timer string
+When used with a double prefix argument \\[universal-argument], change all the timer string
in the region by a fixed amount. This can be used to recalibrate a timer
-that was not started at the correct moment."
+that was not started at the correct moment.
+
+If NO-INSERT-P is non-nil, return the string instead of inserting
+it in the buffer."
(interactive "P")
- (if (equal restart '(4)) (org-timer-start))
- (or org-timer-start-time (org-timer-start))
- (insert (org-timer-value-string)))
+ (when (or (equal restart '(4)) (not org-timer-start-time))
+ (org-timer-start))
+ (if no-insert-p
+ (org-timer-value-string)
+ (insert (org-timer-value-string))))
(defun org-timer-value-string ()
(format org-timer-format (org-timer-secs-to-hms (floor (org-timer-seconds)))))
+(defvar org-timer-timer-is-countdown nil)
(defun org-timer-seconds ()
- (- (org-float-time (or org-timer-pause-time (current-time)))
- (org-float-time org-timer-start-time)))
+ (if org-timer-timer-is-countdown
+ (- (org-float-time org-timer-start-time)
+ (org-float-time (current-time)))
+ (- (org-float-time (or org-timer-pause-time (current-time)))
+ (org-float-time org-timer-start-time))))
;;;###autoload
(defun org-timer-change-times-in-region (beg end delta)
@@ -195,19 +203,22 @@ that was not started at the correct moment."
(defun org-timer-item (&optional arg)
"Insert a description-type item with the current timer value."
(interactive "P")
- (let ((ind 0))
- (save-excursion
- (skip-chars-backward " \n\t")
- (condition-case nil
- (progn
- (org-beginning-of-item)
- (setq ind (org-get-indentation)))
- (error nil)))
- (or (bolp) (newline))
- (org-indent-line-to ind)
- (insert "- ")
- (org-timer (if arg '(4)))
- (insert ":: ")))
+ (cond
+ ;; In a timer list, insert with `org-list-insert-item-generic'.
+ ((and (org-in-item-p)
+ (save-excursion (org-beginning-of-item) (org-at-item-timer-p)))
+ (org-list-insert-item-generic
+ (point) nil (concat (org-timer (when arg '(4)) t) ":: ")))
+ ;; In a list of another type, don't break anything: throw an error.
+ ((org-in-item-p)
+ (error "This is not a timer list"))
+ ;; Else, insert the timer correctly indented at bol.
+ (t
+ (beginning-of-line)
+ (org-indent-line-function)
+ (insert "- ")
+ (org-timer (when arg '(4)))
+ (insert ":: "))))
(defun org-timer-fix-incomplete (hms)
"If hms is a H:MM:SS string with missing hour or hour and minute, fix it."
@@ -292,7 +303,9 @@ VALUE can be `on', `off', or `pause'."
(when (eval org-timer-current-timer)
(run-hooks 'org-timer-cancel-hook)
(cancel-timer org-timer-current-timer)
- (setq org-timer-current-timer nil))
+ (setq org-timer-current-timer nil)
+ (setq org-timer-timer-is-countdown nil)
+ (org-timer-set-mode-line 'off))
(message "Last timer canceled"))
(defun org-timer-show-remaining-time ()
@@ -309,10 +322,6 @@ VALUE can be `on', `off', or `pause'."
(message "%d minute(s) %d seconds left before next time out"
rmins rsecs))))
-(defun bzg-test (&optional test)
- (interactive "P")
- test)
-
;;;###autoload
(defun org-timer-set-timer (&optional opt)
"Prompt for a duration and set a timer.
@@ -353,9 +362,11 @@ replace any running timer."
(widen)
(goto-char pos)
(org-show-entry)
- (org-get-heading))))
+ (or (ignore-errors (org-get-heading))
+ (concat "File:" (file-name-nondirectory (buffer-file-name)))))))
((eq major-mode 'org-mode)
- (org-get-heading))
+ (or (ignore-errors (org-get-heading))
+ (concat "File:" (file-name-nondirectory (buffer-file-name)))))
(t (error "Not in an Org buffer"))))
timer-set)
(if (or (and org-timer-current-timer
@@ -363,6 +374,7 @@ replace any running timer."
(y-or-n-p "Replace current timer? ")))
(not org-timer-current-timer))
(progn
+ (require 'org-clock)
(when org-timer-current-timer
(cancel-timer org-timer-current-timer))
(setq org-timer-current-timer
@@ -370,8 +382,14 @@ replace any running timer."
secs nil `(lambda ()
(setq org-timer-current-timer nil)
(org-notify ,(format "%s: time out" hl) t)
+ (setq org-timer-timer-is-countdown nil)
+ (org-timer-set-mode-line 'off)
(run-hooks 'org-timer-done-hook))))
- (run-hooks 'org-timer-set-hook))
+ (run-hooks 'org-timer-set-hook)
+ (setq org-timer-timer-is-countdown t
+ org-timer-start-time
+ (time-add (current-time) (seconds-to-time (* mins 60))))
+ (org-timer-set-mode-line 'on))
(message "No timer set"))))))
(provide 'org-timer)
diff --git a/lisp/org-wl.el b/lisp/org-wl.el
index f88d830..e1222ed 100644
--- a/lisp/org-wl.el
+++ b/lisp/org-wl.el
@@ -142,13 +142,14 @@ ENTITY is a message entity."
(defun org-wl-store-link ()
"Store a link to a WL message or folder."
- (cond
- ((memq major-mode '(wl-summary-mode mime-view-mode))
- (org-wl-store-link-message))
- ((eq major-mode 'wl-folder-mode)
- (org-wl-store-link-folder))
- (t
- nil)))
+ (unless (eobp)
+ (cond
+ ((memq major-mode '(wl-summary-mode mime-view-mode))
+ (org-wl-store-link-message))
+ ((eq major-mode 'wl-folder-mode)
+ (org-wl-store-link-folder))
+ (t
+ nil))))
(defun org-wl-store-link-folder ()
"Store a link to a WL folder."
diff --git a/lisp/org.el b/lisp/org.el
index f82e16b..c2e6253 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -86,10 +86,6 @@
(unless (boundp 'diary-fancy-buffer)
(defvaralias 'diary-fancy-buffer 'fancy-diary-buffer)))
-;; For XEmacs, noutline is not yet provided by outline.el, so arrange for
-;; the file noutline.el being loaded.
-(if (featurep 'xemacs) (condition-case nil (require 'noutline)))
-;; We require noutline, which might be provided in outline.el
(require 'outline) (require 'noutline)
;; Other stuff we need.
(require 'time-date)
@@ -158,16 +154,20 @@ requirements) is loaded."
(const :tag "Emacs Lisp" emacs-lisp)
(const :tag "Gnuplot" gnuplot)
(const :tag "Haskell" haskell)
+ (const :tag "Javascript" js)
(const :tag "Latex" latex)
(const :tag "Ledger" ledger)
(const :tag "Matlab" matlab)
(const :tag "Mscgen" mscgen)
(const :tag "Ocaml" ocaml)
(const :tag "Octave" octave)
+ (const :tag "Org" org)
(const :tag "Perl" perl)
+ (const :tag "PlantUML" plantuml)
(const :tag "Python" python)
(const :tag "Ruby" ruby)
(const :tag "Sass" sass)
+ (const :tag "Scheme" scheme)
(const :tag "Screen" screen)
(const :tag "Shell Script" sh)
(const :tag "Sql" sql)
@@ -3088,7 +3088,7 @@ points to a file, `org-agenda-diary-entry' will be used instead."
(defcustom org-format-latex-options
'(:foreground default :background default :scale 1.0
- :html-foreground "Black" :html-background "Transparent"
+ :html-foreground "Black" :html-background "Transparent"
:html-scale 1.0 :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))
"Options for creating images from LaTeX fragments.
This is a property list with the following properties:
@@ -3176,7 +3176,6 @@ will be appended."
("" "float" nil)
("" "wrapfig" nil)
("" "soul" t)
- ("" "t1enc" t)
("" "textcomp" t)
("" "marvosym" t)
("" "wasysym" t)
@@ -3191,7 +3190,7 @@ with another package you are using.
The packages in this list are needed by one part or another of Org-mode
to function properly.
-- inputenc, fontenc, t1enc: for basic font and character selection
+- inputenc, fontenc: for basic font and character selection
- textcomp, marvosymb, wasysym, latexsym, amssym: for various symbols used
for interpreting the entities in `org-entities'. You can skip some of these
packages if you don't use any of the symbols in it.
@@ -3325,6 +3324,8 @@ When nil, the \\name form remains in the buffer."
(defvar org-emph-re nil
"Regular expression for matching emphasis.
After a match, the match groups contain these elements:
+0 The match of the full regular expression, including the characters
+ before and after the proper match
1 The character before the proper match, or empty at beginning of line
2 The proper match, including the leading and trailing markers
3 The leading marker like * or /, indicating the type of highlighting
@@ -4038,7 +4039,11 @@ group 3: Priority cookie
group 4: True headline
group 5: Tags")
(make-variable-buffer-local 'org-complex-heading-regexp)
-(defvar org-complex-heading-regexp-format nil)
+(defvar org-complex-heading-regexp-format nil
+ "Printf format to make regexp to match an exact headline.
+This regexp will match the headline of any node which hase the exact
+headline text that is put into the format, but may have any TODO state,
+priority and tags.")
(make-variable-buffer-local 'org-complex-heading-regexp-format)
(defvar org-todo-line-tags-regexp nil
"Matches a headline and puts TODO state into group 2 if present.
@@ -4371,7 +4376,7 @@ means to push this value onto the list in the variable.")
((equal e "{") (push '(:startgroup) tgs))
((equal e "}") (push '(:endgroup) tgs))
((equal e "\\n") (push '(:newline) tgs))
- ((string-match (org-re "^\\([[:alnum:]_@]+\\)(\\(.\\))$") e)
+ ((string-match (org-re "^\\([[:alnum:]_@#%]+\\)(\\(.\\))$") e)
(push (cons (match-string 1 e)
(string-to-char (match-string 2 e)))
tgs))
@@ -4415,7 +4420,7 @@ means to push this value onto the list in the variable.")
(concat "^\\(\\*+\\)[ \t]+\\(?:\\("
(mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
"\\)\\>\\)?\\(?:[ \t]*\\(\\[#.\\]\\)\\)?[ \t]*\\(.*?\\)"
- "\\(?:[ \t]+\\(:[[:alnum:]_@:]+:\\)\\)?[ \t]*$")
+ "\\(?:[ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)?[ \t]*$")
org-complex-heading-regexp-format
(concat "^\\(\\*+\\)[ \t]+\\(?:\\("
(mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
@@ -4424,7 +4429,7 @@ means to push this value onto the list in the variable.")
"\\(?:[ \t]*\\(?:\\[[0-9%%/]+\\]\\)\\)?" ;; stats cookie
"[ \t]*\\(%s\\)"
"\\(?:[ \t]*\\(?:\\[[0-9%%/]+\\]\\)\\)?" ;; stats cookie
- "\\(?:[ \t]+\\(:[[:alnum:]_@:]+:\\)\\)?[ \t]*$")
+ "\\(?:[ \t]+\\(:[[:alnum:]_@#%%:]+:\\)\\)?[ \t]*$")
org-nl-done-regexp
(concat "\n\\*+[ \t]+"
"\\(?:" (mapconcat 'regexp-quote org-done-keywords "\\|")
@@ -4433,7 +4438,7 @@ means to push this value onto the list in the variable.")
(concat "^\\(\\*+\\)[ \t]+\\(?:\\("
(mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
(org-re
- "\\)\\>\\)? *\\(.*?\\([ \t]:[[:alnum:]:_@]+:[ \t]*\\)?$\\)"))
+ "\\)\\>\\)? *\\(.*?\\([ \t]:[[:alnum:]:_@#%]+:[ \t]*\\)?$\\)"))
org-looking-at-done-regexp
(concat "^" "\\(?:"
(mapconcat 'regexp-quote org-done-keywords "\\|") "\\)"
@@ -4851,7 +4856,7 @@ This should be called after the variable `org-link-types' has changed."
org-plain-link-re
(concat
"\\<\\(" (mapconcat 'regexp-quote org-link-types "\\|") "\\):"
- (org-re "\\([^ \t\n()<>]+\\(?:([[:word:]0-9]+)\\|\\([^[:punct:] \t\n]\\|/\\)\\)\\)"))
+ (org-re "\\([^ \t\n()<>]+\\(?:([[:word:]0-9_]+)\\|\\([^[:punct:] \t\n]\\|/\\)\\)\\)"))
;; "\\([^]\t\n\r<>() ]+[^]\t\n\r<>,.;() ]\\)")
org-bracket-link-regexp
"\\[\\[\\([^][]+\\)\\]\\(\\[\\([^][]+\\)\\]\\)?\\]"
@@ -5017,13 +5022,22 @@ will be prompted for."
'(display t invisible t intangible t))
t)))
+(defcustom org-src-fontify-natively nil
+ "When non-nil, fontify code in code blocks."
+ :type 'boolean
+ :group 'org-appearance
+ :group 'org-babel)
+
(defun org-fontify-meta-lines-and-blocks (limit)
"Fontify #+ lines and blocks, in the correct ways."
(let ((case-fold-search t))
(if (re-search-forward
- "^\\([ \t]*#\\+\\(\\([a-zA-Z]+:?\\| \\|$\\)\\(_\\([a-zA-Z]+\\)\\)?\\)\\(.*\\)\\)"
+ "^\\([ \t]*#\\+\\(\\([a-zA-Z]+:?\\| \\|$\\)\\(_\\([a-zA-Z]+\\)\\)?\\)[ \t]*\\(\\([^ \t\n]*\\)[ \t]*\\(.*\\)\\)\\)"
limit t)
(let ((beg (match-beginning 0))
+ (block-start (match-end 0))
+ (block-end nil)
+ (lang (match-string 7))
(beg1 (line-beginning-position 2))
(dc1 (downcase (match-string 2)))
(dc3 (downcase (match-string 3)))
@@ -5048,6 +5062,7 @@ will be prompted for."
(concat "^[ \t]*#\\+end" (match-string 4) "\\>.*")
nil t) ;; on purpose, we look further than LIMIT
(setq end (match-end 0) end1 (1- (match-beginning 0)))
+ (setq block-end (match-beginning 0))
(when quoting
(remove-text-properties beg end
'(display t invisible t intangible t)))
@@ -5058,6 +5073,8 @@ will be prompted for."
(add-text-properties end1 (+ end 1) '(face org-meta-line))
; for end_src
(cond
+ ((and lang org-src-fontify-natively)
+ (org-src-font-lock-fontify-block lang block-start block-end))
(quoting
(add-text-properties beg1 (+ end1 1) '(face
org-block)))
@@ -5347,7 +5364,7 @@ between words."
"\\)\\>")))
(defun org-activate-tags (limit)
- (if (re-search-forward (org-re "^\\*+.*[ \t]\\(:[[:alnum:]_@:]+:\\)[ \r\n]") limit t)
+ (if (re-search-forward (org-re "^\\*+.*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \r\n]") limit t)
(progn
(org-remove-flyspell-overlays-in (match-beginning 1) (match-end 1))
(add-text-properties (match-beginning 1) (match-end 1)
@@ -5452,13 +5469,13 @@ needs to be inserted at a specific position in the font-lock sequence.")
'(org-do-emphasis-faces (0 nil append))
'(org-do-emphasis-faces)))
;; Checkboxes
- '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[- X]\\]\\)"
- 2 'org-checkbox prepend)
- (if org-provide-checkbox-statistics
+ '("^[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\)[ \t]+\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\(\\[[- X]\\]\\)"
+ 1 'org-checkbox prepend)
+ (if (cdr (assq 'checkbox org-list-automatic-rules))
'("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
(0 (org-get-checkbox-statistics-face) t)))
;; Description list items
- '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(.*? ::\\)"
+ '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\)[ \t]+\\(.*? ::\\)"
2 'bold prepend)
;; ARCHIVEd headings
(list (concat "^\\*+ \\(.*:" org-archive-tag ":.*\\)")
@@ -5895,12 +5912,15 @@ in special contexts.
(outline-next-heading)
(setq has-children (and (org-at-heading-p t)
(> (funcall outline-level) level))))
- (org-end-of-subtree t)
- (unless (eobp)
- (skip-chars-forward " \t\n")
- (beginning-of-line 1) ; in case this is an item
- )
- (setq eos (if (eobp) (point) (1- (point)))))
+ ;; if we're in a list, org-end-of-subtree is in fact org-end-of-item.
+ (if (org-at-item-p)
+ (setq eos (if (and (org-end-of-item) (bolp))
+ (1- (point))
+ (point)))
+ (org-end-of-subtree t)
+ (unless (eobp)
+ (skip-chars-forward " \t\n"))
+ (setq eos (if (eobp) (point) (1- (point))))))
;; Find out what to do next and set `this-command'
(cond
((= eos eoh)
@@ -5934,14 +5954,14 @@ in special contexts.
;; We just showed the children, or no children are there,
;; now show everything.
(run-hook-with-args 'org-pre-cycle-hook 'subtree)
- (org-show-subtree)
+ (outline-flag-region eoh eos nil)
(message (if children-skipped "SUBTREE (NO CHILDREN)" "SUBTREE"))
(setq org-cycle-subtree-status 'subtree)
(run-hook-with-args 'org-cycle-hook 'subtree))
(t
;; Default action: hide the subtree.
(run-hook-with-args 'org-pre-cycle-hook 'folded)
- (hide-subtree)
+ (outline-flag-region eoh eos t)
(message "FOLDED")
(setq org-cycle-subtree-status 'folded)
(run-hook-with-args 'org-cycle-hook 'folded)))))
@@ -6251,26 +6271,6 @@ DATA should have been made by `org-outline-overlay-data'."
(overlay-put o 'invisible 'outline))
data)))))
-(defmacro org-save-outline-visibility (use-markers &rest body)
- "Save and restore outline visibility around BODY.
-If USE-MARKERS is non-nil, use markers for the positions.
-This means that the buffer may change while running BODY,
-but it also means that the buffer should stay alive
-during the operation, because otherwise all these markers will
-point nowhere."
- (declare (indent 1))
- `(let ((data (org-outline-overlay-data ,use-markers)))
- (unwind-protect
- (progn
- ,@body
- (org-set-outline-overlay-data data))
- (when ,use-markers
- (mapc (lambda (c)
- (and (markerp (car c)) (move-marker (car c) nil))
- (and (markerp (cdr c)) (move-marker (cdr c) nil)))
- data)))))
-
-
;;; Folding of blocks
(defconst org-block-regexp
@@ -6440,7 +6440,9 @@ the headline hierarchy above."
(selected-point
(if (eq interface 'outline)
(car (org-get-location (current-buffer) org-goto-help))
- (nth 3 (org-refile-get-location "Goto: ")))))
+ (let ((pa (org-refile-get-location "Goto: ")))
+ (org-refile-check-position pa)
+ (nth 3 pa)))))
(if selected-point
(progn
(org-mark-ring-push org-goto-start-pos)
@@ -6723,7 +6725,7 @@ This is important for non-interactive uses of the command."
(when hide-previous
(show-children)
(org-show-entry))
- (looking-at ".*?\\([ \t]+\\(:[[:alnum:]_@:]+:\\)\\)?[ \t]*$")
+ (looking-at ".*?\\([ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)?[ \t]*$")
(setq tags (and (match-end 2) (match-string 2)))
(and (match-end 1)
(delete-region (match-beginning 1) (match-end 1)))
@@ -6759,7 +6761,7 @@ This is important for non-interactive uses of the command."
(org-back-to-heading t)
(if (looking-at
(if no-tags
- (org-re "\\*+[ \t]+\\([^\n\r]*?\\)\\([ \t]+:[[:alnum:]:_@]+:[ \t]*\\)?$")
+ (org-re "\\*+[ \t]+\\([^\n\r]*?\\)\\([ \t]+:[[:alnum:]:_@#%]+:[ \t]*\\)?$")
"\\*+[ \t]+\\([^\r\n]*\\)"))
(match-string 1) "")))
@@ -6844,7 +6846,7 @@ Works for outline headings and for plain lists alike."
(org-insert-heading arg)
(cond
((org-on-heading-p) (org-do-demote))
- ((org-at-item-p) (org-indent-item 1))))
+ ((org-at-item-p) (org-indent-item))))
(defun org-insert-todo-subheading (arg)
"Insert a new subheading with TODO keyword or checkbox and demote it.
@@ -6853,7 +6855,7 @@ Works for outline headings and for plain lists alike."
(org-insert-todo-heading arg)
(cond
((org-on-heading-p) (org-do-demote))
- ((org-at-item-p) (org-indent-item 1))))
+ ((org-at-item-p) (org-indent-item))))
;;; Promotion and Demotion
@@ -7529,13 +7531,15 @@ and still retain the repeater to cover future instances of the task."
;;; Outline Sorting
(defun org-sort (with-case)
- "Call `org-sort-entries-or-items' or `org-table-sort-lines'.
+ "Call `org-sort-entries', `org-table-sort-lines' or `org-sort-list'.
Optional argument WITH-CASE means sort case-sensitively.
With a double prefix argument, also remove duplicate entries."
(interactive "P")
- (if (org-at-table-p)
- (org-call-with-arg 'org-table-sort-lines with-case)
- (org-call-with-arg 'org-sort-entries-or-items with-case)))
+ (cond
+ ((org-at-table-p) (org-call-with-arg 'org-table-sort-lines with-case))
+ ((org-at-item-p) (org-call-with-arg 'org-sort-list with-case))
+ (t
+ (org-call-with-arg 'org-sort-entries with-case))))
(defun org-sort-remove-invisible (s)
(remove-text-properties 0 (length s) org-rm-props s)
@@ -7553,14 +7557,12 @@ When children are sorted, the cursor is in the parent line when this
hook gets called. When a region or a plain list is sorted, the cursor
will be in the first entry of the sorted region/list.")
-(defun org-sort-entries-or-items
+(defun org-sort-entries
(&optional with-case sorting-type getkey-func compare-func property)
- "Sort entries on a certain level of an outline tree, or plain list items.
+ "Sort entries on a certain level of an outline tree.
If there is an active region, the entries in the region are sorted.
Else, if the cursor is before the first entry, sort the top-level items.
Else, the children of the entry at point are sorted.
-If the cursor is at the first item in a plain list, the list items will be
-sorted.
Sorting can be alphabetically, numerically, by date/time as given by
a time stamp, by a property or by priority.
@@ -7574,7 +7576,6 @@ n Numerically, by converting the beginning of the entry/item to a number.
a Alphabetically, ignoring the TODO keyword and the priority, if any.
t By date/time, either the first active time stamp in the entry, or, if
none exist, by the first inactive one.
- In items, only the first line will be checked.
s By the scheduled date/time.
d By deadline date/time.
c By creation time, which is assumed to be the first inactive time stamp
@@ -7593,7 +7594,7 @@ WITH-CASE, the sorting considers case as well."
(interactive "P")
(let ((case-func (if with-case 'identity 'downcase))
start beg end stars re re2
- txt what tmp plain-list-p)
+ txt what tmp)
;; Find beginning and end of region to sort
(cond
((org-region-active-p)
@@ -7603,15 +7604,6 @@ WITH-CASE, the sorting considers case as well."
(goto-char (region-beginning))
(if (not (org-on-heading-p)) (outline-next-heading))
(setq start (point)))
- ((org-at-item-p)
- ;; we will sort this plain list
- (org-beginning-of-item-list) (setq start (point))
- (org-end-of-item-list)
- (or (bolp) (insert "\n"))
- (setq end (point))
- (goto-char start)
- (setq plain-list-p t
- what "plain list"))
((or (org-on-heading-p)
(condition-case nil (progn (org-back-to-heading) t) (error nil)))
;; we will sort the children of the current headline
@@ -7644,43 +7636,39 @@ WITH-CASE, the sorting considers case as well."
(setq beg (point))
(if (>= beg end) (error "Nothing to sort"))
- (unless plain-list-p
- (looking-at "\\(\\*+\\)")
- (setq stars (match-string 1)
- re (concat "^" (regexp-quote stars) " +")
- re2 (concat "^" (regexp-quote (substring stars 0 -1)) "[^*]")
- txt (buffer-substring beg end))
- (if (not (equal (substring txt -1) "\n")) (setq txt (concat txt "\n")))
- (if (and (not (equal stars "*")) (string-match re2 txt))
- (error "Region to sort contains a level above the first entry")))
+ (looking-at "\\(\\*+\\)")
+ (setq stars (match-string 1)
+ re (concat "^" (regexp-quote stars) " +")
+ re2 (concat "^" (regexp-quote (substring stars 0 -1)) "[^*]")
+ txt (buffer-substring beg end))
+ (if (not (equal (substring txt -1) "\n")) (setq txt (concat txt "\n")))
+ (if (and (not (equal stars "*")) (string-match re2 txt))
+ (error "Region to sort contains a level above the first entry"))
(unless sorting-type
(message
- (if plain-list-p
- "Sort %s: [a]lpha [n]umeric [t]ime [f]unc A/N/T/F means reversed:"
- "Sort %s: [a]lpha [n]umeric [p]riority p[r]operty todo[o]rder [f]unc
+ "Sort %s: [a]lpha [n]umeric [p]riority p[r]operty todo[o]rder [f]unc
[t]ime [s]cheduled [d]eadline [c]reated
- A/N/T/S/D/C/P/O/F means reversed:")
+ A/N/T/S/D/C/P/O/F means reversed:"
what)
(setq sorting-type (read-char-exclusive))
(and (= (downcase sorting-type) ?f)
(setq getkey-func
(org-icompleting-read "Sort using function: "
- obarray 'fboundp t nil nil))
+ obarray 'fboundp t nil nil))
(setq getkey-func (intern getkey-func)))
(and (= (downcase sorting-type) ?r)
(setq property
(org-icompleting-read "Property: "
- (mapcar 'list (org-buffer-property-keys t))
- nil t))))
+ (mapcar 'list (org-buffer-property-keys t))
+ nil t))))
(message "Sorting entries...")
(save-restriction
(narrow-to-region start end)
-
(let ((dcst (downcase sorting-type))
(case-fold-search nil)
(now (current-time)))
@@ -7688,99 +7676,70 @@ WITH-CASE, the sorting considers case as well."
(/= dcst sorting-type)
;; This function moves to the beginning character of the "record" to
;; be sorted.
- (if plain-list-p
- (lambda nil
- (if (org-at-item-p) t (goto-char (point-max))))
- (lambda nil
- (if (re-search-forward re nil t)
- (goto-char (match-beginning 0))
- (goto-char (point-max)))))
+ (lambda nil
+ (if (re-search-forward re nil t)
+ (goto-char (match-beginning 0))
+ (goto-char (point-max))))
;; This function moves to the last character of the "record" being
;; sorted.
- (if plain-list-p
- 'org-end-of-item
- (lambda nil
- (save-match-data
- (condition-case nil
- (outline-forward-same-level 1)
- (error
- (goto-char (point-max)))))))
-
+ (lambda nil
+ (save-match-data
+ (condition-case nil
+ (outline-forward-same-level 1)
+ (error
+ (goto-char (point-max))))))
;; This function returns the value that gets sorted against.
- (if plain-list-p
- (lambda nil
- (when (looking-at "[ \t]*[-+*0-9.)]+[ \t]+")
- (cond
- ((= dcst ?n)
- (string-to-number (buffer-substring (match-end 0)
- (point-at-eol))))
- ((= dcst ?a)
- (buffer-substring (match-end 0) (point-at-eol)))
- ((= dcst ?t)
- (if (or (re-search-forward org-ts-regexp (point-at-eol) t)
- (re-search-forward org-ts-regexp-both
- (point-at-eol) t))
- (org-time-string-to-seconds (match-string 0))
- (org-float-time now)))
- ((= dcst ?f)
- (if getkey-func
- (progn
- (setq tmp (funcall getkey-func))
- (if (stringp tmp) (setq tmp (funcall case-func tmp)))
- tmp)
- (error "Invalid key function `%s'" getkey-func)))
- (t (error "Invalid sorting type `%c'" sorting-type)))))
- (lambda nil
- (cond
- ((= dcst ?n)
- (if (looking-at org-complex-heading-regexp)
- (string-to-number (match-string 4))
- nil))
- ((= dcst ?a)
- (if (looking-at org-complex-heading-regexp)
- (funcall case-func (match-string 4))
- nil))
- ((= dcst ?t)
- (let ((end (save-excursion (outline-next-heading) (point))))
- (if (or (re-search-forward org-ts-regexp end t)
- (re-search-forward org-ts-regexp-both end t))
- (org-time-string-to-seconds (match-string 0))
- (org-float-time now))))
- ((= dcst ?c)
- (let ((end (save-excursion (outline-next-heading) (point))))
- (if (re-search-forward
- (concat "^[ \t]*\\[" org-ts-regexp1 "\\]")
- end t)
- (org-time-string-to-seconds (match-string 0))
- (org-float-time now))))
- ((= dcst ?s)
- (let ((end (save-excursion (outline-next-heading) (point))))
- (if (re-search-forward org-scheduled-time-regexp end t)
- (org-time-string-to-seconds (match-string 1))
- (org-float-time now))))
- ((= dcst ?d)
- (let ((end (save-excursion (outline-next-heading) (point))))
- (if (re-search-forward org-deadline-time-regexp end t)
- (org-time-string-to-seconds (match-string 1))
- (org-float-time now))))
- ((= dcst ?p)
- (if (re-search-forward org-priority-regexp (point-at-eol) t)
- (string-to-char (match-string 2))
- org-default-priority))
- ((= dcst ?r)
- (or (org-entry-get nil property) ""))
- ((= dcst ?o)
- (if (looking-at org-complex-heading-regexp)
- (- 9999 (length (member (match-string 2)
- org-todo-keywords-1)))))
- ((= dcst ?f)
- (if getkey-func
- (progn
- (setq tmp (funcall getkey-func))
- (if (stringp tmp) (setq tmp (funcall case-func tmp)))
- tmp)
- (error "Invalid key function `%s'" getkey-func)))
- (t (error "Invalid sorting type `%c'" sorting-type)))))
+ (lambda nil
+ (cond
+ ((= dcst ?n)
+ (if (looking-at org-complex-heading-regexp)
+ (string-to-number (match-string 4))
+ nil))
+ ((= dcst ?a)
+ (if (looking-at org-complex-heading-regexp)
+ (funcall case-func (match-string 4))
+ nil))
+ ((= dcst ?t)
+ (let ((end (save-excursion (outline-next-heading) (point))))
+ (if (or (re-search-forward org-ts-regexp end t)
+ (re-search-forward org-ts-regexp-both end t))
+ (org-time-string-to-seconds (match-string 0))
+ (org-float-time now))))
+ ((= dcst ?c)
+ (let ((end (save-excursion (outline-next-heading) (point))))
+ (if (re-search-forward
+ (concat "^[ \t]*\\[" org-ts-regexp1 "\\]")
+ end t)
+ (org-time-string-to-seconds (match-string 0))
+ (org-float-time now))))
+ ((= dcst ?s)
+ (let ((end (save-excursion (outline-next-heading) (point))))
+ (if (re-search-forward org-scheduled-time-regexp end t)
+ (org-time-string-to-seconds (match-string 1))
+ (org-float-time now))))
+ ((= dcst ?d)
+ (let ((end (save-excursion (outline-next-heading) (point))))
+ (if (re-search-forward org-deadline-time-regexp end t)
+ (org-time-string-to-seconds (match-string 1))
+ (org-float-time now))))
+ ((= dcst ?p)
+ (if (re-search-forward org-priority-regexp (point-at-eol) t)
+ (string-to-char (match-string 2))
+ org-default-priority))
+ ((= dcst ?r)
+ (or (org-entry-get nil property) ""))
+ ((= dcst ?o)
+ (if (looking-at org-complex-heading-regexp)
+ (- 9999 (length (member (match-string 2)
+ org-todo-keywords-1)))))
+ ((= dcst ?f)
+ (if getkey-func
+ (progn
+ (setq tmp (funcall getkey-func))
+ (if (stringp tmp) (setq tmp (funcall case-func tmp)))
+ tmp)
+ (error "Invalid key function `%s'" getkey-func)))
+ (t (error "Invalid sorting type `%c'" sorting-type))))
nil
(cond
((= dcst ?a) 'string<)
@@ -8185,11 +8144,13 @@ It should be a function accepting three arguments:
path the path of the link, the text after the prefix (like \"http:\")
desc the description of the link, if any, nil if there was no description
- format the export format, a symbol like `html' or `latex'.
+ format the export format, a symbol like `html' or `latex' or `ascii'..
The function may use the FORMAT information to return different values
depending on the format. The return value will be put literally into
-the exported file.
+the exported file. If the return value is nil, this means Org should
+do what it normally does with links which do not have EXPORT defined.
+
Org-mode has a built-in default for exporting links. If you are happy with
this default, there is no need to define an export function for the link
type. For a simple example of an export function, see `org-bbdb.el'."
@@ -8214,7 +8175,7 @@ For file links, arg negates `org-context-in-file-links'."
(org-load-modules-maybe)
(setq org-store-link-plist nil) ; reset
(let ((outline-regexp (org-get-limited-outline-regexp))
- link cpltxt desc description search txt custom-id)
+ link cpltxt desc description search txt custom-id agenda-link)
(cond
((run-hook-with-args-until-success 'org-store-link-functions)
@@ -8246,9 +8207,10 @@ For file links, arg negates `org-context-in-file-links'."
(get-text-property (point) 'org-marker))))
(when m
(org-with-point-at m
- (if (interactive-p)
- (call-interactively 'org-store-link)
- (org-store-link nil))))))
+ (setq agenda-link
+ (if (interactive-p)
+ (call-interactively 'org-store-link)
+ (org-store-link nil)))))))
((eq major-mode 'calendar-mode)
(let ((cd (calendar-cursor-to-date)))
@@ -8296,13 +8258,14 @@ For file links, arg negates `org-context-in-file-links'."
(setq cpltxt (concat "file:" file)
link (org-make-link cpltxt))))
- ((and buffer-file-name (org-mode-p))
+ ((and (buffer-file-name (buffer-base-buffer)) (org-mode-p))
(setq custom-id (ignore-errors (org-entry-get nil "CUSTOM_ID")))
(cond
((org-in-regexp "<<\\(.*?\\)>>")
(setq cpltxt
(concat "file:"
- (abbreviate-file-name buffer-file-name)
+ (abbreviate-file-name
+ (buffer-file-name (buffer-base-buffer)))
"::" (match-string 1))
link (org-make-link cpltxt)))
((and (featurep 'org-id)
@@ -8324,11 +8287,13 @@ For file links, arg negates `org-context-in-file-links'."
(error
;; probably before first headline, link to file only
(concat "file:"
- (abbreviate-file-name buffer-file-name))))))
+ (abbreviate-file-name
+ (buffer-file-name (buffer-base-buffer))))))))
(t
;; Just link to current headline
(setq cpltxt (concat "file:"
- (abbreviate-file-name buffer-file-name)))
+ (abbreviate-file-name
+ (buffer-file-name (buffer-base-buffer)))))
;; Add a context search string
(when (org-xor org-context-in-file-links arg)
(setq txt (cond
@@ -8385,7 +8350,7 @@ For file links, arg negates `org-context-in-file-links'."
"::#" custom-id))
(setq org-stored-links
(cons (list link desc) org-stored-links))))
- (and link (org-make-link-string link desc)))))
+ (or agenda-link (and link (org-make-link-string link desc))))))
(defun org-store-link-props (&rest plist)
"Store link properties, extract names and addresses."
@@ -8449,7 +8414,7 @@ according to FMT (default from `org-email-link-description-format')."
;; We are using a headline, clean up garbage in there.
(if (string-match org-todo-regexp s)
(setq s (replace-match "" t t s)))
- (if (string-match (org-re ":[[:alnum:]_@:]+:[ \t]*$") s)
+ (if (string-match (org-re ":[[:alnum:]_@#%:]+:[ \t]*$") s)
(setq s (replace-match "" t t s)))
(setq s (org-trim s))
(if (string-match (concat "^\\(" org-quote-string "\\|"
@@ -9065,7 +9030,7 @@ application the system uses for this file type."
(setq type (match-string 1) path (match-string 2))
(throw 'match t)))
(save-excursion
- (when (org-in-regexp (org-re "\\(:[[:alnum:]_@:]+\\):[ \t]*$"))
+ (when (org-in-regexp (org-re "\\(:[[:alnum:]_@#%:]+\\):[ \t]*$"))
(setq type "tags"
path (match-string 1))
(while (string-match ":" path)
@@ -9419,7 +9384,7 @@ in all files. If AVOID-POS is given, ignore matches near that position."
(when (equal (string-to-char s) ?*)
;; Anchor on headlines, post may include tags.
(setq pre "^\\*+[ \t]+\\(?:\\sw+\\)?[ \t]*"
- post (org-re "[ \t]*\\(?:[ \t]+:[[:alnum:]_@:+]:[ \t]*\\)?$")
+ post (org-re "[ \t]*\\(?:[ \t]+:[[:alnum:]_@#%:+]:[ \t]*\\)?$")
s (substring s 1)))
(remove-text-properties
0 (length s)
@@ -9939,15 +9904,9 @@ on the system \"/user@host:\"."
(setq level (org-reduced-level
(- (match-end 1) (match-beginning 1)))
txt (org-link-display-format (match-string 4))
- re (concat "^" (regexp-quote
- (buffer-substring
- (match-beginning 1)
- (match-end 4)))))
- (if (match-end 5) (setq re (concat
- re "[ \t]+"
- (regexp-quote
- (match-string 5)))))
- (setq re (concat re "[ \t]*$"))
+ txt (replace-regexp-in-string "\\( *\[[0-9]+/?[0-9]*%?\]\\)+$" "" txt)
+ re (format org-complex-heading-regexp-format
+ (regexp-quote (match-string 4))))
(when org-refile-use-outline-path
(setq txt (mapconcat
'org-protect-slash
@@ -10246,6 +10205,7 @@ This can be done with a 0 prefix: `C-0 C-c C-w'"
(setq answ (funcall cfunc prompt tbl nil (not new-nodes)
nil 'org-refile-history))
(setq pa (or (assoc answ tbl) (assoc (concat answ "/") tbl)))
+ (org-refile-check-position pa)
(if pa
(progn
(when (or (not org-refile-history)
@@ -10272,6 +10232,26 @@ This can be done with a 0 prefix: `C-0 C-c C-w'"
(org-refile-new-child parent-target child)))
(error "Invalid target location")))))
+(defun org-refile-check-position (refile-pointer)
+ "Check if the refile pointer matches the readline to which it points."
+ (let* ((file (nth 1 refile-pointer))
+ (re (nth 2 refile-pointer))
+ (pos (nth 3 refile-pointer))
+ buffer)
+ (when (org-string-nw-p re)
+ (setq buffer (if (markerp pos)
+ (marker-buffer pos)
+ (or (find-buffer-visiting file)
+ (find-file-noselect file))))
+ (with-current-buffer buffer
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char pos)
+ (beginning-of-line 1)
+ (unless (org-looking-at-p re)
+ (error "Invalid refile position, please rebuild the cache"))))))))
+
(defun org-refile-new-child (parent-target child)
"Use refile target PARENT-TARGET to add new CHILD below it."
(unless parent-target
@@ -10585,7 +10565,7 @@ At all other locations, this simply calls the value of
(let* ((a nil)
(end (point))
(beg1 (save-excursion
- (skip-chars-backward (org-re "[:alnum:]_@"))
+ (skip-chars-backward (org-re "[:alnum:]_@#%"))
(point)))
(beg (save-excursion
(skip-chars-backward "a-zA-Z0-9_:$")
@@ -11734,7 +11714,7 @@ This is done in the same way as adding a state change note."
(defvar org-property-end-re)
(defun org-add-log-setup (&optional purpose state prev-state
- findpos how &optional extra)
+ findpos how extra)
"Set up the post command hook to take a note.
If this is about to TODO state change, the new state is expected in STATE.
When FINDPOS is non-nil, find the correct position for the note in
@@ -11795,10 +11775,11 @@ EXTRA is additional text that will be inserted into the notes buffer."
(defun org-skip-over-state-notes ()
"Skip past the list of State notes in an entry."
(if (looking-at "\n[ \t]*- State") (forward-char 1))
- (while (looking-at "[ \t]*- State")
- (condition-case nil
- (org-next-item)
- (error (org-end-of-item)))))
+ (when (org-in-item-p)
+ (let ((limit (org-list-bottom-point)))
+ (while (looking-at "[ \t]*- State")
+ (goto-char (or (org-get-next-item (point) limit)
+ (org-get-end-of-item limit)))))))
(defun org-add-log-note (&optional purpose)
"Pop up a window for taking a note, and add this note later at point."
@@ -11843,7 +11824,7 @@ EXTRA is additional text that will be inserted into the notes buffer."
"Finish taking a log note, and insert it to where it belongs."
(let ((txt (buffer-string))
(note (cdr (assq org-log-note-purpose org-log-note-headings)))
- lines ind)
+ lines ind bul)
(kill-buffer (current-buffer))
(while (string-match "\\`#.*\n[ \t\n]*" txt)
(setq txt (replace-match "" t t txt)))
@@ -11883,13 +11864,26 @@ EXTRA is additional text that will be inserted into the notes buffer."
(move-marker org-log-note-marker nil)
(end-of-line 1)
(if (not (bolp)) (let ((inhibit-read-only t)) (insert "\n")))
- (insert "- " (pop lines))
- (org-indent-line-function)
- (beginning-of-line 1)
- (looking-at "[ \t]*")
- (setq ind (concat (match-string 0) " "))
- (end-of-line 1)
- (while lines (insert "\n" ind (pop lines)))
+ (setq ind (save-excursion
+ (if (org-in-item-p)
+ (progn
+ (goto-char (org-list-top-point))
+ (org-get-indentation))
+ (skip-chars-backward " \r\t\n")
+ (cond
+ ((and (org-at-heading-p)
+ org-adapt-indentation)
+ (1+ (org-current-level)))
+ ((org-at-heading-p) 0)
+ (t (org-get-indentation))))))
+ (setq bul (org-list-bullet-string "-"))
+ (org-indent-line-to ind)
+ (insert bul (pop lines))
+ (let ((ind-body (+ (length bul) ind)))
+ (while lines
+ (insert "\n")
+ (org-indent-line-to ind-body)
+ (insert (pop lines))))
(message "Note stored")
(org-back-to-heading t)
(org-cycle-hide-drawers 'children)))))
@@ -12127,7 +12121,8 @@ ACTION can be `set', `up', `down', or a character."
(setq new action)
(message "Priority %c-%c, SPC to remove: "
org-highest-priority org-lowest-priority)
- (setq new (read-char-exclusive)))
+ (save-match-data
+ (setq new (read-char-exclusive))))
(if (and (= (upcase org-highest-priority) org-highest-priority)
(= (upcase org-lowest-priority) org-lowest-priority))
(setq new (upcase new)))
@@ -12212,7 +12207,7 @@ only lines with a TODO keyword are included in the output."
(let* ((re (concat "^" outline-regexp " *\\(\\<\\("
(mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
(org-re
- "\\>\\)\\)? *\\(.*?\\)\\(:[[:alnum:]_@:]+:\\)?[ \t]*$")))
+ "\\>\\)\\)? *\\(.*?\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*$")))
(props (list 'face 'default
'done-face 'org-agenda-done
'undone-face 'default
@@ -12412,7 +12407,7 @@ also TODO lines."
;; Parse the string and create a lisp form
(let ((match0 match)
- (re (org-re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL\\([<=>]\\{1,2\\}\\)\\([0-9]+\\)\\|\\([[:alnum:]_]+\\)\\([<>=]\\{1,2\\}\\)\\({[^}]+}\\|\"[^\"]*\"\\|-?[.0-9]+\\(?:[eE][-+]?[0-9]+\\)?\\)\\|[[:alnum:]_@]+\\)"))
+ (re (org-re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL\\([<=>]\\{1,2\\}\\)\\([0-9]+\\)\\|\\(\\(?:[[:alnum:]_]+\\(?:\\\\-\\)*\\)+\\)\\([<>=]\\{1,2\\}\\)\\({[^}]+}\\|\"[^\"]*\"\\|-?[.0-9]+\\(?:[eE][-+]?[0-9]+\\)?\\)\\|[[:alnum:]_@#%]+\\)"))
minus tag mm
tagsmatch todomatch tagsmatcher todomatcher kwd matcher
orterms term orlist re-p str-p level-p level-op time-p
@@ -12440,7 +12435,9 @@ also TODO lines."
(setq rest (substring term (match-end 0))
minus (and (match-end 1)
(equal (match-string 1 term) "-"))
- tag (match-string 2 term)
+ tag (save-match-data (replace-regexp-in-string
+ "\\\\-" "-"
+ (match-string 2 term)))
re-p (equal (string-to-char tag) ?{)
level-p (match-end 4)
prop-p (match-end 5)
@@ -12619,7 +12616,7 @@ ignore inherited ones."
(while (not (equal lastpos (point)))
(setq lastpos (point))
(when (looking-at
- (org-re "[^\r\n]+?:\\([[:alnum:]_@:]+\\):[ \t]*$"))
+ (org-re "[^\r\n]+?:\\([[:alnum:]_@#%:]+\\):[ \t]*$"))
(setq ltags (org-split-string
(org-match-string-no-properties 1) ":"))
(when parent
@@ -12646,7 +12643,7 @@ If ONOFF is `on' or `off', don't toggle but set to this state."
(let (res current)
(save-excursion
(org-back-to-heading t)
- (if (re-search-forward (org-re "[ \t]:\\([[:alnum:]_@:]+\\):[ \t]*$")
+ (if (re-search-forward (org-re "[ \t]:\\([[:alnum:]_@#%:]+\\):[ \t]*$")
(point-at-eol) t)
(progn
(setq current (match-string 1))
@@ -12676,7 +12673,7 @@ If ONOFF is `on' or `off', don't toggle but set to this state."
;; Assumes that this is a headline
(let ((pos (point)) (col (current-column)) ncol tags-l p)
(beginning-of-line 1)
- (if (and (looking-at (org-re ".*?\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$"))
+ (if (and (looking-at (org-re ".*?\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))
(< pos (match-beginning 2)))
(progn
(setq tags-l (- (match-end 2) (match-beginning 2)))
@@ -12746,6 +12743,7 @@ If DATA is nil or the empty string, any tags will be removed."
(org-set-tags t)
(message "No headings"))))
+(defvar org-indent-indentation-per-level)
(defun org-set-tags (&optional arg just-align)
"Set the tags for the current headline.
With prefix ARG, realign all tags in headings in the current buffer."
@@ -12755,7 +12753,7 @@ With prefix ARG, realign all tags in headings in the current buffer."
(col (current-column))
(org-setting-tags t)
table current-tags inherited-tags ; computed below when needed
- tags p0 c0 c1 rpl)
+ tags p0 c0 c1 rpl di tc level)
(if arg
(save-excursion
(goto-char (point-min))
@@ -12795,7 +12793,7 @@ With prefix ARG, realign all tags in headings in the current buffer."
(if org-tags-sort-function
(setq tags (mapconcat 'identity
- (sort (org-split-string tags (org-re "[^[:alnum:]_@]+"))
+ (sort (org-split-string tags (org-re "[^[:alnum:]_@#%]+"))
org-tags-sort-function) ":")))
(if (string-match "\\`[\t ]*\\'" tags)
@@ -12805,6 +12803,9 @@ With prefix ARG, realign all tags in headings in the current buffer."
;; Insert new tags at the correct column
(beginning-of-line 1)
+ (setq level (or (and (looking-at org-outline-regexp)
+ (- (match-end 0) (point) 1))
+ 1))
(cond
((and (equal current "") (equal tags "")))
((re-search-forward
@@ -12813,11 +12814,14 @@ With prefix ARG, realign all tags in headings in the current buffer."
(if (equal tags "")
(setq rpl "")
(goto-char (match-beginning 0))
- (setq c0 (current-column) p0 (if (equal (char-before) ?*)
- (1+ (point)) (point))
- c1 (max (1+ c0) (if (> org-tags-column 0)
- org-tags-column
- (- (- org-tags-column) (length tags))))
+ (setq c0 (current-column)
+ ;; compute offset for the case of org-indent-mode active
+ di (if org-indent-mode
+ (* (1- org-indent-indentation-per-level) (1- level))
+ 0)
+ p0 (if (equal (char-before) ?*) (1+ (point)) (point))
+ tc (+ org-tags-column (if (> org-tags-column 0) (- di) di))
+ c1 (max (1+ c0) (if (> tc 0) tc (- (- tc) (length tags))))
rpl (concat (make-string (max 0 (- c1 c0)) ?\ ) tags)))
(replace-match rpl t t)
(and (not (featurep 'xemacs)) c0 indent-tabs-mode (tabify p0 (point)))
@@ -12946,7 +12950,7 @@ Returns the new tags string, or nil to not change the current settings."
(save-excursion
(beginning-of-line 1)
(if (looking-at
- (org-re ".*[ \t]\\(:[[:alnum:]_@:]+:\\)[ \t]*$"))
+ (org-re ".*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))
(setq ov-start (match-beginning 1)
ov-end (match-end 1)
ov-prefix "")
@@ -13096,7 +13100,7 @@ Returns the new tags string, or nil to not change the current settings."
(org-fast-tag-insert "Current" current c-face)
(org-set-current-tags-overlay current ov-prefix)
(while (re-search-forward
- (org-re "\\[.\\] \\([[:alnum:]_@]+\\)") nil t)
+ (org-re "\\[.\\] \\([[:alnum:]_@#%]+\\)") nil t)
(setq tg (match-string 1))
(add-text-properties
(match-beginning 1) (match-end 1)
@@ -13117,7 +13121,7 @@ Returns the new tags string, or nil to not change the current settings."
(error "Not on a heading"))
(save-excursion
(beginning-of-line 1)
- (if (looking-at (org-re ".*[ \t]\\(:[[:alnum:]_@:]+:\\)[ \t]*$"))
+ (if (looking-at (org-re ".*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))
(org-match-string-no-properties 1)
"")))
@@ -13131,7 +13135,7 @@ Returns the new tags string, or nil to not change the current settings."
(save-excursion
(goto-char (point-min))
(while (re-search-forward
- (org-re "[ \t]:\\([[:alnum:]_@:]+\\):[ \t\r\n]") nil t)
+ (org-re "[ \t]:\\([[:alnum:]_@#%:]+\\):[ \t\r\n]") nil t)
(when (equal (char-after (point-at-bol 0)) ?*)
(mapc (lambda (x) (add-to-list 'tags x))
(org-split-string (org-match-string-no-properties 1) ":")))))
@@ -14002,7 +14006,7 @@ only headings."
(when (org-on-heading-p)
(move-marker (make-marker) (point))))))))
-(defun org-find-exact-headling-in-buffer (heading &optional buffer pos-only)
+(defun org-find-exact-headline-in-buffer (heading &optional buffer pos-only)
"Find node HEADING in BUFFER.
Return a marker to the heading if it was found, or nil if not.
If POS-ONLY is set, return just the position instead of a marker.
@@ -14033,7 +14037,7 @@ When the target headline is found, return a marker to this location."
(message "trying %s" file)
(setq visiting (org-find-base-buffer-visiting file))
(setq buffer (or visiting (find-file-noselect file)))
- (setq m (org-find-exact-headling-in-buffer
+ (setq m (org-find-exact-headline-in-buffer
heading buffer))
(when (and (not m) (not visiting)) (kill-buffer buffer))
(and m (throw 'found m))))))
@@ -14329,6 +14333,10 @@ user."
(setq org-read-date-overlay nil)))))
(setq final (org-read-date-analyze ans def defdecode))
+
+ ;; One round trip to get rid of 34th of August and stuff like that....
+ (setq final (decode-time (apply 'encode-time final)))
+
(setq org-read-date-final-answer ans)
(if to-time
@@ -14596,9 +14604,10 @@ user function argument order change dependent on argument order."
(list arg2 arg1 arg3))
((eq calendar-date-style 'iso)
(list arg2 arg3 arg1)))
- (if (org-bound-and-true-p european-calendar-style)
- (list arg2 arg1 arg3)
- (list arg1 arg2 arg3))))
+ (with-no-warnings ;; european-calendar-style is obsolete as of version 23.1
+ (if (org-bound-and-true-p european-calendar-style)
+ (list arg2 arg1 arg3)
+ (list arg1 arg2 arg3)))))
(defun org-eval-in-calendar (form &optional keepdate)
"Eval FORM in the calendar window and return to current window.
@@ -15969,14 +15978,14 @@ Some of the options can be changed using the variable
(unless checkdir ; make sure the directory exists
(setq checkdir t)
(or (file-directory-p todir) (make-directory todir t)))
-
+
(unless executables-checked
(org-check-external-command
"latex" "needed to convert LaTeX fragments to images")
(org-check-external-command
"dvipng" "needed to convert LaTeX fragments to images")
(setq executables-checked t))
-
+
(unless (file-exists-p movefile)
(org-create-formula-image
txt movefile opt forbuffer))
@@ -16392,10 +16401,12 @@ BEG and END default to the buffer boundaries."
(org-defkey org-mode-map "\C-c\C-xo" 'org-toggle-ordered-property)
(org-defkey org-mode-map "\C-c\C-xi" 'org-insert-columns-dblock)
(org-defkey org-mode-map [(control ?c) (control ?x) ?\;] 'org-timer-set-timer)
+(org-defkey org-mode-map [(control ?c) (control ?x) ?\:] 'org-timer-cancel-timer)
(org-defkey org-mode-map "\C-c\C-x." 'org-timer)
(org-defkey org-mode-map "\C-c\C-x-" 'org-timer-item)
(org-defkey org-mode-map "\C-c\C-x0" 'org-timer-start)
+(org-defkey org-mode-map "\C-c\C-x_" 'org-timer-stop)
(org-defkey org-mode-map "\C-c\C-x," 'org-timer-pause-or-continue)
(define-key org-mode-map "\C-c\C-x\C-c" 'org-columns)
@@ -16584,9 +16595,11 @@ because, in this case the deletion might narrow the column."
(noalign (looking-at "[^|\n\r]* |"))
(c org-table-may-need-update))
(backward-delete-char N)
- (skip-chars-forward "^|")
- (insert " ")
- (goto-char (1- pos))
+ (if (not overwrite-mode)
+ (progn
+ (skip-chars-forward "^|")
+ (insert " ")
+ (goto-char (1- pos))))
;; noalign: if there were two spaces at the end, this field
;; does not determine the width of the column.
(if noalign (setq org-table-may-need-update c)))
@@ -17229,12 +17242,12 @@ This command does many different things, depending on context:
(org-footnote-at-definition-p))
(call-interactively 'org-footnote-action))
((org-at-item-checkbox-p)
+ (call-interactively 'org-list-repair)
(call-interactively 'org-toggle-checkbox)
(org-list-send-list 'maybe))
((org-at-item-p)
- (if arg
- (call-interactively 'org-toggle-checkbox)
- (call-interactively 'org-maybe-renumber-ordered-list))
+ (call-interactively 'org-list-repair)
+ (when arg (call-interactively 'org-toggle-checkbox))
(org-list-send-list 'maybe))
((save-excursion (beginning-of-line 1) (looking-at org-dblock-start-re))
;; Dynamic block
@@ -17291,7 +17304,7 @@ See the individual commands for more information."
(call-interactively 'org-open-at-point))
((and (org-at-heading-p)
(looking-at
- (org-re "\\([ \t]+\\(:[[:alnum:]_@:]+:\\)\\)[ \t]*$")))
+ (org-re "\\([ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)[ \t]*$")))
(org-show-entry)
(end-of-line 1)
(newline))
@@ -17357,21 +17370,21 @@ If the first line is normal text, add an item bullet to each line."
;; We already have items, de-itemize
(while (< (setq l (1+ l)) l2)
(when (org-at-item-p)
- (goto-char (match-beginning 2))
- (delete-region (match-beginning 2) (match-end 2))
- (and (looking-at "[ \t]+") (replace-match "")))
+ (skip-chars-forward " \t")
+ (delete-region (point) (match-end 0)))
(beginning-of-line 2))
(if (org-on-heading-p)
;; Headings, convert to items
(while (< (setq l (1+ l)) l2)
(if (looking-at org-outline-regexp)
- (replace-match "- " t t))
+ (replace-match (org-list-bullet-string "-") t t))
(beginning-of-line 2))
;; normal lines, turn them into items
(while (< (setq l (1+ l)) l2)
(unless (org-at-item-p)
(if (looking-at "\\([ \t]*\\)\\(\\S-\\)")
- (replace-match "\\1- \\2")))
+ (replace-match
+ (concat "\\1" (org-list-bullet-string "-") "\\2"))))
(beginning-of-line 2)))))))
(defun org-toggle-heading (&optional nstars)
@@ -18254,16 +18267,23 @@ really on, so that the block visually is on the match."
(throw 'exit t)))
nil))))
-(defun org-in-regexps-block-p (start-re end-re)
- "Return t if the current point is between matches of START-RE and END-RE.
-This will also return to if point is on one of the two matches."
- (interactive)
- (let ((p (point)))
+(defun org-in-regexps-block-p (start-re end-re &optional bound)
+ "Returns t if the current point is between matches of START-RE and END-RE.
+This will also return t if point is on one of the two matches or
+in an unfinished block. END-RE can be a string or a form
+returning a string.
+
+An optional third argument bounds the search for START-RE. It
+defaults to previous heading or `point-min'."
+ (let ((pos (point))
+ (limit (or bound (save-excursion (outline-previous-heading)))))
(save-excursion
- (and (or (org-at-regexp-p start-re)
- (re-search-backward start-re nil t))
- (re-search-forward end-re nil t)
- (>= (point) p)))))
+ ;; we're on a block when point is on start-re...
+ (or (org-at-regexp-p start-re)
+ ;; ... or start-re can be found above...
+ (and (re-search-backward start-re limit t)
+ ;; ... but no end-re between start-re and point.
+ (not (re-search-forward (eval end-re) pos t)))))))
(defun org-occur-in-agenda-files (regexp &optional nlines)
"Call `multi-occur' with buffers for all agenda files."
@@ -18543,57 +18563,87 @@ which make use of the date at the cursor."
;; Find the previous relevant line
(beginning-of-line 1)
(cond
+ ;; Comments
((looking-at "#") (setq column 0))
+ ;; Headings
((looking-at "\\*+ ") (setq column 0))
+ ;; Drawers
((and (looking-at "[ \t]*:END:")
(save-excursion (re-search-backward org-drawer-regexp nil t)))
(save-excursion
(goto-char (1- (match-beginning 1)))
(setq column (current-column))))
- ((and (looking-at "[ \t]+#\\+end_\\([a-z]+\\)")
+ ;; Special blocks
+ ((and (looking-at "[ \t]*#\\+end_\\([a-z]+\\)")
(save-excursion
(re-search-backward
(concat "^[ \t]*#\\+begin_" (downcase (match-string 1))) nil t)))
(setq column (org-get-indentation (match-string 0))))
+ ((and (not (looking-at "[ \t]*#\\+begin_"))
+ (org-in-regexps-block-p "^[ \t]*#\\+begin_" "[ \t]*#\\+end_"))
+ (save-excursion
+ (re-search-backward "^[ \t]*#\\+begin_\\([a-z]+\\)" nil t))
+ (setq column
+ (if (equal (downcase (match-string 1)) "src")
+ ;; src blocks: let `org-edit-src-exit' handle them
+ (org-get-indentation)
+ (org-get-indentation (match-string 0)))))
+ ;; Lists
+ ((org-in-item-p)
+ (org-beginning-of-item)
+ (looking-at "[ \t]*\\(\\S-+\\)[ \t]*\\(\\(:?\\[@\\(:?start:\\)?[0-9]+\\][ \t]*\\)?\\[[- X]\\][ \t]*\\|.*? :: \\)?")
+ (setq bpos (match-beginning 1) tpos (match-end 0)
+ bcol (progn (goto-char bpos) (current-column))
+ tcol (progn (goto-char tpos) (current-column))
+ bullet (match-string 1)
+ bullet-type (if (string-match "[0-9]" bullet) "n" bullet))
+ (if (> tcol (+ bcol org-description-max-indent))
+ (setq tcol (+ bcol 5)))
+ (if (not itemp)
+ (setq column tcol)
+ (beginning-of-line 1)
+ (goto-char pos)
+ (if (looking-at "\\S-")
+ (progn
+ (looking-at "[ \t]*\\(\\S-+\\)[ \t]*")
+ (setq bullet (match-string 1)
+ btype (if (string-match "[0-9]" bullet) "n" bullet))
+ (setq column (if (equal btype bullet-type) bcol tcol)))
+ (setq column (org-get-indentation)))))
+ ;; This line has nothing special, look upside to get a clue about
+ ;; what to do.
(t
(beginning-of-line 0)
(while (and (not (bobp)) (looking-at "[ \t]*[\n:#|]")
- (not (looking-at "[ \t]*:END:"))
- (not (looking-at org-drawer-regexp)))
- (beginning-of-line 0))
+ (not (looking-at "[ \t]*:END:"))
+ (not (looking-at org-drawer-regexp)))
+ (beginning-of-line 0))
(cond
+ ;; There was an heading above.
((looking-at "\\*+[ \t]+")
(if (not org-adapt-indentation)
(setq column 0)
(goto-char (match-end 0))
(setq column (current-column))))
+ ;; A drawer had started and is unfinished: indent consequently.
((looking-at org-drawer-regexp)
- (goto-char (1- (match-beginning 1)))
- (setq column (current-column)))
+ (goto-char (1- (match-beginning 1)))
+ (setq column (current-column)))
+ ;; The drawer had ended: indent like its :END: line.
((looking-at "\\([ \t]*\\):END:")
- (goto-char (match-end 1))
- (setq column (current-column)))
+ (goto-char (match-end 1))
+ (setq column (current-column)))
+ ;; There was a list that since ended: indent relatively to
+ ;; current heading.
((org-in-item-p)
- (org-beginning-of-item)
- (looking-at "[ \t]*\\(\\S-+\\)[ \t]*\\(\\[[- X]\\][ \t]*\\|.*? :: \\)?")
- (setq bpos (match-beginning 1) tpos (match-end 0)
- bcol (progn (goto-char bpos) (current-column))
- tcol (progn (goto-char tpos) (current-column))
- bullet (match-string 1)
- bullet-type (if (string-match "[0-9]" bullet) "n" bullet))
- (if (> tcol (+ bcol org-description-max-indent))
- (setq tcol (+ bcol 5)))
- (if (not itemp)
- (setq column tcol)
- (goto-char pos)
- (beginning-of-line 1)
- (if (looking-at "\\S-")
- (progn
- (looking-at "[ \t]*\\(\\S-+\\)[ \t]*")
- (setq bullet (match-string 1)
- btype (if (string-match "[0-9]" bullet) "n" bullet))
- (setq column (if (equal btype bullet-type) bcol tcol)))
- (setq column (org-get-indentation)))))
+ (outline-previous-heading)
+ (if (and org-adapt-indentation
+ (looking-at "\\*+[ \t]+"))
+ (progn
+ (goto-char (match-end 0))
+ (setq column (current-column)))
+ (setq column 0)))
+ ;; Else, nothing noticeable found: get indentation and go on.
(t (setq column (org-get-indentation))))))
(goto-char pos)
(if (<= (current-column) (current-indentation))
@@ -18852,7 +18902,7 @@ beyond the end of the headline."
(t 'end-of-line)))
(let ((pos (point)))
(beginning-of-line 1)
- (if (looking-at (org-re ".*?\\(?:\\([ \t]*\\)\\(:[[:alnum:]_@:]+:\\)?[ \t]*\\)?$"))
+ (if (looking-at (org-re ".*?\\(?:\\([ \t]*\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*\\)?$"))
(if (eq special t)
(if (or (< pos (match-beginning 1))
(= pos (match-end 0)))
@@ -18906,7 +18956,7 @@ depending on context."
(not (y-or-n-p "Kill hidden subtree along with headline? ")))
(error "C-k aborted - would kill hidden subtree")))
(call-interactively 'kill-line))
- ((looking-at (org-re ".*?\\S-\\([ \t]+\\(:[[:alnum:]_@:]+:\\)\\)[ \t]*$"))
+ ((looking-at (org-re ".*?\\S-\\([ \t]+\\(:[[:alnum:]_@#%:]+:\\)\\)[ \t]*$"))
(kill-region (point) (match-beginning 1))
(org-set-tags nil t))
(t (kill-region (point) (point-at-eol)))))
diff --git a/xemacs/README b/xemacs/README
deleted file mode 100644
index 00c332c..0000000
--- a/xemacs/README
+++ /dev/null
@@ -1,15 +0,0 @@
-This directory contains files that are necessary or at least useful
-companions for Org-mode under XEmacs:
-
-noutline.el
-
- Greg Chernov's port of the overlay-based implementation of
- outline-mode. This is required, and until XEmacs uses this (or
- another port), you need to install it with Org-mode. The "Installation"
- section in the Manual covers also the installation of this package.
-
-ps-print-invisible.el
-
- Greg Chernovs modification to ps-print, to honor invisible text
- properties during printing. This file is not required for running
- Org-mode, but it is useful when trying to print partial trees. \ No newline at end of file
diff --git a/xemacs/noutline.el b/xemacs/noutline.el
deleted file mode 100644
index f9ea1da..0000000
--- a/xemacs/noutline.el
+++ /dev/null
@@ -1,1051 +0,0 @@
-;;; outline.el --- outline mode commands for Emacs
-
-;; ----------------------------------------------------------------------
-;; This is a port of GNU Emacs outline.el to XEmacs. The port was
-;; done by Greg Chernov and is temporarily made available on the Org-mode
-;; homepage http://www.astro.uva.nl/~dominik/Tools/org/, and as part
-;; of the Org-mode distribution.
-;; ----------------------------------------------------------------------
-
-;; Copyright (C) 1986, 1993, 1994, 1995, 1997, 2000, 2001, 2002,
-;; 2003, 2004, 2005 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: outlines
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; This package is a major mode for editing outline-format documents.
-;; An outline can be `abstracted' to show headers at any given level,
-;; with all stuff below hidden. See the Emacs manual for details.
-
-;;; Todo:
-
-;; - subtree-terminators
-;; - better handle comments before function bodies (i.e. heading)
-;; - don't bother hiding whitespace
-
-;;; Code:
-
-(require 'xemacs)
-(require 'easymenu)
-
-;; XEmacs and compatibility
-
-(defalias 'match-string-no-properties 'match-string)
-
-(if (not (fboundp 'add-to-invisibility-spec))
- (defun add-to-invisibility-spec (arg)
- "Add elements to `buffer-invisibility-spec'.
-See documentation for `buffer-invisibility-spec' for the kind of elements
-that can be added."
- (if (eq buffer-invisibility-spec t)
- (setq buffer-invisibility-spec (list t)))
- (setq buffer-invisibility-spec
- (cons arg buffer-invisibility-spec))))
-
-(if (not (fboundp 'remove-from-invisibility-spec))
- (defun remove-from-invisibility-spec (arg)
- "Remove elements from `buffer-invisibility-spec'."
- (if (consp buffer-invisibility-spec)
- (setq buffer-invisibility-spec
- (delete arg buffer-invisibility-spec)))))
-
-(defvar font-lock-warning-face)
-
-
-(defgroup outlines nil
- "Support for hierarchical outlining."
- :prefix "outline-"
- :group 'editing)
-
-(defcustom outline-regexp "[*\^L]+"
- "Regular expression to match the beginning of a heading.
-Any line whose beginning matches this regexp is considered to start a heading.
-Note that Outline mode only checks this regexp at the start of a line,
-so the regexp need not (and usually does not) start with `^'.
-The recommended way to set this is with a Local Variables: list
-in the file it applies to. See also `outline-heading-end-regexp'."
- :type '(choice regexp (const nil))
- :group 'outlines)
-
-(defcustom outline-heading-end-regexp "\n"
- "Regular expression to match the end of a heading line.
-You can assume that point is at the beginning of a heading when this
-regexp is searched for. The heading ends at the end of the match.
-The recommended way to set this is with a `Local Variables:' list
-in the file it applies to."
- :type 'regexp
- :group 'outlines)
-
-(defvar outline-mode-prefix-map
- (let ((map (make-sparse-keymap)))
- (define-key map "@" 'outline-mark-subtree)
- (define-key map "\C-n" 'outline-next-visible-heading)
- (define-key map "\C-p" 'outline-previous-visible-heading)
- (define-key map "\C-i" 'show-children)
- (define-key map "\C-s" 'show-subtree)
- (define-key map "\C-d" 'hide-subtree)
- (define-key map "\C-u" 'outline-up-heading)
- (define-key map "\C-f" 'outline-forward-same-level)
- (define-key map "\C-b" 'outline-backward-same-level)
- (define-key map "\C-t" 'hide-body)
- (define-key map "\C-a" 'show-all)
- (define-key map "\C-c" 'hide-entry)
- (define-key map "\C-e" 'show-entry)
- (define-key map "\C-l" 'hide-leaves)
- (define-key map "\C-k" 'show-branches)
- (define-key map "\C-q" 'hide-sublevels)
- (define-key map "\C-o" 'hide-other)
- (define-key map "\C-^" 'outline-move-subtree-up)
- (define-key map "\C-v" 'outline-move-subtree-down)
- (define-key map [(control ?<)] 'outline-promote)
- (define-key map [(control ?>)] 'outline-demote)
- (define-key map "\C-m" 'outline-insert-heading)
- ;; Where to bind outline-cycle ?
- map))
-
-
-
-(defvar outline-mode-menu-heading
- '("Headings"
- ["Up" outline-up-heading t]
- ["Next" outline-next-visible-heading t]
- ["Previous" outline-previous-visible-heading t]
- ["Next Same Level" outline-forward-same-level t]
- ["Previous Same Level" outline-backward-same-level t]
- ["New heading" outline-insert-heading t]
- ["Copy to kill ring" outline-headers-as-kill :active (region-active-p)]
- ["Move subtree up" outline-move-subtree-up t]
- ["Move subtree down" outline-move-subtree-down t]
- ["Promote subtree" outline-promote t]
- ["Demote subtree" outline-demote t]))
-
-(defvar outline-mode-menu-show
- '("Show"
- ["Show All" show-all t]
- ["Show Entry" show-entry t]
- ["Show Branches" show-branches t]
- ["Show Children" show-children t]
- ["Show Subtree" show-subtree t]))
-
-(defvar outline-mode-menu-hide
- '("Hide"
- ["Hide Leaves" hide-leaves t]
- ["Hide Body" hide-body t]
- ["Hide Entry" hide-entry t]
- ["Hide Subtree" hide-subtree t]
- ["Hide Other" hide-other t]
- ["Hide Sublevels" hide-sublevels t]))
-
-
-
-(defvar outline-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c" outline-mode-prefix-map)
- map))
-
-(defvar outline-font-lock-keywords
- '(;;
- ;; Highlight headings according to the level.
- (eval . (list (concat "^\\(?:" outline-regexp "\\).+")
- 0 '(outline-font-lock-face) nil t)))
- "Additional expressions to highlight in Outline mode.")
-
-(defface outline-1
- '((t (:foreground "Blue1")))
- "Level 1."
- :group 'outlines)
-
-(defface outline-2
- '((t (:foreground "DarkGoldenrod")))
- "Level 2."
- :group 'outlines)
-
-(defface outline-3
- '((t (:foreground "Purple")))
- "Level 3."
- :group 'outlines)
-
-(defface outline-4
- '((t (:foreground "Firebrick")))
- "Level 4."
- :group 'outlines)
-
-(defface outline-5
- '((t (:foreground "ForestGreen")))
- "Level 5."
- :group 'outlines)
-
-(defface outline-6
- '((t (:foreground "CadetBlue")))
- "Level 6."
- :group 'outlines)
-
-(defface outline-7
- '((t (:foreground "Orchid")))
- "Level 7."
- :group 'outlines)
-
-(defface outline-8
- '((t (:foreground "RosyBrown")))
- "Level 8."
- :group 'outlines)
-
-
-
-(defvar outline-font-lock-faces
- [outline-1 outline-2 outline-3 outline-4
- outline-5 outline-6 outline-7 outline-8])
-
-(defvar outline-font-lock-levels nil)
-(make-variable-buffer-local 'outline-font-lock-levels)
-
-(defun outline-font-lock-face ()
- ;; (save-excursion
- ;; (outline-back-to-heading t)
- ;; (let* ((count 0)
- ;; (start-level (funcall outline-level))
- ;; (level start-level)
- ;; face-level)
- ;; (while (not (setq face-level
- ;; (if (or (bobp) (eq level 1)) 0
- ;; (cdr (assq level outline-font-lock-levels)))))
- ;; (outline-up-heading 1 t)
- ;; (setq count (1+ count))
- ;; (setq level (funcall outline-level)))
- ;; ;; Remember for later.
- ;; (unless (zerop count)
- ;; (setq face-level (+ face-level count))
- ;; (push (cons start-level face-level) outline-font-lock-levels))
- ;; (condition-case nil
- ;; (aref outline-font-lock-faces face-level)
- ;; (error font-lock-warning-face))))
- (save-excursion
- (goto-char (match-beginning 0))
- (looking-at outline-regexp)
- (condition-case nil
- (aref outline-font-lock-faces (1- (funcall outline-level)))
- (error font-lock-warning-face))))
-
-(defvar outline-view-change-hook nil
- "Normal hook to be run after outline visibility changes.")
-
-(defvar outline-mode-hook nil
- "This hook is run when outline mode starts.")
-
-(defvar outline-blank-line nil
- "Non-nil means to leave unhidden blank line before heading.")
-
-;;;###autoload
-(define-derived-mode outline-mode text-mode "Outline"
- "Set major mode for editing outlines with selective display.
-Headings are lines which start with asterisks: one for major headings,
-two for subheadings, etc. Lines not starting with asterisks are body lines.
-
-Body text or subheadings under a heading can be made temporarily
-invisible, or visible again. Invisible lines are attached to the end
-of the heading, so they move with it, if the line is killed and yanked
-back. A heading with text hidden under it is marked with an ellipsis (...).
-
-Commands:\\<outline-mode-map>
-\\[outline-next-visible-heading] outline-next-visible-heading move by visible headings
-\\[outline-previous-visible-heading] outline-previous-visible-heading
-\\[outline-forward-same-level] outline-forward-same-level similar but skip subheadings
-\\[outline-backward-same-level] outline-backward-same-level
-\\[outline-up-heading] outline-up-heading move from subheading to heading
-
-\\[hide-body] make all text invisible (not headings).
-\\[show-all] make everything in buffer visible.
-\\[hide-sublevels] make only the first N levels of headers visible.
-
-The remaining commands are used when point is on a heading line.
-They apply to some of the body or subheadings of that heading.
-\\[hide-subtree] hide-subtree make body and subheadings invisible.
-\\[show-subtree] show-subtree make body and subheadings visible.
-\\[show-children] show-children make direct subheadings visible.
- No effect on body, or subheadings 2 or more levels down.
- With arg N, affects subheadings N levels down.
-\\[hide-entry] make immediately following body invisible.
-\\[show-entry] make it visible.
-\\[hide-leaves] make body under heading and under its subheadings invisible.
- The subheadings remain visible.
-\\[show-branches] make all subheadings at all levels visible.
-
-The variable `outline-regexp' can be changed to control what is a heading.
-A line is a heading if `outline-regexp' matches something at the
-beginning of the line. The longer the match, the deeper the level.
-
-Turning on outline mode calls the value of `text-mode-hook' and then of
-`outline-mode-hook', if they are non-nil."
- (make-local-variable 'line-move-ignore-invisible)
- (setq line-move-ignore-invisible t)
- ;; Cause use of ellipses for invisible text.
- (add-to-invisibility-spec '(outline . t))
-
- (easy-menu-add outline-mode-menu-heading)
- (easy-menu-add outline-mode-menu-show)
- (easy-menu-add outline-mode-menu-hide)
- (set (make-local-variable 'paragraph-start)
- (concat paragraph-start "\\|\\(?:" outline-regexp "\\)"))
- ;; Inhibit auto-filling of header lines.
- (set (make-local-variable 'auto-fill-inhibit-regexp) outline-regexp)
- (set (make-local-variable 'paragraph-separate)
- (concat paragraph-separate "\\|\\(?:" outline-regexp "\\)"))
- (set (make-local-variable 'font-lock-defaults)
- '(outline-font-lock-keywords t nil nil backward-paragraph))
- (setq imenu-generic-expression
- (list (list nil (concat "^\\(?:" outline-regexp "\\).*$") 0)))
- (add-hook 'change-major-mode-hook 'show-all nil t))
-
-(defcustom outline-minor-mode-prefix "\C-c@"
- "Prefix key to use for Outline commands in Outline minor mode.
-The value of this variable is checked as part of loading Outline mode.
-After that, changing the prefix key requires manipulating keymaps."
- :type 'string
- :group 'outlines)
-
-;;;###autoload
-(define-minor-mode outline-minor-mode
- "Toggle Outline minor mode.
-With arg, turn Outline minor mode on if arg is positive, off otherwise.
-See the command `outline-mode' for more information on this mode."
- nil " Outl" (list (cons outline-minor-mode-prefix outline-mode-prefix-map))
- :group 'outlines
- (if outline-minor-mode
- (progn
- ;; Turn off this mode if we change major modes.
- (easy-menu-add outline-mode-menu-heading)
- (easy-menu-add outline-mode-menu-show)
- (easy-menu-add outline-mode-menu-hide)
- (add-hook 'change-major-mode-hook
- (lambda () (outline-minor-mode -1))
- nil t)
- (set (make-local-variable 'line-move-ignore-invisible) t)
- ;; Cause use of ellipses for invisible text.
- (add-to-invisibility-spec '(outline . t)))
- (easy-menu-remove outline-mode-menu-heading)
- (easy-menu-remove outline-mode-menu-show)
- (easy-menu-remove outline-mode-menu-hide)
- (setq line-move-ignore-invisible nil)
- ;; Cause use of ellipses for invisible text.
- (remove-from-invisibility-spec '(outline . t))
- ;; When turning off outline mode, get rid of any outline hiding.
- (show-all)))
-
-(defvar outline-level 'outline-level
- "Function of no args to compute a header's nesting level in an outline.
-It can assume point is at the beginning of a header line and that the match
-data reflects the `outline-regexp'.")
-
-(defvar outline-heading-alist ()
- "Alist associating a heading for every possible level.
-Each entry is of the form (HEADING . LEVEL).
-This alist is used two ways: to find the heading corresponding to
-a given level and to find the level of a given heading.
-If a mode or document needs several sets of outline headings (for example
-numbered and unnumbered sections), list them set by set and sorted by level
-within each set. For example in texinfo mode:
-
- (setq outline-heading-alist
- '((\"@chapter\" . 2) (\"@section\" . 3) (\"@subsection\" . 4)
- (\"@subsubsection\" . 5)
- (\"@unnumbered\" . 2) (\"@unnumberedsec\" . 3)
- (\"@unnumberedsubsec\" . 4) (\"@unnumberedsubsubsec\" . 5)
- (\"@appendix\" . 2) (\"@appendixsec\" . 3)...
- (\"@appendixsubsec\" . 4) (\"@appendixsubsubsec\" . 5) ..))
-
-Instead of sorting the entries in each set, you can also separate the
-sets with nil.")
-(make-variable-buffer-local 'outline-heading-alist)
-
-;; This used to count columns rather than characters, but that made ^L
-;; appear to be at level 2 instead of 1. Columns would be better for
-;; tab handling, but the default regexp doesn't use tabs, and anyone
-;; who changes the regexp can also redefine the outline-level variable
-;; as appropriate.
-(defun outline-level ()
- "Return the depth to which a statement is nested in the outline.
-Point must be at the beginning of a header line.
-This is actually either the level specified in `outline-heading-alist'
-or else the number of characters matched by `outline-regexp'."
- (or (cdr (assoc (match-string 0) outline-heading-alist))
- (- (match-end 0) (match-beginning 0))))
-
-(defun outline-next-preface ()
- "Skip forward to just before the next heading line.
-If there's no following heading line, stop before the newline
-at the end of the buffer."
- (if (re-search-forward (concat "\n\\(?:" outline-regexp "\\)")
- nil 'move)
- (goto-char (match-beginning 0)))
- (if (and (bolp) (or outline-blank-line (eobp)) (not (bobp)))
- (forward-char -1)))
-
-(defun outline-next-heading ()
- "Move to the next (possibly invisible) heading line."
- (interactive)
- ;; Make sure we don't match the heading we're at.
- (if (and (bolp) (not (eobp))) (forward-char 1))
- (if (re-search-forward (concat "^\\(?:" outline-regexp "\\)")
- nil 'move)
- (goto-char (match-beginning 0))))
-
-(defun outline-previous-heading ()
- "Move to the previous (possibly invisible) heading line."
- (interactive)
- (re-search-backward (concat "^\\(?:" outline-regexp "\\)")
- nil 'move))
-
-(defsubst outline-invisible-p (&optional pos)
- "Non-nil if the character after point is invisible."
- (eq 'outline (get-char-property (or pos (point)) 'invisible)))
-
-(defun outline-visible ()
- (not (outline-invisible-p)))
-(make-obsolete 'outline-visible 'outline-invisible-p)
-
-(defun outline-back-to-heading (&optional invisible-ok)
- "Move to previous heading line, or beg of this line if it's a heading.
-Only visible heading lines are considered, unless INVISIBLE-OK is non-nil."
- (beginning-of-line)
- (or (outline-on-heading-p invisible-ok)
- (let (found)
- (save-excursion
- (while (not found)
- (or (re-search-backward (concat "^\\(?:" outline-regexp "\\)")
- nil t)
- (error "before first heading"))
- (setq found (and (or invisible-ok (not (outline-invisible-p)))
- (point)))))
- (goto-char found)
- found)))
-
-(defun outline-on-heading-p (&optional invisible-ok)
- "Return t if point is on a (visible) heading line.
-If INVISIBLE-OK is non-nil, an invisible heading line is ok too."
- (save-excursion
- (beginning-of-line)
- (and (bolp) (or invisible-ok (not (outline-invisible-p)))
- (looking-at outline-regexp))))
-
-(defun outline-insert-heading ()
- "Insert a new heading at same depth at point."
- (interactive)
- (let ((head (save-excursion
- (condition-case nil
- (outline-back-to-heading)
- (error (outline-next-heading)))
- (if (eobp)
- (or (caar outline-heading-alist) "")
- (match-string 0)))))
- (unless (or (string-match "[ \t]\\'" head)
- (not (string-match (concat "\\`\\(?:" outline-regexp "\\)")
- (concat head " "))))
- (setq head (concat head " ")))
- (unless (bolp) (end-of-line) (newline))
- (insert head)
- (unless (eolp)
- (save-excursion (newline-and-indent)))
- (run-hooks 'outline-insert-heading-hook)))
-
-(defun outline-invent-heading (head up)
- (save-match-data
- ;; Let's try to invent one by repeating or deleting the last char.
- (let ((new-head (if up (substring head 0 -1)
- (concat head (substring head -1)))))
- (if (string-match (concat "\\`\\(?:" outline-regexp "\\)")
- new-head)
- ;; Why bother checking that it is indeed higher/lower level ?
- new-head
- ;; Didn't work, so ask what to do.
- (read-string (format "%s heading for `%s': "
- (if up "Parent" "Demoted") head)
- head nil nil)))))
-
-(defun outline-promote (&optional children)
- "Promote headings higher up the tree.
-If prefix argument CHILDREN is given, promote also all the children.
-If the region is active in `transient-mark-mode', promote all headings
-in the region."
- (interactive
- (list (if (and zmacs-regions (region-active-p)) 'region
- (outline-back-to-heading)
- (if current-prefix-arg nil 'subtree))))
- (cond
- ((eq children 'region)
- (outline-map-region 'outline-promote (region-beginning) (region-end)))
- (children
- (outline-map-region 'outline-promote
- (point)
- (save-excursion (outline-get-next-sibling) (point))))
- (t
- (outline-back-to-heading t)
- (let* ((head (match-string-no-properties 0))
- (level (save-match-data (funcall outline-level)))
- (up-head (or (outline-head-from-level (1- level) head)
- ;; Use the parent heading, if it is really
- ;; one level less.
- (save-excursion
- (save-match-data
- (outline-up-heading 1 t)
- (and (= (1- level) (funcall outline-level))
- (match-string-no-properties 0))))
- ;; Bummer!! There is no lower level heading.
- (outline-invent-heading head 'up))))
-
- (unless (rassoc level outline-heading-alist)
- (push (cons head level) outline-heading-alist))
-
- (replace-match up-head nil t)))))
-
-(defun outline-demote (&optional children)
- "Demote headings lower down the tree.
-If prefix argument CHILDREN is given, demote also all the children.
-If the region is active in `transient-mark-mode', demote all headings
-in the region."
- (interactive
- (list (if (and zmacs-regions (region-active-p)) 'region
- (outline-back-to-heading)
- (if current-prefix-arg nil 'subtree))))
- (cond
- ((eq children 'region)
- (outline-map-region 'outline-demote (region-beginning) (region-end)))
- (children
- (outline-map-region 'outline-demote
- (point)
- (save-excursion (outline-get-next-sibling) (point))))
- (t
- (let* ((head (match-string-no-properties 0))
- (level (save-match-data (funcall outline-level)))
- (down-head
- (or (outline-head-from-level (1+ level) head)
- (save-excursion
- (save-match-data
- (while (and (progn (outline-next-heading) (not (eobp)))
- (<= (funcall outline-level) level)))
- (when (eobp)
- ;; Try again from the beginning of the buffer.
- (goto-char (point-min))
- (while (and (progn (outline-next-heading) (not (eobp)))
- (<= (funcall outline-level) level))))
- (unless (eobp)
- (looking-at outline-regexp)
- (match-string-no-properties 0))))
- ;; Bummer!! There is no higher-level heading in the buffer.
- (outline-invent-heading head nil))))
-
- (unless (rassoc level outline-heading-alist)
- (push (cons head level) outline-heading-alist))
- (replace-match down-head nil t)))))
-
-(defun outline-head-from-level (level head &optional alist)
- "Get new heading with level LEVEL from ALIST.
-If there are no such entries, return nil.
-ALIST defaults to `outline-heading-alist'.
-Similar to (car (rassoc LEVEL ALIST)).
-If there are several different entries with same new level, choose
-the one with the smallest distance to the assocation of HEAD in the alist.
-This makes it possible for promotion to work in modes with several
-independent sets of headings (numbered, unnumbered, appendix...)"
- (unless alist (setq alist outline-heading-alist))
- (let ((l (rassoc level alist))
- ll h hl l2 l2l)
- (cond
- ((null l) nil)
- ;; If there's no HEAD after L, any other entry for LEVEL after L
- ;; can't be much better than L.
- ((null (setq h (assoc head (setq ll (memq l alist))))) (car l))
- ;; If there's no other entry for LEVEL, just keep L.
- ((null (setq l2 (rassoc level (cdr ll)))) (car l))
- ;; Now we have L, L2, and H: see if L2 seems better than L.
- ;; If H is after L2, L2 is better.
- ((memq h (setq l2l (memq l2 (cdr ll))))
- (outline-head-from-level level head l2l))
- ;; Now we have H between L and L2.
- ;; If there's a separator between L and H, prefer L2.
- ((memq h (memq nil ll))
- (outline-head-from-level level head l2l))
- ;; If there's a separator between L2 and H, prefer L.
- ((memq l2 (memq nil (setq hl (memq h ll)))) (car l))
- ;; No separator between L and L2, check the distance.
- ((< (* 2 (length hl)) (+ (length ll) (length l2l)))
- (outline-head-from-level level head l2l))
- ;; If all else fails, just keep L.
- (t (car l)))))
-
-(defun outline-map-region (fun beg end)
- "Call FUN for every heading between BEG and END.
-When FUN is called, point is at the beginning of the heading and
-the match data is set appropriately."
- (save-excursion
- (setq end (copy-marker end))
- (goto-char beg)
- (when (re-search-forward (concat "^\\(?:" outline-regexp "\\)") end t)
- (goto-char (match-beginning 0))
- (funcall fun)
- (while (and (progn
- (outline-next-heading)
- (< (point) end))
- (not (eobp)))
- (funcall fun)))))
-
-;; Vertical tree motion
-
-(defun outline-move-subtree-up (&optional arg)
- "Move the currrent subtree up past ARG headlines of the same level."
- (interactive "p")
- (outline-move-subtree-down (- arg)))
-
-(defun outline-move-subtree-down (&optional arg)
- "Move the currrent subtree down past ARG headlines of the same level."
- (interactive "p")
- (let ((movfunc (if (> arg 0) 'outline-get-next-sibling
- 'outline-get-last-sibling))
- (ins-point (make-marker))
- (cnt (abs arg))
- (tmp-string "")
- beg end folded)
- ;; Select the tree
- (outline-back-to-heading)
- (setq beg (point))
- (save-match-data
- (save-excursion (outline-end-of-heading)
- (setq folded (outline-invisible-p)))
- (outline-end-of-subtree))
- (if (= (char-after) ?\n) (forward-char 1))
- (setq end (point))
- ;; Find insertion point, with error handling
- (goto-char beg)
- (while (> cnt 0)
- (or (funcall movfunc)
- (progn (goto-char beg)
- (error "Cannot move past superior level")))
- (setq cnt (1- cnt)))
- (if (> arg 0)
- ;; Moving forward - still need to move over subtree
- (progn (outline-end-of-subtree)
- (if (= (char-after) ?\n) (forward-char 1))))
- (move-marker ins-point (point))
- (setq tmp-string (buffer-substring beg end))
- (delete-region beg end)
- (insert tmp-string)
- (goto-char ins-point)
- (if folded (hide-subtree))
- (move-marker ins-point nil)))
-
-(defun outline-end-of-heading ()
- (if (re-search-forward outline-heading-end-regexp nil 'move)
- (forward-char -1)))
-
-(defun outline-next-visible-heading (arg)
- "Move to the next visible heading line.
-With argument, repeats or can move backward if negative.
-A heading line is one that starts with a `*' (or that
-`outline-regexp' matches)."
- (interactive "p")
- (if (< arg 0)
- (beginning-of-line)
- (end-of-line))
- (while (and (not (bobp)) (< arg 0))
- (while (and (not (bobp))
- (re-search-backward (concat "^\\(?:" outline-regexp "\\)")
- nil 'move)
- (outline-invisible-p)))
- (setq arg (1+ arg)))
- (while (and (not (eobp)) (> arg 0))
- (while (and (not (eobp))
- (re-search-forward (concat "^\\(?:" outline-regexp "\\)")
- nil 'move)
- (outline-invisible-p (match-beginning 0))))
- (setq arg (1- arg)))
- (beginning-of-line))
-
-(defun outline-previous-visible-heading (arg)
- "Move to the previous heading line.
-With argument, repeats or can move forward if negative.
-A heading line is one that starts with a `*' (or that
-`outline-regexp' matches)."
- (interactive "p")
- (outline-next-visible-heading (- arg)))
-
-(defun outline-mark-subtree ()
- "Mark the current subtree in an outlined document.
-This puts point at the start of the current subtree, and mark at the end."
- (interactive)
- (let ((beg))
- (if (outline-on-heading-p)
- ;; we are already looking at a heading
- (beginning-of-line)
- ;; else go back to previous heading
- (outline-previous-visible-heading 1))
- (setq beg (point))
- (outline-end-of-subtree)
- (push-mark (point) nil t)
- (goto-char beg)))
-
-
-(defvar outline-isearch-open-invisible-function nil
- "Function called if `isearch' finishes in an invisible overlay.
-The function is called with the overlay as its only argument.
-If nil, `show-entry' is called to reveal the invisible text.")
-
-(defun outline-discard-extents (&optional beg end)
- "Clear BEG and END of overlays whose property NAME has value VAL.
-Overlays might be moved and/or split.
-BEG and END default respectively to the beginning and end of buffer."
- (unless beg (setq beg (point-min)))
- (unless end (setq end (point-max)))
- (if (< end beg)
- (setq beg (prog1 end (setq end beg))))
- (save-excursion
- (map-extents
- #'(lambda (ex ignored)
- (if (< (extent-start-position ex) beg)
- (if (> (extent-end-position ex) end)
- (progn
- (set-extent-endpoints (copy-extent ex)
- (extent-start-position ex) beg)
- (set-extent-endpoints ex end (extent-end-position ex)))
- (set-extent-endpoints ex (extent-start-position ex) beg))
- (if (> (extent-end-position ex) end)
- (set-extent-endpoints ex end (extent-end-position ex))
- (delete-extent ex))))
- (current-buffer) beg end nil 'end-closed 'outline)))
-
-(defun outline-flag-region (from to flag)
- "Hide or show lines from FROM to TO, according to FLAG.
-If FLAG is nil then text is shown, while if FLAG is t the text is hidden."
- (when (< to from)
- (setq from (prog1 to (setq to from))))
- ;; first clear it all out
- (outline-discard-extents from to)
- (when flag
- (let ((ex (make-extent from to)))
- (set-extent-property ex 'invisible 'outline)
- (set-extent-property ex 'outline flag)
- ;; FIXME: I don't think XEmacs uses this, actually.
- (set-extent-property ex 'isearch-open-invisible
- (or outline-isearch-open-invisible-function
- 'outline-isearch-open-invisible))))
- ;; Seems only used by lazy-lock. I.e. obsolete.
- (run-hooks 'outline-view-change-hook))
-
-;; Function to be set as an outline-isearch-open-invisible' property
-;; to the overlay that makes the outline invisible (see
-;; `outline-flag-region').
-(defun outline-isearch-open-invisible (overlay)
- ;; We rely on the fact that isearch places point on the matched text.
- (show-entry))
-
-(defun hide-entry ()
- "Hide the body directly following this heading."
- (interactive)
- (save-excursion
- (outline-back-to-heading)
- (outline-end-of-heading)
- (outline-flag-region (point) (progn (outline-next-preface) (point)) t)))
-
-(defun show-entry ()
- "Show the body directly following this heading.
-Show the heading too, if it is currently invisible."
- (interactive)
- (save-excursion
- (outline-back-to-heading t)
- (outline-flag-region (max 1 (1- (point)))
- (progn (outline-next-preface) (point)) nil)))
-
-(defun hide-body ()
- "Hide all body lines in buffer, leaving all headings visible."
- (interactive)
- (hide-region-body (point-min) (point-max)))
-
-(defun hide-region-body (start end)
- "Hide all body lines in the region, but not headings."
- ;; Nullify the hook to avoid repeated calls to `outline-flag-region'
- ;; wasting lots of time running `lazy-lock-fontify-after-outline'
- ;; and run the hook finally.
- (let (outline-view-change-hook)
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char (point-min))
- (if (outline-on-heading-p)
- (outline-end-of-heading)
- (outline-next-preface))
- (while (not (eobp))
- (outline-flag-region (point)
- (progn (outline-next-preface) (point)) t)
- (unless (eobp)
- (forward-char (if (looking-at "\n\n") 2 1))
- (outline-end-of-heading))))))
- (run-hooks 'outline-view-change-hook))
-
-(defun show-all ()
- "Show all of the text in the buffer."
- (interactive)
- (outline-flag-region (point-min) (point-max) nil))
-
-(defun hide-subtree ()
- "Hide everything after this heading at deeper levels."
- (interactive)
- (outline-flag-subtree t))
-
-(defun hide-leaves ()
- "Hide all body after this heading at deeper levels."
- (interactive)
- (save-excursion
- (outline-back-to-heading)
- (outline-end-of-heading)
- (hide-region-body (point) (progn (outline-end-of-subtree) (point)))))
-
-(defun show-subtree ()
- "Show everything after this heading at deeper levels."
- (interactive)
- (outline-flag-subtree nil))
-
-(defun outline-show-heading ()
- "Show the current heading and move to its end."
- (outline-flag-region (- (point)
- (if (bobp) 0
- (if (and outline-blank-line
- (eq (char-before (1- (point))) ?\n))
- 2 1)))
- (progn (outline-end-of-heading) (point))
- nil))
-
-(defun hide-sublevels (levels)
- "Hide everything but the top LEVELS levels of headers, in whole buffer."
- (interactive "p")
- (if (< levels 1)
- (error "Must keep at least one level of headers"))
- (let (outline-view-change-hook)
- (save-excursion
- (goto-char (point-min))
- ;; Skip the prelude, if any.
- (unless (outline-on-heading-p t) (outline-next-heading))
- ;; First hide everything.
- (outline-flag-region (point) (point-max) t)
- ;; Then unhide the top level headers.
- (outline-map-region
- (lambda ()
- (if (<= (funcall outline-level) levels)
- (outline-show-heading)))
- (point) (point-max))))
- (run-hooks 'outline-view-change-hook))
-
-(defun hide-other ()
- "Hide everything except current body and parent and top-level headings."
- (interactive)
- (hide-sublevels 1)
- (let (outline-view-change-hook)
- (save-excursion
- (outline-back-to-heading t)
- (show-entry)
- (while (condition-case nil (progn (outline-up-heading 1 t) (not (bobp)))
- (error nil))
- (outline-flag-region (max 1 (1- (point)))
- (save-excursion (forward-line 1) (point))
- nil))))
- (run-hooks 'outline-view-change-hook))
-
-(defun outline-toggle-children ()
- "Show or hide the current subtree depending on its current state."
- (interactive)
- (save-excursion
- (outline-back-to-heading)
- (if (not (outline-invisible-p (point-at-eol)))
- (hide-subtree)
- (show-children)
- (show-entry))))
-
-(defun outline-flag-subtree (flag)
- (save-excursion
- (outline-back-to-heading)
- (outline-end-of-heading)
- (outline-flag-region (point)
- (progn (outline-end-of-subtree) (point))
- flag)))
-
-(defun outline-end-of-subtree ()
- (outline-back-to-heading)
- (let ((first t)
- (level (funcall outline-level)))
- (while (and (not (eobp))
- (or first (> (funcall outline-level) level)))
- (setq first nil)
- (outline-next-heading))
- (if (and (bolp) (not (eolp)))
- ;; We stopped at a nonempty line (the next heading).
- (progn
- ;; Go to end of line before heading
- (forward-char -1)
- (if (and outline-blank-line (bolp))
- ;; leave blank line before heading
- (forward-char -1))))))
-
-(defun show-branches ()
- "Show all subheadings of this heading, but not their bodies."
- (interactive)
- (show-children 1000))
-
-(defun show-children (&optional level)
- "Show all direct subheadings of this heading.
-Prefix arg LEVEL is how many levels below the current level should be shown.
-Default is enough to cause the following heading to appear."
- (interactive "P")
- (setq level
- (if level (prefix-numeric-value level)
- (save-excursion
- (outline-back-to-heading)
- (let ((start-level (funcall outline-level)))
- (outline-next-heading)
- (if (eobp)
- 1
- (max 1 (- (funcall outline-level) start-level)))))))
- (let (outline-view-change-hook)
- (save-excursion
- (outline-back-to-heading)
- (setq level (+ level (funcall outline-level)))
- (outline-map-region
- (lambda ()
- (if (<= (funcall outline-level) level)
- (outline-show-heading)))
- (point)
- (progn (outline-end-of-subtree)
- (if (eobp) (point-max) (1+ (point)))))))
- (run-hooks 'outline-view-change-hook))
-
-
-
-(defun outline-up-heading (arg &optional invisible-ok)
- "Move to the visible heading line of which the present line is a subheading.
-With argument, move up ARG levels.
-If INVISIBLE-OK is non-nil, also consider invisible lines."
- (interactive "p")
- (and (eq this-command 'outline-up-heading)
- (or (eq last-command 'outline-up-heading) (push-mark)))
- (outline-back-to-heading invisible-ok)
- (let ((start-level (funcall outline-level)))
- (if (eq start-level 1)
- (error "Already at top level of the outline"))
- (while (and (> start-level 1) (> arg 0) (not (bobp)))
- (let ((level start-level))
- (while (not (or (< level start-level) (bobp)))
- (if invisible-ok
- (outline-previous-heading)
- (outline-previous-visible-heading 1))
- (setq level (funcall outline-level)))
- (setq start-level level))
- (setq arg (- arg 1))))
- (looking-at outline-regexp))
-
-(defun outline-forward-same-level (arg)
- "Move forward to the ARG'th subheading at same level as this one.
-Stop at the first and last subheadings of a superior heading."
- (interactive "p")
- (outline-back-to-heading)
- (while (> arg 0)
- (let ((point-to-move-to (save-excursion
- (outline-get-next-sibling))))
- (if point-to-move-to
- (progn
- (goto-char point-to-move-to)
- (setq arg (1- arg)))
- (progn
- (setq arg 0)
- (error "No following same-level heading"))))))
-
-(defun outline-get-next-sibling ()
- "Move to next heading of the same level, and return point or nil if none."
- (let ((level (funcall outline-level)))
- (outline-next-visible-heading 1)
- (while (and (not (eobp)) (> (funcall outline-level) level))
- (outline-next-visible-heading 1))
- (if (or (eobp) (< (funcall outline-level) level))
- nil
- (point))))
-
-(defun outline-backward-same-level (arg)
- "Move backward to the ARG'th subheading at same level as this one.
-Stop at the first and last subheadings of a superior heading."
- (interactive "p")
- (outline-back-to-heading)
- (while (> arg 0)
- (let ((point-to-move-to (save-excursion
- (outline-get-last-sibling))))
- (if point-to-move-to
- (progn
- (goto-char point-to-move-to)
- (setq arg (1- arg)))
- (progn
- (setq arg 0)
- (error "No previous same-level heading"))))))
-
-(defun outline-get-last-sibling ()
- "Move to previous heading of the same level, and return point or nil if none."
- (let ((level (funcall outline-level)))
- (outline-previous-visible-heading 1)
- (while (and (> (funcall outline-level) level)
- (not (bobp)))
- (outline-previous-visible-heading 1))
- (if (< (funcall outline-level) level)
- nil
- (point))))
-
-(defun outline-headers-as-kill (beg end)
- "Save the visible outline headers in region at the start of the kill ring.
-
-Text shown between the headers isn't copied. Two newlines are
-inserted between saved headers. Yanking the result may be a
-convenient way to make a table of contents of the buffer."
- (interactive "r")
- (save-excursion
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (let ((buffer (current-buffer))
- start end)
- (with-temp-buffer
- (with-current-buffer buffer
- ;; Boundary condition: starting on heading:
- (when (outline-on-heading-p)
- (outline-back-to-heading)
- (setq start (point)
- end (progn (outline-end-of-heading)
- (point)))
- (insert-buffer-substring buffer start end)
- (insert "\n\n")))
- (let ((temp-buffer (current-buffer)))
- (with-current-buffer buffer
- (while (outline-next-heading)
- (unless (outline-invisible-p)
- (setq start (point)
- end (progn (outline-end-of-heading) (point)))
- (with-current-buffer temp-buffer
- (insert-buffer-substring buffer start end)
- (insert "\n\n"))))))
- (kill-new (buffer-string)))))))
-
-(provide 'outline)
-(provide 'noutline)
-
-;; arch-tag: 1724410e-7d4d-4f46-b801-49e18171e874
-;;; outline.el ends here
diff --git a/xemacs/ps-print-invisible.el b/xemacs/ps-print-invisible.el
deleted file mode 100644
index 8f005fe..0000000
--- a/xemacs/ps-print-invisible.el
+++ /dev/null
@@ -1,225 +0,0 @@
-;;; ps-print-invisible.el - addon to ps-print package that deals
-;; with invisible text printing in xemacs
-
-;; Author: Greg Chernov
-;;
-;; 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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Commentary:
-;;
-;; Put ps-print-invisible.el on your load path.
-;; (require 'ps-print-invisible)
-;; ps-print-buffer-with-faces will not print invisible parts of the buffer.
-;; Work with invisible extents/text properties only
-;; (xemacs hideshow and noutline packages).
-
-(defun ps-generate-postscript-with-faces (from to)
- ;; Some initialization...
- (setq ps-current-effect 0)
-
- ;; Build the reference lists of faces if necessary.
- (when (or ps-always-build-face-reference
- ps-build-face-reference)
- (message "Collecting face information...")
- (ps-build-reference-face-lists))
-
- ;; Black/white printer.
- (setq ps-black-white-faces-alist nil)
- (and (eq ps-print-color-p 'black-white)
- (ps-extend-face-list ps-black-white-faces nil
- 'ps-black-white-faces-alist))
-
- ;; Generate some PostScript.
- (save-restriction
- (narrow-to-region from to)
- (ps-print-ensure-fontified from to)
- (let ((face 'default)
- (position to))
- (cond
- ((memq ps-print-emacs-type '(xemacs lucid))
- ;; Build the list of extents...
- ;;(debug)
- (let ((a (cons 'dummy nil))
- record type extent extent-list
- (list-invisible (ps-print-find-invisible-xmas from to)))
- (ps-x-map-extents 'ps-mapper nil from to a)
- (setq a (sort (cdr a) 'car-less-than-car)
- extent-list nil)
-
- ;; Loop through the extents...
- (while a
- (setq record (car a)
- position (car record)
-
- record (cdr record)
- type (car record)
-
- record (cdr record)
- extent (car record))
-
- ;; Plot up to this record.
- ;; XEmacs 19.12: for some reason, we're getting into a
- ;; situation in which some of the records have
- ;; positions less than 'from'. Since we've narrowed
- ;; the buffer, this'll generate errors. This is a hack,
- ;; but don't call ps-plot-with-face unless from > point-min.
- (and (>= from (point-min))
- (ps-plot-with-face from (min position (point-max)) face))
-
- (cond
- ((eq type 'push)
- (and (or (ps-x-extent-face extent)
- (extent-property extent 'invisible))
- (setq extent-list (sort (cons extent extent-list)
- 'ps-extent-sorter))))
-
- ((eq type 'pull)
- (setq extent-list (sort (delq extent extent-list)
- 'ps-extent-sorter))))
-
-
- (setq face (if extent-list
- (let ((prop (extent-property (car extent-list) 'invisible)))
- (if (or (and (eq buffer-invisibility-spec t)
- (not (null prop)))
- (and (consp buffer-invisibility-spec)
- (or (memq prop buffer-invisibility-spec)
- (assq prop buffer-invisibility-spec))))
- 'emacs--invisible--face
- (ps-x-extent-face (car extent-list))))
- 'default)
- from position
- a (cdr a)))))
-
- ((eq ps-print-emacs-type 'emacs)
- (let ((property-change from)
- (overlay-change from)
- (save-buffer-invisibility-spec buffer-invisibility-spec)
- (buffer-invisibility-spec nil)
- before-string after-string)
- (while (< from to)
- (and (< property-change to) ; Don't search for property change
- ; unless previous search succeeded.
- (setq property-change (next-property-change from nil to)))
- (and (< overlay-change to) ; Don't search for overlay change
- ; unless previous search succeeded.
- (setq overlay-change (min (ps-e-next-overlay-change from)
- to)))
- (setq position (min property-change overlay-change)
- before-string nil
- after-string nil)
- ;; The code below is not quite correct,
- ;; because a non-nil overlay invisible property
- ;; which is inactive according to the current value
- ;; of buffer-invisibility-spec nonetheless overrides
- ;; a face text property.
- (setq face
- (cond ((let ((prop (get-text-property from 'invisible)))
- ;; Decide whether this invisible property
- ;; really makes the text invisible.
- (if (eq save-buffer-invisibility-spec t)
- (not (null prop))
- (or (memq prop save-buffer-invisibility-spec)
- (assq prop save-buffer-invisibility-spec))))
- 'emacs--invisible--face)
- ((get-text-property from 'face))
- (t 'default)))
- (let ((overlays (ps-e-overlays-at from))
- (face-priority -1)) ; text-property
- (while (and overlays
- (not (eq face 'emacs--invisible--face)))
- (let* ((overlay (car overlays))
- (overlay-invisible
- (ps-e-overlay-get overlay 'invisible))
- (overlay-priority
- (or (ps-e-overlay-get overlay 'priority) 0)))
- (and (> overlay-priority face-priority)
- (setq before-string
- (or (ps-e-overlay-get overlay 'before-string)
- before-string)
- after-string
- (or (and (<= (ps-e-overlay-end overlay) position)
- (ps-e-overlay-get overlay 'after-string))
- after-string)
- face-priority overlay-priority
- face
- (cond
- ((if (eq save-buffer-invisibility-spec t)
- (not (null overlay-invisible))
- (or (memq overlay-invisible
- save-buffer-invisibility-spec)
- (assq overlay-invisible
- save-buffer-invisibility-spec)))
- 'emacs--invisible--face)
- ((ps-e-overlay-get overlay 'face))
- (t face)
- ))))
- (setq overlays (cdr overlays))))
- ;; Plot up to this record.
- (and before-string
- (ps-plot-string before-string))
- (ps-plot-with-face from position face)
- (and after-string
- (ps-plot-string after-string))
- (setq from position)))))
- (ps-plot-with-face from to face))))
-
-
-(defun ps-print-find-invisible-xmas (from to)
- (let ((list nil))
- (map-extents '(lambda (ex ignored)
- (let ((prop (extent-property ex 'invisible)))
- (if (or (and (eq buffer-invisibility-spec t)
- (not (null prop)))
- (or (memq prop buffer-invisibility-spec)
- (assq prop buffer-invisibility-spec)))
- (setq list (cons (list
- (extent-start-position ex)
- (extent-end-position ex))
- list))))
- nil)
- (current-buffer)
- from to nil 'start-and-end-in-region 'invisible)
- (reverse list)))
-
-
-(defun ps-mapper (extent list)
- ;;(debug)
- (let ((beg (ps-x-extent-start-position extent))
- (end (ps-x-extent-end-position extent))
- (inv-lst list-invisible)
- (found nil))
- (while (and inv-lst
- (not found))
- (let ((inv-beg (caar inv-lst))
- (inv-end (cadar inv-lst)))
- (if (and (>= beg inv-beg)
- (<= end inv-end)
- (not (extent-property extent 'invisible)))
- (setq found t))
- (setq inv-lst (cdr inv-lst))))
- (if (not found)
- (nconc list
- (list (list beg 'push extent)
- (list end 'pull extent)))))
- nil)
-
-
-(provide 'ps-print-invisible)
-
-
-;;; ps-print-invisible.el ends here \ No newline at end of file