aboutsummaryrefslogtreecommitdiffstats
path: root/askama_derive
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--askama_derive/Cargo.toml2
-rw-r--r--askama_derive/src/generator.rs (renamed from askama/src/generator.rs)0
-rw-r--r--askama_derive/src/lib.rs73
-rw-r--r--askama_derive/src/parser.rs (renamed from askama/src/parser.rs)0
-rw-r--r--askama_derive/src/path.rs19
5 files changed, 91 insertions, 3 deletions
diff --git a/askama_derive/Cargo.toml b/askama_derive/Cargo.toml
index 5018beb..605c40f 100644
--- a/askama_derive/Cargo.toml
+++ b/askama_derive/Cargo.toml
@@ -12,5 +12,5 @@ workspace = ".."
proc-macro = true
[dependencies]
-askama = { path = "../askama", version = "0.2.1" }
+nom = "2.1"
syn = "0.11"
diff --git a/askama/src/generator.rs b/askama_derive/src/generator.rs
index 16209cd..16209cd 100644
--- a/askama/src/generator.rs
+++ b/askama_derive/src/generator.rs
diff --git a/askama_derive/src/lib.rs b/askama_derive/src/lib.rs
index 4b96e17..752978e 100644
--- a/askama_derive/src/lib.rs
+++ b/askama_derive/src/lib.rs
@@ -1,9 +1,78 @@
-extern crate askama;
+#[macro_use]
+extern crate nom;
extern crate proc_macro;
extern crate syn;
use proc_macro::TokenStream;
+mod generator;
+mod parser;
+mod path;
+
+// Holds metadata for the template, based on the `template()` attribute.
+struct TemplateMeta {
+ path: String,
+ print: String,
+}
+
+// Returns a `TemplateMeta` based on the `template()` attribute data found
+// in the parsed struct or enum. Will panic if it does not find the required
+// template path, or if the `print` key has an unexpected value.
+fn get_template_meta(ast: &syn::DeriveInput) -> TemplateMeta {
+ let mut path = None;
+ let mut print = "none".to_string();
+ let attr = ast.attrs.iter().find(|a| a.name() == "template").unwrap();
+ if let syn::MetaItem::List(_, ref inner) = attr.value {
+ for nm_item in inner {
+ if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
+ if let syn::MetaItem::NameValue(ref key, ref val) = *item {
+ match key.as_ref() {
+ "path" => if let syn::Lit::Str(ref s, _) = *val {
+ path = Some(s.clone());
+ } else {
+ panic!("template path must be string literal");
+ },
+ "print" => if let syn::Lit::Str(ref s, _) = *val {
+ print = s.clone();
+ } else {
+ panic!("print value must be string literal");
+ },
+ _ => { panic!("unsupported annotation key found") }
+ }
+ }
+ }
+ }
+ }
+ if path.is_none() {
+ panic!("template path not found in struct attributes");
+ }
+ TemplateMeta { path: path.unwrap(), print: print }
+}
+
+/// Takes a `syn::DeriveInput` and generates source code for it
+///
+/// Reads the metadata from the `template()` attribute to get the template
+/// metadata, then fetches the source from the filesystem. The source is
+/// parsed, and the parse tree is fed to the code generator. Will print
+/// the parse tree and/or generated source according to the `print` key's
+/// value as passed to the `template()` attribute.
+fn build_template(ast: &syn::DeriveInput) -> String {
+ let meta = get_template_meta(ast);
+ let mut src = path::get_template_source(&meta.path);
+ if src.ends_with('\n') {
+ let _ = src.pop();
+ }
+ let nodes = parser::parse(&src);
+ if meta.print == "ast" || meta.print == "all" {
+ println!("{:?}", nodes);
+ }
+ let code = generator::generate(ast, &meta.path, nodes);
+ if meta.print == "code" || meta.print == "all" {
+ println!("{}", code);
+ }
+ code
+}
+
#[proc_macro_derive(Template, attributes(template))]
pub fn derive_template(input: TokenStream) -> TokenStream {
let ast = syn::parse_derive_input(&input.to_string()).unwrap();
@@ -11,5 +80,5 @@ pub fn derive_template(input: TokenStream) -> TokenStream {
syn::Body::Struct(ref data) => data,
_ => panic!("#[derive(Template)] can only be used with structs"),
};
- askama::build_template(&ast).parse().unwrap()
+ build_template(&ast).parse().unwrap()
}
diff --git a/askama/src/parser.rs b/askama_derive/src/parser.rs
index ce13add..ce13add 100644
--- a/askama/src/parser.rs
+++ b/askama_derive/src/parser.rs
diff --git a/askama_derive/src/path.rs b/askama_derive/src/path.rs
new file mode 100644
index 0000000..96ed8c1
--- /dev/null
+++ b/askama_derive/src/path.rs
@@ -0,0 +1,19 @@
+use std::env;
+use std::fs::File;
+use std::io::Read;
+use std::path::{Path, PathBuf};
+
+fn template_dir() -> PathBuf {
+ let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
+ path.push("templates");
+ path
+}
+
+pub fn get_template_source(tpl_file: &str) -> String {
+ let mut path = template_dir();
+ path.push(Path::new(tpl_file));
+ let mut f = File::open(path).unwrap();
+ let mut s = String::new();
+ f.read_to_string(&mut s).unwrap();
+ s
+}