Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
template_extend(3)    User Contributed Perl Documentation   template_extend(3)

       template_extend - how to	extend the Text::Tmpl template library (with C
       or Perl).


	$context->register_simple("name", \&simple_handler);
	sub simple_handler {
	    my($context, $name,	@args) = @_;
	    # do stuff to build	a return string
	    return "result string!";

	$context->register_pair($is_named, "open", "close",
	sub pair_handler {
	    my($context, $name,	@args) = @_;
	    # do stuff to the context

	$subctx	 = Text::Tmpl::context_get_anonymous_child($ctx);
	$subctx	 = Text::Tmpl::context_get_named_child($ctx, $name);
	$peerctx = Text::Tmpl::context_add_peer($ctx);
	$return	 = Text::Tmpl::context_set_named_child($ctx, $name);
	Text::Tmpl::context_output_contents($ctx, $output);


	int template_register_simple(context_p ctx, char *name,
	   void	(*function)(context_p, char **,	int, char**))
	simple_handler(context_p ctx, char **output, int argc, char **argv) {
	    char *returnstring;
	    /* do stuff	to build a return string */
	    *output = (char *)calloc(1,	strlen(returnstring));
	    strncpy(*output, returnstring, strlen(returnstring));

	int template_register_pair(context_p ctx, char named_context,
	   char	*open_name, char *close_name,
	   void	(*function)(context_p, int, char**))
	pair_handler(context_p ctx, int	argc, char **argv) {
	    /* do stuff	to the context */

	context_p context_get_anonymous_child(context_p	ctx);
	context_p context_get_named_child(context_p ctx, char *name);
	int	  context_set_named_child(context_p ctx, char *name);
	context_p context_add_peer(context_p ctx);
	void	  context_output_contents(context_p ctx, char output_contents);

       Creating	new tags in this templating system is pretty easy, despite the
       somewhat	daunting API.  The perl	and C APIs are virtually identical in
       both usage and effects, so I'm going to be discussing the process in a
       (hopefully) language independent	way.

       Note that tags are global in scope - a tag can be registered at any
       point before the	parsing	stage and will be visible to the entire
       template.  This may change in future versions, if there seems to	be a
       demand for scoped tags.

   Tag Argument	Passing
       Arguments to any	tag are	passed into the	tag function as	an argc/argv
       pair in the C API, or a list in the Perl	API.  Either way, element 0 of
       the argument list will be the tag name, so the first argument is
       actually	element	1.

   Simple Tags
       Simple tags are lone tags which generate	a string for inclusion in the
       parsed output.  A perl simple tag function simply returns a string,
       whereas a C simple tag function has to allocate a new string (which the
       caller will free() after	use.)

       The echo	tag function in	C looks	like:

	simple_tag_echo(context_p ctx, char **output, int argc,	char **argv)
	    int	size;

	    if (argc < 1)
		*output	= NULL;

	    size = strlen(argv[1]);
	    *output = (char *)calloc(1,	size + 1);
	    strncpy(*output, argv[1], size);
	    (*output)[size] = '\0';


       This illustrates	a couple of things: errors from	simple tags should be
       indicated by making *output a NULL pointer, and don't forget to null-
       terminate *output.

       In perl,	you would duplicate this by:

	sub simple_tag_echo
	    my $context	= shift	|| return undef;
	    my $name	= shift	|| return undef;
	    my $string	= shift	|| return undef;

	    return $string;

       It should also be pointed out that all of the argument parsing,
       including variable interpolation, has already happened by this point.

       Simple tags are called with the context in which	they are found.	 They
       can make	changes	to the context,	but the	results	may be unexpected -
       for example, attempting to disable the output of	the entire surrounding
       context will not	work.

       The output string from a	single tag will	(if not	NULL) be run through
       the parser.  This means that a simple tag can output a template
       fragment.  So, for example, if you wanted to implement an "else"	tag,
       you could:

	sub simple_tag_else
	    my $context	= shift	|| return undef;
	    my $name	= shift	|| return undef;

	    return "<!--#endif--><!--#ifn-->";

   Tag Pairs
       Tag pairs are more complicated.	As the name implies, tag pairs have a
       beginning and an	end, denoted by	two distinct tags.  When a beginning
       tag is found, the parser	scans forward to find the matching closing
       tag, and	then parses everything in between in the context of the	tag

       There are two kinds of tag pairs	- those	with named contexts, and those
       with anonymous contexts.	 A named context is used for tag pairs which
       allow the programmer to pre-build some (or all) of the context
       structure before	parsing	takes place, such as the loop tag.  An
       anonymous context is used when the context is constructed completely at
       parse time, such	as the comment tag.  The actual	name of	the context,
       in a named context tag pair, is the first argument to the opening tag
       (for example <!--#loop "foo"--> retrieves the named context "foo" from
       the parent context).

       The tag function	is called before parsing of the	context	begins,	so it
       gets to completely set up the context beforehand.  So the comment tag,
       for example, simply disables output of the context:

	tag_pair_comment(context_p ctx,	int argc, char **argv)
	    context_output_contents(ctx, 0);

       The contents of the context are never even parsed, since	the parser
       knows that it won't be output.

   The context_* functions
       This group of functions is used to manipulate context structures	in
       ways the	main template API doesn't allow.  Before we dive into it, some
       understanding of	the context structure will be required.

       Contexts	are quite simple, really.  They	contain	a list of variables
       and a flag which	determines whether the contents	of the context should
       be output.  Each	context	can also know about a number of	other contexts
       internally: its parent, its peer(s) - each peer representing a loop
       iteration - and its named children.  A context may have zero or more of
       each of these.  For example, the	initial	context	returned from
       template_init has no parent, no peers and no named children initially.
       If you call template_loop_iteration, the	main context will gain a
       single named child context, which in turn will have the main context as
       a parent, no peers (yet)	and no named children.	If you call
       template_loop_iteration on the main context with	the same name again,
       the named child will gain a peer	context.  And so on, and so forth...

       In summary: the parent context provides nested scopes, peers represent
       iterations over the same	chunk of the template, and named children are
       contexts	which can be fetched by	name both at preparation time and
       parse time.

	  Creates and returns an unnamed context with the parent set to	the
	  current context (i.e.	a new context within the scope of the current

	  This function	returns	a named	context	within the scope of the
	  current context, if it exists.

	  This function	creates	a new named context within the scope of	the
	  current context.

	  This function	adds a peer context to the context passed in, and
	  initializes it.

	  This function	sets the output_contents flag in the current context.

       Functions which return context_p	pointers will return NULL if there is
       any problem at all.  Functions which return integers return 0 on
       failure and 1 on	success.

       Hopefully none.

       J. David	Lowe,

       libtmpl(1), Text::Tmpl(1), template_syntax(1)

perl v5.32.1			  2003-02-06		    template_extend(3)


Want to link to this manual page? Use this URL:

home | help