[Bio] / Sprout / CompileTemplate.pl Repository:
ViewVC logotype

View of /Sprout/CompileTemplate.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (download) (as text) (annotate)
Thu Dec 6 14:48:44 2007 UTC (12 years ago) by parrello
Branch: MAIN
Changes since 1.3: +7 -4 lines
Added support for a description.

#!/usr/bin/perl -w

=head1 PERL Template Compiler

This script compiles the Komodo templates into web pages. Each web page
displays the template and the relevant prompts. Filling in the prompts
and clicking the SUBMIT button brings up a text page containing the
code to copy into your code editor.

When formatting the template for display, comments are displayed using
the C<codeComment> style and template variables using the C<codeVar>
style. The entire text will be in a C<pre> element with the
C<codeNormal> style.

The templates use the notation C<[[%ask>I<n>C<:>I<prompt>C<]]> for most
variables. In more complex templates, there are also flag prompts
and if-constructs. This notation is designed to be compatible with
the Komodo template/snippet facility.

Each template produces two output files: the web page itself and a
copy of the template that the composition script can to form the
output code. The web page has the extension C<.html> and the
template copy has the extension C<.txt>.

There are two positional parameters: the name of the directory containing
the template files (usually somewhere in the source code tree) and the
name of the output directory into which the template files should be stored.
The template files will be placed in a subdirectory called C<Helpers> under
the output directory. This makes them easier to find.

The currently-supported command-line options are as follows.

=over 4

=item user

Name suffix to be used for log files. If omitted, the PID is used.

=item trace

Numeric trace level. A higher trace level causes more messages to appear. The
default trace level is 2. Tracing will be directly to the standard output
as well as to a C<trace>I<User>C<.log> file in the FIG temporary directory,
where I<User> is the value of the B<user> option above.

=item background

Save the standard and error output to files. The files will be created
in the FIG temporary directory and will be named C<err>I<User>C<.log> and
C<out>I<User>C<.log>, respectively, where I<User> is the value of the
B<user> option above.

=item h

Display this command's parameters and options.

=item phone

Phone number to message when the script is complete.

=item style

URL for the style file. The default is C<../Georgia.css>.

=item

=back

=cut

use strict;
use Tracer;
use DocUtils;
use TestUtils;
use Cwd;
use File::Copy;
use File::Path;
use FIG;
use CGI;

# Get the command-line options and parameters.
my ($options, @parameters) = StandardSetup([qw() ],
                                           {
                                              trace => ["2", "trace level"],
                                              style => ["../Georgia.css", "style file URL for the generated pages"],
                                              phone => ["", "phone number (international format) to call when load finishes"],
                                           },
                                           "<sourceDirectory> <outputDirectory>",
                                           @ARGV);
# Set a variable to contain return type information.
my $rtype;
# Insure we catch errors.
eval {
    # Check the input and output directories.
    my ($inputDir, $outputDir) = @parameters;
    if (! $inputDir) {
        Confess("No input directory specified.");
    } elsif (! -d $inputDir) {
        Confess("Input directory not found.");
    } elsif (! $outputDir) {
        Confess("No output directory specified.");
    } elsif (! -d $outputDir) {
        Confess("Output directory not found.");
    } else {
        # Create a subdirectory for the helpers in the output directory.
        if (! -d "$outputDir/Helpers") {
            Trace("Creating helpers subdirectory in $outputDir.") if T(2);
            mkdir "$outputDir/Helpers";
        }
        # Get the files from the input directory. (The "1" means hidden (.) files are omitted.
        Trace("Reading input directory $inputDir.") if T(2);
        my @files = OpenDir($inputDir, 1);
        Trace(scalar(@files) . " files found.") if T(2);
        # Loop through the files.
        for my $file (@files) {
            # Compute the input and output file names.
            my $inputName = "$inputDir/$file";
            # Only proceed if this is a real file.
            if (-f $inputName) {
                $file =~ s/\./-/g;
                my $outputName = "$outputDir/Helpers/$file.html";
                Trace("$inputName will be compiled into $outputName.") if T(3);
                # Copy the template to the VAR directory.
                my $copyName = "$FIG_Config::var/$file.txt";
                copy($inputName, $copyName);
                # Open the input and output files.
                my $ih = Open(undef, "<$inputName");
                my $oh = Open(undef, ">$outputName");
                # Compile the input file into a web page.
                CompileTemplate($ih, $oh, $copyName, $file, $options->{style});
                # Close the files.
                close $oh;
                close $ih;
                Trace("Compilation complete.") if T(3);
            }
        }
    }
};
if ($@) {
    Trace("Script failed with error: $@") if T(0);
    $rtype = "error";
} else {
    Trace("Script complete.") if T(2);
    $rtype = "no error";
}
if ($options->{phone}) {
    my $msgID = Tracer::SendSMS($options->{phone}, "PERL Template Compiler terminated with $rtype.");
    if ($msgID) {
        Trace("Phone message sent with ID $msgID.") if T(2);
    } else {
        Trace("Phone message not sent.") if T(2);
    }
}

=head3 CompileTemplate

    CompileTemplate($ih, $oh, $copyName, $templateName, $style);

Compile a template from an input stream into a web page that can be used to generate code from
the template. The web page will contain a display of the template file plus a form allowing the
user to enter the values of various template variables. The template content is read from a
file whose name is stored as a hidden variable in the form.

=over 4

=item ih

Open handle for the input file (template).

=item oh

Open handle for the output file (interactive web page).

=item copyName

Fully-qualified name of the server file that contains the template text.

=item templateName

Name of the template (for display purposes).

=item style

Style URL to use for the output web page.

=back

=cut

sub CompileTemplate {
    # Get the parameters.
    my ($ih, $oh, $copyName, $templateName, $style) = @_;
    # We'll accumulate the web page lines in here and unspool them at the end.
    my @retVal = ();
    # Get a CGI object for building the web page.
    my $cgi = CGI->new();
    # Start with the page header.
    push @retVal, $cgi->start_html(-title => "FIG Code Template $templateName",
                                   -style => { src => $style });
    # Create a heading for the template display.
    push @retVal, $cgi->h2("Template Text");
    # We will present the template as preformatted text with SPAN tags mixed in.
    # We do some syntax coloring to distinguish comments, and this requires that
    # we keept track of whether or not we're in POD mode.
    my $inPod = 0;
    # We also need to track the various variables we encounter, because these
    # determine the prompts in the form.
    my %prompts = ();
    # Get some useful strings for adding span codes.
    my $spanVar = $cgi->start_span({ class => "codeVar" });
    my $spanComment = $cgi->start_span({ class => "codeComment" });
    my $spanEnd = $cgi->end_span();
    # Start the table to enclose the text.
    push @retVal, $cgi->start_table({border => 2});
    push @retVal, "<tr><td><pre class=\"codeNormal\">";
    # Now loop through the input file.
    while (! eof $ih) {
        # Get the current line.
        my $line = <$ih>;
        # Chop off the new-line mark.
        chomp $line;
        # Parse for prompts.
        while ($line =~ /\[\[\%([a-z]+\d+):([^\]]+)\]\]/g) {
            $prompts{$1} = $2;
        }
        # Html-escape the text.
        $line = CGI::escapeHTML($line);
        # Span the various meta-constructs.
        $line =~ s/(\[\[\%[^]]+\]\])/$spanVar$1$spanEnd/g;
        # Check for a pod mode change.
        if ($inPod && $line =~ /^=cut/) {
            # End of pod mode, so we turn off the comment style.
            $line .= $spanEnd;
            $inPod = 0;
        } elsif (! $inPod && $line =~ /^=/) {
            # Start pod mode, so we turn on the comment style.
            $line = "$spanComment$line";
            $inPod = 1;
        }
        # If we're not in POD mode, check for comment lines. Sadly, we aren't yet
        # smart enough to find inline comments. We're trying to be simple here.
        if (! $inPod) {
            $line =~ s/(#.*$)/$spanComment$1$spanEnd/;
        }
        # Output the modified line.
        push @retVal, $line;
    }
    # Stop the table.
    push @retVal, "</pre></td></tr>";
    push @retVal, $cgi->end_table();
    # Now comes the form. The form data is processed by the ProcessTemplate CGI script.
    push @retVal, $cgi->h2("Code Generation Form");
    push @retVal, $cgi->start_form(-name   => 'CodeGen',
                                   -action => "$FIG_Config::cgi_url/ProcessTemplate.cgi");
    # Put in the hidden field containing the template file name.
    push @retVal, $cgi->hidden(-name => 'templateFile', -value => $copyName);
    # We'll use the prompt hash to generate the input fields. We'll process them by key name, so that
    # they sort in a natural order.
    my @promptKeys = sort keys %prompts;
    # Start a table. This helps format the prompts.
    push @retVal, $cgi->start_table({ border => 2 });
    # We'll put all the flags in here. They are added at the end of the table.
    my @flagLines = ();
    # This will be a list of the flag names. We put this list into a hidden field so we
    # know which flag IDs are valid.
    my @flagNames = ();
    # Loop through the prompts.
    for my $promptKey (@promptKeys) {
        # Extract the prompt text.
        my $promptText = $prompts{$promptKey};
        if ($promptKey =~ /flag/) {
            # Here we have a checkbox. It goes in the cell for flags.
            push @flagLines, $cgi->checkbox(-name => $promptKey, -value => 1, -label => $promptText);
            # Save its name.
            push @flagNames, $promptKey;
        } else {
            # Here we have an input box. It goes in a table row.
            push @retVal, $cgi->Tr($cgi->td([$promptText, $cgi->textfield(-name => $promptKey, -size => 40)]));
        }
    }
    # Put in the flag row (if any)
    if (@flagLines) {
        push @retVal, $cgi->Tr($cgi->td(["Flags", join($cgi->br, @flagLines)]));
    }
    # Put in the file title row.
    push @retVal, $cgi->Tr($cgi->td(["File Title", $cgi->textfield(-name => "fileTitle", -size => 40)]));
    # Finally, add the description.
    push @retVal, $cgi->Tr($cgi->td(["Description", $cgi->textarea(-name => 'desc', -rows => 10,
                                                                   -cols => 80, -wrap => 'physical')]));
    # Now for the submit button.
    push @retVal, $cgi->Tr( $cgi->td({-colspan => 2, -align => "center" },
                            $cgi->submit(-name => 'submit', -value => 'GENERATE')));
    # Close the table.
    push @retVal, $cgi->end_table();
    # Put in a list of the flag names.
    push @retVal, $cgi->hidden(-name => 'flagList', -value => join(",", @flagNames));
    # Close the form.
    push @retVal, $cgi->end_form();
    # Write the output web page.
    print $oh join("\n", @retVal);
}

1;

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3