diff options
author | Nicolas Goaziou <n.goaziou@gmail.com> | 2011-05-11 18:02:15 +0200 |
---|---|---|
committer | Nicolas Goaziou <n.goaziou@gmail.com> | 2011-06-29 12:00:42 +0200 |
commit | ab9c52fd7911763a903a3d673dce2876ada9e551 (patch) | |
tree | ebab65fb72fb74f753fd033a22d06776ae76508e | |
parent | 9c316540779ba887fbfaae250c2b855ebbdccc32 (diff) | |
download | org-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.el | 2 | ||||
-rw-r--r-- | lisp/org-docbook.el | 2 | ||||
-rw-r--r-- | lisp/org-exp.el | 6 | ||||
-rw-r--r-- | lisp/org-footnote.el | 33 | ||||
-rw-r--r-- | lisp/org-html.el | 2 | ||||
-rw-r--r-- | lisp/org-latex.el | 107 |
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." |