Automatically insert a node after its first insertion

I explain the title:

When we type a link to another node in a node, we have to insert it with the command “org-roam-node-insert” or by using company (and wait a little while before pressing return).

The “problem” is the following:
When we write a link to node B in node A, it may happen several times. So I want, just by writing the name of my concept B, that it automatically inserts it. (kind of like the “Radio Targets” in org-mode).

This would further remove the friction when writing things.

Of course, I don’t know if this is possible, that’s why I ask this question :wink:

Thanks in advance for your answers

I can think of some approaches that may get closer to what you are going for. It’s a little difficult to define what exactly you want to do.

I’d simply copy and paste the “first insertion”; no need to build anything custom, and yet saves time – I guess that’s what you wish to get as an outcome: save some time.

If you fancy more, you could have a custom function to automatically put the “first insertion” into the kill-ring or a custom variable, and then yank it.

If you want to have multiple of “first insertions” (e.g. the first insertion for each of links to concepts A, B, C, D), then it starts to get more complex. If this is the case, you could keep track of the list of the names of concepts you have inserted and corresponding links in a custom local variable. You could then get a function to regex each of the names and replace them with their respective link on save, for example.

Not sure if you have need for this complexity. You would probably not want to persist the list across Emacs session – another layer of complexity.

It’s a little difficult to define what exactly you want to do.

I want almost the same functionality of Radio Targets of org.

Imagine you write a node. In this node, you make a link to “another node” with the command org-roam-node-insert.
Now that it has been done once, you just need to write “another node”, and then the “another node” become “[[id:id to another node][another node]]” automatically.

But yes, this should work for any node already inserted, not just for the last one.

If you want to have multiple of “first insertions” (e.g. the first insertion for each of links to concepts A, B, C, D), then it starts to get more complex. If this is the case, you could keep track of the list of the names of concepts you have inserted and corresponding links in a custom local variable. You could then get a function to regex each of the names and replace them with their respective link on save, for example.

That can do the job, and I think it’s a good idea.
I’m not in a hurry right now, but when I get the feature done, I’ll post it here.

Not sure if you have need for this complexity. You would probably not want to persist the list across Emacs session – another layer of complexity.

I think that a simple hook can make the job. Not sure about that, but I will try with.

Thank you for your answer !

You kind of got it already with Org-roam. Turn off org-roam-completion-everywhere, and turn on org-roam-link-auto-replace. Then you can enter[[roam: concept name]]; on save, this gets changed to an ID link. You might like to have a custom function to just insert [[roam: |]] and move the cursor to where “|” is. Company or Corfu will work for this too.

Ho your tip is cool. I was going to say my problem was solved… but i still have to call a function. whether it’s org-roam-node-find or the one that lets me insert [[roam:]], I still have to remember to call that function, and therefore to insert a link.
Ideally, I’d just like to call the insert function only one time to “make emacs understand” that when I write this word/term, it will insert the link by itself the next times, without even calling any command.

But I still find your tip cool x)

Not necessarily.

The code below lets you type “[[” and then Emacs automatically adds “[[roam:”. Effectively this lets you just type “[[concept” to turn it into a link to an node for “concept”. See the animation below. I’m just typing and not calling a command. In the end I just quickly save the buffer to turn it into an ID link to the node. The cursor goes back to the beginning of the word, which is a bit of friction, but I believe that can also be fixed rather easily (depending on what other configurations you have, etc.).

I did this in 15 minutes in my lunch time so a bit rough, but this might get you closer to what you want without a significant amount of code. If this does not look promising, you can just disregard it, too. I’m just showing a different approach with only a simple change, leveraging as much built-in features as possible.

It works with the built-inelectric-pair-mode to auto-insert the closing brackets “]]”, and org-roam-link-auto-replace as I suggested above.

2022-07-07_07-41-52

  ;;; intended to be used with electric-pair-mode
  (defun my/insert ()
    (when (looking-back "\\[\\[" (- (point) 2))
      (insert "roam:")))

  ;;; To add
  (add-hook 'post-self-insert-hook #'my/insert 'APPEND)

  ;;; To remove
  ;; (remove-hook 'post-self-insert-hook #'my/insert)

Hmm I see, thank you for your answer and all its tips.

It sounds very practical.
I’m quibbling, but I think I have a “better” solution:

When inserting (the first time) an “abc” concept, I store its titles in a list (local variable).

Then, as soon as I rewrite “abc”, I replace “abc” by “[[id:theid][abc]]”, because “abc” is present in my list.

I think this will do the trick, I’ll post the solution here when I’ve done it.
Do you think this is a good idea?

Perhaps. I don’t have the same need so I can’t judge. I would just suggest that you trust your own judgement.

1 Like