Skip to content

Conversation

@mkh-user
Copy link
Member

@mkh-user mkh-user commented Oct 10, 2025

Type of Change

  • New feature
  • Documentation update

Description

This pull request implements the template system as described in Issue #2. It introduces a reusable file templating mechanism to streamline file creation and reduce repetitive work. Key features include:

  • user://templates/ directory for storing user-defined templates
  • Placeholder support using {{{...}}} syntax, including internal variables like {{{!date}}}, {{{!file_name}}}, etc.
  • Interactive placeholder replacement panel with auto-insert options
  • New menu entries:
    • File > New With Template
    • Format > Save As Template
    • Format > Templates... (opens Template Manager)

Testing

  • Verified placeholder replacement for internal and custom keys
  • Confirmed template saving and loading behavior
  • Tested Template Manager for preview, edit, and delete functionality
  • Ensured graceful handling of unsaved files and error states

Impact

  • Improves onboarding and productivity for new and existing users
  • Enables customizable file generation workflows
  • Lays groundwork for future template sharing via marketplace

Additional Information

Documentation added in docs/templates.md, including usage examples and screenshots.
All new UI strings localized via translation.csv.
Assets and scenes for Template Manager included.

Checklist

  • Code follows project style guidelines
  • Self-reviewed and tested
  • Comments added where needed
  • Documentation updated
  • No new warnings introduced
  • Changes added to CHANGELOG

Summary by CodeRabbit

  • New Features
    • Full template system: save templates, create new files from templates, and manage them with a Template Manager.
    • Placeholder completion flow: search-and-replace popup with Next/Previous, replace/insert, and contextual auto-insert (file/date/time).
    • Continue placeholder completion action to resume pending placeholder replacements.
  • UI
    • Replace popup UI added and new menu items for template and placeholder actions.
  • Bug Fixes
    • Corrected input API name and improved mode-loading fallback.
  • Documentation
    • Added Templates guide and updated menu docs.
  • Tests
    • Updated tests to match corrected API name.

@mkh-user mkh-user added this to the Text Forge 0.2 milestone Oct 10, 2025
@mkh-user mkh-user self-assigned this Oct 10, 2025
@mkh-user mkh-user added the action scripts Official action scripts or action scripts features label Oct 10, 2025
@mkh-user mkh-user linked an issue Oct 10, 2025 that may be closed by this pull request
@mkh-user mkh-user added the feature: Templates Provides reusable templates for faster setup or content generation label Oct 10, 2025
@mkh-user mkh-user moved this from Needs Review to In Progress in Release: Text Forge 1.0 Oct 10, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 10, 2025

Walkthrough

Adds a template system: new template actions (create, save, continue), Template Manager UI and scene, a regex-driven Replace popup for placeholder completion, constants and assets, menu entries, a Factory API rename (signle → single), and docs/tests updates.

Changes

Cohort / File(s) Summary
Template core & UI
core/main.gd, core/main.tscn, core/scripts/replace_popup.gd, core/scripts/replace_popup.gd.uid, action_scripts/templates.gd, action_scripts/templates.gd.uid, docs/templates.md, mkdocs.yml
Adds template integration: main hooks for templates, Replace popup implementation (regex search/replace, placeholder insertion/navigation), templates action script linking to manager scene, documentation and nav entry.
Action scripts (create/save/continue)
action_scripts/new_with_template.gd, action_scripts/new_with_template.gd.uid, action_scripts/save_as_template.gd, action_scripts/save_as_template.gd.uid, action_scripts/continue_placeholder_completion.gd, action_scripts/continue_placeholder_completion.gd.uid
New action scripts: New With Template (template selection, unsaved-file handling), Save As Template (confirm, name input, write template, reload), Continue Placeholder Completion (triggers replace flow). UID files added.
Template Manager scene & script
action_scripts/scenes/template_manager.tscn, action_scripts/scenes/template_manager.gd, action_scripts/scenes/template_manager.gd.uid
New Template Manager scene and controller: list templates, preview, edit/open, remove (trash), and UI wiring.
Asset import configs
assets/close.svg.import, assets/down.svg.import, assets/insert.svg.import, assets/up.svg.import
Add import configuration files for UI icons used by the Replace popup and template UI.
Factory API and tests
core/autoload/factory.gd, tests/core/autoload/factory_test.gd, action_scripts/go_to_line.gd
Fix function name signle_line_inputsingle_line_input and update tests/call sites accordingly.
Core constants & editor init
core/classes/static.gd, core/scripts/editor_api.gd
Add constants (DEFAULT_MODES, TEMPLATE_TEMPLATES, PATTERN_PLACEHOLDER) and guard mode-loading to avoid duplicate imports.
Replace popup scene integration
core/main.tscn, core/scripts/replace_popup.gd.uid
Add Replace popup nodes/resources to main scene and wire controls to the replace-popup script.
Menu & UI data
data/main_ui.ini, docs/menus.md
Insert menu items: Continue Placeholder Completion, Save As Template; renumber Templates entry and document new menu entries.
Changelog & tests
CHANGELOG.md, tests/core/autoload/factory_test.gd
Add unreleased changelog entry for templates and update tests for the Factory API rename.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Main
  participant TemplatesMenu as "Templates submenu"
  participant Editor
  participant ReplacePopup as "Replace Popup"

  User->>Main: File → New With Template
  Main->>TemplatesMenu: reload_templates()
  User->>TemplatesMenu: select template
  TemplatesMenu->>Main: load_template(name)
  Main->>Editor: set editor text from template
  Main->>ReplacePopup: start(pattern = S.PATTERN_PLACEHOLDER)
  ReplacePopup->>Editor: find & highlight first placeholder
  note right of ReplacePopup: User may Next/Previous, Replace, Insert, or Close
  User->>ReplacePopup: Close
  ReplacePopup->>Editor: deselect & hide
Loading
sequenceDiagram
  autonumber
  actor User
  participant Action as "Continue Placeholder Action"
  participant Main
  participant ReplacePopup as "Replace Popup"

  User->>Action: Format → Continue Placeholder Completion
  Action->>Main: start_replace_action(S.PATTERN_PLACEHOLDER)
  Main->>ReplacePopup: start(pattern)
  alt matches found
    ReplacePopup->>ReplacePopup: show popup near caret (highlight current match)
  else no matches
    ReplacePopup->>ReplacePopup: close popup (no matches)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • Template system #2 — Implements the requested template system features (save/load templates, Template Manager, placeholder replacement and continuation), matching this PR’s objectives.

Possibly related PRs

  • Refactor singletons #109 — Modifies the same core singletons/constants and Factory API naming, likely overlapping with this PR’s changes.

Poem

I hop through code with whiskers bright,
Templates sprout in morning light.
Placeholders wink, I nudge and fill,
Save, reopen — what a thrill!
A rabbit ships a tiny patch of delight. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly summarizes the primary change of adding a templating system and is concise and directly related to the main feature in this pull request.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 2-template-system

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]

This comment was marked as resolved.

@coderabbitai

This comment was marked as duplicate.

coderabbitai[bot]

This comment was marked as resolved.

@coderabbitai

This comment was marked as duplicate.

coderabbitai[bot]

This comment was marked as resolved.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (3)
action_scripts/scenes/template_manager.gd (2)

44-47: Guard against selecting guidance items.

When the template list is empty, lines 15-16 add non-selectable guidance messages. If a user somehow selects one of these items (e.g., through keyboard navigation or a race condition), lines 46-47 would attempt to load a non-existent template file, causing an error.

Apply this diff:

 func _on_templates_item_selected(index: int) -> void:
+	# Skip if this is a guidance message
+	if not templates.is_item_selectable(index):
+		return
 	preview_panel.show()
 	template_name.text = templates.get_item_text(index)
 	preview.text = FileAccess.get_file_as_string(S.TEMPLATE_TEMPLATES.format([template_name.text]))

38-41: Handle trash failures and refactor list refresh.

Line 39 doesn't check if OS.move_to_trash() succeeds, which could fail silently. Line 41 calls _ready() to refresh the list, but _ready() is a lifecycle method and shouldn't be manually invoked.

Apply this diff:

 func _delete_template() -> void:
-	OS.move_to_trash(S.globalize_path(S.TEMPLATE_TEMPLATES.format([template_name.text])))
+	var path := S.globalize_path(S.TEMPLATE_TEMPLATES.format([template_name.text]))
+	var err := OS.move_to_trash(path)
+	if err != OK:
+		Global.send_notification(Global.Notification.ERROR, "Failed to remove template!", "Error code: " + str(err))
+		return
 	preview_panel.hide()
-	_ready()
+	_reload_list()
+
+func _reload_list() -> void:
+	templates.clear()
+	if not DirAccess.dir_exists_absolute(S.globalize_path(S.FOLDER_TEMPLATES)):
+		DirAccess.make_dir_recursive_absolute(S.globalize_path(S.FOLDER_TEMPLATES))
+	for t in DirAccess.get_files_at(S.FOLDER_TEMPLATES):
+		templates.add_item(t.get_basename())
+	if templates.item_count == 0:
+		templates.add_item("There is no template to show!", null, false)
+		templates.add_item("Use Format > Save As Template to create one.", null, false)
action_scripts/save_as_template.gd (1)

15-33: Remove unrelated file name mutation and add overwrite warning.

Line 32 removes the unsaved indicator (*) from the current file's name when saving a template. This is incorrect because saving as a template doesn't save the current file—it only creates a new template file. Additionally, there's no warning when overwriting an existing template.

Apply this diff:

 func _save_template(_name: String) -> void:
 	_name = _name.strip_edges().validate_filename()
 	if _name.is_empty():
 		Global.send_notification(Global.Notification.ERROR, "Invalid template name!", "Please use letters, numbers, space, dash or underscore.")
 		return
 	if not DirAccess.dir_exists_absolute(S.globalize_path(S.FOLDER_TEMPLATES)):
 		DirAccess.make_dir_recursive_absolute(S.globalize_path(S.FOLDER_TEMPLATES))
 	var path := S.TEMPLATE_TEMPLATES.format([_name])
+	if FileAccess.file_exists(path):
+		Global.send_notification(Global.Notification.WARNING, "Template exists", "Overwriting existing template: " + _name)
 	var file_access := FileAccess.open(path, FileAccess.WRITE)
 	var err := FileAccess.get_open_error()
 	if err or not file_access:
 		Global.send_notification(Global.Notification.ERROR, "Failed to save file as template!", "Error code: " + str(err))
 		return
 	file_access.store_string(Global.get_editor_text())
 	file_access.close()
 	Global.send_notification(Global.Notification.INFO, "File saved as template!")
 	Global.get_core().reload_templates()
-	Global.set_file_name(Global.get_file_name().replace("*", ""))
 	Signals.open_file.emit(path)
🧹 Nitpick comments (1)
core/main.gd (1)

48-51: Inconsistent comment formatting for method references.

Line 48 references _reload_recent_files while line 50 references _reload_templates, but the actual method on line 416 is reload_templates (without underscore prefix). The comments should consistently reference the actual method names.

Apply this diff:

-## Recent files [PopupMenu], see also [method _reload_recent_files].
+## Recent files [PopupMenu], see also [method _reload_recent_files()].
 var recent_files_submenu: PopupMenu
-## Templates [PopupMenu], see also [method _reload_templates].
+## Templates [PopupMenu], see also [method reload_templates()].
 var templates_submenu: PopupMenu
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ac0e80 and d130067.

📒 Files selected for processing (11)
  • CHANGELOG.md (1 hunks)
  • action_scripts/new_with_template.gd (1 hunks)
  • action_scripts/save_as_template.gd (1 hunks)
  • action_scripts/scenes/template_manager.gd (1 hunks)
  • action_scripts/scenes/template_manager.tscn (1 hunks)
  • core/autoload/factory.gd (2 hunks)
  • core/main.gd (3 hunks)
  • core/scripts/editor_api.gd (1 hunks)
  • core/scripts/replace_popup.gd (1 hunks)
  • docs/menus.md (2 hunks)
  • docs/templates.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • docs/templates.md
  • core/scripts/editor_api.gd
  • core/scripts/replace_popup.gd
🔇 Additional comments (3)
core/autoload/factory.gd (3)

5-6: LGTM! Typo fixed in class documentation.

The typo has been corrected from "signle" to "single" in the class-level documentation.


48-49: Past review comment addressed - typo fixed.

The typo "signle" has been corrected to "single" in the function-level comment, resolving the concern raised in the previous review.


50-71: All references to signle_line_input removed
A full-code search returned no instances of the old name; the rename is complete.

coderabbitai[bot]

This comment was marked as resolved.

@mkh-user mkh-user merged commit 8a6d2b5 into Main Oct 10, 2025
2 checks passed
@mkh-user mkh-user deleted the 2-template-system branch October 10, 2025 17:19
@github-project-automation github-project-automation bot moved this from In Progress to Completed in Release: Text Forge 1.0 Oct 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action scripts Official action scripts or action scripts features feature: Templates Provides reusable templates for faster setup or content generation

Projects

Status: Completed

Development

Successfully merging this pull request may close these issues.

Template system

2 participants