reddit / emacs

Did you know that Org links in property drawers are not links?

tonyaldon · 2022-04-09 06:45
(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!!!
lilytex · 2022-04-09 08:49
Yes! Indeed i think it would be a good implementation of "type" links, similar to https://github.com/zadam/trilium org-edna links work this way and allow yo to define triggers and blockers for a task in this way that do not count as backlinks in org-roam since they are not proper org links. Karl Voit explains it in this post: https://karl-voit.at/2020/08/14/project-mgt-draft/
xenodium · 2022-04-09 08:50
Happy Cake day Tony! Nice to see you've continued producing content. Thank you.
tonyaldon · 2022-04-09 09:54
Thank you :) I'm glad that you read it. ps: I like the gifts you use in your blog https://xenodium.com/
tonyaldon · 2022-04-09 10:05
>Yes! Indeed i think it would be a good implementation of "type" links, similar to [https://github.com/zadam/trilium](https://github.com/zadam/trilium) I don't understand what you want to say. Can you be more specific? In my writings, I never say that something is good or bad. I just try to show how things work and I like to show how they are implemented using code snippets. Nothing beyond that. I don't share my opinion about the design nor the implementation. Thank you for sharing the article.
lilytex · 2022-04-09 17:22
Yes, I didn't translate clearly at all what was in my mind and ended up rambling incoherently. As an example of this fact, org-edna defines new :BLOCKER: and :TRIGGER: properties that allow you to define dependencies between tasks and trigger todo changes in multiple tasks when you change the todo state of a given one, such as explained in Karl's post. Another example of links being in property drawers is that, when using the org-roam backlink feature, these links inside property drawers from org-edna are not considered backlinks. The backlinks of a given org-mode node are all the nodes that link back to the former. Finally, "BLOCKER" and "TRIGGER" can be thought of as "types" of links. I was introduced by a friend to [https://github.com/zadam/trilium](https://github.com/zadam/trilium) which takes this concept of "types" of links even further, e.g. [https://github.com/zadam/trilium/wiki/Relation-map](https://github.com/zadam/trilium/wiki/Relation-map)
tonyaldon · 2022-04-09 17:55
Thank u/lilytex for the clarification and the link to the wiki on Relation map. Have a nice day :)
arthurno1 · 2022-04-09 18:14
> Did you know that Org links in property drawers are not links? No, they are not links, they are URLs 😀. I hope you don't mind, but that is quite a lengthy post just to say that an [URL is not same as a link]( https://www.geeksforgeeks.org/difference-between-url-and-link/). Yes different pieces of org process URLs differently, which is quite natural.
tonyaldon · 2022-04-10 08:28
Thank you for your comment u/arthurno1, it shows that my post is not as clear as I thought. >No, they are not links, they are URLs 😀. My point is not to say that something is not a link but an URL. My point is to DIFFERENTIATE between: 1. parts of an org buffer that match the regexp `org-link-any-re` and, 2. `link` objects defined by the Org Parser. This has nothing to do with URLs. It has to do with how the Org Parser decides if an expression that matches `org-link-any-re` should be a link or not. In the post, I could have replace the URL `https://orgmode.org/worg/` by: * `[[file:/some-path-to/my-file.org]]` * `[[help:org-link-any-re]]`, * `[[info:org#Hyperlinks]]`, * etc. I hope this clarify my point. I'll do a better job next time. >[URL is not same as a link](https://www.geeksforgeeks.org/difference-between-url-and-link/) Thanks for sharing this link, but note that in the post I never refers to the html elements. If you are interested in Hyperlinks (which are not restricted to HTML nor org-mode), I encourage you to read: * [https://en.wikipedia.org/wiki/Hyperlink](https://en.wikipedia.org/wiki/Hyperlink) * [https://en.wikipedia.org/wiki/Hypertext](https://en.wikipedia.org/wiki/Hypertext) * [https://en.wikipedia.org/wiki/Texinfo](https://en.wikipedia.org/wiki/Texinfo) Have a nice day ;)
WikiSummarizerBot · 2022-04-10 08:28
**[Hyperlink](https://en.wikipedia.org/wiki/Hyperlink)** >In computing, a hyperlink, or simply a link, is a reference to data that the user can follow by clicking or tapping. A hyperlink points to a whole document or to a specific element within a document. Hypertext is text with hyperlinks. The text that is linked from is called anchor text. **[Hypertext](https://en.wikipedia.org/wiki/Hypertext)** >Hypertext is text displayed on a computer display or other electronic devices with references (hyperlinks) to other text that the reader can immediately access. Hypertext documents are interconnected by hyperlinks, which are typically activated by a mouse click, keypress set, or screen touch. Apart from text, the term "hypertext" is also sometimes used to describe tables, images, and other presentational content formats with integrated hyperlinks. Hypertext is one of the key underlying concepts of the World Wide Web, where Web pages are often written in the Hypertext Markup Language (HTML). **[Texinfo](https://en.wikipedia.org/wiki/Texinfo)** >Texinfo is a typesetting syntax used for generating documentation in both on-line and printed form (creating filetypes as dvi, html, pdf, etc. , and its own hypertext format, info) with a single source file. It is implemented by a computer program released as free software of the same name, created and made available by the GNU Project from the Free Software Foundation. The main purpose of Texinfo is to provide a way to easily typeset software manuals. ^([ )[^(F.A.Q)](https://www.reddit.com/r/WikiSummarizer/wiki/index#wiki_f.a.q)^( | )[^(Opt Out)](https://reddit.com/message/compose?to=WikiSummarizerBot&message=OptOut&subject=OptOut)^( | )[^(Opt Out Of Subreddit)](https://np.reddit.com/r/emacs/about/banned)^( | )[^(GitHub)](https://github.com/Sujal-7/WikiSummarizerBot)^( ] Downvote to remove | v1.5)