summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2011-05-11 18:02:15 +0200
committerNicolas Goaziou <n.goaziou@gmail.com>2011-06-29 12:00:42 +0200
commitab9c52fd7911763a903a3d673dce2876ada9e551 (patch)
treeebab65fb72fb74f753fd033a22d06776ae76508e
parent9c316540779ba887fbfaae250c2b855ebbdccc32 (diff)
downloadorg-mode-ab9c52fd7911763a903a3d673dce2876ada9e551.tar.gz
Improve footnotes handling in exporters
* lisp/org-exp.el (org-export-footnotes-markers, org-export-footnotes-data): new variables. (org-export-preprocess-string): use a more explicit argument. * lisp/org-html.el (org-export-as-html): initialize new variables. * lisp/org-docbook.el (org-export-as-docbook): initialize new variables. * lisp/org-latex.el (org-export-latex-footmark-seen): new variable. (org-export-as-latex): initialize new variables. (org-export-latex-preprocess): allow to export two or more footnotes in a row. Also permit to have footnotes refering to previously defined footnotes. * lisp/org-ascii.el (org-export-as-ascii): feed org-footnote-normalize with data so it can normalize footnotes before first headline, or footnotes with their definition outside exported region.
-rw-r--r--lisp/org-ascii.el2
-rw-r--r--lisp/org-docbook.el2
-rw-r--r--lisp/org-exp.el6
-rw-r--r--lisp/org-footnote.el33
-rw-r--r--lisp/org-html.el2
-rw-r--r--lisp/org-latex.el107
6 files changed, 88 insertions, 64 deletions
diff --git a/lisp/org-ascii.el b/lisp/org-ascii.el
index 46d75e7..6469a1a 100644
--- a/lisp/org-ascii.el
+++ b/lisp/org-ascii.el
@@ -291,6 +291,8 @@ publishing directory."
(buffer-substring
(if (org-region-active-p) (region-beginning) (point-min))
(if (org-region-active-p) (region-end) (point-max))))
+ (org-export-footnotes-markers nil)
+ (org-export-footnotes-data (org-footnote-all-labels 'with-defs))
(lines (org-split-string
(org-export-preprocess-string
region
diff --git a/lisp/org-docbook.el b/lisp/org-docbook.el
index 124e1dc..f3cb487 100644
--- a/lisp/org-docbook.el
+++ b/lisp/org-docbook.el
@@ -519,6 +519,8 @@ publishing directory."
(buffer-substring
(if region-p (region-beginning) (point-min))
(if region-p (region-end) (point-max))))
+ (org-export-footnotes-markers nil)
+ (org-export-footnotes-data (org-footnote-all-labels 'with-defs))
(lines
(org-split-string
(org-export-preprocess-string
diff --git a/lisp/org-exp.el b/lisp/org-exp.el
index 0a0d112..8c414ec 100644
--- a/lisp/org-exp.el
+++ b/lisp/org-exp.el
@@ -623,6 +623,10 @@ table.el tables."
(defvar org-last-level nil) ; dynamically scoped variable
(defvar org-min-level nil) ; dynamically scoped variable
(defvar org-levels-open nil) ; dynamically scoped parameter
+(defvar org-export-footnotes-markers nil
+ "Alist of markers used for footnotes, along with their associated definition.")
+(defvar org-export-footnotes-data nil
+ "Alist of labels used in buffers, along with their associated definition.")
(defconst org-export-plist-vars
'((:link-up nil org-export-html-link-up)
@@ -1153,7 +1157,7 @@ on this string to produce the exported version."
;; Normalize footnotes
(when (plist-get parameters :footnotes)
- (org-footnote-normalize nil t))
+ (org-footnote-normalize nil 'pre-process-p))
;; Find all headings and compute the targets for them
(setq target-alist (org-export-define-heading-targets target-alist))
diff --git a/lisp/org-footnote.el b/lisp/org-footnote.el
index 66feeac..586e812 100644
--- a/lisp/org-footnote.el
+++ b/lisp/org-footnote.el
@@ -309,22 +309,37 @@ If no footnote is found, return nil."
(concat "fn:" label))
(t label)))
-(defun org-footnote-all-labels ()
- "Return list with all defined foot labels used in the buffer."
- (let (rtn l ref)
+(defun org-footnote-all-labels (&optional with-defs)
+ "Return list with all defined foot labels used in the buffer.
+
+If WITH-DEFS is non-nil, also associate the definition to each
+label. The function will then return an alist whose key is label
+and value definition."
+ (let (rtn
+ (push-to-rtn
+ (function
+ ;; Depending on WITH-DEFS, store label or (label . def) of
+ ;; footnote reference/definition given as argument in RTN.
+ (lambda (el)
+ (let ((lbl (car el)))
+ (push (if with-defs (cons lbl (nth 3 el)) lbl) rtn))))))
(save-excursion
(save-restriction
(widen)
;; Find all labels found in definitions.
(goto-char (point-min))
- (while (re-search-forward org-footnote-definition-re nil t)
- (setq l (org-match-string-no-properties 2))
- (and l (add-to-list 'rtn l)))
+ (let (def)
+ (while (re-search-forward org-footnote-definition-re nil t)
+ (when (setq def (org-footnote-at-definition-p))
+ (funcall push-to-rtn def))))
;; Find all labels found in references.
(goto-char (point-min))
- (while (and (setq ref (org-footnote-get-next-reference))
- (goto-char (nth 2 ref)))
- (and (car ref) (add-to-list 'rtn (car ref))))))
+ (let (ref)
+ (while (setq ref (org-footnote-get-next-reference))
+ (goto-char (nth 2 ref))
+ (and (car ref) ; ignore anonymous footnotes
+ (not (funcall (if with-defs #'assoc #'member) (car ref) rtn))
+ (funcall push-to-rtn ref))))))
rtn))
(defun org-footnote-unique-label (&optional current)
diff --git a/lisp/org-html.el b/lisp/org-html.el
index fd43bbf..7627fb2 100644
--- a/lisp/org-html.el
+++ b/lisp/org-html.el
@@ -1177,6 +1177,8 @@ PUB-DIR is set, use this as the publishing directory."
(if region-p (region-beginning) (point-min))
(if region-p (region-end) (point-max))))
(org-export-have-math nil)
+ (org-export-footnotes-markers nil)
+ (org-export-footnotes-data (org-footnote-all-labels 'with-defs))
(lines
(org-split-string
(org-export-preprocess-string
diff --git a/lisp/org-latex.el b/lisp/org-latex.el
index 856a884..f68879a 100644
--- a/lisp/org-latex.el
+++ b/lisp/org-latex.el
@@ -65,6 +65,8 @@
(defvar org-export-latex-display-custom-times nil)
(defvar org-export-latex-all-targets-re nil)
(defvar org-export-latex-add-level 0)
+(defvar org-export-latex-footmark-seen nil
+ "List of footnotes markers seen so far by exporter.")
(defvar org-export-latex-sectioning "")
(defvar org-export-latex-sectioning-depth 0)
(defvar org-export-latex-special-keyword-regexp
@@ -766,7 +768,10 @@ when PUB-DIR is set, use this as the publishing directory."
'(:org-license-to-kill nil))))
(org-update-radio-target-regexp)
(org-export-latex-set-initial-vars ext-plist arg)
- (setq org-export-opt-plist org-export-latex-options-plist)
+ (setq org-export-opt-plist org-export-latex-options-plist
+ org-export-footnotes-data (org-footnote-all-labels 'with-defs)
+ org-export-footnotes-markers nil
+ org-export-latex-footmark-seen nil)
(org-install-letbind)
(run-hooks 'org-export-latex-after-initial-vars-hook)
(let* ((wcf (current-window-configuration))
@@ -2412,60 +2417,54 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
(org-if-unprotected
(replace-match "")))
- ;; When converting to LaTeX, replace footnotes
- ;; FIXME: don't protect footnotes from conversion
- (when (plist-get org-export-latex-options-plist :footnotes)
+ ;; When converting to LaTeX, replace footnotes.
+ (when (plist-get opt-plist :footnotes)
(goto-char (point-min))
- (while (and (re-search-forward "\\[\\([0-9]+\\)\\]" nil t)
- (not (equal (char-before (match-beginning 0)) ?\])))
- (org-if-unprotected
- (when (and (save-match-data
- (save-excursion (beginning-of-line)
- (looking-at "[^:|#]")))
- (not (org-in-verbatim-emphasis)))
- (let ((foot-beg (match-beginning 0))
- (foot-end (match-end 0))
- (foot-prefix (match-string 0))
- footnote footnote-rpl)
- (save-excursion
- (if (not (re-search-forward (concat "^" (regexp-quote foot-prefix))
- nil t))
- (replace-match (org-export-latex-protect-string
- (concat "$^{" (match-string 1) "}$")))
- (replace-match "")
- (let* ((end (save-excursion
- (if (re-search-forward "^$\\|^#.*$\\|\\[[0-9]+\\]" nil t)
- (match-beginning 0) (point-max))))
- (body (org-trim (buffer-substring (point) end))))
- ;; Fix for footnotes ending on a link or a list.
- (setq footnote
- (concat body
- (if (string-match "ORG-LIST-END-MARKER\\'" body)
- "\n" " ")))
- (delete-region (point) end))
- (goto-char foot-beg)
- (delete-region foot-beg foot-end)
- (unless (null footnote)
- (setq footnote-rpl (format "\\footnote{%s}" footnote))
- (add-text-properties 0 10 '(org-protected t) footnote-rpl)
- (add-text-properties (1- (length footnote-rpl))
- (length footnote-rpl)
- '(org-protected t) footnote-rpl)
- (put-text-property 0 (length footnote-rpl)
- 'original-indentation 1000 footnote-rpl)
- (if (org-on-heading-p)
- (setq footnote-rpl
- (concat (org-export-latex-protect-string "\\protect")
- footnote-rpl)))
- (insert footnote-rpl)))
- )))))
-
- ;; Remove footnote section tag for LaTeX
- (goto-char (point-min))
- (while (re-search-forward
- (concat "^" footnote-section-tag-regexp) nil t)
- (org-if-unprotected
- (replace-match "")))))
+ (let (ref mark-max)
+ (while (setq ref (org-footnote-get-next-reference))
+ (let* ((beg (nth 1 ref))
+ (lbl (string-to-number (car ref)))
+ (def (or (cdr (assoc lbl org-export-footnotes-markers)) "")))
+ ;; Fix body for footnotes ending on a link or a list and
+ ;; remove definition from buffer.
+ (setq def
+ (concat def
+ (if (string-match "ORG-LIST-END-MARKER\\'" def)
+ "\n" " ")))
+ (org-footnote-delete-definitions (number-to-string lbl))
+ ;; Compute string to insert (FNOTE), and protect the outside
+ ;; macro from further transformation. When footnote at point
+ ;; is referring to a previously defined footnote, use
+ ;; \footnotemark. Otherwise, use \footnote.
+ (let ((fnote (if (memq lbl org-export-latex-footmark-seen)
+ (org-export-latex-protect-string
+ (format "\\footnotemark[%d]" lbl))
+ (push lbl org-export-latex-footmark-seen)
+ (concat (org-export-latex-protect-string "\\footnote{")
+ def
+ (org-export-latex-protect-string "}")))))
+ (when (org-on-heading-p)
+ (setq fnote
+ (concat (org-export-latex-protect-string "\\protect") fnote)))
+ ;; Replace footnote reference with FOOTNOTE.
+ ;; `save-excursion' is required if there are two footnotes
+ ;; in a row. In that case, point would be left at the
+ ;; beginning of the second one, and
+ ;; `org-footnote-get-next-reference' would then skip it.
+ (goto-char beg)
+ (delete-region beg (nth 2 ref))
+ (save-excursion (insert fnote)))))))
+
+ ;; Remove footnote section tag for LaTeX
+ (goto-char (point-min))
+ (while (re-search-forward
+ (concat "^" footnote-section-tag-regexp) nil t)
+ (org-if-unprotected
+ (replace-match "")))
+ ;; Remove any left-over footnote definition.
+ (goto-char (point-min))
+ (mapc (lambda (fn) (org-footnote-delete-definitions (car fn)))
+ org-export-footnotes-data))
(defun org-export-latex-fix-inputenc ()
"Set the coding system in inputenc to what the buffer is."