Stringizer functions in TIScript

Motivation.

Tasks of defining string expressions and textual fragments in script code are pretty common.

Typical example in JS/browser is:

someelement.innerHTML = 
"<span style=\"color:#ffffff\">" + somestuff + "</span>";

As you see this could be quite noisy and complex to be comprehensible by human.

Various scripting languages are trying to reduce syntax noise in various ways. Scala for example allows to define XML literals http://programming-scala.labs.oreilly.com/ch10.html inline without need of "mangling" it by quotes. This feature appears as quite neat but is limited by XML only. E.g. it will not work for HTML ("HTML is not XML"™) or for things like CSS selectors, etc.

Another example is string templates in Ruby. They allow to define string literals with embedded code:

template = 'Dear #{customer},\nPlease pay us #{amount} now.\n'

but this still needs string literal. One more problem with such approach: various types of strings need different escapement rules applied to values being embedded in the string. E.g. for HTML it should be String.htmlEscape() call, for URLs – String.urlEscape(), etc.

So there is a need to have some syntax construction that will allow to define various ways to define string compostions.

Solution.

As a solution I’ve implemented in TIScript so called stringizer functions.

Stringizer function is a function (or method) with the name starting from ‘$’ character and with variable number of parameters.

Call of such function is written in the form:

$name( ... some text here... )

Where the text inside ‘(‘ and ‘)’ is not required to be enclosed in quotes. Characters ‘(‘ and ‘)’ are serving role of quotes by themselves.

Example of such stringizer call:

var firstDiv = self.$( #content > div:first-child );

$ here a stringizer method that accepts CSS selector expressions. The sample above is a direct equivalent of this:

var firstDiv = self.select( "#content > div:first-child" );

Text inside ‘(‘ and ‘)’ may contain expressions enclosed in curly brackets ‘{‘ and ‘}’. Result of the expression in such brackets will be passed into the stringizer function as is.

Having all this in place the very first example of the article can be written in Sciter simply as:

someelement.html
    = $html( <span style="color:#ffffff">{ somestuff }</span> );

TIScript will de facto compile this call as:

someelement.html 
    = $html( "<span style="color:#ffffff">", 
               somestuff, 
               "</span>" );

The only thing left is an implementation of the $html() function that we can define like this:

function $html(params..)
{
  for( var (n,v) in params )
    if( n & 1 ) // each odd paramter is a 
                    // value of expression inside '{' and '}'
      params[n] = v.toHtmlString(); // calling method 
                    // that will do HTML escapement
  return params.join(""); //return composed string
}

Some ideas

Here are some ideas for such stringizer functions we can use in the Sciter:

  • function Element.$append( ... inline html ... ) – method of the DOM element class – appends the html after last child of the element.
  • function Element.$prepend( ... inline html ... ) – prepends the html before first child of the element.
  • function $text( ... some text ... ) – simple way of composing texts.
  • function Stream.$print(... some text ... ) – simply prints text with possible { } inclusions.
  • function $xml( ... some xml... ) – to compose XML string and create XML tree using built-in XML parser.
  • you name it…