Function: org-footnote-normalize

org-footnote-normalize is an interactive and byte-compiled function defined in org-footnote.el.gz.

Signature

(org-footnote-normalize)

Documentation

Turn every footnote in buffer into a numbered one.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-footnote.el.gz
(defun org-footnote-normalize ()
  "Turn every footnote in buffer into a numbered one."
  (interactive)
  (org-preserve-local-variables
   (let ((n 0)
	 (translations nil)
	 (definitions nil)
	 (references (org-footnote--collect-references 'anonymous)))
     (org-with-wide-buffer
      ;; Update label for reference.  We need to do this before
      ;; clearing definitions in order to rename nested footnotes
      ;; before they are deleted.
      (dolist (cell references)
	(let* ((label (car cell))
	       (anonymous (not label))
	       (new
		(cond
		 ;; In order to differentiate anonymous references
		 ;; from regular ones, set their labels to integers,
		 ;; not strings.
		 (anonymous (setcar cell (cl-incf n)))
		 ((cdr (assoc label translations)))
		 (t (let ((l (number-to-string (cl-incf n))))
		      (push (cons label l) translations)
		      l)))))
	  (goto-char (nth 1 cell))	; Move to reference's start.
	  (org-footnote--set-label
	   (if anonymous (number-to-string new) new))
	  (let ((size (nth 3 cell)))
	    ;; Transform inline footnotes into regular references and
	    ;; retain their definition for later insertion as
	    ;; a regular footnote definition.
	    (when size
	      (let ((def (concat
			  (format "[fn:%s] " new)
			  (org-trim
			   (substring
			    (delete-and-extract-region
			     (point) (+ (point) size 1))
			    1)))))
		(push (cons (if anonymous new label) def) definitions)
		(when org-footnote-fill-after-inline-note-extraction
		  (org-fill-paragraph)))))))
      ;; Collect definitions.  Update labels according to ALIST.
      (let ((definitions
	      (nconc definitions
		     (org-footnote--collect-definitions 'delete)))
	    (inserted))
	(org-footnote--clear-footnote-section)
	(dolist (cell references)
	  (let* ((label (car cell))
		 (anonymous (integerp label))
		 (pos (nth 1 cell)))
	    ;; Move to appropriate location, if required.  When there
	    ;; is a footnote section or reference is nested, point is
	    ;; already at the expected location.
	    (unless (or org-footnote-section (not (nth 2 cell)))
	      (goto-char pos)
	      (org-footnote--goto-local-insertion-point))
	    ;; Insert new definition once label is updated.
	    (unless (member label inserted)
	      (push label inserted)
	      (let ((stored (cdr (assoc label definitions)))
		    ;; Anonymous footnotes' label is already
		    ;; up-to-date.
		    (new (if anonymous label
			   (cdr (assoc label translations)))))
		(insert "\n"
			(cond
			 ((not stored)
			  (format "[fn:%s] DEFINITION NOT FOUND." new))
			 (anonymous stored)
			 (t
			  (replace-regexp-in-string
			   "\\`\\[fn:\\(.*?\\)\\]" new stored nil nil 1)))
			"\n")))))
	;; Insert un-referenced footnote definitions at the end.
	(pcase-dolist (`(,label . ,definition) definitions)
	  (unless (member label inserted)
	    (insert "\n"
		    (replace-regexp-in-string org-footnote-definition-re
					      (format "[fn:%d]" (cl-incf n))
					      definition)
		    "\n"))))))))