summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2012-03-02 22:37:12 +0100
committerNicolas Goaziou <n.goaziou@gmail.com>2012-03-02 22:37:12 +0100
commit6b91eb9e657ab0a91c2df6d0081b302af20f083a (patch)
tree7efac79df04716324f204a06fcba3dba95db398d
parent000afe01abbd3b8b3416a12a91e33f8e9f51b9a1 (diff)
downloadorg-mode-6b91eb9e657ab0a91c2df6d0081b302af20f083a.tar.gz
org-footnote: Fix normalization of inline footnotes with no footnote section
* lisp/org-footnote.el (org-footnote-normalize): Fix normalization of inline footnotes with no footnote section. * testing/lisp/test-org-footnote.el: New test file. Thanks to Samuel Wales for reporting this.
-rw-r--r--lisp/org-footnote.el42
-rw-r--r--testing/lisp/test-org-footnote.el260
2 files changed, 283 insertions, 19 deletions
diff --git a/lisp/org-footnote.el b/lisp/org-footnote.el
index 25376f5..71c0101 100644
--- a/lisp/org-footnote.el
+++ b/lisp/org-footnote.el
@@ -676,8 +676,7 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
;; If EXPORT-PROPS isn't nil, also add `org-footnote'
;; property to it, so it can be easily recognized by
;; exporters.
- (if sort-only
- (goto-char (nth 2 ref))
+ (if sort-only (goto-char (nth 2 ref))
(delete-region (nth 1 ref) (nth 2 ref))
(goto-char (nth 1 ref))
(let ((new-ref (format "[%d]" marker)))
@@ -706,7 +705,10 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
'(:todo-keywords t :tags t :priority t))))
(org-export-preprocess-string def parameters))
def)
- inlinep pos) ref-table)))))
+ ;; Reference beginning position is a marker
+ ;; to preserve it during further buffer
+ ;; modifications.
+ inlinep (copy-marker pos)) ref-table)))))
;; 2. Find and remove the footnote section, if any. Also
;; determine where footnotes shall be inserted (INS-POINT).
(cond
@@ -722,10 +724,9 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
(skip-chars-backward " \r\t\n")
(forward-line)
(unless (bolp) (newline)))
- ;; No footnote section set: Footnotes will be added before next
- ;; headline.
- ((eq major-mode 'org-mode)
- (org-with-limited-levels (outline-next-heading)))
+ ;; No footnote section set: Footnotes will be added at the end
+ ;; of the section containing their first reference.
+ ((eq major-mode 'org-mode))
(t
;; Remove any left-over tag in the buffer, if one is set up.
(when org-footnote-tag-for-non-org-mode-files
@@ -758,18 +759,21 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
(lambda (x)
(cond
;; When only sorting, ignore inline footnotes.
- ((and sort-only (nth 3 x)) nil)
+ ;; Also clear position marker.
+ ((and sort-only (nth 3 x))
+ (set-marker (nth 4 x) nil) nil)
;; No definition available: provide one.
((not (nth 2 x))
- (append (butlast x 2)
- (list (format "DEFINITION NOT FOUND: %s" (car x))
- (nth 3 x))))
+ (append
+ (list (car x) (nth 1 x)
+ (format "DEFINITION NOT FOUND: %s" (car x)))
+ (nthcdr 3 x)))
(t x)))
ref-table)))
(setq ref-table (nreverse ref-table))
;; 4. Remove left-over definitions in the buffer.
- (mapc (lambda (x) (unless (nth 3 x)
- (org-footnote-delete-definitions (car x))))
+ (mapc (lambda (x)
+ (unless (nth 3 x) (org-footnote-delete-definitions (car x))))
ref-table)
;; 5. Insert the footnotes again in the buffer, at the
;; appropriate spot.
@@ -791,11 +795,6 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
(skip-chars-backward " \t\n\r")
(delete-region (point) ins-point)
(unless (bolp) (newline))
- ;; Keep one blank line between footnotes and signature.
- (when (and (derived-mode-p 'message-mode)
- (save-excursion
- (re-search-forward message-signature-separator nil t)))
- (open-line 1))
(when org-footnote-tag-for-non-org-mode-files
(insert "\n" org-footnote-tag-for-non-org-mode-files "\n")))
((and org-footnote-section (not export-props))
@@ -808,6 +807,8 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
(insert
(mapconcat
(lambda (x)
+ ;; Clean markers.
+ (set-marker (nth 4 x) nil)
(format "\n[%s] %s" (nth (if sort-only 0 1) x) (nth 2 x)))
ref-table "\n"))
(unless (eobp) (insert "\n\n"))
@@ -819,7 +820,10 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
((not sort-only)
(mapc
(lambda (x)
- (goto-char (nth 4 x))
+ (let ((pos (nth 4 x)))
+ (goto-char pos)
+ ;; Clean marker.
+ (set-marker pos nil))
(org-footnote-goto-local-insertion-point)
(insert (format "\n[%s] %s\n" (nth 1 x) (nth 2 x))))
ref-table))
diff --git a/testing/lisp/test-org-footnote.el b/testing/lisp/test-org-footnote.el
new file mode 100644
index 0000000..52e5538
--- /dev/null
+++ b/testing/lisp/test-org-footnote.el
@@ -0,0 +1,260 @@
+;;; test-org-footnote.el --- Tests for org-footnote.el
+
+;; Copyright (C) 2012 Nicolas Goaziou
+
+;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(ert-deftest test-org-footnote/normalize-in-org ()
+ "Test specifications for `org-footnote-normalize' in an Org buffer."
+ ;; 1. With a non-nil `org-footnote-section'.
+ (let ((org-footnote-section "Footnotes")
+ (org-blank-before-new-entry '((heading . auto))))
+ ;; 1.1. Normalize each type of footnote: standard, labelled,
+ ;; numbered, inline, anonymous.
+ (org-test-with-temp-text
+ "Paragraph[fn:1][fn:label][1][fn:inline:Inline][fn::Anonymous]
+
+* Footnotes
+
+\[fn:1] Standard
+
+\[fn:label] Labelled
+
+\[1] Numbered"
+ (org-footnote-normalize)
+ (should
+ (equal (buffer-string)
+ "Paragraph[1][2][3][4][5]
+
+* Footnotes
+
+\[1] Standard
+
+\[2] Labelled
+
+\[3] Numbered
+
+\[4] Inline
+
+\[5] Anonymous
+
+
+")))
+ ;; 1.2. When no footnote section is present, create it. Follow
+ ;; `org-blank-before-new-entry' specifications when doing so.
+ (org-test-with-temp-text "Paragraph[fn:1]\n\n[fn:1] Definition"
+ (org-footnote-normalize)
+ (should (equal (buffer-string)
+ "Paragraph[1]\n\n* Footnotes\n\n[1] Definition")))
+ (org-test-with-temp-text "Paragraph[fn:1]\n* Head1\n[fn:1] Definition"
+ (let ((org-blank-before-new-entry '((heading))))
+ (org-footnote-normalize))
+ (should (equal (buffer-string)
+ "Paragraph[1]\n* Head1\n* Footnotes\n\n[1] Definition")))
+ ;; 1.3. When the footnote section is misplaced, move it at the end
+ ;; of the buffer.
+ (org-test-with-temp-text "* Head1
+Body[fn:1]
+* Footnotes
+\[fn:1] Definition 1
+* Head2"
+ (org-footnote-normalize)
+ (should
+ (equal (buffer-string)
+ "* Head1
+Body[1]
+* Head2
+
+* Footnotes
+
+\[1] Definition 1"))))
+ ;; 2. With a nil `org-footnote-section'.
+ (let ((org-footnote-section nil))
+ ;; 2.1. Normalize each type of footnote: standard, labelled,
+ ;; numbered, inline, anonymous.
+ (org-test-with-temp-text
+ "Paragraph[fn:1][fn:label][1][fn:inline:Inline][fn::Anonymous]
+
+\[fn:1] Standard
+
+\[fn:label] Labelled
+
+\[1] Numbered"
+ (org-footnote-normalize)
+ (should
+ (equal (buffer-string)
+ "Paragraph[1][2][3][4][5]
+
+\[1] Standard
+
+\[2] Labelled
+
+\[3] Numbered
+
+\[4] Inline
+
+\[5] Anonymous
+
+")))
+ ;; 2.2. Put each footnote definition at the end of the section
+ ;; containing its first reference.
+ (org-test-with-temp-text
+ "* Head 1
+Text[fn:1:Def1]
+* Head 2
+Text[fn:1]
+* Head 3
+Text[fn:2:Def2]"
+ (org-footnote-normalize)
+ (should
+ (equal (buffer-string)
+ "* Head 1
+Text[1]
+
+\[1] Def1
+* Head 2
+Text[1]
+* Head 3
+Text[2]
+
+\[2] Def2
+")))))
+
+(ert-deftest test-org-footnote/normalize-outside-org ()
+ "Test `org-footnote-normalize' specifications for buffers not in Org mode."
+ ;; 1. In a non-Org buffer, footnotes definitions are always put at
+ ;; its end.
+ (let ((org-footnote-tag-for-non-org-mode-files nil))
+ (with-temp-buffer
+ (insert "Paragraph[fn:1][fn:label][1][fn:inline:Inline][fn::Anonymous]
+
+\[fn:1] Standard
+
+\[fn:label] Labelled
+
+\[1] Numbered
+
+Some additional text.")
+ (org-footnote-normalize)
+ (should
+ (equal (buffer-string)
+ "Paragraph[1][2][3][4][5]
+
+Some additional text.
+
+\[1] Standard
+
+\[2] Labelled
+
+\[3] Numbered
+
+\[4] Inline
+
+\[5] Anonymous"))))
+ ;; 2. With a special tag.
+ (let ((org-footnote-tag-for-non-org-mode-files "Footnotes:"))
+ ;; 2.1. The tag must be inserted before the footnotes, separated
+ ;; from the rest of the text with a blank line.
+ (with-temp-buffer
+ (insert "Paragraph[fn:1][fn::Anonymous]
+
+\[fn:1] Standard
+
+Some additional text.")
+ (org-footnote-normalize)
+ (should
+ (equal (buffer-string)
+ "Paragraph[1][2]
+
+Some additional text.
+
+Footnotes:
+
+\[1] Standard
+
+\[2] Anonymous")))
+ ;; 2.2. Any tag already inserted in the buffer should be removed
+ ;; prior to footnotes insertion.
+ (with-temp-buffer
+ (insert "Text[fn:1]
+Footnotes:
+
+Additional text.
+
+Footnotes:
+
+\[fn:1] Definition")
+ (org-footnote-normalize)
+ (should
+ (equal (buffer-string)
+ "Text[1]
+
+Additional text.
+
+Footnotes:
+
+\[1] Definition"))))
+ ;; 3. As an exception, in `message-mode' buffer, if a signature is
+ ;; present, insert footnotes before it.
+ (let ((org-footnote-tag-for-non-org-mode-files nil)
+ (message-signature-separator "^-- $"))
+ (with-temp-buffer
+ (insert "Body[fn::def]
+--
+Fake signature
+--
+Signature")
+ (let ((major-mode 'message-mode)) (org-footnote-normalize))
+ (should
+ (equal (buffer-string)
+ "Body[1]
+--
+Fake signature
+
+\[1] def
+
+--
+Signature")))))
+
+(ert-deftest test-org-footnote/sort ()
+ "Test footnotes definitions sorting."
+ (let ((org-footnote-section nil))
+ (org-test-with-temp-text
+ "Text[fn:1][fn::inline][fn:2][fn:label]
+
+\[fn:label] C
+
+\[fn:1] A
+
+\[fn:2] B"
+ (org-footnote-normalize 'sort)
+ (should
+ (equal (buffer-string)
+ "Text[fn:1][fn::inline][fn:2][fn:label]
+
+\[fn:1] A
+
+\[fn:2] B
+
+\[fn:label] C
+
+")))))
+
+
+(provide 'test-org-footnote)
+;;; test-org-footnote.el ends here