Justin Carter's madfellas.com

New site launched for FarCry Core 7.0 release

This past week we released FarCry Core 7.0 - the super sweet CFML framework - and launched a nice new site to celebrate! 

There's also some new FarCry Community Forums running Discourse in a Docker container on DigitalOcean. If you haven't had a look at FarCry Core in a while I'd recommend giving it a try, it's really shaping up nicely :)




The new Dashboard for FarCry 7

The FarCry Core webtop has had a huge makeover in recent months. One of the new features we've added is a configurable, extendable Dashboard for the webtop home page.

When Ghost was announced last year there was a lot of hype and controversy surrounding the dashboard and it's availability; it was beautifully designed, but was it useful or neccessary? For FarCry we think dashboards are useful but they need to contain a mix of statistics and activity feeds - the useful stuff that a user really wants to know when they are about to start work.


FarCry 7 Dashboard 

Out of the box we ship a few simple dashboard cards as examples but the main idea is that developers can create dashboard cards that are tailored to their products, plugins or projects. For example the FarCry CMS plugin ships with dashboard cards that shows embargoed news and recently receieved user feedback. For custom applications the possibilities are endless; new user registrations, comments to be moderated, integrated analytics, newsletter signups, this weeks sales figures, etc.

FarCry Core 7.0 is shaping up to be a great release so keep your eye out for more news in the coming weeks :) 

Redesigning the FarCry 7 Login Page

The login page in the upcoming release of FarCry Core 7 has had a similar redesign treatment to the overall webtop redesign. In addition to adding a custom webtop logo you can also upload a background image for the login page which makes it easier to customise out of the box. The login page will also still work with our existing User Directory plugins such as LDAP, RPX Now and Google OAuth (though with Google OAuth set as the default User Directory you essentially skip the login screen).

This is the default login page for a vanilla installation of FarCry Core with a plain grey background. To customise it, log in to the webtop and browse to Admin -> General Configuration, and upload a Login Background image:

Once your background image has uploaded, log out to see your new masterpiece :)  

Blurry, abstract and textured background images give a nice effect and can still help convey the brand of your application, while adding a little something extra to the often bland login page that goes unappreciated!

Redesigning the FarCry 7 Site Tree

In the upcoming relase of FarCry Core 7 we've rewritten the Site Tree to make it fast, easy to use, and added a nice quick preview feature.

The Site Tree now looks more consistent with the other object admin grids across the webtop but of course feature expanding nodes that are loaded via Ajax, and a simplified context menu that is touch friendly. This is one of the parts of FarCry Core where we've stated to use Backbone.js for some of the more complicated UI elements (the other main one being the new bulk file and image upload UI).

The quick preview button (the "eye" icon next to Edit) is a nice new feature which lets you preview a page in the site tree without leaving the webtop or even opening a new tab. It also supports switching between different screen sizes and makes use of FarCry's native support for device targeted webskins. This means you could preview a page using the mobile templates as opposed to the full desktop version, or if you build one set of webskins that are fully responsive you can see the effects of using different screen widths, or you can mix and match the two techniques.

The quick preview feature will be also be made available to standard object admin grids in other areas of the webtop some time before release.

Special thanks to Mark from TAFE Western for the use of the screenshots in this post :)

FarCry Core 6.1 Express: Ready to run

farcry-usb

FarCry Express is a "ready to run" installation of the latest FarCry 6.1 code base and the brand spanking new Fandango theme. So now you have no excuse for not checking out the latest FarCry code base!

http://org.farcrycore.s3.amazonaws.com/express/farcry-express-111125.zip

Express is not a production ready environment, but its a lot of fun to get a handle on the FarCry caper, run a few tests, do some training or just toy with an idea.  The install runs a Railo Express instance from the folder -- everything is contained in the one little directory branch. To uninstall or start a-fresh, just delete the folder and you're done. It even works on a USB!


This is a cross-post from the official FarCry Core Team blog.

Sublime Text 2 key bindings for CFML Developers

One of the first things I did when I started using Sumblime Text 2 was to set up some key bindings to emulate functionality that I was used to using in CFEclipse / CFBuilder 1. These were the usual keyboard shortcuts for inserting or wrapping selections in code like CFDUMP, CFOUTPUT, hashes, comments, etc.

To set up your own user key bindings, choose Preferences -> Key bindings - User from the menu. The configuration is an array of JSON objects, so remember to put your comma's in the right places :)

Here's my current ColdFusion / CFML related key bindings which you might find useful.

 

[
// cf tags
//
	// cfabort
	{ "keys": ["ctrl+shift+a"], "command": "insert_snippet", "args": {"contents": "<cfabort>" } },
	// cfdump
	{ "keys": ["ctrl+shift+d"], "command": "insert_snippet", "args": {"contents": "<cfdump var="#${0:$SELECTION}#">" } },
	// cfoutput
	{ "keys": ["ctrl+shift+o"], "command": "insert_snippet", "args": {"contents": "<cfoutput>${0:$SELECTION}</cfoutput>" } },
// wrappers
//
	// hash
	{ "keys": ["ctrl+shift+h"], "command": "insert_snippet", "args": {"contents": "#${0:$SELECTION}#" } },
	// single line comment
	{ "keys": ["ctrl+shift+m"], "command": "insert_snippet", "args": {"contents": "<!--- ${0:$SELECTION} --->" }, "context": 
		[
			{ "key": "text", "operator": "not_regex_contains", "operand": "
" }
		]
	},
	// multi line comment
	{ "keys": ["ctrl+shift+m"], "command": "insert_snippet", "args": {"contents": "<!--- 
${0:$SELECTION} --->
" }, "context": 
		[
			{ "key": "text", "operator": "regex_contains", "operand": "
" }
		]
	},
// remap sublime text defaults
//
	{ "keys": ["ctrl+alt+d"], "command": "duplicate_line" },
	{ "keys": ["ctrl+alt+m"], "command": "expand_selection", "args": {"to": "brackets"} }
]

Sublime Text 2 and Distraction Free mode

Sublime Text 2 offers a couple of different editing modes which I find useful on different occasions. The bulk of my coding is usually done in a normal window mode but there is also Full Screen mode, which - obviously - takes over the whole screen including the taskbar area, and Distraction Free mode, which just lets you view ONLY the file you're working on without any extra chrome or features or "distractions" on the screen.

Out of the box, Distraction Free mode can feel a little bit limiting because word wrap is turned on at 80 characters. I like the way the code is "centred" on-screen but I prefer to increase the word wrap to at least 120 characters (Sublime Text's word wrapping is quite good with automatic intending of wrapped lines) and also to hide the menu bar and enable the mini-map (the mini view of the code on the right side of the screen).

 

sublimetext2-distraction-free

 

To do this you can simply add some settings to your "Distraction Free User Preferences" file, via the Preferences -> File Settings - More -> Distraction Free - User menu item. You can also toggle the menu bar and mini-map in the View menu and your preferences will be saved for all Distraction Free mode sessions.

 

{
	"gutter": false,
	"line_numbers": false,
	"word_wrap": true,
	"wrap_width": 120
}

 

Note I have gutter and line numbers disabled (as they are out of the box), but you can enable them if you wish. I'm not yet used to having the line numbers and gutter appear all the way to the left side of the screen when the code is centred, it feels slightly wrong, but I've also found that when concentrating on a single file I'm really not worried about line numbers. They are a must at almost all other times though :)

It's also worth noting that you could turn on tabs if you wanted to, or any other number of features - whatever works for you.

Vote for CFML tag literals in cfscript on the CF Bug Tracker

This is just a short post. I've added an Enhancement Request to the Adobe ColdFusion Bug Tracker for adding XML and CFML tag literals to cfscript. If you like the idea then please go ahead and vote for it :)

http://cfbugs.adobe.com/cfbugreport/flexbugui/cfbugtracker/main.html#bugId=86199


If you missed my previous blog entries about CFML tag literals (C4X) you can read them here:

CFML proposal: XML and CFML tag literals for cfscript (C4X)
Using CFML tags in cfscript (C4X prototype)


There has also been some discussion on Ben Forta's blog about cfscript and ActionScript. Check out these two posts:

Ben Forta: Justin Carter On CFML In CFSCRIPT
Ben Forta: I Am Not A Fan Of CFSCRIPT


I'm a fan of cfscript and I'd prefer Adobe to keep refining it rather than trying to provide new scripting language options - but that's another post for another day :)

Using CFML tags in cfscript (C4X prototype)

Update: I've added Enhancement Request #86199 to the Adobe ColdFusion Bug Tracker. Please go there and vote for it if you would like to see this considered in a future version of ColdFusion!

About 8 months ago I wrote a blog entry which discussed the concept of using XML and CFML tag literals in cfscript, dubbed C4X for want of a better title. (If you missed that entry you might want to read it first before continuing with this one). A few weeks later I wrote some proof of concept code in the form of a function that would let me use this C4X style of syntax in cfscript.

The following code has only been tested on ColdFusion 9, and since it uses the virtual file system along with included virtual files it requires a mapping for the logical path /ram pointing to ram:// (this should also work on Railo though I haven't tried it). The function itself is just 40 simple lines of code:

function c4x(string tagInput)
{
    var c4xResult = "";
    var c4xFilename = "c4x_#createUUID()#.cfm";
    var tag = listFirst(arguments.tagInput, " #chr(9)##chr(10)##chr(13)#<>");
 
    if (left(tag, 2) eq "cf") {
        if (tag eq "cfquery") {
            // query: inject name attribute
            arguments.tagInput = replace(arguments.tagInput, "cfquery", "cfquery name='c4xResult'");            
        }
        else if (tag eq "cfxml") {
            // xml: inject variable attribute
            arguments.tagInput = replace(arguments.tagInput, "cfxml", "cfxml variable='c4xResult'");            
        }
        else {
            // other: capture output using cfsavecontent
            arguments.tagInput = "<cfsavecontent variable='c4xResult'>" & arguments.tagInput & "</cfsavecontent>";
        }    
        // write code to ram disk, execute, clean up
        try {
            fileWrite("ram://#c4xFilename#", arguments.tagInput);
            include "/ram/#c4xFilename#";
        }
        finally {
            fileDelete("ram://#c4xFilename#");
        }
    }
    else {
        if (isXML(arguments.tagInput)) {
            // xml: parse and return xml object
            c4xResult = xmlParse(arguments.tagInput);
        }
        else {
            throw(message="C4X: Invalid syntax. Root tag must be a valid CFML tag or well-formed XML. Application framework and flow control tags are invalid.")
        }
    }
         
    return c4xResult;
}


Essentially this lets us pass some CFML to the c4x() function in a string and we'll get back a result such as a query, XML object or some other type of output (or, in this prototype, nothing if the CFML tag has no output). This method could also handle custom tags, although not custom tags that have bee imported into a namespace from a tag library.

What does C4X look like again?

If C4X support existed natively in CFML, a simple query against the cfartgallery database could look like this in a script-based CFC or <cfscript> block:

artists = <cfquery datasource="cfartgallery">
		SELECT firstname, lastname, email, city
		FROM app.artists
		WHERE
			city IN (<cfqueryparam cfsqltype="cf_sql_varchar" list="true" value="New York,Washington">)
	</cfquery>;


If the C4X proof of concept function above was available in the variables scope then we could use it like this:

artists = c4x('<cfquery datasource="cfartgallery">
		SELECT firstname, lastname, email, city
		FROM app.artists
		WHERE
			city IN (<cfqueryparam cfsqltype="cf_sql_varchar" list="true" value="New York,Washington">)
	</cfquery>');


This code works now, in CF9. The artists variable will now contain the query object resulting from the <cfquery> tag. The only difference between the two pieces of code is simply the function wrapping the CFML code; the 7 unnecessary, but necessary, characters of c4x(' ')...

How do the current script equivalents compare?

Below I have three example pieces of code; a simple query, a dynamic query with logic, and a query of a query. Each of these examples will be compared using code from ColdFusion 9, Railo 3.2, and the mythical C4X :)

As we well know the CF9 script version of performing queries is more verbose than the way CF developers have traditionally done things, with the <cfquery> tag.

What some people might not know is that with Railo 3.2 there is another way of doing queries in script which is different to the CF9 implementation. In my opinion, it seems to strike a nice balance, but perhaps still isn't ideal due to the need for using writeOutput() to build up your SQL statements.

So, on to the comparisons!

A simple query

// CF9 query
qs = new Query(datasource="cfartgallery");
qs.setSQL("SELECT firstname, lastname, email, city
	FROM app.artists
	WHERE
		city IN (:cities )");
qs.addParam(name="cities", cfsqltype="cf_sql_varchar", list="true", value="New York,Washington");
artists = qs.execute().getResult();
 
// Railo 3.2 query
query name="artists" datasource="cfartgallery" {
	writeOutput("SELECT firstname, lastname, email, city
		FROM app.artists
		WHERE
			city IN (?)");
	queryparam cfsqltype="cf_sql_varchar" list="true" value="New York,Washington";
}
 
// C4X query
artists = <cfquery datasource="cfartgallery">
	SELECT firstname, lastname, email, city
	FROM app.artists
	WHERE
		city IN (<cfqueryparam cfsqltype="cf_sql_varchar" list="true" value="New York,Washington">)
</cfquery>;

A dynamic query with logic

// CF9 query with logic
qs2 = new Query(datasource="cfartgallery");
qrySQL = "SELECT firstname, lastname, email, city
	FROM app.artists
	WHERE
		city IN (:cities )";
qs2.addParam(name="cities", cfsqltype="cf_sql_varchar", list="true", value="New York,Washington");
if (myartMember) {
	qrySQL &= " AND email LIKE :email";
	qs2.addParam(name="email", cfsqltype="cf_sql_varchar", value="%@myart.com");
}
qs2.setSQL(qrySQL);
artists2 = qs2.execute().getResult();
 
// Railo 3.2 query with logic
query name="artists" datasource="cfartgallery" {
	writeOutput("SELECT firstname, lastname, email, city
		FROM app.artists
		WHERE
			city IN (?)");
	queryparam cfsqltype="cf_sql_varchar" list="true" value="New York,Washington";
	if (myartMember) {
		writeOutput(" AND email LIKE ?");
		queryparam cfsqltype="cf_sql_varchar" value="%@myart.com";
	}
}
 
// C4X query with logic
artists2 = <cfquery datasource="cfartgallery">
	SELECT firstname, lastname, email, city
	FROM app.artists
	WHERE
		city IN (<cfqueryparam cfsqltype="cf_sql_varchar" list="true" value="New York,Washington">)
		<cfif myartMember>
			AND email LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%@myart.com">
		</cfif>
</cfquery>;

A query of a query

// CF9 query of a query
qs3 = new Query(dbtype="query");
qs3.setAttributes(artists=artists);
qs3.setSQL("SELECT firstname, lastname
	FROM artists
	WHERE
		lastname LIKE :lastname");
qs3.addParam(name="lastname", cfsqltype="cf_sql_varchar", value="T%");
artistsQoQ = qs3.execute().getResult();
 
// Railo 3.2 query of a query
query name="artistsQoQ" dbtype="query" {
	writeOutput("SELECT firstname, lastname
		FROM artists
		WHERE
			lastname LIKE ?");
	queryparam cfsqltype="cf_sql_varchar" value="T%";
}
 
// C4X query of a query
artistsQoQ = <cfquery dbtype="query">
	SELECT firstname, lastname
	FROM artists
	WHERE
		lastname LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="T%">
</cfquery>;

Comparison results

As you can see from the code above and the table below, the C4X version of the code is a bit more concise than the Railo 3.2 version and significantly more concise than the CF9 version.

  Simple query Dynamic query Query of a query
CF9 276 chars (100%) 435 chars (100%) 269 chars (100%)
  7 lines 12 lines 8 lines
Railo 229 chars (83%) 350 chars (80%) 179 chars (67%)
  7 lines 11 lines 7 lines
C4X 217 chars (79%) 329 chars (76%) 167 chars (62%)
  6 lines 9 lines 6 lines


Better yet, there isn't really any new syntax to learn to be able to write code this way; simply remove the name attribute from the <cfquery> tag, place a variable and assignment operator before the tag and a semicolon after the tag. It's just the same old CFML you've always had to write, used in a new way inside script-based CFCs or <cfscript> blocks.

Why C4X?

As I mentioned in the previous blog entry, the main reason for implementing CFML tag literals is flexibility. It provides access to existing native tags that might not have script equivalents (yet). It's a potential solution for integrating custom tags into script based CFCs. It provides code reuse options. If you think about it, CFML tags and custom tags are now the outcasts in script based CFCs (i.e. they cannot be used), whereas previously cfscript was limited in its functionality compared to the possibilities with CFML tags.

I do like the direction Railo 3.2 has taken, but is it ideal?

To finish, here's a bunch of tweets which show a few reasons why cfscript still needs to be improved:

CFML proposal: XML and CFML tag literals for cfscript (C4X)

Update: I've added Enhancement Request #86199 to the Adobe ColdFusion Bug Tracker. Please go there and vote for it if you would like to see this considered in a future version of ColdFusion!

This is a feature proposal for the CFML standard and for ColdFusion 10. It's reasonably long so you might want to grab a coffee or a cold drink before settling in for the ride. You can't say I didn't warn you :)

Almost a year ago Sean Corfield called for comments to help the CFML Advisory Committee decide on how some parts of cfscript should be implemented in future versions of ColdFusion. Full script based components were mostly under control, the only real sticking point was how to handle the script equivalent of nested CFML tags that also include body text - such as cfmail, cfquery and custom tags - which I'll call the "problem tags". A month later, after reviewing the 145 replies in the discussion, Sean made his recommendation to the committee to introduce a set of objects for the "problem tags". The use of objects was a logical, straight forward solution which would not introduce any new syntax and would therefore have no direct impact on the learning curve of the language or on the compiler(s). It was definitely the right step for bringing the capabilities of cfscript into line with the capabilities of CFML tags.

ColdFusion 9 was released in October 2009 and brought with it the much desired enhancements to cfscript, including full script based components, implicit getters and setters, many of the missing functions that developers have typically created UDF wrappers for, script equivalents of newly introduced tags, and the new "problem tag" objects which Adobe called script functions implemented as CFCs.

The CFML Advisory Committee and Adobe have finally brought cfscript up to the point where, in most cases, there is no need to chop and change between script and tag based approaches because the majority of code can now be written successfully either way. Which brings us to today...

Can cfscript be further improved?

At the moment cfscript is in good shape but I think most developers would agree that there are still things that could be done to improve our productivity and help with code readability and maintenance.

There are some CFML tags that still do not have script equivalents such as cffeed and cfldap (as noted by Chris Peters in his post on Full script CFCs aren't yet where they need to be), cfcontent, cfheader, cfschedule and cfsetting. We could continue to write UDF and CFC wrappers for these tags but of course it would be nicer if the language specification and vendors had clear rules about providing a consistent implementation for all tags and their equivalent functions or objects. Consistency and coverage are important.

There are also some things about the script functions implemented as CFCs which are not quite optimal. For tags like cfmail and cfquery the script equivalent tends to be slightly more verbose than the tag based approach - which in itself isn't a problem, more like a potential target for optimisation. Ben Nadel has also found a couple of issues* with the Query.cfc implementation, one of which is a bug in the parsing of named parameters and the other which can potentially expose a SQL injection vulnerability that wouldn't exist when using the cfquery tag. Ben does note that this is only a problem "when you are using horrible SQL to begin with" but you could say that any code which exposes a vulnerability is horrible. Ben also concluded that some of the cfscript "tag operators" are inconsistent in the way they are implemented (with/without named arguments, with/without parenthesis, etc). So there may be some opportunities for improvement in this area. (*Please note: one or both of the above Query.cfc issues may have been addressed after the RC or Gold release of CF9 but I have so far been unable to confirm it).

Finally, cfscript doesn't yet attempt to tackle support for custom tags. The main reason for this, and any tags which use body text and nested tags, is that trying to morph the syntax into something that looks like script - and yet will actually work - is difficult. Sean was the first to admit this, and it became evident after many attempts that there isn't really a nice "scripty looking" way to do it. Vince Bonfanti says that we shouldn't even try to solve the problem, and that we should ban the use of cfcomponent and cffunction tags and the writeOutput() function as soon as is feasible. Personally I couldn't disagree more. Banning tag based CFCs is pretty extreme, but there is also nothing wrong with allowing developers the flexibility to build something the way they want to build it - after all that is what we've been fighting for in regards to cfscript! Let's leave the choice of syntactic optimisation up to the developers and not dictate it in the language. (As a side note, Railo supports component based custom tags which I think are also quite exciting for CFML and cfscript).

Overall these issues aren't show stoppers though and I'm sure the tag to script coverage will push further towards 100% in future releases.

However, there is one more important issue to recognise with the balance of tags versus script. You can use cfscript anywhere you like within a tag based component or page, but you cannot use CFML tags within a script based component. You might ask, "Why would you want to do that anyway?" Well, the answer, as I alluded to above, is simply: flexibility.

What is cfscript for XML (C4X)?

If you are not familiar with ECMAScript for XML have a quick read of the E4X entry on Wikipedia. There are a couple of ways that the addition of E4X-style syntax could benefit CFML so I want to describe them in incremental steps. I'll call this concept C4X meaning "cfscript for XML".

The idea of having something like C4X in cfscript is not mine. I saw it first mentioned by Rick Osborne in Sean's call for comments where it received some good support by a number of people. Rick then went on to expand on his ideas in a blog entry titled CF9 + E4X + C4X. Even more interesting is that 3 months prior he had already suggested that cfscript should have E4X-like support (and commented that it was already too late to get it into CF9):

"There's no way we're going to see something E4X-like with XML fragments built into CF9. If we scream loud enough we might see it in CF10. Maybe." -- Rick Osborne

This is my attempt to get the conversation going again, and if enough people are interested then we can all "scream" together. So, on to the actual examples...

XML literals

The first and most obvious benefit of C4X is the ability to declare XML literals. When XML is treated as a primitive type it means you could assign a chunk of XML directly to a variable, i.e. there is no need to create a string and then use the xmlParse() function to parse it into an XML object.

Creating an XML object in cfscript without C4X:

person = xmlParse("<person>
  <firstname>Ben</firstname>
  <lastname>Forta</lastname>
</person>");

Creating an XML object in cfscript with C4X:

person = <person>
  <firstname>Ben</firstname>
  <lastname>Forta</lastname>
</person>;

This is the most basic example and as you can see it saves a dozen keystrokes and makes the code slightly cleaner and easier to read. It's not ground breaking but it's an improvement.

XML literals would also support variable / statement evaluation and could be useful for working with XML-compliant chunks of HTML. You could build fragments of HTML from a data set and then do further processing on them as XML (using the existing functions of the language) - something which would be difficult to do with strings - before finally using / rendering them.

Creating an XML-compliant HTML fragment including variable evaluations with C4X:

article = <div class="article">
  <h2>#qArticle.title#</h2>
  <p>#qArticle.teaser#</p>
</div>;

A full E4X-style implementation would also include filtering, manipulation via operators (e.g. using + for appending nodes) and a bunch of other stuff, but at this stage I am a little hesitant to suggest taking it that far (though this is up for debate). The main thing I wanted to do was explain XML literals and their benefits so that I could introduce the next C4X concept.

CFML tag literals

This is where we get to the meat of the proposal. C4X could overcome some of the issues raised above by allowing us to write declarative code where it makes the most sense: when dealing with nested CFML tags and tag body text. I'm not sure that "tag literals" is the right term but I'll run with it.

Since the cfquery and cfmail (and other) tags now have a script equivalent in CF9 we can begin to look at ways in which our cfscript code can be further enhanced. I'll demonstrate this by showing CF9's script version followed by the proposed C4X version.

Executing a query in cfscript without C4X:

qry = new Query(datasource="myDSN");
qry.setSql = "SELECT * FROM users";
qUsers = qry.execute().getResult();

Executing a query in cfscript with C4X:

qUsers = <cfquery datasource="myDSN">
  SELECT * FROM users
</cfquery>;

The first thing you'll notice is how tidy the C4X version is, at around 70% of the keystrokes of the script equivalent. The second thing is that the (usually required) name attribute is omitted from the cfquery tag because the assignment implies that the cfquery tag will assign the resultant query object directly to the qUsers variable. This implied attribute assignment could also work for all other tags that typically have a name or result attribute (note: since it's not quite consistent across all the built-in tags the actual attribute name will vary from tag to tag - I haven't done a full analysis but in most cases the implied attribute should be a single, obvious attribute).

So those query examples were pretty trivial. Let's beef it up a little with some logic and a parameterised value.

Executing a query in cfscript without C4X:

function getUsers(userID="0") { 
  var qry = new Query(datasource="myDSN");
  var sql = "SELECT * FROM users";
  if (arguments.userID neq 0) {
    sql += " WHERE userID = :userID";
    qry.addParam(name="userID", value=arguments.userID, cfsqltype="cf_sql_integer");
  }
  qry.setSQL(sql);
  var qUsers = qry.execute().getResult();
  return qUsers;
}

Executing a query in cfscript with C4X:

function getUsers(userID="0") { 
  var qUsers = <cfquery datasource="myDSN">
    SELECT * FROM users
    <cfif arguments.userID neq 0>
      WHERE userID = <cfqueryparam name="userID" value="#arguments.userID#" cfsqltype="cf_sql_integer">
    </cfif>
  </cfquery>;
  return qUsers;
}

With the slightly more complex query the C4X example is around 80% of the keystrokes of the script equivalent and a couple of lines of code shorter. I think at this point it's becoming clearer how workable this solution could be.

So which tags could be used as a CFML tag literal? Pretty much any CFML tag except for flow control tags I think. If it's a tag that "returns" a value like cfquery then definitely. If it's a tag that just does some processing and doesn't return anything then there's no reason it couldn't return "true" if no exceptions were thrown. If it's a tag that outputs something to the response stream then the output could either be assigned to the variable or we could use the cfsavecontent tag as a wrapper to capture it (the latter would probably be better).

How does a compiler handle C4X?

I don't think C4X is a difficult thing for a compiler to deal with. If the root node is a CFML tag (or a custom tag) then it's clearly a block of CFML code. Otherwise, it's assumed that it's a chunk of XML that could contain some variables or statements that need to be evaluated, and invalid XML should throw a compile time error. And, obviously, for this to work the XML or CFML literal would have to have a single root node / tag.

Internally, CFML engines may choose to treat XML literals as a subclass of their existing XML classes if that provides some benefit during compilation or for any future additions to C4X (such as full E4X-style filtering syntax and other operations, if they were deemed feasible; again, I'm still on the fence). I don't know enough about how the engines work under the hood to make any further suggestions here though.

One more consideration is how do IDE's handle C4X? Well, if an IDE can handle E4X's XML literals then C4X support should be somewhere in the same ball park, and so I'd be hopeful that it's within the realm of possibility for the IDEs that we use today.

Final thoughts

Personally I think it only takes a glance to see that C4X could be quite nice to work with, and the beauty of it is that it's not the only way to write the code - if you want to use a purely object based scripting solution then you can, because it already exists. On top of that, this is just the same as existing code that we have always had to write in CFML, just used in a new way (with a variable name, assignment operator and a semi-colon - definitely not rocket science!). There is barely any learning curve at all.

I'd be very interested to hear the thoughts of the ColdFusion community, staff/members of the CFML Advisory Committee, Adobe, Railo and OpenBD, and especially from those who thought E4X-style syntax was a bad idea 12 months ago. Now that a pure, object based solution exists, is there room for an improvement like C4X, and if not is there a better reason than "I just don't like tags inside script", even though in most cases the code could be considered cleaner and easier to read?

I think C4X could be another step in the right direction for CFML. Let us know what you think!