Repository: mitsuhiko/minijinja (language: 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.


Discussion / hints:
This is happening because slicing returns an iterator and not a sequence.  You can solve this by using `|list`:

```jinja
{{ ([1,2,3][1:]|list)[0] }}
```

This is not how it works in Jinja2 but I wonder if it's reasonable to stringify this as it seems a bit of a weird edge case.  However this also makes me wonder if it should not be possible to index into an iterable.  Since they are (usually) restartable in MiniJinja that wouldn't be the worst in the world.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 671ce0e4..be2316df 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 c557ad5b..08fc24d7 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 9360a945..622cdad1 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 59cd4dd7..fbb00b7a 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