In my many attempts to use org-roam the sidebar buffer with the backlinks was always completely useless. That is because is seems to display the entirety of a heading. My headings are usually long, which means that the sidebar is always completely occupied by just one backlink. I never found a solution. Now it occurred me that I may be doing something wrong. Am I suppose to create a smaller heading where I put my link? I kinda like just linking mid text so the link integrates with my writing, but is that wrong for me to do?
For Org-roam and Emacs in general, there is rarely a case where you are doing something wrong. The question for you is:
- What does it look like now?
- What do you want it to look like for it to be useful for you?
This is awesome, thanks!
For me the sidebar should have a limit for how much of a node it would display. So instead of showing the entire heading, it might show at most 90 characters from each. Ideally, however, it would be best if it could show the context where the link is situated. So in a text like this:
Phasellus ultrices nunc ac mi varius, sed laoreet dolor fringilla. Vivamus non MY SUPER COOL LINK, pretium auctor mauris. Donec id orci ipsum. Nulla interdum arcu nec efficitur viverra. Duis imperdiet sapien at sapien ullamcorper imperdiet.
The sidebar might show something like this:
varius, sed laoreet dolor fringilla. Vivamus non MY SUPER COOL LINK, pretium auctor mauris. Donec id orci ipsum. Nulla
This is 50 characters before the link and 50 characthers after.
IDK, just an idea…
Anyway, if that is not possible, than simply displaying only the first 100 characters of the heading would be great…
Try this
(defun org-roam-preview-default-function ()
"Return the preview content at point.
This function returns the text 50 chars before and 60 chars after
the beginning of the link (the 60 char after includes the link's
length itself)."
(let ((beg (save-excursion
(backward-char 50)
(point)))
(end (save-excursion
(forward-char 60)
(point))))
(string-trim (buffer-substring-no-properties beg end))))
You can also do the same thing without overriding the function that comes with Org-roam. Create a function with your name and set it to org-roam-preview-function
, like this:
(setopt org-roam-preview-function #'my-org-roam-preview-function)
;; You can use `setq' if you like. It is a customizing variable, so use
;; your preferred way to customize it. (See the screen image below)
Include more chars after (increase the number to one greater than 60) to include at least the closing brackets. From your screen shot, it looks like your links are cut off on the right.
@alienbogart
Alternative to my suggestion above, this probably works on your end.
I suggest you try to understand the code and adapt to your own Emacs. Both of my suggestions work on my end. I left some comments in the code, too. Good luck.
(defun org-roam-preview-default-function ()
"Return the preview content at point.
This function returns the text 50 chars before and 50 chars after
the beginning and end of the link respectively."
(let ((beg (save-excursion
;; The function gets called while the point is at the
;; beginning of the link (this is what Org-roam does).
(backward-char 50)
(point)))
(end (save-excursion
;; This `res-research-forward' moves the point to
;; the end of link.
(re-search-forward org-link-bracket-re nil :noerror)
(forward-char 50)
(point))))
(string-trim (buffer-substring-no-properties beg end))))
I was 100% trying to understand the code since before I even made the question
I am not a programmer. I am not an IT professional. I am a writer, and the thing I write is fiction. I wish to use Roam as a creativity tool. I know how to follow instructions, but my abilities as a programmers are basically zero.
Thank you for your answer and patience. I think it’s working now.
Which one did you choose in the end?
I only briefly tested but both are working really well. I’ll have to test for longer to understand which is better for me. Just adding more chars to the first like you say worked fine. And the other function worked fine as well. Honestly I think you did a really good job so it’s difficult to decide, they’re both really great.
Okay thank you. The latter one guarantees that it is always 50 (or any) characters from the end of the link. From this perspective, it’s more sophisticated than the former — when it works.
The former is crude and simpler… So less chance of not working. But if your link is really long, you may have the same situation of the tail of link cut off, because the count always starts from the beginning of link…
If I were in your shoes, I would choose crude and simple — it works and easier to fix by adjusting the number.
I would like to jump in quick here and suggest to do (save-match-data
before running
re-search-forward org-link-bracket-re nil :noerror
This will prevent overwriting the match data. I feel your second option is much better @nobiot - such dynamic variability would go a long way in giving the user the peace of mind about having arbitary link descriptions
Currently I also see the following problem - it does not differentiate between what comes first - 50 chars after the link ends or a next heading. 50 chars before or the heading beginning.
Another problem - what if the buffer ends before the next 50 chars - the function will fail silently without any warning.
I would in my case modify the behaviour as such –
(defun org-roam-preview-default-function ()
"Return the preview content at point.
This function returns the text 50 chars before and 50 chars after
the beginning and end of the link respectively. If the next heading
is less than 50 characters away, it stops at the next heading."
(let ((beg (save-excursion
(if (>= (- (point) 50) (save-excursion (org-roam-end-of-meta-data t) (point)))
(backward-char 50)
(org-roam-end-of-meta-data t))
(point)))
(end (save-excursion
(save-match-data
(re-search-forward org-link-bracket-re nil :noerror)
(if (<= (+ (point) 50) (save-excursion (org-next-visible-heading 1) (point)))
(forward-char 50)
(org-next-visible-heading 1))
(point)))))
(string-trim (buffer-substring-no-properties beg end))))
This makes the function more robust, failure proof - albeit at the cost of complexity.
Thanks and best.
I present a refactored version - this is the same as my previous solution - but much cleaner and avoids redundant computation.
(defun org-roam-preview-default-function ()
"Return the preview content at point.
This function returns the text 50 chars before and 50 chars after
the beginning and end of the link respectively. If the next heading
is less than 50 characters away, it stops at the next heading."
(let* ((_beg (save-excursion (org-roam-end-of-meta-data t) (point)))
(_end (save-excursion (org-next-visible-heading 1) (point)))
(beg (if (>= (- (point) 50) _beg) (progn (save-excursion (backward-char 50) (point)))
_beg))
(end (if (<= (+ (point) 50) _end) (progn (save-excursion (save-match-data (re-search-forward org-link-bracket-re nil :noerror) (forward-char 50) (point))))
_end)))
(string-trim (buffer-substring-no-properties beg end))))
also OP @alienbogart consider changing post title to something like “'How to configure org-roam-buffer char length?`” and move to Guides and Howto section instead of Troubleshoot for the benefit of future readers.
Thanks and best.
I have thought about this a little bit more, I think a much simpler solution could be implemented - namely that which is already implemented for unlinked references - to just get the immediate line where the link is embedded.
For this, youd have to agree not to think in terms of characters back and forth - but in terms of lines
(defun custom/org-roam-preview-default-function ()
"Return the preview content at point.
This function returns the text of the immediate line(s) where the link is located."
(let ((beg (save-excursion
(org-beginning-of-line 1) (point)))
(end (save-excursion
(org-end-of-line 1) (point))))
(string-trim (buffer-substring-no-properties beg end))))
(setopt org-roam-preview-function #'custom/org-roam-preview-default-function)
To have say more than one line showing - change the 1’s to some N where N-1 lines back and forth would be shown
For example to show 2 lines before and 2 lines after do
(defun custom/org-roam-preview-default-function ()
"Return the preview content at point.
This function returns the immediate line(s) where the link is located."
(let ((beg (save-excursion
(org-beginning-of-line -1) (point)))
(end (save-excursion
(org-end-of-line 3) (point))))
(string-trim (buffer-substring-no-properties beg end))))
since
-1-1 = -2 & 3-1 =2
Therefore the following
:PROPERTIES:
:ID: 20240922T081550.535686
:END:
#+title: target
* h1
-4
-3
-2
-1
[[id:20240922T081423.122777][source]]
1
2
3
4
[[id:20240922T081423.122777][source]]
* h2
would show up as this
Backlinks (2)
target (h1)
-2
-1
[[id:20240922T081423.122777][source]]
1
2
target (h1)
3
4
[[id:20240922T081423.122777][source]]
* h2
This is a much simple solution.
I have tested all of the functions on Doom Emacs. Only one didn’t work at all, but in was honesty there were so many that I am little confused which one it was right now. I had been using this function until now:
(defun my-org-roam-preview-default-function2 ()
(let ((beg (save-excursion
(backward-char 50)
(point)))
(end (save-excursion
(forward-char 100)
(point))))
(string-trim (buffer-substring-no-properties beg end))))
It was not working perfectly, some links still showed up with all the markup visible, but mostly it worked.
I have now tested this new function that was presented as another solution:
(defun custom/org-roam-preview-default-function ()
"Return the preview content at point.
This function returns the immediate line(s) where the link is located."
(let ((beg (save-excursion
(org-beginning-of-line -1) (point)))
(end (save-excursion
(org-end-of-line 3) (point))))
(string-trim (buffer-substring-no-properties beg end))))
I have tested it and it worked really well, even though I use soft-wrapping it is working fine. I have been using the same for all the tests because it is the file with the greater amount of backlinks, and everything is displaying properly as far as I can tell. Not a single link is being displayed with all its ugly markup.
I will continue to test this function and report it is misbehaves.
I appreciate so much all the effort you guys made to help me, if I ever manage to finish my book I’ll make sure to thank you. I’ll add a not for that on my Roam so I don’t forget!
I have seen a request for me to rename this post and also to move it. I will now see if I can figure out how to do that!
Thanks!