summaryrefslogtreecommitdiff
path: root/lisp/org/org-footnote.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/org/org-footnote.el')
-rw-r--r--lisp/org/org-footnote.el99
1 files changed, 84 insertions, 15 deletions
diff --git a/lisp/org/org-footnote.el b/lisp/org/org-footnote.el
index 3978d454d61..7da75b1989b 100644
--- a/lisp/org/org-footnote.el
+++ b/lisp/org/org-footnote.el
@@ -5,7 +5,7 @@
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
;; Homepage: http://orgmode.org
-;; Version: 6.21b
+;; Version: 6.29c
;;
;; This file is part of GNU Emacs.
;;
@@ -45,6 +45,7 @@
(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))
+(defvar org-odd-levels-only) ;; defined in org.el
(defconst org-footnote-re
(concat "[^][\n]" ; to make sure it is not at the beginning of a line
@@ -57,7 +58,7 @@
"\\]")
"Regular expression for matching footnotes.")
-(defconst org-footnote-definition-re
+(defconst org-footnote-definition-re
(org-re "^\\(\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]\\)")
"Regular expression matching the definition of a footnote.")
@@ -111,6 +112,23 @@ plain Automatically create plain number labels like [1]"
(const :tag "Offer automatic [fn:N] for editing" confirm)
(const :tag "Create automatic [N]" plain)))
+(defcustom org-footnote-auto-adjust nil
+ "Non-nil means, automatically adjust footnotes after insert/delete.
+When this is t, after each insertion or deletion of a footnote,
+simple fn:N footnotes will be renumbered, and all footnotes will be sorted.
+If you want to have just sorting or just renumbering, set this variable
+to `sort' or `renumber'.
+
+The main values of this variable can be set with in-buffer options:
+
+#+STARTUP: fnadjust
+#+STARTUP: nofnadjust"
+ :group 'org-footnote
+ :type '(choice
+ (const :tag "Renumber" renumber)
+ (const :tag "Sort" sort)
+ (const :tag "Renumber and Sort" t)))
+
(defcustom org-footnote-fill-after-inline-note-extraction nil
"Non-nil means, fill paragraphs after extracting footnotes.
When extracting inline footnotes, the lengths of lines can change a lot.
@@ -246,10 +264,12 @@ or new, let the user edit the definition of the footnote."
(message "New reference to existing note"))
(org-footnote-define-inline
(insert "[" label ": ]")
- (backward-char 1))
+ (backward-char 1)
+ (org-footnote-auto-adjust-maybe))
(t
(insert "[" label "]")
- (org-footnote-create-definition label)))))
+ (org-footnote-create-definition label)
+ (org-footnote-auto-adjust-maybe)))))
(defun org-footnote-create-definition (label)
"Start the definition of a footnote with label LABEL."
@@ -295,11 +315,16 @@ With prefix arg SPECIAL, offer additional commands in a menu."
(let (tmp c)
(cond
(special
- (message "Footnotes: [s]ort | convert to [n]umeric | [d]elete")
+ (message "Footnotes: [s]ort | [r]enumber fn:N | [S]=r+s |->[n]umeric | [d]elete")
(setq c (read-char-exclusive))
(cond
((equal c ?s)
(org-footnote-normalize 'sort))
+ ((equal c ?r)
+ (org-footnote-renumber-fn:N))
+ ((equal c ?S)
+ (org-footnote-renumber-fn:N)
+ (org-footnote-normalize 'sort))
((equal c ?n)
(org-footnote-normalize))
((equal c ?d)
@@ -316,14 +341,24 @@ With prefix arg SPECIAL, offer additional commands in a menu."
;;;###autoload
(defun org-footnote-normalize (&optional sort-only for-preprocessor)
"Collect the footnotes in various formats and normalize them.
-This find the different sorts of footnotes allowed in Org, and
+This finds the different sorts of footnotes allowed in Org, and
normalizes them to the usual [N] format that is understood by the
Org-mode exporters.
When SORT-ONLY is set, only sort the footnote definitions into the
referenced sequence."
;; This is based on Paul's function, but rewritten.
- (let ((count 0) ref def idef ref-table beg beg1 marker a before
- ins-point)
+ (let* ((limit-level
+ (and (boundp 'org-inlinetask-min-level)
+ org-inlinetask-min-level
+ (1- org-inlinetask-min-level)))
+ (nstars (and limit-level
+ (if org-odd-levels-only
+ (and limit-level (1- (* limit-level 2)))
+ limit-level)))
+ (outline-regexp
+ (concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ ")))
+ (count 0)
+ ref def idef ref-table beg beg1 marker a before ins-point)
(save-excursion
;; Now find footnote references, and extract the definitions
(goto-char (point-min))
@@ -362,8 +397,8 @@ referenced sequence."
(and idef
org-footnote-fill-after-inline-note-extraction
(fill-paragraph)))
- (if (not a) (push (list ref marker def) ref-table))))
-
+ (if (not a) (push (list ref marker def (if idef t nil)) ref-table))))
+
;; First find and remove the footnote section
(goto-char (point-min))
(cond
@@ -386,7 +421,7 @@ referenced sequence."
(insert "* " org-footnote-section "\n")
(setq ins-point (point))))))
(t
- (if (re-search-forward
+ (if (re-search-forward
(concat "^"
(regexp-quote org-footnote-tag-for-non-org-mode-files)
"[ \t]*$")
@@ -397,16 +432,17 @@ referenced sequence."
(delete-region (point) (point-max))
(insert "\n\n" org-footnote-tag-for-non-org-mode-files "\n")
(setq ins-point (point))))
-
+
;; Insert the footnotes again
(goto-char (or ins-point (point-max)))
(setq ref-table (reverse ref-table))
(when sort-only
- ;; remove anonymous fotnotes from the list
+ ;; remove anonymous and inline footnotes from the list
(setq ref-table
(delq nil (mapcar
(lambda (x) (and (car x)
(not (equal (car x) "fn:"))
+ (not (nth 3 x))
x))
ref-table))))
;; Make sure each footnote has a description, or an error message.
@@ -451,12 +487,12 @@ ENTRY is (fn-label num-mark definition)."
(defun org-footnote-goto-local-insertion-point ()
"Find insertion point for footnote, just before next outline heading."
- (outline-next-heading)
+ (org-with-limited-levels (outline-next-heading))
(or (bolp) (newline))
(beginning-of-line 0)
(while (and (not (bobp)) (= (char-after) ?#))
(beginning-of-line 0))
- (if (looking-at "#\\+TBLFM:") (beginning-of-line 2))
+ (if (looking-at "[ \t]*#\\+TBLFM:") (beginning-of-line 2))
(end-of-line 1)
(skip-chars-backward "\n\r\t "))
@@ -493,9 +529,42 @@ and all references of a footnote label."
(goto-char (point-max)))
(delete-region beg (point))
(incf ndef))))
+ (org-footnote-auto-adjust-maybe)
(message "%d definition(s) of and %d reference(s) of footnote %s removed"
ndef nref label))))
+(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")))))))
+
+(defun org-footnote-auto-adjust-maybe ()
+ "Renumber and/or sort footnotes according to user settings."
+ (when (memq org-footnote-auto-adjust '(t renumber))
+ (org-footnote-renumber-fn:N))
+ (when (memq org-footnote-auto-adjust '(t sort))
+ (let ((label (nth 1 (org-footnote-at-definition-p))))
+ (org-footnote-normalize 'sort)
+ (when label
+ (goto-char (point-min))
+ (and (re-search-forward (concat "^\\[" (regexp-quote label) "\\]")
+ nil t)
+ (progn (insert " ")
+ (just-one-space)))))))
+
(provide 'org-footnote)
;; arch-tag: 1b5954df-fb5d-4da5-8709-78d944dbfc37