Repository: djc/askama (rust)

Issue:
Iterate over NewType Vec<T>
Can I use a NewType wrapper around `Vec<T>` in `for x in y` template file?

If I use something like `struct X {values: Vec<Y>}` then I can easily get its data using `for x in values`. This template will compile to `for (_loop_index, x) in (&self.values).iter_into().enumerate()`.

But I want to use NewType instead of a normal struct. 

So I need to iterate over `self.0` -> how do I write template for that?

`for x in self.0` returns `or (_loop_index, x) in (&self.self.0).into_iter().enumerate()`

`for x in 0` returns `for (_loop_index, x) in (&0).into_iter().enumerate()`

Is there something obvious that I am missing? 

This is the struct I am playing with and the template in question:

```rust
#[derive(Template)]
#[template(path = "handlers.html", print="all")]
struct VA ( Vec<A>);

impl std::ops::DerefMut for VA {
    fn deref_mut(&mut self) -> &mut Vec<A>{
        &mut self.0
    }
}
```

```jinja2
{% for a in ??? %}
...
{% endfor %}


Pull request description:
Allow referencing self as a variable (fixes #207)

Patch:
diff --git a/askama/src/lib.rs b/askama/src/lib.rs
index 2e69dfd..faf2f24 100644
--- a/askama/src/lib.rs
+++ b/askama/src/lib.rs
@@ -49,12 +49,9 @@
 //!   (`none`), the parsed syntax tree (`ast`), the generated code (`code`)
 //!   or `all` for both. The requested data will be printed to stdout at
 //!   compile time.
-//! * `escape` (as `escape = "none"`): set the escape mode for expression
-//!   output; the currently implemented modes are `none` and `html`. Askama
-//!   infers the escape mode from the template file name (with `path`) or
-//!   specified extension (`ext`): if the extension is `html`, `htm` or `xml`,
-//!   the `html` escape mode is used; otherwise, no implicit escaping is done.
-//!   Setting an escape mode explicitly overrides the inferred value.
+//! * `escape` (as `escape = "none"`): override the template's extension used for
+//!   the purpose of determining the escaper for this template. See the section
+//!   on configuring custom escapers for more information.
 //! * `syntax` (as `syntax = "foo"`): set the syntax name for a parser defined
 //!   in the configuration file. The default syntax , "default",  is the one
 //!   provided by Askama.
@@ -64,7 +61,7 @@
 //! At compile time, Askama will read optional configuration values from
 //! `askama.toml` in the crate root (the directory where `Cargo.toml` can
 //! be found). Currently, this covers the directories to search for templates,
-//! as well as custom syntax configuration.
+//! custom syntax configuration and escaper configuration.
 //!
 //! This example file demonstrates the default configuration:
 //!
@@ -109,6 +106,24 @@
 //! Values must be 2 characters long and start delimiters must all start with the same
 //! character. If a key is omitted, the value from the default syntax is used.
 //!
+//! Here is an example of a custom escaper:
+//!
+//! ```toml
+//! [[escaper]]
+//! path = "::tex_escape::Tex"
+//! extensions = ["tex"]
+//! ```
+//!
+//! An escaper block consists of the attributes `path` and `name`. `path`
+//! contains a Rust identifier that must be in scope for templates using this
+//! escaper. `extensions` defines a list of file extensions that will trigger
+//! the use of that escaper. Extensions are matched in order, starting with the
+//! first escaper configured and ending with the default escapers for HTML
+//! (extensions `html`, `htm`, `xml`, `j2`, `jinja`, `jinja2`) and plain text
+//! (no escaping; `none`, `txt`, and the empty string). Note that this means
+//! you can also define other escapers that match different extensions to the
+//! same escaper.
+//!
 //! ## Variables
 //!
 //! Top-level template variables are defined by the template's context type.
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index b0630df..8f2866e 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -1116,7 +1116,7 @@ impl<'a> Generator<'a> {
     }
 
     fn visit_var(&mut self, buf: &mut Buffer, s: &str) -> DisplayWrap {
-        if self.locals.contains(s) {
+        if self.locals.contains(s) || s == "self" {
             buf.write(s);
         } else {
             buf.write("self.");


Test patch:
diff --git a/testing/tests/vars.rs b/testing/tests/vars.rs
index 04f9ff2..da8aef6 100644
--- a/testing/tests/vars.rs
+++ b/testing/tests/vars.rs
@@ -43,3 +43,17 @@ fn test_let_decl() {
     };
     assert_eq!(t.render().unwrap(), "bar");
 }
+
+#[derive(Template)]
+#[template(
+    source = "{% for v in self.0 %}{{ v }}{% endfor %}",
+    ext = "txt",
+    print = "code"
+)]
+struct SelfIterTemplate(Vec<usize>);
+
+#[test]
+fn test_self_iter() {
+    let t = SelfIterTemplate(vec![1, 2, 3]);
+    assert_eq!(t.render().unwrap(), "123");
+}