diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/template.c | 68 | ||||
-rw-r--r-- | src/template.h | 5 |
2 files changed, 68 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 |