aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny van Kooten <dannyvankooten@users.noreply.github.com>2020-03-20 14:38:18 +0100
committerDanny van Kooten <dannyvankooten@users.noreply.github.com>2020-03-20 14:38:18 +0100
commitd38575d2b97f7a86cfe6dd93df7de31612e19890 (patch)
treec2040791e14ace117fb3ada5df2a522f0273b51a
parentfbfe506e2e7e2c86763997057d7e10c691c61b32 (diff)
downloadunja-d38575d2b97f7a86cfe6dd93df7de31612e19890.tar.gz
unja-d38575d2b97f7a86cfe6dd93df7de31612e19890.zip
add first filter: trim
-rw-r--r--src/template.c41
-rw-r--r--tests/test_template.c11
2 files changed, 48 insertions, 4 deletions
diff --git a/src/template.c b/src/template.c
index 0d1faa8..1c1945e 100644
--- a/src/template.c
+++ b/src/template.c
@@ -17,6 +17,7 @@ struct unja_object {
enum unja_object_type type;
int integer;
char *string;
+ char *string_ptr;
};
struct unja_object null_object = {
@@ -82,6 +83,7 @@ mpc_parser_t *parser_init() {
mpc_parser_t *content = mpc_new("content");
mpc_parser_t *factor = mpc_new("factor");
mpc_parser_t *term = mpc_new("term");
+ mpc_parser_t *filter = mpc_new("filter");
template = mpc_new("template");
mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE,
@@ -91,7 +93,8 @@ mpc_parser_t *parser_init() {
" text : /[^{][^{%#]*/;"
" string : '\"' /([^\"])*/ '\"' ;"
" factor : <symbol> | <number> | <string> ;"
- " term : <factor> (<spaces> ('*' | '/' | '%') <spaces> <factor>)* ;"
+ " filter : <spaces> '|' <spaces> <symbol>; "
+ " term : <factor> (<spaces> ('*' | '/' | '%') <spaces> <factor>)* <filter>?;"
" lexp : <term> (<spaces> ('+' | '-') <spaces> <term>)* ;"
" expression: <lexp> <spaces> '>' <spaces> <lexp> "
" | <lexp> <spaces> '<' <spaces> <lexp> "
@@ -114,6 +117,7 @@ mpc_parser_t *parser_init() {
" body : <content>* ;"
" template : /^/ <body> /$/ ;",
spaces,
+ filter,
factor,
term,
symbol,
@@ -270,7 +274,9 @@ struct unja_object *make_string_object(char *value, char *value2) {
l += strlen(value2);
}
+
obj->string = malloc(l);
+ obj->string_ptr = obj->string;
strcpy(obj->string, value);
if(value2) {
@@ -319,7 +325,7 @@ void object_free(struct unja_object *obj) {
switch(obj->type) {
case OBJ_NULL: return;
case OBJ_STRING:
- free(obj->string);
+ free(obj->string_ptr);
break;
case OBJ_INT: break;
}
@@ -339,6 +345,7 @@ int object_is_truthy(struct unja_object *obj) {
struct context {
struct hashmap *vars;
+ struct hashmap *filters;
struct env *env;
struct template *current_template;
};
@@ -451,8 +458,21 @@ struct unja_object *eval_expression(mpc_ast_t* expr, struct context *ctx) {
unsigned int offset = 0;
mpc_ast_t *left_node = expr->children[0];
struct unja_object *left = eval_expression(left_node, ctx);
+ result = left;
+
+ while (offset < (expr->children_num - 1)) {
+ /* Check if we arrived at a filter (guaranteed to be last in expression list) */
+ if (strstr(expr->children[offset+1]->tag, "filter")) {
+ char *filter_name = expr->children[offset+1]->children[3]->contents;
+ struct unja_object *(*filter_fn)(struct unja_object *) = hashmap_get(ctx->filters, filter_name);
+ if (NULL == filter_fn) {
+ errx(EXIT_FAILURE, "unknown filter: %s", filter_name);
+ }
+ result = filter_fn(result);
+ break;
+ }
+
- while (offset < expr->children_num - 1) {
mpc_ast_t *op = expr->children[offset+2];
mpc_ast_t *right_node = expr->children[offset+4];
struct unja_object *right = eval_expression(right_node, ctx);
@@ -598,7 +618,6 @@ int eval(struct buffer *buf, mpc_ast_t* t, struct context *ctx) {
return 0;
}
-
char *render_ast(mpc_ast_t *ast, struct context *ctx) {
#if DEBUG
printf("AST: \n");
@@ -615,12 +634,26 @@ char *render_ast(mpc_ast_t *ast, struct context *ctx) {
return buf.string;
}
+struct unja_object *filter_trim(struct unja_object *in) {
+ /* TODO: Keep original pointer */
+ in->string = trim_leading_whitespace(in->string);
+ trim_trailing_whitespace(in->string);
+ return in;
+}
+
+struct hashmap *default_filters() {
+ struct hashmap *filters = hashmap_new();
+ hashmap_insert(filters, "trim", filter_trim);
+ return filters;
+}
+
char *template_string(char *tmpl, struct hashmap *vars) {
#if DEBUG
printf("Template: %s\n", tmpl);
#endif
mpc_ast_t *ast = parse(tmpl);
struct context ctx;
+ ctx.filters = default_filters();
ctx.vars = vars;
ctx.env = NULL;
ctx.current_template = NULL;
diff --git a/tests/test_template.c b/tests/test_template.c
index 758f7fb..b0f03ff 100644
--- a/tests/test_template.c
+++ b/tests/test_template.c
@@ -454,4 +454,15 @@ TEST(inheritance_depth_2) {
env_free(env);
}
+TEST(filter) {
+ char *input = "{{ text | trim }}";
+ struct hashmap *ctx = hashmap_new();
+ char *text = "\nHello world\n";
+ hashmap_insert(ctx, "text", text);
+ char *output = template_string(input, ctx);
+ assert_str(output, "Hello world");
+ hashmap_free(ctx);
+ free(output);
+}
+
END_TESTS \ No newline at end of file