Skip to content

[BUG] {{CURSOR}} silently not placed when capturing to a large open note #1798

Description

@pkelly102

Describe the bug
A Capture with {{CURSOR}} in its format doesn't move the cursor when the destination note is large (~100KB+) and already open in the active editor. There's no error or notice. The cursor just stays where it was, or ends up at the start of the inserted line. Small notes work fine, so it looks intermittent.

To reproduce

  1. Capture choice: "Capture to active file", Insert after # Encounters, format {{VALUE:Note}} {{CURSOR}}. "Run Templater on entire destination file" is off.
  2. Open a note of ~130KB that has a # Encounters heading, and put the cursor somewhere below the heading.
  3. Run the capture.
  4. The text is inserted correctly, but the cursor doesn't move to the {{CURSOR}} position.

Results from running the same choice via quickAddApi.executeChoice (cursor on the captured line, out of 3–4 runs):

Note size Cursor placed editor.getValue() matches immediately after vault.modify
2 KB 3/3 yes
40 KB 3/3 yes
132 KB 0/3 no; matches after ~13–21 ms
250 KB (only tested with the patch below) no; matches after ~25 ms

Root cause (from reading 2.27.0 main.js)

  • The capture writes with app.vault.modify(file, newContent), then the cursor helper (minified Vg(app, file, offsets, content)) is called right away.
  • The helper compares editor.getValue() to content and returns false on mismatch (if(s!==n){if(s!==n.replace(/\r\n?/g,"\n"))return!1; …}).
  • For small files, Obsidian applies an external vault.modify to an open editor synchronously, so the check passes.
  • For larger files, the editor update lands a few ms later, so the check fails every time and placement is skipped silently.

Suggested fix
Either option works:

  • When the destination is the active file, wait for the editor to reflect the write before placing the cursor. For example, retry the comparison for up to ~1s, or wait on the editor's next change/editor-change event.
  • Or, for the active file, apply the capture through an editor transaction instead of vault.modify, so the offsets are always in sync.

I'm running a local patch that retries the comparison every 25 ms for up to 40 tries (returning true while a retry is pending so callers don't fall through to a second placement). It fixed the problem at every size above (4/4 each at 2 KB, 132 KB and 250 KB).

Related, possibly worth documenting
When "Run Templater on entire destination file after capture" is on, the {{CURSOR}} position is discarded on purpose (cursor = null when afterCapture === "wholeFile"), even if the file contains no <% %>. Users switching from <% tp.file.cursor() %> (which needed that setting) to {{CURSOR}} will hit this. A note in the {{CURSOR}} docs, or only discarding when Templater actually changed the file, would help.

Environment

  • QuickAdd 2.27.0
  • Obsidian 1.13.7, macOS
  • Templater installed (auto-jump to cursor on; no tp.file.cursor markers in the note)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions