#========================================================================
#
# Changes 
#
# DESCRIPTION
#   Revision history for Template Toolkit.
#
# AUTHOR
#   Andy Wardley   <abw@cre.canon.co.uk>
#
#------------------------------------------------------------------------
# $Id: Changes,v 1.61 1999/11/05 10:29:22 abw Exp $
#========================================================================

#------------------------------------------------------------------------
# Version 0.28  1999/11/05 10:29:05
#------------------------------------------------------------------------

* OK, so I lied about 0.27 being the final beta release. :-)=
  The main reason is that the internal FILTER interface has been
  improved at the cost of (possibly) breaking existing filter code.
  This isn't as bad as it sounds because the filter code probably
  wasn't working properly anyway, due to the interface not being up to
  scratch.  Anyway, it's a change worthy of another beta release,
  IMHO, to allow the changes to be tested and any wrinkles ironed out.
  Interfaces should remain stable from now on so you can consider this
  version a release candidate.

* Changed the behaviour of the AND (&&) and OR (||) operators to act as 
  "short-circuit" operators as in Perl.  If the left hand side of an OR 
  evaluates true, then the right hand side will not be evaluated.  Likewise
  for an AND which will bypass evaluation of the RHS if the LHS evaluates
  false.  I thought this was going to be tricky to implement but Simon
  Matthews sat me down in the pub with a few pints of beer and a laptop 
  and it all came together quite well.  Inspirational hacking, indeed!
  Updated t/binop.t to test this behaviour.

* Added ABSOLUTE_PATHS option which allows template files to be specified 
  using absolute paths (e.g. '/foo/bar/baz.html').  Enabled by default.
  Thanks to all those who badgered me about this until I got a clue. :-)=
  Added t/abspath.t and updated documentation.  Changed the parser grammar
  to accept '/' as the first character of an unquoted INCLUDE file, e.g.
  [% INCLUDE /slash/bang/wallop %]

* Added 'perl5lib' option to ttree to allow additional Perl library 
  directories to be specified.  These are simply unshifted onto @INC.

* Changed Template::Context::_evaluate() test on ARRAY objects so that
  the generic size, max, etc., and numerical indexing operations work 
  on blessed arrays.

* Added register_filter($name, $factory) method to context to allow
  plugin modules (or whatever) to register filters for subsequent use.
  Moved the filters defined in Template::Plugin::Filter into a new
  module, Template::Filters, which defines all the "system" filters.
  This is loaded the first time a FILTER directive is encountered and
  registers all filters for subsequent use.

* Changed behaviour of Context use_filter() method so that it no longer
  passes the name of the filter to the factory method.

* Added new filters 'redirect' and 'into'.  The first redirects a block 
  into a separate file, as specified by a filename.  The file will be 
  written relative to the OUTPUT_PATH.  This can be used to generate 
  mucho pages from a list of records (see following example).  

    List of User:
    <ul>
      [% FOREACH user = myorg.userlist %]
         [% INCLUDE user_page FILTER redirect("users/${user.id}.html") %]
         <li><a href="users/${user.id}.html">[% user.name %]</a>
      [%
    </ul>

  The 'into' filter saves the output into a named variable.
 
    [% INCLUDE myfile FILTER into('myvar') %]

    [% FILTER into('description') %]
       Rhubarb, rhubard, blah, blah, cabbages.
    [% END %]

* Added a minor feature to add a 'filename' variable which stores the name 
  of the top-level template file.  This doesn't happen if a 'filename'
  variables is already defined or if the template was specified via a 
  reference (i.e. no filename available).

* Added new Template Plugin module 'Datafile'.

* Francois Desarmenien has released a new version of Parse::Yapp (0.32) 
  which includes the patch to specify an alternate grammar template file 
  (yapp -t <template>).  Removed parser/parse_yapp_patch and updated 
  parser/README. 

#------------------------------------------------------------------------
# Version 0.27  1999/10/01 16:51:46
#------------------------------------------------------------------------

* Fifth and most certainly, final, beta release.  The core toolkit is now 
  stable and there are only a few low-level interface issues left to 
  resolve (e.g. filters).  The 'ttree' utility is now fully functional
  and reliable.  
  
* Added numerical list indexing of the form 'list.n', e.g 'list.0', 'list.3'.
  Added t/listndx.t to test suite.  Examples of use:
    [% list = ['one' 'two' 'three' 'four' ] %]
    [% list.0 %] [% list.1 %] 
    [% list.${n} FOREACH n = [0..3] %] 

* Fixed a bug identified by Simon Matthews which was causing corruption 
  of the context runtime stack when an empty hash was created.  Added a 
  special case to detect empty hashes rather than blindly splicing n 
  (possibly 0) elements off the stack to construct a hash.  Added tests
  to t/hash.t.

* Fixed several bugs in ttree identified by Martin Portman; files of the 
  same name in different directories were treated as the same file and all
  received the same (cached) contents, target directories weren't always 
  being created, and a few other minor oddities were cleansed.  Also added
  -n option to do nothing.

* Modified grammar slightly to allow multiple FILTER directives to be 
  chained one after another, as suggested by Eugene Miretskiy e.g.
  [% INCLUDE foobar FILTER this FILTER that %]

#------------------------------------------------------------------------
# Version 0.26  1999/09/15 12:22:36
#------------------------------------------------------------------------

* Fourth (and hopefully final) public beta release.

* Finished writing bin/ttree.  It is now fully functional and (mostly)
  documented.  Added AppConfig (which ttree uses) as a Makefile.PL 
  pre-requisite

* Added '..' range operator for specification of simple loops:
  e.g. [% FOREACH i = [ 1..10 ] %]

* Changed parser grammar to call a factory function to generate directives.
  This can be specified as a package name or by reference to a prototype or
  factory object. 
  e.g. 
      my $t = Template->new({ FACTORY => 'MyOrg::Template::Directive' });
  or
      my $t = Template->new({ FACTORY => MyOrg::TDFactory->new() }); 

* Re-structured the intermediate code generated by the parser and wrote
  a new runtime evaluation loop in Context::_evaluate().  Re-wrote parts
  of the parser grammer accordingly.  This offers some new features, like
  named parameters described below; is simpler to understand, maintain and
  use; has smaller state and rule tables resulting in faster loading and 
  smaller footprint, generates less intermediate code resulting in faster 
  parsing and using slightly less memory.  The runtime FSM now uses a 
  double-ended queue.  Shifting/unshift opcodes and data to and from a list 
  is understandably slower than simply iterating through the list elements 
  as we previously did, but the added simplicitly seems to outweigh any 
  losses.  Rough benchmarks show it runs about 10% faster now.

* Added facility for named parameters.  These are automatically collated
  into a hash array which is then passed by reference as the last item
  in the parameter list.  e.g. foo(10, 20, name='fred', 30, age=30) is
  converted to foo(10, 20, 30, { name => 'fred', age => 30 }).  This applies
  to parameters passed to functions/methods like this example, USE and 
  FILTER parameters.

* Changed FOREACH to only localise the stash when it is expected to import
  hash members, i.e. no iterator variable is specified.  Thanks to Graham
  Barr for spotting the irregularity.

* Iterator methods first() and next() have been renamed get_first()
  and get_next(), respectively, and methods size(), max(), index(), 
  number(), first() and last() have been provided.  The FOREACH loop 
  defines a 'loop' variable which contains a reference to the iterator,
  allowing you to do things like the following.  Updated t/foriter.t.

  [% FOREACH thing = myapp.somelist %]
     [% INCLUDE thing_table_header IF loop.first %]
        #[% loop.number ]/[% loop.size %]: [% thing %]
     [% INCLUDE thing_table_footer IF loop.last %]
  [% END %]

* Added generic list methods size(), max() and sort() which can be appended
  to any list (or indeed, iterator) to return the number of elements, 
  maximum index (size - 1), or a sorted representation of the list.

  [% FOREACH name = myapp.list_of_names.sort %]
     [% name %]
  [% END %]

* Added generic keys() and values() methods for hash references.

* Added RECURSION option to allow recursion into template files.
  Added t/recurse.t to test it.

* Changed handling of output files to automatically create any 
  intermediate directories required for the destination.  This is
  implemented in Template::Utils::output_handler() by calling on
  File::Path's mkpath() function.

* Fixed bug where a PLUGIN_BASE specified as a string didn't get the 
  default Template::Plugin base added.  Thanks to Hans von Lengerke for
  the patch.

* Fixed a problem identified by Simon Matthews whereby files in local
  directories would not be processed if a file of the same name existed
  in an INCLUDE_PATH directory.  This isn't always what you want.  Added
  support for a './' prefix on a file (e.g. './header' instead of 'header')
  which causes the loader to look only in the current directory and not
  in the INCLUDE_PATH.  Caching is as per default CACHE option, with 
  leading './' left intact in the name.

#------------------------------------------------------------------------
# Version 0.25  1999/08/16 14:44:45
#------------------------------------------------------------------------

* Third public beta release.

* Added 'ttree' utility for process directory trees of template files,
  akin to the 'metapage' script in Text::MetaText.  Not yet documented 
  and missing a few features but very much working and useful.

* Added PRE_PROCESS and POST_PROCESS options to denote template files
  for processing before and after templates.  Changed organisation of
  Context module a little, adding explicit localise() and delocalise()
  methods. Added t/preproc.t.

* Change Template::process() method to accept optional third and fourth
  parameters, $output and $error, to denote output and/or error destinations
  for processing that template only.  The process() method calls the 
  context redirect() for output and/or error, processes the template file
  and then restores them to their previous values, effectively closing
  any files that may have been opened.  The destination may now also be
  a filename relative to OUTPUT_PATH which is constructed and passed 
  to output_handler() (see next item).  Added t/output.t.

* Modified Template::Utils:output_handler() to accept a string as a
  destination, treat it as a filename, open the file and return a glob,
  created by Symbol::gensym containing the file handle.

* Various minor documentation updates.

* Added t/accessor.t and made minor changes to t/texpectl.pl.

#------------------------------------------------------------------------
# Version 0.24  1999/08/12 22:04:26
#------------------------------------------------------------------------

* Second public beta release.

* Improved FILTERS configuration option which now allows filter 
  constructors (factories) to be defined.  These take responsibility
  for creating filter instances as they are required.

* Documented WHILE, PROCESS, IMPORT, TAGS, BREAK and FILTER
  directives.  Re-wrote the overview and summary sections, moved some
  bits around, generally improved various other parts of the docs.
  The Template.pod and README file are now constructed automatically 
  by the 'make dist' from source in doc/src, using bin/mkdoc.

* Removed operating-system dependant code which was detecting and
  storing path separators.  I realised that if everyone uses '/' as
  the path separator, then Perl will do the conversion automagically.  
  Much easier.  This also means that the OS, PATH_SEP and PATH_SPLIT 
  options are no longer required.  

* Deleted old and boring 'examples' directory.

* Deleted obsolete code from Template::Debug.pm

#------------------------------------------------------------------------
# Version 0.23  1999/08/10 12:12:07
#------------------------------------------------------------------------

* Interim (non-public) release.  This will become the next public 
  beta release once the documentation has been updated to reflect 
  the following changes.  For now, the best source of inspiration for 
  usage of new features can be found in the relevant test scripts.

* Added PROCESS directive which acts like INCLUDE but doesn't localise
  variables.  This allows configuration files, etc., to update non-local
  variables.  Added t/process.t to test suite.

* Added IMPORT directive to copy all members of a hash into the main 
  namespace.  Added t/import.t to test suite.

* Added WHILE directive to repeat a loop while an expression evaluates
  true.  The $Template::Directive::While::MAXITER variable defines an
  upper iteration limit and kills the loop with an error if it is exceeded.
  By default this value is set to 1000.  Added t/while.t to test suite.

* Added BREAK directive to prematurely exit FOREACH or WHILE loop.  Added 
  t/break.t to test suite and updated t/while.t and t/foreach.t.

* Added TAGS directive to allow per-file switching of the tokens that mark
  the start and end of directives.  Added t/tags.t to test suite

* Added FILTER directive to allow post-processing of output.  Filters
  are defined in the Template::Plugin::Filter module.  The Context 
  use_filter() method simply calls use_plugin(), requesting the 'filter'
  plugin module, providing he filter name and any additional parameters
  specified.  Thus "FILTER foo(bar)" is roughly equivalent to 
  "USE filter('foo', bar)".  Added t/filter.t to test suite.

* Changed Context to allow multiple PLUGIN_BASE packages to be defined.

* Added Template::OS module to autodetect operating system and return
  specific values such as path separator.  The Context creates an OS 
  object and stores it internally.

* Added OS option to Template.pm to specify operating system to override
  the autodetect.

* Changed old DIR_SEPARATOR option to PATH_SEP and old PATH_SEPARATOR to 
  PATH_SPLIT.  These are defaulted based on OS if not specified.

* Removed some old code which allowed an absolute filename to be specified
  and opened by the cache.  This isn't a bad thing, per se, but needs
  to be optional and disabled by default.  

* Added an AUTOLOAD method to Template.pm to delegate to Context object.
  Template redirect() removed, given that it is now accessible via 
  AUTOLOAD.

* Added inc() and dec() root functions to the Context object which get 
  evaluated to simple increment/decrement subs when called as root 
  variables and not otherwise defined.  This may be extended in the 
  future to provide default object/package whose methods/subs should be 
  called when root variables are requested but not defined.

#------------------------------------------------------------------------
# Version 0.22  1999/08/04 20:37:43
#------------------------------------------------------------------------

* First public beta release.

* Updated all of the documentation.  The general toolkit document, 
  Template-Toolkit.pod has been deleted and its content moved into
  Template.pm.

* Added facility to escape '$' in a document (and then have it correctly 
  unescaped) to avoid unintentionally referencing a variable when 
  INTERPOLATE is on.  Added test to t/interp.t

* Changed default tag style to be '[% blah_blah %]' whilst also supporting
  the old '%% blah_blah %%' style.  The TAG_STYLE parameter may be 
  specified as 'regular' ([% ...%]), 'percent' (%% ... %%) or 'default'
  (both of the above - [\[%]% ... %[\]%]).  The START_TAG and END_TAG 
  may still be specified and will override any values set by the TAG_STYLE.

* Added ERROR directive to allow reporting of errors via the $context->error()
  method, which by default writes to STDERR.  Changed 'error' variable as 
  passed to a CATCH block to 'e' to avoid a name clash with 'ERROR'.  Added
  t/error.t to test suite.

* Added CASE option, which by default is set to 0 to indicate non-case 
  sensitivity of *KEYWORDS* (variables are always case sensitive).
  When set off, a keyword such as 'INCLUDE' can be specified in any
  case.  When set on, all keywords must be expressed in exact, upper
  case.  Lower or mixed case versions of the same words (e.g. 'include',
  'for', 'Filter') are treated as variables.  The only exceptions are 
  'and', 'or' and 'not' which can *always* be expressed in any case.
  Added t/case.t to test.

* Added interpolation of "\n" into double-quoted text strings.

* Added THROW directive and t/throw.t to test it.  Usage is:
  %% THROW type info %%, mapping 'type' to a %% CATCH type %%.

* Improved handling of exceptions, blocking only multiple occurances
  of the same exception type.  Nested exception throwing now works OK.

* Added a catch($type, $handler) method to Template::Context for installing
  exception handlers.  Changed Template::Directive::Catch->process() to 
  call this method.

* Fixed memory leak caused by circular dependency rooted at Context.
  Template.pm DESTROY method calls context->old() to perform clearup.

* Removed ERROR_PARSE ('parse' exception) and made it a case of ERROR_FILE
  ('file').

* Removed redundant EXPAND_* constants from Template::Constants.


#------------------------------------------------------------------------
# Version 0.21  1999/07/28 16:12:58
#------------------------------------------------------------------------

* Fifth (and final?) alpha release.

* Improved Template::Iterator to allow data items to be ordered by an 
  external function or by one of the default ordering styles: 'sorted'
  or 'reverse'.  The Iterator will also accept an action parameter
  which is called on each iteration.  These can be set by passing an
  additional hash reference to the iterator constructor containing ORDER
  and/or ACTION keys.  e.g.
 
  my $iterator = Template::Iterator->new(['foo', 'bar', 'baz'], 
			{ ORDER => 'sorted', ACTION => \&format_data });

  These can also be added as named parameters in parenthesis after a 
  list constructor, e.g.

  %% FOREACH user = [ tom dick harry ] ( order => 'sorted') %%
     ...
  %% END %%

  %% iterator = [ foo bar baz ] ( order => 'reverse' ) %%
  %% INCLUDE winner FOREACH person = iterator %%

* Added the Template::Plugin::Format module which implements a very 
  simple plugin for creating sprintf-like formatting functions.  e.g. 
  %% USE format; bold = format('<b>%s</b>'); bold('foo'); bold('bar') %%
  %% FOREACH [ foo bar baz]( order='sorted' action=format('-- %s --') ) %%
  etc., etc.  See t/format.t for examples.

* Added thrown() method and internal flag to Template::Exception to 
  indicate if it has been handled by the $context->thrown() method.
  Changed Template::Directive::Block to throw any unthrown exceptions
  it recevies to the $context->throw() method.  The upshot is that 
  user code can now simply C<return (undef, Template::Exception->new(...))>
  and the calling block loop will throw the exception.  Previously, the 
  user code was required to directly call $context->throw() to raise an 
  exception.  User code is no longer passed a reference to the context 
  (although plugin objects have an internal reference they can use) so 
  this would not have been possible otherwise.  Fixed a couple of other 
  minor bugs in the exception throwing/handling in the process.

* Finalised the return protocol for user code and object methods and 
  implemented.  Code/methods may return a value and optionally, an 
  additional status.  The status code may be a Template::Exception
  (see previous item).  An undefined value returned will raise an
  'undef' exception unless the error is already defined.  If the 
  error is STATUS_OK (0) then the calue will be silently converted 
  to an empty string ''.

* Added tests t/code.t and t/object.t to test variable bindings to 
  user code and objects respectively.  Added t/private.t to test that
  members prefixed with '_' or '.' remain unexposed.

* Added OP_TOLERANT as a temporary fix to set a flag to prevent the 
  context runop() method from automatically raising an undef exception
  when it resolves a variable to an undefined value.  This is to allow
  directives such as IF to tolerate undefined values without raising 
  exceptions.  Added tests to t/if.t to test this.

* Fixed another instance of the OP_NOT bug (previously fixed in 0.18)
  which manifested itself when UNLESS was used as a side-effect, e.g. 
  %% RETURN UNLESS something_to_do %%.  Added tests to t/unless.t to 
  detect.

* Fixed minor bug in the parser which wasn't allowing a trailing comma
  in an argument or named parameter list.  Updated t/hash.t and added 
  t/list.t to test this and other related issues.

* Added public context() method to Template.pm to return internal
  context reference.


#------------------------------------------------------------------------
# Version 0.20  1999/07/27 12:59:08
#------------------------------------------------------------------------

* Fourth public alpha release.

* Fixed bug in Context throw() method which was causing re-entrancy 
  problems in CATCH handlers.  Also changed to pass a variable named 
  'error' into the CATCH block containing the members 'type' and 'info'.
  e.g. %% CATCH undef %% <!-- $error.info --> %% END %%.  Added tests
  to t/catch.t.

* Added '+' chomp option to compliment '-' option.  The '+' disables chomping
  for that directive, the '-' forces it.  Improved the PRE_CHOMP to work 
  better when POST_CHOMP is also enabled and to pre-chomp correctly on the 
  first line of the file.  And hopefully, all this without screwing up line
  numbering.

* Fixed grammar to allow literals as lvalues.

* Changed BLOCK definition grammar to allow names that contain dots and 
  slashes as per INCLUDE.  These are treated as literal.

* Fixed bug in FOREACH which was causing an undefined variable reference
  to go un-noticed.  

* Changed FOREACH to clone (localise) a stash context so that it
  doesn't trample on previously defined variables.  In addition, it
  will also automagically import the members of HASH references that
  are returned by each iteration when a target loop variable isn't
  specified.

  This now allows you to write things like:
     %% FOREACH userlist %%
        $name ($id)
     %% END %%

  Instead of:
     %% FOREACH user = userlist %%
	$user.name ($user.id)
     %% END %%

* added tests to t/foreach.t to verify the above behaviour.

* added test scripts binop.t, chomp.t, prechomp.t, postchomp.t
  and skel.t.  Extended/improved tests in if.t, predefs.t.

* Fixed bug in tokeniser that was failing to recognise '!='. 


#------------------------------------------------------------------------
# Version 0.19  1999/07/26 19:53:39
#------------------------------------------------------------------------

* Third public alpha release.

* Added Template::Plugin and engaged the USE directive to load plugin
  modules, instantiate plugin objects and bind them to variables in 
  the stash.  Modified the grammar a little to build the appropriate 
  reduction for the parenthesised parameters that may be passed from 
  the USE directive.  Wrote simple stubs for Template::Plugin::CGI and 
  Template::Plugin::DBI.

* Fixed bug in UNLESS which was using the old '!' character instead of
  OP_NOT.  Added t/unless.t to test UNLESS directive and IF directive
  with logical negation operator ('!', aka OP_NOT)

* Changed INCLUDE parameter to allow '/' as well as '.' within the name.
  This is in addition to the regular \w characters permitted.  Names 
  containing any other characters must be quoted.  Updated t/include.t
  to add test for this.

* Fixed bug that was causing the 'and' and 'or' boolean operations to 
  not be recognised unless specified in UPPER CASE.  

* Added t/direcive.t to test general directive options (e.g. chomping,
  whitespace and case insensitivity, etc.

* Fixed IMPORT option and added t/import.t test.

* Fixed EXPORT and added t/export.t test.


#------------------------------------------------------------------------
# Version 0.18  1999/07/23 11:50
#------------------------------------------------------------------------

* Second public alpha release

* Re-wrote the parser grammar and associated runtime support for the 
  very last time.  The grammar needs some polishing and there are a 
  couple of ugly/elegant hacks (depending on your perspective)  
  to manage special cases for INCLUDE, in particular.  These
  could be improved, but they work for now.

* The language now fully supports multiple namespace variables of 
  which any sub-element might be represented by a variable, hash array
  or entry, list, code reference or object.  The runtime opcode loop
  evaluates these with respect to one another where joined by '.'

* Parameters can be specified to any individual element.  e.g. foo(a).bar(b)

* An individual element may be an evaluated variable  e.g. user.${uname}

* The INTERPOLATE option now includes period as part of identifier names.
  Braces need only be used to delimit a variable against another period.
  e.g.  $user.name   ${user.id}.gif

* An assignment may now be enclosed in parentheses and used as a term, e.g.
  %% IF (users = mydb.get_userlist) %%

* Changed the calling convention for variables bound to code and
  object (methods).  A reference is no longer passed as the first 
  parameter.  This makes it easier to interface to existing code
  and marginally quicker to write new code.  The Template::Stash
  module can be sub-classed to create plug-in library modules which
  can have far greater intimacy with the Template Toolkit.

* Fixed broken parameter passing into code bound to variables.  Added
  t/call.t to test correct behaviour.  Then the whole calling convention
  got changed again, but its legacy remains...

* Re-wrote and/or cleaned up the entire test suite.  Some are still
  incomplete or missing.

* Updated Template-Toolkit.pod to remove some of the documentation that 
  was clearly obsoleted by these changes.  Added and corrected most of the
  obvious stuff, but there's still some lacking and it may include features 
  missing, changed or broken.

* Numerous minor bugs, typos, etc.


#------------------------------------------------------------------------
# Version 0.17  1999/06/24 23:55
#------------------------------------------------------------------------

* First public alpha release




