Files
canon/canon/template.hpp
T
paulhorn a82bdf4734 Add template overrides: canon templates and templates export
Every generated source file, README.md and .gitignore now comes from a
template that a file of the same name can replace:

- <project>/.canon/templates/ for that project, which wins over
- ~/.config/canon/templates/ ($XDG_CONFIG_HOME respected) for all
  projects; canon new reads only these

canon templates lists each template, where it comes from and the
placeholders it can use. canon templates export [<file>...] [--user]
copies built-in texts as a starting point and never overwrites.

Overrides are checked strictly: an unknown file name or a placeholder
the template does not provide is an error naming the file; hidden files
are ignored. Generators take a template_set, so they stay pure.

Also:
- executor: a symlink to a directory counts as a directory (macOS /var,
  linked config directories)
- plan: add_directory stops at the filesystem root
- project: find_project_root, shared by load_project and templates
- tests: a templates scenario; scenarios run canon with their own empty
  XDG_CONFIG_HOME so personal templates cannot affect results

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 19:01:37 +02:00

25 lines
822 B
C++

#pragma once
#include <expected>
#include <functional>
#include <map>
#include <string>
#include <string_view>
#include <vector>
namespace canon {
using template_vars = std::map<std::string, std::string, std::less<>>;
// Replaces every {{key}} in text with vars[key].
// Throws std::invalid_argument for an unknown key or an unterminated placeholder.
// Check user-supplied text with placeholders() first; for built-in templates
// either failure is a bug that tests should catch.
[[nodiscard]] std::string render(std::string_view text, const template_vars& vars);
// The key of every {{key}} in text, in order of appearance, or why the text
// cannot be rendered (an unclosed placeholder).
[[nodiscard]] std::expected<std::vector<std::string>, std::string> placeholders(std::string_view text);
} // namespace canon