From 371a3294887cdb714aff14494c5286a19524c807 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sat, 15 Feb 2020 17:31:34 +0100 Subject: [PATCH 2/2] ol: Extend open tooling in link parameters * lisp/ol.el (org-link-parameters): Add :open parameter. (org-link-open): Call custom-link functions after internal ones. (org-link-open-as-file): New function. (org-link-parameters): Reference new function. (org-link-open): Use new function. --- lisp/ol.el | 75 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/lisp/ol.el b/lisp/ol.el index f850a5313..710947c92 100644 --- a/lisp/ol.el +++ b/lisp/ol.el @@ -93,13 +93,21 @@ Subsequent optional elements make up a property list for that type. All properties ar optional. However, the most important ones -are, in this order, `:follow', `:export', and `:store', described -below. +are, in this order, `:open' (or `:follow'), `:export', and +`:store', described below. +`:open' `:follow' - Function that takes the link path (a string) as an argument and - \"opens\" the link. + Function used to follow the link, when `org-open-at-point' is + command runs on it. + + The function stored in `:open' is called with two arguments: + the path, as a string, and a universal prefix argument, whereas + the one stored in `:follow' is called with the path only. + + You may use `org-link-open-as-file' helper function for types + similar to \"file\". `:export' @@ -990,37 +998,14 @@ for internal and \"file\" links, or stored as a parameter in (let ((type (org-element-property :type link)) (path (org-element-property :path link))) (cond + ;; Opening a "file" link requires special treatment since we + ;; first need to integrate search option, if any. ((member type '("file" "attachment")) (when (string= type "attachment") (setq path (org-attach-link-expand link))) - (if (string-match "[*?{]" (file-name-nondirectory path)) - (dired path) - ;; Look into `org-link-parameters' in order to find - ;; a DEDICATED-FUNCTION to open file. The function will be - ;; applied on raw link instead of parsed link due to the - ;; limitation in `org-add-link-type' ("open" function called - ;; with a single argument). If no such function is found, - ;; fallback to `org-open-file'. - (let* ((option (org-element-property :search-option link)) - (app (org-element-property :application link)) - (dedicated-function - (org-link-get-parameter (if app (concat type "+" app) type) - :follow))) - (if dedicated-function - (funcall dedicated-function - (concat path - (and option (concat "::" option)))) - (apply #'org-open-file - path - (cond (arg) - ((equal app "emacs") 'emacs) - ((equal app "sys") 'system)) - (cond ((not option) nil) - ((string-match-p "\\`[0-9]+\\'" option) - (list (string-to-number option))) - (t (list nil option)))))))) - ((functionp (org-link-get-parameter type :follow)) - (funcall (org-link-get-parameter type :follow) path)) + (let* ((option (org-element-property :search-option link)) + (path (if option (concat path "::" option) path))) + (org-link-open-as-file path arg))) ((member type '("coderef" "custom-id" "fuzzy" "radio")) (unless (run-hook-with-args-until-success 'org-open-link-functions path) (if (not arg) (org-mark-ring-push) @@ -1042,6 +1027,10 @@ for internal and \"file\" links, or stored as a parameter in (>= (point-max) destination)) (widen)) (goto-char destination)))) + ((functionp (org-link-get-parameter type :open)) + (funcall (org-link-get-parameter type :open) path arg)) + ((functionp (org-link-get-parameter type :follow)) + (funcall (org-link-get-parameter type :follow) path)) (t (browse-url-at-point))))) (defun org-link-open-from-string (s &optional arg) @@ -1240,6 +1229,28 @@ of matched result, which is either `dedicated' or `fuzzy'." (reverse slines))) "\n"))))) (mapconcat #'identity (split-string s) " "))) +(defun org-link-open-as-file (path arg) + "Pretend PATH is a file name and open it. + +According to \"file\"-link syntax, PATH may include addition +search options, separated from the file name with \"::\". + +This function is meant to be used as a possible tool for `:open' +property in `org-link-parameters.'" + (if (string-match "[*?{]" (file-name-nondirectory path)) + (dired path) + (let* ((option (and (string-match "::\\(.*\\)\\'" path) + (match-string 1 path))) + (path (if (not option) path + (substring path 0 (match-beginning 0))))) + (apply #'org-open-file + path + arg + (cond ((not option) nil) + ((string-match-p "\\`[0-9]+\\'" option) + (list (string-to-number option))) + (t (list nil option))))))) + (defun org-link-display-format (s) "Replace links in string S with their description. If there is no description, use the link target." -- 2.25.0