Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Race Condition with Templater #55

Open
dredhorse opened this issue May 10, 2022 · 17 comments
Open

Race Condition with Templater #55

dredhorse opened this issue May 10, 2022 · 17 comments
Assignees

Comments

@dredhorse
Copy link

Use File Open Hook is disabled.

There are two issue I notice with my templates.

I do rename the title of the note with the templater function: await tp.file.rename(newFilename)
after that, I include a template file with tp.file.include(otherTemplate) which adds the frontmatter
and then I include another template which includes the H1.

  1. Related to your plugin:
    If the plugin is enabled the file rename doesn't work
    if the plugin is disabled the file rename does work.

  2. Probably related to templater:
    Templater doesn't pick up the correct note title after the rename in the included templates. Looking into this issue atm too.

A workaround for 1) could be to either wait a little (which you already suggested for the original bug) or perhaps to allow more options to configure what the plugin does. For example, only update the H1 if the file is renamed, or only update the filename if the H1 is renamed.

@dredhorse
Copy link
Author

Bug for 2. SilentVoid13/Templater#636 (comment)

@evanharmon1
Copy link

I just ran into this issue as well. Filename Heading Sync causes templater's await tp.file.rename(newFilename) to not work. Specifically, in my case, it renames the file but doesn't include the rest of the template commands. Or perhaps the other template commands work but then Filename Heading sync deletes the content. Any insight on how this might be fixed?

@eternialz
Copy link

eternialz commented Jul 22, 2022

I also encountered this issue but with the tp.file.move function:

Using this template, the note is placed directly in a specific folder and renamed using the move function:

# Untitled

Anything here doesn't appear in the created note, only the first heading

<% tp.file.move("Topic/Untitled")) %>

As a temporary "workaround", if you can call it that, you can place the move or rename function call inside a setTimeout :

<%*
setTimeout(() =>{
	tp.file.move("Topic/Untitled")
}, 0)
-%>

A little bit clunky since the note doesn't remain open but it is created with all the content from the template

@evanharmon1
Copy link

Good idea! With that strategy, this was the best I could come up with:

<%*
setTimeout(() =>{
	tp.file.rename("Title preface string " + tp.file.selection().split('\n')[1])
}, 0)
-%>

<% tp.file.selection() %>

Close, but I'm not sure it quite does the trick in my situation since it closes the note and then I need to go back to the note I grab the selection from and delete the selection and link to the note. But I might keep tinkering.

@dvcrn
Copy link
Owner

dvcrn commented Aug 5, 2022

Sorry I don't use Templater and not sure what I could add to fix this race condition besides artificial delays, like was suggested here with setTimeout

filename-heading-sync is just using the normal obsidian events to do it's thing. If you rely heavily on templater and the artificial delay isn't doing it for you, maybe deactivate both hooks and sync only manually. The last release included 2 commands for manual syncing

Any PRs for this issue are very welcome!

@eternialz
Copy link

I didn't want to disable file save hook because it was the feature that made me use this plugin but I guess the two manual commands will do for now.

However, if you don't need heading sync after the template has been parsed and the file created, you can trigger those 2 commands through templater, after renaming or moving has occured :

<%* 
    this.app.commands.executeCommandById('obsidian-filename-heading-sync:sync-filename-to-heading');
    this.app.commands.executeCommandById('obsidian-filename-heading-sync:sync-heading-to-filename');
-%>

@dredhorse
Copy link
Author

I think another option would be to be able to select a "one-way" sync.

So have options to

  • only update the filename if the header changes
  • only update the header if the filename changes

I think the issue also comes because "best practice" for templater is to use

[[filename]]

as a header.

Need to test if removing the [[]] would remove the issue.

On the other side I have

[[filename|This is my Test File]]

also as header.

Perhaps my use case just doesn't support the syncing.

@labgeea
Copy link

labgeea commented Nov 22, 2024

any news on this by any chance? :)

@zeltak
Copy link

zeltak commented Dec 24, 2024

Hi yeah also would love to see this resolved

Z

@dvcrn
Copy link
Owner

dvcrn commented Dec 25, 2024

Looked a bit into it

Templater emits a bunch of hooks:

  • this.plugin.app.workspace.trigger("templater:new-note-from-template", {
  • this.plugin.app.workspace.trigger("templater:template-appended", {
  • this.plugin.app.workspace.trigger("templater:new-note-from-template", {
  • this.plugin.app.workspace.trigger("templater:overwrite-file", {

Example: https://github.com/SilentVoid13/Templater/blob/master/src/core/Templater.ts#L265C44-L265C71

We can detect whether templater is installed and enabled with

app.plugins.enabledPlugins.has("templater-obsidian")

We could check if templater is active, then wait for these events before syncing the heading. new-note-from-template hook should be enough?

@dvcrn
Copy link
Owner

dvcrn commented Dec 25, 2024

People with Templater issues, can you provide me a dead-simple step-by-step guide how I can reproduce the error? With template you're using and everything please

@pyxelr
Copy link

pyxelr commented Dec 25, 2024

People with Templater issues, can you provide me a dead-simple step-by-step guide how I can reproduce the error? With template you're using and everything please

It has been a while since I looked into this problem, but I can share my dummy setup to recreate it, as well as how I overcome it.

My current Obsidian theme is Minimal but it should not matter.

Files

I have the usr/templater/sprint_filename file in Obsidian with a couple of comments that I wrote in the past about this issue (that I cannot entirely understand now):

<%*
if (tp.file.title.startsWith('Untitled'))
{
   const extra = await tp.system.prompt("<sprint>-<day> || sp/r&r-<sprint>");
   let name = '';
   let templatePath = '';

   if (extra.includes("sp")) {
	   name = `${tp.date.now()} (${extra})`;
	   templatePath = `[[sp]]`;
   } else if (extra.includes("r&r")) {
	   name = `${tp.date.now()} (${extra})`;
	   templatePath = `[[r&r]]`;
   } else {
	   name = `${tp.date.now()} (d ${extra})`;
	   templatePath = `[[daily]]`
   }

   // Append the file name as the first heading
   // Disable "Use File Open Hook" in "Filename Heading Sync" plugin to prevent bugs
   // If bugs still occur, add this to the ignore regex rule of the plugin "|~AAA/Sprints/*"
   await tp.file.cursor_append(`# ${name}\n\n`);

   // Include the specific template based on the input
   // For it to work, you need to create the note in one of the folders ignored by the regex rule
   // There is an open issue: https://github.com/dvcrn/obsidian-filename-heading-sync/issues/55
   if (templatePath) {
	   const templateContent = await tp.file.include(templatePath);
	   await tp.file.cursor_append(templateContent);
   }

   // Move the file
   const sprintNumberMatch = extra.match(/\b\d+\b/);

   if (sprintNumberMatch !== null) {
	   const sprintNumber = sprintNumberMatch[0];
	   await tp.file.move(`~AAA/Sprints/Sprint ${sprintNumber}/` + name);
   }

}
-%>

The sample templatePath file (used in the script above) is usr/templates/sp:

## 📝 Notes

- ...

Plugin settings

Templater

  • Template folder location: usr/templater
  • Template hotkeys: using Ctrl/Cmd + Shift + M to "Templater: Insert usr/templater/sprint_filename.md"

Templates (built-in Obsidian plugin)

I am not sure if its settings matter, but here they are:

  • Template folder location: usr/templates

Filename Heading Sync

  • Ignore Regex Rule: usr/*|~AAA/Sprints/*
  • Use File Open Hook: disabled
  • Use File Save Hook: enabled
  • New Heading Style: Prefix
  • Replace Heading Style: disabled

Working solution

With the aforementioned settings, open any file in ~AAA/Sprints/ Obsidian path (e.g. ~AAA/Sprint/blabla):

  1. Hit Ctrl/Cmd+N to create a new file anywhere in your Obsidian Vault (it will be named Untitled)
  2. Hit Ctrl/Cmd+Shift+M to apply the Templater script
  3. Put e.g. sp-1 into the context window
  4. You should observe the following file ~AAA/Sprints/Sprint 1/2024-12-25 (sp-1) with the expected content:
# 2024-12-25 (sp 1)

## 📝 Notes

- ...

Recreating the bug

In the Filename Heading Sync plugin options, remove the applied regex rule, and execute the "Working solution" steps above. In the result, you will observe only the file heading (without the rest of the template):

# 2024-12-25 (sp-2)

Or, when you additionally enable the Use File Open Hook option, it will duplicate the file heading at the file bottom:

# 2024-12-25 (sp-1)

## 📝 Notes

- ...
# 2024-12-25 (sp-1)

The file will be named correctly in both examples, but its content is wrong.

@dvcrn
Copy link
Owner

dvcrn commented Dec 26, 2024

Thanks! Let me take a look today and see if it's as simple as adding some waiting for the Templater hook, maybe behind a setting

@dvcrn dvcrn self-assigned this Jan 4, 2025
dvcrn added a commit that referenced this issue Jan 6, 2025
Try to wait for templater events for a short time before activating sync
Ref #55
@dvcrn
Copy link
Owner

dvcrn commented Jan 6, 2025

I've added a proof of concept that waits for the templater hooks (if templater is installed). I need a few more simple templates to test this

The example from @eternialz above is now working with this

Could someone with more Templater usage give the following main.js a try? Unzip the .zip file and move main.js into <Vault Location>/.obsidian/plugins/obsidian-filename-heading-sync, overwrite the existing main.js

main.js.zip

@dvcrn
Copy link
Owner

dvcrn commented Jan 19, 2025

Would anyone be able to give this version a try and tell me if they still have issues?

@zeltak
Copy link

zeltak commented Jan 21, 2025

Initial tests seem to show its working. will use it under some more scenarios and update soon

thx so much

X

@dvcrn
Copy link
Owner

dvcrn commented Jan 24, 2025

I've released the experimental support in https://github.com/dvcrn/obsidian-filename-heading-sync/releases/tag/1.9.3

It's basically just adding a short wait for the Templater hook. It's very barebones but may resolve some of this race condition. If no Templater hook is fired, it runs after waiting for 100ms so the wait should not be perceivable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants