From 7cd6fdcd34469544099d4fdc29bbaa14fc650e54 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Mon, 25 Feb 2013 21:32:15 +0100 Subject: [PATCH] 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. --- lisp/org-element.el | 17 +++++++--- testing/lisp/test-org-element.el | 67 +++++++++++++++++++++------------------- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/lisp/org-element.el b/lisp/org-element.el index 1c9ee9ff5..fb12b419f 100644 --- a/lisp/org-element.el +++ b/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 '(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 text-markup timestamp) "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) (latex-fragment . latex-or-entity)) "Alist of translations between object type and successor name. - Sharing the same successor comes handy when, for example, the 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) (keyword inline-babel-call inline-src-block latex-or-entity link macro 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 inline-src-block latex-or-entity line-break link macro radio-target statistics-cookie sub/superscript target text-markup @@ -3101,6 +3100,16 @@ beginning position." (when (re-search-forward link-regexp limit t) (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 diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index 5a08b9ed0..cfb66e8ee 100644 --- a/testing/lisp/test-org-element.el +++ b/testing/lisp/test-org-element.el @@ -1193,7 +1193,7 @@ e^{i\\pi}+1=0 (ert-deftest test-org-element/link-parser () "Test `link' parser." - ;; 1. Radio target. + ;; Radio target. (should (equal "radio" @@ -1201,18 +1201,18 @@ e^{i\\pi}+1=0 (org-element-property :type (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 (equal '("Orgmode.org") (org-test-with-temp-text "[[http://orgmode.org][Orgmode.org]]" (org-element-contents (org-element-map (org-element-parse-buffer) 'link 'identity nil t))))) - ;; 2.2. Without description. + ;; ... without description. (should (equal "http" @@ -1220,7 +1220,7 @@ e^{i\\pi}+1=0 (org-element-property :type (org-element-map (org-element-parse-buffer) 'link 'identity nil t))))) - ;; 2.3. With expansion. + ;; ... with expansion. (should (equal "//orgmode.org/worg" @@ -1229,7 +1229,7 @@ e^{i\\pi}+1=0 (org-element-property :path (org-element-map (org-element-parse-buffer) 'link 'identity nil t)))))) - ;; 2.4. With translation. + ;; ... with translation. (should (equal "127.0.0.1" @@ -1238,9 +1238,9 @@ e^{i\\pi}+1=0 (let ((org-link-translation-function 'link-translate)) (org-element-property :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 (equal "id" @@ -1248,7 +1248,7 @@ e^{i\\pi}+1=0 (org-element-property :type (org-element-map (org-element-parse-buffer) 'link 'identity nil t))))) - ;; 2.6. Custom-id link. + ;; ... custom-id link. (should (equal "custom-id" @@ -1256,7 +1256,7 @@ e^{i\\pi}+1=0 (org-element-property :type (org-element-map (org-element-parse-buffer) 'link 'identity nil t))))) - ;; 2.7 Coderef link. + ;; ... coderef link. (should (equal "coderef" @@ -1264,7 +1264,7 @@ e^{i\\pi}+1=0 (org-element-property :type (org-element-map (org-element-parse-buffer) 'link 'identity nil t))))) - ;; 2.8 Fuzzy link. + ;; ... fuzzy link. (should (equal "fuzzy" @@ -1272,31 +1272,29 @@ e^{i\\pi}+1=0 (org-element-property :type (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 (equal '(("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 (equal '(("file" "projects.org" "docview")) (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 (org-test-with-temp-text "A link: http://orgmode.org" (org-element-map (org-element-parse-buffer) 'link 'identity))) - ;; 4. Angular link. + ;; Angular link. (should (org-test-with-temp-text "A link: " (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 "#+LINK: orgmode http://www.orgmode.org/\n* H [[orgmode:#docs]]" (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 -- 2.11.4.GIT