PageRenderTime 67ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/CS/migrated/tags/PRE_OR_REMOVAL/mk/perl5/bin/ttree

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