mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-11-22 07:09:47 +00:00
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.
This commit is contained in:
parent
a965c06213
commit
ca060f7be7
14
doc/org.texi
14
doc/org.texi
@ -1845,13 +1845,13 @@ or on a per-file basis by using
|
|||||||
@cindex footnotes
|
@cindex footnotes
|
||||||
|
|
||||||
Org mode supports the creation of footnotes. In contrast to the
|
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
|
@file{footnote.el} package, Org mode's footnotes are designed for work on
|
||||||
larger document, not only for one-off documents like emails. The basic
|
a larger document, not only for one-off documents like emails.
|
||||||
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
|
A footnote is started by a footnote marker in square brackets in column 0, no
|
||||||
brackets in column 0, no indentation allowed. If you need a paragraph break
|
indentation allowed. It ends at the next footnote definition, headline, or
|
||||||
inside a footnote, use the @LaTeX{} idiom @samp{\par}. The footnote reference
|
after two consecutive empty lines. The footnote reference is simply the
|
||||||
is simply the marker in square brackets, inside text. For example:
|
marker in square brackets, inside text. For example:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
The Org homepage[fn:1] now looks a lot better than it used to.
|
The Org homepage[fn:1] now looks a lot better than it used to.
|
||||||
|
@ -693,7 +693,7 @@ Assume point is at the beginning of the footnote definition."
|
|||||||
(re-search-forward
|
(re-search-forward
|
||||||
(concat org-outline-regexp-bol "\\|"
|
(concat org-outline-regexp-bol "\\|"
|
||||||
org-footnote-definition-re "\\|"
|
org-footnote-definition-re "\\|"
|
||||||
"^[ \t]*$") limit 'move))
|
"^\\([ \t]*\n\\)\\{2,\\}") limit 'move))
|
||||||
(match-beginning 0)
|
(match-beginning 0)
|
||||||
(point))))
|
(point))))
|
||||||
(contents-begin (progn (search-forward "]")
|
(contents-begin (progn (search-forward "]")
|
||||||
|
@ -251,11 +251,12 @@ otherwise."
|
|||||||
(when (save-excursion (beginning-of-line) (org-footnote-in-valid-context-p))
|
(when (save-excursion (beginning-of-line) (org-footnote-in-valid-context-p))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(end-of-line)
|
(end-of-line)
|
||||||
;; Footnotes definitions are separated by new headlines or blank
|
;; Footnotes definitions are separated by new headlines, another
|
||||||
;; lines.
|
;; footnote definition or 2 blank lines.
|
||||||
(let ((lim (save-excursion (re-search-backward
|
(let ((lim (save-excursion
|
||||||
(concat org-outline-regexp-bol
|
(re-search-backward
|
||||||
"\\|^[ \t]*$") nil t))))
|
(concat org-outline-regexp-bol
|
||||||
|
"\\|^\\([ \t]*\n\\)\\{2,\\}") nil t))))
|
||||||
(when (re-search-backward org-footnote-definition-re lim t)
|
(when (re-search-backward org-footnote-definition-re lim t)
|
||||||
(let ((label (org-match-string-no-properties 1))
|
(let ((label (org-match-string-no-properties 1))
|
||||||
(beg (match-beginning 0))
|
(beg (match-beginning 0))
|
||||||
@ -271,7 +272,7 @@ otherwise."
|
|||||||
(re-search-forward
|
(re-search-forward
|
||||||
(concat org-outline-regexp-bol "\\|"
|
(concat org-outline-regexp-bol "\\|"
|
||||||
org-footnote-definition-re "\\|"
|
org-footnote-definition-re "\\|"
|
||||||
"^[ \t]*$") bound 'move))
|
"^\\([ \t]*\n\\)\\{2,\\}") bound 'move))
|
||||||
(match-beginning 0)
|
(match-beginning 0)
|
||||||
(point)))))
|
(point)))))
|
||||||
(list label beg end
|
(list label beg end
|
||||||
|
@ -724,10 +724,10 @@ Some other text
|
|||||||
(org-element-parse-buffer) 'footnote-definition 'identity nil t)))
|
(org-element-parse-buffer) 'footnote-definition 'identity nil t)))
|
||||||
;; Footnote with more contents
|
;; Footnote with more contents
|
||||||
(should
|
(should
|
||||||
(= 28
|
(= 29
|
||||||
(org-element-property
|
(org-element-property
|
||||||
:end
|
: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-map
|
||||||
(org-element-parse-buffer)
|
(org-element-parse-buffer)
|
||||||
'footnote-definition 'identity nil t)))))
|
'footnote-definition 'identity nil t)))))
|
||||||
|
@ -19,6 +19,58 @@
|
|||||||
|
|
||||||
;;; Code:
|
;;; 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 ()
|
(ert-deftest test-org-footnote/normalize-in-org ()
|
||||||
"Test specifications for `org-footnote-normalize' in an Org buffer."
|
"Test specifications for `org-footnote-normalize' in an Org buffer."
|
||||||
;; 1. With a non-nil `org-footnote-section'.
|
;; 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."
|
"Test `org-footnote-normalize' specifications for buffers not in Org mode."
|
||||||
;; 1. In a non-Org buffer, footnotes definitions are always put at
|
;; 1. In a non-Org buffer, footnotes definitions are always put at
|
||||||
;; its end.
|
;; its end.
|
||||||
(let ((org-footnote-tag-for-non-org-mode-files nil))
|
(should
|
||||||
(with-temp-buffer
|
(equal
|
||||||
(insert "Paragraph[fn:1][fn:label][1][fn:inline:Inline][fn::Anonymous]
|
"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.
|
Some additional text.
|
||||||
|
|
||||||
@ -164,7 +205,21 @@ Some additional text.
|
|||||||
|
|
||||||
\[4] Inline
|
\[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.
|
;; 2. With a special tag.
|
||||||
(let ((org-footnote-tag-for-non-org-mode-files "Footnotes:"))
|
(let ((org-footnote-tag-for-non-org-mode-files "Footnotes:"))
|
||||||
;; 2.1. The tag must be inserted before the footnotes, separated
|
;; 2.1. The tag must be inserted before the footnotes, separated
|
||||||
@ -174,12 +229,14 @@ Some additional text.
|
|||||||
|
|
||||||
\[fn:1] Standard
|
\[fn:1] Standard
|
||||||
|
|
||||||
|
|
||||||
Some additional text.")
|
Some additional text.")
|
||||||
(org-footnote-normalize)
|
(org-footnote-normalize)
|
||||||
(should
|
(should
|
||||||
(equal (buffer-string)
|
(equal (buffer-string)
|
||||||
"Paragraph[1][2]
|
"Paragraph[1][2]
|
||||||
|
|
||||||
|
|
||||||
Some additional text.
|
Some additional text.
|
||||||
|
|
||||||
Footnotes:
|
Footnotes:
|
||||||
|
Loading…
Reference in New Issue
Block a user