summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2013-02-21 15:30:16 +0100
committerNicolas Goaziou <n.goaziou@gmail.com>2013-02-24 14:44:07 +0100
commitca060f7be76814d603bf5d17bd55e4131e3a0bdb (patch)
treec1c07d2e9602c400f5ed5fc9fdfa1a6f364162b3
parenta965c062133dea33dfddb5e3eabf373e2084b466 (diff)
downloadorg-mode-ca060f7be76814d603bf5d17bd55e4131e3a0bdb.tar.gz
Require 2 blank lines to separate footnote definition
* lisp/org-element.el (org-element-footnote-definition-parser): Require 2 blank lines to separate footnote definition. * lisp/org-footnote.el (org-footnote-at-definition-p): Require 2 blank lines to separate footnote definition. * doc/org.texi: Update documentation for footnotes. * testing/lisp/test-org-element.el: Update tests. * testing/lisp/test-org-footnote.el: Add tests. Footnote definitions can still be separated with other footnote definitions and headlines. This change allows to have multiple paragraphs in a footnote definition without resorting to the "\par" trick.
-rw-r--r--doc/org.texi14
-rw-r--r--lisp/org-element.el2
-rw-r--r--lisp/org-footnote.el13
-rw-r--r--testing/lisp/test-org-element.el4
-rw-r--r--testing/lisp/test-org-footnote.el87
5 files changed, 89 insertions, 31 deletions
diff --git a/doc/org.texi b/doc/org.texi
index f9df819..0758dee 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -1845,13 +1845,13 @@ or on a per-file basis by using
@cindex footnotes
Org mode supports the creation of footnotes. In contrast to the
-@file{footnote.el} package, Org mode's footnotes are designed for work on a
-larger document, not only for one-off documents like emails. The basic
-syntax is similar to the one used by @file{footnote.el}, i.e., a footnote is
-defined in a paragraph that is started by a footnote marker in square
-brackets in column 0, no indentation allowed. If you need a paragraph break
-inside a footnote, use the @LaTeX{} idiom @samp{\par}. The footnote reference
-is simply the marker in square brackets, inside text. For example:
+@file{footnote.el} package, Org mode's footnotes are designed for work on
+a larger document, not only for one-off documents like emails.
+
+A footnote is started by a footnote marker in square brackets in column 0, no
+indentation allowed. It ends at the next footnote definition, headline, or
+after two consecutive empty lines. The footnote reference is simply the
+marker in square brackets, inside text. For example:
@example
The Org homepage[fn:1] now looks a lot better than it used to.
diff --git a/lisp/org-element.el b/lisp/org-element.el
index fc2f5dd..d09147d 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -693,7 +693,7 @@ Assume point is at the beginning of the footnote definition."
(re-search-forward
(concat org-outline-regexp-bol "\\|"
org-footnote-definition-re "\\|"
- "^[ \t]*$") limit 'move))
+ "^\\([ \t]*\n\\)\\{2,\\}") limit 'move))
(match-beginning 0)
(point))))
(contents-begin (progn (search-forward "]")
diff --git a/lisp/org-footnote.el b/lisp/org-footnote.el
index 9aa388b..02af43f 100644
--- a/lisp/org-footnote.el
+++ b/lisp/org-footnote.el
@@ -251,11 +251,12 @@ otherwise."
(when (save-excursion (beginning-of-line) (org-footnote-in-valid-context-p))
(save-excursion
(end-of-line)
- ;; Footnotes definitions are separated by new headlines or blank
- ;; lines.
- (let ((lim (save-excursion (re-search-backward
- (concat org-outline-regexp-bol
- "\\|^[ \t]*$") nil t))))
+ ;; Footnotes definitions are separated by new headlines, another
+ ;; footnote definition or 2 blank lines.
+ (let ((lim (save-excursion
+ (re-search-backward
+ (concat org-outline-regexp-bol
+ "\\|^\\([ \t]*\n\\)\\{2,\\}") nil t))))
(when (re-search-backward org-footnote-definition-re lim t)
(let ((label (org-match-string-no-properties 1))
(beg (match-beginning 0))
@@ -271,7 +272,7 @@ otherwise."
(re-search-forward
(concat org-outline-regexp-bol "\\|"
org-footnote-definition-re "\\|"
- "^[ \t]*$") bound 'move))
+ "^\\([ \t]*\n\\)\\{2,\\}") bound 'move))
(match-beginning 0)
(point)))))
(list label beg end
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index a65355f..c979715 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -724,10 +724,10 @@ Some other text
(org-element-parse-buffer) 'footnote-definition 'identity nil t)))
;; Footnote with more contents
(should
- (= 28
+ (= 29
(org-element-property
:end
- (org-test-with-temp-text "[fn:1] Definition\n| a | b |"
+ (org-test-with-temp-text "[fn:1] Definition\n\n| a | b |"
(org-element-map
(org-element-parse-buffer)
'footnote-definition 'identity nil t)))))
diff --git a/testing/lisp/test-org-footnote.el b/testing/lisp/test-org-footnote.el
index f55ed84..5fb7351 100644
--- a/testing/lisp/test-org-footnote.el
+++ b/testing/lisp/test-org-footnote.el
@@ -19,6 +19,58 @@
;;; Code:
+(ert-deftest test-org-footnote/delete ()
+ "Test `org-footnote-delete' specifications."
+ ;; Regular test.
+ (should
+ (equal "Paragraph"
+ (org-test-with-temp-text "Paragraph[1]\n\n[1] Definition"
+ (search-forward "[")
+ (org-footnote-delete)
+ (org-trim (buffer-string)))))
+ ;; Remove multiple definitions and references.
+ (should
+ (equal "Paragraph and another"
+ (org-test-with-temp-text
+ "Paragraph[1] and another[1]\n\n[1] def\n\n[1] def"
+ (search-forward "[")
+ (org-footnote-delete)
+ (org-trim (buffer-string)))))
+ ;; Delete inline footnotes and all references.
+ (should
+ (equal "Para and"
+ (org-test-with-temp-text "Para[fn:label:def] and[fn:label]"
+ (search-forward "[")
+ (org-footnote-delete)
+ (org-trim (buffer-string)))))
+ ;; Delete anonymous footnotes.
+ (should
+ (equal "Para"
+ (org-test-with-temp-text "Para[fn::def]"
+ (search-forward "[")
+ (org-footnote-delete)
+ (org-trim (buffer-string)))))
+ ;; With an argument, delete footnote with specified label.
+ (should
+ (equal "Paragraph[1] and another\n\n[1] def"
+ (let ((org-footnote-section nil))
+ (org-test-with-temp-text
+ "Paragraph[1] and another[2]\n\n[1] def\n\n[2] def2"
+ (org-footnote-delete "2")
+ (org-trim (buffer-string))))))
+ ;; Error when no argument is specified at point is not at a footnote
+ ;; reference.
+ (should-error
+ (org-test-with-temp-text "Para[1]\n\n[1] Def"
+ (org-footnote-delete)))
+ ;; Correctly delete footnotes with multiple paragraphs.
+ (should
+ (equal "Para\n\n\nOutside footnote."
+ (org-test-with-temp-text
+ "Para[1]\n\n[1] para1\n\npara2\n\n\nOutside footnote."
+ (org-footnote-delete "1")
+ (org-trim (buffer-string))))))
+
(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'.
@@ -138,21 +190,10 @@ Text[2]
"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]
+ (should
+ (equal
+ "Paragraph[1][2][3][4][5]
-\[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.
@@ -164,7 +205,21 @@ Some additional text.
\[4] Inline
-\[5] Anonymous"))))
+\[5] Anonymous"
+ (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)
+ (buffer-string)))))
;; 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
@@ -174,12 +229,14 @@ Some additional text.
\[fn:1] Standard
+
Some additional text.")
(org-footnote-normalize)
(should
(equal (buffer-string)
"Paragraph[1][2]
+
Some additional text.
Footnotes: