add include callback

This commit is contained in:
pantor
2021-09-07 10:00:33 +02:00
parent 9b9dd96a46
commit cf71b54151
8 changed files with 770 additions and 682 deletions
+3
View File
@@ -5,6 +5,7 @@
#include <string>
#include "string_view.hpp"
#include "template.hpp"
namespace inja {
@@ -65,6 +66,8 @@ struct LexerConfig {
*/
struct ParserConfig {
bool search_included_templates_in_files {true};
std::function<Template(const std::string&, const std::string&)> include_callback;
};
/*!
+11 -1
View File
@@ -161,7 +161,10 @@ public:
json load_json(const std::string &filename) {
std::ifstream file;
open_file_or_throw(input_path + filename, file);
file.open(input_path + filename);
if (file.fail()) {
INJA_THROW(FileError("failed accessing file at '" + input_path + filename + "'"));
}
json j;
file >> j;
return j;
@@ -202,6 +205,13 @@ public:
void include_template(const std::string &name, const Template &tmpl) {
template_storage[name] = tmpl;
}
/*!
@brief Sets a function that is called when an included file is not found
*/
void set_include_callback(const std::function<Template(const std::string&, const std::string&)>& callback) {
parser_config.include_callback = callback;
}
};
/*!
+1
View File
@@ -6,6 +6,7 @@
#include "function_storage.hpp"
#include "string_view.hpp"
#include "utils.hpp"
namespace inja {
+34 -7
View File
@@ -86,19 +86,43 @@ class Parser {
}
void add_to_template_storage(nonstd::string_view path, std::string& template_name) {
if (config.search_included_templates_in_files && template_storage.find(template_name) == template_storage.end()) {
if (template_storage.find(template_name) != template_storage.end()) {
return;
}
std::string original_path = static_cast<std::string>(path);
std::string original_name = template_name;
if (config.search_included_templates_in_files) {
// Build the relative path
template_name = static_cast<std::string>(path) + template_name;
template_name = original_path + original_name;
if (template_name.compare(0, 2, "./") == 0) {
template_name.erase(0, 2);
}
if (template_storage.find(template_name) == template_storage.end()) {
auto include_template = Template(load_file(template_name));
template_storage.emplace(template_name, include_template);
parse_into_template(template_storage[template_name], template_name);
// Load file
std::ifstream file;
file.open(template_name);
if (!file.fail()) {
std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
auto include_template = Template(text);
template_storage.emplace(template_name, include_template);
parse_into_template(template_storage[template_name], template_name);
return;
} else if (!config.include_callback) {
INJA_THROW(FileError("failed accessing file at '" + template_name + "'"));
}
}
}
// Try include callback
if (config.include_callback) {
auto include_template = config.include_callback(original_path, original_name);
template_storage.emplace(template_name, include_template);
}
}
bool parse_expression(Template &tmpl, Token::Kind closing) {
@@ -632,9 +656,12 @@ public:
sub_parser.parse_into(tmpl, path);
}
std::string load_file(nonstd::string_view filename) {
std::string load_file(const std::string& filename) {
std::ifstream file;
open_file_or_throw(static_cast<std::string>(filename), file);
file.open(filename);
if (file.fail()) {
INJA_THROW(FileError("failed accessing file at '" + filename + "'"));
}
std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
return text;
}
-13
View File
@@ -11,19 +11,6 @@
namespace inja {
inline void open_file_or_throw(const std::string &path, std::ifstream &file) {
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
#ifndef INJA_NOEXCEPTION
try {
file.open(path);
} catch (const std::ios_base::failure & /*e*/) {
INJA_THROW(FileError("failed accessing file at '" + path + "'"));
}
#else
file.open(path);
#endif
}
namespace string_view {
inline nonstd::string_view slice(nonstd::string_view view, size_t start, size_t end) {
start = std::min(start, view.size());