diff options
author | Danny van Kooten <dannyvankooten@users.noreply.github.com> | 2020-03-17 16:12:55 +0100 |
---|---|---|
committer | Danny van Kooten <dannyvankooten@users.noreply.github.com> | 2020-03-17 16:12:55 +0100 |
commit | f5f04edbf832aa2e219c621b9895c33dce3e47ba (patch) | |
tree | 5f99786426b1df0402f3c6d61b590a2376c05862 | |
parent | 735d8becf2595c8fee990b55e2d323317f019c8d (diff) | |
download | unja-f5f04edbf832aa2e219c621b9895c33dce3e47ba.tar.gz unja-f5f04edbf832aa2e219c621b9895c33dce3e47ba.zip |
first stab at supporting template inheritance
-rw-r--r-- | src/template.c | 68 | ||||
-rw-r--r-- | src/template.h | 5 | ||||
-rw-r--r-- | tests/data/01/base.tmpl | 9 | ||||
-rw-r--r-- | tests/data/01/child.tmpl | 5 | ||||
-rw-r--r-- | tests/test_template.c | 8 |
5 files changed, 90 insertions, 5 deletions
diff --git a/src/template.c b/src/template.c index 7aa3a75..c43827a 100644 --- a/src/template.c +++ b/src/template.c @@ -1,6 +1,8 @@ #include <stdio.h> #include <stdlib.h> #include <err.h> +#include <unistd.h> +#include <dirent.h> #include "vendor/mpc.h" #include "template.h" @@ -26,6 +28,11 @@ struct buffer { char *string; }; +struct env { + struct hashmap *templates; +}; + +/* ensure buffer has room for a string sized l, grows buffer capacity if needed */ void buffer_reserve(struct buffer *buf, int l) { int req_size = buf->size + l; if (req_size >= buf->cap) { @@ -40,14 +47,44 @@ void buffer_reserve(struct buffer *buf, int l) { } } +struct env *env_new(char *dirname) { + DIR *dr = opendir(dirname); + if (dr == NULL) { + err(EXIT_FAILURE, "could not open directory %s", dirname); + } + + struct env *env = malloc(sizeof *env); + env->templates = hashmap_new(); + chdir(dirname); + + struct dirent *de; + while ((de = readdir(dr)) != NULL) { + // skip files starting with a dot + if (de->d_name[0] == '.') { + continue; + } + + char *name = de->d_name; + char *tmpl = read_file(name); + hashmap_insert(env->templates, name, tmpl); + } + + closedir(dr); + return env; +} + +void env_free(struct env *env) { + // TODO: Free template strings + free(env); +} + char *read_file(char *filename) { char *input = malloc(BUFSIZ); unsigned int size = 0; FILE *f = fopen(filename, "r"); if (!f) { - printf("Could not open \"%s\" for reading", filename); - exit(1); + err(EXIT_FAILURE, "Could not open \"%s\" for reading", filename); } unsigned int read = 0; @@ -217,6 +254,20 @@ struct unja_object *eval_expression(mpc_ast_t* expr, struct hashmap *ctx) { int eval(struct buffer *buf, mpc_ast_t* t, struct hashmap *ctx) { static int trim_whitespace = 0; + + if (strstr(t->tag, "content|statement|extends")) { + char *template_name = t->children[2]->children[1]->contents; + // TODO: Render given template instead + // but replace blocks with blocks in current template + return 0; + } + + + if (strstr(t->tag, "content|statement|block")) { + char *block_name = t->children[2]->contents; + return eval(buf, t->children[4], ctx); + } + // eval print statement if (strstr(t->tag, "content|print")) { // maybe eat whitespace going backward @@ -275,8 +326,11 @@ int eval(struct buffer *buf, mpc_ast_t* t, struct hashmap *ctx) { return 0; } - for (int i=0; i < t->children_num; i++) { - eval(buf, t->children[i], ctx); + + if (strstr(t->tag, ">")) { + for (int i=0; i < t->children_num; i++) { + eval(buf, t->children[i], ctx); + } } return 0; @@ -318,7 +372,7 @@ mpc_parser_t *parser_init() { " statement_open: \"{%\" /-? */;" " statement_close: / *-?/ \"%}\";" " for : <statement_open> \"for \" <symbol> \"in\" <symbol> <statement_close> <body> <statement_open> \"endfor\" <statement_close> ;" - " block : <statement_open> \"block \" <symbol> <statement_close> <statement_open> \"endblock\" <statement_close>;" + " block : <statement_open> \"block \" <symbol> <statement_close> <body> <statement_open> \"endblock\" <statement_close>;" " extends : <statement_open> \"extends \" <string> <statement_close>;" " if : <statement_open> \"if \" <expression> <statement_close> <body> (<statement_open> \"else\" <statement_close> <body>)? <statement_open> \"endif\" <statement_close> ;" " statement : <for> | <block> | <extends> | <if> ;" @@ -375,3 +429,7 @@ char *template(char *tmpl, struct hashmap *ctx) { return buf.string; } +char *render(struct env *env, char *template_name, struct hashmap *ctx) { + char *tmpl = hashmap_get(env->templates, template_name); + return template(tmpl, ctx); +}
\ No newline at end of file diff --git a/src/template.h b/src/template.h index 36d540d..f65da47 100644 --- a/src/template.h +++ b/src/template.h @@ -3,3 +3,8 @@ char *read_file(char *filename); char *template(char *tmpl, struct hashmap *ctx); + +struct env; +struct env *env_new(); +void env_free(struct env *env); +char *render(struct env *env, char *template_name, struct hashmap *ctx);
\ No newline at end of file diff --git a/tests/data/01/base.tmpl b/tests/data/01/base.tmpl new file mode 100644 index 0000000..6ca89cb --- /dev/null +++ b/tests/data/01/base.tmpl @@ -0,0 +1,9 @@ +Header + +{% block content %} +Content +{% endblock %} + +{% block footer %} +Footer +{% endblock %}
\ No newline at end of file diff --git a/tests/data/01/child.tmpl b/tests/data/01/child.tmpl new file mode 100644 index 0000000..05467a6 --- /dev/null +++ b/tests/data/01/child.tmpl @@ -0,0 +1,5 @@ +{% extends "base.tmpl" %} + +{% block content %} +Child content +{% endblock %}
\ No newline at end of file diff --git a/tests/test_template.c b/tests/test_template.c index c13ef4c..cc57ba5 100644 --- a/tests/test_template.c +++ b/tests/test_template.c @@ -215,6 +215,14 @@ TEST(buffer_alloc) { free(output); } +TEST(directory) { + struct env *env = env_new("./tests/data/01/"); + char *output = render(env, "child.tmpl", NULL); + assert_str(output, "Header\n\nChild content\n\nFooter"); + free(output); + env_free(env); +} + END_TESTS
\ No newline at end of file |