emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [O] [dev] Implement "ref" link types


From: Nicolas Goaziou
Subject: Re: [O] [dev] Implement "ref" link types
Date: Mon, 20 Feb 2012 23:06:32 +0100

Completing myself, here is a patch implementing the previous suggestion,
along with example output obtained with it.  You may need to
(fmakunbound 'org-e-ascii-target) to avoid an error, since this patch
removes the function.


First, the test buffer.


#+begin_src org
#+TITLE: Cross-references
#+LANGUAGE: en

* First headline.

  Here we demonstrate cross-references to items.

  1. A first item in a list.
  2. Another item
     1. With three subparts. This one.
     2. Another one.
     3. <<itm:last>> And the last subpart.
        
  We end the list at item [[itm:last]].

  Before we continue, here is a rather trivial equation, assuming base
  isn't too low[fn:1].
  
  #+name: eq:trivial
  \begin{equation}
  1 + 1 = 2
  \end{equation}

  We can verify it with the following code:

  #+name: oneplusone
  #+caption: Shortly after the beginning of arithmetic.
  #+BEGIN_SRC emacs-lisp :exports code
  (+ 1 1)
  #+END_SRC

** Sub-topic

   Here we demonstrate cross-references to tables.<<sec:tables>>

   #+name: tab:numbers
   #+caption: Test
   | one | 1 |
   | two | 2 |

   #+name: tab:letters
   #+caption: Letters
   | a | aille |
   | b | bi    |

   In table [[tab:numbers]] we can only see two numbers.  Yet, in 
[[tab:numbers][the very
   same table]], we can already tell the radix used isn't too low
   (remember footnote [[fn:basetwo]]?).  On the other hand, table
   [[tab:letters]] shows letters, but that's clearly uninteresting.

   #+name: eq:euler
   \begin{equation}
   e^{i\pi} + 1 = 0
   \end{equation}

   Equation [[eq:euler]], also known as Euler's equation, is remarkable
   unlike to the equation [[eq:trivial]], which is boring (except the
   elisp part, in listing [[oneplusone]]).

   #+target: end
   This is the end of section [[sec:tables]]. [[end][Invisible link to line 
above]]

* Footnotes

[fn:1] <<fn:basetwo>> That is strictly greater than two.
#+end_src



Then the ASCII output.



#+begin_src text
1 First headline.
=================

  Here we demonstrate cross-references to items.

  1. A first item in a list.
  2. Another item
     1. With three subparts. This one.
     2. Another one.
     3. And the last subpart.

  We end the list at item 2.3.

  Before we continue, here is a rather trivial equation, assuming base
  isn't too low[1].

  \begin{equation}
  1 + 1 = 2
  \end{equation}

  We can verify it with the following code:

  ,----
  | (+ 1 1)
  `----
  Listing 1: Shortly after the beginning of arithmetic.


1.1 Sub-topic
~~~~~~~~~~~~~

  Here we demonstrate cross-references to tables.

   one  1 
   two  2 
  Table 1: Test

   a  aille 
   b  bi    
  Table 2: Letters

  In table 1 we can only see two numbers.  Yet, in the very same table,
  we can already tell the radix used isn't too low (remember footnote
  1?).  On the other hand, table 2 shows letters, but that's clearly
  uninteresting.

  \begin{equation}
  e^{i\pi} + 1 = 0
  \end{equation}

  Equation 2, also known as Euler's equation, is remarkable unlike to
  the equation 1, which is boring (except the elisp part, in listing 1).

  This is the end of section 1.1.
#+end_src



And with LaTeX.



#+begin_src latex
\section{First headline.}
\label{sec-1}

Here we demonstrate cross-references to items.

\begin{enumerate}
\item A first item in a list.
\item Another item
\begin{enumerate}
\item With three subparts. This one.
\item Another one.
\item \label{itm:last} And the last subpart.
\end{enumerate}
\end{enumerate}

We end the list at item \ref{itm:last}.

Before we continue, here is a rather trivial equation, assuming base
isn't too low\footnote{\label{fn:basetwo} That is strictly greater than two.}.

\begin{equation}
\label{eq:trivial}
1 + 1 = 2
\end{equation}

We can verify it with the following code:

\begin{figure}[H]
\caption{\label{oneplusone}Shortly after the beginning of arithmetic.}
\begin{verbatim}
(+ 1 1)
\end{verbatim}
\end{figure}

\subsection{Sub-topic}
\label{sec-1-1}

Here we demonstrate cross-references to tables.\label{sec:tables}

\begin{table}[htb]
\caption{\label{tab:numbers}Test}
\begin{center}
\begin{tabular}{lr}
one & 1 \\
two & 2 \\
\end{tabular}
\end{center}
\end{table}

\begin{table}[htb]
\caption{\label{tab:letters}Letters}
\begin{center}
\begin{tabular}{ll}
a & aille \\
b & bi \\
\end{tabular}
\end{center}
\end{table}

In table \ref{tab:numbers} we can only see two numbers.  Yet, in 
\hyperref[tab:numbers]{the very
   same table}, we can already tell the radix used isn't too low
(remember footnote \ref{fn:basetwo}?).  On the other hand, table
\ref{tab:letters} shows letters, but that's clearly uninteresting.

\begin{equation}
\label{eq:euler}
e^{i\pi} + 1 = 0
\end{equation}

Equation \ref{eq:euler}, also known as Euler's equation, is remarkable
unlike to the equation \ref{eq:trivial}, which is boring (except the
elisp part, in listing \ref{oneplusone}).

This is the end of section \ref{sec:tables}. 
#+end_src


Regards,

-- 
Nicolas Goaziou
>From dcae2d1015f958dcb1ed3c92349ad0c2e18a1219 Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <address@hidden>
Date: Mon, 20 Feb 2012 22:24:38 +0100
Subject: [PATCH] Implement cross-references numbers

* lisp/org.el (org-link-search): Search for #+name affiliated keywords
  and invisible targets.
* contrib/lisp/org-element.el (org-element-link-parser): Remove "ref"
  links relative part.
(org-element-target-parser): Move property name from `:raw-value' to
`:value'.
(org-element-recursive-objects): Remove targets from tables.  Cells
are not parsed unless explicitely asked by back-end developer, too
late.  A target wouldn't be noticed in time.  One solution could be to
parse every table, but that's time consumming.
(org-element-object-restrictions): Target are not recursive anymore.
* contrib/lisp/org-export.el (org-export-resolve-fuzzy-link): Find
  elements with a matching "#+name: path" affiliated keyword.
(org-export-get-ordinal): Make special cases for headlines, items,
footnotes definitions and references.
(org-export-resolve-ref-link): Removed function.
* EXPERIMENTAL/org-e-latex.el (org-e-latex-link): Handle
  cross-reference numbers.
(org-e-latex-target): Targets have no contents.
* EXPERIMENTAL/org-e-ascii.el (org-e-ascii--describe-links): Ignore
  fuzzy links in link description at the end of the section.
(org-e-ascii-link): Handle cross-reference numbers.
---
 EXPERIMENTAL/org-e-ascii.el |   80 ++++++++-----------
 EXPERIMENTAL/org-e-latex.el |   48 ++++-------
 contrib/lisp/org-element.el |   20 ++---
 contrib/lisp/org-export.el  |  185 ++++++++++++++++++++++++++----------------
 lisp/org.el                 |   16 ++++
 5 files changed, 187 insertions(+), 162 deletions(-)

diff --git a/EXPERIMENTAL/org-e-ascii.el b/EXPERIMENTAL/org-e-ascii.el
index ef1ca1c..1361e23 100644
--- a/EXPERIMENTAL/org-e-ascii.el
+++ b/EXPERIMENTAL/org-e-ascii.el
@@ -826,28 +826,24 @@ channel."
                         (org-element-get-property :raw-link link)
                       (org-export-secondary-string desc 'e-ascii info)))))
        (cond
-       ;; Coderefs, radio links and ref links are ignored.
-       ((member type '("coderef" "radio" "ref")) nil)
-       ;; Id, custom-id and fuzzy links (with the exception of
-       ;; targets): Headlines refer to their numbering.
-       ((member type '("custom-id" "fuzzy" "id"))
-        (let ((destination (if (string= type "fuzzy")
-                               (org-export-resolve-fuzzy-link link info)
-                             (org-export-resolve-id-link link info))))
-          (unless (eq (car destination) 'target)
-            (concat
-             (org-e-ascii--fill-string
-              (format
-               "[%s] %s"
-               anchor
-               (if (not destination)
-                   (org-e-ascii--translate "Unknown reference" info)
-                 (format
-                  (org-e-ascii--translate "See section %s" info)
-                  (mapconcat 'number-to-string
-                             (org-export-get-headline-number destination info)
-                             "."))))
-              width info) "\n\n"))))
+       ;; Coderefs, radio links and fuzzy links are ignored.
+       ((member type '("coderef" "radio" "fuzzy")) nil)
+       ;; Id and custom-id links: Headlines refer to their numbering.
+       ((member type '("custom-id" "id"))
+        (let ((destination (org-export-resolve-id-link link info)))
+          (concat
+           (org-e-ascii--fill-string
+            (format
+             "[%s] %s"
+             anchor
+             (if (not destination)
+                 (org-e-ascii--translate "Unknown reference" info)
+               (format
+                (org-e-ascii--translate "See section %s" info)
+                (mapconcat 'number-to-string
+                           (org-export-get-headline-number destination info)
+                           "."))))
+            width info) "\n\n")))
        ;; Do not add a link that cannot be resolved and doesn't have
        ;; any description: destination is already visible in the
        ;; paragraph.
@@ -1392,29 +1388,23 @@ INFO is a plist holding contextual information."
        (org-element-get-property :path link)
        (cdr (assq 'radio-target org-element-object-restrictions)))
        'e-ascii info))
-     ;; Ref link: If there's no description (DESC, return link's
-     ;; destination sequence number among elements of same
-     ;; type. Otherwise, use DESC.
-     ((string= type "ref")
-      (if (org-string-nw-p desc) desc
-       (format "%d"
-               (org-export-get-ordinal
-                (org-export-resolve-ref-link link info)
-                info nil nil
-                (lambda (el) (or (org-element-get-property :caption el)
-                            (org-element-get-property :name el)))))))
      ;; Do not apply a special syntax on fuzzy links pointing to
      ;; targets.
-     ((and (string= type "fuzzy")
-          (let ((path (org-element-get-property :path link)))
-            (loop for target in (plist-get info :target-list)
-                  thereis (string=
-                           (org-element-get-property :raw-value target)
-                           path))))
-      (if (org-string-nw-p desc) desc raw-link))
+     ((string= type "fuzzy")
+      (let ((destination (org-export-resolve-fuzzy-link link info)))
+       ;; Ignore invisible "#+target: path".
+       (unless (eq (car destination) 'keyword)
+         (if (org-string-nw-p desc) desc
+           (when destination
+             (let ((number (org-export-get-ordinal destination info)))
+               (when number
+                 (if (atom number) (number-to-string number)
+                   (mapconcat 'number-to-string number ".")))))))))
      (t
-      (concat (format "[%s]" (if (org-string-nw-p desc) desc raw-link))
-             (unless org-e-ascii-links-to-notes (format " (%s)" raw-link)))))))
+      (if (not (org-string-nw-p desc)) (format "[%s]" raw-link)
+       (concat
+        (format "[%s]" desc)
+        (unless org-e-ascii-links-to-notes (format " (%s)" raw-link))))))))
 
 
 ;;;; Macro
@@ -1852,11 +1842,7 @@ INFO is a plist used as a communication channel."
 
 ;;;; Target
 
-(defun org-e-ascii-target (target contents info)
-  "Transcode a TARGET object from Org to ASCII.
-CONTENTS is the contents of the target.  INFO is a plist holding
-contextual information."
-  contents)
+;; Targets are invisible.
 
 
 ;;;; Time-stamp
diff --git a/EXPERIMENTAL/org-e-latex.el b/EXPERIMENTAL/org-e-latex.el
index eec331a..75b5a9b 100644
--- a/EXPERIMENTAL/org-e-latex.el
+++ b/EXPERIMENTAL/org-e-latex.el
@@ -1266,8 +1266,8 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
     (cond
      ((string= key "latex") value)
      ((string= key "index") (format "\\index{%s}" value))
-     ((string= key "target")
-      (format "\\label{%s}" (org-export-solidify-link-text value)))
+     ;; Invisible targets.
+     ((string= key "target") nil)
      ((string= key "toc")
       (let ((value (downcase value)))
        (cond
@@ -1426,32 +1426,26 @@ INFO is a plist holding contextual information.  See
               (org-element-parse-secondary-string
                path (cdr (assq 'radio-target org-element-object-restrictions)))
               'e-latex info)))
-     ;; Ref link: If no description is provided, reference label PATH
-     ;; and display table number.  Otherwise move to label but display
-     ;; description instead.
-     ((string= type "ref")
-      (if (not desc) (format "\\ref{%s}" path)
-       (format "\\hyperref[%s]{%s}" path desc)))
      ;; Links pointing to an headline: Find destination and build
      ;; appropriate referencing command.
      ((member type '("custom-id" "fuzzy" "id"))
       (let ((destination (if (string= type "fuzzy")
                             (org-export-resolve-fuzzy-link link info)
                           (org-export-resolve-id-link link info))))
-       ;; Fuzzy link points to a target.  Do as above.
        (case (car destination)
-         (target
-          (format "\\hyperref[%s]{%s}"
-                  (org-export-solidify-link-text
-                   (org-element-get-property :raw-value destination))
+         ;; Fuzzy link points nowhere.
+         ('nil
+          (format "\\texttt{%s}"
                   (or desc
                       (org-export-secondary-string
                        (org-element-get-property :raw-link link)
                        'e-latex info))))
-         ;; Fuzzy link points to an headline.  If headlines are
-         ;; numbered and the link has no description, display
-         ;; headline's number.  Otherwise, display description or
-         ;; headline's title.
+         ;; Fuzzy link points to an invisible target.
+         (keyword nil)
+         ;; LINK points to an headline.  If headlines are numbered
+         ;; and the link has no description, display headline's
+         ;; number.  Otherwise, display description or headline's
+         ;; title.
          (headline
           (let ((label
                  (format "sec-%s"
@@ -1466,13 +1460,10 @@ INFO is a plist holding contextual information.  See
                           (org-export-secondary-string
                            (org-element-get-property :title destination)
                            'e-latex info))))))
-         ;; Fuzzy link points nowhere.
+       ;; Fuzzy link points to a target.  Do as above.
          (otherwise
-          (format "\\texttt{%s}"
-                  (or desc
-                      (org-export-secondary-string
-                       (org-element-get-property :raw-link link)
-                       'e-latex info)))))))
+          (if (not desc) (format "\\ref{%s}" path)
+            (format "\\hyperref[%s]{%s}" path desc))))))
      ;; Coderef: replace link with the reference name or the
      ;; equivalent line number.
      ((string= type "coderef")
@@ -1945,14 +1936,11 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
 
 ;;;; Target
 
-(defun org-e-latex-target (target text info)
+(defun org-e-latex-target (target contents info)
   "Transcode a TARGET object from Org to LaTeX.
-TEXT is the text of the target.  INFO is a plist holding
-contextual information."
-  (format "\\label{%s}%s"
-         (org-export-solidify-link-text
-          (org-element-get-property :raw-value target))
-         text))
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (format "\\label{%s}" (org-element-get-property :value target)))
 
 
 ;;;; Time-stamp
diff --git a/contrib/lisp/org-element.el b/contrib/lisp/org-element.el
index 5b61942..554537e 100644
--- a/contrib/lisp/org-element.el
+++ b/contrib/lisp/org-element.el
@@ -1961,9 +1961,6 @@ Assume point is at the beginning of the link."
         ;; Explicit type (http, irc, bbdb...).  See `org-link-types'.
         ((string-match org-link-re-with-space3 link)
          (setq type (match-string 1 link) path (match-string 2 link)))
-        ;; Ref type: PATH is the name of the target element.
-        ((string-match "^ref:\\(.*\\)" link)
-         (setq type "ref" path (org-trim (match-string 1 link))))
         ;; Id type: PATH is the id.
         ((string-match "^id:\\([-a-f0-9]+\\)" link)
          (setq type "id" path (match-string 1 link)))
@@ -2265,25 +2262,21 @@ CONTENTS is the contents of the object."
   "Parse target at point.
 
 Return a list whose car is `target' and cdr a plist with
-`:begin', `:end', `:contents-begin', `:contents-end', `raw-value'
-and `:post-blank' as keywords.
+`:begin', `:end', `:contents-begin', `:contents-end', `value' and
+`:post-blank' as keywords.
 
 Assume point is at the target."
   (save-excursion
     (looking-at org-target-regexp)
     (let ((begin (point))
-         (contents-begin (match-beginning 1))
-         (contents-end (match-end 1))
-         (raw-value (org-match-string-no-properties 1))
+         (value (org-match-string-no-properties 1))
          (post-blank (progn (goto-char (match-end 0))
                             (skip-chars-forward " \t")))
          (end (point)))
       `(target
        (:begin ,begin
                :end ,end
-               :contents-begin ,contents-begin
-               :contents-end ,contents-end
-               :raw-value ,raw-value
+               :value ,value
                :post-blank ,post-blank)))))
 
 (defun org-element-target-interpreter (target contents)
@@ -2470,7 +2463,7 @@ Sharing the same successor comes handy when, for example, 
the
 regexp matching one object can also match the other object.")
 
 (defconst org-element-recursive-objects
-  '(emphasis link macro subscript superscript target radio-target)
+  '(emphasis link macro subscript superscript radio-target)
   "List of recursive object types.")
 
 (defconst org-element-non-recursive-block-alist
@@ -2540,8 +2533,7 @@ This list is checked after translations have been 
applied.  See
     (subscript entity export-snippet inline-babel-call inline-src-block
               latex-fragment sub/superscript text-markup)
     (superscript entity export-snippet inline-babel-call inline-src-block
-                latex-fragment sub/superscript text-markup)
-    (target entity export-snippet latex-fragment sub/superscript text-markup))
+                latex-fragment sub/superscript text-markup))
   "Alist of recursive objects restrictions.
 
 CAR is a recursive object type and CDR is a list of successors
diff --git a/contrib/lisp/org-export.el b/contrib/lisp/org-export.el
index 34f290e..aa6ca52 100644
--- a/contrib/lisp/org-export.el
+++ b/contrib/lisp/org-export.el
@@ -1278,7 +1278,13 @@ Following tree properties are set:
    `(:parse-tree
      ,data
      :target-list
-     ,(org-element-map data 'target (lambda (target local) target) info)
+     ,(org-element-map
+       data '(keyword target)
+       (lambda (blob local)
+        (when (or (eq (car blob) 'target)
+                  (string= (downcase (org-element-get-property :key blob))
+                           "target"))
+          blob)) info)
      :headline-numbering ,(org-export-collect-headline-numbering data info)
      :back-end ,backend)
    info))
@@ -2579,8 +2585,11 @@ INFO is a plist holding contextual information.
 
 Return value can be an object, an element, or nil:
 
-- If LINK path exactly matches any target, return the target
-  object.
+- If LINK path matches a target object (i.e. <<path>>) or
+  element (i.e. \"#+target: path\"), return it.
+
+- If LINK path exactly matches the name affiliated keyword
+  \(i.e. #+name: path) of an element, return that element.
 
 - If LINK path exactly matches any headline name, return that
   element.  If more than one headline share that name, priority
@@ -2591,39 +2600,53 @@ Return value can be an object, an element, or nil:
 
 Assume LINK type is \"fuzzy\"."
   (let ((path (org-element-get-property :path link)))
-    ;; Link points to a target: return it.
-    (or (loop for target in (plist-get info :target-list)
-             when (string= (org-element-get-property :raw-value target) path)
-             return target)
-       ;; Link either points to an headline or nothing.  Try to find
-       ;; the source, with priority given to headlines with the closest
-       ;; common ancestor.  If such candidate is found, return its
-       ;; beginning position as an unique identifier, otherwise return
-       ;; nil.
-       (let ((find-headline
-              (function
-               ;; Return first headline whose `:raw-value' property
-               ;; is NAME in parse tree DATA, or nil.
-               (lambda (name data)
-                 (org-element-map
-                  data 'headline
-                  (lambda (headline local)
-                    (when (string=
-                           (org-element-get-property :raw-value headline)
-                           name)
-                      headline))
-                  info 'first-match)))))
-         ;; Search among headlines sharing an ancestor with link,
-         ;; from closest to farthest.
-         (or (catch 'exit
-               (mapc
-                (lambda (parent)
-                  (when (eq (car parent) 'headline)
-                    (let ((foundp (funcall find-headline path parent)))
-                      (when foundp (throw 'exit foundp)))))
-                (plist-get info :genealogy)) nil)
-             ;; No match with a common ancestor: try the full parse-tree.
-             (funcall find-headline path (plist-get info :parse-tree)))))))
+    (cond
+     ;; First try to find a matching "<<path>>" unless user specified
+     ;; he was looking for an headline (path starts with a *
+     ;; character).
+     ((and (not (eq (substring path 0 1) ?*))
+          (loop for target in (plist-get info :target-list)
+                when (string= (org-element-get-property :value target) path)
+                return target)))
+     ;; Then try to find an element with a matching "#+name: path"
+     ;; affiliated keyword.
+     ((and (not (eq (substring path 0 1) ?*))
+          (org-element-map
+           (plist-get info :parse-tree) org-element-all-elements
+           (lambda (el local)
+             (when (string= (org-element-get-property :name el) path) el))
+           info 'first-match)))
+     ;; Last case: link either points to an headline or to
+     ;; nothingness.  Try to find the source, with priority given to
+     ;; headlines with the closest common ancestor.  If such candidate
+     ;; is found, return its beginning position as an unique
+     ;; identifier, otherwise return nil.
+     (t
+      (let ((find-headline
+            (function
+             ;; Return first headline whose `:raw-value' property is
+             ;; NAME in parse tree DATA, or nil.
+             (lambda (name data)
+               (org-element-map
+                data 'headline
+                (lambda (headline local)
+                  (when (string=
+                         (org-element-get-property :raw-value headline)
+                         name)
+                    headline))
+                info 'first-match)))))
+       ;; Search among headlines sharing an ancestor with link, from
+       ;; closest to farthest.
+       (or (catch 'exit
+             (mapc
+              (lambda (parent)
+                (when (eq (car parent) 'headline)
+                  (let ((foundp (funcall find-headline path parent)))
+                    (when foundp (throw 'exit foundp)))))
+              (plist-get info :genealogy)) nil)
+           ;; No match with a common ancestor: try the full
+           ;; parse-tree.
+           (funcall find-headline path (plist-get info :parse-tree))))))))
 
 (defun org-export-resolve-id-link (link info)
   "Return headline referenced as LINK destination.
@@ -2641,20 +2664,6 @@ is either \"id\" or \"custom-id\"."
          headline))
      info 'first-match)))
 
-(defun org-export-resolve-ref-link (link info)
-  "Return element referenced as LINK destination.
-
-INFO is a plist used as a communication channel.
-
-Assume LINK type is \"ref\" and.  Return value is the first
-element whose `:name' property matches LINK's `:path', or nil."
-  (let ((name (org-element-get-property :path link)))
-    (org-element-map
-     (plist-get info :parse-tree) org-element-all-elements
-     (lambda (el local)
-       (when (string= (org-element-get-property :name el) name) el))
-     info 'first-match)))
-
 (defun org-export-resolve-coderef (ref info)
   "Resolve a code reference REF.
 
@@ -2745,27 +2754,61 @@ Optional argument PREDICATE is a function returning a 
non-nil
 value if the current element or object should be counted in.  It
 accepts one argument: the element or object being considered.
 This argument allows to count only a certain type of objects,
-like inline images, which are a subset of links \(in that case,
-`org-export-inline-image-p' might be an useful predicate\)."
-  (let ((counter 0)
-        ;; Determine if search should apply to current section, in
-        ;; which case it should be retrieved first, or to full parse
-        ;; tree.  As a special case, an element or object without
-        ;; a parent headline will also trigger a full search,
-        ;; notwithstanding WITHIN-SECTION value.
-        (data
-         (if (not within-section) (plist-get info :parse-tree)
-          (or (org-export-get-parent-headline element info)
-              (plist-get info :parse-tree)))))
-    ;; Increment counter until ELEMENT is found again.
-    (org-element-map
-     data (or types (car element))
-     (lambda (el local)
-       (cond
-        ((equal element el) (1+ counter))
-       ((not predicate) (incf counter) nil)
-       ((funcall predicate el) (incf counter) nil)))
-     info 'first-match)))
+like inline images, which are a subset of links (in that case,
+`org-export-inline-image-p' might be an useful predicate).
+
+Return value is a list of numbers if ELEMENT is an headline or an
+item.  It is nil for keywords.  It represents the footnote number
+for footnote definitions and footnote references.  If ELEMENT is
+a target, return the same value as if ELEMENT was the closest
+table, item or headline containing the target.  In any other
+case, return the sequence number of ELEMENT among elements or
+objects of the same type."
+  ;; A target keyword, representing an invisible target, never has
+  ;; a sequence number.
+  (unless (eq (car element) 'keyword)
+    ;; Ordinal of a target object is the ordinal of the closest table,
+    ;; item, or headline containing the object.
+    (when (eq (car element) 'target)
+      (setq element
+           (loop for parent in (org-export-get-genealogy element info)
+                 when
+                 (memq
+                  (car parent)
+                  '(footnote-definition footnote-reference headline item 
table))
+                 return parent)))
+    (case (car element)
+      ;; Special case 1: An headline returns its number as a list.
+      (headline (org-export-get-headline-number element info))
+      ;; Special case 2: An item returns its number as a list.
+      (item (let ((struct (org-element-get-property :structure element)))
+             (org-list-get-item-number
+              (org-element-get-property :begin element)
+              struct
+              (org-list-prevs-alist struct)
+              (org-list-parents-alist struct))))
+      ((footnote definition footnote-reference)
+       (org-export-get-footnote-number element info))
+      (otherwise
+       (let ((counter 0)
+            ;; Determine if search should apply to current section,
+            ;; in which case it should be retrieved first, or to full
+            ;; parse tree.  As a special case, an element or object
+            ;; without a parent headline will also trigger a full
+            ;; search, notwithstanding WITHIN-SECTION value.
+            (data
+             (if (not within-section) (plist-get info :parse-tree)
+               (or (org-export-get-parent-headline element info)
+                   (plist-get info :parse-tree)))))
+        ;; Increment counter until ELEMENT is found again.
+        (org-element-map
+         data (or types (car element))
+         (lambda (el local)
+           (cond
+            ((equal element el) (1+ counter))
+            ((not predicate) (incf counter) nil)
+            ((funcall predicate el) (incf counter) nil)))
+         info 'first-match))))))
 
 
 ;;;; For Src-Blocks
diff --git a/lisp/org.el b/lisp/org.el
index a81f7fc..6708801 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9896,6 +9896,22 @@ visibility around point, thus ignoring
               pos (match-beginning 0))))
       ;; There is an exact target for this
       (goto-char pos))
+     ((save-excursion
+       (goto-char (point-min))
+       (and
+        (re-search-forward
+         (format "^[ \t]*#\\+target: %s" (regexp-quote s0)) nil t)
+        (setq type 'dedicated pos (match-beginning 0))))
+      ;; Found an invisible target.
+      (goto-char pos))
+     ((save-excursion
+       (goto-char (point-min))
+       (and
+        (re-search-forward
+         (format "^[ \t]*#\\+name: %s" (regexp-quote s0)) nil t)
+        (setq type 'dedicated pos (match-beginning 0))))
+      ;; Found an element with a matching name.
+      (goto-char pos))
      ((and (string-match "^(\\(.*\\))$" s0)
           (save-excursion
             (goto-char (point-min))
-- 
1.7.9.1


reply via email to

[Prev in Thread] Current Thread [Next in Thread]