(This post in Org format -> [https://github.com/tonyaldon/posts](https://github.com/tonyaldon/posts))
Wait a minute! Are you telling me that the URL `https://orgmode.org/worg/` used as property value in a property drawer is not a link?
Yes!
Even if clicking the URL opens it in my browser.
Yes!
Even if the URL is displayed like any other links in the buffer (using the face `org-link`).
Yes!
But, if the URL `https://orgmode.org/worg/` is used in a paragraph, it is a link.
Yes!
WHY?
Because, while in both cases, in a property drawer and in a paragraph, the URL `https://orgmode.org/worg/` is matched by the regexp `org-link-any-re`:
1. in a property drawer (specifically in a `node-property`), the URL `https://orgmode.org/worg/` is not parsed as a `link` object by the Org parser (but only as the `:value` of the `node-property` object containg it) and,
2. in a paragraph, the URL `https://orgmode.org/worg/` is parsed as a `link` object by the Org parser.
THIS IS THE ORG PARSER THAT DICTATES THE RULES :)
END!!!
Maybe not.
Let's build some examples to get an idea of this difference and what it implies.
To falicilate our discussion let's call:
1. R-LINKS the parts of an org-mode buffer that match the regexp `org-link-any-re`,
2. P-LINKS the parts of an org-mode buffer that are parsed as `link` objects by the Org parser.
In an org-mode buffer, the parts that match the regexp `org-link-any-re`, the R-LINKS, are all:
1. "activated", meaning they have there text properties set by the function `org-activate-links` (triggered by `jit-lock` mechanism),
2. and depending on the place of the function `org-activate-links` in the let binded list `org-font-lock-extra-keywords` in the function `org-set-font-lock-defaults` (used to set font lock defaults for the current buffer), the face of those parts is either the face `org-link`, another face or `org-link`'s face merged with another face.
For instance, we can look at the text properties of the URL `https://orgmode.org/worg/` used in different places (comment, property drawer and paragraph) in the following org-mode buffer:
# Worg's URL in a comment: https://orgmode.org/worg/
* Heading
:PROPERTIES:
:MY_URL: https://orgmode.org/worg/
:END:
The same URL to Worg in a paragraph: https://orgmode.org/worg/.
by evaluating (with `pp-eval-expression`) the form
(text-properties-at (point))
with the point on top of each URL.
We obtains the 3 following lists:
;; URL in comment
(font-lock-multiline t
keymap (keymap
(follow-link . mouse-face)
(mouse-3 . org-find-file-at-mouse)
(mouse-2 . org-open-at-mouse))
mouse-face highlight
face font-lock-comment-face
org-category "links"
font-lock-fontified t
help-echo "LINK: https://orgmode.org/worg/"
fontified t
htmlize-link (:uri "https://orgmode.org/worg/"))
;; URL in a property drawer
(font-lock-multiline t
keymap (keymap
(follow-link . mouse-face)
(mouse-3 . org-find-file-at-mouse)
(mouse-2 . org-open-at-mouse))
mouse-face highlight
face org-link
org-category "links"
help-echo "LINK: https://orgmode.org/worg/"
fontified t
htmlize-link (:uri "https://orgmode.org/worg/")
rear-nonsticky (mouse-face highlight keymap invisible intangible help-echo org-linked-text htmlize-link))
;; URL in a paragraph
(font-lock-multiline t
keymap (keymap
(follow-link . mouse-face)
(mouse-3 . org-find-file-at-mouse)
(mouse-2 . org-open-at-mouse))
mouse-face highlight
face org-link
org-category "links"
help-echo "LINK: https://orgmode.org/worg/"
fontified t
htmlize-link (:uri "https://orgmode.org/worg/")
rear-nonsticky (mouse-face highlight keymap invisible intangible help-echo org-linked-text htmlize-link))
We observe that:
1. those 3 URLs can be open with `org-open-at-mouse` by clicking (with `mouse-2`) them (due to the text property `keymap`),
2. when we over the mouse on them (the 3), we see the help echo showing `LINK: https://orgmode.org/worg/`,
3. the face (with Emacs default settings) of the URL in the comment is `font-lock-comment-face`, and the face of the URL in the property drawer and in the paragraph have the same value, the face `org-link`.
Now, if we parse (with the Org parser) the same previous org-mode buffer by evaluating (with `pp-eval-expression`) the form:
(org-element-parse-buffer)
we obtain the following structure (some parts are skipped):
(org-data
(...)
(section
(...)
(comment
(...
:value "Worg's URL in a comment: https://orgmode.org/worg/"
...)))
(headline
(...)
(section
(...)
(property-drawer
(...)
(node-property
(:key "MY_URL"
:value "https://orgmode.org/worg/"
...)))
(paragraph
(...)
#("The same URL to Worg in a paragraph: " 0 37 (:parent #3))
(link
(:type "https"
:path "//orgmode.org/worg/"
:format plain
:raw-link "https://orgmode.org/worg/"
:application nil
:search-option nil
...))
#(".\n" 0 2 (:parent #3))))))
We observe that the only URL that is parsed as a `link` object is the URL inside the paragraph. The others are values of the property `:value` of a `comment` element for the first one and a `node-property` element for the second one.
So, some R-LINKS are not P-LINKS.
Now, if we look at the function `org-element-link-parser`
(defun org-element-link-parser ()
"..."
(catch 'no-object
(let (...)
(cond
((and org-target-link-regexp
(save-excursion (or (bolp) (backward-char))
(looking-at org-target-link-regexp)))
;; ...
)
((looking-at org-link-bracket-re)
;; ...
)
((looking-at org-link-plain-re)
;; ...
)
((looking-at org-link-angle-re)
;; ...
)
(t (throw 'no-object nil)))
(list 'link (list ...)))))
which is responsible to parse `link` objects, and we look at the function `org-link-make-regexps` which is responsible to set the variable `org-link-any-re` (among other link related variables):
(defun org-link-make-regexps ()
"..."
(let (...)
(setq
;; ...
org-link-any-re (concat "\\(" org-link-bracket-re "\\)\\|\\("
org-link-angle-re "\\)\\|\\("
org-link-plain-re "\\)"))))
we see that, except for radio target links (`<<...>>`), P-LINKS are also R-LINKS.
So someone who implements a command that operates on "links" must decide:
1. whether the command is aimed at P-LINKS only (which is the case of the command `org-next-link` bound by default to `C-c C-x C-n`),
2. or at all R-LINKS more broadly (which is the case of `org-open-at-point` bound by default to `C-c C-o`).
We can check this by calling once the command `org-next-link` with the point at the beginning of the previous org-mode buffer. We see that the point moves to the third URL in the buffer, the only one that is a P-LINK.
And if we call the command `org-open-at-point` with the point on each URL, we see that the URL `https://orgmode.org/worg/` is open 3 times in our browser. This is because the command `org-open-at-point` provides support for R-LINKS that are not P-LINKS.
We can see this by looking at the source:
(defun org-open-at-point (&optional arg)
"..."
(interactive "P")
;; ...
(unless (run-hook-with-args-until-success 'org-open-at-point-functions)
(let* ((context
(org-element-lineage
(org-element-context)
'(citation citation-reference clock comment comment-block
footnote-definition footnote-reference headline
inline-src-block inlinetask keyword link node-property
planning src-block timestamp)
t))
(type (org-element-type context))
...)
(cond
((not type) (user-error "No link found"))
;; No valid link at point. For convenience, look if something
;; looks like a link under point in some specific places.
((memq type '(comment comment-block node-property keyword))
(call-interactively #'org-open-at-point-global))
;; ...
((eq type 'link) (org-link-open context arg))
;; ...
(t (user-error "No link found")))))
(run-hook-with-args 'org-follow-link-hook))
Specifically, the command `org-open-at-point`, for the R-LINKS that are part of one of the following org elements `comment`, `comment-block`, `node-property`, `keyword`, delegate the action to the command `org-open-at-point-global`.
If you want to know more about the command `org-open-at-point` you can read this post: [Search options in file links | link abbreviations | COME WITH ME on this JOURNEY into the heart of the command org-open-at-point](https://www.reddit.com/r/emacs/comments/tw3fpu/search_options_in_file_links_link_abbreviations/).
WE ARE DONE!!!