COMMUNITY

haxe.Template question

Hej !

I try to do something like that :

class Test {
	static function main() {
    var s		= "Hello ::recipient.name:: from company $$instance(::recipient.companies::,1,\"name\") ### ::foreach recipient.companies::::name::::end::";
    var ctx : Dynamic = {
			recipient: {
				name : "Mrs. Annie Cordy",
        companies : [ { name : "Company 1" }, { name : "Company 2" } ]
      }
    }
    var tpl	= new haxe.Template( s );
    var out	= tpl.execute( ctx, Test );
    trace( out );
	}
  @:keep
  static function instance( resolve:String->Dynamic, a : Array<Dynamic>, n : Int, field : String ){
		return Reflect.field( a[ n ], field );
  }
}

Here’s the try example : Try Haxe !

Does anyone know how can I achieve that please ? I want to have a macro function to get an array index object instead of iterating with forech

Thanks all !

I think I can get it with hscript to parse the array but maybe there is another way ?

I succeed with that : Try Haxe ! , but if anyone has a better solution I take it :slight_smile:

class Test {
	static function main() {
		var s = "Hello ::recipient.name:: from company $$instance(recipient.companies,1,name)";
		var ctx = {
			recipient: {
				name: "Mrs. Annie Cordy",
				companies: [{name: "Company 1"}, {name: "Company 2"}]
			}
		}
		var tpl = new haxe.Template(s);
		var out = tpl.execute(ctx, Test);
		trace(out);
	}

	@:keep
	static function instance(resolve:String->Dynamic, v:String, n:Int, field:String) {
		var a = v.split( "." );
    var o	= resolve( a.shift() );
    do {
			o = Reflect.field( o, a.shift() );
    }while( a.length > 0 );
    var it : Array<Dynamic> = o;
    return Reflect.field( it[ n ], field );
	}
}

Maybe @RealyUniqueName ?

All fields are evaluated as strings, maybe it should be good to have a way to get an object as is forachieve some maipulations ?

If your templates are available at compile time then tink_template is a good alternative to haxe.Template.
With it you should be able to do (: recipient.companies[1].name :), or could always call a function from the template anyway.

Thanks Valentin for your reply.
I yet use tink_template for my web templates that I found awesome. But here I need it on run-time. I found haxe.Template quite good but it misses some little things like that, that’s pitty.

Take a look at this awesome new run-time Template system based on hscript !!! :rofl: :
The synthax used is ::+ and +::, called “super stars” :upside_down_face:

var ctx	= {
			recipient: {
				name	: "Mrs. Annie Cordy",
				male 	: false, 
				companies: [{name: "Company 1"}, {name: "Company 2"}]
			}
		}

		var s	= "Hello ::+ctx.recipient.name+:: from ::+ctx.recipient.companies[ 0 ].name+::
		::+( if( !ctx.recipient.male ):: Bonjour Madame ! ::else:: Bonjour Monsieur ! ::)+::
		You work in these companies : ::+ctx.recipient.companies.map( function( c ) return c.name ).join( ', ' )+::";

		var ps	= s.split( "::" ).join( '"' );
		var pss	= 'var str	= "$ps";return str;';

		try{
			var parser	= new hscript.Parser();
			var ast 	= parser.parseString( pss );
			var interp 	= new hscript.Interp();
			interp.variables.set( "ctx", ctx ); 
			var ret		=  interp.execute( ast );
			trace( ret );
		}catch( e ){
			trace( "HScript interpreter : " + e.message );
		}

Gives :

Hello Mrs. Annie Cordy from Company 1
Bonjour Madame !
You work in these companies : Company 1, Company 2

In order to unify a bit the synthax we could do this mapping :parrot::

::if+		=> ::+(if
+if::		=> ::
::+else+::	=> ::else::
::+endif+::	=> ::)::

So the source would look like :

Hello ::+ctx.recipient.name+:: from ::+ctx.recipient.companies[ 0 ].name+::
::+if( !ctx.recipient.male )+if:: Bonjour Madame ! ::+else+:: Bonjour Monsieur ! ::+endif+::
You work in these companies : ::+ctx.recipient.companies.map( function( c ) return c.name ).join( ', ' )+::