aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny van Kooten <dannyvankooten@users.noreply.github.com>2020-03-17 16:12:55 +0100
committerDanny van Kooten <dannyvankooten@users.noreply.github.com>2020-03-17 16:12:55 +0100
commitf5f04edbf832aa2e219c621b9895c33dce3e47ba (patch)
tree5f99786426b1df0402f3c6d61b590a2376c05862
parent735d8becf2595c8fee990b55e2d323317f019c8d (diff)
downloadunja-f5f04edbf832aa2e219c621b9895c33dce3e47ba.tar.gz
unja-f5f04edbf832aa2e219c621b9895c33dce3e47ba.zip
first stab at supporting template inheritance
-rw-r--r--src/template.c68
-rw-r--r--src/template.h5
-rw-r--r--tests/data/01/base.tmpl9
-rw-r--r--tests/data/01/child.tmpl5
-rw-r--r--tests/test_template.c8
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