Twig icon indicating copy to clipboard operation
Twig copied to clipboard

Allow multiple statements (semicolon)

Open rgpublic opened this issue 6 months ago • 8 comments

I wonder why no one ever asked for this before. I think Twig is by now a very mature and grownup template language. Even if we try to keep our templates clean, the need for multiple statements within a {% %} block arises very quickly. If you need e.g. 5 such statements you need 5 such {% %} blocks. It's not very readable and gets tedious fast. Therefore, I'd like to request the feature ";". It could be implemented extremely easy: It's actually just syntactic sugar for "%}{%". A ";" at the end of a block should be allowed though and just ignored. Since the ";" isn't used for anything else at the moment this wouldn't even cause a compatibility issue.

Thanks for considering & of course for making Twig :-)

rgpublic avatar Jun 24 '25 14:06 rgpublic

Twig does not have a concept of statement. It has a concept of tags, where each tag parser is mostly free to parse things in any way it wants. So the requested feature cannot be implemented without a huge BC break in the ecosystem of extensions (changing entirely how tag parsers work)

stof avatar Jun 24 '25 15:06 stof

I've implemented it myself temporarily by subclassing the lexer and writing sth. like:

        if ($this->code[$this->cursor]==self::STATEMENT_SEPARATOR) {
            ++$this->cursor;

            $this->pushToken(Token::BLOCK_END_TYPE);
            $this->pushToken(Token::BLOCK_START_TYPE);

            return;
        }

It's just a few lines and already works without any problems with thousands of Twig files I have. So I don't think it will be a BC break. Twig already has the concept of blocks (sorry for the wrong wording if I called them statements). My request was just to have ";" as a shortcut to end the current block and immediately start a new block. This would already enable to write sth. like this:

{%
do attributes.addClass("test"); 
do attributes.removeClass("test2")
%}

rgpublic avatar Jun 24 '25 17:06 rgpublic

@rgpublic but this works only if tag parsers don't treat ; as meaning something in their own scope (which they could totally do today)

stof avatar Jun 25 '25 11:06 stof

@stof: Yeah, but this is of course a universal catch-all argument. Twig is extensible. Anything could be registered. This argument works against any extension of the language. New operators, new tokens, new anything. If you perceive it like that, Twig as a language is completely frozen and you could never ever add any new syntax feature. I don't think it makes much sense. In particular, I don't think registering ";" in an extension is a likely scenario. Nevertheless, you are right of course that this might require a new Twig major version and can't be done in a minor release. That's okay. But still I think my feature request is absolutely valid and makes sense. Twig templates have become an endless sea of these {% ... %} and many template developers know the ";" which appears in so many common languages. When Twig was in its infant years, it might have made sense to omit it. Now that it's a mature language and used in large-scale projects like Drupal, I think it doesn't make sense so much anymore to force these verbose {% %} tags on every statement/command/ however you name it.

rgpublic avatar Jun 25 '25 13:06 rgpublic

Twig templates have become an endless sea of these {% ... %}

I'm interested in such a template, to be honest. Everytime I've encountered such templates in the past, it was because the template was doing a lot of business logic that should definitely have been done by the template data provider - like setting multiple variables, manipulating data, doing computations, things like that.

ericmorand avatar Jun 25 '25 13:06 ericmorand

@ericmorand : You are essentially saying "Need to do more than one single thing in a Twig template? It's your fault". That's a very bold and blanket statement in my opinion. I'm working in Drupal, taking care of a multitude of websites, and I can definitely say that sometimes it just doesn't make sense to move everything out of the template. Twig is a powerful language with loops, closures, etc. And if you need e.g. to do a little bit of output manipulation etc it's sometimes a good idea to do that in place - just where the output happens instead of spreading all these parts around over multiple PHP files.

If it's really business logic then I'd tend to agree. But sometimes the mere manipulation of output can get complex and this is definitely sth. Twig is capable to do - more often than not even better than PHP due to its powerful language features. It's really sad that doing this immediately results in endless {% ... %}. It almost feels like the template author should be "punished" for writing multiple statements. Therefore, ";" is IMHO a worthwhile addition to the language. Nobody is forced to use it. But it provides an option for more complex templates, that is really useful from my point of view.

rgpublic avatar Jun 25 '25 14:06 rgpublic

@rgpublic my point is that Twig is not a programming langage; it is a templating langage. I believe that a templating langage does not need what you propose because statements are unfrequent in templates, by nature.

ericmorand avatar Jun 25 '25 14:06 ericmorand

@ericmorand : Okay. We agree to disagree here. So be it. I think a templating language needs this. Just an arbitrary example from Drupal - I could name dozens of others:

https://api.drupal.org/api/drupal/core%21themes%21claro%21templates%21classy%21misc%21help-section.html.twig/11.x

    {% set size = links|length // 4 %}
    {% if size * 4 < links|length %}
      {% set size = size + 1 %}
    {% endif %}

This could look like this which is infinitely more readable IMO:

    {% 
    set size = links|length // 4;
    if size * 4 < links|length;
       set size = size + 1;
    endif;
   %}

It's basically a simple thing. Templates authors do this all the time. Like in this real-world example. You can always argue they should move everything to PHP. But it doesn't make sense. Sometimes these calculates etc need to be done. And they can be done in Twig. If only those annoying repeated block tags wouldn't mess up everything.

But oh well, I see we are not agreeing on it. I accept that, of course. I just wanted to bring up this proposal, because we are using this for many years in our company and found it extremely useful. I thought others would profit as well. I will continue to subclass our Twig Lexer then to implement it ourselves. Unfortunately this has also gotten infinitely more complex since everything is nowadays declared final, private etc, sigh :-(

rgpublic avatar Jun 25 '25 14:06 rgpublic