2008-12-30 17:40:14 -05:00
|
|
|
;;; org-footnote.el --- Footnote support in Org and elsewhere
|
|
|
|
;;
|
2015-02-15 19:40:07 -05:00
|
|
|
;; Copyright (C) 2009-2015 Free Software Foundation, Inc.
|
2008-12-30 17:40:14 -05:00
|
|
|
;;
|
|
|
|
;; Author: Carsten Dominik <carsten at orgmode dot org>
|
|
|
|
;; Keywords: outlines, hypermedia, calendar, wp
|
|
|
|
;; Homepage: http://orgmode.org
|
|
|
|
;;
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
;;
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
;; This file contains the code dealing with footnotes in Org-mode.
|
|
|
|
;; The code can also be used in arbitrary text modes to provide
|
|
|
|
;; footnotes. Compared to Steven L Baur's footnote.el it provides
|
|
|
|
;; better support for resuming editing. It is less configurable than
|
|
|
|
;; Steve's code, though.
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
(eval-when-compile
|
|
|
|
(require 'cl))
|
|
|
|
(require 'org-macs)
|
|
|
|
(require 'org-compat)
|
|
|
|
|
2011-08-14 04:52:14 -04:00
|
|
|
(declare-function message-point-in-header-p "message" ())
|
2011-08-16 14:02:30 -04:00
|
|
|
(declare-function org-back-over-empty-lines "org" ())
|
|
|
|
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
2011-07-16 03:19:50 -04:00
|
|
|
(declare-function org-combine-plists "org" (&rest plists))
|
2014-06-01 08:19:25 -04:00
|
|
|
(declare-function org-element-context "org-element" (&optional element))
|
|
|
|
(declare-function org-element-property "org-element" (property element))
|
|
|
|
(declare-function org-element-type "org-element" (element))
|
2011-08-16 14:02:30 -04:00
|
|
|
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
|
|
|
|
(declare-function org-fill-paragraph "org" (&optional justify))
|
2011-08-14 04:52:14 -04:00
|
|
|
(declare-function org-icompleting-read "org" (&rest args))
|
2011-08-16 14:02:30 -04:00
|
|
|
(declare-function org-id-uuid "org-id" ())
|
|
|
|
(declare-function org-in-block-p "org" (names))
|
2014-05-26 11:33:24 -04:00
|
|
|
(declare-function org-at-comment-p "org" ())
|
2008-12-30 17:40:14 -05:00
|
|
|
(declare-function org-in-regexp "org" (re &optional nlines visually))
|
2009-10-29 11:34:33 -04:00
|
|
|
(declare-function org-in-verbatim-emphasis "org" ())
|
2011-09-04 10:45:39 -04:00
|
|
|
(declare-function org-inside-LaTeX-fragment-p "org" ())
|
2009-12-11 02:49:44 -05:00
|
|
|
(declare-function org-inside-latex-macro-p "org" ())
|
2011-08-16 14:02:30 -04:00
|
|
|
(declare-function org-mark-ring-push "org" (&optional pos buffer))
|
|
|
|
(declare-function org-show-context "org" (&optional key))
|
|
|
|
(declare-function org-trim "org" (s))
|
2012-03-19 16:38:12 -04:00
|
|
|
(declare-function org-skip-whitespace "org" ())
|
2011-08-16 14:02:30 -04:00
|
|
|
(declare-function outline-next-heading "outline")
|
2012-03-20 08:04:55 -04:00
|
|
|
(declare-function org-skip-whitespace "org" ())
|
2011-07-18 13:25:10 -04:00
|
|
|
|
2011-08-14 04:52:14 -04:00
|
|
|
(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
|
2008-12-30 17:40:14 -05:00
|
|
|
|
|
|
|
(defconst org-footnote-re
|
2011-06-28 19:14:13 -04:00
|
|
|
;; Only [1]-like footnotes are closed in this regexp, as footnotes
|
|
|
|
;; from other types might contain square brackets (i.e. links) in
|
|
|
|
;; their definition.
|
2011-04-29 09:46:25 -04:00
|
|
|
;;
|
|
|
|
;; `org-re' is used for regexp compatibility with XEmacs.
|
2011-10-21 16:36:53 -04:00
|
|
|
(concat "\\[\\(?:"
|
|
|
|
;; Match inline footnotes.
|
|
|
|
(org-re "fn:\\([-_[:word:]]+\\)?:\\|")
|
|
|
|
;; Match other footnotes.
|
|
|
|
"\\(?:\\([0-9]+\\)\\]\\)\\|"
|
|
|
|
(org-re "\\(fn:[-_[:word:]]+\\)")
|
|
|
|
"\\)")
|
2008-12-30 17:40:14 -05:00
|
|
|
"Regular expression for matching footnotes.")
|
|
|
|
|
2009-06-08 02:00:46 -04:00
|
|
|
(defconst org-footnote-definition-re
|
2011-08-16 09:31:20 -04:00
|
|
|
(org-re "^\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]")
|
2008-12-30 17:40:14 -05:00
|
|
|
"Regular expression matching the definition of a footnote.")
|
|
|
|
|
2012-02-24 03:42:15 -05:00
|
|
|
(defconst org-footnote-forbidden-blocks
|
Remove references to the DocBook exporter
* org.el (org-emphasis-alist, org-protecting-blocks):
* org-src.el (org-edit-src-find-region-and-lang):
* org-list.el (org-list-forbidden-blocks):
* org-footnote.el (org-footnote-forbidden-blocks): Remove
references to the deleted DocBook exporter.
* org.texi (Top, Markup, Initial text, Images and tables)
(@LaTeX{} fragments, @LaTeX{} fragments, Exporting)
(Export options, JavaScript support, Beamer class export):
Remove references to the DocBook export, which has been
deleted.
(History and Acknowledgments): Mention that DocBook has been
deleted, suggest to use the Texinfo exporter instead, then to
convert the .texi to DocBook with makeinfo.
(Links in ODT export, Tables in ODT export): Fix indices.
2013-02-14 03:48:36 -05:00
|
|
|
'("ascii" "beamer" "comment" "example" "html" "latex" "odt" "src")
|
2011-07-10 04:33:25 -04:00
|
|
|
"Names of blocks where footnotes are not allowed.")
|
2011-07-08 09:48:07 -04:00
|
|
|
|
2010-04-27 02:11:03 -04:00
|
|
|
(defgroup org-footnote nil
|
|
|
|
"Footnotes in Org-mode."
|
|
|
|
:tag "Org Footnote"
|
|
|
|
:group 'org)
|
|
|
|
|
2008-12-30 17:40:14 -05:00
|
|
|
(defcustom org-footnote-section "Footnotes"
|
2013-01-27 18:02:51 -05:00
|
|
|
"Outline heading containing footnote definitions.
|
|
|
|
|
|
|
|
This can be nil, to place footnotes locally at the end of the
|
|
|
|
current outline node. If can also be the name of a special
|
|
|
|
outline heading under which footnotes should be put.
|
|
|
|
|
2009-01-01 12:01:07 -05:00
|
|
|
This variable defines the place where Org puts the definition
|
2013-01-27 18:02:51 -05:00
|
|
|
automatically, i.e. when creating the footnote, and when sorting
|
|
|
|
the notes. However, by hand you may place definitions
|
|
|
|
*anywhere*.
|
|
|
|
|
|
|
|
If this is a string, during export, all subtrees starting with
|
org-element: Implement caching for dynamic parser
* lisp/org-element.el (org-element-use-cache, org-element--cache,
org-element--cache-sync-idle-time,
org-element--cache-merge-changes-threshold, org-element--cache-status,
org-element--cache-opening-line, org-element--cache-closing-line): New
variables.
(org-element-cache-reset, org-element--cache-pending-changes-p,
org-element--cache-push-change, org-element--cache-cancel-changes,
org-element--cache-get-key, org-element-cache-get,
org-element-cache-put, org-element--shift-positions,
org-element--cache-before-change, org-element--cache-record-change,
org-element--cache-sync): New functions.
(org-element-at-point, org-element-context): Use cache when possible.
* lisp/org.el (org-mode, org-set-modules): Reset cache.
* lisp/org-footnote.el (org-footnote-section): Reset cache.
* testing/lisp/test-org-element.el: Update tests.
This patch gives a boost to `org-element-at-point' and, to a lesser
extent, to `org-element-context'.
2013-10-27 06:09:17 -04:00
|
|
|
this heading will be ignored.
|
|
|
|
|
|
|
|
If you don't use the customize interface to change this variable,
|
|
|
|
you will need to run the following command after the change:
|
|
|
|
|
|
|
|
\\[universal-argument] \\[org-element-cache-reset]"
|
2010-04-27 02:11:03 -04:00
|
|
|
:group 'org-footnote
|
2013-11-17 03:52:54 -05:00
|
|
|
:initialize 'custom-initialize-default
|
2013-11-05 14:47:29 -05:00
|
|
|
:set (lambda (var val)
|
|
|
|
(set var val)
|
|
|
|
(when (fboundp 'org-element-cache-reset)
|
|
|
|
(org-element-cache-reset 'all)))
|
2009-01-01 12:01:07 -05:00
|
|
|
:type '(choice
|
2009-11-12 07:39:29 -05:00
|
|
|
(string :tag "Collect footnotes under heading")
|
2009-01-03 03:03:04 -05:00
|
|
|
(const :tag "Define footnotes locally" nil)))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
|
|
|
(defcustom org-footnote-tag-for-non-org-mode-files "Footnotes:"
|
|
|
|
"Tag marking the beginning of footnote section.
|
2011-08-16 14:02:30 -04:00
|
|
|
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
|
2008-12-30 17:40:14 -05:00
|
|
|
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
|
2011-08-16 14:02:30 -04:00
|
|
|
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."
|
2010-04-27 02:11:03 -04:00
|
|
|
:group 'org-footnote
|
2011-08-16 14:02:30 -04:00
|
|
|
:type '(choice
|
|
|
|
(string :tag "Collect footnotes under tag")
|
|
|
|
(const :tag "Don't use a tag" nil)))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
|
|
|
(defcustom org-footnote-define-inline nil
|
2010-01-21 10:15:40 -05:00
|
|
|
"Non-nil means define footnotes inline, at reference location.
|
2008-12-30 17:40:14 -05:00
|
|
|
When nil, footnotes will be defined in a special section near
|
|
|
|
the end of the document. When t, the [fn:label:definition] notation
|
|
|
|
will be used to define the footnote at the reference position."
|
|
|
|
:group 'org-footnote
|
|
|
|
:type 'boolean)
|
|
|
|
|
2009-01-02 09:53:02 -05:00
|
|
|
(defcustom org-footnote-auto-label t
|
2010-01-21 10:15:40 -05:00
|
|
|
"Non-nil means define automatically new labels for footnotes.
|
2009-01-02 09:53:02 -05:00
|
|
|
Possible values are:
|
|
|
|
|
2013-04-08 12:08:03 -04:00
|
|
|
nil Prompt the user for each label.
|
|
|
|
t Create unique labels of the form [fn:1], [fn:2], etc.
|
|
|
|
confirm Like t, but let the user edit the created value.
|
|
|
|
The label can be removed from the minibuffer to create
|
2009-01-02 09:53:02 -05:00
|
|
|
an anonymous footnote.
|
2011-03-11 13:50:59 -05:00
|
|
|
random Automatically generate a unique, random label.
|
2013-04-08 12:08:03 -04:00
|
|
|
plain Automatically create plain number labels like [1]."
|
2009-01-02 09:53:02 -05:00
|
|
|
:group 'org-footnote
|
|
|
|
:type '(choice
|
2009-11-12 07:39:29 -05:00
|
|
|
(const :tag "Prompt for label" nil)
|
2009-01-02 09:53:02 -05:00
|
|
|
(const :tag "Create automatic [fn:N]" t)
|
|
|
|
(const :tag "Offer automatic [fn:N] for editing" confirm)
|
2011-03-11 13:50:59 -05:00
|
|
|
(const :tag "Create a random label" random)
|
2009-01-02 09:53:02 -05:00
|
|
|
(const :tag "Create automatic [N]" plain)))
|
|
|
|
|
2009-07-03 11:56:47 -04:00
|
|
|
(defcustom org-footnote-auto-adjust nil
|
2010-01-21 10:15:40 -05:00
|
|
|
"Non-nil means automatically adjust footnotes after insert/delete.
|
2009-07-03 11:56:47 -04:00
|
|
|
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
|
2013-05-09 09:19:02 -04:00
|
|
|
(const :tag "No adjustment" nil)
|
2009-07-03 11:56:47 -04:00
|
|
|
(const :tag "Renumber" renumber)
|
|
|
|
(const :tag "Sort" sort)
|
|
|
|
(const :tag "Renumber and Sort" t)))
|
|
|
|
|
2009-01-03 03:03:04 -05:00
|
|
|
(defcustom org-footnote-fill-after-inline-note-extraction nil
|
2010-01-21 10:15:40 -05:00
|
|
|
"Non-nil means fill paragraphs after extracting footnotes.
|
2009-01-03 03:03:04 -05:00
|
|
|
When extracting inline footnotes, the lengths of lines can change a lot.
|
|
|
|
When this option is set, paragraphs from which an inline footnote has been
|
|
|
|
extracted will be filled again."
|
|
|
|
:group 'org-footnote
|
|
|
|
:type 'boolean)
|
|
|
|
|
2011-07-08 09:48:07 -04:00
|
|
|
(defun org-footnote-in-valid-context-p ()
|
|
|
|
"Is point in a context where footnotes are allowed?"
|
2011-07-19 06:51:23 -04:00
|
|
|
(save-match-data
|
2014-05-26 11:33:24 -04:00
|
|
|
(not (or (org-at-comment-p)
|
2011-09-04 10:45:39 -04:00
|
|
|
(org-inside-LaTeX-fragment-p)
|
2011-07-19 06:51:23 -04:00
|
|
|
;; Avoid literal example.
|
2011-07-30 06:38:06 -04:00
|
|
|
(org-in-verbatim-emphasis)
|
2011-07-19 06:51:23 -04:00
|
|
|
(save-excursion
|
|
|
|
(beginning-of-line)
|
|
|
|
(looking-at "[ \t]*:[ \t]+"))
|
|
|
|
;; Avoid cited text and headers in message-mode.
|
|
|
|
(and (derived-mode-p 'message-mode)
|
|
|
|
(or (save-excursion
|
|
|
|
(beginning-of-line)
|
|
|
|
(looking-at message-cite-prefix-regexp))
|
|
|
|
(message-point-in-header-p)))
|
|
|
|
;; Avoid forbidden blocks.
|
|
|
|
(org-in-block-p org-footnote-forbidden-blocks)))))
|
2011-07-08 09:48:07 -04:00
|
|
|
|
2008-12-30 17:40:14 -05:00
|
|
|
(defun org-footnote-at-reference-p ()
|
|
|
|
"Is the cursor at a footnote reference?
|
2011-04-29 09:46:25 -04:00
|
|
|
|
2011-07-14 03:49:50 -04:00
|
|
|
If so, return a list containing its label, beginning and ending
|
|
|
|
positions, and the definition, when inlined."
|
2011-07-08 09:48:07 -04:00
|
|
|
(when (and (org-footnote-in-valid-context-p)
|
2011-06-30 04:59:54 -04:00
|
|
|
(or (looking-at org-footnote-re)
|
|
|
|
(org-in-regexp org-footnote-re)
|
2011-04-29 09:46:25 -04:00
|
|
|
(save-excursion (re-search-backward org-footnote-re nil t)))
|
2011-11-06 08:14:12 -05:00
|
|
|
(/= (match-beginning 0) (point-at-bol)))
|
2011-04-29 09:46:25 -04:00
|
|
|
(let* ((beg (match-beginning 0))
|
2011-10-24 02:10:56 -04:00
|
|
|
(label (or (org-match-string-no-properties 2)
|
|
|
|
(org-match-string-no-properties 3)
|
2011-04-29 09:46:25 -04:00
|
|
|
;; Anonymous footnotes don't have labels
|
2011-10-24 02:10:56 -04:00
|
|
|
(and (match-string 1)
|
|
|
|
(concat "fn:" (org-match-string-no-properties 1)))))
|
2011-04-29 09:46:25 -04:00
|
|
|
;; 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
|
|
|
|
;; get fooled by unrelated closing square brackets.
|
|
|
|
(end (ignore-errors (scan-sexps beg 1))))
|
|
|
|
;; Point is really at a reference if it's located before true
|
2011-07-18 15:54:24 -04:00
|
|
|
;; ending of the footnote.
|
2011-07-19 06:51:23 -04:00
|
|
|
(when (and end (< (point) end)
|
|
|
|
;; Verify match isn't a part of a link.
|
|
|
|
(not (save-excursion
|
|
|
|
(goto-char beg)
|
|
|
|
(let ((linkp
|
|
|
|
(save-match-data
|
|
|
|
(org-in-regexp org-bracket-link-regexp))))
|
|
|
|
(and linkp (< (point) (cdr linkp))))))
|
|
|
|
;; Verify point doesn't belong to a LaTeX macro.
|
2013-01-30 10:06:01 -05:00
|
|
|
(not (org-inside-latex-macro-p)))
|
2011-04-29 09:46:25 -04:00
|
|
|
(list label beg end
|
|
|
|
;; Definition: ensure this is an inline footnote first.
|
|
|
|
(and (or (not label) (match-string 1))
|
2011-10-29 08:21:56 -04:00
|
|
|
(org-trim (buffer-substring-no-properties
|
|
|
|
(match-end 0) (1- end)))))))))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
|
|
|
(defun org-footnote-at-definition-p ()
|
2012-02-02 03:08:28 -05:00
|
|
|
"Is point within a footnote definition?
|
2011-04-29 09:46:25 -04:00
|
|
|
|
2012-02-02 03:08:28 -05:00
|
|
|
This matches only pure definitions like [1] or [fn:name] at the
|
|
|
|
beginning of a line. It does not match references like
|
|
|
|
\[fn:name:definition], where the footnote text is included and
|
|
|
|
defined locally.
|
2011-04-29 09:46:25 -04:00
|
|
|
|
2012-02-02 03:08:28 -05:00
|
|
|
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."
|
2011-09-17 06:01:54 -04:00
|
|
|
(when (save-excursion (beginning-of-line) (org-footnote-in-valid-context-p))
|
2011-07-18 15:54:24 -04:00
|
|
|
(save-excursion
|
|
|
|
(end-of-line)
|
2013-02-21 09:30:16 -05:00
|
|
|
;; 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))))
|
2011-07-18 15:54:24 -04:00
|
|
|
(when (re-search-backward org-footnote-definition-re lim t)
|
2012-02-02 03:08:28 -05:00
|
|
|
(let ((label (org-match-string-no-properties 1))
|
|
|
|
(beg (match-beginning 0))
|
|
|
|
(beg-def (match-end 0))
|
|
|
|
;; In message-mode, do not search after signature.
|
|
|
|
(end (let ((bound (and (derived-mode-p 'message-mode)
|
|
|
|
(save-excursion
|
|
|
|
(goto-char (point-max))
|
|
|
|
(re-search-backward
|
|
|
|
message-signature-separator nil t)))))
|
|
|
|
(if (progn
|
|
|
|
(end-of-line)
|
|
|
|
(re-search-forward
|
2011-09-29 16:44:58 -04:00
|
|
|
(concat org-outline-regexp-bol "\\|"
|
|
|
|
org-footnote-definition-re "\\|"
|
2013-02-21 09:30:16 -05:00
|
|
|
"^\\([ \t]*\n\\)\\{2,\\}") bound 'move))
|
2012-04-06 13:14:51 -04:00
|
|
|
(match-beginning 0)
|
2012-02-02 03:08:28 -05:00
|
|
|
(point)))))
|
|
|
|
(list label beg end
|
|
|
|
(org-trim (buffer-substring-no-properties beg-def end)))))))))
|
2011-04-29 09:46:25 -04:00
|
|
|
|
2011-04-30 07:23:21 -04:00
|
|
|
(defun org-footnote-get-next-reference (&optional label backward limit)
|
|
|
|
"Return complete reference of the next footnote.
|
|
|
|
|
|
|
|
If LABEL is provided, get the next reference of that footnote. If
|
|
|
|
BACKWARD is non-nil, find previous reference instead. LIMIT is
|
|
|
|
the buffer position bounding the search.
|
|
|
|
|
|
|
|
Return value is a list like those provided by `org-footnote-at-reference-p'.
|
|
|
|
If no footnote is found, return nil."
|
|
|
|
(save-excursion
|
2011-05-02 05:34:06 -04:00
|
|
|
(let* ((label-fmt (if label (format "\\[%s[]:]" label) org-footnote-re)))
|
2011-04-30 07:23:21 -04:00
|
|
|
(catch 'exit
|
|
|
|
(while t
|
|
|
|
(unless (funcall (if backward #'re-search-backward #'re-search-forward)
|
|
|
|
label-fmt limit t)
|
|
|
|
(throw 'exit nil))
|
|
|
|
(unless backward (backward-char))
|
2011-05-02 05:34:06 -04:00
|
|
|
(let ((ref (org-footnote-at-reference-p)))
|
|
|
|
(when ref (throw 'exit ref))))))))
|
|
|
|
|
|
|
|
(defun org-footnote-next-reference-or-definition (limit)
|
|
|
|
"Move point to next footnote reference or definition.
|
|
|
|
|
|
|
|
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."
|
2011-07-29 15:06:38 -04:00
|
|
|
(let* (ref (origin (point)))
|
2011-05-02 05:34:06 -04:00
|
|
|
(catch 'exit
|
|
|
|
(while t
|
|
|
|
(unless (re-search-forward org-footnote-re limit t)
|
2011-07-29 15:06:38 -04:00
|
|
|
(goto-char origin)
|
2011-05-02 05:34:06 -04:00
|
|
|
(throw 'exit nil))
|
2011-06-28 19:14:13 -04:00
|
|
|
;; Beware: with [1]-like footnotes point will be just after
|
|
|
|
;; the closing square bracket.
|
|
|
|
(backward-char)
|
2011-05-02 05:34:06 -04:00
|
|
|
(cond
|
|
|
|
((setq ref (org-footnote-at-reference-p))
|
|
|
|
(throw 'exit ref))
|
2011-06-28 19:14:13 -04:00
|
|
|
;; Definition: also grab the last square bracket, only
|
|
|
|
;; matched in `org-footnote-re' for [1]-like footnotes.
|
2011-07-05 07:28:03 -04:00
|
|
|
((save-match-data (org-footnote-at-definition-p))
|
2011-06-28 19:14:13 -04:00
|
|
|
(let ((end (match-end 0)))
|
|
|
|
(throw 'exit
|
|
|
|
(list nil (match-beginning 0)
|
|
|
|
(if (eq (char-before end) 93) end (1+ end)))))))))))
|
2011-04-30 07:23:21 -04:00
|
|
|
|
2011-04-29 09:46:25 -04:00
|
|
|
(defun org-footnote-get-definition (label)
|
|
|
|
"Return label, boundaries and definition of the footnote LABEL."
|
|
|
|
(let* ((label (regexp-quote (org-footnote-normalize-label label)))
|
|
|
|
(re (format "^\\[%s\\]\\|.\\[%s:" label label))
|
|
|
|
pos)
|
|
|
|
(save-excursion
|
2011-08-25 15:12:07 -04:00
|
|
|
(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)))))))))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
|
|
|
(defun org-footnote-goto-definition (label)
|
2011-09-29 09:30:46 -04:00
|
|
|
"Move point to the definition of the footnote LABEL.
|
|
|
|
Return a non-nil value when a definition has been found."
|
2008-12-30 17:40:14 -05:00
|
|
|
(interactive "sLabel: ")
|
2015-04-25 05:09:05 -04:00
|
|
|
(let ((def-start (nth 1 (org-footnote-get-definition label))))
|
2015-04-25 04:36:35 -04:00
|
|
|
(cond
|
2015-04-25 05:09:05 -04:00
|
|
|
((not def-start)
|
|
|
|
(user-error "Cannot find definition of footnote %s" label))
|
|
|
|
((or (> def-start (point-max))
|
|
|
|
(< def-start (point-min)))
|
2015-04-25 04:36:35 -04:00
|
|
|
(user-error "Footnote definition outside of narrowed part of buffer"))
|
|
|
|
(t
|
|
|
|
(org-mark-ring-push)
|
2015-04-25 05:09:05 -04:00
|
|
|
(goto-char def-start)
|
2015-04-25 04:36:35 -04:00
|
|
|
(looking-at (format "\\[%s[]:]" label))
|
2011-04-29 09:46:25 -04:00
|
|
|
(goto-char (match-end 0))
|
2009-01-02 10:28:35 -05:00
|
|
|
(org-show-context 'link-search)
|
Use (derived-mode-p 'org-mode) instead of (eq major-mode 'org-mode).
* org.el (org-show-hierarchy-above, org-cycle)
(org-global-cycle, org-files-list, org-store-link)
(org-link-search, org-open-file, org-display-outline-path)
(org-refile-get-location, org-update-all-dblocks)
(org-change-tag-in-region, org-entry-properties)
(org-save-all-org-buffers, org-revert-all-org-buffers)
(org-buffer-list, org-cdlatex-mode)
(org-install-agenda-files-menu, org-end-of-subtree)
(org-speedbar-set-agenda-restriction): Use (derived-mode-p
'org-mode) instead of (eq major-mode 'org-mode).
* org-timer.el (org-timer-set-timer): Ditto.
* org-table.el (orgtbl-mode, org-table-align, orgtbl-mode): Ditto.
* org-src.el (org-edit-src-exit, org-edit-src-code)
(org-edit-fixed-width-region, org-edit-src-exit): Ditto.
* org-remember.el (org-remember-handler): Ditto.
* org-mouse.el (dnd-open-file, org-mouse-insert-item): Ditto.
* org-macs.el (org-get-limited-outline-regexp): Ditto.
* org-lparse.el (org-replace-region-by): Ditto.
* org-latex.el (org-latex-to-pdf-process)
(org-replace-region-by-latex): Ditto.
* org-indent.el (org-indent-indent-buffer): Ditto.
* org-id.el (org-id-store-link, org-id-update-id-locations)
(org-id-store-link): Ditto.
* org-html.el (org-export-html-preprocess)
(org-replace-region-by-html): Ditto.
* org-footnote.el (org-footnote-normalize)
(org-footnote-goto-definition)
(org-footnote-create-definition, org-footnote-normalize): Ditto.
* org-docbook.el (org-replace-region-by-docbook): Ditto.
* org-ctags.el (find-tag): Ditto.
* org-colview.el (org-columns-redo)
(org-columns-display-here, org-columns-edit-value)
(org-columns-redo): Ditto.
* org-colview-xemacs.el (org-columns-redo)
(org-columns-display-here, org-columns-edit-value)
(org-columns-redo): Ditto.
* org-capture.el (org-capture-insert-template-here)
(org-capture, org-capture-finalize)
(org-capture-set-target-location)
(org-capture-insert-template-here): Ditto.
* org-ascii.el (org-replace-region-by-ascii): Ditto.
* org-archive.el (org-archive-subtree): Ditto.
* org-agenda.el (org-agenda)
(org-agenda-get-restriction-and-command)
(org-agenda-get-some-entry-text, org-search-view)
(org-tags-view, org-agenda-get-day-entries)
(org-agenda-format-item, org-agenda-goto, org-agenda-kill)
(org-agenda-archive-with, org-agenda-switch-to): Ditto.
2012-04-20 14:03:45 -04:00
|
|
|
(when (derived-mode-p 'org-mode)
|
2011-09-29 09:30:46 -04:00
|
|
|
(message "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'."))
|
2015-04-25 04:36:35 -04:00
|
|
|
t))))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
2010-04-14 10:45:45 -04:00
|
|
|
(defun org-footnote-goto-previous-reference (label)
|
2010-10-24 08:40:54 -04:00
|
|
|
"Find the first closest (to point) reference of footnote with label LABEL."
|
2008-12-30 17:40:14 -05:00
|
|
|
(interactive "sLabel: ")
|
|
|
|
(org-mark-ring-push)
|
2011-04-30 07:23:21 -04:00
|
|
|
(let* ((label (org-footnote-normalize-label label)) ref)
|
2008-12-30 17:40:14 -05:00
|
|
|
(save-excursion
|
2011-04-30 07:23:21 -04:00
|
|
|
(setq ref (or (org-footnote-get-next-reference label t)
|
|
|
|
(org-footnote-get-next-reference label)
|
|
|
|
(save-restriction
|
|
|
|
(widen)
|
|
|
|
(or
|
|
|
|
(org-footnote-get-next-reference label t)
|
|
|
|
(org-footnote-get-next-reference label))))))
|
|
|
|
(if (not ref)
|
|
|
|
(error "Cannot find reference of footnote %s" label)
|
|
|
|
(goto-char (nth 1 ref))
|
|
|
|
(org-show-context 'link-search))))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
|
|
|
(defun org-footnote-normalize-label (label)
|
2011-05-02 05:37:39 -04:00
|
|
|
"Return LABEL as an appropriate string."
|
|
|
|
(cond
|
|
|
|
((numberp label) (number-to-string label))
|
|
|
|
((equal "" label) nil)
|
|
|
|
((not (string-match "^[0-9]+$\\|^fn:" label))
|
|
|
|
(concat "fn:" label))
|
|
|
|
(t label)))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
2011-05-11 12:02:15 -04:00
|
|
|
(defun org-footnote-all-labels (&optional with-defs)
|
|
|
|
"Return list with all defined foot labels used in the buffer.
|
|
|
|
|
|
|
|
If WITH-DEFS is non-nil, also associate the definition to each
|
|
|
|
label. The function will then return an alist whose key is label
|
|
|
|
and value definition."
|
2011-07-03 15:32:41 -04:00
|
|
|
(let* (rtn
|
|
|
|
(push-to-rtn
|
|
|
|
(function
|
|
|
|
;; Depending on WITH-DEFS, store label or (label . def) of
|
|
|
|
;; footnote reference/definition given as argument in RTN.
|
|
|
|
(lambda (el)
|
|
|
|
(let ((lbl (car el)))
|
|
|
|
(push (if with-defs (cons lbl (nth 3 el)) lbl) rtn))))))
|
2008-12-30 17:40:14 -05:00
|
|
|
(save-excursion
|
|
|
|
(save-restriction
|
|
|
|
(widen)
|
2011-04-30 07:23:21 -04:00
|
|
|
;; Find all labels found in definitions.
|
2008-12-30 17:40:14 -05:00
|
|
|
(goto-char (point-min))
|
2011-05-11 12:02:15 -04:00
|
|
|
(let (def)
|
|
|
|
(while (re-search-forward org-footnote-definition-re nil t)
|
|
|
|
(when (setq def (org-footnote-at-definition-p))
|
|
|
|
(funcall push-to-rtn def))))
|
2011-04-30 07:23:21 -04:00
|
|
|
;; Find all labels found in references.
|
2008-12-30 17:40:14 -05:00
|
|
|
(goto-char (point-min))
|
2011-05-11 12:02:15 -04:00
|
|
|
(let (ref)
|
|
|
|
(while (setq ref (org-footnote-get-next-reference))
|
|
|
|
(goto-char (nth 2 ref))
|
|
|
|
(and (car ref) ; ignore anonymous footnotes
|
|
|
|
(not (funcall (if with-defs #'assoc #'member) (car ref) rtn))
|
|
|
|
(funcall push-to-rtn ref))))))
|
2008-12-30 17:40:14 -05:00
|
|
|
rtn))
|
|
|
|
|
2009-01-02 09:53:02 -05:00
|
|
|
(defun org-footnote-unique-label (&optional current)
|
|
|
|
"Return a new unique footnote label.
|
2011-08-23 15:26:51 -04:00
|
|
|
|
2011-08-06 06:07:37 -04:00
|
|
|
The function returns the first \"fn:N\" or \"N\" label that is
|
2011-08-23 15:26:51 -04:00
|
|
|
currently not used.
|
|
|
|
|
|
|
|
Optional argument CURRENT is the list of labels active in the
|
|
|
|
buffer."
|
2009-01-02 09:53:02 -05:00
|
|
|
(unless current (setq current (org-footnote-all-labels)))
|
|
|
|
(let ((fmt (if (eq org-footnote-auto-label 'plain) "%d" "fn:%d"))
|
|
|
|
(cnt 1))
|
|
|
|
(while (member (format fmt cnt) current)
|
|
|
|
(incf cnt))
|
|
|
|
(format fmt cnt)))
|
|
|
|
|
2015-02-15 15:30:29 -05:00
|
|
|
(defun org-footnote--allow-reference-p ()
|
|
|
|
"Non-nil when a footnote reference can be inserted at point."
|
|
|
|
;; XXX: This is similar to `org-footnote-in-valid-context-p' but
|
|
|
|
;; more accurate and usually faster, except in some corner cases.
|
|
|
|
;; It may replace it after doing proper benchmarks as it would be
|
|
|
|
;; used in fontification.
|
|
|
|
(unless (bolp)
|
|
|
|
(let* ((context (org-element-context))
|
|
|
|
(type (org-element-type context)))
|
|
|
|
(cond
|
|
|
|
;; No footnote reference in attributes.
|
|
|
|
((let ((post (org-element-property :post-affiliated context)))
|
|
|
|
(and post (< (point) post)))
|
|
|
|
nil)
|
|
|
|
;; Paragraphs and blank lines at top of document are fine.
|
|
|
|
((memq type '(nil paragraph)))
|
|
|
|
;; So are contents of verse blocks.
|
|
|
|
((eq type 'verse-block)
|
|
|
|
(and (>= (point) (org-element-property :contents-begin context))
|
|
|
|
(< (point) (org-element-property :contents-end context))))
|
2015-04-11 18:25:33 -04:00
|
|
|
;; In an headline or inlinetask, point must be either on the
|
|
|
|
;; heading itself or on the blank lines below.
|
|
|
|
((memq type '(headline inlinetask))
|
|
|
|
(or (not (org-at-heading-p))
|
|
|
|
(and (save-excursion (beginning-of-line)
|
|
|
|
(and (let ((case-fold-search t))
|
|
|
|
(not (looking-at "\\*+ END[ \t]*$")))
|
|
|
|
(looking-at org-complex-heading-regexp)))
|
|
|
|
(match-beginning 4)
|
|
|
|
(>= (point) (match-beginning 4))
|
|
|
|
(or (not (match-beginning 5))
|
|
|
|
(< (point) (match-beginning 5))))))
|
2015-02-15 15:30:29 -05:00
|
|
|
;; White spaces after an object or blank lines after an element
|
|
|
|
;; are OK.
|
|
|
|
((>= (point)
|
|
|
|
(save-excursion (goto-char (org-element-property :end context))
|
|
|
|
(skip-chars-backward " \r\t\n")
|
|
|
|
(if (memq type org-element-all-objects) (point)
|
|
|
|
(1+ (line-beginning-position 2))))))
|
|
|
|
;; Other elements are invalid.
|
|
|
|
((memq type org-element-all-elements) nil)
|
|
|
|
;; Just before object is fine.
|
|
|
|
((= (point) (org-element-property :begin context)))
|
|
|
|
;; Within recursive object too, but not in a link.
|
|
|
|
((eq type 'link) nil)
|
|
|
|
((let ((cbeg (org-element-property :contents-begin context))
|
|
|
|
(cend (org-element-property :contents-end context)))
|
|
|
|
(and cbeg (>= (point) cbeg) (<= (point) cend))))))))
|
|
|
|
|
2008-12-30 17:40:14 -05:00
|
|
|
(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)
|
2015-02-15 15:30:29 -05:00
|
|
|
(unless (org-footnote--allow-reference-p)
|
|
|
|
(user-error "Cannot insert a footnote here"))
|
|
|
|
(let* ((all (org-footnote-all-labels))
|
2014-05-31 05:26:37 -04:00
|
|
|
(label
|
|
|
|
(org-footnote-normalize-label
|
2015-02-15 15:30:29 -05:00
|
|
|
(if (eq org-footnote-auto-label 'random)
|
|
|
|
(format "fn:%x" (random #x100000000))
|
|
|
|
(let ((propose (org-footnote-unique-label all)))
|
|
|
|
(if (memq org-footnote-auto-label '(t plain)) propose
|
|
|
|
(org-icompleting-read
|
|
|
|
"Label (leave empty for anonymous): "
|
|
|
|
(mapcar #'list all) nil nil
|
|
|
|
(and (eq org-footnote-auto-label 'confirm) propose))))))))
|
|
|
|
(cond ((not label)
|
|
|
|
(insert "[fn:: ]")
|
|
|
|
(backward-char 1))
|
|
|
|
((member label all)
|
|
|
|
(insert "[" label "]")
|
|
|
|
(message "New reference to existing note"))
|
|
|
|
(org-footnote-define-inline
|
|
|
|
(insert "[" label ": ]")
|
|
|
|
(backward-char 1)
|
|
|
|
(org-footnote-auto-adjust-maybe))
|
|
|
|
(t
|
|
|
|
(insert "[" label "]")
|
|
|
|
(org-footnote-create-definition label)
|
|
|
|
(org-footnote-auto-adjust-maybe)))))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
2012-02-07 02:43:09 -05:00
|
|
|
(defvar org-blank-before-new-entry) ; silence byte-compiler
|
2008-12-30 17:40:14 -05:00
|
|
|
(defun org-footnote-create-definition (label)
|
|
|
|
"Start the definition of a footnote with label LABEL."
|
|
|
|
(interactive "sLabel: ")
|
2013-01-26 07:40:18 -05:00
|
|
|
(let ((label (org-footnote-normalize-label label))
|
|
|
|
electric-indent-mode) ;; Prevent wrong indentation
|
2008-12-30 17:40:14 -05:00
|
|
|
(cond
|
2011-08-16 14:02:30 -04:00
|
|
|
;; In an Org file.
|
Use (derived-mode-p 'org-mode) instead of (eq major-mode 'org-mode).
* org.el (org-show-hierarchy-above, org-cycle)
(org-global-cycle, org-files-list, org-store-link)
(org-link-search, org-open-file, org-display-outline-path)
(org-refile-get-location, org-update-all-dblocks)
(org-change-tag-in-region, org-entry-properties)
(org-save-all-org-buffers, org-revert-all-org-buffers)
(org-buffer-list, org-cdlatex-mode)
(org-install-agenda-files-menu, org-end-of-subtree)
(org-speedbar-set-agenda-restriction): Use (derived-mode-p
'org-mode) instead of (eq major-mode 'org-mode).
* org-timer.el (org-timer-set-timer): Ditto.
* org-table.el (orgtbl-mode, org-table-align, orgtbl-mode): Ditto.
* org-src.el (org-edit-src-exit, org-edit-src-code)
(org-edit-fixed-width-region, org-edit-src-exit): Ditto.
* org-remember.el (org-remember-handler): Ditto.
* org-mouse.el (dnd-open-file, org-mouse-insert-item): Ditto.
* org-macs.el (org-get-limited-outline-regexp): Ditto.
* org-lparse.el (org-replace-region-by): Ditto.
* org-latex.el (org-latex-to-pdf-process)
(org-replace-region-by-latex): Ditto.
* org-indent.el (org-indent-indent-buffer): Ditto.
* org-id.el (org-id-store-link, org-id-update-id-locations)
(org-id-store-link): Ditto.
* org-html.el (org-export-html-preprocess)
(org-replace-region-by-html): Ditto.
* org-footnote.el (org-footnote-normalize)
(org-footnote-goto-definition)
(org-footnote-create-definition, org-footnote-normalize): Ditto.
* org-docbook.el (org-replace-region-by-docbook): Ditto.
* org-ctags.el (find-tag): Ditto.
* org-colview.el (org-columns-redo)
(org-columns-display-here, org-columns-edit-value)
(org-columns-redo): Ditto.
* org-colview-xemacs.el (org-columns-redo)
(org-columns-display-here, org-columns-edit-value)
(org-columns-redo): Ditto.
* org-capture.el (org-capture-insert-template-here)
(org-capture, org-capture-finalize)
(org-capture-set-target-location)
(org-capture-insert-template-here): Ditto.
* org-ascii.el (org-replace-region-by-ascii): Ditto.
* org-archive.el (org-archive-subtree): Ditto.
* org-agenda.el (org-agenda)
(org-agenda-get-restriction-and-command)
(org-agenda-get-some-entry-text, org-search-view)
(org-tags-view, org-agenda-get-day-entries)
(org-agenda-format-item, org-agenda-goto, org-agenda-kill)
(org-agenda-archive-with, org-agenda-switch-to): Ditto.
2012-04-20 14:03:45 -04:00
|
|
|
((derived-mode-p 'org-mode)
|
2011-08-16 14:02:30 -04:00
|
|
|
;; If `org-footnote-section' is defined, find it, or create it
|
|
|
|
;; at the end of the buffer.
|
2011-05-02 05:37:39 -04:00
|
|
|
(when org-footnote-section
|
2011-03-11 13:49:06 -05:00
|
|
|
(goto-char (point-min))
|
2011-05-02 05:37:39 -04:00
|
|
|
(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)))
|
2011-08-16 14:02:30 -04:00
|
|
|
(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).
|
2009-09-28 14:38:09 -04:00
|
|
|
(org-footnote-goto-local-insertion-point)
|
|
|
|
(org-show-context 'link-search))
|
2008-12-30 17:40:14 -05:00
|
|
|
(t
|
2011-07-25 05:24:57 -04:00
|
|
|
;; In a non-Org file. Search for footnote tag, or create it if
|
2011-08-16 14:02:30 -04:00
|
|
|
;; specified (at the end of buffer, or before signature if in
|
2011-07-25 05:24:57 -04:00
|
|
|
;; Message mode). Set point after any definition already there.
|
2011-08-16 14:02:30 -04:00
|
|
|
(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))))
|
2011-09-28 13:07:38 -04:00
|
|
|
(set-marker-insertion-type max t)
|
2011-07-25 05:24:57 -04:00
|
|
|
(goto-char max)
|
2011-08-16 14:02:30 -04:00
|
|
|
;; 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.
|
2011-09-29 09:20:34 -04:00
|
|
|
(when (and tag (not (re-search-backward tag nil t)))
|
|
|
|
(skip-chars-backward " \t\r\n")
|
|
|
|
(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"))
|
2011-08-16 14:02:30 -04:00
|
|
|
;; Remove superfluous white space and clear marker.
|
2011-09-29 09:20:34 -04:00
|
|
|
(goto-char max)
|
2011-08-16 14:02:30 -04:00
|
|
|
(skip-chars-backward " \t\r\n")
|
|
|
|
(delete-region (point) max)
|
|
|
|
(unless (bolp) (newline))
|
2011-07-25 05:24:57 -04:00
|
|
|
(set-marker max nil))))
|
2011-08-16 14:02:30 -04:00
|
|
|
;; Insert footnote label.
|
2012-02-02 15:02:18 -05:00
|
|
|
(when (zerop (org-back-over-empty-lines)) (newline))
|
|
|
|
(insert "[" label "] \n")
|
|
|
|
(backward-char)
|
2011-08-16 14:02:30 -04:00
|
|
|
;; Only notify user about next possible action when in an Org
|
|
|
|
;; buffer, as the bindings may have different meanings otherwise.
|
Use (derived-mode-p 'org-mode) instead of (eq major-mode 'org-mode).
* org.el (org-show-hierarchy-above, org-cycle)
(org-global-cycle, org-files-list, org-store-link)
(org-link-search, org-open-file, org-display-outline-path)
(org-refile-get-location, org-update-all-dblocks)
(org-change-tag-in-region, org-entry-properties)
(org-save-all-org-buffers, org-revert-all-org-buffers)
(org-buffer-list, org-cdlatex-mode)
(org-install-agenda-files-menu, org-end-of-subtree)
(org-speedbar-set-agenda-restriction): Use (derived-mode-p
'org-mode) instead of (eq major-mode 'org-mode).
* org-timer.el (org-timer-set-timer): Ditto.
* org-table.el (orgtbl-mode, org-table-align, orgtbl-mode): Ditto.
* org-src.el (org-edit-src-exit, org-edit-src-code)
(org-edit-fixed-width-region, org-edit-src-exit): Ditto.
* org-remember.el (org-remember-handler): Ditto.
* org-mouse.el (dnd-open-file, org-mouse-insert-item): Ditto.
* org-macs.el (org-get-limited-outline-regexp): Ditto.
* org-lparse.el (org-replace-region-by): Ditto.
* org-latex.el (org-latex-to-pdf-process)
(org-replace-region-by-latex): Ditto.
* org-indent.el (org-indent-indent-buffer): Ditto.
* org-id.el (org-id-store-link, org-id-update-id-locations)
(org-id-store-link): Ditto.
* org-html.el (org-export-html-preprocess)
(org-replace-region-by-html): Ditto.
* org-footnote.el (org-footnote-normalize)
(org-footnote-goto-definition)
(org-footnote-create-definition, org-footnote-normalize): Ditto.
* org-docbook.el (org-replace-region-by-docbook): Ditto.
* org-ctags.el (find-tag): Ditto.
* org-colview.el (org-columns-redo)
(org-columns-display-here, org-columns-edit-value)
(org-columns-redo): Ditto.
* org-colview-xemacs.el (org-columns-redo)
(org-columns-display-here, org-columns-edit-value)
(org-columns-redo): Ditto.
* org-capture.el (org-capture-insert-template-here)
(org-capture, org-capture-finalize)
(org-capture-set-target-location)
(org-capture-insert-template-here): Ditto.
* org-ascii.el (org-replace-region-by-ascii): Ditto.
* org-archive.el (org-archive-subtree): Ditto.
* org-agenda.el (org-agenda)
(org-agenda-get-restriction-and-command)
(org-agenda-get-some-entry-text, org-search-view)
(org-tags-view, org-agenda-get-day-entries)
(org-agenda-format-item, org-agenda-goto, org-agenda-kill)
(org-agenda-archive-with, org-agenda-switch-to): Ditto.
2012-04-20 14:03:45 -04:00
|
|
|
(when (derived-mode-p 'org-mode)
|
2011-08-16 14:02:30 -04:00
|
|
|
(message
|
|
|
|
"Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'."))))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun org-footnote-action (&optional special)
|
|
|
|
"Do the right thing for footnotes.
|
2011-06-29 09:26:22 -04:00
|
|
|
|
|
|
|
When at a footnote reference, jump to the definition.
|
|
|
|
|
|
|
|
When at a definition, jump to the references if they exist, offer
|
|
|
|
to create them otherwise.
|
|
|
|
|
|
|
|
When neither at definition or reference, create a new footnote,
|
2014-06-01 02:42:09 -04:00
|
|
|
interactively if possible.
|
2011-06-29 09:26:22 -04:00
|
|
|
|
2014-06-01 02:42:09 -04:00
|
|
|
With prefix arg SPECIAL, or when no footnote can be created,
|
|
|
|
offer additional commands in a menu."
|
2008-12-30 17:40:14 -05:00
|
|
|
(interactive "P")
|
2014-06-01 02:42:09 -04:00
|
|
|
(let* ((context (and (not special) (org-element-context)))
|
|
|
|
(type (org-element-type context)))
|
2008-12-30 17:40:14 -05:00
|
|
|
(cond
|
2014-06-01 02:42:09 -04:00
|
|
|
((eq type 'footnote-reference)
|
|
|
|
(let ((label (org-element-property :label context)))
|
|
|
|
(cond
|
|
|
|
;; Anonymous footnote: move point at the beginning of its
|
|
|
|
;; definition.
|
|
|
|
((not label)
|
|
|
|
(goto-char (org-element-property :contents-begin context)))
|
|
|
|
;; A definition exists: move to it.
|
|
|
|
((ignore-errors (org-footnote-goto-definition label)))
|
|
|
|
;; No definition exists: offer to create it.
|
|
|
|
((yes-or-no-p (format "No definition for %s. Create one? " label))
|
|
|
|
(org-footnote-create-definition label)))))
|
|
|
|
((eq type 'footnote-definition)
|
|
|
|
(org-footnote-goto-previous-reference
|
|
|
|
(org-element-property :label context)))
|
|
|
|
((or special
|
|
|
|
(zerop (current-column))
|
|
|
|
(not (org-footnote-in-valid-context-p)))
|
2014-05-31 05:26:37 -04:00
|
|
|
(message "Footnotes: [s]ort | [r]enumber fn:N | [S]=r+s |->[n]umeric | [d]elete")
|
2014-06-01 02:42:09 -04:00
|
|
|
(let ((c (read-char-exclusive)))
|
|
|
|
(cond
|
|
|
|
((eq c ?s) (org-footnote-normalize 'sort))
|
|
|
|
((eq c ?r) (org-footnote-renumber-fn:N))
|
|
|
|
((eq c ?S)
|
|
|
|
(org-footnote-renumber-fn:N)
|
|
|
|
(org-footnote-normalize 'sort))
|
|
|
|
((eq c ?n) (org-footnote-normalize))
|
|
|
|
((eq c ?d) (org-footnote-delete))
|
|
|
|
(t (error "No such footnote command %c" c)))))
|
2008-12-30 17:40:14 -05:00
|
|
|
(t (org-footnote-new)))))
|
|
|
|
|
|
|
|
;;;###autoload
|
2013-01-27 18:02:51 -05:00
|
|
|
(defun org-footnote-normalize (&optional sort-only)
|
2008-12-30 17:40:14 -05:00
|
|
|
"Collect the footnotes in various formats and normalize them.
|
2011-04-30 07:23:21 -04:00
|
|
|
|
2009-07-03 11:56:47 -04:00
|
|
|
This finds the different sorts of footnotes allowed in Org, and
|
2013-01-27 18:02:51 -05:00
|
|
|
normalizes them to the usual [N] format.
|
2011-04-30 07:23:21 -04:00
|
|
|
|
2008-12-30 17:40:14 -05:00
|
|
|
When SORT-ONLY is set, only sort the footnote definitions into the
|
2013-01-27 18:02:51 -05:00
|
|
|
referenced sequence."
|
2008-12-30 17:40:14 -05:00
|
|
|
;; This is based on Paul's function, but rewritten.
|
2011-04-30 07:23:21 -04:00
|
|
|
;;
|
|
|
|
;; Re-create `org-with-limited-levels', but not limited to Org
|
|
|
|
;; buffers.
|
2009-06-21 02:29:35 -04:00
|
|
|
(let* ((limit-level
|
|
|
|
(and (boundp 'org-inlinetask-min-level)
|
|
|
|
org-inlinetask-min-level
|
|
|
|
(1- org-inlinetask-min-level)))
|
|
|
|
(nstars (and limit-level
|
2013-01-27 18:02:51 -05:00
|
|
|
(if org-odd-levels-only (1- (* limit-level 2))
|
2009-06-21 02:29:35 -04:00
|
|
|
limit-level)))
|
Don't use `outline-regexp' anymore.
Use `org-outline-regexp' instead or `outline-regexp'. Also use the
new defconst `org-outline-regexp-bol' to match `org-outline-regexp'
at the beginning of line.
* org.el (org-outline-regexp-bol): New defconst.
(org-outline-level, org-set-font-lock-defaults, org-cycle)
(org-overview, org-content, org-flag-drawer)
(org-first-headline-recenter, org-insert-todo-heading)
(org-map-region, org-move-subtree-down, org-paste-subtree)
(org-kill-is-subtree-p, org-context-p, org-refile)
(org-refile-new-child, org-toggle-comment, org-todo)
(org-add-planning-info, org-add-log-setup, org-scan-tags)
(org-set-tags, org-insert-property-drawer)
(org-prepare-agenda-buffers, org-preview-latex-fragment)
(org-speed-command-default-hook, org-check-for-hidden)
(org-toggle-item, org-toggle-heading)
(org-indent-line-function, org-set-autofill-regexps)
(org-fill-paragraph, org-toggle-fixed-width-section)
(org-yank-generic, org-yank-folding-would-swallow-text)
(org-first-sibling-p, org-goto-sibling)
(org-goto-first-child, org-show-entry): Use
`org-outline-regexp' and `org-outline-regexp-bol'.
* org-remember.el (org-remember-handler): Use
`org-outline-regexp-bol'.
* org-mouse.el (org-mouse-match-todo-keyword, org-mode-hook)
(org-mouse-move-tree, org-mouse-transform-to-outline): Use
`org-outline-regexp' and `org-outline-regexp-bol'.
* org-macs.el (org-with-limited-levels)
(org-get-limited-outline-regexp): Use `org-outline-regexp'.
* org-indent.el (org-indent-outline-re)
(org-indent-refresh-section, org-indent-refresh-to): Use
`org-outline-regexp' and `org-outline-regexp-bol'.
* org-html.el (org-export-as-html): Use
`org-outline-regexp-bol'.
* org-footnote.el (org-footnote-at-definition-p)
(org-footnote-normalize): Use `org-outline-regexp' and
`org-outline-regexp-bol'.
* org-exp.el (org-export-preprocess-string): Don't redefine
`outline-regexp'.
* org-docbook.el (org-export-as-docbook): Use
`org-outline-regexp-bol'.
* org-colview.el (org-columns, org-columns-compute): Use
`org-outline-regexp' and `org-outline-regexp-bol'.
* org-colview-xemacs.el (org-columns, org-columns-compute):
Use `org-outline-regexp-bol'.
* org-clock.el (org-clock-insert-selection-line)
(org-clock-in, org-clock-out, org-dblock-write:clocktable):
Use `org-outline-regexp' and `org-outline-regexp-bol'.
* org-ascii.el (org-export-as-ascii)
(org-export-ascii-push-links): Use `org-outline-regexp' and
`org-outline-regexp-bol'.
* org-archive.el (org-archive-to-archive-sibling)
(org-archive-all-done): Use `org-outline-regexp' and
`org-outline-regexp-bol'.
* org-agenda.el (org-agenda, org-search-view)
(org-agenda-list-stuck-projects, org-agenda-get-timestamps)
(org-agenda-get-progress, org-agenda-get-blocks): Use
`org-outline-regexp' and `org-outline-regexp-bol'.
2011-07-17 15:17:08 -04:00
|
|
|
(org-outline-regexp
|
2009-06-21 02:29:35 -04:00
|
|
|
(concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ ")))
|
2013-01-27 18:02:51 -05:00
|
|
|
(count 0)
|
|
|
|
ins-point ref ref-table)
|
2011-04-30 07:23:21 -04:00
|
|
|
(save-excursion
|
|
|
|
;; 1. Find every footnote reference, extract the definition, and
|
2011-07-16 04:45:40 -04:00
|
|
|
;; collect that data in REF-TABLE. If SORT-ONLY is nil, also
|
2011-04-30 07:23:21 -04:00
|
|
|
;; normalize references.
|
2008-12-30 17:40:14 -05:00
|
|
|
(goto-char (point-min))
|
2011-04-30 07:23:21 -04:00
|
|
|
(while (setq ref (org-footnote-get-next-reference))
|
|
|
|
(let* ((lbl (car ref))
|
2012-02-02 04:01:50 -05:00
|
|
|
(pos (nth 1 ref))
|
2011-04-30 07:23:21 -04:00
|
|
|
;; When footnote isn't anonymous, check if it's label
|
2011-07-16 04:45:40 -04:00
|
|
|
;; (REF) is already stored in REF-TABLE. In that case,
|
|
|
|
;; extract number used to identify it (MARKER). If
|
2011-04-30 07:23:21 -04:00
|
|
|
;; footnote is unknown, increment the global counter
|
|
|
|
;; (COUNT) to create an unused identifier.
|
|
|
|
(a (and lbl (assoc lbl ref-table)))
|
|
|
|
(marker (or (nth 1 a) (incf count)))
|
|
|
|
;; Is the reference inline or pointing to an inline
|
|
|
|
;; footnote?
|
|
|
|
(inlinep (or (stringp (nth 3 ref)) (nth 3 a))))
|
2011-07-16 04:45:40 -04:00
|
|
|
;; Replace footnote reference with [MARKER]. Maybe fill
|
|
|
|
;; paragraph once done. If SORT-ONLY is non-nil, only move
|
2011-04-30 07:23:21 -04:00
|
|
|
;; to the end of reference found to avoid matching it twice.
|
2012-03-02 16:37:12 -05:00
|
|
|
(if sort-only (goto-char (nth 2 ref))
|
2011-04-30 07:23:21 -04:00
|
|
|
(delete-region (nth 1 ref) (nth 2 ref))
|
|
|
|
(goto-char (nth 1 ref))
|
2013-01-27 18:02:51 -05:00
|
|
|
(insert (format "[%d]" marker))
|
2011-04-30 07:23:21 -04:00
|
|
|
(and inlinep
|
|
|
|
org-footnote-fill-after-inline-note-extraction
|
|
|
|
(org-fill-paragraph)))
|
2011-08-18 12:58:48 -04:00
|
|
|
;; Add label (REF), identifier (MARKER), definition (DEF)
|
2012-02-02 04:01:50 -05:00
|
|
|
;; type (INLINEP) and position (POS) to REF-TABLE if data
|
|
|
|
;; was unknown.
|
2011-04-30 07:23:21 -04:00
|
|
|
(unless a
|
2013-01-27 18:02:51 -05:00
|
|
|
(let ((def (or (nth 3 ref) ; Inline definition.
|
2011-04-30 07:23:21 -04:00
|
|
|
(nth 3 (org-footnote-get-definition lbl)))))
|
2013-01-27 18:02:51 -05:00
|
|
|
(push (list lbl marker def
|
2012-03-02 16:37:12 -05:00
|
|
|
;; Reference beginning position is a marker
|
|
|
|
;; to preserve it during further buffer
|
|
|
|
;; modifications.
|
|
|
|
inlinep (copy-marker pos)) ref-table)))))
|
2011-07-16 04:43:46 -04:00
|
|
|
;; 2. Find and remove the footnote section, if any. Also
|
|
|
|
;; determine where footnotes shall be inserted (INS-POINT).
|
2008-12-30 17:40:14 -05:00
|
|
|
(cond
|
Use (derived-mode-p 'org-mode) instead of (eq major-mode 'org-mode).
* org.el (org-show-hierarchy-above, org-cycle)
(org-global-cycle, org-files-list, org-store-link)
(org-link-search, org-open-file, org-display-outline-path)
(org-refile-get-location, org-update-all-dblocks)
(org-change-tag-in-region, org-entry-properties)
(org-save-all-org-buffers, org-revert-all-org-buffers)
(org-buffer-list, org-cdlatex-mode)
(org-install-agenda-files-menu, org-end-of-subtree)
(org-speedbar-set-agenda-restriction): Use (derived-mode-p
'org-mode) instead of (eq major-mode 'org-mode).
* org-timer.el (org-timer-set-timer): Ditto.
* org-table.el (orgtbl-mode, org-table-align, orgtbl-mode): Ditto.
* org-src.el (org-edit-src-exit, org-edit-src-code)
(org-edit-fixed-width-region, org-edit-src-exit): Ditto.
* org-remember.el (org-remember-handler): Ditto.
* org-mouse.el (dnd-open-file, org-mouse-insert-item): Ditto.
* org-macs.el (org-get-limited-outline-regexp): Ditto.
* org-lparse.el (org-replace-region-by): Ditto.
* org-latex.el (org-latex-to-pdf-process)
(org-replace-region-by-latex): Ditto.
* org-indent.el (org-indent-indent-buffer): Ditto.
* org-id.el (org-id-store-link, org-id-update-id-locations)
(org-id-store-link): Ditto.
* org-html.el (org-export-html-preprocess)
(org-replace-region-by-html): Ditto.
* org-footnote.el (org-footnote-normalize)
(org-footnote-goto-definition)
(org-footnote-create-definition, org-footnote-normalize): Ditto.
* org-docbook.el (org-replace-region-by-docbook): Ditto.
* org-ctags.el (find-tag): Ditto.
* org-colview.el (org-columns-redo)
(org-columns-display-here, org-columns-edit-value)
(org-columns-redo): Ditto.
* org-colview-xemacs.el (org-columns-redo)
(org-columns-display-here, org-columns-edit-value)
(org-columns-redo): Ditto.
* org-capture.el (org-capture-insert-template-here)
(org-capture, org-capture-finalize)
(org-capture-set-target-location)
(org-capture-insert-template-here): Ditto.
* org-ascii.el (org-replace-region-by-ascii): Ditto.
* org-archive.el (org-archive-subtree): Ditto.
* org-agenda.el (org-agenda)
(org-agenda-get-restriction-and-command)
(org-agenda-get-some-entry-text, org-search-view)
(org-tags-view, org-agenda-get-day-entries)
(org-agenda-format-item, org-agenda-goto, org-agenda-kill)
(org-agenda-archive-with, org-agenda-switch-to): Ditto.
2012-04-20 14:03:45 -04:00
|
|
|
((and org-footnote-section (derived-mode-p 'org-mode))
|
2012-02-02 04:01:50 -05:00
|
|
|
(goto-char (point-min))
|
|
|
|
(if (re-search-forward
|
2012-04-20 05:12:44 -04:00
|
|
|
(concat "^\\*[ \t]+" (regexp-quote org-footnote-section)
|
|
|
|
"[ \t]*$") nil t)
|
2012-02-02 15:02:18 -05:00
|
|
|
(delete-region (match-beginning 0) (org-end-of-subtree t t)))
|
2012-02-02 04:01:50 -05:00
|
|
|
;; A new footnote section is inserted by default at the end of
|
|
|
|
;; the buffer.
|
2011-08-18 12:58:48 -04:00
|
|
|
(goto-char (point-max))
|
2012-02-02 15:02:18 -05:00
|
|
|
(skip-chars-backward " \r\t\n")
|
|
|
|
(forward-line)
|
2011-08-18 12:58:48 -04:00
|
|
|
(unless (bolp) (newline)))
|
2012-03-02 16:37:12 -05:00
|
|
|
;; No footnote section set: Footnotes will be added at the end
|
|
|
|
;; of the section containing their first reference.
|
2013-01-27 18:02:51 -05:00
|
|
|
((derived-mode-p 'org-mode))
|
2008-12-30 17:40:14 -05:00
|
|
|
(t
|
2011-08-16 15:43:23 -04:00
|
|
|
;; 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]*$")))
|
2012-02-02 04:01:50 -05:00
|
|
|
(goto-char (point-min))
|
2011-08-16 15:43:23 -04:00
|
|
|
(while (re-search-forward tag nil t)
|
|
|
|
(replace-match "")
|
|
|
|
(delete-region (point) (progn (forward-line) (point))))))
|
2011-08-16 14:02:30 -04:00
|
|
|
;; In Message mode, ensure footnotes are inserted before the
|
2011-07-15 13:24:59 -04:00
|
|
|
;; signature.
|
2011-08-18 12:58:48 -04:00
|
|
|
(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)))))
|
2013-01-27 18:02:51 -05:00
|
|
|
(setq ins-point (point-marker))
|
2011-04-30 07:23:21 -04:00
|
|
|
;; 3. Clean-up REF-TABLE.
|
2009-01-03 03:03:04 -05:00
|
|
|
(setq ref-table
|
2011-04-30 07:23:21 -04:00
|
|
|
(delq nil
|
|
|
|
(mapcar
|
2009-01-03 03:03:04 -05:00
|
|
|
(lambda (x)
|
2011-04-30 07:23:21 -04:00
|
|
|
(cond
|
|
|
|
;; When only sorting, ignore inline footnotes.
|
2012-03-02 16:37:12 -05:00
|
|
|
;; Also clear position marker.
|
|
|
|
((and sort-only (nth 3 x))
|
|
|
|
(set-marker (nth 4 x) nil) nil)
|
2011-04-30 07:23:21 -04:00
|
|
|
;; No definition available: provide one.
|
|
|
|
((not (nth 2 x))
|
2012-03-02 16:37:12 -05:00
|
|
|
(append
|
|
|
|
(list (car x) (nth 1 x)
|
|
|
|
(format "DEFINITION NOT FOUND: %s" (car x)))
|
|
|
|
(nthcdr 3 x)))
|
2011-04-30 07:23:21 -04:00
|
|
|
(t x)))
|
|
|
|
ref-table)))
|
|
|
|
(setq ref-table (nreverse ref-table))
|
2011-08-18 12:58:48 -04:00
|
|
|
;; 4. Remove left-over definitions in the buffer.
|
2012-03-02 16:37:12 -05:00
|
|
|
(mapc (lambda (x)
|
|
|
|
(unless (nth 3 x) (org-footnote-delete-definitions (car x))))
|
2011-08-18 12:58:48 -04:00
|
|
|
ref-table)
|
|
|
|
;; 5. Insert the footnotes again in the buffer, at the
|
2011-06-26 04:46:15 -04:00
|
|
|
;; appropriate spot.
|
2011-08-18 12:58:48 -04:00
|
|
|
(goto-char ins-point)
|
2011-04-30 07:23:21 -04:00
|
|
|
(cond
|
2011-07-16 04:43:46 -04:00
|
|
|
;; No footnote: exit.
|
|
|
|
((not ref-table))
|
|
|
|
;; Cases when footnotes should be inserted in one place.
|
2013-01-27 18:02:51 -05:00
|
|
|
((or (not (derived-mode-p 'org-mode)) org-footnote-section)
|
2011-08-16 14:02:30 -04:00
|
|
|
;; 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'.
|
2013-01-27 18:02:51 -05:00
|
|
|
(if (not (derived-mode-p 'org-mode))
|
|
|
|
(progn (skip-chars-backward " \t\n\r")
|
|
|
|
(delete-region (point) ins-point)
|
|
|
|
(unless (bolp) (newline))
|
|
|
|
(when org-footnote-tag-for-non-org-mode-files
|
|
|
|
(insert "\n" org-footnote-tag-for-non-org-mode-files "\n")))
|
2011-08-16 14:02:30 -04:00
|
|
|
(when (and (cdr (assq 'heading org-blank-before-new-entry))
|
|
|
|
(zerop (save-excursion (org-back-over-empty-lines))))
|
|
|
|
(insert "\n"))
|
2013-01-27 18:02:51 -05:00
|
|
|
(insert "* " org-footnote-section "\n"))
|
2011-08-18 12:58:48 -04:00
|
|
|
(set-marker ins-point nil)
|
2011-08-16 14:02:30 -04:00
|
|
|
;; Insert the footnotes, separated by a blank line.
|
2012-02-02 04:01:50 -05:00
|
|
|
(insert
|
|
|
|
(mapconcat
|
|
|
|
(lambda (x)
|
2012-03-02 16:37:12 -05:00
|
|
|
;; Clean markers.
|
|
|
|
(set-marker (nth 4 x) nil)
|
2012-02-02 04:01:50 -05:00
|
|
|
(format "\n[%s] %s" (nth (if sort-only 0 1) x) (nth 2 x)))
|
|
|
|
ref-table "\n"))
|
2013-01-27 18:02:51 -05:00
|
|
|
(unless (eobp) (insert "\n\n")))
|
2012-02-02 04:01:50 -05:00
|
|
|
;; Each footnote definition has to be inserted at the end of
|
|
|
|
;; the section where its first reference belongs.
|
2012-03-03 07:00:46 -05:00
|
|
|
(t
|
2012-02-02 04:01:50 -05:00
|
|
|
(mapc
|
|
|
|
(lambda (x)
|
2012-03-02 16:37:12 -05:00
|
|
|
(let ((pos (nth 4 x)))
|
|
|
|
(goto-char pos)
|
|
|
|
;; Clean marker.
|
|
|
|
(set-marker pos nil))
|
2012-02-02 04:01:50 -05:00
|
|
|
(org-footnote-goto-local-insertion-point)
|
2012-03-03 07:07:59 -05:00
|
|
|
(insert (format "\n[%s] %s\n"
|
|
|
|
(if sort-only (car x) (nth 1 x))
|
|
|
|
(nth 2 x))))
|
2012-03-03 07:00:46 -05:00
|
|
|
ref-table))))))
|
2009-01-03 03:03:04 -05:00
|
|
|
|
|
|
|
(defun org-footnote-goto-local-insertion-point ()
|
|
|
|
"Find insertion point for footnote, just before next outline heading."
|
2009-07-19 03:42:22 -04:00
|
|
|
(org-with-limited-levels (outline-next-heading))
|
2009-01-05 07:15:12 -05:00
|
|
|
(or (bolp) (newline))
|
2009-01-03 03:03:04 -05:00
|
|
|
(beginning-of-line 0)
|
|
|
|
(while (and (not (bobp)) (= (char-after) ?#))
|
|
|
|
(beginning-of-line 0))
|
2012-04-21 09:36:04 -04:00
|
|
|
(if (let ((case-fold-search t)) (looking-at "[ \t]*#\\+tblfm:")) (beginning-of-line 2))
|
2009-01-03 18:28:42 -05:00
|
|
|
(end-of-line 1)
|
2010-10-22 05:53:19 -04:00
|
|
|
(skip-chars-backward "\n\r\t ")
|
|
|
|
(forward-line))
|
2008-12-30 17:40:14 -05:00
|
|
|
|
2011-04-30 07:23:21 -04:00
|
|
|
(defun org-footnote-delete-references (label)
|
|
|
|
"Delete every reference to footnote LABEL.
|
|
|
|
Return the number of footnotes removed."
|
|
|
|
(save-excursion
|
|
|
|
(goto-char (point-min))
|
|
|
|
(let (ref (nref 0))
|
|
|
|
(while (setq ref (org-footnote-get-next-reference label))
|
|
|
|
(goto-char (nth 1 ref))
|
|
|
|
(delete-region (nth 1 ref) (nth 2 ref))
|
|
|
|
(incf nref))
|
|
|
|
nref)))
|
|
|
|
|
|
|
|
(defun org-footnote-delete-definitions (label)
|
|
|
|
"Delete every definition of the footnote LABEL.
|
|
|
|
Return the number of footnotes removed."
|
|
|
|
(save-excursion
|
|
|
|
(goto-char (point-min))
|
|
|
|
(let ((def-re (concat "^\\[" (regexp-quote label) "\\]"))
|
|
|
|
(ndef 0))
|
|
|
|
(while (re-search-forward def-re nil t)
|
|
|
|
(let ((full-def (org-footnote-at-definition-p)))
|
2012-03-24 15:34:41 -04:00
|
|
|
(when full-def
|
2012-04-08 06:01:57 -04:00
|
|
|
;; Remove the footnote, and all blank lines before it.
|
|
|
|
(goto-char (nth 1 full-def))
|
|
|
|
(skip-chars-backward " \r\t\n")
|
|
|
|
(unless (bolp) (forward-line))
|
|
|
|
(delete-region (point) (nth 2 full-def))
|
2012-03-24 15:34:41 -04:00
|
|
|
(incf ndef))))
|
2011-04-30 07:23:21 -04:00
|
|
|
ndef)))
|
|
|
|
|
2008-12-30 17:40:14 -05:00
|
|
|
(defun org-footnote-delete (&optional label)
|
|
|
|
"Delete the footnote at point.
|
|
|
|
This will remove the definition (even multiple definitions if they exist)
|
2011-04-29 09:46:25 -04:00
|
|
|
and all references of a footnote label.
|
|
|
|
|
|
|
|
If LABEL is non-nil, delete that footnote instead."
|
2008-12-30 17:40:14 -05:00
|
|
|
(catch 'done
|
2011-04-29 09:46:25 -04:00
|
|
|
(let* ((nref 0) (ndef 0) x
|
|
|
|
;; 1. Determine LABEL of footnote at point.
|
|
|
|
(label (cond
|
|
|
|
;; LABEL is provided as argument.
|
|
|
|
(label)
|
2012-08-11 13:10:44 -04:00
|
|
|
;; Footnote reference at point. If the footnote is
|
2011-04-29 09:46:25 -04:00
|
|
|
;; anonymous, delete it and exit instead.
|
|
|
|
((setq x (org-footnote-at-reference-p))
|
|
|
|
(or (car x)
|
|
|
|
(progn
|
|
|
|
(delete-region (nth 1 x) (nth 2 x))
|
|
|
|
(message "Anonymous footnote removed")
|
|
|
|
(throw 'done t))))
|
|
|
|
;; Footnote definition at point.
|
|
|
|
((setq x (org-footnote-at-definition-p))
|
|
|
|
(car x))
|
|
|
|
(t (error "Don't know which footnote to remove")))))
|
2011-04-30 07:23:21 -04:00
|
|
|
;; 2. Now that LABEL is non-nil, find every reference and every
|
|
|
|
;; definition, and delete them.
|
|
|
|
(setq nref (org-footnote-delete-references label)
|
|
|
|
ndef (org-footnote-delete-definitions label))
|
|
|
|
;; 3. Verify consistency of footnotes and notify user.
|
2009-07-03 11:56:47 -04:00
|
|
|
(org-footnote-auto-adjust-maybe)
|
2008-12-30 17:40:14 -05:00
|
|
|
(message "%d definition(s) of and %d reference(s) of footnote %s removed"
|
|
|
|
ndef nref label))))
|
|
|
|
|
2009-07-01 04:37:03 -04:00
|
|
|
(defun org-footnote-renumber-fn:N ()
|
|
|
|
"Renumber the simple footnotes like fn:17 into a sequence in the document."
|
|
|
|
(interactive)
|
2011-09-29 16:34:15 -04:00
|
|
|
(let (map (n 0))
|
|
|
|
(org-with-wide-buffer
|
|
|
|
(goto-char (point-min))
|
|
|
|
(while (re-search-forward "\\[fn:\\([0-9]+\\)[]:]" nil t)
|
2011-09-29 16:53:45 -04:00
|
|
|
(save-excursion
|
|
|
|
(goto-char (match-beginning 0))
|
|
|
|
;; Ensure match is a footnote reference or definition.
|
2011-10-01 02:57:33 -04:00
|
|
|
(when (save-match-data (if (bolp)
|
|
|
|
(org-footnote-at-definition-p)
|
|
|
|
(org-footnote-at-reference-p)))
|
2011-09-29 16:53:45 -04:00
|
|
|
(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))))))))
|
2009-07-01 04:37:03 -04:00
|
|
|
|
2009-07-03 11:56:47 -04:00
|
|
|
(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))
|
2011-04-29 09:46:25 -04:00
|
|
|
(let ((label (car (org-footnote-at-definition-p))))
|
2009-07-03 11:56:47 -04:00
|
|
|
(org-footnote-normalize 'sort)
|
|
|
|
(when label
|
|
|
|
(goto-char (point-min))
|
|
|
|
(and (re-search-forward (concat "^\\[" (regexp-quote label) "\\]")
|
|
|
|
nil t)
|
2009-08-03 11:30:30 -04:00
|
|
|
(progn (insert " ")
|
2009-07-03 11:56:47 -04:00
|
|
|
(just-one-space)))))))
|
|
|
|
|
2008-12-30 17:40:14 -05:00
|
|
|
(provide 'org-footnote)
|
|
|
|
|
2012-10-02 02:50:46 -04:00
|
|
|
;; Local variables:
|
|
|
|
;; generated-autoload-file: "org-loaddefs.el"
|
|
|
|
;; End:
|
|
|
|
|
2009-01-03 03:03:04 -05:00
|
|
|
;;; org-footnote.el ends here
|