pebble icon indicating copy to clipboard operation
pebble copied to clipboard

Introduce "do" tag from Twig

Open pwolaq opened this issue 5 years ago • 3 comments

Hello,

I was wondering if you thought about implementing do tag from twig - recently I wanted to modify a list in Pebble and I ended up using hacks like this:

{% set arr = [] %}
{{ arr.add("item") ? "" : "" }}

With do tag I could do it like this:

{% set arr = [] %}
{% do arr.add("item") %}

Or maybe there is another solution? If no, I would be happy to help with implementing the do tag.

pwolaq avatar Mar 11 '21 11:03 pwolaq

Perhaps you could make something using this? https://pebbletemplates.io/wiki/guide/extending-pebble/#tags

ogrammer avatar Mar 13 '21 19:03 ogrammer

I made one for you.

Create DoTokenParser.java from this code:

import com.mitchellbosecke.pebble.extension.NodeVisitor;
import com.mitchellbosecke.pebble.lexer.Token;
import com.mitchellbosecke.pebble.lexer.TokenStream;
import com.mitchellbosecke.pebble.node.AbstractRenderableNode;
import com.mitchellbosecke.pebble.node.RenderableNode;
import com.mitchellbosecke.pebble.node.expression.Expression;
import com.mitchellbosecke.pebble.parser.Parser;
import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
import com.mitchellbosecke.pebble.tokenParser.TokenParser;

import java.io.Writer;

public class DoTokenParser implements TokenParser {

	public static class DoNode extends AbstractRenderableNode {

		public final Expression<?> expression;

		public DoNode(int lineNumber, Expression<?> expression) {
			super(lineNumber);
			this.expression = expression;
		}

		@Override
		public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) {
			expression.evaluate(self, context);
		}

		@Override
		public void accept(NodeVisitor visitor) {
			visitor.visit(this);
		}
	}

	public String getTag() {
		return "do";
	}

	@Override
	public RenderableNode parse(Token token, Parser parser) {
		TokenStream stream = parser.getStream();
		int lineNumber = token.getLineNumber();

		// skip the "do" token
		stream.next();

		// use the built in expression parser to parse the expression
		Expression<?> expression = parser.getExpressionParser().parseExpression();

		// expect to see "%}"
		stream.expect(Token.Type.EXECUTE_END);

		return new DoNode(lineNumber, expression);
	}
}

And then use this on your PebbleEngine builder:

		.extension(new AbstractExtension() {
			@Override
			public List<TokenParser> getTokenParsers() {
				return Collections.singletonList(new DoTokenParser());
			}
		})

ogrammer avatar Mar 13 '21 19:03 ogrammer

Yes, I thought about it but I think it might be useful for others too so instead of using extensions I suggested adding this to the core library.

Anyway, thanks for your help :)

pwolaq avatar Mar 13 '21 20:03 pwolaq