From 482f06ee25b629c12e0db8478c9d01a3d562fd56 Mon Sep 17 00:00:00 2001 From: soup Date: Sun, 19 May 2024 01:52:05 -0400 Subject: [PATCH] Fix some bugs --- src/internal/execute.rs | 4 +++- src/internal/parse.rs | 33 +++++++++++++++++++++++++++++++ src/lib.rs | 43 +++++++++++++++++++++++++++++++---------- 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/src/internal/execute.rs b/src/internal/execute.rs index 2952454..5f8b489 100644 --- a/src/internal/execute.rs +++ b/src/internal/execute.rs @@ -27,6 +27,8 @@ pub fn lookup<'a>( path: &ValuePath, value: &'a dyn Value, ) -> Option<&'a dyn Value> { + dbg!(value); + dbg!(path); let mut value = value; for name in &path.0 { match value.lookup(name) { @@ -60,6 +62,6 @@ pub fn for_(out: &mut String, f: &For, value: &dyn Value) { let mut idx = 0; while let Some(value) = value.for_(idx) { execute_(out, &f.body, value); - idx += 0; + idx += 1; } } diff --git a/src/internal/parse.rs b/src/internal/parse.rs index 83fb24f..8490e36 100644 --- a/src/internal/parse.rs +++ b/src/internal/parse.rs @@ -156,6 +156,8 @@ impl<'a> ParseState<'a> { } inner.parse_one(); } + inner.text_might_end(); + inner.add_current_text_to_ast(); self.current_byte_offset = inner.current_byte_offset; if !self.remaining().starts_with("{/for}") { return; @@ -269,4 +271,35 @@ mod test { })], ); } + + #[test] + fn parse_for_2() { + go( + "{for .}{.}, {/for}", + vec![AstKind::For(For { + expr: ValuePath(vec![]), + body: vec![ + AstKind::Print(Print(ValuePath(vec![]))), + AstKind::Text(", ".to_string()), + ], + })], + ); + } + + #[test] + fn parse_for_nested() { + go( + "{for .items}{for .names}{.},{/for}{/for}", + vec![AstKind::For(For { + expr: ValuePath(vec!["items".to_string()]), + body: vec![AstKind::For(For { + expr: ValuePath(vec!["names".to_string()]), + body: vec![ + AstKind::Print(Print(ValuePath(vec![]))), + AstKind::Text(",".to_string()), + ], + })], + })], + ) + } } diff --git a/src/lib.rs b/src/lib.rs index d0a8d95..a0fa67e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ use internal::{ parse::{parse, Ast}, }; -pub trait Value { +pub trait Value: core::fmt::Debug { fn print(&self, out: &mut String); fn lookup(&self, name: &str) -> Option<&dyn Value>; fn has(&self) -> Option<&dyn Value>; @@ -212,24 +212,47 @@ impl Newt { mod test { use crate::{Newt, Value}; + fn go(tmpl: &str, value: &dyn Value, expected: &str) { + assert_eq!(Newt::build(tmpl).execute(value), expected) + } + #[test] fn simple_print() { - let tmpl = r#"Hello, {.}"#; - let out = Newt::build(tmpl).execute(&"World!"); - assert_eq!(out, "Hello, World!"); + go("Hello, {.}!", &"World", "Hello, World!") } #[test] fn print_lookup() { - let tmpl = "Hello, {.name}!"; - let out = Newt::build(tmpl).execute(&[("name", &"Ted" as &dyn Value)]); - assert_eq!(out, "Hello, Ted!"); + go( + "Hello, {.name}!", + &[("name", &"Ted" as &dyn Value)], + "Hello, Ted!", + ); } #[test] fn print_for() { - let tmpl = "{for .}{.}, {/for}"; - let out = Newt::build(tmpl).execute(&[&"Bob" as &dyn Value, &"Larry"]); - assert_eq!(out, "Bob, Larry"); + go( + "{for .}{.}, {/for}", + &[&"Bob" as &dyn Value, &"Larry"], + "Bob, Larry, ", + ); + } + + #[test] + fn print_for_nested() { + go( + "{for .items}{for .names}{.}, {/for}{/for}", + &[( + "items", + &[ + &[( + "names", + &[&"Bob" as &dyn Value, &"Larry"] as &dyn Value, + )] as &dyn Value, + ] as &dyn Value, + )], + "Bob, Larry, ", + ) } }