-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
1100 lines (787 loc) · 37.6 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
NAME
Template::Plex - (P)erl (L)exical and (EX)tendable Templating
SYNOPSIS
Write a template:
__DATA__
@{[
init {
use Time::HiRes qw<time>;
$title="Mr.";
}
]}
Dear $title Connery,
Ordered a $size pizza with $slices slices to share between @$people and
myself. That averages @{[$slices/(@$people+1)]} slices each.
Use a template:
use Template::Plex;
my $vars={
size=>"large",
slices=>8,
people=>[qw<Kim Sam Harry Sally>]
};
my $template= Template::Plex->load(\*DATA, $vars);
print $template->render;
#OUTPUT
Dear Mr. Connery,
Ordered a large pizza with 8 slices to share between Kim, Sam, Harry,
Sally and myself. That averages 1.6 slices each.
Change values and render it again:
$vars->{size}="extra large";
$vars->{slices}=12;
print $template->render;
#OUTPUT
Dear Mr. Connery,
Ordered a extra large pizza with 12 slices to share between Kim, Sam,
Harry, Sally and myself. That averages 2.4 slices each.
DESCRIPTION
"Template::Plex" facilitates the use of Perl (not embedded perl) as a
template language. It implements bootstrapping and a system to load,
cache, inherit and render templates with minimal code.
The 'lexical' part of this module refers to the lexical aliasing of
input variables into the template. This reduces the amount of markup
required to reference variables and thus improves the style and
readability of a template.
Templates can be extended and reused with sub templates and inheritance.
The template system itself can be extended by sub classing
"Template::Plex" and implementing customised load routines and other
helper methods.
The short tutorial in this document plus the examples included in the
distribution cover the basics to get you started. Reading through the
"load" API options is also recommended to get a better understanding on
how templates are processed.
MOTIVATION
Many templating systems are available, yet none use Perl as the template
language? Perl already has a great text interpolation, so why not use
it?
Lexical aliasing allows the input variables to be accessed directly by
name (i.e. $name) instead of as a member of a hash ref
(i.e."$fields->{name}") or by delimiting with custom syntax (i.e.
"<%=name%>")
I like the idea of Jekyll's 'Front Matter', but think its potential is
limited as it can only support variables and not code. With Perl's
flexible syntax introducing code is doable.
TUTORIAL
Syntax Genesis
We all know how to interpolate variables into a string in Perl:
"This string $uses a $some{variables}"
But how can we easily interpolate a statement, function or method call?
We can use the "@{[]}" construct.
"This is a perl string interpolating @{[ map uc, qw<a b c d>]}"
If we need multiple statements, we can combine with a "do" statement.
Like always the last statement executed in a "do" block is returned (
and interpolated into the string):
"This is a perl string interpolating
@{[ do {
my $result="STATEMENTS";
...
lc $result;
}
]}
"
Combining the above examples, we make a "Template::Plex" template simply
by removing the outer quoting operators:
This string $uses a $some{variables}
This is a perl string interpolating @{[ map uc, qw<a b c d>]}
This is a perl string interpolating
@{[ do {
my $result="STATEMENTS";
lc $result;
}
]}
A "Template::Plex" template is just Perl! The above is the literal text
you can save to a file and load as a template.
Specifically, a "Template::Plex" template it is the subset of Perl
that's valid between double quotation operators.
Smart Meta Data and Code
Templates can include an "init{}" block at the beginning which is
executed (only once) during the setup stage of the template. In some
ways this is similar to Jekyll 'Front Matter', but more powerful. You
can manipulate input variables, define helper subroutines, or import
modules:
@{[ init {
use Time::HiRes qw<time>;
sub my_func{ 1+2 };
}
]}
Calculated @{[my_func]} at @{[time]}
The "init" block does not inject any content into a template, but
manipulates the state of a template.
Each template has access to it self, using the $self variable. This
comes in very handy when loading sub templates and doing more advanced
task or even extending the template system.
So far we have seen the "do" and "init" directives. General code can
also be executed with a "pl" block. This does the same as "do" but does
not inject the result into the template.
Loading and Rendering
There are a few ways of executing a template from your application. Each
of them are accessible via class methods:
#Load a template and render later
my $template=Template::Plex->load($path, $vars, %options);
my $result=$template->render;
#Load a template from cache and render later
my $template=Template::Plex->cache($key, $path, $vars, %options);
my $result=$template->render;
#Load from cache and render now
my $result= Template::Plex->immediate($path, $vars, %options);
A "load" call returns a new template object each time, where a "cache"
call returns a template already loaded (or loads it once), for a user
defined key. The returned template is then rendered by calling the
"render" method.
The "immediate" call loads and caches a template with a user defined key
and then immediately renders it, returning the results.
Template Reuse
Reusing templates can reduce the repetitive nature of content.
"Template::Plex" provides multiple facilities for template reuse.
Sub Templates
A sub template is just another template. While you can load a sub
template with the class methods shown previously, it's not recommended.
This is because you would need to specify all the variables and options
again manually.
You normally would like to pass on the same variables and options to sub
templates, so a better way is to call the same method on the $self
object:
@{[$self->load(...)]}
@{[$self->cache(...)]}
@{[$self->immediate(...)]}
This will automatically link the variables and relevant options to be
the same as the current template.
Better still, these methods are made available within a template simply
as a subroutine call:
@{[load ... ]}
@{[cache ... ]}
@{[immediate ...]}
Slots and Inheritance
A sub template can be used at any location within a template. However
there are special locations called slots. These are defined with the
"slot" directive:
@{[slot slot1=>"some text"]}
@{[slot slot_abc=> cache "sub template"]}
@{[slot]}
The slot name can be any string and the value can either be text or a
template object. This value is the default value, which is used when no
child template wants to fill the slot.
A slot named 'default' (or no name) is special and is the location at
which a child template body will be rendered.
A child template can also fill other slots in the parent by explicitly
using the "fill_slot" directive. The value can be text or a loaded
template
@{[fill_slot name=>"override content"]}
@{[fill_slot another=>load "path to template"]}
Child can setup inheritance by using the "inherit" directive within a
"init" block, specifying the template to use as the parent:
@{[ init {
inherit "my_parent.plex";
}
]}
The following is an example showing a child template inheriting from a
parent. The child will provide content to the default slot in the parent
and also override the 'header' slot with another template which it
loads:
Parent Template:
@{[slot header=>"==HEADER=="]}
More parent content...
@{[slot]}
@{[slot footer=>"==FOOTER=="]}
Sub template (header):
-=-=-=Fancy header=-=-=-
Child template:
@{[ init {
inherit "parent.plex";
}
]}
@{[slot header=> load "header.plex";
This content will render into default slot
Inclusion
Depricated. Please use sub templates to achieve the same result Much
like the C language preprocessor, including an other template or other
file will do a literal copy of its contents into the calling template.
The resulting text is processed again and again as long as more include
statements are present:
@{[include("...")]}
This basically makes a single large template. As such the included
templates will use the same aliased variables.
In simple use cases, it is similar to loading a sub template. However it
lacks the flexibility of sub templates.
Logging and Error Handling
As templates are executed, they may throw an exception. If a syntax
error or file can not be read, an exception is also thrown during load.
In the case of a syntax error, "die" is called with a summary of
template, prefixed with line numbers which caused the error. Currently 5
line before and after the error are included for context generated by
Error::Show. Deliberately breaking the synopsis example (see examples
dir) gives the following error output:
perl -I lib examples/synopsis_syntax_error.pl
GLOB(0x7f8510025928)
1 {@{[
2 init {
3 use Time::HiRes qw<time>;
4 a+1
5=> $title="Mr.";
6 }
7 ]}
8 Dear $title Connery,
9 Ordered a $size pizza with $slices slices to share between @$people and
10 myself. That averages @{[$slices/(@$people+1)]} slices each.}
syntax error at GLOB(0x7f8510025928) 5 near "1
It is recommended to use a try/catch block to process the errors.
Currently Log::ger combined with "Log::OK" is utilised for logging and
debugging purposes. This comes in very handy when developing sub
classes.
Also note that line numbers reported in errors can be inaccurate when
the block_fix and include features are in use, as the content of the
source file is altered
Filters
Unlike other template system, there are no built in filters. However as
"Template::Plex" templates are just Perl you are free to use builtin
string routines or import other modules in to your template.
API
"load"
#Class method. Used by top level applciation
Template::Plex->load($path, $vars, %opts);
#Object method. Used within a template
@{[$self->load($path, $vars, %opts);
#Subroutine. Prefered within a template.
@{[load $path, $vars, %opts]}
#Reuse existing $vars and %opts from withing a template
@{[load $path]}
A factory method, returning a new instance of a template, loaded from a
scalar, file path or an existing file handle.
From a top level user application, the class method must be used. From
within a template, either the object method form or subroutine form can
be used.
If no variables or options are specified when loading a sub templates,
the variables and options from the calling templates are reused.
Arguments to this function:
$path
This is a required argument.
If $path is a string, it is treated as a file path to a template
file. The file is opened and slurped with the content being used as
the template. If $root option is specified, it is prepended to this
string
If $path is a filehandle, or GLOB ref, it is slurped with the
content being used as the template. Can be used to read template
stored in "__DATA__" for example
If $path is an array ref, the items of the array are joined into a
string, which is used directly as the template.
From v0.7.0 If $path is an scalar ref, the path is treated relative
to the calling template or top level file.
$vars
This is an optional argument but if present must be an empty hash
ref "{}" or "undef".
The top level items of the $vars hash are aliased into the template
using the key name (key names must be valid for a variable name for
this to operate). This allows an element such as "$fields{name"}> to
be directly accessible as $name in the template and sub templates.
External modification of the items in $vars will be visible in the
template. This is thee primary mechanism change inputs for
subsequent renders of the template.
In addition, the $vars itself is aliased to %fields variable (note
the %) and directly usable in the template like a normal hash e.g.
$fields{name}
If the $vars is an empty hash ref "{}" or "undef" then no variables
will be lexically aliased. The only variables accessible to the
template will be via the "render" method call.
%options
These are non required arguments, but must be key value pairs when
used.
Options are stored lexically for access in the template in the
variable %options. This variable is automatically used as the
options argument in recursive calls to "load" or "plx", if no
options are provided.
Currently supported options are:
root
"root" is a directory path, which if present, is prepended to to
the $path parameter if $path is a string (file path).
no_include
Disables the uses of the preprocessor include feature. The
template text will not be scanned and will prevent the "include"
feature from operating. See "include" for more details
This doesn't impact recursive calls to "load" when
dynamically/conditionally loading templates.
"no_init_fix"
Disables correcting missing init blocks.
If not specified or false, a template file is scanned for a
"@{[init{..}]}" directive. If one is found, the template is not
modified. Otherwise, a 'null' block is added at the beginning of
the template.
The added block is not effected by the enabling/disabling of
block fix mechanism.
no_block_fix
Disables removing of EOL after a "@{[]}"
eg
Line 1
@{[
""
]} <-- this NL removed by default
Line 3
In the above example, the default behaviour is to remove the
newline after the closing "]}". The rendered output would be:
Line1
Line3
If block fix was disabled (i.e. "no_block_fix" was true) the
output would be:
Line1
Line3
NOTE: in the case of a syntax error present in the template, the
line numbers maybe incorrect when block_fix is active, as it
effectively removes a line from the source
no_eof_chomp
When this key is present and value is true, the last newline in
the template file is left in place.
Most text editors insert a extra newline as the last character
in a file. By default a chomp is performed before the template
is prepared to avoid extra newlines in the output when using sub
templates.
If you really need that newline you can specify the
"no_eof_chomp => 1" key or place an extra empty line at the end
of your template.
use_comments
Depricated and will be removed in later versions. Use this for
new code:
@{[
# block comment
# goes here
]}
From v0.5.0 Enables stripping of lines that start with perl
style comments from the template before preparation. This is
disabled by default
package
Specifies a package to run the template in. Any "our" variables
defined in the template will be in this package. If a package is
not specified, a unique package name is created to prevent name
collisions
base
Specifies the base class type of the template. If not specified,
templates are of type "Template::Plex". Sub classes must inherit
from this class.
Sub classes should force always specify this field.
no_alias
Top level elements in a $vars hash are aliased into the template
by default.
If this key is present and true, aliasing is disabled and all
variables need to be accessed via the %fields.
use An array ref of packages names (as strings) to use within a
template's package. Intended to be utilised by subclasses to add
features to a template.
inject
An array ref of strings, representing Perl code, to be injected
into the template package. Intended to be utilised for
subclasses to inject small pieces of code which cannot be
otherwise required/used.
Return value
The return value is "Template::Plex" (or subclass) object which can
be rendered using the "render" method.
Example Usage my $hash={ name=>"bob", age=>98 };
my $template_dir="/path/to/dir";
my $obj=Template::Plex->load("template.plex", $hash, root=>$template_dir);
$obj->render;
=back
"cache"
# Class method
#
Template::Plex->cache($key, $path, $vars, %options);
# Object method
$self->cache($key, $path, $vars, %options);
# Subroutine
cache $key, $path, $vars, %options;
#Force the current line/package/template as a key
cache undef, $path, $vars, $%opts;
# v0.6.0 onwards also supports additional arguments forms
# Implicit key, explicit variables and options
#
Template::Plex->cache($path, $vars, %options);
$self->cache($path, $vars, %options);
cache $path, $vars, %options;
# Implicit key and implicit variables/options
#
Template::Plex->cache($path);
$self->cache($path);
cache $path;
This is a wrapper around the "load" API primarily used to improve
performance of sub templates used in loops.
From v0.6.0: If the number of arguments passed to the cache
functions/method is 1, it is assumed to be a path and an implicit cache
key is used and implicit reuse of variables and options is assumed. If
the number of arguments is larger than 1, AND the second argument is a
hash ref of variables, then an implicit cache key is used and the first
argument is expected to be a path.
Otherwise an explicit cache key is expected as the first argument and
the second argument is expected to be a path.
Subsequent calls with the same key will return the already loaded
template from active cache.
If called from the top level user application, the cache is shared.
Templates have their own cache storage to prevent cross collisions.
If the explicit key provided is "undef" or an implicit key is used, then
information about the caller (including the line number, package and
target template) is used generate one. This approach allows for a
template which maybe rendered multiple times in a loop, to only be
loaded once for example.
Returns the loaded or cached template
"immediate"
# Class method
Template::Plex->immediate($key, $path, $vars, %options);
# Object method
$self->immediate($key, $path, $vars, %options);
# Subrutine
immediate $key, $path, $vars, %options;
#Use current line/package/template as key
immediate undef, $path, $vars, %options;
# v0.6.0 onwards also supports additional arguments forms
# Implicit key, explicit variables and options
Template::Plex->immediate($path, $vars, %options);
$self->immediate($path, $vars, %options);
immediate $path, $vars, %options;
# Implicit key and implicit variables/options
#
Template::Plex->immediate($path);
$self->immediate($path);
immediate $key;
Loads and renders a template immediately. Uses the same arguments as
"cache". Calls the "cache" API but also calls "render" on the returned
template.
From v0.6.4: The "vars" argument is also used as the extra fields for a
render call. This allows for an immediately loaded/rendered template to
now use field values as well the initial lexical variables.
From v0.6.0: Please refere to the "cache" api on details regarding
argument handling
Returns the result of the rendered loaded/cached template.
"include"
@{[include("path")}]
Depricated and will be removed in later versions. For new code just use
"load" and with no vars to get the same result but with better debugging
ability.
This is a special directive that replaces the directive with the literal
contents of the file pointed to by path in a similar style to #include
in the C preprocessor. This is a preprocessing step which happens before
the template is prepared for execution.
If "root" was included in the options to "load", then it is prepended to
"path" if defined.
When a template is loaded by "load" the processing of this is subject to
the "no_include" option. If "no_include" is specified, any template text
that contains the "@{[include("path")}]" text will result in a syntax
error
NOTE: in the case of a syntax error present in the template, the line
numbers maybe incorrect if "include" is used, as it effectively adds
lines to the template source.
pl
block
@{[ block { ... } ]}
# or
@{[ pl { ... } ]}
A subroutine which executes a block just like the built in "do". However
it always returns an empty string.
Only usable in a template "@{[]}" construct, to execute arbitrary
statements. However, as an empty string is returned, Perl's
interpolation won't inject anything at that point in the template.
If you DO want the last statement returned into the template, use the
built in "do".
eg
@{[
# This will assign a variable for use later in the template
# but WILL NOT inject the value 1 into template when rendered
pl {
$i=1;
}
]}
@{[
# This will assign a variable for use later in the tamplate
# AND immediately inject '1' into the template when rendered
do {
$i=1
}
]}
init
@{[ init {...} ]}
It is used to configure or setup meta data for a template and return
immediately. It takes a single argument which is a Perl block.
Only the first "init {...}" block in a template will be executed.
A "init {...}" block is executed once, even when the template is
rendered multiple times
Before the block is run, the "pre_init" method is called. After the
block is run, the "post_init" method is called.
After the initialisation stages have run, a initialisation flag is set
and the remainder on the template is skipped with the "skip" method.
This means only the first "init" block in a template will be executed
pre_init
Do not call this directly. It is called internally by an init block.
Implemented as an empty method designed to be overridden in a subclass.
post_init
Do not call this directly. It is called internally by an init block.
Implemented as an empty method designed to be overridden in a subclass.
inherit
@{[ init {
inherit "Path to template";
}
]}
Specifies the template which will is the current template's parent. The
current template will be rendered into the default slot of the parent.
slot
@{[slot name=>$value]}
Declares a slot in a template which can be filled by a child template
calling "fill_slot" directives.
"name" is the name of the slot to render into the template. If not
specified, the slot is the default slot which will be rendered by the
content of a child template.
$value is optional and is the default content to render in the case a
child does not provide data for the slot. It can be a scalar value or a
template loaded by "load" or "cache"
fill_slot
@{[fill_slot name=>$value]}
Fills an inherited slot of name "name" with $value, replacing the
current contents.
The default slot cannot be specified. It is filled with the rendered
result of the child template.
append_slot
@{[append_slot name=>$value]}
Appends to an inherited slot of name "name" with $value.
prepend_slot
@{[prepend_slot name=>$value]}
Prepends to an inherited slot of name "name" with $value.
fill_var
@{[fill_var name=>$value]}
Sets the value of a package variable of "name" with $value. Useful for
shared global variables accessible outside of template inheritance.
Returns an empty string.
append_var
@{[append_var name=>$value]}
Appends $value to an global package variable of name "name". Returns an
empty string.
prepend_var
@{[prepend_var name=>$value]}
Prepends $value to an global package variable of name "name". Returns an
empty string.
clear
clear;
Subject to change. Clears the cached templates
jmap
jmap {block} $delimiter, @array
Performs a join using $delimiter between each item in the @array after
they are processed through "block"
Very handy for rendering lists:
eg
<ul>
@{[jmap {"<li>$_</li>"} "\n", @items]}
</ul>
Note the lack of comma after the block.
"skip"
Causes the template to immediately finish, with an empty string as
result. From within a template, either the class method or template
directive can be used:
@{[$self->skip]}
@{[skip]}
"meta"
Returns the options hash used to load the template. From within a
template, it is recommended to use the %options hash instead:
@{[$self->meta->{file}]}
or
@{[$options{file}]}
This can also be used outside template text to inspect a templates meta
information
$template->meta;
"args"
Returns the argument hash used to load the template. From within a
template, it is recommended to use the aliased variables or the %fields
hash instead:
@{[$self->args->{my_arg}]}
or
@{[$fields{my_arg}]}
or
$my_arg
This can also be used outside template text to inspect a templates input
variables
$template->args;
parent
$self->parent;
Returns the parent template.
render
$template->render($fields);
This object method renders a template object created by "load" into a
string. It takes an optional argument $fields which is a reference to a
hash containing field variables. "fields" is aliased into the template
as %fields which is directly accessible in the template
eg
my $more_data={
name=>"John",
};
my $string=$template->render($more_data);
#Template:
My name is $fields{John}
Note that the lexically aliased variables setup in "load" are
independent to the %fields variable and can both be used simultaneously
in a template
SUB CLASSING
Sub classing is as per the standard Perl "use parent". The object
storage is actually an array.
Package constants are defined for the indexes of the fields along with
"KEY_OFFSET" and "KEY_COUNT" to aid in adding extra fields in sub
classes.
If you intend on adding additional fields in your class you will need to
do the following as the object
use parent "Template::Plex";
use constant KEY_OFFSET=>Template::Plex::KEY_OFFSET+ Template::Plex::KEY_COUNT;
use enum ("first_field_=".KEYOFFSET, ..., last_field_);
use constant KEY_COUNT=>last_field_ - first_field_ +1;
Any further sub classing will need to repeat this using using your
package name.
FEATURE CHEAT SHEET
* Templates can contain a initialisation state
@{[
init {
# Nomral perl code here will only execute once
# when templates is loaded
}
]}
* Templates can cache at caller location
Sub/template is loaded only the first time in this map/loop
@{[map {immediate undef, "path_to_template",{}} qw< a b c d e >]}
And rendereds serveral times
* Lexical and package variables accessed/created within templates
@{[
init {
$input_var//=1; #set default
}
}]
Value is $input_var;
* Call and create subroutines within templates:
@{[
init {
sub my_great_calc {
my $input=shift;
$input*2/5;
}
}
}]
Result of calculation: @{[my_great_calc(12)]}
* 'Include' Templates within templates easily:
@{[include("path_to_file")]}
* Recursive sub template loading
@{[load "path_to_sub_template"]}
* Conditional rendering
@{[ $flag and $var]}
@{[ $flag?$var:""]}
@{[
pl {
if($flag){
#do stuff
}
}
]}
* Lists/Loops/maps
template interpolates @$lists directly
Items that are ok:
@{[
do {
#Standard for loop
my $output;
for(@$items){
$output.=$_."\n" if /ok/;
}
$output;
}
}]
More ok items:
@{[map {/ok/?"$_\n":()} @$items]}
* "use" other modules directly in templates:
@{[
init {
use Time::HiRes qw<time>
}
]}
Time of day right now: @{[time]}
TIPS ON USAGE
Potential Pitfalls
* Remeber to set $" locally to your requied seperator
The default is a space, however when generating HTML lists for
example, a would make it easier to read:
#Before executing template
local $"="\n";
load ...
Or alternatively use "jmap" to explicitly set the interpolation
separator each time
* Aliasing is a two way steet
Changes made to aliased variables external to the template are
available inside the template (one of the main tenets of this
module)
Changes make to aliased variables internal to the template are
available outside the template.
* Unbalanced Delimiter Pairs
Perl double quote operators are smart and work on balanced pairs of
delimiters. This allows for the delimiters to appear in the text
body without error.
However if your template doesn't have balanced pairs (i.e. a missing
"}" in javascript/c/perl/etc), the template will fail to compile and
give a strange error.
If you know you don't have balanced delimiters, then you can escape
them with a backslash
Currently Template::Plex delimiter pair used is { }. It isn't
changeable in this version.
* Are you sure it's one statement?