Browse Source

org-element: Only allow plain links in links

* lisp/org-element.el (org-element-all-successors): Add `plain-link'
  successor.
(org-element-object-restrictions): Remove `link' within `link'.  Allow
`plain-link' instead.
(org-element-plain-link-successor): New function.
* testing/lisp/test-org-element.el: Add test.

Plain links within links are needed for the following kind of syntax:

  [[http://orgmode.org][file:unicorn.png]]

No other link type is allowed within links.
Nicolas Goaziou 12 years ago
parent
commit
7cd6fdcd34
2 changed files with 48 additions and 36 deletions
  1. 13 4
      lisp/org-element.el
  2. 35 32
      testing/lisp/test-org-element.el

+ 13 - 4
lisp/org-element.el

@@ -186,7 +186,7 @@ is not sufficient to know if point is at a paragraph ending.  See
 
 
 (defconst org-element-all-successors
 (defconst org-element-all-successors
   '(export-snippet footnote-reference inline-babel-call inline-src-block
   '(export-snippet footnote-reference inline-babel-call inline-src-block
-		   latex-or-entity line-break link macro radio-target
+		   latex-or-entity line-break link macro plain-link radio-target
 		   statistics-cookie sub/superscript table-cell target
 		   statistics-cookie sub/superscript table-cell target
 		   text-markup timestamp)
 		   text-markup timestamp)
   "Complete list of successors.")
   "Complete list of successors.")
@@ -198,7 +198,6 @@ is not sufficient to know if point is at a paragraph ending.  See
     (verbatim . text-markup) (entity . latex-or-entity)
     (verbatim . text-markup) (entity . latex-or-entity)
     (latex-fragment . latex-or-entity))
     (latex-fragment . latex-or-entity))
   "Alist of translations between object type and successor name.
   "Alist of translations between object type and successor name.
-
 Sharing the same successor comes handy when, for example, the
 Sharing the same successor comes handy when, for example, the
 regexp matching one object can also match the other object.")
 regexp matching one object can also match the other object.")
 
 
@@ -315,8 +314,8 @@ a secondary string.")
 	  link macro radio-target sub/superscript target text-markup)
 	  link macro radio-target sub/superscript target text-markup)
     (keyword inline-babel-call inline-src-block latex-or-entity link macro
     (keyword inline-babel-call inline-src-block latex-or-entity link macro
 	     sub/superscript text-markup timestamp)
 	     sub/superscript text-markup timestamp)
-    (link export-snippet inline-babel-call inline-src-block latex-or-entity link
-	  sub/superscript text-markup)
+    (link export-snippet inline-babel-call inline-src-block latex-or-entity
+	  plain-link sub/superscript text-markup)
     (paragraph export-snippet footnote-reference inline-babel-call
     (paragraph export-snippet footnote-reference inline-babel-call
 	       inline-src-block latex-or-entity line-break link macro
 	       inline-src-block latex-or-entity line-break link macro
 	       radio-target statistics-cookie sub/superscript target text-markup
 	       radio-target statistics-cookie sub/superscript target text-markup
@@ -3101,6 +3100,16 @@ beginning position."
       (when (re-search-forward link-regexp limit t)
       (when (re-search-forward link-regexp limit t)
 	(cons 'link (match-beginning 0))))))
 	(cons 'link (match-beginning 0))))))
 
 
+(defun org-element-plain-link-successor (limit)
+  "Search for the next plain link object.
+
+LIMIT bounds the search.
+
+Return value is a cons cell whose CAR is `link' and CDR is
+beginning position."
+  (and (save-excursion (re-search-forward org-plain-link-re limit t))
+       (cons 'link (match-beginning 0))))
+
 
 
 ;;;; Macro
 ;;;; Macro
 
 

+ 35 - 32
testing/lisp/test-org-element.el

@@ -1193,7 +1193,7 @@ e^{i\\pi}+1=0
 
 
 (ert-deftest test-org-element/link-parser ()
 (ert-deftest test-org-element/link-parser ()
   "Test `link' parser."
   "Test `link' parser."
-  ;; 1. Radio target.
+  ;; Radio target.
   (should
   (should
    (equal
    (equal
     "radio"
     "radio"
@@ -1201,18 +1201,18 @@ e^{i\\pi}+1=0
       (org-element-property
       (org-element-property
        :type
        :type
        (org-element-map
        (org-element-map
-	(let ((org-target-link-regexp "radio")) (org-element-parse-buffer))
-	'link 'identity nil t)))))
-  ;; 2. Standard link.
+	   (let ((org-target-link-regexp "radio")) (org-element-parse-buffer))
+	   'link 'identity nil t)))))
+  ;; Standard link.
   ;;
   ;;
-  ;; 2.1. With description.
+  ;; ... with description.
   (should
   (should
    (equal
    (equal
     '("Orgmode.org")
     '("Orgmode.org")
     (org-test-with-temp-text "[[http://orgmode.org][Orgmode.org]]"
     (org-test-with-temp-text "[[http://orgmode.org][Orgmode.org]]"
       (org-element-contents
       (org-element-contents
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
-  ;; 2.2. Without description.
+  ;; ... without description.
   (should
   (should
    (equal
    (equal
     "http"
     "http"
@@ -1220,7 +1220,7 @@ e^{i\\pi}+1=0
       (org-element-property
       (org-element-property
        :type
        :type
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
-  ;; 2.3. With expansion.
+  ;; ... with expansion.
   (should
   (should
    (equal
    (equal
     "//orgmode.org/worg"
     "//orgmode.org/worg"
@@ -1229,7 +1229,7 @@ e^{i\\pi}+1=0
 	(org-element-property
 	(org-element-property
 	 :path
 	 :path
 	 (org-element-map (org-element-parse-buffer) 'link 'identity nil t))))))
 	 (org-element-map (org-element-parse-buffer) 'link 'identity nil t))))))
-  ;; 2.4. With translation.
+  ;; ... with translation.
   (should
   (should
    (equal
    (equal
     "127.0.0.1"
     "127.0.0.1"
@@ -1238,9 +1238,9 @@ e^{i\\pi}+1=0
 	(let ((org-link-translation-function 'link-translate))
 	(let ((org-link-translation-function 'link-translate))
 	  (org-element-property
 	  (org-element-property
 	   :path
 	   :path
-	   (org-element-map
-	    (org-element-parse-buffer) 'link 'identity nil t)))))))
-  ;; 2.5. Id link.
+	   (org-element-map (org-element-parse-buffer) 'link
+	     'identity nil t)))))))
+  ;; ... id link.
   (should
   (should
    (equal
    (equal
     "id"
     "id"
@@ -1248,7 +1248,7 @@ e^{i\\pi}+1=0
       (org-element-property
       (org-element-property
        :type
        :type
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
-  ;; 2.6. Custom-id link.
+  ;; ... custom-id link.
   (should
   (should
    (equal
    (equal
     "custom-id"
     "custom-id"
@@ -1256,7 +1256,7 @@ e^{i\\pi}+1=0
       (org-element-property
       (org-element-property
        :type
        :type
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
-  ;; 2.7 Coderef link.
+  ;; ... coderef link.
   (should
   (should
    (equal
    (equal
     "coderef"
     "coderef"
@@ -1264,7 +1264,7 @@ e^{i\\pi}+1=0
       (org-element-property
       (org-element-property
        :type
        :type
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
-  ;; 2.8 Fuzzy link.
+  ;; ... fuzzy link.
   (should
   (should
    (equal
    (equal
     "fuzzy"
     "fuzzy"
@@ -1272,31 +1272,29 @@ e^{i\\pi}+1=0
       (org-element-property
       (org-element-property
        :type
        :type
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
        (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))
-  ;; 2.9 File-type link with search option.
+  ;; ... file-type link with search option.
   (should
   (should
    (equal
    (equal
     '(("file" "projects.org" "*task title"))
     '(("file" "projects.org" "*task title"))
     (org-test-with-temp-text "[[file:projects.org::*task title]]"
     (org-test-with-temp-text "[[file:projects.org::*task title]]"
-      (org-element-map
-       (org-element-parse-buffer) 'link
-       (lambda (l) (list (org-element-property :type l)
-		    (org-element-property :path l)
-		    (org-element-property :search-option l)))))))
-  ;; 2.10 File-type link with application.
+      (org-element-map (org-element-parse-buffer) 'link
+	(lambda (l) (list (org-element-property :type l)
+		     (org-element-property :path l)
+		     (org-element-property :search-option l)))))))
+  ;; ... file-type link with application.
   (should
   (should
    (equal
    (equal
     '(("file" "projects.org" "docview"))
     '(("file" "projects.org" "docview"))
     (org-test-with-temp-text "[[docview:projects.org]]"
     (org-test-with-temp-text "[[docview:projects.org]]"
-      (org-element-map
-       (org-element-parse-buffer) 'link
-       (lambda (l) (list (org-element-property :type l)
-		    (org-element-property :path l)
-		    (org-element-property :application l)))))))
-  ;; 3. Plain link.
+      (org-element-map (org-element-parse-buffer) 'link
+	(lambda (l) (list (org-element-property :type l)
+		     (org-element-property :path l)
+		     (org-element-property :application l)))))))
+  ;; Plain link.
   (should
   (should
    (org-test-with-temp-text "A link: http://orgmode.org"
    (org-test-with-temp-text "A link: http://orgmode.org"
      (org-element-map (org-element-parse-buffer) 'link 'identity)))
      (org-element-map (org-element-parse-buffer) 'link 'identity)))
-  ;; 4. Angular link.
+  ;; Angular link.
   (should
   (should
    (org-test-with-temp-text "A link: <http://orgmode.org>"
    (org-test-with-temp-text "A link: <http://orgmode.org>"
      (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))
      (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))
@@ -1314,10 +1312,15 @@ e^{i\\pi}+1=0
 	  (org-test-with-temp-text
 	  (org-test-with-temp-text
 	      "#+LINK: orgmode http://www.orgmode.org/\n* H [[orgmode:#docs]]"
 	      "#+LINK: orgmode http://www.orgmode.org/\n* H [[orgmode:#docs]]"
 	    (progn (org-mode-restart)
 	    (progn (org-mode-restart)
-		   (org-element-map
-		    (org-element-parse-buffer) 'link
-		    (lambda (link) (org-element-property :type link))
-		    nil t nil t))))))
+		   (org-element-map (org-element-parse-buffer) 'link
+		     (lambda (link) (org-element-property :type link))
+		     nil t nil t)))))
+  ;; Plain links are allowed as description of regular links.
+  (should
+   (equal "file"
+	  (org-test-with-temp-text "[[http://orgmode.org][file:unicorn.jpg]]"
+	    (search-forward "file:")
+	    (org-element-property :type (org-element-context))))))
 
 
 
 
 ;;;; Macro
 ;;;; Macro