Add built local::lib
[catagits/Gitalist.git] / local-lib5 / bin / ttree
CommitLineData
3fea05b9 1#!/usr/bin/perl -w
2
3eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
4 if 0; # not running under some shell
5#========================================================================
6#
7# ttree
8#
9# DESCRIPTION
10# Script for processing all directory trees containing templates.
11# Template files are processed and the output directed to the
12# relvant file in an output tree. The timestamps of the source and
13# destination files can then be examined for future invocations
14# to process only those files that have changed. In other words,
15# it's a lot like 'make' for templates.
16#
17# AUTHOR
18# Andy Wardley <abw@wardley.org>
19#
20# COPYRIGHT
21# Copyright (C) 1996-2003 Andy Wardley. All Rights Reserved.
22# Copyright (C) 1998-2003 Canon Research Centre Europe Ltd.
23#
24# This module is free software; you can redistribute it and/or
25# modify it under the same terms as Perl itself.
26#
27#------------------------------------------------------------------------
28#
29# $Id: ttree 1196 2009-04-07 13:34:14Z abw $
30#
31#========================================================================
32
33use strict;
34use Template;
35use AppConfig qw( :expand );
36use File::Copy;
37use File::Path;
38use File::Spec;
39use File::Basename;
40use Text::ParseWords qw(quotewords);
41
42my $NAME = "ttree";
43my $VERSION = 2.90;
44my $HOME = $ENV{ HOME } || '';
45my $RCFILE = $ENV{"\U${NAME}rc"} || "$HOME/.${NAME}rc";
46my $TTMODULE = 'Template';
47
48#------------------------------------------------------------------------
49# configuration options
50#------------------------------------------------------------------------
51
52# offer create a sample config file if it doesn't exist, unless a '-f'
53# has been specified on the command line
54unless (-f $RCFILE or grep(/^(-f|-h|--help)$/, @ARGV) ) {
55 print("Do you want me to create a sample '.ttreerc' file for you?\n",
56 "(file: $RCFILE) [y/n]: ");
57 my $y = <STDIN>;
58 if ($y =~ /^y(es)?/i) {
59 write_config($RCFILE);
60 exit(0);
61 }
62}
63
64# read configuration file and command line arguments - I need to remember
65# to fix varlist() and varhash() in AppConfig to make this nicer...
66my $config = read_config($RCFILE);
67my $dryrun = $config->nothing;
68my $verbose = $config->verbose || $dryrun;
69my $colour = $config->colour;
70my $summary = $config->summary;
71my $recurse = $config->recurse;
72my $preserve = $config->preserve;
73my $all = $config->all;
74my $libdir = $config->lib;
75my $ignore = $config->ignore;
76my $copy = $config->copy;
77my $accept = $config->accept;
78my $absolute = $config->absolute;
79my $relative = $config->relative;
80my $suffix = $config->suffix;
81my $binmode = $config->binmode;
82my $depends = $config->depend;
83my $depsfile = $config->depend_file;
84my ($n_proc, $n_unmod, $n_skip, $n_copy, $n_mkdir) = (0) x 5;
85
86my $srcdir = $config->src
87 || die "Source directory not set (-s)\n";
88my $destdir = $config->dest
89 || die "Destination directory not set (-d)\n";
90die "Source and destination directories may not be the same:\n $srcdir\n"
91 if $srcdir eq $destdir;
92
93# unshift any perl5lib directories onto front of INC
94unshift(@INC, @{ $config->perl5lib });
95
96# get all template_* options from the config and fold keys to UPPER CASE
97my %ttopts = $config->varlist('^template_', 1);
98my $ttmodule = delete($ttopts{ module });
99my $ucttopts = {
100 map { my $v = $ttopts{ $_ }; defined $v ? (uc $_, $v) : () }
101 keys %ttopts,
102};
103
104# get all template variable definitions
105my $replace = $config->get('define');
106
107# now create complete parameter hash for creating template processor
108my $ttopts = {
109 %$ucttopts,
110 RELATIVE => $relative,
111 ABSOLUTE => $absolute,
112 INCLUDE_PATH => [ $srcdir, @$libdir ],
113 OUTPUT_PATH => $destdir,
114};
115
116# load custom template module
117if ($ttmodule) {
118 my $ttpkg = $ttmodule;
119 $ttpkg =~ s[::][/]g;
120 $ttpkg .= '.pm';
121 require $ttpkg;
122}
123else {
124 $ttmodule = $TTMODULE;
125}
126
127
128#------------------------------------------------------------------------
129# inter-file dependencies
130#------------------------------------------------------------------------
131
132if ($depsfile or $depends) {
133 $depends = dependencies($depsfile, $depends);
134}
135else {
136 $depends = { };
137}
138
139my $global_deps = $depends->{'*'} || [ ];
140
141# add any PRE_PROCESS, etc., templates as global dependencies
142foreach my $ttopt (qw( PRE_PROCESS POST_PROCESS PROCESS WRAPPER )) {
143 my $deps = $ucttopts->{ $ttopt } || next;
144 my @deps = ref $deps eq 'ARRAY' ? (@$deps) : ($deps);
145 next unless @deps;
146 push(@$global_deps, @deps);
147}
148
149# remove any duplicates
150$global_deps = { map { ($_ => 1) } @$global_deps };
151$global_deps = [ keys %$global_deps ];
152
153# update $depends hash or delete it if there are no dependencies
154if (@$global_deps) {
155 $depends->{'*'} = $global_deps;
156}
157else {
158 delete $depends->{'*'};
159 $global_deps = undef;
160}
161$depends = undef
162 unless keys %$depends;
163
164my $DEP_DEBUG = $config->depend_debug();
165
166
167#------------------------------------------------------------------------
168# pre-amble
169#------------------------------------------------------------------------
170
171if ($colour) {
172 no strict 'refs';
173 *red = \&_red;
174 *green = \&_green;
175 *yellow = \&_yellow;
176 *blue = \&_blue;
177}
178else {
179 no strict 'refs';
180 *red = \&_white;
181 *green = \&_white;
182 *yellow = \&_white;
183 *blue = \&_white;
184}
185
186if ($verbose) {
187 local $" = ', ';
188
189
190 print "$NAME $VERSION (Template Toolkit version $Template::VERSION)\n\n";
191
192 my $sfx = join(', ', map { "$_ => $suffix->{$_}" } keys %$suffix);
193
194 print(" Source: $srcdir\n",
195 " Destination: $destdir\n",
196 "Include Path: [ @$libdir ]\n",
197 " Ignore: [ @$ignore ]\n",
198 " Copy: [ @$copy ]\n",
199 " Accept: [ @$accept ]\n",
200 " Suffix: [ $sfx ]\n");
201 print(" Module: $ttmodule ", $ttmodule->module_version(), "\n")
202 unless $ttmodule eq $TTMODULE;
203
204 if ($depends && $DEP_DEBUG) {
205 print "Dependencies:\n";
206 foreach my $key ('*', grep { !/\*/ } keys %$depends) {
207 printf( " %-16s %s\n", $key,
208 join(', ', @{ $depends->{ $key } }) )
209 if defined $depends->{ $key };
210
211 }
212 }
213 print "\n" if $verbose > 1;
214 print red("NOTE: dry run, doing nothing...\n")
215 if $dryrun;
216}
217
218#------------------------------------------------------------------------
219# main processing loop
220#------------------------------------------------------------------------
221
222my $template = $ttmodule->new($ttopts)
223 || die $ttmodule->error();
224
225if (@ARGV) {
226 # explicitly process files specified on command lines
227 foreach my $file (@ARGV) {
228 my $path = $srcdir ? File::Spec->catfile($srcdir, $file) : $file;
229 if ( -d $path ) {
230 process_tree($file);
231 }
232 else {
233 process_file($file, $path, force => 1);
234 }
235 }
236}
237else {
238 # implicitly process all file in source directory
239 process_tree();
240}
241
242if ($summary || $verbose) {
243 my $format = "%13d %s %s\n";
244 print "\n" if $verbose > 1;
245 print(
246 " Summary: ",
247 $dryrun ? red("This was a dry run. Nothing was actually done\n") : "\n",
248 green(sprintf($format, $n_proc, $n_proc == 1 ? 'file' : 'files', 'processed')),
249 green(sprintf($format, $n_copy, $n_copy == 1 ? 'file' : 'files', 'copied')),
250 green(sprintf($format, $n_mkdir, $n_mkdir == 1 ? 'directory' : 'directories', 'created')),
251 yellow(sprintf($format, $n_unmod, $n_unmod == 1 ? 'file' : 'files', 'skipped (not modified)')),
252 yellow(sprintf($format, $n_skip, $n_skip == 1 ? 'file' : 'files', 'skipped (ignored)'))
253 );
254}
255
256exit(0);
257
258
259#========================================================================
260# END
261#========================================================================
262
263
264#------------------------------------------------------------------------
265# process_tree($dir)
266#
267# Walks the directory tree starting at $dir or the current directory
268# if unspecified, processing files as found.
269#------------------------------------------------------------------------
270
271sub process_tree {
272 my $dir = shift;
273 my ($file, $path, $abspath, $check);
274 my $target;
275 local *DIR;
276
277 my $absdir = join('/', $srcdir ? $srcdir : (), defined $dir ? $dir : ());
278 $absdir ||= '.';
279
280 opendir(DIR, $absdir) || do { warn "$absdir: $!\n"; return undef; };
281
282 FILE: while (defined ($file = readdir(DIR))) {
283 next if $file eq '.' || $file eq '..';
284 $path = defined $dir ? "$dir/$file" : $file;
285 $abspath = "$absdir/$file";
286
287 next unless -e $abspath;
288
289 # check against ignore list
290 foreach $check (@$ignore) {
291 if ($path =~ /$check/) {
292 printf yellow(" - %-32s (ignored, matches /$check/)\n"), $path
293 if $verbose > 1;
294 $n_skip++;
295 next FILE;
296 }
297 }
298
299 # check against acceptance list
300 if (@$accept) {
301 unless ((-d $abspath && $recurse) || grep { $path =~ /$_/ } @$accept) {
302 printf yellow(" - %-32s (not accepted)\n"), $path
303 if $verbose > 1;
304 $n_skip++;
305 next FILE;
306 }
307 }
308
309 if (-d $abspath) {
310 if ($recurse) {
311 my ($uid, $gid, $mode);
312
313 (undef, undef, $mode, undef, $uid, $gid, undef, undef,
314 undef, undef, undef, undef, undef) = stat($abspath);
315
316 # create target directory if required
317 $target = "$destdir/$path";
318 unless (-d $target || $dryrun) {
319 mkpath($target, $verbose, $mode) or
320 die red("Could not mkpath ($target): $!\n");
321
322 # commented out by abw on 2000/12/04 - seems to raise a warning?
323 # chown($uid, $gid, $target) || warn "chown($target): $!\n";
324
325 $n_mkdir++;
326 printf green(" + %-32s (created target directory)\n"), $path
327 if $verbose;
328 }
329 # recurse into directory
330 process_tree($path);
331 }
332 else {
333 $n_skip++;
334 printf yellow(" - %-32s (directory, not recursing)\n"), $path
335 if $verbose > 1;
336 }
337 }
338 else {
339 process_file($path, $abspath);
340 }
341 }
342 closedir(DIR);
343}
344
345
346#------------------------------------------------------------------------
347# process_file()
348#
349# File filtering and processing sub-routine called by process_tree()
350#------------------------------------------------------------------------
351
352sub process_file {
353 my ($file, $absfile, %options) = @_;
354 my ($dest, $destfile, $filename, $check,
355 $srctime, $desttime, $mode, $uid, $gid);
356 my ($old_suffix, $new_suffix);
357 my $is_dep = 0;
358 my $copy_file = 0;
359
360 $absfile ||= $file;
361 $filename = basename($file);
362 $destfile = $file;
363
364 # look for any relevant suffix mapping
365 if (%$suffix) {
366 if ($filename =~ m/\.(.+)$/) {
367 $old_suffix = $1;
368 if ($new_suffix = $suffix->{ $old_suffix }) {
369 $destfile =~ s/$old_suffix$/$new_suffix/;
370 }
371 }
372 }
373 $dest = $destdir ? "$destdir/$destfile" : $destfile;
374
375# print "proc $file => $dest\n";
376
377 # check against copy list
378 foreach my $copy_pattern (@$copy) {
379 if ($filename =~ /$copy_pattern/) {
380 $copy_file = 1;
381 $check = $copy_pattern;
382 last;
383 }
384 }
385
386 # stat the source file unconditionally, so we can preserve
387 # mode and ownership
388 ( undef, undef, $mode, undef, $uid, $gid, undef,
389 undef, undef, $srctime, undef, undef, undef ) = stat($absfile);
390
391 # test modification time of existing destination file
392 if (! $all && ! $options{ force } && -f $dest) {
393 $desttime = ( stat($dest) )[9];
394
395 if (defined $depends and not $copy_file) {
396 my $deptime = depend_time($file, $depends);
397 if (defined $deptime && ($srctime < $deptime)) {
398 $srctime = $deptime;
399 $is_dep = 1;
400 }
401 }
402
403 if ($desttime >= $srctime) {
404 printf yellow(" - %-32s (not modified)\n"), $file
405 if $verbose > 1;
406 $n_unmod++;
407 return;
408 }
409 }
410
411 # check against copy list
412 if ($copy_file) {
413 $n_copy++;
414 unless ($dryrun) {
415 copy($absfile, $dest) or die red("Could not copy ($absfile to $dest) : $!\n");
416
417 if ($preserve) {
418 chown($uid, $gid, $dest) || warn red("chown($dest): $!\n");
419 chmod($mode, $dest) || warn red("chmod($dest): $!\n");
420 }
421 }
422
423 printf green(" > %-32s (copied, matches /$check/)\n"), $file
424 if $verbose;
425
426 return;
427 }
428
429 $n_proc++;
430
431 if ($verbose) {
432 printf(green(" + %-32s"), $file);
433 print(green(" (changed suffix to $new_suffix)")) if $new_suffix;
434 print "\n";
435 }
436
437 # process file
438 unless ($dryrun) {
439 $template->process($file, $replace, $destfile,
440 $binmode ? {binmode => $binmode} : {})
441 || print(red(" ! "), $template->error(), "\n");
442
443 if ($preserve) {
444 chown($uid, $gid, $dest) || warn red("chown($dest): $!\n");
445 chmod($mode, $dest) || warn red("chmod($dest): $!\n");
446 }
447 }
448}
449
450
451#------------------------------------------------------------------------
452# dependencies($file, $depends)
453#
454# Read the dependencies from $file, if defined, and merge in with
455# those passed in as the hash array $depends, if defined.
456#------------------------------------------------------------------------
457
458sub dependencies {
459 my ($file, $depend) = @_;
460 my %depends = ();
461
462 if (defined $file) {
463 my ($fh, $text, $line);
464 open $fh, $file or die "Can't open $file, $!";
465 local $/ = undef;
466 $text = <$fh>;
467 close($fh);
468 $text =~ s[\\\n][]mg;
469
470 foreach $line (split("\n", $text)) {
471 next if $line =~ /^\s*(#|$)/;
472 chomp $line;
473 my ($file, @files) = quotewords('\s*:\s*', 0, $line);
474 $file =~ s/^\s+//;
475 @files = grep(defined, quotewords('(,|\s)\s*', 0, @files));
476 $depends{$file} = \@files;
477 }
478 }
479
480 if (defined $depend) {
481 foreach my $key (keys %$depend) {
482 $depends{$key} = [ quotewords(',', 0, $depend->{$key}) ];
483 }
484 }
485
486 return \%depends;
487}
488
489
490
491#------------------------------------------------------------------------
492# depend_time($file, \%depends)
493#
494# Returns the mtime of the most recent in @files.
495#------------------------------------------------------------------------
496
497sub depend_time {
498 my ($file, $depends) = @_;
499 my ($deps, $absfile, $modtime);
500 my $maxtime = 0;
501 my @pending = ($file);
502 my @files;
503 my %seen;
504
505 # push any global dependencies onto the pending list
506 if ($deps = $depends->{'*'}) {
507 push(@pending, @$deps);
508 }
509
510 print " # checking dependencies for $file...\n"
511 if $DEP_DEBUG;
512
513 # iterate through the list of pending files
514 while (@pending) {
515 $file = shift @pending;
516 next if $seen{ $file }++;
517
518 if (File::Spec->file_name_is_absolute($file) && -f $file) {
519 $modtime = (stat($file))[9];
520 print " # $file [$modtime]\n"
521 if $DEP_DEBUG;
522 }
523 else {
524 $modtime = 0;
525 foreach my $dir ($srcdir, @$libdir) {
526 $absfile = File::Spec->catfile($dir, $file);
527 if (-f $absfile) {
528 $modtime = (stat($absfile))[9];
529 print " # $absfile [$modtime]\n"
530 if $DEP_DEBUG;
531 last;
532 }
533 }
534 }
535 $maxtime = $modtime
536 if $modtime > $maxtime;
537
538 if ($deps = $depends->{ $file }) {
539 push(@pending, @$deps);
540 print " # depends on ", join(', ', @$deps), "\n"
541 if $DEP_DEBUG;
542 }
543 }
544
545 return $maxtime;
546}
547
548
549#------------------------------------------------------------------------
550# read_config($file)
551#
552# Handles reading of config file and/or command line arguments.
553#------------------------------------------------------------------------
554
555sub read_config {
556 my $file = shift;
557 my $verbose = 0;
558 my $verbinc = sub {
559 my ($state, $var, $value) = @_;
560 $state->{ VARIABLE }->{ verbose } = $value ? ++$verbose : --$verbose;
561 };
562 my $config = AppConfig->new(
563 {
564 ERROR => sub { die(@_, "\ntry `$NAME --help'\n") }
565 },
566 'help|h' => { ACTION => \&help },
567 'src|s=s' => { EXPAND => EXPAND_ALL },
568 'dest|d=s' => { EXPAND => EXPAND_ALL },
569 'lib|l=s@' => { EXPAND => EXPAND_ALL },
570 'cfg|c=s' => { EXPAND => EXPAND_ALL, DEFAULT => '.' },
571 'verbose|v' => { DEFAULT => 0, ACTION => $verbinc },
572 'recurse|r' => { DEFAULT => 0 },
573 'nothing|n' => { DEFAULT => 0 },
574 'preserve|p' => { DEFAULT => 0 },
575 'absolute' => { DEFAULT => 0 },
576 'relative' => { DEFAULT => 0 },
577 'colour|color'=> { DEFAULT => 0 },
578 'summary' => { DEFAULT => 0 },
579 'all|a' => { DEFAULT => 0 },
580 'define=s%',
581 'suffix=s%',
582 'binmode=s',
583 'ignore=s@',
584 'copy=s@',
585 'accept=s@',
586 'depend=s%',
587 'depend_debug|depdbg',
588 'depend_file|depfile=s' => { EXPAND => EXPAND_ALL },
589 'template_module|module=s',
590 'template_anycase|anycase',
591 'template_encoding|encoding=s',
592 'template_eval_perl|eval_perl',
593 'template_load_perl|load_perl',
594 'template_interpolate|interpolate',
595 'template_pre_chomp|pre_chomp|prechomp',
596 'template_post_chomp|post_chomp|postchomp',
597 'template_trim|trim',
598 'template_pre_process|pre_process|preprocess=s@',
599 'template_post_process|post_process|postprocess=s@',
600 'template_process|process=s',
601 'template_wrapper|wrapper=s',
602 'template_recursion|recursion',
603 'template_expose_blocks|expose_blocks',
604 'template_default|default=s',
605 'template_error|error=s',
606 'template_debug|debug=s',
607 'template_start_tag|start_tag|starttag=s',
608 'template_end_tag|end_tag|endtag=s',
609 'template_tag_style|tag_style|tagstyle=s',
610 'template_compile_ext|compile_ext=s',
611 'template_compile_dir|compile_dir=s' => { EXPAND => EXPAND_ALL },
612 'template_plugin_base|plugin_base|pluginbase=s@' => { EXPAND => EXPAND_ALL },
613 'perl5lib|perllib=s@' => { EXPAND => EXPAND_ALL },
614 );
615
616 # add the 'file' option now that we have a $config object that we
617 # can reference in a closure
618 $config->define(
619 'file|f=s@' => {
620 EXPAND => EXPAND_ALL,
621 ACTION => sub {
622 my ($state, $item, $file) = @_;
623 $file = $state->cfg . "/$file"
624 unless $file =~ /^[\.\/]|(?:\w:)/;
625 $config->file($file) }
626 }
627 );
628
629 # process main config file, then command line args
630 $config->file($file) if -f $file;
631 $config->args();
632
633 $config;
634}
635
636
637sub ANSI_escape {
638 my $attr = shift;
639 my $text = join('', @_);
640 return join("\n",
641 map {
642 # look for an existing escape start sequence and add new
643 # attribute to it, otherwise add escape start/end sequences
644 s/ \e \[ ([1-9][\d;]*) m/\e[$1;${attr}m/gx
645 ? $_
646 : "\e[${attr}m" . $_ . "\e[0m";
647 }
648 split(/\n/, $text, -1) # -1 prevents it from ignoring trailing fields
649 );
650}
651
652sub _red(@) { ANSI_escape(31, @_) }
653sub _green(@) { ANSI_escape(32, @_) }
654sub _yellow(@) { ANSI_escape(33, @_) }
655sub _blue(@) { ANSI_escape(34, @_) }
656sub _white(@) { @_ } # nullop
657
658
659#------------------------------------------------------------------------
660# write_config($file)
661#
662# Writes a sample configuration file to the filename specified.
663#------------------------------------------------------------------------
664
665sub write_config {
666 my $file = shift;
667
668 open(CONFIG, ">$file") || die "failed to create $file: $!\n";
669 print(CONFIG <<END_OF_CONFIG);
670#------------------------------------------------------------------------
671# sample .ttreerc file created automatically by $NAME version $VERSION
672#
673# This file originally written to $file
674#
675# For more information on the contents of this configuration file, see
676#
677# perldoc ttree
678# ttree -h
679#
680#------------------------------------------------------------------------
681
682# The most flexible way to use ttree is to create a separate directory
683# for configuration files and simply use the .ttreerc to tell ttree where
684# it is.
685#
686# cfg = /path/to/ttree/config/directory
687
688# print summary of what's going on
689verbose
690
691# recurse into any sub-directories and process files
692recurse
693
694# regexen of things that aren't templates and should be ignored
695ignore = \\b(CVS|RCS)\\b
696ignore = ^#
697
698# ditto for things that should be copied rather than processed.
699copy = \\.png\$
700copy = \\.gif\$
701
702# by default, everything not ignored or copied is accepted; add 'accept'
703# lines if you want to filter further. e.g.
704#
705# accept = \\.html\$
706# accept = \\.tt2\$
707
708# options to rewrite files suffixes (htm => html, tt2 => html)
709#
710# suffix htm=html
711# suffix tt2=html
712
713# options to define dependencies between templates
714#
715# depend *=header,footer,menu
716# depend index.html=mainpage,sidebar
717# depend menu=menuitem,menubar
718#
719
720#------------------------------------------------------------------------
721# The following options usually relate to a particular project so
722# you'll probably want to put them in a separate configuration file
723# in the directory specified by the 'cfg' option and then invoke tree
724# using '-f' to tell it which configuration you want to use.
725# However, there's nothing to stop you from adding default 'src',
726# 'dest' or 'lib' options in the .ttreerc. The 'src' and 'dest' options
727# can be re-defined in another configuration file, but be aware that 'lib'
728# options accumulate so any 'lib' options defined in the .ttreerc will
729# be applied every time you run ttree.
730#------------------------------------------------------------------------
731# # directory containing source page templates
732# src = /path/to/your/source/page/templates
733#
734# # directory where output files should be written
735# dest = /path/to/your/html/output/directory
736#
737# # additional directories of library templates
738# lib = /first/path/to/your/library/templates
739# lib = /second/path/to/your/library/templates
740
741END_OF_CONFIG
742
743 close(CONFIG);
744 print "$file created. Please edit accordingly and re-run $NAME\n";
745}
746
747
748#------------------------------------------------------------------------
749# help()
750#
751# Prints help message and exits.
752#------------------------------------------------------------------------
753
754sub help {
755 print<<END_OF_HELP;
756$NAME $VERSION (Template Toolkit version $Template::VERSION)
757
758usage: $NAME [options] [files]
759
760Options:
761 -a (--all) Process all files, regardless of modification
762 -r (--recurse) Recurse into sub-directories
763 -p (--preserve) Preserve file ownership and permission
764 -n (--nothing) Do nothing, just print summary (enables -v)
765 -v (--verbose) Verbose mode. Use twice for more verbosity: -v -v
766 -h (--help) This help
767 -s DIR (--src=DIR) Source directory
768 -d DIR (--dest=DIR) Destination directory
769 -c DIR (--cfg=DIR) Location of configuration files
770 -l DIR (--lib=DIR) Library directory (INCLUDE_PATH) (multiple)
771 -f FILE (--file=FILE) Read named configuration file (multiple)
772
773Display options:
774 --colour / --color Enable colo(u)rful verbose output.
775 --summary Show processing summary.
776
777File search specifications (all may appear multiple times):
778 --ignore=REGEX Ignore files matching REGEX
779 --copy=REGEX Copy files matching REGEX
780 --accept=REGEX Process only files matching REGEX
781
782File Dependencies Options:
783 --depend foo=bar,baz Specify that 'foo' depends on 'bar' and 'baz'.
784 --depend_file FILE Read file dependancies from FILE.
785 --depend_debug Enable debugging for dependencies
786
787File suffix rewriting (may appear multiple times)
788 --suffix old=new Change any '.old' suffix to '.new'
789
790File encoding options
791 --binmode=value Set binary mode of output files
792 --encoding=value Set encoding of input files
793
794Additional options to set Template Toolkit configuration items:
795 --define var=value Define template variable
796 --interpolate Interpolate '\$var' references in text
797 --anycase Accept directive keywords in any case.
798 --pre_chomp Chomp leading whitespace
799 --post_chomp Chomp trailing whitespace
800 --trim Trim blank lines around template blocks
801 --eval_perl Evaluate [% PERL %] ... [% END %] code blocks
802 --load_perl Load regular Perl modules via USE directive
803 --absolute Enable the ABSOLUTE option
804 --relative Enable the RELATIVE option
805 --pre_process=TEMPLATE Process TEMPLATE before each main template
806 --post_process=TEMPLATE Process TEMPLATE after each main template
807 --process=TEMPLATE Process TEMPLATE instead of main template
808 --wrapper=TEMPLATE Process TEMPLATE wrapper around main template
809 --default=TEMPLATE Use TEMPLATE as default
810 --error=TEMPLATE Use TEMPLATE to handle errors
811 --debug=STRING Set TT DEBUG option to STRING
812 --start_tag=STRING STRING defines start of directive tag
813 --end_tag=STRING STRING defined end of directive tag
814 --tag_style=STYLE Use pre-defined tag STYLE
815 --plugin_base=PACKAGE Base PACKAGE for plugins
816 --compile_ext=STRING File extension for compiled template files
817 --compile_dir=DIR Directory for compiled template files
818 --perl5lib=DIR Specify additional Perl library directories
819 --template_module=MODULE Specify alternate Template module
820
821See 'perldoc ttree' for further information.
822
823END_OF_HELP
824
825 exit(0);
826}
827
828__END__
829
830
831#------------------------------------------------------------------------
832# IMPORTANT NOTE
833# This documentation is generated automatically from source
834# templates. Any changes you make here may be lost.
835#
836# The 'docsrc' documentation source bundle is available for download
837# from http://www.template-toolkit.org/docs.html and contains all
838# the source templates, XML files, scripts, etc., from which the
839# documentation for the Template Toolkit is built.
840#------------------------------------------------------------------------
841
842=head1 NAME
843
844Template::Tools::ttree - Process entire directory trees of templates
845
846=head1 SYNOPSIS
847
848 ttree [options] [files]
849
850=head1 DESCRIPTION
851
852The F<ttree> script is used to process entire directory trees containing
853template files. The resulting output from processing each file is then
854written to a corresponding file in a destination directory. The script
855compares the modification times of source and destination files (where
856they already exist) and processes only those files that have been modified.
857In other words, it is the equivalent of 'make' for the Template Toolkit.
858
859It supports a number of options which can be used to configure
860behaviour, define locations and set Template Toolkit options. The
861script first reads the F<.ttreerc> configuration file in the HOME
862directory, or an alternative file specified in the TTREERC environment
863variable. Then, it processes any command line arguments, including
864any additional configuration files specified via the C<-f> (file)
865option.
866
867=head2 The F<.ttreerc> Configuration File
868
869When you run F<ttree> for the first time it will ask you if you want
870it to create a F<.ttreerc> file for you. This will be created in your
871home directory.
872
873 $ ttree
874 Do you want me to create a sample '.ttreerc' file for you?
875 (file: /home/abw/.ttreerc) [y/n]: y
876 /home/abw/.ttreerc created. Please edit accordingly and re-run ttree
877
878The purpose of this file is to set any I<global> configuration options
879that you want applied I<every> time F<ttree> is run. For example, you
880can use the C<ignore> and C<copy> option to provide regular expressions
881that specify which files should be ignored and which should be copied
882rather than being processed as templates. You may also want to set
883flags like C<verbose> and C<recurse> according to your preference.
884
885A minimal F<.ttreerc>:
886
887 # ignore these files
888 ignore = \b(CVS|RCS)\b
889 ignore = ^#
890 ignore = ~$
891
892 # copy these files
893 copy = \.(gif|png|jpg|pdf)$
894
895 # recurse into directories
896 recurse
897
898 # provide info about what's going on
899 verbose
900
901In most cases, you'll want to create a different F<ttree> configuration
902file for each project you're working on. The C<cfg> option allows you
903to specify a directory where F<ttree> can find further configuration
904files.
905
906 cfg = /home/abw/.ttree
907
908The C<-f> command line option can be used to specify which configuration
909file should be used. You can specify a filename using an absolute or
910relative path:
911
912 $ ttree -f /home/abw/web/example/etc/ttree.cfg
913 $ ttree -f ./etc/ttree.cfg
914 $ ttree -f ../etc/ttree.cfg
915
916If the configuration file does not begin with C</> or C<.> or something
917that looks like a MS-DOS absolute path (e.g. C<C:\\etc\\ttree.cfg>) then
918F<ttree> will look for it in the directory specified by the C<cfg> option.
919
920 $ ttree -f test1 # /home/abw/.ttree/test1
921
922The C<cfg> option can only be used in the F<.ttreerc> file. All the
923other options can be used in the F<.ttreerc> or any other F<ttree>
924configuration file. They can all also be specified as command line
925options.
926
927Remember that F<.ttreerc> is always processed I<before> any
928configuration file specified with the C<-f> option. Certain options
929like C<lib> can be used any number of times and accumulate their values.
930
931For example, consider the following configuration files:
932
933F</home/abw/.ttreerc>:
934
935 cfg = /home/abw/.ttree
936 lib = /usr/local/tt2/templates
937
938F</home/abw/.ttree/myconfig>:
939
940 lib = /home/abw/web/example/templates/lib
941
942When F<ttree> is invoked as follows:
943
944 $ ttree -f myconfig
945
946the C<lib> option will be set to the following directories:
947
948 /usr/local/tt2/templates
949 /home/abw/web/example/templates/lib
950
951Any templates located under F</usr/local/tt2/templates> will be used
952in preference to those located under
953F</home/abw/web/example/templates/lib>. This may be what you want,
954but then again, it might not. For this reason, it is good practice to
955keep the F<.ttreerc> as simple as possible and use different
956configuration files for each F<ttree> project.
957
958=head2 Directory Options
959
960The C<src> option is used to define the directory containing the
961source templates to be processed. It can be provided as a command
962line option or in a configuration file as shown here:
963
964 src = /home/abw/web/example/templates/src
965
966Each template in this directory typically corresponds to a single
967web page or other document.
968
969The C<dest> option is used to specify the destination directory for the
970generated output.
971
972 dest = /home/abw/web/example/html
973
974The C<lib> option is used to define one or more directories containing
975additional library templates. These templates are not documents in
976their own right and typically comprise of smaller, modular components
977like headers, footers and menus that are incorporated into pages templates.
978
979 lib = /home/abw/web/example/templates/lib
980 lib = /usr/local/tt2/templates
981
982The C<lib> option can be used repeatedly to add further directories to
983the search path.
984
985A list of templates can be passed to F<ttree> as command line arguments.
986
987 $ ttree foo.html bar.html
988
989It looks for these templates in the C<src> directory and processes them
990through the Template Toolkit, using any additional template components
991from the C<lib> directories. The generated output is then written to
992the corresponding file in the C<dest> directory.
993
994If F<ttree> is invoked without explicitly specifying any templates
995to be processed then it will process every file in the C<src> directory.
996If the C<-r> (recurse) option is set then it will additionally iterate
997down through sub-directories and process and other template files it finds
998therein.
999
1000 $ ttree -r
1001
1002If a template has been processed previously, F<ttree> will compare the
1003modification times of the source and destination files. If the source
1004template (or one it is dependant on) has not been modified more
1005recently than the generated output file then F<ttree> will not process
1006it. The F<-a> (all) option can be used to force F<ttree> to process
1007all files regardless of modification time.
1008
1009 $ tree -a
1010
1011Any templates explicitly named as command line argument are always
1012processed and the modification time checking is bypassed.
1013
1014=head2 File Options
1015
1016The C<ignore>, C<copy> and C<accept> options are used to specify Perl
1017regexen to filter file names. Files that match any of the C<ignore>
1018options will not be processed. Remaining files that match any of the
1019C<copy> regexen will be copied to the destination directory. Remaining
1020files that then match any of the C<accept> criteria are then processed
1021via the Template Toolkit. If no C<accept> parameter is specified then
1022all files will be accepted for processing if not already copied or
1023ignored.
1024
1025 # ignore these files
1026 ignore = \b(CVS|RCS)\b
1027 ignore = ^#
1028 ignore = ~$
1029
1030 # copy these files
1031 copy = \.(gif|png|jpg|pdf)$
1032
1033 # accept only .tt2 templates
1034 accept = \.tt2$
1035
1036The C<suffix> option is used to define mappings between the file
1037extensions for source templates and the generated output files. The
1038following example specifies that source templates with a C<.tt2>
1039suffix should be output as C<.html> files:
1040
1041 suffix tt2=html
1042
1043Or on the command line,
1044
1045 --suffix tt2=html
1046
1047You can provide any number of different suffix mappings by repeating
1048this option.
1049
1050The C<binmode> option is used to set the encoding of the output file.
1051For example use C<--binmode=:utf8> to set the output format to unicode.
1052
1053=head2 Template Dependencies
1054
1055The C<depend> and C<depend_file> options allow you to specify
1056how any given template file depends on another file or group of files.
1057The C<depend> option is used to express a single dependency.
1058
1059 $ ttree --depend foo=bar,baz
1060
1061This command line example shows the C<--depend> option being used to
1062specify that the F<foo> file is dependant on the F<bar> and F<baz>
1063templates. This option can be used many time on the command line:
1064
1065 $ ttree --depend foo=bar,baz --depend crash=bang,wallop
1066
1067or in a configuration file:
1068
1069 depend foo=bar,baz
1070 depend crash=bang,wallop
1071
1072The file appearing on the left of the C<=> is specified relative to
1073the C<src> or C<lib> directories. The file(s) appearing on the right
1074can be specified relative to any of these directories or as absolute
1075file paths.
1076
1077For example:
1078
1079 $ ttree --depend foo=bar,/tmp/baz
1080
1081To define a dependency that applies to all files, use C<*> on the
1082left of the C<=>.
1083
1084 $ ttree --depend *=header,footer
1085
1086or in a configuration file:
1087
1088 depend *=header,footer
1089
1090Any templates that are defined in the C<pre_process>, C<post_process>,
1091C<process> or C<wrapper> options will automatically be added to the
1092list of global dependencies that apply to all templates.
1093
1094The C<depend_file> option can be used to specify a file that contains
1095dependency information.
1096
1097 $ ttree --depend_file=/home/abw/web/example/etc/ttree.dep
1098
1099Here is an example of a dependency file:
1100
1101 # This is a comment. It is ignored.
1102
1103 index.html: header footer menubar
1104
1105 header: titlebar hotlinks
1106
1107 menubar: menuitem
1108
1109 # spanning multiple lines with the backslash
1110 another.html: header footer menubar \
1111 sidebar searchform
1112
1113Lines beginning with the C<#> character are comments and are ignored.
1114Blank lines are also ignored. All other lines should provide a
1115filename followed by a colon and then a list of dependant files
1116separated by whitespace, commas or both. Whitespace around the colon
1117is also optional. Lines ending in the C<\> character are continued
1118onto the following line.
1119
1120Files that contain spaces can be quoted. That is only necessary
1121for files after the colon (':'). The file before the colon may be
1122quoted if it contains a colon.
1123
1124As with the command line options, the C<*> character can be used
1125as a wildcard to specify a dependency for all templates.
1126
1127 * : config,header
1128
1129=head2 Template Toolkit Options
1130
1131F<ttree> also provides access to the usual range of Template Toolkit
1132options. For example, the C<--pre_chomp> and C<--post_chomp> F<ttree>
1133options correspond to the C<PRE_CHOMP> and C<POST_CHOMP> options.
1134
1135Run C<ttree -h> for a summary of the options available.
1136
1137=head1 AUTHORS
1138
1139Andy Wardley E<lt>abw@andywardley.comE<gt>
1140
1141L<http://www.andywardley.com/|http://www.andywardley.com/>
1142
1143With contributions from Dylan William Hardison (support for
1144dependencies), Bryce Harrington (C<absolute> and C<relative> options),
1145Mark Anderson (C<suffix> and C<debug> options), Harald Joerg and Leon
1146Brocard who gets everywhere, it seems.
1147
1148=head1 VERSION
1149
11502.68, distributed as part of the
1151Template Toolkit version 2.19, released on 27 April 2007.
1152
1153=head1 COPYRIGHT
1154
1155 Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
1156
1157
1158This module is free software; you can redistribute it and/or
1159modify it under the same terms as Perl itself.
1160
1161=head1 SEE ALSO
1162
1163L<tpage|Template::Tools::tpage>
1164