# Custom Roam-style link

**URL:** <https://org-roam.discourse.group/t/custom-roam-style-link/39>\
**Category:** Development\
**Created:** [May 4, 2020, 8:50am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39 "2020-05-04T08:50:21Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![nobiot](https://yyz2.discourse-cdn.com/free1/user_avatar/org-roam.discourse.group/nobiot/32/159_2.png) [@nobiot](https://org-roam.discourse.group/u/nobiot)\
**Post date:** [July 21, 2020, 11:25am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/41 "2020-07-21T11:25:52Z")

</div>

@santi-younger,  
For what it’s worth, I have been using my own personal plug-in / extension to enable markdown files to work with Org-roam (I call it “[Md-roam](https://github.com/nobiot/md-roam)”). It supports `[[file-name-without-extension]]` wiki-link syntax, and it can co-exists with Org files, as it respects Org Mode syntax when the buffer is an Org file. I didn’t have vimwiki in mind when I started it (I have just learned about it from you), so the wiki-link syntax may not be exactly the same. It’s been working well for me. It’s a personal project, so it might feel rough around edges (and far less ambitious than the feature suggested here), but used by some others, too. I suppose it might be something you could consider in your transition period.

---

<div class="post-metadata">

**Author:** ![santi-younger](https://yyz2.discourse-cdn.com/free1/user_avatar/org-roam.discourse.group/santi-younger/32/275_2.png) [@santi-younger](https://org-roam.discourse.group/u/santi-younger)\
**Post date:** [July 21, 2020, 1:18pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/42 "2020-07-21T13:18:52Z")

</div>

Thanks for that @nobiot I really appreciate the help. I’ll definitely get around to move my vim .md notes to emacs with Md-roam! Thank you for your hard work.

---

<div class="post-metadata">

**Author:** ![jethro](https://avatars.discourse-cdn.com/v4/letter/j/b5a626/32.png) [@jethro](https://org-roam.discourse.group/u/jethro)\
**Post date:** [August 1, 2020, 9:46am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/43 "2020-08-01T09:46:40Z")

</div>

Here’s a preview of what’s coming up in the PR, let me know what you think!

[![](https://global.discourse-cdn.com/free1/uploads/orgroam/original/1X/6ebf95c2bf42334e97fcdc6f4d4071baa99c8eec.jpeg "Org-roam fuzzy links UX preview") ](https://www.youtube.com/watch?v=v4fEwppIPhY)

---

<div class="post-metadata">

**Author:** ![scotto](https://avatars.discourse-cdn.com/v4/letter/s/b38774/32.png) [@scotto](https://org-roam.discourse.group/u/scotto)\
**Post date:** [August 1, 2020, 6:57pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/44 "2020-08-01T18:57:01Z")

</div>

I like the idea. But does override the standard org-mode internal like, which also has the `[[]]` syntax?

---

<div class="post-metadata">

**Author:** ![zaeph](https://yyz2.discourse-cdn.com/free1/user_avatar/org-roam.discourse.group/zaeph/32/764_2.png) [@zaeph](https://org-roam.discourse.group/u/zaeph)\
**Post date:** [August 1, 2020, 8:11pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/45 "2020-08-01T20:11:47Z")

</div>

@jethro’s implementation only changes the way you input the link: when you save, the links are resolved to their actual targets, either becoming a `file:`-link or `id:`-link. Technically, it overrides Org-mode’s default behaviour for `[[foo]]` links, but the same can be achieved with by typing `[[*foo]]` which will 1) create an ID for the headline `foo` if it doesn’t exist, and replace `[[*foo]]` with `[[id:…][foo]]`.

---

<div class="post-metadata">

**Author:** ![rodelrod](https://yyz2.discourse-cdn.com/free1/user_avatar/org-roam.discourse.group/rodelrod/32/184_2.png) [@rodelrod](https://org-roam.discourse.group/u/rodelrod)\
**Post date:** [August 1, 2020, 9:24pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/46 "2020-08-01T21:24:50Z")

</div>

Looks brilliant!

---

<div class="post-metadata">

**Author:** ![jethro](https://avatars.discourse-cdn.com/v4/letter/j/b5a626/32.png) [@jethro](https://org-roam.discourse.group/u/jethro)\
**Post date:** [August 2, 2020, 3:02am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/47 "2020-08-02T03:02:03Z")

</div>

> [@scotto](#):
>
> But does override the standard org-mode internal like, which also has the `[[]]` syntax?

Yes it does, but only within Org-roam files.

---

<div class="post-metadata">

**Author:** ![public\_image\_limited](https://avatars.discourse-cdn.com/v4/letter/p/5e9695/32.png) [@public\_image\_limited](https://org-roam.discourse.group/u/public_image_limited)\
**Post date:** [August 5, 2020, 9:02pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/48 "2020-08-05T21:02:37Z")

</div>

Hope this is the right place to chime in. I’d love to try any of these new link styles, but none of that works. I have org roam version 1.2.1 installed. If I disable company-org-roam, I lose all autocompletion. `company-capf` is one of the company backends, but there is no autocompletion. I can force completion with `M-x complete`. And even here, what is inserted is a file link. What am I making wrong?

---

<div class="post-metadata">

**Author:** ![bruce](https://avatars.discourse-cdn.com/v4/letter/b/ccd318/32.png) [@bruce](https://org-roam.discourse.group/u/bruce)\
**Post date:** [August 5, 2020, 10:45pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/49 "2020-08-05T22:45:46Z")

</div>

So it looks like you add the double-brackets, and then do a backspace to initiate the pop-up auto-completion. Is that correct?

Or is that just an artifact of the particular screen-cast?

It would be ideal if the auto-complete could pop-up immediately after entering the double-brackets.

---

<div class="post-metadata">

**Author:** ![jethro](https://avatars.discourse-cdn.com/v4/letter/j/b5a626/32.png) [@jethro](https://org-roam.discourse.group/u/jethro)\
**Post date:** [August 6, 2020, 1:26am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/50 "2020-08-06T01:26:18Z")

</div>

This is now merged in master.

> [@bruce](#):
>
> So it looks like you add the double-brackets, and then do a backspace to initiate the pop-up auto-completion. Is that correct?

Nope, I’m calling `company-complete` manually here, I don’t have my company auto-show suggestions.

> [@bruce](#):
>
> It would be ideal if the auto-complete could pop-up immediately after entering the double-brackets.

You can do this already, if you configure company this way:

```auto
(setq company-idle-delay 0
      company-minimum-prefix-length 0)
(push 'company-capf company-backends)

```

 ![company](https://global.discourse-cdn.com/free1/uploads/orgroam/original/1X/f8a2bab30fd306597cb46ddec41712e49f3db6cd.gif)

EDIT: the navigation in the gif is to the heading that was outside the screen recording

---

<div class="post-metadata">

**Author:** ![jethro](https://avatars.discourse-cdn.com/v4/letter/j/b5a626/32.png) [@jethro](https://org-roam.discourse.group/u/jethro)\
**Post date:** [August 6, 2020, 1:30am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/51 "2020-08-06T01:30:11Z")

</div>

Make sure you are on the latest commit, this came a while after 1.2.1.

---

<div class="post-metadata">

**Author:** ![public\_image\_limited](https://avatars.discourse-cdn.com/v4/letter/p/5e9695/32.png) [@public\_image\_limited](https://org-roam.discourse.group/u/public_image_limited)\
**Post date:** [August 6, 2020, 6:29am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/52 "2020-08-06T06:29:37Z")

</div>

Great, that works now!

Now I am actually working on a small “zettelbrowser”, which gathers some useful entry points and navigation for the zettelkasten. Currently, I can look at the 10 most linked files, the last modified files, etc. In particulat, for each zettel, I can look at the list of backlinks and “tolinks” (is this the word?), so I can kind of browse my notes. Internally, I use an SQL query which, among others, checks for links with the type “file”.

I will publish the project soon on github, but I am reluctant because of the amazing speed of development. And I wanted to integrate the fuzzy links. I see in the database, that the new link has its own type, “fuzzy”. There is no filename associated with it, just the title or the title with an asterisk and the heading. No file name. I would, of course, like to integrate this new link type into my zettelkasten tool. So I guess my questions are:

- Is it planned to keep this links plain “symbolic”, that is, that they are just names and the program has to look app the associated file by itself?

- If the links are supposed to be kept symbolic, is there an easy way to resolve them within SQL? Everything else seems to me very costly for “bulk” operations. I toyed around a bit, and for me, the difficulty is to split the symbol at the asterisk. We have to transform the column content `(name)*_` to `name` within the query. Up to now, my SQL queries just checked for equal file names to find links. Maybe it would make sense to save a copy of the link in new column in a normalized form (only the title, no asterisk); that would allow for an easy JOIN SQL query.

- Looking at the database, I also see that other, not-related links are also recognized as “fuzzy” and inserted in the database. In my case, I find an old zotxt link (“zotero://select/items…”) and internal org links ("[[\*Heading]]"). Maybe the mechanism which identifies the links before saving them should be more strict.

---

<div class="post-metadata">

**Author:** ![jethro](https://avatars.discourse-cdn.com/v4/letter/j/b5a626/32.png) [@jethro](https://org-roam.discourse.group/u/jethro)\
**Post date:** [August 7, 2020, 3:50am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/53 "2020-08-07T03:50:07Z")

</div>

> [@public\_image\_limited](#):
>
> Is it planned to keep this links plain “symbolic”, that is, that they are just names and the program has to look app the associated file by itself?

Yes. But the plan is to have them be fuzzy links only for a short while, there will be mechanisms in place to replace the fuzzy links with full links (file/id).

> [@public\_image\_limited](#):
>
> In my case, I find an old zotxt link (“zotero://select/items…”) and internal org links (“[[\*Heading]]”).

I don’t see a problem having extra things in the db. It’s also impossible to tell apart internal org links from Org-roam fuzzy links, since Org-roam replaces that behaviour entirely.

Don’t worry too much about the fuzzy links for now, until things settle.

---

<div class="post-metadata">

**Author:** ![public\_image\_limited](https://avatars.discourse-cdn.com/v4/letter/p/5e9695/32.png) [@public\_image\_limited](https://org-roam.discourse.group/u/public_image_limited)\
**Post date:** [August 7, 2020, 7:56am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/54 "2020-08-07T07:56:10Z")

</div>

> [@jethro](#):
>
> Don’t worry too much about the fuzzy links for now, until things settle.

Thanks for the answer!

It’s just that I don’t want my zettelkasten browser to break. Currently, I use one big query which gathers all informations I want per page (mtime, title, tags, etc.), it works surprisingly well and fast, and the system is built around this query. So introducing further joins and lookups might break that system.

---

<div class="post-metadata">

**Author:** ![santi-younger](https://yyz2.discourse-cdn.com/free1/user_avatar/org-roam.discourse.group/santi-younger/32/275_2.png) [@santi-younger](https://org-roam.discourse.group/u/santi-younger)\
**Post date:** [August 8, 2020, 3:12pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/55 "2020-08-08T15:12:05Z")

</div>

This is just amazing, thank you so much for your hard work!

---

<div class="post-metadata">

**Author:** ![alan](https://avatars.discourse-cdn.com/v4/letter/a/a87d85/32.png) [@alan](https://org-roam.discourse.group/u/alan)\
**Post date:** [August 9, 2020, 10:17pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/56 "2020-08-09T22:17:19Z")

</div>

This is great! I originally wanted fuzzy links but I couldn’t figure out how to adequately manipulate the default behavior of org 🙃

I haven’t dug into the code or db for managing headline id links yet. Is it necessary to resolve the fuzzy file+headline links into proper `id:` links in order for it to save the link to the db? Leaving a file-only link fuzzy works just fine, and the fuzzy file+headline can otherwise navigate correctly – I just don’t see the headline version in the backlinks. I expected the behavior to be the creation of an ID property under the headline upon file save, and the backlinks buffer to populate the same as if I had a proper `id:` link. Since it can auto-complete headlines in fuzzy form and navigate correctly without `id:` resolution, it seems like it would be trivial to create an ID property and update the db without requiring resolution from fuzzy to `id:`. The implementation of a fuzzy-upon-edit behavior probably supersedes this issue – do you think the editing functionality will be simple to do?

Replacing `roam:` with the fuzzy links also breaks the demo implementation of [Add Link-tags feature](https://org-roam.discourse.group/t/add-link-tags-feature/171/23), so I need to come up with an alternative! Would something like link-tags be related to the implementation of [link types](https://github.com/org-roam/org-roam/pull/1009)? Except I don’t really want to define a new link type – simply annotate existing org-roam links. It wouldn’t be difficult to parse an implementation of link-tags out of the link-description section in any of fuzzy, file, or id types, but I would rather refactor with the most “correct” design 😉

---

<div class="post-metadata">

**Author:** ![jethro](https://avatars.discourse-cdn.com/v4/letter/j/b5a626/32.png) [@jethro](https://org-roam.discourse.group/u/jethro)\
**Post date:** [August 10, 2020, 2:00pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/57 "2020-08-10T14:00:21Z")

</div>

> [@alan](#):
>
> I expected the behavior to be the creation of an ID property under the headline upon file save, and the backlinks buffer to populate the same as if I had a proper `id:` link.

This is the default behaviour now.

> [@alan](#):
>
> Since it can auto-complete headlines in fuzzy form and navigate correctly without `id:` resolution, it seems like it would be trivial to create an ID property and update the db without requiring resolution from fuzzy to `id:`

The db is only a cache of the current contents in the Org files, so this would be really strange.

> [@alan](#):
>
> The implementation of a fuzzy-upon-edit behavior probably supersedes this issue – do you think the editing functionality will be simple to do?

Not sure, but doesn’t sound terribly hard.

> [@alan](#):
>
> Replacing `roam:` with the fuzzy links also breaks the demo implementation of [Add Link-tags feature](https://org-roam.discourse.group/t/add-link-tags-feature/171/23), so I need to come up with an alternative! Would something like link-tags be related to the implementation of [link types](https://github.com/org-roam/org-roam/pull/1009)? Except I don’t really want to define a new link type – simply annotate existing org-roam links. It wouldn’t be difficult to parse an implementation of link-tags out of the link-description section in any of fuzzy, file, or id types, but I would rather refactor with the most “correct” design

For this, we need to extend the spec of the fuzzy links with additional separators. If we were to go with org’s link types, that restricts us to only 1 link tag per link. The tags will need to be kept in the link description upon resolution. We can come up with a simple proposal, like

```auto
[[Title*Headline::tag1::tag2]]

```

Then we can consider implementing this, but I’m wondering how much interest there is in this feature.

---

<div class="post-metadata">

**Author:** ![alan](https://avatars.discourse-cdn.com/v4/letter/a/a87d85/32.png) [@alan](https://org-roam.discourse.group/u/alan)\
**Post date:** [August 10, 2020, 4:25pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/58 "2020-08-10T16:25:22Z")

</div>

> [@jethro](#):
>
> This is the default behaviour now.

It is the default behavior with `(setq org-roam-auto-replace-fuzzy-links t)`, but when `nil` org-roam does not create an ID and save a backlink. If the fuzzy link is only for a file (no headline), then a backlink is created like normal even without resolving the link to a full `file:` link.

> [@jethro](#):
>
> The db is only a cache of the current contents in the Org files, so this would be really strange.

Perhaps I am not clear. Fuzzy file+headline links work as you would expect without needing replacement by true `id:` links, except that no backlink is saved. Fuzzy file links work, and save a backlink even without replacement by true `file:` links. Since all of the machinery is already in place to resolve id from fuzzy, I was wondering if it possible to save backlinks while leaving file+headline fuzzy.

It is just about preference and ease of editing. Making a fuzzy-on-edit behavior solves the issue entirely, but without having looked into the updated code at all I didn’t know if it would be simpler to save backlinks for fuzzy file+headline the same way as fuzzy file-only links.

> [@jethro](#):
>
> For this, we need to extend the spec of the fuzzy links with additional separators. If we were to go with org’s link types, that restricts us to only 1 link tag per link. The tags will need to be kept in the link description upon resolution. We can come up with a simple proposal, like
> 
> ```auto
> [[Title*Headline::tag1::tag2]]
> 
> ```
> 
> Then we can consider implementing this, but I’m wondering how much interest there is in this feature.

Yes, the most straightforward solution is to handle tags in the description section. This is an important personal use case for me – I’m going to do it one way or another 😆 I’m happy to share the end result, but I don’t think this has the same level of interest that would warrant inclusion in core org-roam at all. I am only wondering what your opinions are for implementing something with this kind of custom functionality now that a lot more development has been done around links (if there is a more or less “correct” way to maintain tighter integration with core development so that I don’t end up with conflicts).

It sounds like simply parsing link descriptions will be the way to go. Or else I don’t think it would be very difficult to come up with some post-link parsing scheme like `[[link]]::tag::` and hooks/advice that would potentially have minimal need to integrate with the rest of org-roam.

---

<div class="post-metadata">

**Author:** ![jethro](https://avatars.discourse-cdn.com/v4/letter/j/b5a626/32.png) [@jethro](https://org-roam.discourse.group/u/jethro)\
**Post date:** [August 11, 2020, 5:25am UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/59 "2020-08-11T05:25:02Z")

</div>

> [@alan](#):
>
> Fuzzy file+headline links work as you would expect without needing replacement by true `id:` links, except that no backlink is saved. Fuzzy file links work, and save a backlink even without replacement by true `file:` links. Since all of the machinery is already in place to resolve id from fuzzy, I was wondering if it possible to save backlinks while leaving file+headline fuzzy.

Headline backlinks work via an ID, in the `to` column of the links table, so saving these file+headline links aren’t so easy. It’s possible to do this lookup on the fly, but that would make cache builds much more expensive. Hopefully the fuzzy-on-edit behaviour alleviates the bulk of the issue, although I’m wondering how often you edit your links. I don’t do this at all.

> [@alan](#):
>
> It sounds like simply parsing link descriptions will be the way to go. Or else I don’t think it would be very difficult to come up with some post-link parsing scheme like `[[link]]::tag::` and hooks/advice that would potentially have minimal need to integrate with the rest of org-roam.

I’m fine pulling this into Org-roam’s core, it sounds useful, and this will require an additional column in the links table anyway. I just don’t want to overload the link description with too many things, so this might be the last of it.

---

<div class="post-metadata">

**Author:** ![alan](https://avatars.discourse-cdn.com/v4/letter/a/a87d85/32.png) [@alan](https://org-roam.discourse.group/u/alan)\
**Post date:** [August 11, 2020, 4:04pm UTC](https://org-roam.discourse.group/t/custom-roam-style-link/39/60 "2020-08-11T16:04:35Z")

</div>

> [@jethro](#):
>
> Hopefully the fuzzy-on-edit behaviour alleviates the bulk of the issue, although I’m wondering how often you edit your links. I don’t do this at all.

It would indeed eliminate the issue entirely. In practice I edit them significantly less than my nagging on this issue implies 😄 It is just a nicety. I typically go through a write/save/edit/extend/summarize process multiple times with some academic notes. For some reason deleting a link entirely and entering a new one bothers me while writing, even though it’s likely objectively simpler/better. I haven’t gotten to really use the new fuzzy links + headlines and nested captures, so my link-breaking edits may be even less now. Since I don’t have any plans to move away from org-roam, the automatic conversion from fuzzy to `file:` or `id:` feels incongruent. I would just prefer to leave them all fuzzy, but this is strictly a personal issue.

> [@jethro](#):
>
> I’m fine pulling this into Org-roam’s core, it sounds useful, and this will require an additional column in the links table anyway. I just don’t want to overload the link description with too many things, so this might be the last of it.

Sounds good! I agree that I would prefer not to overload the description – the benefit of a custom link was that tags could live in the path and be hidden if desired. Any opinion on post-bracket parsing? Other than a design/style decision about potentially multi-word tags, I don’t think it would be very difficult or cumbersome. It would be link-type agnostic, and leave the link description parsing untouched.

I’ll start putting something together in the next week or two.

[Previous page](https://org-roam.discourse.group/t/custom-roam-style-link/39.md?page=2)

[Next page](https://org-roam.discourse.group/t/custom-roam-style-link/39.md?page=4)
