Porytiles
Loading...
Searching...
No Matches
tileset_command_setup.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <filesystem>
4#include <memory>
5#include <string>
6#include <unistd.h>
7#include <utility>
8#include <vector>
9
10#include "CLI/CLI.hpp"
11#include "fruit/fruit.h"
12#include "gsl/pointers"
13
56
57namespace porytiles {
58
73 private:
81 struct ProviderChain {
82 std::vector<std::unique_ptr<ConfigProvider>> providers;
83 gsl::not_null<YamlFileProvider *> yaml_provider;
84 };
85
86 [[nodiscard]] static ProviderChain make_provider_chain(
87 const std::filesystem::path &project_root,
88 const CliOptionStorage &cli_storage,
91 {
92 // Layered configuration, highest priority first: CLI options, YAML files, base-game header defines,
93 // defaults. Every provider reads stated values only; the derivation that used to live in a provider now
94 // happens in the schema resolver's reconciliation, downstream of the chain.
95 //
96 // TODO: YamlFileProvider holds the raw stderr sink, so its warnings bypass the user's diagnostic filters in
97 // every command. The filters are themselves config values, so the chain has to exist before the filters can
98 // (a bootstrap circularity). Fix by late-binding the provider's diagnostics sink to the filtered one after
99 // initialize() succeeds.
100 std::vector<std::unique_ptr<ConfigProvider>> providers{};
101 providers.push_back(std::make_unique<CliOptionProvider>(cli_storage));
102 providers.push_back(std::make_unique<YamlFileProvider>(text_formatter, stderr_diag, project_root));
103 // Take the handle from the owning slot so its provenance is the list itself, not a moved-from local.
104 auto *yaml_provider = static_cast<YamlFileProvider *>(providers.back().get());
105 providers.push_back(
106 std::make_unique<HeaderDefineProvider>(
107 project_root, std::filesystem::path{"include/fieldmap.h"}, text_formatter));
108 providers.push_back(std::make_unique<DefaultProvider>());
109 return {std::move(providers), yaml_provider};
110 }
111
112 public:
113 TilesetCommandEnv(std::filesystem::path root, const CliOptionStorage &cli_storage)
114 : project_root{std::move(root)}, injector{di::get_formatter_component, !isatty(STDERR_FILENO)},
117 provider_chain{make_provider_chain(project_root, cli_storage, text_formatter, &stderr_diag)},
118 yaml_provider{provider_chain.yaml_provider}, config{text_formatter, std::move(provider_chain.providers)}
119 {
120 }
121
131 [[nodiscard]] ChainableResult<void> initialize(const std::string &tileset_name)
132 {
133 // Eagerly validate all YAML config files for unknown keys
134 if (yaml_provider->preload_and_validate(ConfigScopeType::tileset, tileset_name)) {
135 return FormattableError{
136 "Configuration validation failed for tileset '{}'.", FormatParam{tileset_name, Style::bold}};
137 }
138
139 // Build diagnostic filters from config values
141 warnings_exclude, config.diagnostic_warnings_exclude(ConfigScopeType::tileset, tileset_name), void);
143 warnings_include, config.diagnostic_warnings_include(ConfigScopeType::tileset, tileset_name), void);
145 remarks_exclude, config.diagnostic_remarks_exclude(ConfigScopeType::tileset, tileset_name), void);
147 remarks_include, config.diagnostic_remarks_include(ConfigScopeType::tileset, tileset_name), void);
148
149 DiagnosticTagFilter warning_filter{std::move(warnings_exclude).value(), std::move(warnings_include).value()};
150 DiagnosticTagFilter remark_filter{std::move(remarks_exclude).value(), std::move(remarks_include).value()};
151
152 // Wrap with filter decorator for all subsequent operations
153 // TODO: YamlFileProvider keeps emitting through the raw stderr sink even after this point (see
154 // make_provider_chain). Once it supports a late-bound diagnostics sink, rebind it to the filtered one here.
155 diag = std::make_unique<FilteredUserDiagnostics>(
156 text_formatter, &stderr_diag, std::move(warning_filter), std::move(remark_filter));
157 return {};
158 }
159
164
165 std::filesystem::path project_root;
166 fruit::Injector<TextFormatter> injector;
169
170 private:
171 // Bridges make_provider_chain's single return value across the member initializers: the handles copy out,
172 // config takes ownership of the vector. After construction the providers vector is moved-from and empty.
173 ProviderChain provider_chain;
174
175 public:
176 // Typed handle to the YamlFileProvider owned by config's provider list, needed for eager YAML validation.
177 gsl::not_null<YamlFileProvider *> yaml_provider;
179 std::unique_ptr<FilteredUserDiagnostics> diag;
180};
181
193};
194
201resolve_attribute_context(TilesetCommandEnv &env, const std::string &tileset_name)
202{
203 MetatileAttributeSchemaResolver resolver{env.project_root, &env.config, env.text_formatter, env.diag.get()};
204 PT_TRY_ASSIGN_PASS_ERR(resolved, resolver.resolve(tileset_name), ResolvedAttributeContext);
205 ProviderMap provider_map =
206 build_provider_map(env.project_root, resolved.schema, env.text_formatter, env.diag.get());
207 return ResolvedAttributeContext{std::move(resolved), std::move(provider_map)};
208}
209
225 public:
227 : tile_printer{std::make_unique<AsciiTilePrinter>(env.text_formatter)},
228 palette_printer{std::make_unique<ColorPalettePrinter>(env.text_formatter)}, jasc_loader{env.text_formatter},
229 jasc_saver{env.text_formatter}, anim_json_parser{env.text_formatter},
230 anim_code_parser{env.text_formatter, env.diag.get()},
231 metadata_provider{env.project_root, env.text_formatter, env.diag.get()},
232 layout_metadata_provider{env.project_root, env.text_formatter, env.diag.get()},
233 metadata_writer{env.project_root, env.text_formatter}, incbin_appender{env.project_root, env.text_formatter},
234 tileset_anims_modifier{env.project_root, &env.config, env.diag.get()}, resolved{std::move(context.resolved)},
235 provider_map{std::move(context.provider_map)},
237 env.project_root,
240 &env.config,
241 resolved.declaration_bytes,
242 env.diag.get(),
245 attributes_csv_loader{env.text_formatter, &env.config, env.diag.get()},
246 key_provider{env.project_root, &env.config, &metadata_provider, env.text_formatter, env.diag.get()},
248 env.project_root,
249 &resolved.schema,
259 &env.config,
260 &env.config,
261 env.project_root,
262 &resolved.schema,
264 env.text_formatter,
265 env.diag.get(),
268 &jasc_saver,
271 checksum_provider{env.project_root},
272 repo{
278 env.diag.get()},
279 compiler{
280 &env.config,
281 &resolved.schema,
282 env.text_formatter,
283 env.diag.get(),
284 tile_printer.get(),
285 palette_printer.get()}
286 {
287 }
288
293
294 std::unique_ptr<TilePrinter> tile_printer;
295 std::unique_ptr<PalettePrinter> palette_printer;
310 // The invocation's resolved schema and its provider map, moved in from the pre-resolved context and shared by
311 // every consumer below.
322};
323
324} // namespace porytiles
#define PT_TRY_ASSIGN_PASS_ERR(var, expr, return_type)
Unwraps a ChainableResult, passing through the error chain with an empty FormattableError when types ...
Generates C header code for tileset animations.
Parses C code to extract tileset animation parameters using callback chain discovery.
Parses and writes animation configuration JSON files (anim.json).
ChainableResult< ConfigValue< std::vector< std::string > > > diagnostic_remarks_include(ConfigScopeType type, const std::string &scope) const
ChainableResult< ConfigValue< std::vector< std::string > > > diagnostic_warnings_exclude(ConfigScopeType type, const std::string &scope) const
ChainableResult< ConfigValue< std::vector< std::string > > > diagnostic_warnings_include(ConfigScopeType type, const std::string &scope) const
ChainableResult< ConfigValue< std::vector< std::string > > > diagnostic_remarks_exclude(ConfigScopeType type, const std::string &scope) const
A TilePrinter implementation that generates ASCII art tiles with formatting based on the provided Tex...
A service that loads metatile attributes from a CSV file.
A result type that maintains a chainable sequence of errors for debugging and error reporting.
Regex-based include/exclude filter for diagnostic tags.
A text parameter with associated styling for formatted output.
General-purpose error implementation with formatted message support.
Definition error.hpp:57
Appends INCBIN declarations for Porytiles-managed tileset assets.
An implementation of FilePaletteLoader that loads palettes from JASC-PAL (Paintshop Pro) palette file...
An implementation of FilePaletteSaver that saves palettes to JASC-PAL (Paintshop Pro) palette files.
A Config implementation that lazily pulls a config value by consulting multiple priority-ordered back...
Resolves the invocation's metatile attribute schema: fetch config, scan, infer, reconcile.
An image loader that reads PNG files to create an Image with an index pixel type.
An image saver that saves PNG files from an Image with an index pixel type.
An image loader that reads PNG files to create an Image with an Rgba32 pixel type.
An image saver that saves PNG files from an Image with an Rgba32 pixel type.
Pokeemerald project filesystem-based implementation of ArtifactChecksumProvider.
Provides a pokeemerald project filesystem-based implementation for LayoutMetadataProvider.
Manages Porytiles-owned tilesets via TilesetManifest JSON files.
Modifies tileset_anims.c to include Porytiles-managed animation code headers.
Provides a pokeemerald project filesystem-based implementation for TilesetArtifactKeyProvider.
Provides a filesystem-based implementation for TilesetArtifactReader.
Provides a filesystem-based implementation for TilesetArtifactWriter.
Provides a pokeemerald project filesystem-based implementation for TilesetMetadataProvider.
Provides surgical update capability for tileset metadata in headers.h files.
Concrete implementation of UserDiagnostics that outputs structured messages to stderr,...
static const Style bold
Bold text formatting.
Abstract base class for applying text styling with context-aware formatting.
Bootstrap class so every tileset command can share common config and diagnostic setup.
TilesetCommandEnv & operator=(const TilesetCommandEnv &)=delete
fruit::Injector< TextFormatter > injector
TilesetCommandEnv(std::filesystem::path root, const CliOptionStorage &cli_storage)
TilesetCommandEnv & operator=(TilesetCommandEnv &&)=delete
std::unique_ptr< FilteredUserDiagnostics > diag
ChainableResult< void > initialize(const std::string &tileset_name)
Runs the fallible half of env setup: YAML validation and the diagnostic filter construction.
StderrStyledUserDiagnostics stderr_diag
TilesetCommandEnv(TilesetCommandEnv &&)=delete
TilesetCommandEnv(const TilesetCommandEnv &)=delete
gsl::not_null< YamlFileProvider * > yaml_provider
The schema-driven service graph shared by the compile, create, import, and decompile commands.
std::unique_ptr< TilePrinter > tile_printer
ProjectArtifactChecksumProvider checksum_provider
ProjectTilesetMetadataProvider metadata_provider
TilesetCommandServices(TilesetCommandServices &&)=delete
ProjectPorytilesTilesetManager tileset_manager
TilesetCommandServices & operator=(const TilesetCommandServices &)=delete
TilesetCommandServices & operator=(TilesetCommandServices &&)=delete
std::unique_ptr< PalettePrinter > palette_printer
ProjectTilesetAnimsModifier tileset_anims_modifier
ProjectTilesetArtifactReader artifact_reader
TilesetCommandServices(TilesetCommandEnv &env, ResolvedAttributeContext context)
ProjectTilesetMetadataWriter metadata_writer
ProjectTilesetArtifactWriter artifact_writer
TilesetCommandServices(const TilesetCommandServices &)=delete
ProjectTilesetArtifactKeyProvider key_provider
LoadedMetatileAttributeSchema resolved
ProjectLayoutMetadataProvider layout_metadata_provider
Service that compiles a Tileset (primary or secondary).
Repository interface for the Tileset aggregate root.
A ConfigProvider implementation that reads configuration values from multiple YAML files with priorit...
std::size_t resolve_terminal_width(int fd, std::size_t fallback=80)
Resolves the column width to use for wrapping diagnostic output on fd.
std::map< std::string, std::unique_ptr< EnumMapProvider >, std::less<> > ProviderMap
Maps schema field names to the provider that names that field's values.
ChainableResult< ResolvedAttributeContext > resolve_attribute_context(TilesetCommandEnv &env, const std::string &tileset_name)
Resolves the invocation's metatile attribute schema and builds the provider map for its fields.
@ tileset
Configuration scoped to a specific tileset.
ProviderMap build_provider_map(const std::filesystem::path &project_root, const Schema &schema, gsl::not_null< const TextFormatter * > format, gsl::not_null< const UserDiagnostics * > diag)
Builds a header provider for every provider-backed field in a schema.
Storage struct for CLI option values.
The product of reconciling the project's metatile attribute schema.
The invocation's resolved attribute schema and provider map, produced before the service graph.