From 0e1b2ca857c17b02e031bd8ea3ea4ae2b10508b6 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 28 Nov 2010 16:00:01 +0100 Subject: [PATCH] Added joined by statement to for loops --- doc/02-Twig-for-Template-Designers.markdown | 14 ++++++++++++++ lib/Twig/Node/For.php | 23 +++++++++++++++++++++-- lib/Twig/TokenParser/For.php | 9 ++++++++- test/Twig/Tests/Node/ForTest.php | 17 ++++++++++++----- 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/doc/02-Twig-for-Template-Designers.markdown b/doc/02-Twig-for-Template-Designers.markdown index abc5038..91880c2 100644 --- a/doc/02-Twig-for-Template-Designers.markdown +++ b/doc/02-Twig-for-Template-Designers.markdown @@ -581,6 +581,20 @@ You can also access both keys and values: >On Twig before 0.9.3, you need to use the `items` filter to access both the >keys and values (`{% for key, value in users|items %}`). +To conveniently display comma-separated lists or things alike, you can use +`joined by ", "` at the end of the loop statement. Of course this is not +limited to commas. + + [twig] +

Members

+

+ {% for key in users|keys joined by ", " %}{{ key }}{% endfor %} +

+ +>**NOTE** +>This way you don't have to check if the item is the first or last, the comma +>will only be added in between two items. + ### If The `if` statement in Twig is comparable with the if statements of PHP. In the diff --git a/lib/Twig/Node/For.php b/lib/Twig/Node/For.php index 2f7a2df..38ad626 100644 --- a/lib/Twig/Node/For.php +++ b/lib/Twig/Node/For.php @@ -18,9 +18,9 @@ */ class Twig_Node_For extends Twig_Node { - public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $withLoop = false, $lineno, $tag = null) + public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $withLoop = false, Twig_Node_Expression $joinedBy = null, $lineno, $tag = null) { - parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => $withLoop), $lineno, $tag); + parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else, 'joined_with' => $joinedBy), array('with_loop' => $withLoop), $lineno, $tag); } /** @@ -68,6 +68,10 @@ class Twig_Node_For extends Twig_Node ; } + if (null !== $this->getNode('joined_with')) { + $compiler->write("\$context['_first_iteration'] = true;\n"); + } + $compiler ->write("foreach (\$context['_seq'] as ") ->subcompile($this->getNode('key_target')) @@ -81,6 +85,21 @@ class Twig_Node_For extends Twig_Node $compiler->write("\$context['_iterated'] = true;\n"); } + if (null !== $this->getNode('joined_with')) { + $compiler + ->write("if (\$context['_first_iteration']) {\n") + ->indent() + ->write("\$context['_first_iteration'] = false;\n") + ->outdent() + ->write("} else {\n") + ->indent() + ->write("echo ") + ->subcompile($this->getNode('joined_with')) + ->raw(";\n") + ->outdent() + ->write("}\n"); + } + $compiler->subcompile($this->getNode('body')); if ($this->getAttribute('with_loop')) { diff --git a/lib/Twig/TokenParser/For.php b/lib/Twig/TokenParser/For.php index 4fec054..42b71af 100644 --- a/lib/Twig/TokenParser/For.php +++ b/lib/Twig/TokenParser/For.php @@ -32,6 +32,13 @@ class Twig_TokenParser_For extends Twig_TokenParser $withLoop = false; } + $joinedBy = null; + if ($this->parser->getStream()->test('joined')) { + $this->parser->getStream()->next(); + $this->parser->getStream()->expect('by'); + $joinedBy = $this->parser->getExpressionParser()->parseExpression(); + } + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); $body = $this->parser->subparse(array($this, 'decideForFork')); if ($this->parser->getStream()->next()->getValue() == 'else') { @@ -50,7 +57,7 @@ class Twig_TokenParser_For extends Twig_TokenParser $valueTarget = $targets->getNode(0); } - return new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, $lineno, $this->getTag()); + return new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, $joinedBy, $lineno, $this->getTag()); } public function decideForFork($token) diff --git a/test/Twig/Tests/Node/ForTest.php b/test/Twig/Tests/Node/ForTest.php index d99109f..71144f8 100644 --- a/test/Twig/Tests/Node/ForTest.php +++ b/test/Twig/Tests/Node/ForTest.php @@ -24,7 +24,7 @@ class Twig_Tests_Node_ForTest extends Twig_Tests_Node_TestCase $body = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0); $else = null; $withLoop = false; - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, 0); + $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, null, 0); $this->assertEquals($keyTarget, $node->getNode('key_target')); $this->assertEquals($valueTarget, $node->getNode('value_target')); @@ -35,7 +35,7 @@ class Twig_Tests_Node_ForTest extends Twig_Tests_Node_TestCase $this->assertEquals($withLoop, $node->getAttribute('with_loop')); $else = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0); - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, 0); + $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, null, 0); $this->assertEquals($else, $node->getNode('else')); } @@ -58,7 +58,7 @@ class Twig_Tests_Node_ForTest extends Twig_Tests_Node_TestCase $body = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0); $else = null; $withLoop = false; - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, 0); + $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, null, 0); $tests[] = array($node, << \$context['v']) { + if (\$context['_first_iteration']) { + \$context['_first_iteration'] = false; + } else { + echo ", "; + } echo (isset(\$context['foo']) ? \$context['foo'] : null); ++\$context['loop']['index0']; ++\$context['loop']['index']; @@ -120,7 +127,7 @@ EOF $body = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0); $else = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0); $withLoop = true; - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, 0); + $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $body, $else, $withLoop, null, 0); $tests[] = array($node, <<