Repository: mitsuhiko/minijinja (rust)

Issue:
 Element access to a slice of a list returns `undefined`
## Description
Accessing an element of a slice of an array seems impossible.
 
## Reproduction steps

Let us see this example:

```jinja2
{% set messages = ["first", "second", "third"] %}
FIRST: {{ messages[0] }}
{% set messages = messages[1:] %}
SECOND: {{ messages[0] }}
```

Result:
```
FIRST: first
SECOND: 
```

A simpler case goes like:

```jinja2
{{ [1,2,3][1:][0] }}
```
which should print "2". However, it returns `undefined` thus a blank string.

You can easily reproduce them in the minijinja playgorund.
## What did you expect
It should work as if I accessed an element of a sub-list. It seems it works in the original Jinja2 written in Python.

Pull request description:
Add support for indexing into iterables
This makes any iterable indexable.  They were already sliceable.

Fixes #564

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 671ce0e..be2316d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,9 @@ All notable changes to MiniJinja are documented here.
 - Added `filesizeformat` to minijinja-contrib.  #556
 - Added support for the `loop_controls` feature which adds
   `{% break %}` and `{% continue %}`.  #558
+- Iterables can now be indexed into.  It was already possible previously
+  to slice them.  This improves support for Jinja2 compatibility as Jinja2
+  is more likely to create temporary lists when slicing lists.  #565
 
 ## 2.1.2
 
diff --git a/minijinja/src/value/mod.rs b/minijinja/src/value/mod.rs
index c557ad5..08fc24d 100644
--- a/minijinja/src/value/mod.rs
+++ b/minijinja/src/value/mod.rs
@@ -1301,7 +1301,23 @@ impl Value {
 
         match self.0 {
             ValueRepr::Object(ref dy) => match dy.repr() {
-                ObjectRepr::Map | ObjectRepr::Plain | ObjectRepr::Iterable => dy.get_value(key),
+                ObjectRepr::Map | ObjectRepr::Plain => dy.get_value(key),
+                ObjectRepr::Iterable => {
+                    if let Some(rv) = dy.get_value(key) {
+                        return Some(rv);
+                    }
+                    // The default behavior is to try to index into the iterable
+                    // as if nth() was called.  This lets one slice an array and
+                    // then index into it.
+                    if let Some(idx) = index(key, || dy.enumerator_len()) {
+                        if let Some(mut iter) = dy.try_iter() {
+                            if let Some(rv) = iter.nth(idx) {
+                                return Some(rv);
+                            }
+                        }
+                    }
+                    None
+                }
                 ObjectRepr::Seq => {
                     let idx = index(key, || dy.enumerator_len()).map(Value::from);
                     dy.get_value(idx.as_ref().unwrap_or(key))


Test patch:
diff --git a/minijinja/tests/inputs/slicing.txt b/minijinja/tests/inputs/slicing.txt
index 9360a94..622cdad 100644
--- a/minijinja/tests/inputs/slicing.txt
+++ b/minijinja/tests/inputs/slicing.txt
@@ -15,3 +15,5 @@
 {{ intrange[::2] }}
 {{ intrange[2:10] }}
 {{ intrange[2:10:2] }}
+{{ intrange[2:10][0] }}
+{{ intrange[2:10][2:][0] }}
diff --git a/minijinja/tests/snapshots/test_templates__vm@slicing.txt.snap b/minijinja/tests/snapshots/test_templates__vm@slicing.txt.snap
index 59cd4dd..fbb00b7 100644
--- a/minijinja/tests/snapshots/test_templates__vm@slicing.txt.snap
+++ b/minijinja/tests/snapshots/test_templates__vm@slicing.txt.snap
@@ -1,6 +1,6 @@
 ---
 source: minijinja/tests/test_templates.rs
-description: "{{ hello[:] }}\n{{ hello[1:] }}\n{{ hello[1:-1] }}\n{{ hello[::2] }}\n{{ hello[2:10] }}\n{{ hello[2:10:2] }}\n{{ intrange[:] }}\n{{ intrange[1:] }}\n{{ intrange[1:-1] }}\n{{ intrange[::2] }}\n{{ intrange[2:10] }}\n{{ intrange[2:10:2] }}"
+description: "{{ hello[:] }}\n{{ hello[1:] }}\n{{ hello[1:-1] }}\n{{ hello[::2] }}\n{{ hello[2:10] }}\n{{ hello[2:10:2] }}\n{{ intrange[:] }}\n{{ intrange[1:] }}\n{{ intrange[1:-1] }}\n{{ intrange[::2] }}\n{{ intrange[2:10] }}\n{{ intrange[2:10:2] }}\n{{ intrange[2:10][0] }}\n{{ intrange[2:10][2:][0] }}"
 info:
   hello: Hällo Wörld
   intrange:
@@ -28,4 +28,5 @@ loWr
 [0, 2, 4, 6, 8]
 [2, 3, 4, 5, 6, 7, 8, 9]
 [2, 4, 6, 8]
-
+2
+4