ANNOUNCE: Text::MetaText module v0.15 released. 
Author Message
 ANNOUNCE: Text::MetaText module v0.15 released.

I've recently uploaded my Text::MetaText module to PAUSE.  It should be
percolating through CPAN as I type.

   Text::
   ::MetaText     bdp0  Text processing/markup meta-language      

Documentation attached.

A

===> snip <===

NAME
    Text::MetaText - Perl extension implementing meta-language for
    processing "template" text files.

SYNOPSIS
        use Text::MetaText;
        my $mt = new Text::MetaText;
        print $mt->process($filename, \%vardefs);

SUMMARY OF METATEXT DIRECTIVES
        %% DEFINE variable=value %%   # define variable(s)

        %% SUBST variable  %%         # insert variable value
        %% variable %%                # short form of above

        %% BLOCK blockname %%         # define a block 'blockname'
           block text...
        %% ENDBLOCK %%

        %% INCLUDE blockname %%       # include 'blockname' block text
        %% INCLUDE filename  %%       # include external file 'filename'

        %% INCLUDE file_or_block      # a more complete example...
           variable=value             # additional variable definition(s)
           if=condition               # conditional inclusion
           format=format_string       # printf-like format string with '%s'
           filter=fltname(params)     # post-process filter
        %%

        %% TIME                       # current system time, as per time(2)
           format=format_string       # display format, as per strftime(3C)
        %%

DESCRIPTION
    MetaText is a text processing and markup meta-language which can
    be used for processing "template" files. This module is a Perl 5
    extension implementing a MetaText object class which processes
    text files, interpreting and acting on the embedded MetaText
    directives within.

    Like a glorified pre-processor, MetaText can; include files,
    define and substitute variable values, execute conditional
    actions based on variables, call other perl functions or object
    methods and capture the resulting output back into the document,
    and more. It can format the resulting output of any of these
    operations in a number of ways. The objects, and inherently, the
    format and symantics of the MetaText langauge itself, are highly
    configurable.

    MetaText was originally designed to aid in the creation of html
    documents in a large web site. It remains well suited for this
    and similar tasks, being able to create web pages (dynamically
    or statically) that are consistent with each other, yet easily
    customisable:

    *   standard headers, footers and other elements can be defined in
        separate files and then inserted into web documents:

            %% INCLUDE header %%

    *   variables can be defined externally or from within a document,
        then can be substituted back into the text. This is useful
        for including your %% name %% or %% email %% address or any
        other variable, and for encoding URL's or file paths that
        can then be changed en masse. e.g.

            <img src="%% imgroot %%/foo/bar.gif">

    *   conditional actions can be made based on variable definitions,
        allowing easily and instantly customisable web pages. e.g

            %% INCLUDE higraphics/header if="higfx && userid != abw" %%

    *   blocks of text can be internally defined simplifying the
        creation of repetitive elements. e.g.

            %% BLOCK table_row %%
            <tr> <td>%% userid %%</td> <td>%% name %%</td> </tr>
            %% ENDBLOCK %%

            %% INCLUDE table_row userid=lwall  name="Larry Wall"         %%
            %% INCLUDE table_row userid=tomc   name="Tom Christiansen"   %%
            %% INCLUDE table_row userid=merlyn name="Randal L. Schwartz" %%

    *   in addition, the metapage utility is a script which can
        automatically traverse document trees, processing updated
        files to assist in web document management and other similar
        tasks.

PREREQUISITES
    MetaText requires Perl 5.004 or later. The Date::Format module
    should also be installed. This is available from CPAN (in the
    "TimeDate" distribution) as described in the following section.

OBTAINING AND INSTALLING THE METATEXT MODULE
    The MetaText module is available from CPAN. As the 'perlmod' man
    page explains:

        CPAN stands for the Comprehensive Perl Archive Network.
        This is a globally replicated collection of all known Perl
        materials, including hundreds of unbunded modules.  

        [...]

        For an up-to-date listing of CPAN sites, see
        http://www.*-*-*.com/ ://ftp.perl.com/perl/ .

    Within the CPAN archive, MetaText is in the "Text::" group which
    forms part of the the category:

      *) String Processing, Language Text Processing,
         Parsing and Searching

    The module is available in the following directories:

        /modules/by-module/Text/Text-MetaText-<version>.tar.gz
        /authors/id/ABW/Text-MetaText-<version>.tar.gz

    For the latest information on MetaText or to download the latest
    pre-release/beta version of the module, consult the definitive
    reference, the MetaText Home Page:

        http://www.*-*-*.com/ ~abw/perl/metatext/

    MetaText is distributed as a single gzipped tar archive file:

        Text-MetaText-<version>.tar.gz

    Note that "<version>" represents the current MetaText Revision
    number, of the form "0.14". See the REVISION manpage below to
    determine the current version number for Text::MetaText.

    Unpack the archive to create a MetaText installation directory:

        gunzip Text-MetaText-<version>.tar.gz
        tar xvf Text-MetaText-<version>.tar

    'cd' into that directory, make, test and install the MetaText
    module:

        cd Text-MetaText-<version>
        perl Makefile.PL
        make
        make test
        make install

    The 't' sub-directory contains a number of small sample files
    which are processed by the test script (called by 'make test').
    See the README file in that directory for more information. A
    logfile (test.log) is generated to report any errors that occur
    during this process. Please note that the test suite is
    incomplete and very much in an 'alpha' state. Any further
    contributions here are welcome.

    The 'make install' will install the module on your system. You
    may need root access to perform this task. If you install the
    module in a local directory (for example, by executing "perl
    Makefile.PL LIB=~/lib" in the above - see `perldoc MakeMaker'
    for full details), you will need to ensure that the PERL5LIB
    environment variable is set to include the location, or add a
    line to your scripts explicitly naming the library location:

        use lib '/local/path/to/lib';

    The metapage utility is a script designed to automate MetaText
    processing of files. It can traverse directory trees, identify
    modified files (by comparing the time stamp of the equivalent
    file in both "source" and "destination" directories), process
    them and direct the resulting output to the appropriate file
    location in the destination tree. One can think of metapage as
    the MetaText equivalent of the Unix make(1S) utility.

    The installation process detailed above should install metapage
    in your system's perl 'installbin' directory (try `perl '-
    V:installbin'' to check this location). See the metapage
    documentation (`perldoc metapage') for more information on
    configuring and using metapage.

USING THE METATEXT MODULE
    To import and use the MetaText module the following line should
    appear in your Perl script:

        use Text::MetaText;

    MetaText is implemented using object-oriented methods. A new
    MetaText object is created and initialised using the
    Text::MetaText->new() method. This returns a reference to a new
    MetaText object.

        my $mt = Text::MetaText->new;

    A number of configuration options can be specified when creating
    a MetaText object. A reference to a hash array of options and
    their associated values should be passed as a parameter to the
    new() method.

        $my $mt = Text::MetaText->new( { 'opt1' => 'val1', 'opt2' => 'val2' } );

    The configurations options available are described in full
    below. All keywords are treated case-insensitively (i.e. "LIB",
    "lib" and "Lib" are all considered equal).

    LIB The INCLUDE directive causes the external file specified
        ("INCLUDE <file>") to be imported into the current document.
        The LIB option specifies one or more directories in which
        the file can be found. Multiple directories should be
        separated by a colon or comma. The current directory is also
        searched by default.

            my $mt = Text::MetaText->new( { LIB => "/tmp:/usr/metatext/lib" } );

    CASE
        The default behaviour for MetaText is to treat variable
        names and identifiers case insensitively. Thus, the
        following are treated identically:

            %% INCLUDE foo %%
            %% INCLUDE FOO %%

        Setting the CASE option to any non-zero value causes the
        document to be processed case sensitively.

            my $mt = Text::MetaText->new( { CASE => 1 } ); # case sensitive

        Note that the configuration options described in this
        section are always treated case insensitively regardless of
        the CASE setting.

    MAGIC
        MetaText directives are identifed in the document being
        processed as text blocks surrounded by special "magic"
        identifers. The default identifiers are a double percent
        string, "%%", for both opening and closing identifiers.
        Thus, a typical directive looks like:

            %% INCLUDE some/file %%

        and may be embedded within other text:

            normal text, blah, blah %% INCLUDE some/file %% more normal text

        The MAGIC option allows new identifiers to be defined. A
        single value assigned to MAGIC defines a token to be used
        for both opening and closing identifiers:

            my $mt = Text::MetaText->new( { MAGIC => '++' } );

            ++ INCLUDE file ++

        A reference to an array providing two values (elements 0 and
        1) indicates separate tokens to be used for opening and
        closing identifiers:

            my $mt = Text::MetaText->new( { MAGIC => [ '<!--', '-->' ] } );

            <!-- INCLUDE file -->

    CHOMP
        When MetaText processes a file it identifies directives and
        replaces them with the result of whatever magical process
        the directive represents (e.g. file contents for an INCLUDE,
        variable value for a SUBST, etc). Anything outside the
        directive, including newline characters, are left intact.
        Where a directive is defined that has no corresponding
        output (DEFINE, for example, which silently sets a variable
        value), the trailing newline characters can leave large
        tracts of blank lines in the output documents.

        For example:

          line 1
          %% DEFINE f="foo" %%
          %% DEFINE b="bar" %%
          line 2

        Produces the following output:

          line 1

          line 2

        This happens because the newline characters at the end of
        the second and third lines are left intact in the output
        text.

        Setting CHOMP to any true value will remove any newline
        characters that appear immediately after a MetaText
        directive. Any characters coming between the directive and
        the newline, including whitespace, will override this
        behaviour and cause the intervening characters and newline
        to be output intact.

        With CHOMP set, the following example demonstrates the
        behaviour:

          line 1
          %% DEFINE f="foo" %%
          %% DEFINE b="bar" %%<space>
          line 2

        Produces the following output (Note that "<space>" is
        intended to represent a single space character, not the
        string "<space>" itself, although the effect would be
        identical):

          line 1
          <space>
          line 2

    FILTER
        There may be times when you may want to INCLUDE a file or
        element in a document but want to filter the contents in
        some way. You may wish to escape (i.e. prefix with a
        backslash '\') certain characters such as quotes, search for
        certain text and replace with an alternative phrase, or
        perform some other post-processing task. The FILTER option
        allows you to define one or more code blocks that can be
        called as filter functions from an INCLUDE directive. Each
        code block is given a unique name to identify it and may
        have calling parameters (parenthesised and separated by
        commas) that can be specified as part of the directive. e.g.

            %% INCLUDE foo filter="slurp(prm1, prm2, ...)" %%

        Two default filters are pre-defined: escape() and sr().
        escape() takes as a parameter a perl-like regular expression
        pattern that indicates characters that should be 'escaped'
        (i.e. prefixed by a backslash '\') in the text. For example,
        to escape any of the character class `["'\]' you would
        specify the filter as:

            %% INCLUDE foo filter="escape([\"'\\])" %%

        The second filter, sr(), takes two arguments, a search
        string and a replace string. A simple substitution is made
        on the included text. e.g.

            %% INCLUDE foo filter="sr(spam, \"processed meat\")" %%

        Note that quotes and other special metacharacters should be
        escaped within the filter string as shown in the two
        examples above.

        Additional filters can be specified by passing a reference
        to a hash array that contains the name of the filter and the
        code itself in each key/value pair. Your filter function
        should be designed to accept the name of the function as the
        first parameter, followed by a line of text to be processed.
        Any additional parameters specified in the INCLUDE directive
        follow. The filter function is called for each line of an
        INCLUDE block and should return the modified text.

        Example:

            my $mt = Text::MetaText->new( {
                FILTER => {
                    'xyzzy' => sub {

                         $text = # do something here...
                         $text;  # return modified text
                    }
                }
            } );

            %% INCLUDE file1 filter="xyzzy(...)" %%

        A new FILTER definition will replace any existing filter
        with the same name.

    EXECUTE
        The SUBST directive performs a simple substitution for the
        value of the named variable. In the example shown below, the
        entire directive, including the surrounding 'magic' tokens
        '%%', is replaced with the value of the variable 'foo':

            %% SUBST foo %%  (or more succinctly, %% foo %%)

        If the named variable has not been defined, MetaText can
        interpret the variable as the name of an object method in
        the current class or as a function in the main package.

        If the EXECUTE flag is set to any true value, the MetaText
        processor will interpret the variable as an object method
        and attempt to apply it to its own object instance (i.e.
        $self->$method(...)). If the method is not defined, the
        processor fails quietly (but see ROGUE below to see what can
        happen next). This allows classes to be derived from
        MetaText that implement methods that can be called (when
        EXECUTE == 1) as follows:

            %% method1 ... %%       # calls $self->method1(...);
            %% method2 ... %%       # calls $self->method2(...);

        The text returned from the method is used as a replacement
        value for the directive.

        The following pseudo-code example demonstrates this:

            package MyMetaText;

            sub foo { "This is method 'foo'" }  # simple return string
            sub bar { "This is method 'bar'" }  # "        "         "

            package main;

            my $mt = MyMetaText->new( { EXECUTE => 1 } );
            print $mt->process("myfile");

        which, for the file 'myfile':

            %% foo %%
            %% bar %%

        generates the following output:

            This is method 'foo'
            This is method 'bar'

        If the EXECUTE flag is set to a value > 1 and the variable
        name does not correspond to a class method, the processor
        tries to interpret the variable as a function in the main
        package. Like the example above, the processor fails
        silently if the function is not defined (but see ROGUE
        below).

        The following pseudo-code extract demonstrates this:

            my $mt = Text::MetaText->new( { EXECUTE => 2 } );
            print $mt->processs("myfile");

            sub foo { "This is function 'foo'" }  # simple return string
            sub bar { "This is fucntion 'bar'" }  # "        "         "

        which, for the file 'myfile':

            %% foo %%
            %% bar %%

        generates the following output:

            This is function 'foo'
            This is function 'bar'

        Any additional parameters specified in the directive are
        passed to the class method or function as a hash array
        reference. The original parameter string is also passed.
        Note that the first parameter passed to class methods is the
        MetaText (or derivative) object reference itself.

        Example:

            %% foo name="Seuss" title="Dr" %%

        causes the equivalent of (when EXECUTE is any true value):

            $self->foo(                                  # implicit $self ref
                { 'name' => 'Seuss', 'title' => 'Dr' },  # hash ref of params
                  'name="Seuss" title="Dr"' );           # parameter string

        and/or (when EXECUTE > 1):

            &main::foo(
                { 'name' => 'Seuss', 'title' => 'Dr' },  # hash ref of params
                  'name="Seuss" title="Dr"' );           # parameter string

    ROGUE
        This configuration item determines how MetaText behaves when
        it encounters a directive it does not recognise. The ROGUE
        option may contain one or more of the ROGUE keywords
        separated by any non-word character. The keywords and their
        associated meanings are:

            warn    Issue a warning (via the ERROR function, if
                    specified) when the directive is encountered.

            delete  Delete any unrecognised directives.

        The default behaviour is to silently leave any unrecognised
        directive in the processed text.

        Example:

            my $mt = Text::MetaText->new( { ROGUE => "delete,warn" } );

    DELIMITER
        The DELIMITER item specifies the character or character
        sequence that is used to delimit lists of data. This is
        used, for example, by the "in" operator which can be used in
        evaluation conditions. e.g.

            %% INCLUDE hardenuf if="uid in abw,wrigley" %%

        In this case, the condition evaluates true if the uid
        variable contains the value "abw" or "wrigley". The default
        delimiter character is a comma.

        The example:

            my $mt = Text::MetaText->new( { DELIMITER => ":" } );

        would thus correctly process:

            %% INCLUDE hardenuf if="uid in abw:wrigley" %%

    ERROR
        The ERROR configuration item allows an alternative error
        reporting function to be specified for error handling. The
        function should expect a printf() like calling convention.

        Example:

            my $mt = Text::MetaText->new( {
                ERROR => sub {


                }
            } );

    DEBUG
        The DEBUG item allows an alternative debug function to be
        provided. The function should expect a printf() like calling
        convention, as per the ERROR option described above. The
        default DEBUG function sends debug messages to STDERR,
        prefixed by a debug string: 'D> '.

    DEBUGLEVEL
        The DEBUGLEVEL item specifies which, if any, of the debug
        messages are displayed during the operation of the MetaText
        object. Like the ROGUE option described above, the
        DEBUGLEVEL value should be constructed from one or more of
        the following keywords:

            none      no debugging information (default)
            info      general processing information
            config    MetaText object configuration items
            preproc   pre-processing phase
            process   processing phase
            postproc  post-processing phase
            data      additional data parameters in debug messages
            content   content of pre-processed INCLUDE blocks
            function  list functions calls as executed
            evaluate  trace conditional evaluations
            test      used for any temporary test code
            all       all of the above (excluding "none", obviously)

        Example:

            my $mt = Text::MetaText->new( {
                DEBUGLEVEL => "preproc,process,data"
            } );

    MAXDEPTH
        It is possible for MetaText to become stuck in an endless
        loop if a circular dependancy exists between one or more
        files. For example:

            foo:
                %% INCLUDE bar %%

            bar:
                %% INCLUDE foo %%

        To detect and avoid such conditions, MetaText allows files
        to be nested up to MAXDEPTH times. By default, this value is
        32. If you are processing a file which has nested INCLUDE
        directives to a depth greater than 32 and MetaText returns
        with a "Maximum recursion exceeded" warning, set this
        confiuration item to a higher value. e.g.

            my $mt = Text::MetaText->new( { MAXDEPTH => 42 } );

PROCESSING TEXT
    The MetaText process() method is called to process a file,
    interpreting any MetaText directives embedded within it. The
    first parameter should be the name of the file which should
    reside in the current working directory or in one of the
    directories specified in the LIB configuration option. A
    filename starting with a slash '/' is considered to be an
    absolute path. The optional second parameter may be a reference
    to a hash array containing a number of variable/value
    definitions that should be pre-defined when processing the file.

        print $mt->process("somefile", { name => "Fred" });

    If "somefile" contains:

        Hello %% name %%

    then the output generated would be:

        Hello Fred

    Pre-defining variables in this way is equivalent to using the
    DEFINE directive (described below) at the start of the INCLUDE
    file

        %% DEFINE name="Fred" %%
        Hello %% name %%

    The process() function will continue until it reaches the end of
    the file or a line containing the pattern "__END__" by itself
    ("END" enclosed by double underscores, no other characters or
    whitespace on the line). Note that the pre-processor (a private
    method which is called by process(), so feel free to forget all
    about it) *does* scan past any __END__ marker. In practice, that
    means you can define blocks *after*, but use them *before*, the
    __END__ marker. e.g.

        Martin, %% INCLUDE taunt %%

        __END__                 << processor stops here and ignores
                                   everything following
        %% BLOCK taunt %%       << but the pre-processor has correctly
        you Camper!                continued and parsed this block so that
        %% ENDBLOCK %%             it can be included in the main body

    produces the output:

        Martin, you Camper!

    The process() function returns a string containing the processed
    file or block output.

        my $output = $mt->process("myfile");
        print $output;

METATEXT DIRECTIVES
    A MetaText directive is a block of text in a file that is
    enclosed by the MAGIC identifiers (by default '%%'). A directive
    may span multiple lines and may include blank lines within in.
    Whitespace within a directive is generally ignored except where
    quoted as part of a specific value.

        %% DEFINE
           name    = Yorick
           age     = 30
           comment = "A fellow of infinite jest"
        %%

    The first word of the directive indicates the directive type.
    Directives may be specified in upper, lower or mixed case,
    irrespective of the CASE sensitivity flag (which affects only
    variable names). The general convention is to specify the
    directive type in UPPER CASE to aid clarity.

    The MetaText directives are:

    DEFINE
        Define the values for one or more variables

    SUBST
        Substitute the value of a named variable

    INCLUDE
        Process and include the contents of the named file or block

    BLOCK
        Define a named block which can be subsequently INCLUDE'd

    ENDBLOCK
        Marks the end of a BLOCK definition

    To improve clarity and reduce excessive, unnecessary and
    altogether undesirable verbosity, a directive block that doesn't
    start with a recognised MetaText directive is assumed to be a
    'SUBST' variable substitution. Thus,

        %% SUBST foo %%

    can be written more succinctly as

        %% foo %%

    When MetaText processes directives, it is effectively performing
    a "search and replace". The MetaText directive block is replaced
    with whatever text is appropriate for the directive specified.
    Generally speaking, MetaText does not alter any text content or
    formatting outside of directive blocks. The only exception to
    this rule is when CHOMP is turned on (see the section on "USING
    THE METATEXT MODULE") and newlines immediately following a
    directive are subsequently deleted.

  DEFINE

    The DEFINE directive allows simple variables to be assigned
    values. Multiple variables may be defined in a single DEFINE
    directive.

        %% DEFINE
           name  = Caliban
           quote = "that, when I waked, I cried to dream again."
        %%

    Variables defined within a file or passed to the process()
    function as a hash array remain defined until the file or block
    is processed in entirety. Variable values will be inherited by
    any nested files or blocks INCLUDE'd into the file. Re-
    definitions of existing variables will persist within the file
    or block, masking any existing values, until the end of the file
    or block when the previous values will be restored.

    The following example illustrates this:

        foo:
            Hello %% name %%              # name assumes any predefined value
            %% DEFINE name=tom %%
            Hello %% name %%              # name = 'tom'
            %% INCLUDE bar name='dick' %% # name = 'dick' for "INCLUDE bar"
            Hello %% name %%              # name = 'tom'

        bar:
            Hello %% name %%              # name = 'dick'
            %% DEFINE name='harry' %%     # name = 'harry'
            Hello %% name %%

    Processing the file 'foo' as follows:

        print $mt->process('foo', { 'name' => 'nobody' });

    produces the following output (with explanatory comments added
    for clarity):

        Hello nobody                      # value from process() hash
        Hello tom                         # from foo
        Hello{*filter*}                        # from bar
        Hello harry                       # re-defined in bar
        Hello tom                         # restored to previous value in foo

  SUBST

    A SUBST directive performs a simple variable substitution. If
    the variable is defined, its value will be inserted in place of
    the directive.

    Example:

        %% DEFINE name=Jake %%
        Hello %% SUBST name %%  

    generates the following output:

        Hello Jake

    The SUBST keyword can be omitted for brevity. Thus "%% name %%"
    is processed identically to "%% SUBST name %%".

    If the variable is undefined, the MetaText processor will,
    according to the value of the EXECUTE configuration value, try
    to execute a class method or a function in the main package with
    the same name as the SUBST variable. If EXECUTE is set to any
    true value, the processor will try to make a corresponding
    method call for the current object (that is, the current
    instantiation of the MetaText or derived class). If no such
    method exists and EXECUTE is set to any value greater than 1,
    the processor will then try to execute a function in the main
    package with the same name as the SUBST variable In either case,
    the text returned from the method or function is included into
    the current block in place of the SUBST directive (non-text
    values are automatically coerced to text strings). If neither a
    variable, method or function exists, the SUBST directive will
    either be deleted or left intact (and additionally, a warning
    may be issued), depending on the value of the ROGUE
    configuration item.

    See EXTENDING METATEXT below for more information on deriving
    MetaText classes and using EXECUTE to extend the meta-language.

    The "format" and "filter" options as described in the INCLUDE
    section below are applied to the processed SUBST result before
    being inserted back into the document.

    Some MetaText variables have a special meaning. Unless
    specifically defined otherwise, the variable(s) listed below
    generate the following output:

        TIME    The current system time in seconds since the epoch,
                00:00:00 Jan 1 1970.  Use the "format" option to
                specify a time/date format.

  INCLUDE

    The INCLUDE directive instructs MetaText to load and process the
    contents of the file or block specified. If the target is a
    file, it should reside in the current directory or a directory
    specified in the LIB configuration variable. Alternatively, the
    target may be a text block specified with BLOCK..ENDBLOCK
    directives (see below).

        %% INCLUDE chapter1 %%

    The target may also be a variable name and should be prefixed
    with a '$' to identify it as such. On evaluation, the value of
    the named variable will be used as the target:

    Example:

        %% DEFINE chapter=ch1 %%
        %% INCLUDE $chapter   %%  

    is equivalent to:

        %% INCLUDE ch1 %%

    Additional variables may be defined for substitution within the
    file:

        %% INCLUDE chapter2 bgcolor=#ffffff title="Chapter 2" %%

    The contents of the file "chapter2":

        <html><head><title>%%title%%</title></head>
        <body bgcolor="%% bgcolor %">
          ...
        </body>

    would produce the output:

        <head><title>Chapter 2</title></head>
        <body bgcolor="#ffffff">
          ...
        </body>

    Defining variables in this way is equivalent to using the DEFINE
    directive. Variables remain in scope for the lifetime of the
    file being processed and then revert to any previously defined
    values (or undefined). Any additional files processed via
    further INCLUDE directives within the file will also inherit any
    defined variable values.

    Example:

          %% INCLUDE file1 name="World" %%

    for the files:

        file1:                   # name => "World" from INCLUDE directive
            %% INCLUDE file2 %%

        file2:                   # inherits "name" variable from file1
            %% INCLUDE file3 %%    

        file3:                   # inherits "name" variable from file2
            Hello %% name %%

    produces the output:

        Hello World

    The output generated by INCLUDE and SUBST directives can be
    formatted using a printf-like template. The format string should
    be specified as a "format" option in the INCLUDE or SUBST
    directive. Each line of the included text is formatted and
    concatentated to create the final output. Within the format
    string, '%s' is used to represent the text.

    For example, the 'author' element below could be used to display
    details of the author of the current document.

        author:
            File:   %% file %%
            Author: %% name %%
            Date:   %% date %%

    For inclusion in an HTML document, the text can be encapsulated
    in HTML comment tags ("<!--" and "-->") using a format string:

        %% INCLUDE author
           file   = index.html
           name   = "Andy Wardley"
           date   = 19-Mar-1987
           format = "<!-- %-12s -->"
        %%

    Which produces the following output:

        <!-- File:   index.html   -->
        <!-- Author: Andy Wardley -->
        <!-- Date:   19-Mar-1987  -->

    Note that the print format is applied to each line of the
    included text. To encapsulate the element as a whole, simply
    apply the formatting outside of the INCLUDE directive:

        <!--
           %% INCLUDE author
           ...
           %%
        -->

    In these examples, the formatting is applied as if the
    replacement value/line is a character string. Any of the
    standard printf(3) format tokens can be used to coerce the value
    into a specific type.

    As mentioned in the SUBST section above, the TIME variable is
    used to represent the current system time in seconds since the
    epoch (see time(2)). The "format" option can also be employed to
    represent such values in a more user-friendly format. Any format
    string that does not contain a '%s' token is assumed to be a
    time-based value and is formatted using the time2str() function
    from the Date::Format module (distributed as part of the
    TimeDate package).

    Example:

        The date is %% TIME format="%d-%b-%y" %%

    Generates:

        The date is 19-Mar-98

    See `perldoc Date::Format' for information on the formatting
    characters available.

    The pragmatic token '%P' can be added to a format to override
    this behaviour and force the use of printf(). The '%P' token is
    otherwise ignored.

    Example:

        %% DEFINE foo=123456789  %%
        %% foo format="%d-%b-%y" %%  # "day-month-year" using time2str
        %% foo format="%d"       %%  # "day" using timestr
        %% foo format="%P%d"     %%  # decimal value using printf
        %% foo format="%s"       %%  # string value using printf

    Generates:

        29-Nov-73
        29
        123456789
        123456789

    Text that is inserted with an INCLUDE or SUBST directive can
    also be filtered. There are two default filters provided,
    'escape' which can be used to escape (prefix with a backslash
    '\') certain characters, and 'sr' which is used to perform
    simple search and replace actions. Other filters may be added
    with the FILTER option when creating the object (see the FILTER
    section in the section on "USING THE METATEXT MODULE", above).

    Like the 'format' option, output filters work on a line of text
    at a time. Any parameters required for the filter can be
    specified in parentheses after the filter name. The 'escape'
    filter expects a perl-style character class indicating the
    characters to escape. The 'sr' filter expects two parameters, a
    search pattern and a replacement string, separated by a comma.
    Note that parameters that include embedded spaces should be
    quoted. The quote characters themselves must also be escaped as
    they already form part of a quoted string (the filter text).
    (This way of representing parameters is admittedly far from
    ideal and may be improved in a future version.)

    Example:

        %% DEFINE text="Madam I'm Adam" %%
        %% SUBST  text filter="escape(['])"               %%
        %% SUBST  text filter="sr(Adam, \"Frank Bough\")" %%

    Generates:

       {*filter*}I\'m Adam
       {*filter*}I'm Frank Bough

    Conditional tests can be applied to INCLUDE blocks to determine
    if the block should evaluated or ignored. Variables and absolute
    values can be used and can be evaluated in the following ways:

        a == b       # a is equal to b
        a != b       # a is not equal to b
        a >  b       # a is greater than b
        a <  b       # a is less than b
        a => b       # a is greater than or equal to b
        a <= b       # a is less than or equal to b
        a =~ b       # a matches the perl regex pattern b
        a !~ b       # a does not match the perl regex pattern b
        a in b,c,d   # a appears in the list b, c, d (see DELIMITER)

    The items on the right of the evaluations can be absolute values
    or variable names which should be prefixed by a '$'. The items
    on the left of the evaluation are assumed to be variable names.
    There is no need to prefix these with a '$', but you can if you
    choose.

    The single equality, "a = b", is treated identically to a double
    equality "a == b" although the two traditionally represent
    different things (the first, an assignment, the second, a
    comparison). In this context, I consider the former usage
    confusing and would recommend use of the latter at all times.

    Variables without any comparison operator or operand are tested
    for a true/false value.

    Examples:

        %% INCLUDE foo if="name==fred"        %%
        %% INCLUDE foo if="$name==fred"       %%  # equivalent to above
        %% INCLUDE foo if="name==$goodguy"    %%
        %% INCLUDE foo if="hour > 10"         %%
        %% INCLUDE foo if="tonk =~ [Ss]pl?at" %%
        %% INCLUDE foo if="camper"            %%

    Multiple conditions can be joined using the following boolean
    operators

        a && b       # condition 'a' and 'b'
        a || b       # condition 'a' or  'b'
        a ^  b       # condition 'a' xor 'b'
        a and b      # same as "a && b" but with lower precedence
        a or  b      # same as "a || b" but with lower precedence
        a xor b      # same as "a ^  b" but with lower precedence

    Conditional equations are evaluated left to right and may
    include parentheses to explicitly set precedence.

    Examples:

        %% INCLUDE tonk    
           if="hardenuf && uid in abw,wrigley"          
        %%
        %% INCLUDE tapestry
           if="(girly && studly < 1) || uid == neilb"    
        %%
        %% INCLUDE tapestry
           if="($girly && $studly < 1) || $uid == neilb"
        %%

    Note that the third example above is identical in meaning to the
    second, but explicitly prefixes variable names with '$'. This is
    optional for elements on the left hand side of comparison
    operators, but mandatory for those on the right that might
    otherwise be interpreted as absolute values.

  BLOCK..ENDBLOCK

    In some cases it is desirable to have a block of text available
    to be inserted via INCLUDE without having to define it in an
    external file. The BLOCK..ENDBLOCK directives allow this.

    A BLOCK directive with a unique identifier marks the start of a
    block definition. The block continues, including any valid
    MetaText directives, until an ENDBLOCK directive is found.

    A BLOCK..ENDBLOCK definition may appear anywhere in the file. It
    is in fact possible to INCLUDE the block before it has been
    defined as long as the block definition resides in the same
    file.

    Processing of a file stops when it encounters the __END__ marker
    on a line by itself. Blocks can be defined after this marker
    even though the contents of the file after __END__ are ignored
    by the processor.

        # include a block defined later
        %% INCLUDE greeting name=Prospero %%

        __END__
        %% BLOCK greeting %%
        Hello %% name %%
        %% ENDBLOCK %%

    This produces the following output:

        # include a block defined later
        Hello Prospero

    Additional variable definitions specified in an INCLUDE
    directive will be applied to blocks just as they would to
    external files.

    A BLOCK..ENDBLOCK definition that appears in the main part of a
    document (i.e. before, or in the absence of an __END__ line)
    will not appear in the processed output. A simple "print" flag
    added to the BLOCK directive overrides this behaviour, causing a
    copy of the BLOCK to appear in it's place:

        %% DEFINE name=Caliban %%

        %% BLOCK greeting print %%
        Hello %% name %%
        %% ENDBLOCK %%

        %% INCLUDE greeting name="Prospero" %%

    produces the following output:

        Hello Caliban

        Hello Prospero

    Conditions ("if" and "unless") can be applied to BLOCK
    directives, but they affect how and when the BLOCK itself is
    printed, rather than determining if the block gets defined or
    not. Conditionals have no effect on BLOCK directives that do not
    include a "print" flag.

EXTENDING METATEXT
    MetaText may be used as a base class for deriving other text
    processing modules. Any member function of a derived class can
    be called directly as a MetaText directive. See the EXECUTE
    configuration option for more details.

    Pseudo-code example:

        package MyMetaText;

        # define a new derived class method, get_name()
        sub get_name {
            my $self   = shift;
            my $params = shift;

            # return name from an ID hash, for example
            $self->{ PEOPLE }->{ $params->{'id'} } || 'nobody';
        }

        package main;

        # use the new derived class
        my $mmt = MyMetaText { EXECUTE => 1 };

        # process 'myfile'
        print $mmt->process('myfile');

    which, for a sample file, 'myfile':

        %% get_name id=foo %%
        %% get_name id=bar %%

    is equivalent to:

        print $mmt->get_name({ 'id' => 'foo' }), "\n";
        print $mmt->get_name({ 'id' => 'bar' }), "\n";

    Alternatively, a simple calling script can be written that
    defines functions that themselves can be called from within a
    document:

        my $mt = Text::MetaText->new( { EXECUTE => 2 } );

        print $mt->process("myfile");

        sub get_name {
            my $params = shift;
            $global_people->{ $params->{'id'} } || 'nobody';
        }

    Please note that the functionality provided by the EXECUTE
    option, and inherently, the extensibility possible by deriving
    MetaText sub-classes, relies in part on the operation of the
    AUTOLOAD method. Authors of derived MetaText classes should be
    aware of, and account for this, if re-defining the AUTOLOAD
    method.

WARNINGS AND ERRORS
    The following list indicates warning or error messages that
    MetaText can generate and their associated meanings.

    "Closing directive tag missing in %s"
        A MetaText directive was found that was not terminated
        before the end of the file. e.g. `%% INCLUDE something ...'
        The processor attempts to compensate, but check your source
        files and add any missing MAGIC tokens.

    "Invalid configuration parameter: %s"
        An invalid configuration parameter was identified in the
        hash array passed to Text::MetaText->new(). See the section
        on "USING THE METATEXT MODULE".

    "Invalid debug/error function"
        The debug or error handling routine specified for the ERROR
        or DEBUG configuration options was not a code reference. See
        the ERROR and/or DEBUG sections for more details.

    "Invalid debug option: %s"
        A token was specified for the DEBUGLEVEL configuration item
        which was invalid. See the DEBUGLEVEL section for a complete
        list of valid tokens.

    "Invalid roque option: %s"
        A token was specified for the ROGUE configuration item which
        was invalid. See the ROGUE section for a complete list of
        valid tokens.

    "Maximum recursion exceeded"
        The processed file had multiple INCLUDE directives that
        nested to a depth greater than MAXDEPTH (default: 32). Set
        MAXDEPTH higher to avoid this problem, or check your files
        for circular dependencies.

    "Missing directive keyword"
        A MetaText directive was identified that had no keyword or
        other content. e.g. `%% %%'

    "Text::MetaText->new expects a hash array reference"
        The new() method can accept a reference to a hash array as
        the first parameter which contains configuration variables
        and values. This error is generated if the parameter is not
        a hash array reference.

    "Unrecognise directive: %s"
        An internal error that should never happen. The pre-
        processor has identified a directive type that the processor
        then failed to recognise.

    "Unrecognised token: %s"
        A `%% SUBST <variable> %%' or `%% <variable> %%' directive
        was found for which there was no corresponding <variable>
        defined. This warning is only generated when the 'warn'
        token is set for the ROGUE option.

    "Unmatched parenthesis: %s"
        A conditional evaluation ("if" or "unless") for a directive
        is missing a closing parenthesis. e.g. `%% INCLUDE foobar
        if="(foo && bar || baz" %%'

    "%s: non-existant or invalid filter"
        An INCLUDE or SUBST directive included a "filter" option
        that refers to a non-existant filter. e.g. `%% INCLUDE foo
        filter=nosuchfilter() %%'

AUTHOR

    See also:

        http://www.*-*-*.com/ ~abw/
        http://www.*-*-*.com/ ~abw/perl/metatext/

    My thanks extend to the people who have used and tested
    MetaText. In particular, the members of the Peritas Online team;
    Simon Matthews, Simon Millns and Gareth Scott; who brutally
    tested the software over a period of many months and provided
    valuable feedback, ideas and of course, bug reports. I am also
    indebted to the members of the SAS Team at Canon Research Centre
    Europe Ltd; Tim O'Donoghue, Neil Bowers, Ave Wrigley, Martin
    Portman, Channing Walton and Gareth Rees; although I'm not yet
    sure why. :-)

    I welcome bug reports, enhancement suggestions, comments,
    criticisms (hopefully constructive) and patches related to
    MetaText. I would appreciate hearing from you if you find
    MetaText particularly useful or indeed if it *doesn't* do what
    you want, for whatever reason. Hopefully this will help me make
    MetaText help you more.

    It pains me to say that MetaText comes without guarantee or
    warranty of suitability for any purpose whatsoever. That doesn't
    mean it doesn't do anything good, but just that I don't want
    some scrupulous old git to sue me because they thought I implied
    it did something it doesn't. *<sigh>*

REVISION
    $Revision: 0.15 $

COPYRIGHT
    Copyright (c) 1996-1998 Andy Wardley. All Rights Reserved.

    This program is free software; you can redistribute it and/or
    modify it under the same terms as Perl itself.

SEE ALSO
    The metapage utility, the Date::Format module.

--

Signature lost in transit.  We apologise for any inconvenience caused.



Mon, 24 Jul 2000 03:00:00 GMT  
 
 [ 1 post ] 

 Relevant Pages 

1. ANNOUNCE: Text::MetaText v0.15

2. ANNOUNCE: Text::MetaText version 0.19 released.

3. ANNOUNCE: Text::MetaText version 0.19 released.

4. ANNOUNCE: nsapi_perl/Netscape::Server v0.15

5. ANNOUNCE: List::Compare v0.15

6. ANNOUNCE: IO-1.15 Release -- Perl IO classes

7. ANNOUNCE - Tie::RangeHash v0.60 released

8. ANNOUNCE: Tie::RangeHash v0.42 released

9. ANNOUNCE: Tie::RangeHash v0.40 released

10. ANNOUNCE: Chart::XMGR v0.95 released

11. ANNOUNCE: Tk::Multi v0.1 beta release

12. ANNOUNCE: Algorithm::Diff v1.15 uploaded to CPAN

 

 
Powered by phpBB® Forum Software