summaryrefslogtreecommitdiff
path: root/lisp/org/org-footnote.el
diff options
context:
space:
mode:
authorBastien Guerry <bastien1@free.fr>2012-01-03 18:27:21 +0100
committerBastien Guerry <bastien1@free.fr>2012-01-03 18:27:21 +0100
commite66ba1dfc4cf2e12100191d2c24436c42d097268 (patch)
treeb50b009e703fe1a9e8cb13cddf7928a97ad6210c /lisp/org/org-footnote.el
parent88c5c7c8313162b94173fd4333e6062aa07c4d2e (diff)
downloademacs-e66ba1dfc4cf2e12100191d2c24436c42d097268.tar.gz
emacs-e66ba1dfc4cf2e12100191d2c24436c42d097268.tar.bz2
emacs-e66ba1dfc4cf2e12100191d2c24436c42d097268.zip
Merge Org 7.8.03
Diffstat (limited to 'lisp/org/org-footnote.el')
-rw-r--r--lisp/org/org-footnote.el400
1 files changed, 228 insertions, 172 deletions
diff --git a/lisp/org/org-footnote.el b/lisp/org/org-footnote.el
index 0d47132d2f8..a8125513db6 100644
--- a/lisp/org/org-footnote.el
+++ b/lisp/org/org-footnote.el
@@ -5,7 +5,6 @@
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
;; Homepage: http://orgmode.org
-;; Version: 7.7
;;
;; This file is part of GNU Emacs.
;;
@@ -38,28 +37,33 @@
(require 'org-macs)
(require 'org-compat)
+(declare-function message-point-in-header-p "message" ())
+(declare-function org-back-over-empty-lines "org" ())
+(declare-function org-back-to-heading "org" (&optional invisible-ok))
(declare-function org-combine-plists "org" (&rest plists))
+(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
+(declare-function org-export-preprocess-string "org-exp"
+ (string &rest parameters))
+(declare-function org-fill-paragraph "org" (&optional justify))
+(declare-function org-icompleting-read "org" (&rest args))
+(declare-function org-id-uuid "org-id" ())
+(declare-function org-in-block-p "org" (names))
(declare-function org-in-commented-line "org" ())
(declare-function org-in-indented-comment-line "org" ())
(declare-function org-in-regexp "org" (re &optional nlines visually))
-(declare-function org-in-block-p "org" (names))
-(declare-function org-mark-ring-push "org" (&optional pos buffer))
-(declare-function outline-next-heading "outline")
-(declare-function org-trim "org" (s))
-(declare-function org-show-context "org" (&optional key))
-(declare-function org-back-to-heading "org" (&optional invisible-ok))
-(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
(declare-function org-in-verbatim-emphasis "org" ())
+(declare-function org-inside-LaTeX-fragment-p "org" ())
(declare-function org-inside-latex-macro-p "org" ())
-(declare-function org-id-uuid "org" ())
-(declare-function org-fill-paragraph "org" (&optional justify))
-(declare-function org-export-preprocess-string "org-exp"
- (string &rest parameters))
+(declare-function org-mark-ring-push "org" (&optional pos buffer))
+(declare-function org-show-context "org" (&optional key))
+(declare-function org-trim "org" (s))
+(declare-function outline-next-heading "outline")
-(defvar org-outline-regexp-bol) ; defined in org.el
-(defvar org-odd-levels-only) ;; defined in org.el
-(defvar org-bracket-link-regexp) ; defined in org.el
-(defvar message-signature-separator) ;; defined in message.el
+(defvar org-outline-regexp-bol) ; defined in org.el
+(defvar org-odd-levels-only) ; defined in org.el
+(defvar org-bracket-link-regexp) ; defined in org.el
+(defvar message-cite-prefix-regexp) ; defined in message.el
+(defvar message-signature-separator) ; defined in message.el
(defconst org-footnote-re
;; Only [1]-like footnotes are closed in this regexp, as footnotes
@@ -67,17 +71,17 @@
;; their definition.
;;
;; `org-re' is used for regexp compatibility with XEmacs.
- (org-re (concat "\\[\\(?:"
- ;; Match inline footnotes.
- "fn:\\([-_[:word:]]+\\)?:\\|"
- ;; Match other footnotes.
- "\\(?:\\([0-9]+\\)\\]\\)\\|"
- "\\(fn:[-_[:word:]]+\\)"
- "\\)"))
+ (concat "\\[\\(?:"
+ ;; Match inline footnotes.
+ (org-re "fn:\\([-_[:word:]]+\\)?:\\|")
+ ;; Match other footnotes.
+ "\\(?:\\([0-9]+\\)\\]\\)\\|"
+ (org-re "\\(fn:[-_[:word:]]+\\)")
+ "\\)")
"Regular expression for matching footnotes.")
(defconst org-footnote-definition-re
- (org-re "^\\(\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]\\)")
+ (org-re "^\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]")
"Regular expression matching the definition of a footnote.")
(defvar org-footnote-forbidden-blocks '("example" "verse" "src" "ascii" "beamer"
@@ -106,13 +110,17 @@ heading will be removed after extracting footnote definitions."
(defcustom org-footnote-tag-for-non-org-mode-files "Footnotes:"
"Tag marking the beginning of footnote section.
-The Org-mode footnote engine can be used in arbitrary text files as well
-as in Org-mode. Outside Org-mode, new footnotes are always placed at
+The Org footnote engine can be used in arbitrary text files as well
+as in Org-mode. Outside Org mode, new footnotes are always placed at
the end of the file. When you normalize the notes, any line containing
only this tag will be removed, a new one will be inserted at the end
-of the file, followed by the collected and normalized footnotes."
+of the file, followed by the collected and normalized footnotes.
+
+If you don't want any tag in such buffers, set this variable to nil."
:group 'org-footnote
- :type 'string)
+ :type '(choice
+ (string :tag "Collect footnotes under tag")
+ (const :tag "Don't use a tag" nil)))
(defcustom org-footnote-define-inline nil
"Non-nil means define footnotes inline, at reference location.
@@ -171,8 +179,11 @@ extracted will be filled again."
(save-match-data
(not (or (org-in-commented-line)
(org-in-indented-comment-line)
- (org-in-verbatim-emphasis)
+ (org-inside-LaTeX-fragment-p)
+ ;; Avoid protected environments (LaTeX export)
+ (get-text-property (point) 'org-protected)
;; Avoid literal example.
+ (org-in-verbatim-emphasis)
(save-excursion
(beginning-of-line)
(looking-at "[ \t]*:[ \t]+"))
@@ -194,13 +205,13 @@ positions, and the definition, when inlined."
(or (looking-at org-footnote-re)
(org-in-regexp org-footnote-re)
(save-excursion (re-search-backward org-footnote-re nil t)))
- ;; Only inline footnotes can start at bol.
- (or (eq (char-before (match-end 0)) 58)
- (/= (match-beginning 0) (point-at-bol))))
+ (/= (match-beginning 0) (point-at-bol)))
(let* ((beg (match-beginning 0))
- (label (or (match-string 2) (match-string 3)
+ (label (or (org-match-string-no-properties 2)
+ (org-match-string-no-properties 3)
;; Anonymous footnotes don't have labels
- (and (match-string 1) (concat "fn:" (match-string 1)))))
+ (and (match-string 1)
+ (concat "fn:" (org-match-string-no-properties 1)))))
;; Inline footnotes don't end at (match-end 0) as
;; `org-footnote-re' stops just after the second colon.
;; Find the real ending with `scan-sexps', so Org doesn't
@@ -223,12 +234,12 @@ positions, and the definition, when inlined."
;; optional argument of the command. Thus, check
;; the `org-protected' property of that command.
(or (not (org-inside-latex-macro-p))
- (and (get-text-property (1- beg) 'org-protected)
- (not (get-text-property beg 'org-protected)))))
+ (get-text-property (1- beg) 'org-protected)))
(list label beg end
;; Definition: ensure this is an inline footnote first.
(and (or (not label) (match-string 1))
- (org-trim (buffer-substring (match-end 0) (1- end)))))))))
+ (org-trim (buffer-substring-no-properties
+ (match-end 0) (1- end)))))))))
(defun org-footnote-at-definition-p ()
"Is the cursor at a footnote definition?
@@ -239,7 +250,7 @@ footnote text is included and defined locally.
The return value will be nil if not at a footnote definition, and a list with
label, start, end and definition of the footnote otherwise."
- (when (org-footnote-in-valid-context-p)
+ (when (save-excursion (beginning-of-line) (org-footnote-in-valid-context-p))
(save-excursion
(end-of-line)
(let ((lim (save-excursion (re-search-backward
@@ -247,7 +258,7 @@ label, start, end and definition of the footnote otherwise."
"\\|^[ \t]*$") nil t))))
(when (re-search-backward org-footnote-definition-re lim t)
(end-of-line)
- (list (match-string 2)
+ (list (org-match-string-no-properties 1)
(match-beginning 0)
(save-match-data
;; In a message, limit search to signature.
@@ -257,15 +268,14 @@ label, start, end and definition of the footnote otherwise."
(re-search-backward
message-signature-separator nil t)))))
(or (and (re-search-forward
- (org-re
- (concat "^[ \t]*$" "\\|"
- org-outline-regexp-bol
- "\\|"
- "^\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]"))
+ (concat org-outline-regexp-bol "\\|"
+ org-footnote-definition-re "\\|"
+ "^[ \t]*$")
bound 'move)
(progn (skip-chars-forward " \t\n") (point-at-bol)))
(point))))
- (org-trim (buffer-substring (match-end 0) (point)))))))))
+ (org-trim (buffer-substring-no-properties
+ (match-end 0) (point)))))))))
(defun org-footnote-get-next-reference (&optional label backward limit)
"Return complete reference of the next footnote.
@@ -295,10 +305,11 @@ LIMIT is the buffer position bounding the search.
Return value is a list like those provided by
`org-footnote-at-reference-p' or `org-footnote-at-definition-p'.
If no footnote is found, return nil."
- (let* (ref)
+ (let* (ref (origin (point)))
(catch 'exit
(while t
(unless (re-search-forward org-footnote-re limit t)
+ (goto-char origin)
(throw 'exit nil))
;; Beware: with [1]-like footnotes point will be just after
;; the closing square bracket.
@@ -320,19 +331,21 @@ If no footnote is found, return nil."
(re (format "^\\[%s\\]\\|.\\[%s:" label label))
pos)
(save-excursion
- (when (or (re-search-forward re nil t)
- (and (goto-char (point-min))
- (re-search-forward re nil t))
- (and (progn (widen) t)
- (goto-char (point-min))
- (re-search-forward re nil t)))
- (let ((refp (org-footnote-at-reference-p)))
- (cond
- ((and (nth 3 refp) refp))
- ((org-footnote-at-definition-p))))))))
+ (save-restriction
+ (when (or (re-search-forward re nil t)
+ (and (goto-char (point-min))
+ (re-search-forward re nil t))
+ (and (progn (widen) t)
+ (goto-char (point-min))
+ (re-search-forward re nil t)))
+ (let ((refp (org-footnote-at-reference-p)))
+ (cond
+ ((and (nth 3 refp) refp))
+ ((org-footnote-at-definition-p)))))))))
(defun org-footnote-goto-definition (label)
- "Move point to the definition of the footnote LABEL."
+ "Move point to the definition of the footnote LABEL.
+Return a non-nil value when a definition has been found."
(interactive "sLabel: ")
(org-mark-ring-push)
(let ((def (org-footnote-get-definition label)))
@@ -342,7 +355,9 @@ If no footnote is found, return nil."
(looking-at (format "\\[%s\\]\\|\\[%s:" label label))
(goto-char (match-end 0))
(org-show-context 'link-search)
- (message "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'."))))
+ (when (eq major-mode 'org-mode)
+ (message "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'."))
+ t)))
(defun org-footnote-goto-previous-reference (label)
"Find the first closest (to point) reference of footnote with label LABEL."
@@ -406,7 +421,12 @@ and value definition."
(defun org-footnote-unique-label (&optional current)
"Return a new unique footnote label.
-The returns the firsts fn:N labels that is currently not used."
+
+The function returns the first \"fn:N\" or \"N\" label that is
+currently not used.
+
+Optional argument CURRENT is the list of labels active in the
+buffer."
(unless current (setq current (org-footnote-all-labels)))
(let ((fmt (if (eq org-footnote-auto-label 'plain) "%d" "fn:%d"))
(cnt 1))
@@ -414,21 +434,17 @@ The returns the firsts fn:N labels that is currently not used."
(incf cnt))
(format fmt cnt)))
-(defvar org-footnote-label-history nil
- "History of footnote labels entered in current buffer.")
-(make-variable-buffer-local 'org-footnote-label-history)
-
(defun org-footnote-new ()
"Insert a new footnote.
This command prompts for a label. If this is a label referencing an
existing label, only insert the label. If the footnote label is empty
or new, let the user edit the definition of the footnote."
(interactive)
- (unless (and (not (bolp)) (org-footnote-in-valid-context-p))
+ (unless (org-footnote-in-valid-context-p)
(error "Cannot insert a footnote here"))
- (let* ((labels (and (not (equal org-footnote-auto-label 'random))
- (org-footnote-all-labels)))
- (propose (org-footnote-unique-label labels))
+ (let* ((lbls (and (not (equal org-footnote-auto-label 'random))
+ (org-footnote-all-labels)))
+ (propose (org-footnote-unique-label lbls))
(label
(org-footnote-normalize-label
(cond
@@ -438,16 +454,16 @@ or new, let the user edit the definition of the footnote."
(require 'org-id)
(substring (org-id-uuid) 0 8))
(t
- (completing-read
+ (org-icompleting-read
"Label (leave empty for anonymous): "
- (mapcar 'list labels) nil nil
- (if (eq org-footnote-auto-label 'confirm) propose nil)
- 'org-footnote-label-history))))))
+ (mapcar 'list lbls) nil nil
+ (if (eq org-footnote-auto-label 'confirm) propose nil)))))))
(cond
+ ((bolp) (error "Cannot create a footnote reference at left margin"))
((not label)
(insert "[fn:: ]")
(backward-char 1))
- ((member label labels)
+ ((member label lbls)
(insert "[" label "]")
(message "New reference to existing note"))
(org-footnote-define-inline
@@ -459,51 +475,78 @@ or new, let the user edit the definition of the footnote."
(org-footnote-create-definition label)
(org-footnote-auto-adjust-maybe)))))
+(defvar org-blank-before-new-entry nil) ; silence byte-compiler
(defun org-footnote-create-definition (label)
"Start the definition of a footnote with label LABEL."
(interactive "sLabel: ")
(let ((label (org-footnote-normalize-label label)))
(cond
- ((org-mode-p)
- ;; No section, put footnote into the current outline node Try to
- ;; find or make the special node
+ ;; In an Org file.
+ ((eq major-mode 'org-mode)
+ ;; If `org-footnote-section' is defined, find it, or create it
+ ;; at the end of the buffer.
(when org-footnote-section
(goto-char (point-min))
(let ((re (concat "^\\*+[ \t]+" org-footnote-section "[ \t]*$")))
(unless (or (re-search-forward re nil t)
(and (progn (widen) t)
(re-search-forward re nil t)))
- (goto-char (point-max))
- (insert "\n\n* " org-footnote-section "\n"))))
- ;; Now go to the end of this entry and insert there.
+ (goto-char (point-max))
+ (skip-chars-backward " \t\r\n")
+ (unless (bolp) (newline))
+ ;; Insert new section. Separate it from the previous one
+ ;; with a blank line, unless `org-blank-before-new-entry'
+ ;; explicitly says no.
+ (when (and (cdr (assq 'heading org-blank-before-new-entry))
+ (zerop (save-excursion (org-back-over-empty-lines))))
+ (insert "\n"))
+ (insert "* " org-footnote-section "\n"))))
+ ;; Move to the end of this entry (which may be
+ ;; `org-footnote-section' or the current one).
(org-footnote-goto-local-insertion-point)
(org-show-context 'link-search))
(t
;; In a non-Org file. Search for footnote tag, or create it if
- ;; necessary (at the end of buffer, or before a signature if in
+ ;; specified (at the end of buffer, or before signature if in
;; Message mode). Set point after any definition already there.
- (let ((tag (concat "^" org-footnote-tag-for-non-org-mode-files "[ \t]*$"))
- (max (save-excursion
- (if (and (derived-mode-p 'message-mode)
- (re-search-forward
- message-signature-separator nil t))
- (copy-marker (point-at-bol) t)
- (copy-marker (point-max) t)))))
+ (let ((tag (and org-footnote-tag-for-non-org-mode-files
+ (concat "^" (regexp-quote
+ org-footnote-tag-for-non-org-mode-files)
+ "[ \t]*$")))
+ (max (if (and (derived-mode-p 'message-mode)
+ (goto-char (point-max))
+ (re-search-backward
+ message-signature-separator nil t))
+ (progn
+ ;; Ensure one blank line separates last
+ ;; footnote from signature.
+ (beginning-of-line)
+ (open-line 2)
+ (point-marker))
+ (point-max-marker))))
+ (set-marker-insertion-type max t)
(goto-char max)
- (unless (re-search-backward tag nil t)
+ ;; Check if the footnote tag is defined but missing. In this
+ ;; case, insert it, before any footnote or one blank line
+ ;; after any previous text.
+ (when (and tag (not (re-search-backward tag nil t)))
(skip-chars-backward " \t\r\n")
- (delete-region (point) max)
- (insert "\n\n" org-footnote-tag-for-non-org-mode-files "\n"))
- ;; Skip existing footnotes.
- (while (re-search-forward org-footnote-definition-re max t))
- (let ((def (org-footnote-at-definition-p)))
- (when def (goto-char (nth 2 def))))
+ (while (re-search-backward org-footnote-definition-re nil t))
+ (unless (bolp) (newline 2))
+ (insert org-footnote-tag-for-non-org-mode-files "\n\n"))
+ ;; Remove superfluous white space and clear marker.
+ (goto-char max)
+ (skip-chars-backward " \t\r\n")
+ (delete-region (point) max)
+ (unless (bolp) (newline))
(set-marker max nil))))
- ;; Insert footnote label, position point and notify user.
- (unless (bolp) (insert "\n"))
- (insert "\n[" label "] \n")
- (backward-char)
- (message "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'.")))
+ ;; Insert footnote label.
+ (insert "\n[" label "] ")
+ ;; Only notify user about next possible action when in an Org
+ ;; buffer, as the bindings may have different meanings otherwise.
+ (when (eq major-mode 'org-mode)
+ (message
+ "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'."))))
;;;###autoload
(defun org-footnote-action (&optional special)
@@ -570,11 +613,11 @@ If Org is amidst an export process, EXPORT-PROPS will hold the
export properties of the buffer.
When EXPORT-PROPS is non-nil, the default action is to insert
-normalized footnotes towards the end of the pre-processing buffer.
-Some exporters like docbook, odt, etc. expect that footnote
-definitions be available before any references to them. Such
-exporters can let bind `org-footnote-insert-pos-for-preprocessor' to
-symbol 'point-min to achieve the desired behavior.
+normalized footnotes towards the end of the pre-processing
+buffer. Some exporters (docbook, odt...) expect footnote
+definitions to be available before any references to them. Such
+exporters can let bind `org-footnote-insert-pos-for-preprocessor'
+to symbol `point-min' to achieve the desired behaviour.
Additional note on `org-footnote-insert-pos-for-preprocessor':
1. This variable has not effect when FOR-PREPROCESSOR is nil.
@@ -634,8 +677,8 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
(and inlinep
org-footnote-fill-after-inline-note-extraction
(org-fill-paragraph)))
- ;; Add label (REF), identifier (MARKER) and definition (DEF)
- ;; to REF-TABLE if data was unknown.
+ ;; Add label (REF), identifier (MARKER), definition (DEF)
+ ;; and type (INLINEP) to REF-TABLE if data was unknown.
(unless a
(let ((def (or (nth 3 ref) ; inline
(and export-props
@@ -646,52 +689,52 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
;; through `org-export-preprocess-string' so
;; it is ready to insert in the
;; backend-specific buffer.
- (if export-props
+ (if (and export-props def)
(let ((parameters
(org-combine-plists
export-props
'(:todo-keywords t :tags t :priority t))))
(org-export-preprocess-string def parameters))
def)
- inlinep) ref-table)))
- ;; Remove definition of non-inlined footnotes.
- (unless inlinep (org-footnote-delete-definitions lbl))))
+ inlinep) ref-table)))))
;; 2. Find and remove the footnote section, if any. Also
;; determine where footnotes shall be inserted (INS-POINT).
(goto-char (point-min))
(cond
- ((org-mode-p)
- (if (and org-footnote-section
- (re-search-forward
- (concat "^\\*[ \t]+" (regexp-quote org-footnote-section)
- "[ \t]*$")
- nil t))
- (progn
- (setq ins-point (match-beginning 0))
- (delete-region (match-beginning 0) (org-end-of-subtree t)))
- (setq ins-point (point-max))))
+ ((and org-footnote-section
+ (eq major-mode 'org-mode)
+ (re-search-forward
+ (concat "^\\*[ \t]+" (regexp-quote org-footnote-section)
+ "[ \t]*$")
+ nil t))
+ (delete-region (match-beginning 0) (org-end-of-subtree t)))
+ ((eq major-mode 'org-mode)
+ (goto-char (point-max))
+ (unless (bolp) (newline)))
(t
- (when (re-search-forward
- (concat "^"
- (regexp-quote org-footnote-tag-for-non-org-mode-files)
- "[ \t]*$")
- nil t)
- (replace-match ""))
- ;; In message-mode, ensure footnotes are inserted before the
+ ;; Remove any left-over tag in the buffer, if one is set up.
+ (when org-footnote-tag-for-non-org-mode-files
+ (let ((tag (concat "^" (regexp-quote
+ org-footnote-tag-for-non-org-mode-files)
+ "[ \t]*$")))
+ (while (re-search-forward tag nil t)
+ (replace-match "")
+ (delete-region (point) (progn (forward-line) (point))))))
+ ;; In Message mode, ensure footnotes are inserted before the
;; signature.
- (let ((pt-max
- (or (and (derived-mode-p 'message-mode)
- (save-excursion
- (goto-char (point-max))
- (re-search-backward
- message-signature-separator nil t)
- (1- (point))))
- (point-max))))
- (goto-char pt-max)
- (skip-chars-backward " \t\n\r")
- (forward-line)
- (delete-region (point) pt-max))
- (setq ins-point (point))))
+ (if (and (derived-mode-p 'message-mode)
+ (goto-char (point-max))
+ (re-search-backward message-signature-separator nil t))
+ (beginning-of-line)
+ (goto-char (point-max)))))
+ ;; During export, `org-footnote-insert-pos-for-preprocessor' has
+ ;; precedence over previously found position.
+ (setq ins-point
+ (copy-marker
+ (if (and export-props
+ (eq org-footnote-insert-pos-for-preprocessor 'point-min))
+ (point-min)
+ (point))))
;; 3. Clean-up REF-TABLE.
(setq ref-table
(delq nil
@@ -708,34 +751,48 @@ Additional note on `org-footnote-insert-pos-for-preprocessor':
(t x)))
ref-table)))
(setq ref-table (nreverse ref-table))
- ;; 4. Insert the footnotes again in the buffer, at the
+ ;; 4. Remove left-over definitions in the buffer.
+ (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.
- (goto-char (or
- (and export-props
- (eq org-footnote-insert-pos-for-preprocessor 'point-min)
- (point-min))
- ins-point
- (point-max)))
+ (goto-char ins-point)
(cond
;; No footnote: exit.
((not ref-table))
;; Cases when footnotes should be inserted in one place.
- ((or (not (org-mode-p))
+ ((or (not (eq major-mode 'org-mode))
org-footnote-section
(not sort-only))
- ;; Insert again the section title.
+ ;; Insert again the section title, if any. Ensure that title,
+ ;; or the subsequent footnotes, will be separated by a blank
+ ;; lines from the rest of the document. In an Org buffer,
+ ;; separate section with a blank line, unless explicitly
+ ;; stated in `org-blank-before-new-entry'.
(cond
- ((not (org-mode-p))
- (insert "\n\n" org-footnote-tag-for-non-org-mode-files "\n"))
+ ((not (eq major-mode 'org-mode))
+ (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))
- (or (bolp) (insert "\n"))
+ (when (and (cdr (assq 'heading org-blank-before-new-entry))
+ (zerop (save-excursion (org-back-over-empty-lines))))
+ (insert "\n"))
(insert "* " org-footnote-section "\n")))
- ;; Insert the footnotes.
- (insert "\n"
- (mapconcat (lambda (x) (format "[%s] %s"
+ (set-marker ins-point nil)
+ ;; Insert the footnotes, separated by a blank line.
+ (insert (mapconcat (lambda (x) (format "\n[%s] %s"
(nth (if sort-only 0 1) x) (nth 2 x)))
- ref-table "\n\n")
- "\n\n")
+ ref-table "\n"))
+ (unless (eobp) (insert "\n"))
;; When exporting, add newly inserted markers along with their
;; associated definition to `org-export-footnotes-seen'.
(when export-props
@@ -831,20 +888,21 @@ If LABEL is non-nil, delete that footnote instead."
(defun org-footnote-renumber-fn:N ()
"Renumber the simple footnotes like fn:17 into a sequence in the document."
(interactive)
- (let (map i (n 0))
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (while (re-search-forward "\\[fn:\\([0-9]+\\)[]:]" nil t)
- (setq i (string-to-number (match-string 1)))
- (when (and (string-match "\\S-" (buffer-substring
- (point-at-bol) (match-beginning 0)))
- (not (assq i map)))
- (push (cons i (number-to-string (incf n))) map)))
- (goto-char (point-min))
- (while (re-search-forward "\\(\\[fn:\\)\\([0-9]+\\)\\([]:]\\)" nil t)
- (replace-match (concat "\\1" (cdr (assq (string-to-number (match-string 2)) map)) "\\3")))))))
+ (let (map (n 0))
+ (org-with-wide-buffer
+ (goto-char (point-min))
+ (while (re-search-forward "\\[fn:\\([0-9]+\\)[]:]" nil t)
+ (save-excursion
+ (goto-char (match-beginning 0))
+ ;; Ensure match is a footnote reference or definition.
+ (when (save-match-data (if (bolp)
+ (org-footnote-at-definition-p)
+ (org-footnote-at-reference-p)))
+ (let ((new-val (or (cdr (assoc (match-string 1) map))
+ (number-to-string (incf n)))))
+ (unless (assoc (match-string 1) map)
+ (push (cons (match-string 1) new-val) map))
+ (replace-match new-val nil nil nil 1))))))))
(defun org-footnote-auto-adjust-maybe ()
"Renumber and/or sort footnotes according to user settings."
@@ -862,6 +920,4 @@ If LABEL is non-nil, delete that footnote instead."
(provide 'org-footnote)
-
-
;;; org-footnote.el ends here