diff options
author | Nicolas Goaziou <mail@nicolasgoaziou.fr> | 2016-03-07 23:43:23 +0100 |
---|---|---|
committer | Nicolas Goaziou <mail@nicolasgoaziou.fr> | 2016-03-12 23:18:55 +0100 |
commit | 32c3f33d00b3dc9affa44b4af432dc349d41e444 (patch) | |
tree | 48211b6185257395fa9a1528dfd77e978ef13c2b | |
parent | 6ec06dcff98e2db9811d1d1e9da01399e9cc1fe3 (diff) | |
download | org-mode-32c3f33d00b3dc9affa44b4af432dc349d41e444.tar.gz |
ox: Use a new scheme for internal references
* lisp/ox.el (org-export-get-reference): Use randomly generated labels.
(org-export-new-reference):
(org-export-format-reference): New functions.
* testing/lisp/test-ox.el (test-org-export/get-reference): New test.
The new scheme is better when datum type cannot be known ahead of time
or when references are not created sequentially, e.g., during
a publishing process where a reference to a file can be require before
the file is published.
-rw-r--r-- | lisp/ox.el | 58 | ||||
-rw-r--r-- | testing/lisp/test-ox.el | 22 |
2 files changed, 64 insertions, 16 deletions
@@ -4315,29 +4315,55 @@ has type \"radio\"." ;;;; For References ;; ;; `org-export-get-reference' associate a unique reference for any -;; object or element. +;; object or element. It uses `org-export-new-reference' and +;; `org-export-format-reference' to, respectively, generate new +;; internal references and turn them into a string suitable for +;; output. ;; ;; `org-export-get-ordinal' associates a sequence number to any object ;; or element. +(defun org-export-new-reference (references) + "Return a unique reference, among REFERENCES. +REFERENCES is an alist whose values are in-use references, as +numbers. Returns a number, which is the internal representation +of a reference. See also `org-export-format-reference'." + ;; Generate random 7 digits hexadecimal numbers. Collisions + ;; increase exponentially with the numbers of references. However, + ;; the odds for encountering at least one collision with 1000 active + ;; references in the same document are roughly 0.2%, so this + ;; shouldn't be the bottleneck. + (let ((new (random #x10000000))) + (while (rassq new references) (setq new (random #x10000000))) + new)) + +(defun org-export-format-reference (reference) + "Format REFERENCE into a string. +REFERENCE is a number representing a reference, as returned by +`org-export-new-reference', which see." + (format "org%x" reference)) + (defun org-export-get-reference (datum info) "Return a unique reference for DATUM, as a string. + DATUM is either an element or an object. INFO is the current -export state, as a plist. Returned reference consists of -alphanumeric characters only." - (let ((type (org-element-type datum)) - (cache (or (plist-get info :internal-references) - (let ((h (make-hash-table :test #'eq))) - (plist-put info :internal-references h) - h)))) - (or (gethash datum cache) - (puthash datum - (format "org%s%d" - (if type - (replace-regexp-in-string "-" "" (symbol-name type)) - "secondarystring") - (cl-incf (gethash type cache 0))) - cache)))) +export state, as a plist. + +This functions checks `:crossrefs' property in INFO for search +cells matching DATUM before creating a new reference. Returned +reference consists of alphanumeric characters only." + (let ((cache (plist-get info :internal-references))) + (or (car (rassq datum cache)) + (let* ((new (org-export-new-reference cache)) + (search-cells (org-export-search-cells datum)) + (reference-string (org-export-format-reference new))) + ;; Cache contains both data already associated to + ;; a reference and in-use internal references, so as to make + ;; unique references. + (push (cons search-cells new) cache) + (push (cons reference-string datum) cache) + (plist-put info :internal-references cache) + reference-string)))) (defun org-export-get-ordinal (element info &optional types predicate) "Return ordinal number of an element or object. diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 0b89d42..f51288f 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -2873,6 +2873,28 @@ Another text. (ref:text) (should (equal (org-export-file-uri "~/file.org") (concat "file://" (expand-file-name "~/file.org"))))) +(ert-deftest test-org-export/get-reference () + "Test `org-export-get-reference' specifications." + (should + (org-test-with-parsed-data "* Headline" + (org-export-get-reference (org-element-map tree 'headline #'identity nil t) + info))) + ;; For a given element always return the same reference. + (should + (org-test-with-parsed-data "* Headline" + (let ((headline (org-element-map tree 'headline #'identity nil t))) + (equal (org-export-get-reference headline info) + (org-export-get-reference headline info))))) + ;; Use search cells defined in `:crossrefs'. + (should + (equal "org1" + (org-test-with-parsed-data "* Headline" + (let* ((headline (org-element-map tree 'headline #'identity nil t)) + (search-cell (car (org-export-search-cells headline)))) + (setq info + (plist-put info :crossrefs (list (cons search-cell 1)))) + (org-export-get-reference headline info)))))) + ;;; Src-block and example-block |