Tag and script in the same file (Lucee Language)

Continuing the discussion from Script or lucee tag?:

Now you raise it, my view on this is no they shouldn’t, which removes the need for the script “tag” and makes the previous thread null and void.

1 Like

This is my opinion too.

Spending my time with PHP these days, I’m only ever doing PHP in the backend code (the M&C of MVC)… we use Twig for the views. We literally can’t use PHP in out views!

I think this is a good approach, and makes for better code and separation of concerns. However I think the structure of CFML’s (and so: .lucee’s) tag-based functionality is an even better fit than Twig’s {% %} approach, so it’s OK to stick with tags.

One of the more fruitful Iris topics we discussed was exactly how few tags Iris should have. It wasn’t many (it’s all in that spreadsheet floating around). I think this should filter through to .lucee.

It’s the sort of change that might irk some old CFMLers, but they’re probably not likely to move from CFML anyhow, so might not be much of a consideration.


Adam

1 Like

I fully agree, too.

I fully disagree. And I’m sure I’m not the only one.

If I have a template with tags, why prohibit my ability to open a script block?

Are you really advocating that the following code should be disallowed? Or am I misinterpreting what you are saying?

<:script>
/*
    set magic unicorn variables
*/
foo=1;
bar=2;
<:/script>

<:output>
I have #foo# ton of unicorn dust. And #bar# rainbows.
<:/output>

Whether or not you use a mix of tags and script in the same template should be a decision that is left to the person writing their application.

3 Likes

you’re not the only one. +1.

I’d prefer to see it become more flexible and be able to treat files as script by default without any restrictions on using tags :smile:

person = new Person({id: 1234});

<:output>
Hi #person.name()#!
</:output>

(Treat “output” in the above example as a placeholder, it could be implemented as another keyword/tagname/whatever. Obviously this may put us back into the realm of discussing file extensions. For script only code the <:script> tag should be unnecessary, and for mixed code I’d prefer a way to break into tags – even if it was a heredoc style block and I had to use writeOutput to output the result.)

1 Like

Yeah I agree. One pain point I have with CFML is when I want to do a query in the piece of script I’m presented with the choice of swapping between script and tag based. My preference is to use the tag style of queries. I really want both in this situation.

IIRC we discussed {{ double-curly-braces }} for “tag islands” in scripts, e.g.:

person = new Person({id: 1234, name: "Lucee"});

{{  <!--- tag island was opened by two subsequent curly braces !--->
<:output>
    <h2>Hi #person.getName()#!</h2>
    <p>Your ID is #person.getId()#</p>
</:output>
}}  // tag island closed, back to script syntax

Yeah that could work :slight_smile: I’m maybe not sold on the double curly braces, it could clash with some nested implicit structs? But I’ll keep using it in my example code below for now just to continue the discussion.

Would there be any reason to not always treat that block as an output block? And should you be able to capture the output? (similar to savecontent).

x = "world";

// this gets outputted immediately
{{
  Hello <:mycustomtag>#x#</:mycustomtag>!
}}

// this sets the "output" variable
output = {{
  Hello <:mycustomtag>#x#</:mycustomtag>!
}}

1 Like

@21Solutions I’m not that keen on the idea of tag islands. Just seems like 4 extra chars I need to type - what purpose is it serving? With out them I will still know that it is a tag.

@justincarter the idea of where output goes using tag islands is interesting but that is like a shorthand to some output stream/savecontent. I could see some bugs being generated where someone deletes “world”; and next x has the value of what is expected to be outputted.

You mean if someone accidentally deletes half of the line of code and doesn’t realise? I guess, but they could also delete half of a line in a number of places, e.g. the custom tag output (i.e. </:mycustomtag>!) and the code might execute differently than expected without error. They could accidentally delete one or more complete lines of code and it still might not crash :smile:

This is a reasonably point. Going back to my earlier comment about the PHP & Twig combo… we choose to use Twig; it’s not the only option, and we could use PHP in our views if we decided to do so. However the way PHP is written has kinda moved on from mishmashing code and view logic.

Yeah, chuck it in a different file, where it belongs. Then <:include> it.

CFML - and web app design in general - has moved on from “chuck all the code in one file”, and I think this should be actively encouraged. There’s no need for .lucee to facilitate the perpetuation of code like this.

Bear in mind I would also advocate a very slim subset of tags even existing in .lucee. Basic flow control and a coupla debugging tags only. Have a look @ that Iris spreadsheet for the general gist.


Adam

Just trying to point out that sometimes devs do silly things and if the language can help them not do them that would be good :slight_smile:

1 Like

I totally disagree.

that would slow down development, and slow down execution. I see only downside and no upside.

if you prefer to do it that way in your code – go for it – you can do it that way right now and no modification to the engine is required. but that doesn’t mean that everybody should be forced to do it that way.

Regardless of the merit of such a statement, we should not be limiting people’s options without there being a good reason; for example, performance.

If I found myself writing a view where i had little choice but to put in a bunch of variable assignments and/or conditional logic it would be very frustrating to be prohibited from using a script block because somebody “knew better”.

And <:include> is rarely where I would want anything to belong :wink:

There are plenty of legitimate reasons for wanting to simplify things in <:script> in the midst of a template full of tags. If you don’t want to mix <:script> with tags then don’t.

@fingersdancing - the parser needs to know whether it’s trying to parse tags or script. there should be a clear separation.

keep in mind that a tag is not necessarily a tag. it can be literal text as well. e.g.

for (i=1; i<=10; i++) {

   Hello <em>there<em>!  // Hello is literal string that should throw an error
}

as opposed to:

for (i=1; i<=10; i++) {

   {{
   Hello <em>there<em>!  <!--- parser knows this is literal string !--->
   }}
}

Totally agree also. Maybe it is bad as an idea to mix views and data retrieval, but it sometimes is the fastest way to do things, without actually writing ugly code.

+1. Definitely will slow down development. And CFML is all about easy and rapid development, not complicated stuff.

@21Solutions why does there need to be a clear separation of tags and script? All tags start with “<:” and I don’t know of an operator or expression in script which is that. So is that is not a clear identifier of a tag expression starting/ending?

We need to consider other tags not just cfoutput or cfsavescript. Just thinking about those two is a narrow view of the discussion around having tags in script. Mail is one example of another tag but there other tags which don’t exist yet and we need to consider them in this discussion.

for (i=1; i<=10; i++) {
  <:mail to=person[i]>
    <:text>
      hey #person[i].name#
    <:/text>
    <:html>
       <h1>hey #person[i].name#</h1>
    <:/html>
  </:mail>
}

To me this is a core switch of the defacto arrangement that everything is tags or whitespace and then you explicitly state script in blocks of script tags. So if everything is script by default then you need to explicitly state tags and once inside a tag you must maintain tags.

So to output i + the tick count (assume it is 10) would do something like this

i = 10;
<:output><:set i += getTickCount()/>#i#<:/output>

std output>20

compare to here where the “script” would be treated as a string.

i = 10;
<:output>i += getTickCount()#i#<:/output>

std output>i += getTickCount()10

If we need to add the tag islands it should be because it supports developers is some manner. Having to write a tag island each time I need to do a tag in script seems like an inconvenience to me. I can’t how it is making development better so given the choice I would not have tag islands.

That’s right, there could be a lot of scope to add a new dimension to the language. If you take the position that all files should be treated as script but you allow other tags to be usable in some way when needed or desired, then there is possibly no need to use the <:script> tag :slight_smile:

You could simply output something:

person = new Person({id: 1234})

<:output>
Hi #person.name()#!
</:output>

You could capture output to do something with it later:

person = new Person({id: 1234})

out = <:output>
  Hi #person.name()#!
</:output>

Or you could run a query:

function findPerson() {
  var qPerson = <:query>
    SELECT * from person
    WHERE id = 1234
  </:query>
  return qPerson
}

Or you could work with custom tags that output something (and/or capture it as in this example):

import taglib="/farcry/core/tags/webskin" prefix="skin";

function getView(objectid, webskin) {
  var out = <skin:view objectid="#objectid#" webskin="#webskin#">
  return out
}

Or custom tags that return data (rather than passing in a string attribute for the variable name to set in the caller scope or some other global scope, i.e. r_chart="stData").

import taglib="/orgchart" prefix="org";

qPeople = getPeopleByOrganisationID(10)

stData = <org:chart data=qPeople>
  <org:department id="5">
    <org:title>IT</org:title>
  </org:department>
</my:orchart>

Or work with XML:

xml = <:xml>
  <people>
    <person>Bob</person>
    <person>Susi</person>
  </people>
</:xml>

So it might be possible to allow the use of tags wherever they are needed or desired without the need for a special “tag island” block. The tags themselves could probably serve that purpose? And of course, it’s just an option for those who need it :slight_smile:

1 Like