diff --git a/contrib/lisp/org-e-groff.el b/contrib/lisp/org-e-groff.el index 756a818c1..c1860e8f6 100644 --- a/contrib/lisp/org-e-groff.el +++ b/contrib/lisp/org-e-groff.el @@ -1336,8 +1336,6 @@ INFO is a plist holding contextual information. See ((member type '("http" "https" "ftp" "mailto")) (concat type ":" raw-path)) ((string= type "file") - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) (if (file-name-absolute-p raw-path) (concat "file://" (expand-file-name raw-path)) (concat "file://" raw-path))) diff --git a/contrib/lisp/org-e-html.el b/contrib/lisp/org-e-html.el index 94f42ea64..0d991eaca 100644 --- a/contrib/lisp/org-e-html.el +++ b/contrib/lisp/org-e-html.el @@ -2277,10 +2277,6 @@ INFO is a plist holding contextual information. See ((member type '("http" "https" "ftp" "mailto")) (concat type ":" raw-path)) ((string= type "file") - ;; Extract just the file path and strip all other - ;; components. - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) ;; Treat links to ".org" files as ".html", if needed. (setq raw-path (funcall --link-org-files-as-html-maybe raw-path info)) diff --git a/contrib/lisp/org-e-latex.el b/contrib/lisp/org-e-latex.el index 8dd2d924a..f2b8e9230 100644 --- a/contrib/lisp/org-e-latex.el +++ b/contrib/lisp/org-e-latex.el @@ -1748,8 +1748,6 @@ INFO is a plist holding contextual information. See ((member type '("http" "https" "ftp" "mailto")) (concat type ":" raw-path)) ((string= type "file") - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) (if (file-name-absolute-p raw-path) (concat "file://" (expand-file-name raw-path)) (concat "file://" raw-path))) diff --git a/contrib/lisp/org-e-man.el b/contrib/lisp/org-e-man.el index 981f831d7..264fdef02 100644 --- a/contrib/lisp/org-e-man.el +++ b/contrib/lisp/org-e-man.el @@ -731,8 +731,6 @@ INFO is a plist holding contextual information. See ((member type '("http" "https" "ftp" "mailto")) (concat type ":" raw-path)) ((string= type "file") - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) (if (file-name-absolute-p raw-path) (concat "file://" (expand-file-name raw-path)) (concat "file://" raw-path))) diff --git a/contrib/lisp/org-e-odt.el b/contrib/lisp/org-e-odt.el index 0f9e2d487..d83c72fb2 100644 --- a/contrib/lisp/org-e-odt.el +++ b/contrib/lisp/org-e-odt.el @@ -2485,8 +2485,6 @@ INFO is a plist holding contextual information. See ((member type '("http" "https" "ftp" "mailto")) (concat type ":" raw-path)) ((string= type "file") - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) (if (file-name-absolute-p raw-path) (concat "file://" (expand-file-name raw-path)) (concat "file://" raw-path))) diff --git a/contrib/lisp/org-e-texinfo.el b/contrib/lisp/org-e-texinfo.el index a19139fa5..d744a3a7b 100644 --- a/contrib/lisp/org-e-texinfo.el +++ b/contrib/lisp/org-e-texinfo.el @@ -1223,8 +1223,6 @@ INFO is a plist holding contextual information. See ((member type '("http" "https" "ftp")) (concat type ":" raw-path)) ((string= type "file") - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) (if (file-name-absolute-p raw-path) (concat "file://" (expand-file-name raw-path)) (concat "file://" raw-path))) diff --git a/contrib/lisp/org-md.el b/contrib/lisp/org-md.el index 4579ca31e..8e8189c95 100644 --- a/contrib/lisp/org-md.el +++ b/contrib/lisp/org-md.el @@ -307,10 +307,6 @@ a communication channel." ((member type '("http" "https" "ftp")) (concat type ":" raw-path)) ((equal type "file") - ;; Extract just the file path and strip - ;; all other components. - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) ;; Treat links to ".org" files as ".html", ;; if needed. (setq raw-path diff --git a/lisp/org-element.el b/lisp/org-element.el index f0e1a0f41..265ca536c 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -214,6 +214,12 @@ regexp matching one object can also match the other object.") Names must be uppercase. Any block whose name has no association is parsed with `org-element-special-block-parser'.") +(defconst org-element-link-type-is-file + '("file" "file+emacs" "file+sys" "docview") + "List of link types equivalent to \"file\". +Only these types can accept search options and an explicit +application to open them.") + (defconst org-element-affiliated-keywords '("CAPTION" "DATA" "HEADER" "HEADERS" "LABEL" "NAME" "PLOT" "RESNAME" "RESULT" "RESULTS" "SOURCE" "SRCNAME" "TBLNAME") @@ -2717,14 +2723,15 @@ beginning position." "Parse link at point. Return a list whose CAR is `link' and CDR a plist with `:type', -`:path', `:raw-link', `:begin', `:end', `:contents-begin', -`:contents-end' and `:post-blank' as keywords. +`:path', `:raw-link', `:application', `:search-option', `:begin', +`:end', `:contents-begin', `:contents-end' and `:post-blank' as +keywords. Assume point is at the beginning of the link." (save-excursion (let ((begin (point)) end contents-begin contents-end link-end post-blank path type - raw-link link) + raw-link link search-option application) (cond ;; Type 1: Text targeted from a radio target. ((and org-target-link-regexp (looking-at org-target-link-regexp)) @@ -2779,10 +2786,26 @@ Assume point is at the beginning of the link." ;; LINK-END variable. (setq post-blank (progn (goto-char link-end) (skip-chars-forward " \t")) end (point)) + ;; Extract search option and opening application out of + ;; "file"-type links. + (when (member type org-element-link-type-is-file) + ;; Application. + (cond ((string-match "^file\\+\\(.*\\)$" type) + (setq application (match-string 1 type))) + ((not (string-match "^file" type)) + (setq application type))) + ;; Extract search option from PATH. + (when (string-match "::\\(.*\\)$" path) + (setq search-option (match-string 1 path) + path (replace-match "" nil nil path))) + ;; Make sure TYPE always report "file". + (setq type "file")) (list 'link (list :type type :path path :raw-link (or raw-link path) + :application application + :search-option search-option :begin begin :end end :contents-begin contents-begin diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index 63faca1b1..1b119ca31 100644 --- a/testing/lisp/test-org-element.el +++ b/testing/lisp/test-org-element.el @@ -1101,6 +1101,26 @@ 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. + (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. + (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. (should (org-test-with-temp-text "A link: http://orgmode.org"