obsidian-omnisearch
obsidian-omnisearch copied to clipboard
[Feature request] Insert link to header and block
Is your feature request related to a problem? Please describe. Sometimes I have a longer document (Doc A), with numerous headers and each with numerous paragraphs inside.
I rely heavily on the plugin Outliner to keep it easily navigated (fold, unfold ...).
Using Omnisearch, If I am working on another document (Doc B) and want to insert a reference link to a paragraph in Doc A, I can search the keywords in the paragraph and insert a link to Doc A in Doc B.
However, since it's a long document, just inserting a link to Doc A is not that helpful.
Describe the solution you'd like In the example above, I hope Omnisearch can give us quick options to insert:
- header link of the target paragraph to Doc A and
- block link of the target paragraph to Doc A.
Describe alternatives you've considered Quick switcher ++ doesn't seem to be able to insert header link.
Now I need to search with Omnisearch first, then open the target document and remember header name. Then I use the default approach [[ to search for the target document with header.
Additional context
+1 it would be a convenient feature.
I really want this feature, so I think I might try to implement it. @scambier Could you please give me some advice on this idea.
Sure thing :)
Thanks for making me look, it's probably easier than I initially thought.
1) Match an Omnisearch result with a block or a heading on the relevant note.
Fortunately, all Omnisearch results already have an offset that is used to display the relevant excerpt, and to position the cursor at the right place when opening a result.
https://github.com/scambier/obsidian-omnisearch/blob/e59f252cb4e175c259c3e86976838587632cfe50/src/globals.ts#L78-L85 https://github.com/scambier/obsidian-omnisearch/blob/e59f252cb4e175c259c3e86976838587632cfe50/src/globals.ts#L68-L71
And Obsidian's metadata for each note also lists blocks (sections) and headings, so it should be relatively trivial to match an Omnisearch result with the relevant block or heading:
2) Create a link from the offset value of the block/heading.
Omnisearch already uses generateMarkdownLink() to create a link to a note, and you "just" need to give it a subpath: a #heading or a ^blockId.
For headings, it's quite straightforward: extract the heading text from the position.start/end values, clean it with stripHeading(), and you should be good.
For blocks, it looks harder. If the block already has an id, you'll find it directly in the metadata (see SectionCache or CachedMetadata.blocks in obsidian api). Otherwise, I haven't found anything to generate an id. I'll ask on Discord and/or the forum and see if I find something.
3) Update the UI
Now for the UI, I don't have any idea more original or cleaner than "let's add 2 shortcuts to insert a link to the closest heading or block" 😅
Probably some variations of alt ↵
You're welcome to give it a go if you wish 👍 Don't hesitate to ask for help if needed
@scambier wow! Thank you so much for such a detailed description. With you help I've yet implemented header link insertion! I'll try with the block link later.
For now it's more interesting to understand about matches. Tell me please, is it possible to output each match as a separate element in the interface?
I mean, when I plan to insert a link to a file, it may not be so important for me to see a specific occurrence of a search term among the possible dozens. But when I want to insert a link to header, it is important for me to scroll through all to some very specific one. I.e. is it possible to disaggregate the matches array or in the other words how to make the matches array flat?
Great!
The aggregation is done at the last moment, right before the results are displayed here:
https://github.com/scambier/obsidian-omnisearch/blob/e59f252cb4e175c259c3e86976838587632cfe50/src/components/ModalInFile.svelte#L64-L71 https://github.com/scambier/obsidian-omnisearch/blob/e59f252cb4e175c259c3e86976838587632cfe50/src/components/ModalInFile.svelte#L155-L174
Matches are aggregated on the same result when they're fewer than 300 chars apart; roughly when they can be displayed on the same excerpt. (Now that I think about it, aggregation could probably be reworked to group results on the same block 🤔)
If you're willing to submit a PR for this feature request, I'd like to keep this behavior. If de-aggregation is a must for you, can I suggest adding an opt-out setting to keep aggregation as the default?
Thank you! I'll try to add de-aggregation.
By the way, there are a couple of questions:
- ) I encountered a situation where there is no heading in a note. In such cases, I believe it would be appropriate to simply reuse the
InsertLinkfunction. What are your thoughts on this? - I have some doubts regarding these lines: https://github.com/scambier/obsidian-omnisearch/blob/e59f252cb4e175c259c3e86976838587632cfe50/src/components/ModalVault.svelte#L221-L225
Why is a separate behavior needed for this case? Is it possible that a link will be inserted without the file? How should these conditions be interpreted?
-
Yup, seems like the correct behavior
-
The split logic here is a remnant of a removed feature: Omnisearch could index non-created files (that only "exist" as links), hence the need to handle this particular case. I removed the feature a year ago, but it could be re-added at some point (see #133 #227)
There's no api to insert blockIds, but it's doable by hand.
See here for an example. (the parameter
secis theSectionCacheof the block that you want to insert a link to. You can get it by something likeapp.metadataCache.getFileCache(file)?.sections?.find(sec => sec.position.start.line == line))https://github.com/RyotaUshio/obsidian-math-booster/blob/24ffc2b4b984f2ef7d24629bc2932f39db44b8c9/src/utils.ts#L217
Courtesy of Ush on Discord