(defun org-link-open (link &optional arg)
"Open a link object LINK.
ARG is an optional prefix argument. Some link types may handle
it. For example, it determines what application to run when
opening a \"file\" link.
Functions responsible for opening the link are either hard-coded
for internal and \"file\" links, or stored as a parameter in
`org-link-parameters', which see."
(let ((type (org-element-property :type link))
(path (org-element-property :path link)))
(pcase type
;; Opening a "file" link requires special treatment since we
;; first need to integrate search option, if any.
("file"
(let* ((option (org-element-property :search-option link))
(path (if option (concat path "::" option) path)))
(org-link-open-as-file path
(pcase (org-element-property :application link)
((guard arg) arg)
("emacs" 'emacs)
("sys" 'system)))))
;; Internal links.
((or "coderef" "custom-id" "fuzzy" "radio")
(unless (run-hook-with-args-until-success 'org-open-link-functions path)
(if (not arg) (org-mark-ring-push)
(switch-to-buffer-other-window (org-link--buffer-for-internals)))
(let ((destination
(org-with-wide-buffer
(if (equal type "radio")
(org-link--search-radio-target path)
(org-link-search
(pcase type
("custom-id" (concat "#" path))
("coderef" (format "(%s)" path))
(_ path))
;; Prevent fuzzy links from matching themselves.
(and (equal type "fuzzy")
(+ 2 (org-element-property :begin link)))))
(point))))
(unless (and (<= (point-min) destination)
(>= (point-max) destination))
(widen))
(goto-char destination))))
(_
;; Look for a dedicated "follow" function in custom links.
(let ((f (org-link-get-parameter type :follow)))
(when (functionp f)
;; Function defined in `:follow' parameter may use a single
;; argument, as it was mandatory before Org 9.4. This is
;; deprecated, but support it for now.
(condition-case nil
(funcall (org-link-get-parameter type :follow) path arg)
(wrong-number-of-arguments
(funcall (org-link-get-parameter type :follow) path)))))))))