feat(template): run a template from the configured folder without a per-file choice (#1023)#1343
feat(template): run a template from the configured folder without a per-file choice (#1023)#1343chhoumann wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughAdds a "New note from template" feature enabling note creation from configured template files. A new ChangesNew note from template feature
Sequence Diagram(s)sequenceDiagram
participant User
participant ChoiceSuggester
participant runTemplateFromFolder
participant GenericSuggester
participant ChoiceExecutor
rect rgba(100, 149, 237, 0.5)
note over User,ChoiceSuggester: Interactive launcher
User->>ChoiceSuggester: Opens Run QuickAdd (includeTemplateFolderRow: true)
ChoiceSuggester-->>User: Displays "New note from template" sentinel row
User->>ChoiceSuggester: Selects template launcher row
ChoiceSuggester->>runTemplateFromFolder: runTemplateFromFolder(app, plugin, {choiceExecutor})
runTemplateFromFolder->>GenericSuggester: Suggest(templateFiles, renderTemplateRow)
GenericSuggester-->>runTemplateFromFolder: User selects TFile
runTemplateFromFolder->>ChoiceExecutor: execute(createFolderTemplateChoice(templatePath))
ChoiceExecutor-->>User: Note created in default location
end
rect rgba(60, 179, 113, 0.5)
note over User,ChoiceExecutor: CLI (non-interactive)
User->>runTemplateFromFolder: quickadd:run-template path=templates/note.md value-value=MyNote
runTemplateFromFolder->>runTemplateFromFolder: resolve path, enforce value, build choice
runTemplateFromFolder->>ChoiceExecutor: executeWithOutcome(ephemeral TemplateChoice)
ChoiceExecutor-->>User: {ok:true, file: "MyNote.md", duration: ...}
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install timed out. The project may have too many dependencies for the sandbox. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying quickadd with
|
| Latest commit: |
4620c53
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://9f350943.quickadd.pages.dev |
| Branch Preview URL: | https://chhoumann-1023-run-template.quickadd.pages.dev |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e4bd85da1c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // front for non-interactive runs (ui mode can still prompt). Headless runs have | ||
| // no editor selection, so {{value}} comes solely from this variable. | ||
| if (!isTruthy(params.ui)) { | ||
| const variables = extractVariables(params, RESERVED_RUN_TEMPLATE_PARAMS); |
There was a problem hiding this comment.
Return JSON errors for malformed run-template vars
When quickadd:run-template is invoked non-interactively with a valid path but malformed vars= JSON, this precheck calls extractVariables before entering runResolvedChoice's try/catch, so parseVarsJson rejects the handler instead of returning the usual {ok:false, error: ...} CLI envelope. This differs from quickadd:run and from run-template ui, and can surface an unhandled CLI failure for a documented input path; wrap this parse in the same error-envelope handling or move it into the guarded common path.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Good catch — fixed in cb84d6d. runTemplateHandler is now wrapped in a try/catch that returns the standard {ok:false, error} envelope, so malformed vars= JSON in the up-front note-name check surfaces like quickadd:run / run-template ui instead of rejecting the handler. Added a regression test (returns a JSON error envelope for malformed vars).
2218229 to
cb84d6d
Compare
…er-file choice (#1023) Adds 'New note from template': a command + a gated Run QuickAdd launcher row + a quickadd:run-template CLI seam that create a note from any template in the configured template folder, prompting for the note name — no dedicated Template choice required. - runTemplateFromFolder engine builds a throwaway TemplateChoice (fileNameFormat enabled with VALUE_SYNTAX so the note-name requirement is visible to preflight/CLI/one-page) and runs it through the existing ChoiceExecutor/TemplateChoiceEngine. - Requires a configured template folder (notice + opens settings) rather than flooding a whole-vault picker; launcher row is gated on a configured folder + the showTemplateFolderInLauncher toggle. - CLI: shared runResolvedChoice; resolve the path via getTemplateFile (accepts leading-slash/extensionless like the engine); reserve path= so it can't leak as a variable; up-front file-existence check and blank-note-name rejection for an honest non-interactive envelope. - Docs: CLI.md (quickadd:run-template), Settings.md (toggle), TemplateChoice.md (discoverability).
cb84d6d to
4620c53
Compare
|
Post-review hardening (adversarial re-review): |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/cli/registerQuickAddCliHandlers.test.ts (1)
419-436: ⚡ Quick winAdd explicit coverage for leading-slash template paths.
This block validates extensionless input, but the stated CLI contract also includes leading-slash paths (for example
/Templates/Daily.md). Please add a companion case to prevent regressions in path normalization.Suggested test addition
it("accepts extensionless template paths the engine would resolve", async () => { const { plugin, handlers } = createPlugin([]); // Engine resolver appends .md; the CLI must accept "Templates/Daily" too. withTemplateFile(plugin, "Templates/Daily.md"); registerQuickAddCliHandlers(plugin); const run = handlers.find((h) => h.command === "quickadd:run-template"); const payload = JSON.parse( String( await run!.handler({ path: "Templates/Daily", "value-value": "Note" }), ), ); expect(payload.ok).toBe(true); const executed = ( executors[0].executeWithOutcome as ReturnType<typeof vi.fn> ).mock.calls[0][0]; expect(executed.templatePath).toBe("Templates/Daily.md"); }); + +it("accepts leading-slash template paths", async () => { + const { plugin, handlers } = createPlugin([]); + withTemplateFile(plugin, "Templates/Daily.md"); + registerQuickAddCliHandlers(plugin); + const run = handlers.find((h) => h.command === "quickadd:run-template"); + + const payload = JSON.parse( + String( + await run!.handler({ path: "/Templates/Daily.md", "value-value": "Note" }), + ), + ); + expect(payload.ok).toBe(true); + const executed = ( + executors[0].executeWithOutcome as ReturnType<typeof vi.fn> + ).mock.calls[0][0]; + expect(executed.templatePath).toBe("Templates/Daily.md"); +});🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/cli/registerQuickAddCliHandlers.test.ts` around lines 419 - 436, Add a new test case to validate that leading-slash template paths (such as "/Templates/Daily.md") are properly normalized by the CLI handler. Create a companion test similar to the existing "accepts extensionless template paths the engine would resolve" test: use withTemplateFile to register the template file, call registerQuickAddCliHandlers to set up handlers, find the handler with command "quickadd:run-template", invoke the handler with a leading-slash path like "/Templates/Daily", and assert that the executed templatePath is normalized to the correct form without the leading slash (such as "Templates/Daily.md"). This ensures path normalization handles both extensionless and leading-slash input formats as part of the CLI contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/cli/registerQuickAddCliHandlers.test.ts`:
- Around line 419-436: Add a new test case to validate that leading-slash
template paths (such as "/Templates/Daily.md") are properly normalized by the
CLI handler. Create a companion test similar to the existing "accepts
extensionless template paths the engine would resolve" test: use
withTemplateFile to register the template file, call registerQuickAddCliHandlers
to set up handlers, find the handler with command "quickadd:run-template",
invoke the handler with a leading-slash path like "/Templates/Daily", and assert
that the executed templatePath is normalized to the correct form without the
leading slash (such as "Templates/Daily.md"). This ensures path normalization
handles both extensionless and leading-slash input formats as part of the CLI
contract.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7a9108a0-8394-4e60-be5d-0a4f7dd25ae1
📒 Files selected for processing (16)
docs/docs/Advanced/CLI.mddocs/docs/Choices/TemplateChoice.mddocs/docs/Settings.mdsrc/IChoiceExecutor.tssrc/cli/registerQuickAddCliHandlers.test.tssrc/cli/registerQuickAddCliHandlers.tssrc/commandLabels.tssrc/engine/runTemplateFromFolder.test.tssrc/engine/runTemplateFromFolder.tssrc/gui/suggesters/choiceSuggester.test.tssrc/gui/suggesters/choiceSuggester.tssrc/main.commandLabels.test.tssrc/main.tssrc/quickAddSettingsTab.test.tssrc/quickAddSettingsTab.tssrc/settings.ts
✅ Files skipped from review due to trivial changes (6)
- src/commandLabels.ts
- src/quickAddSettingsTab.test.ts
- docs/docs/Choices/TemplateChoice.md
- docs/docs/Advanced/CLI.md
- src/main.commandLabels.test.ts
- docs/docs/Settings.md
🚧 Files skipped from review as they are similar to previous changes (8)
- src/quickAddSettingsTab.ts
- src/settings.ts
- src/main.ts
- src/gui/suggesters/choiceSuggester.ts
- src/gui/suggesters/choiceSuggester.test.ts
- src/engine/runTemplateFromFolder.test.ts
- src/cli/registerQuickAddCliHandlers.ts
- src/engine/runTemplateFromFolder.ts
Closes #1023.
What
Adds New note from template — run a template straight from your configured template folder, prompting for the new note's name, without maintaining a Template choice per file.
Three entry points, all backed by one reusable core (
runTemplateFromFolder) that builds a throwaway, non-persistedTemplateChoiceand runs it through the existingChoiceExecutor→TemplateChoiceEngine:New note from template(palette / hotkey / ribbon).📄 New note from template…row at the top of the picker, gated on a configured template folder + the new Show "New note from template" in the launcher toggle (Settings → Choice Picker).quickadd:run-template path=<vault-path> value-value=<name>— the scriptable form.No new persisted choice type (rejected as too much surface); no migration.
Why this shape
getTemplateFiles()(the listing seam) +TemplateChoiceEngine(the run seam) — the only thing missing was the thin join.fileNameFormat = { enabled: true, format: {{value}} }on purpose: runtime is identical toenabled:false, butcollectChoiceRequirementsonly scans the file-name format when enabled, so this makes the note-name visible to the non-interactive CLI guard and the one-page form (otherwise the CLI would hang / report a false success).Review
Designed and reviewed before coding (ultracode multi-lens + 2 opposite-model adversarial reviewers), then the implementation was reviewed the same way. Findings fixed:
ok:truewith no note created (the collector consumes a provided-but-empty value, sorun-templaterejects a blank name up front for non-interactive runs).getTemplateFile(acceptsTemplates/Dailyand/Templates/Daily.mdlike the engine);path=is reserved so it can't leak as a template variable; up-front file-existence check.Known, documented limitations (inherited from the Template engine, shared with
quickadd:run){{value}}uses the selection as the name (intrinsic{{VALUE}}behavior).Verified
pnpm build+pnpm lintclean; 2042 tests pass (new unit coverage: ephemeral-choice defaults, real-collector integration + negative control, picker resolve/cancel, launcher-row injection/gating/dispatch/exclusion, CLI envelopes incl. blank-name + extensionless paths).{{value}}resolved; blank/empty/omitted name →ok:false+missingFlags; launcher row appears/dispatches; require-config notice + opens settings; extensionless & leading-slash paths resolve.Release impact
feat→ minor bump. New settingshowTemplateFolderInLauncher(default true; only surfaces the row when a template folder is configured).main.js/styles.cssare gitignored and regenerated by CI.Summary by CodeRabbit
quickadd:run-templateCLI support to create notes from a specified vault-relative template path (supportsvarsJSON and interactive/non-interactive modes).quickadd:run-templatesyntax and failure/cancellation behavior, plus guidance on when to use this vs a full template choice.