Placing a cursor in a file name using Templater

What I’m trying to do

I am trying to place a cursor automatically in part of a file name using Templater plugin. Here is my workflow:

  1. Click on a folder in the left “Files” pane of Obsidian.
  2. Press CMD + N to create a new file.
  3. Press the assigned hotkey (CMD + SHIFT + N) to use the following Templater script:
<%  tp.file.rename(tp.date.now() + " (d " + tp.file.cursor(1) + ")" ) %>
  1. This script renames a file name to:
2023-02-08 (d <% tp.file.cursor() %>)
  1. If I press CMD + SHIFT + N again, it will turn the file name into this; however, the cursor will not be placed before the ) character:
2023-02-08 (d )

Eventually, I can fix placing a cursor by pressing TAB before step 4, and the cursor will be placed in the right place. However, it still requires pressing twice the assigned hotkey for the provided template script.

Is there a way to optimize this workflow/script? Ideally, I would like to do only steps 1-3 (without pressing TAB) and have a cursor automatically placed before the ) character in the file name.

I am using the BryanJenks/PamelaWang meta templater method with some Js to put (move) the newly created files into designated A, B, C, etc. folders. No need to press any buttons in the workflow. My cursor is placed two lines below H1 and I can start typing. You can configure any name for the note.

1 Like

I’m not getting why you’re pressing so many keys… It should be enough to trigger your template once, and you should be where you’re supposed to be. So something’s askew in your setup.

Are you using folder templates in Templater? Which folder are you in when you trigger the creation of the note? And how does it decide which sub folder you want to place your note in?

What is Cmd + N set to? The original, or Templater: Create new note from template?

How does your template look, it feels like you’ve left out something.

Finally, whenever you do file operations within Templater you should await the result, so please do await tp.file.rename( ... ), not just tp.file.rename( ... )

The “Settings > Appearance > Show inline title” setting shows the file name at the top of the notes as a stylistic convenience, but this display is not actually part of the note content. If you turn on line numbering (Settings > Editor > Show line number), it makes this more clear. Line 1, which appears after the title, is the first actual line of your note content.

Templater can only position the cursor within the note content. It cannot place it within the title, which exists outside that content.

I suggest instead of trying to get the cursor there, you prompt for the unique text you want for the file name. Something like the following:

<%*
if (tp.file.title.startsWith('Untitled'))
{
   const extra = await tp.system.prompt("Title");
   const name = `${tp.date.now()} (d ${extra})`;
   await tp.file.rename(name);
}
-%>
1 Like

Definitely, there is a lot of optimization ahead of me, but I wanted to start with something basic. Perhaps, I will further improve my script with all the tips coming from the video suggested by @zanodor.

To answer your questions:

  • I’m keeping my Templater files inside of a templater/ folder
  • Cmd + N is set to the original new file creation
  • My Templater script is just this single line from the 3rd point of the first message.

I can’t thank you enough, this is even better than what I’ve been looking for!

Right, I am rather keeping the Show inline title option as disabled.

Is it also possible to add something within your script to place my cursor two lines below H1? For now, after executing it, my cursor is being placed here (1), and I would prefer it somewhere here (2):

templater-from-ninjineer

Since you are using Templater to create your files, check out the function tp.file.cursor(). It lets you create an ordered sequence of cursor positions which you can scroll through quickly in the newly created note.

<% tp.file.cursor(N) %>
1 Like

Something like this:

<%*
if (tp.file.title.startsWith('Untitled'))
{
   const extra = await tp.system.prompt("Title");
   const name = `${tp.date.now()} (d ${extra})`;
   await tp.file.rename(name);
}
-%>
# <% name %>

<% tp.file.cursor(0) %>
1 Like

Hmm, it didn’t really work in my case. I will also try debugging it later myself.

templater-from-ninjineer-2

Actually, I am quite stuck and cannot resolve my issue. Would you mind checking if the template from your answer works for you?

To give a bit more context:

  • I am pressing CTRL + N to create a new note in a folder, and my cursor is being automatically focused on the filename in the title bar. At that time, I press a hotkey assigned to your template
  • I am keeping “Show inline title” as off, “Show tab title bar” as on, and I’m also using the Filename Heading Sync extension
    • If this extension is turned on, I’m ending up as on the screenshot in my previous answer, and if it’s off, I’m in the same situation but without the word “Untitled”
  • Nevertheless, the filename is correctly updated, but the # <% name %> rule is not working (the H1 heading is not being updated), and my cursor is not being moved from the title bar

I scratched my head on this for bit before I realized the problem stems from the fact that I declared name inside the if { }. As soon as the code exits that block the variable no longer exists. Thus later when I attempt to use it in <% name %> there’s no value to apply.

<%*
let name = tp.file.title;
if (name.startsWith('Untitled'))
{
   const extra = await tp.system.prompt("Title");
   name = `${tp.date.now()} (d ${extra})`;
   await tp.file.rename(name);
}
-%>
# <% name %>

<% tp.file.cursor(0) %>

On my test vault:

  1. I created a New note
  2. Obsidian highlights the word Untitled, which would allow me to immediately name the note.
  3. Instead, I triggered the above template, which prompts for a Title.
  4. The formerly Untitled note gets renamed to 2023-02-16 (d sample) (for example) and the H1 line gets the same text.
  5. The cursor ends up blinking on line 3 of the note.

If cursor does not end up there for you, it’s possible the Filename Heading Sync extension you’re using interferes in some way. Or it could be another extension altogether causing an issue.

1 Like

Thanks!

That had to be indeed quite tricky to discover that the variable is scoped only inside the if { }.

This script works for me; however, I need to apply the following before triggering the script:

  1. Turn off the Filename Heading Sync extension.
  2. After creating a new note with CTRL + N, press the arrow down button so that the focus moves from the file name field (1) to the 1st line of the file (2):

If I don’t use the arrow down step, then the focus of my cursor stays within the file name field (1), but the file gets renamed correctly. Additionally, if I don’t turn off the extension, then the automatically inserted # Untitled text on the file creation, gets carried to the <% tp.file.cursor(0) %> place.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.