$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: srajko_at_[hidden]
Date: 2007-05-29 16:47:43
Author: srajko
Date: 2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
New Revision: 4354
URL: http://svn.boost.org/trac/boost/changeset/4354
Log:
add support for template merges
Added:
   sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj.py
      - copied, changed from r4349, /sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj
Removed:
   sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj
Text files modified: 
   sandbox/template_under_construction/file_template/libs/file_template/doc/Jamfile.v2                                  |     6                                         
   sandbox/template_under_construction/file_template/libs/file_template/doc/file_template.qbk                           |    95 +++++++++                               
   sandbox/template_under_construction/file_template/libs/file_template/doc/sandbox.qbk                                 |    41 +---                                    
   sandbox/template_under_construction/file_template/libs/file_template/doc/templates.qbk                               |   356 ++++++++++++++++++++++++++++++--------  
   sandbox/template_under_construction/make_template.py                                                                 |   370 ++++++++++++++++++++++++++++++--------- 
   sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide.py               |    24 ++                                      
   sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj.py  |    31 +-                                      
   sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/xcodeide.py             |     2                                         
   sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/doc/$template_library$.qbk.py |    31 +-                                      
   sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/doc/Jamfile.v2.py             |    50 +++-                                    
   sandbox/template_under_construction/sandbox/sandbox.py                                                               |    14                                         
   11 files changed, 755 insertions(+), 265 deletions(-)
Modified: sandbox/template_under_construction/file_template/libs/file_template/doc/Jamfile.v2
==============================================================================
--- sandbox/template_under_construction/file_template/libs/file_template/doc/Jamfile.v2	(original)
+++ sandbox/template_under_construction/file_template/libs/file_template/doc/Jamfile.v2	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -18,7 +18,7 @@
    :
         <xsl:param>chunk.first.sections=1
         <xsl:param>chunk.section.depth=3
-        <xsl:param>toc.section.depth=3
-        <xsl:param>toc.max.depth=3
-        <xsl:param>generate.section.toc.level=3
+        <xsl:param>toc.section.depth=4
+        <xsl:param>toc.max.depth=4
+        <xsl:param>generate.section.toc.level=2
     ;
\ No newline at end of file
Modified: sandbox/template_under_construction/file_template/libs/file_template/doc/file_template.qbk
==============================================================================
--- sandbox/template_under_construction/file_template/libs/file_template/doc/file_template.qbk	(original)
+++ sandbox/template_under_construction/file_template/libs/file_template/doc/file_template.qbk	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -1,6 +1,6 @@
 [library FileTemplate
     [quickbook 1.4]
-    [version 0.9]
+    [version 0.91]
     [authors [Rajko, Stjepan]]
     [copyright 2007 Stjepan Rajko]
     [purpose generates file and directory trees from templates]
@@ -11,18 +11,95 @@
     ]
 ]
 
-
-FileTemplate is a template processor for files and directories.  It provides a basic
-framework which makes producing templated dile/directory trees relatively easy.
-The philosophy of the framework is that simple things should be simple, and more
-complicated things should be doable relatively simply.  By being implemented in
-Python, and allowing template-specific python scripts in the template, FileTemplate
-has a pretty good degree of flexibility.
+[def template_object_ref [link filetemplate.templates.reference.template template object]]
+[def results_object_ref [link filetemplate.templates.reference.results results object]]
+[def python_file_ref [link filetemplate.templates.phases.processing.python_files
+    python generated file]]
+[def python_files_ref [link filetemplate.templates.phases.processing.python_files
+    python generated files]]
+[def python_script_ref [link filetemplate.templates.phases.examination.template_script template script]]
+[def python_scripts_ref [link filetemplate.templates.phases.examination.template_script template scripts]]
+[def sandbox_template_ref [link filetemplate.sandbox sandbox template]]
+[def template_option_ref [link filetemplate.templates.options FileTemplate option]]
+[def template_options_ref [link filetemplate.templates.options FileTemplate options]]
+[def sandbox_option_ref [link filetemplate.sandbox.options sandbox option]]
+[def sandbox_options_ref [link filetemplate.sandbox.options sandbox options]]
+[def substitution_template_ref [link filetemplate.templates.substitutions substitution template]]
+[def substitution_templates_ref [link filetemplate.templates.substitutions substitution templates]]
+[def invocation_phase_ref [link filetemplate.templates.phases.invocation invocation phase]]
+[def template_merge_ref [link filetemplate.templates.merges template merge]]
+[def template_merges_ref [link filetemplate.templates.merges template merges]]
+[def command_line_ref [link filetemplate.templates.phases.invocation.command_line command line]]
+[python]
+
+FileTemplate is a template processor for files and directories.  This could be useful in the
+following scenarios:
+
+* There is a generic starting point for a certain type of project.  The user can specify
+information to fine-tune their particular starting point.
+* The user would like to integrate their existing files, and integrate them into a starting
+point for a new project.  The user can perform a template_merge_ref between the template
+for the new project, and the existing files (acting as a second template).
+
+FileTemplate provides a basic
+framework which makes producing templated file/directory trees relatively easy.
+The philosophy behind the development of the framework is that simple things should be simple,
+and more complicated things should be doable.  By being implemented in
+Python, and allowing template-specific python scripts to be placed in a template, FileTemplate
+provides a reasonable degree of flexibility.
 
 FileTemplate is being developed for construction of seed projects for the Boost Sandbox.
-The [link filetemplate.sandbox sandbox] template, which is used for this purpose,
+The sandbox_template_ref, which is used for this purpose,
 is currently the only template developed using FileTemplate.
 
+[note FileTemplate is in no way an official part or tool of the Boost libraries.]
+
+Here are some examples of what you can do with FileTemplate, and how you would
+go about doing it:
+
+[table Examples of things you can do with the sandbox template
+    [[To accomplish this:][You can do this:]]
+    [
+        [Use the =sandbox= template to start a new Boost sandbox library (you will be prompted for whatever the
+        template processor needs to know)] 
+        [Run: [^python make_template.py sandbox]
+
+        =sandbox= specifies the root directory of the template.]
+    ][
+        [Use the =sandbox= template and specify everything from the command line]
+        [Run: [^python make_template.py destination\=/boost_sandbox sandbox library\=my_new_library "author\=John Doe"]
+
+        =destination= is a global template_option_ref, and specifies where the result is constructed.
+        =library= and =author= are sandbox_options_ref.]
+    ][
+        [Tell the =sandbox= template to also construct MSVC 8.0 IDE projects (which
+        provide access to files and =bjam= builds)]
+        [Run: [^ python make_template.py sandbox vc8ide\=y]]
+    ][
+        [Combine the =sandbox= template with your existing code (the created documentation build files and MSVC IDE projects will include your existing files)]
+        [Run: [^ python make_template.py sandbox library\=boostified_library vc8ide=y /old_library/include/old_library into\=boostified_library/boost/boostified_library]
+
+        Here, the template processor is performing a template_merge_ref.
+        The existing source tree =/old_library/include/old_library= is used as an additional template.
+        It is given the option =into\=boostified_library/boost/boostified_library=, which specifies where the content
+        should go in the built result.]
+    ]
+]
+
+[table Examples of things you can do if you're designing your own template
+    [[To accomplish this:][You can do this:]]
+    [
+        [Design a template =simple= which is meant to be copied verbatim]
+        [Create a directory called =simple=, and place the desired files and directories inside.]
+    ][
+        [Design a template in which =$template_whatever$= inside template files is substituted into a user-specified value]
+        [Place inside the template directory a python_script_ref which uses the template_object_ref to get the user-specified value and set up the substitution.]
+    ][
+        [Create a template for file =random.txt= whose content requires more than simple substitutions]
+        [In place of =random.txt= create a python_file_ref =random.txt.py= which constructs the content and submits it to the template_object_ref.]
+    ]
+]
+
 * [link filetemplate.sandbox Learn more about using the sandbox template].
 * [link filetemplate.templates
  Learn more about the FileTemplate system, using and and developing templates].
Modified: sandbox/template_under_construction/file_template/libs/file_template/doc/sandbox.qbk
==============================================================================
--- sandbox/template_under_construction/file_template/libs/file_template/doc/sandbox.qbk	(original)
+++ sandbox/template_under_construction/file_template/libs/file_template/doc/sandbox.qbk	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -17,7 +17,7 @@
 =sandbox/template-under-construction= directory and execute:
 
 [pre
-    >python make_template.py template=sandbox.py
+    >python make_template.py sandbox
 ]
 
 The script will ask you some questions and create a seed project with the
@@ -42,13 +42,13 @@
 
 Second, you will need to download some additional tools to build the documentation.
 Instructions for this part can be found in the
-[@http://www.boost.org/doc/html/boostbook.html Boostbook documentation].
+[@http://www.boost.org/doc/html/boostbook.html Boostbook documentation]
+and the
+[@http://www.boost-consulting.com/boost/tools/quickbook/doc/html/quickbook/install.html
+Quickbook documentation].
 The projects generated by file_template rely on xsltproc,
 DocBook XSL and DTD distributions, and Doxygen.  The sandbox template does not currently use
-Apache FOP.  Here are some of the download links for your convenience:
-
-* [@http://sourceforge.net/project/showfiles.php?group_id=21935#files docbook xsl]
-* [@http://www.stack.nl/~dimitri/doxygen/download.html doxygen]
+Apache FOP.
 
 [caution Make sure you download docbook-xsl and not docbook5-xsl.]
 
@@ -57,16 +57,9 @@
 the directions in the [@http://svn.boost.org/trac/boost/wiki/BoostSubversion Boost subversion wiki].
 
 Once you have all this in place, go to the template-under-construction folder of the sandbox.
-Run the make_template.py script, and follow the instructions.  For example,
-the project used to build this documentation was created as follows:
-
-[python]
-
-    python make_template.py
-    library name: (e.g., something_new): sandbox_template
-    library author[s]: (e.g., Yours Truly[,Yours D. NotTruly]): Stjepan Rajko
+Run the make_template.py script, and follow the instructions.
 
-You can also use the command line to specify the options.
+You can also use the command_line_ref line to specify the options.
 
 Some other information that might come in handy as you start working on your project:
 
@@ -93,14 +86,14 @@
     [[vc8ide][Specifies whether the IDE projects for MSVC 8.0 should be generated][n]]
 ]
 
-For example, this project was started using the following command line:
+For example, this project could have been started using the following command line:
 
 [pre
-    python make_template.py template=sandbox.py library=file_template "author=Stjepan Rajko" docs=qb vc8ide=y
+    python make_template.py sandbox library=file_template "author=Stjepan Rajko" docs=qb vc8ide=y
 ]
 
-For more information about template options, see the
-[link filetemplate.templates.options FileTemplate options] documentation.
+For more information about template options, and for other options provided
+by FileTemplate, see the template_options_ref documentation.
 
 [endsect]
 
@@ -161,17 +154,7 @@
 It might be better to perform a clean followed by a build.  However, this has the downside
 of not being to be able to access =bjam -a= from the IDE.
 
-* The template directory structure should be revised.  Instead of invoking the template
-processor by specifying the template script, perhaps it would be better to specify the
-template root directory - which can hold the template script if one is necessary,
-and the actual template tree.
-
-* Destination directory should be specifiable.
-
 * Since the template processor now supports file-specific substitution templates,
   most of the copyright templates should just be called $template\_copyright$.
 
-* the user-specified library name should be given in all lowercase - this should
-  be enforced.
-
 [endsect]
Modified: sandbox/template_under_construction/file_template/libs/file_template/doc/templates.qbk
==============================================================================
--- sandbox/template_under_construction/file_template/libs/file_template/doc/templates.qbk	(original)
+++ sandbox/template_under_construction/file_template/libs/file_template/doc/templates.qbk	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -8,26 +8,56 @@
 [link filetemplate.templates.phases processing phases] documentation.
 
 To learn about creating new templates or extending existing templates,
-you should also read about
-[link filetemplate.templates.options options] and
-[link filetemplate.templates.substitutions substitution templates]
-
+you should also read about template_options_ref and 
+substitution_templates_ref.
 
 [section:phases Processing phases]
 
 [section:invocation Invocation]
-The template processor first initializes [link filetemplate.templates.reference template class]
-object, which processes the template and can be used by the python scripts present
-in the template to customize the behavior of the template.
-
-Then, the template processor will invoke the startup script for the template,
-which is specified through the =template= [link filetemplate.templates.options option].
-The startup script gives the template processor any information
-it needs to know, and sets up
-[link filetemplate.templates.substitutions substitution templates] if applicable.
+
+[section:command_line Command line]
+
+The template processor begins by processing the command line for template_options_ref.
+The options are specified via [~option=value] arguments.  In simple cases, such
+as when using only one template, the ordering of the command line arguments should not
+affect the output.  However, when multiple templates are used symoultaneously for a
+template_merge_ref, the order matters.  The order is as follows.
+
+# Global template_options_ref can be specified at any point, but are recommended to be
+placed at the beginning for consistency.
+# template_options_ref that should be applied to all templates are specified before any
+template is listed.
+# template_options_ref that should be applied to an individual template only should be
+specified after listing the template (and before the next template is listed).
+
+[tip The template can be specified without explicitly using =template\==.  E.g., you can run
+[^ python make_template.py sandbox] instead of [^ python make_template.py template=sandbox]]
+
+The following examples illustrates this structure:
+
+[table Command line structure examples:
+    [[invocation][global options][options for all templates][first template][second template]]
+
+    [[=python make_template.py=][][][sandbox][]]
+
+    [[=python make_template.py=][[^ destination=/boost_sandbox]]
+    []
+    [[^ sandbox library=boostified_library vc8ide\=y ignore\=$template_library$/boost]]
+    [ /old_library/include/old_library into\=boostified_library/boost/boostified_library]]
+]
+
+Some options, such as =ignore=, can be specified multiple times.
+
+[endsect]
+
+After processing the command line, or prompting the user if necessary, the template
+processor will initialize
+each template_object_ref (which processes the template and can be used by any in-template
+python_script_ref to customize the behavior of the template)
+and the global template_options_ref.
 
 The template processor will then
-[link filetemplate.templates.phases examine the template tree].
+[link filetemplate.templates.phases.examination examine the template tree].
 
 [endsect]
 
@@ -38,19 +68,20 @@
 the names of all directories and files located in the tree, which will then
 be copied / processed in the next phase.
 
+[section:template_script Template scripts]
+
 To customize what information is to be copied, and to specify additional
-customization possibilites (e.g., via [link filetemplate.templates.substitutions
-substitution templates]),
+customization possibilites (e.g., via substitution_templates_ref),
 template scripts may be inserted in the template tree.
 
 Template scripts are python files which begin with the following text on their first line:
-[python]
 
     # template script
 
 Every script found during the transversal will be executed.  The script can
-interact with the template processor through the
-[link filetemplate.templates.reference template object].
+interact with the template processor through the template_object_ref.
+
+[endsect]
 
 [endsect]
 
@@ -62,18 +93,19 @@
 A file for which no specific substitution templates are specified will be copied verbatim.
 
 [h4 Processed file content]
-A file for which at least one specific substitution template is specified will be processed
-for substitution templates and specific templates.
+A file for which at least one specific substitution_template_ref is specified will be processed
+for global substitution_templates_ref and specific substitution_templates_ref.
 
-[h4 Python generated file content]
+[section:python_file Python generated files]
 A file of the name /filename/=.py= can be used to generate the file /filename/.  To do so,
 it must begin with
 
     # template file
     
 When the script generates the content, it supplies it to the template processor via the
-`template.submit_content(content)` command (see the
-[link filetemplate.templates.reference template object] reference).
+`template.submit_content(content)` command (see the template_object_ref reference).
+
+[endsect]
 
 [endsect]
 
@@ -82,65 +114,165 @@
 [section:options Options]
 
 Options are used to fine-tune the behavior of the FileTemplate template processor as well
-as the behavior of the template.  The following options are used by the template processor
-(specific templates may use additional options):
+as the behavior of the template.
+
+[h4 Global options]
+/Global options/ govern the behavior of the template processor.
+
+[table Global options
+    [[option][desctiption][valid values][default value]]
+
+    [[destination][Destination directory where the results will be constructed.]
+    [valid directory path (will be created if it does not exist)][current directory]]
+    
+]
+
+[h4 Template options]
+/Template options/ can be used to specify how a particular template is processed.
+Templates may use additional, template-specific options, as is the case with sandbox_options_ref.
 
-[table Options used by the FileTemplate template processor
+[table Template options
     [[option][desctiption][valid values][default value]]
-    [[template][Template-specific script][valid filename][]]
-    [[erase][Determines whether the template processor should erase the destination
-    directory tree if it already exists][y/n]]
+    [[template][Template directory][valid directory][]]
+
+    [[into][Determines where the output of the template will be placed inside the resulting tree]
+    [valid directoy in resulting tree][root of the resulting tree]]
+    
+    [[ignore][Ignores a directory of the source template tree][directory in source template tree]
+    []]
+    
+    [/    [[erase][Determines whether the template processor should erase the destination
+    directory tree if it already exists][y/n]]]    
 ]
 
-Options can be specified at command-line via [~option=value] arguments.  If an option
-is not specified, and it has no default value, the user will be prompted for the value.
+Options can be specified using the command line.  See the invocation_phase_ref reference
+for more information.  If an option
+is not specified in the command line, and it has no default value, the user will be prompted for the value.
 
 This is the output of a sample session:
 
 [pre
 
->python make_template.py [*template=sandbox.py] [*library=my_library]
-/--------------------
-| Executing template file sandbox.py...
-/
-/--------------------
-| Processing Boost Sandbox template.
-/
-[*author: [~John Doe]]
-/--------------------
-| Examining the template project tree...
-/
-$template_library$
-$template_library$\boost
-$template_library$\boost\$template_library$
-$template_library$\libs
-$template_library$\libs\$template_library$
-$template_library$\libs\$template_library$\build
-$template_library$\libs\$template_library$\doc
-$template_library$\libs\$template_library$\doc\html
-$template_library$\libs\$template_library$\doc\html\images
-$template_library$\libs\$template_library$\example
-$template_library$\libs\$template_library$\src
-$template_library$\libs\$template_library$\test
-Directory my_library already exists.
-[*erase: Erase it (please make sure you want to erase the entire directory tree rooted at my_library)? \[y/n\] [~y]]
-/--------------------
-| Erasing...
-/
-/--------------------
+python.exe make_template.py [* sandbox]
+/-------------------------------------------
+| Processing template sandbox with options:
++---
+|| {'ignore': set(\[\]), 'template': 'sandbox'}
+|\/-------------------------------------------
+|| Examining the template project tree...
+|+---
+|||
+||\/-------------------------------------------
+||| Welcome to the Boost Sandbox template.
+||+---
+||\/-------------------------------------------
+||| [* Enter value for option library:]
+||+---
+||| [* (all lowercase, use underscores to separate words, e.g. "my_library"): my_library]
+||\/-------------------------------------------
+||| [* Enter value for option author:
+||+---
+||| (comma separated, no spaces outside names, e.g., "My Name,Notmy R. Name": Stjepan Rajko]
+||| $template_library$
+||| $template_library$\/boost
+||| $template_library$\/boost\/$template_library$
+||| $template_library$\/libs
+||| $template_library$\/libs\/$template_library$
+||| $template_library$\/libs\/$template_library$\/build
+||| $template_library$\/libs\/$template_library$\/test
+||| $template_library$\/libs\/$template_library$\/doc
+||| $template_library$\/libs\/$template_library$\/doc\html
+||| $template_library$\/libs\/$template_library$\/doc\/html\/images
+||| $template_library$\/libs\/$template_library$\/src
+||| $template_library$\/libs\/$template_library$\/example
+\/-------------------------------------------
+| Preparing destination tree...
++---
+|\/-------------------------------------------
+|| Directories:
+|+---
+|| my_library
+|| my_library\/boost
+|| my_library\/libs
+|| my_library\/boost\/my_library
+|| my_library\/libs\/my_library
+|| my_library\/libs\/my_library\/build
+|| my_library\/libs\/my_library\/test
+|| my_library\/libs\/my_library\/doc
+|| my_library\/libs\/my_library\/src
+|| my_library\/libs\/my_library\/example
+|| my_library\/libs\/my_library\/doc\/html
+|| my_library\/libs\/my_library\/doc\/html\/images
+|\/-------------------------------------------
+|| Files:
+|+---
+|| my_library\/LICENSE_1_0.txt
+|| my_library\/boost-build.jam
+|| my_library\/Jamfile.v2
+|| my_library\/project-root.jam
+|| my_library\/boost\/my_library.hpp
+|| my_library\/boost\/my_library\/my_library.hpp
+|| my_library\/libs\/my_library\/test\/test.cpp
+|| my_library\/libs\/my_library\/test\/Jamfile.v2
+|| my_library\/libs\/my_library\/doc\/html\/reference.css
+|| my_library\/libs\/my_library\/doc\/html\/boostbook.css
+|| my_library\/libs\/my_library\/doc\/html\/images\/prev.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/tip.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/important.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/next.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/toc-minus.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/draft.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/caution.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/Thumbs.db
+|| my_library\/libs\/my_library\/doc\/html\/images\/up.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/note.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/warning.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/toc-plus.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/blank.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/home.png
+|| my_library\/libs\/my_library\/doc\/html\/images\/toc-blank.png
+|| my_library\/libs\/my_library\/example\/example.cpp
+|| my_library\/libs\/my_library\/example\/Jamfile.v2
+|| my_library\/libs\/my_library\/doc\/my_library.qbk
+|| my_library\/libs\/my_library\/doc\/Jamfile.v2
+\/-------------------------------------------
 | Creating file tree from template...
-/
-my_library\boost
-my_library\libs
-my_library\boost\my_library
-my_library\libs\my_library
-my_library\libs\my_library\build
-my_library\libs\my_library\doc
-my_library\libs\my_library\example
-my_library\libs\my_library\src
-my_library\libs\my_library\test
-my_library\libs\my_library\doc\html
-my_library\libs\my_library\doc\html\images
++---
+|/-------------------------------------------
+|| Python files...
+|+---
+||| .\/my_library\/libs\/my_library\/doc\/my_library.qbk
+||| .\/my_library\/libs\/my_library\/doc\/Jamfile.v2
+|\/-------------------------------------------
+|| Files...
+|+---
+||| .\/my_library\/LICENSE_1_0.txt
+||| .\/my_library\/boost-build.jam
+||| .\/my_library\/Jamfile.v2
+||| .\/my_library\/project-root.jam
+||| .\/my_library\/boost\/my_library.hpp
+||| .\/my_library\/boost\/my_library\/my_library.hpp
+||| .\/my_library\/libs\/my_library\/test\/test.cpp
+||| .\/my_library\/libs\/my_library\/test\/Jamfile.v2
+||| .\/my_library\/libs\/my_library\/doc\/html\/reference.css
+||| .\/my_library\/libs\/my_library\/doc\/html\/boostbook.css
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/prev.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/tip.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/important.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/next.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/toc-minus.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/draft.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/caution.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/Thumbs.db
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/up.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/note.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/warning.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/toc-plus.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/blank.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/home.png
+||| .\/my_library\/libs\/my_library\/doc\/html\/images\/toc-blank.png
+||| .\/my_library\/libs\/my_library\/example\/example.cpp
+||| .\/my_library\/libs\/my_library\/example\/Jamfile.v2
 ]
 [endsect]
 
@@ -178,7 +310,19 @@
 
 [endsect]
 
-[section:reference Template object reference]
+[section:merges Template merges]
+
+FileTemplate can be used to merge results created by several templates.  If a template uses
+the results_object_ref to customize its output based on files created by all processed templates,
+this can be used to seamlessly integrate additional files in the template results.
+
+The sandbox_template_ref uses this to allow additional files (e.g., existing source code) to be
+integrated in the newly created Boost sandbox library project.
+    
+[endsect]
+
+[section:reference Reference]
+[section:template Template object]
 The template object contains several functions which can be used from template
 scripts to customize template behavior.
 
@@ -200,11 +344,11 @@
 
     template.name_replacement('$template_library$', library_name)
 
-To set up a specific substitution template:
+To set up a specific substitution_template_ref:
 
     template.content_replacement(['.hpp', '.cpp'], '$template_created$', '// Created in $template_year$')
 
-To set up a general substitution template:
+To set up a general substitution_template_ref:
 
     template.all_content_replacement('$template_year$', str(time.localtime().tm_year))
 
@@ -224,6 +368,64 @@
     Yes it is."""
     
     template.submit_content(content)
+   
+or
+
+    template.append_content("""
+    This is a script-generated file.""")
+    template.append_content("""
+    Yes it is.""")
+
+[endsect]
+
+[section:results Results object]
+
+The results object holds information about the files and directories which will
+be generated by the template processor.  It includes files and directories from
+*all* templates being processed, and can therefore be used to allow seamless
+integration of templates.
+
+For example, if a template includes a file whose
+contents depend on the directory tree below a certain directory,
+you can =walk= the results object and extract the directory tree.
+The following example does so to include all non-detail include
+directories for the sandbox_template_ref:
+
+    doxy_source_files = list()
+    for root, dirs, files in results.walk(
+        # we want the returned root to be relative to $template_library$
+        template.replace_name('$template_library$'),
+        # and want to walk the boost/$template_library$ directory underneath that
+        template.replace_name('boost/$template_library$')):
+        if os.path.basename(root) != 'detail':
+            doxy_source_files.append(
+                template.replace_name(os.path.join(os.path.join('../../..',
+                root), '*.hpp').replace('\\','/')))
+
+A similar example uses the =files_in= and =directories_in= functions of the
+result object to construct the list of files and filters for a MSVC IDE:
+
+        def vc_list_files(level, output_base, destination_base, directory):
+            tabs = ''.join(['\t' for x in range(level)])
+            output_base_directory = os.path.join(output_base, directory)
+            destination_base_directory = os.path.join(destination_base, directory)
+            for name in results.files_in(destination_base_directory):
+                template.append_content("""
+    """ + tabs + """<File
+    """ + tabs + '\tRelativePath="'+os.path.join(output_base_directory,name)+""""
+    """ + tabs + """\t>
+    """ + tabs + """</File>""")
+
+            for name in results.directories_in(destination_base_directory):
+                template.append_content("""
+    """ + tabs + """<Filter
+    """ + tabs + '\tName="'+name+""""
+    """ + tabs + """\t>""")
+                vc_list_files(level+1, output_base_directory, destination_base_directory, name)
+                template.append_content("""
+    """ + tabs + """</Filter>""")
+
+[endsect]
 
 [endsect]
 
@@ -240,7 +442,9 @@
 in a directory other than the same directory as the script.
 This allows templates configured in a more centralized way.
 
+[/
 * The =erase= option should require the user to type =erase= for the value
 instead of =y=, just to be safe.
+]
 
 [endsect]
\ No newline at end of file
Modified: sandbox/template_under_construction/make_template.py
==============================================================================
--- sandbox/template_under_construction/make_template.py	(original)
+++ sandbox/template_under_construction/make_template.py	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -12,40 +12,94 @@
 import re
 
 global template
+global log
+global options
+global results
+
+class Log(object):
+    def __init__(self):
+        self.__level__ = 0
+
+    def __prefix__(self):
+        return ''.join('|' for x in range(self.__level__))
+
+    def __print__(self, string):
+        print self.__prefix__() + string
+
+    def message(self, string):
+        self.__print__('/-------------------------------------------')
+        self.__print__('| ' + string)
+        self.__print__('+---')
+
+    def phase(self, string):
+        self.message(string)
+        self.__level__ += 1
+
+    def end(self):
+        self.__level__ -= 1
+        
+    def line(self, string):
+        self.__print__('| ' + string)
+
+    def raw(self, string):
+        return raw_input(self.__prefix__() + '| ' + string)
+
+
+log = Log()
 
 # The Options class holds user-specified options.
 class Options(object):
+
+    # initializes the object
+    # initializes self.options
+    # initializes common regular expressions used for option verification
     def __init__(self):
+        
+        # initialize self.options
         self.options = dict()
-        for arg in sys.argv[1:]:
-            option, eq, val = arg.partition('=')
-            self.options[option] = val
+        self.options['ignore']=set()
+        
+        # initialize common regular expressions
         self.any = re.compile(r'.*\Z')
         self.boolean = re.compile(r'[yn]\Z')
         self.alnum = re.compile(r'\w+\Z')
+        self.alnum_lowercase = re.compile(r'[a-z0-9_]+\Z')
 
+
+    # raises an exception if the string doesn't match the regular expression
+    # returns string
     def verify (self, string, regexp):
         if regexp != None and not regexp.match(string):
             raise NameError, string + ' does not match ' + regexp.pattern
         return string
 
+
+    # makes the value of the option to be value, or prompts if value==None
+    # value is set to the new value of the option and returned
     def make(self, option, value, prompt=None):
         if value==None:
-            if prompt==None:
-                prompt_text = option + ': '
+            if (option != None):
+                log.message('Enter value for option ' + option + ':')
             else:
-                prompt_text = option + ': ' + prompt
-            value = raw_input(prompt_text)
+                log.message('Enter value: ')
+            if prompt==None:
+                prompt = option + ': '
+            value = log.raw(prompt)
 
-        self.options[option] = value
+        if option != None:
+            self.options[option] = value
         return value
 
+
+    # returns the value of an option.  the user will be prompted if necessary.
     def get(self, option, regexp=None, default=None, prompt=None):
         if self.options.has_key(option):
             # option has already been set
             return self.verify(self.options[option], regexp)
         return self.verify(self.make(option, default, prompt), regexp)
 
+
+    # returns the value (True/False) of a boolean option.
     def get_boolean(self, option, default_bool=None, prompt=None):
         if default_bool != None:
             if default_bool:
@@ -57,6 +111,7 @@
         value = self.get(option, self.boolean, default, prompt)
         return value=='y'
 
+
 # The Replacement class models a template replacement,
 # either for file names or file content.
 class Replacement(object):
@@ -66,6 +121,7 @@
     def replace(self, string):
         return string.replace(self.template, self.value)
 
+
 # Replacements is a collection of Replacement objects.
 class Replacements(list):
     def replace(self, string):
@@ -73,6 +129,7 @@
             string = item.replace(string)
         return string
 
+
 # FileSpecificReplacement associates file extensions with a replacement   
 class FileSpecificReplacement(Replacement):
     def __init__(self, extensions, key, value):
@@ -121,6 +178,10 @@
 # such as all of its options and replacements.
 class Template(object):
     def __init__(self):
+        self.__file_list__ = list()
+        self.__directory_list__ = list()
+        self.__python_list__ = list()
+
         self.template_dir = ''
         self.options = Options()
         self.content_replacements = ContentReplacements()
@@ -135,13 +196,19 @@
     def submit_content(self, content):
         self.__content__ = content
 
-    def process_content(self, file_name, python=False):
+    def append_content(self, content):
+        self.__content__ += content
+
+    def process_content(self, name, python=False):
+        file_name = os.path.join(self.directory, name)
         if python:
             self.__content__ = ''
+            global template
+            template = self
             execfile(file_name + '.py')
             content = self.__content__
         else:
-            if not template.content_replacements.matches(name):
+            if not self.content_replacements.matches(name):
                 return None
             content = self.read_content(file_name)
 
@@ -156,12 +223,7 @@
             content_lines.pop(0)
         content = '\n'.join(content_lines)
                 
-        return self.replace_content(file_name, content)
-
-    def log_message(self, string):
-        print '/--------------------'
-        print '| ' + string
-        print '/'
+        return self.replace_content(name, content)
 
     def name_replacement(self, key, value):
         self.name_replacements.append(Replacement(key, value))
@@ -176,22 +238,20 @@
     def replace_name(self, name):
         return self.name_replacements.replace(name)
 
-    def destination_name(self, name):
-        if name.startswith(self.template_root):
-            return self.name_replacements.replace(name[len(self.template_root):])
-        else:
-            return self.name_replacements.replace(name)        
-
     def replace_content(self, name, content):
         return self.content_replacements.replace(name, content)
 
-    def examine(self, directory):
-        self.__file_list__ = list()
-        self.__directory_list__ = list()
-        self.__python_list__ = list()
 
-        for root, dirs, files in os.walk(directory):
-            print root
+    def examine(self):
+        self.directory = self.options.get('template')
+        self.into = self.options.get('into',None,'')
+        ignore_set = self.options.get('ignore')
+        
+        cwd = os.getcwd()
+        os.chdir(self.directory)
+        for root, dirs, files in os.walk(''):
+            log.line(root)
+
             self.__dirs_clear__ = list()
             self.__files_clear__ = list()
 
@@ -201,13 +261,7 @@
                     content = self.read_content(os.path.join(root, name))
 
                     if content.startswith('# template script'):
-                         execfile(pathname)
-                    elif content.startswith('# template module'):
-                        module_name,py,nothing = name.rpartition('.py')
-                        sys.path.insert(os.path.abspath(root), 0)
-                        mod = __import__(module_name, globals(),  locals(), [], -1)
-                        sys.path.remove(os.path.abspath(root))
-                        mod.do_smt()
+                        execfile(pathname)
                     elif content.startswith('# template file'):
                         self.__python_list__.append(pathname[0:len(pathname)-3])
                     else:
@@ -219,13 +273,15 @@
                 self.__file_list__.remove(os.path.join(root, name))
 
             for name in dirs:
-                if name.startswith('.'):
+                if name.startswith('.') or \
+                   os.path.normpath(os.path.join(root, name)) in ignore_set:
                     self.ignore_subdirectory(name)
             for name in self.__dirs_clear__:
                 dirs.remove(name)
             for name in dirs:
                 self.__directory_list__.append( (os.path.join(root, name)) )
-            
+
+        os.chdir(cwd)
         return self.__directory_list__, self.__file_list__, self.__python_list__
 
     def ignore_subdirectory(self, name):
@@ -256,56 +312,200 @@
     fout.write(content)
     fout.close()
 
-# The main processing script.
-
-# template is a global variable accessible by template scripts.
-template = Template()
+class Result(object):
+    def __init__(self, template, source, destination):
+        self.template = template
+        self.source = source
+        self.destination = destination
+    def __str__(self):
+        return str((self.template.options.get('template'), self.source, self.destination))
 
-# We first read a template script file and run it.
-template_file = template.options.get("template", template.options.any)
-template.log_message('Executing template file ' + template_file + '...')
-execfile(template_file)
-
-# We then traverse the template tree and prepare a list of
-# directories and files to be created, and process any found template
-# scripts.
-template.log_message('Examining the template project tree...')
-
-directory_list, file_list, python_list = template.examine(template.template_root + template.template_dir)
-
-project_dir = template.replace_name(template.template_dir)
-
-if os.path.exists(project_dir):
-    print 'Directory ' + project_dir + ' already exists.'
-    do_erase = template.options.get_boolean(
-        'erase', None, 'Erase it (please make sure you want to erase the entire directory tree rooted at ' + project_dir + ')? [y/n] ')
-    if do_erase:
-        template.log_message('Erasing...')
-        for root, dirs, files in os.walk(project_dir, topdown=False):
-            for name in files:
-                os.remove(os.path.join(root, name))
-            for name in dirs:
-                os.rmdir(os.path.join(root, name))
-        os.rmdir(project_dir)
+class Results(object):
+    def __init__(self):
+        self.directory_list = list()
+        self.file_list = list()
+        self.python_list = list()
+
+    def append(self, template, directory_list, file_list, python_list):
+        self.__append_list__(self.directory_list, template, directory_list)
+        self.__append_list__(self.file_list, template, file_list)
+        self.__append_list__(self.python_list, template, python_list)
+
+    def __append_list__(self, my_list, template, append_list):
+        for item in append_list:
+            result = Result(template, item, os.path.join(template.into,template.replace_name(item)))
+            my_list.append(result)
+
+    def __mkdir__(self,directory):
+        parent = os.path.dirname(directory)
+        if len(parent) and not os.path.exists(parent):
+            self.__mkdir__(parent)
+        os.mkdir(directory)
+
+    def prepare(self):
+        self.destination = options.get('destination', None, '.')
+        if not os.path.exists(self.destination):
+            self.__mkdir__(self.destination)
+
+        log.message('Directories:')
+        for item in self.directory_list:
+            log.line(item.destination)
+            self.erase(item.destination)
+        for item in self.directory_list:
+            path = os.path.join(self.destination, item.destination)
+            if not os.path.exists(path):
+                self.__mkdir__(path)
+
+        log.message('Files:')
+        for item in self.file_list + self.python_list:
+            log.line(item.destination)
+            self.erase(item.destination)
+
+    def erase(self, name):
+        path = os.path.join(self.destination, name)       
+        if os.path.exists(path):
+            log.message(path + ' already exists.')
+            do_erase = options.get_boolean(
+                None, None, 'Erase ' + path + '? [y/n] ')
+            if do_erase:
+                if os.path.isfile(path):
+                    os.remove(path)
+                if os.path.isdir(path):
+                        log.phase('Erasing...')
+                        for root, dirs, files in os.walk(path, topdown=False):
+                            for name in files:
+                                log.line(os.path.join(root, name))
+                                os.remove(os.path.join(root, name))
+                            for name in dirs:
+                                log.line(os.path.join(root, name))
+                                os.rmdir(os.path.join(root, name))
+                        log.line(path)
+                        os.rmdir(path)
+                        log.end()
+
+    def create(self):
+        log.phase('Python files...')
+        for item in self.python_list:
+            new_name = os.path.join(self.destination, item.destination)
+            log.line(new_name)
+            content = item.template.process_content(item.source, True)
+            set_content(new_name, content)
+        log.end()
+
+        log.phase('Files...')
+        for item in self.file_list:
+            template = item.template
+            new_name = os.path.join(self.destination, item.destination)
+            log.line(new_name)
+            content = item.template.process_content(item.source)
+            if content:
+                set_content(new_name, content)
+            else:
+                shutil.copy(os.path.join(item.template.directory, item.source), new_name)
+        log.end()
 
-template.log_message('Creating file tree from template...')
+    def __scan__(self, my_list, directory):
+        result_list = list()
+        result_set = set()
+        for item in my_list:
+            idir, ibase = os.path.split(item.destination)
+            if os.path.normpath(idir) == os.path.normpath(directory) and ibase not in result_set :
+                result_list.append(ibase)
+                result_set.add(ibase)
+        return result_list
+
+    def files_in(self, directory):
+        return self.__scan__(self.file_list + self.python_list, directory)
+
+    def directories_in(self, directory):
+        return self.__scan__(self.directory_list, directory)
+    
+    def walk(self, base, directory):
+        # get all files and subdirectories        
+        root = os.path.normpath(directory)
+        dirs = self.directories_in(os.path.join(base, directory))
+        files = self.files_in(os.path.join(base, directory))
+        yield root, files, dirs
+        for d in dirs:
+            for root, files, dirs in self.walk(base, os.path.join(directory, d)):
+                yield root, files, dirs
+
+# reads options from the command line
+# command line has the format:
+# python make_template.py ((option=value )* (template))* (option=value)*
+# options specified immediately before a template are for that template only.
+# options specified at the end are for all templates.
+def process_command_line():  
+    templates = list()
+    templates.append(Template())
+    index = 0
+
+    global_options = set(['destination'])    
+    options = templates[0].options
+    
+    for arg in sys.argv[1:]:
+        option, eq, val = arg.partition('=')
+        if len(eq)==0:
+            # templates can be specified without template=
+            val = option
+            option = 'template'
+
+        # option=value sets the option
+        if option=='template':
+            # done with this template, move to the next
+            templates.append(Template())
+            index += 1
+        if option in global_options:
+            options.options[option] = val
+        elif option == 'ignore':
+            templates[index].options.options[option].add(os.path.normpath(val))
+        else:
+            templates[index].options.options[option] = val
 
-os.mkdir(project_dir)
+    templates.pop(0)
 
-for name in directory_list:
-    new_name = template.destination_name(name)
-    print new_name
-    os.mkdir(new_name)
-
-for name in python_list:
-    new_name = template.destination_name(name)
-    content = template.process_content(name, True)
-    set_content(new_name, content)
-
-for name in file_list:
-    new_name = template.destination_name(name)
-    content = template.process_content(name)
-    if content:
-        set_content(new_name, content)
+    if not len(templates):
+        # user never specified a template
+        templates.append(Template())
+        templates[0].options.get('template')
     else:
-        shutil.copy(name, new_name)
+        # last set of options applies to all templates
+        for t in templates[1:]:
+            for option,value in options.options.iteritems():
+                if not t.options.options.has_key(option):
+                    t.options.options[option] = value
+
+    return templates, options
+
+# The main processing script.
+
+templates, options = process_command_line()
+results = Results()
+
+# template is a global variable accessible by template scripts.
+for template in templates:
+
+    # We first read the template script file and run it.
+    template_path = template.options.get('template')
+    log.phase('Processing template ' + template_path + ' with options:')
+    log.line(str(template.options.options))
+
+    # We then traverse the template tree and prepare a list of
+    # directories and files to be created, and process any found template
+    # scripts.
+    log.phase('Examining the template project tree...')
+    directory_list, file_list, python_list = template.examine()
+    results.append(template, directory_list, file_list, python_list)
+    
+    log.end()
+ 
+    log.end()
+
+# prepare the destination tree by erasing existing files and directories.
+log.phase('Preparing destination tree...')
+results.prepare()
+log.end()
+
+log.phase('Creating file tree from template...')
+results.create()
+log.end()
Modified: sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide.py
==============================================================================
--- sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide.py	(original)
+++ sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide.py	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -7,7 +7,7 @@
 
 if template.options.get_boolean('vc8ide', False):
 
-    template.log_message('Processing MSVC 8.0 IDE template.')
+    log.message('Processing MSVC 8.0 IDE template.')
 
     _msvc_build_command = """\t\t\t\tBuildCommandLine="bjam --v2 ../../$(ProjectName) $(ConfigurationName)"
 \t\t\t\tReBuildCommandLine="bjam --v2 -a ../../$(ProjectName) $(ConfigurationName)"
@@ -26,6 +26,28 @@
     template.content_replacement(['.vcproj'], '$template_msvc_build_command$', _msvc_build_command)
     template.content_replacement(['.vcproj'], '$template_msvc_doc_build_command$', _msvc_doc_build_command)
 
+    global vc_list_files
+    
+    def vc_list_files(level, output_base, destination_base, directory):
+        tabs = ''.join(['\t' for x in range(level)])
+        output_base_directory = os.path.join(output_base, directory)
+        destination_base_directory = os.path.join(destination_base, directory)
+        for name in results.files_in(destination_base_directory):
+            template.append_content("""
+""" + tabs + """<File
+""" + tabs + '\tRelativePath="'+os.path.join(output_base_directory,name)+""""
+""" + tabs + """\t>
+""" + tabs + """</File>""")
+
+        for name in results.directories_in(destination_base_directory):
+            template.append_content("""
+""" + tabs + """<Filter
+""" + tabs + '\tName="'+name+""""
+""" + tabs + """\t>""")
+            vc_list_files(level+1, output_base_directory, destination_base_directory, name)
+            template.append_content("""
+""" + tabs + """</Filter>""")
+
 else:
 
     template.ignore_subdirectory('vc8ide')
Deleted: sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj
==============================================================================
--- sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
+++ (empty file)
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="build"
-	ProjectGUID="{$template_msvc_build_uuid$}"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="debug|Win32"
-			OutputDirectory="..\..\..\..\bin.v2\libs\$(SolutionName)\$(ProjectName)\msvc-8.0\$(ConfigurationName)\threading-multi"
-			IntermediateDirectory="$(OutDir)"
-			ConfigurationType="0"
-			>
-			<Tool
-				Name="VCNMakeTool"
-$template_msvc_build_command$
-				Output=""
-				PreprocessorDefinitions=""
-				IncludeSearchPath=""
-				ForcedIncludes=""
-				AssemblySearchPath=""
-				ForcedUsingAssemblies=""
-				CompileAsManaged=""
-			/>
-		</Configuration>
-		<Configuration
-			Name="release|Win32"
-			OutputDirectory="..\..\..\..\bin.v2\libs\$(SolutionName)\$(ProjectName)\msvc-8.0\$(ConfigurationName)\threading-multi"
-			IntermediateDirectory="$(OutDir)"
-			ConfigurationType="0"
-			>
-			<Tool
-				Name="VCNMakeTool"
-$template_msvc_build_command$
-				Output=""
-				PreprocessorDefinitions=""
-				IncludeSearchPath=""
-				ForcedIncludes=""
-				AssemblySearchPath=""
-				ForcedUsingAssemblies=""
-				CompileAsManaged=""
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="boost"
-			>
-			<Filter
-				Name="$template_library$"
-				>
-				<File
-					RelativePath="..\..\..\..\boost\$template_library$\$template_library$.hpp"
-					>
-				</File>
-			</Filter>
-			<File
-				RelativePath="..\..\..\..\boost\$template_library$.hpp"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="solution build"
-			>
-			<File
-				RelativePath="..\..\..\..\boost-build.jam"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\project-root.jam"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Jamfile.v2"
-				>
-			</File>
-		</Filter>
-		<File
-			RelativePath="..\..\build\Jamfile.v2"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
Copied: sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj.py (from r4349, /sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj)
==============================================================================
--- /sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj	(original)
+++ sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/vc8ide/build.vcproj.py	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -1,4 +1,12 @@
-<?xml version="1.0" encoding="Windows-1252"?>
+# template file
+
+# Copyright 2007 Stjepan Rajko.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+template.append_content(
+r"""<?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
         ProjectType="Visual C++"
         Version="8.00"
@@ -52,23 +60,9 @@
         </Configurations>
         <References>
         </References>
-	<Files>
-		<Filter
-			Name="boost"
-			>
-			<Filter
-				Name="$template_library$"
-				>
-				<File
-					RelativePath="..\..\..\..\boost\$template_library$\$template_library$.hpp"
-					>
-				</File>
-			</Filter>
-			<File
-				RelativePath="..\..\..\..\boost\$template_library$.hpp"
-				>
-			</File>
-		</Filter>
+	<Files>""")
+vc_list_files(2, r'..\..\..\..', template.replace_name('$template_library$'), 'boost')
+template.append_content(r"""
                 <Filter
                         Name="solution build"
 			>
@@ -93,3 +87,4 @@
         <Globals>
         </Globals>
 </VisualStudioProject>
+""")
Modified: sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/xcodeide.py
==============================================================================
--- sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/xcodeide.py	(original)
+++ sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/build/xcodeide.py	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -2,7 +2,7 @@
 
 if template.options.get_boolean('xcodeide', False):
 
-    template.log_message('Processing Xcode IDE template.')
+    log.message('Processing Xcode IDE template.')
     
 else:
 
Modified: sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/doc/$template_library$.qbk.py
==============================================================================
--- sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/doc/$template_library$.qbk.py	(original)
+++ sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/doc/$template_library$.qbk.py	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -7,7 +7,7 @@
 
 docs = template.options.get('docs')
                      
-content="""
+template.append_content("""
 [library $template_Library$
     [quickbook 1.4]
     [version 0.01e-10]
@@ -34,40 +34,37 @@
 
 The $template_Library$ is located in the $template_library$ directory of the boost sandbox.
 
-"""
+""")
 if docs!='qb':
-    content+="""
+    template.append_content("""
 You might also want to look at the [link $template_library$.reference reference].
 
-"""
+""")
 
-content+="""
+template.append_content("""
 [endsect]
 
 [endsect]
-"""
+""")
 if docs=='qb+doxy':
-    content+="""
+    template.append_content("""
 [section:reference Reference]
 
 The reference for this library is [@doxygen/index.html generated separately].
 
 [endsect]
 
-"""
+""")
+elif docs=='qb+doxyref':
+    template.append_content("""
+[xinclude $template_library$_doxygen.xml]
+""")
 
-content+="""
+template.append_content("""
 [section:license License]
 
 $template_qbk_copyright$
 
 [endsect]
-"""
-
-if docs=='qb+doxyref':
-    content+="""
-[xinclude $template_library$_doxygen.xml]
-"""
-
-template.submit_content(content)
+""")
 
Modified: sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/doc/Jamfile.v2.py
==============================================================================
--- sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/doc/Jamfile.v2.py	(original)
+++ sandbox/template_under_construction/sandbox/$template_library$/libs/$template_library$/doc/Jamfile.v2.py	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -6,10 +6,9 @@
 # http://www.boost.org/LICENSE_1_0.txt)
 
 docs = template.options.get('docs')
-doxygen = docs != 'qb'
-    
+doxygen = docs != 'qb'    
 
-content = """$template_start$
+template.append_content("""$template_start$
 $template_python_copyright$
 
 project boost/$template_library$/doc ;
@@ -20,13 +19,29 @@
 local loc = [ path.native [ path.pwd ] ] ;
 local root = [ path.native [ path.join [ path.pwd ] ../../.. ] ] ;
 
-xml $template_library$_xml : $template_library$.qbk ;"""
+xml $template_library$_xml : $template_library$.qbk ;""")
+
+doxy_source_files = list()
+for root, dirs, files in results.walk(
+    # we want the returned root to be relative to $template_library$
+    template.replace_name('$template_library$'),
+    # and want to walk the boost/$template_library$ directory underneath that
+    template.replace_name('boost/$template_library$')):
+    if os.path.basename(root) != 'detail':
+        doxy_source_files.append(
+            template.replace_name(os.path.join(os.path.join('../../..',
+            root), '*.hpp').replace('\\','/')))
+
+if docs=='qb+doxy':
+    doxy_source_files.append('dox/*.hpp')
 
 if doxygen:
-    content += """
+    template.append_content("""
 doxygen $template_library$_doxygen
    :
-      [ glob ../../../boost/$template_library$/*.hpp dox/*.hpp ]
+      [ glob
+             """ + """
+             """.join(doxy_source_files) + """ ]
    :
         <doxygen:param>EXAMPLE_PATH=../example
         <doxygen:param>STRIP_FROM_PATH=$(root)
@@ -39,26 +54,26 @@
         <doxygen:param>MACRO_EXPANSION=YES
         <doxygen:param>SEARCH_INCLUDES=YES
         <doxygen:param>INCLUDE_PATH=../../..
-        <doxygen:param>PREDEFINED=DOXYGEN_DOCS_ONLY"""
+        <doxygen:param>PREDEFINED=DOXYGEN_DOCS_ONLY""")
 
     if docs=='qb+doxy':
-        content += """
+        template.append_content("""
         <doxygen:param>GENERATE_HTML=YES
         <doxygen:param>HTML_OUTPUT=$(loc)/html/doxygen
-        <doxygen:param>HTML_STYLESHEET=$(loc)/html/boostbook_doxygen.css"""
-    content +="""
+        <doxygen:param>HTML_STYLESHEET=$(loc)/html/boostbook_doxygen.css""")
+    template.append_content("""
    ;
-"""
+""")
 
-content += """
+template.append_content("""
 boostbook standalone
    :
-      $template_library$_xml"""
+      $template_library$_xml""")
 if (doxygen):
-    content+="""
-      $template_library$_doxygen"""
+    template.append_content("""
+      $template_library$_doxygen""")
 
-content +="""
+template.append_content("""
     :
         <xsl:param>chunk.first.sections=1
         <xsl:param>chunk.section.depth=3
@@ -66,6 +81,5 @@
         <xsl:param>toc.max.depth=3
         <xsl:param>generate.section.toc.level=3
     ;
-"""
+""")
 
-template.submit_content(content)
Modified: sandbox/template_under_construction/sandbox/sandbox.py
==============================================================================
--- sandbox/template_under_construction/sandbox/sandbox.py	(original)
+++ sandbox/template_under_construction/sandbox/sandbox.py	2007-05-29 16:47:41 EDT (Tue, 29 May 2007)
@@ -1,17 +1,15 @@
 # template script
 
-template.log_message('Processing Boost Sandbox template.')
-
-template.template_root = 'sandbox/'
-template.template_dir = '$template_library$'
-
-library_name = template.options.get('library', template.options.alnum, None,
-    'library name (all lowercase, use underscores to separate words, e.g. "my_library"): ')
 # Copyright 2007 Stjepan Rajko.
 # Distributed under the Boost Software License, Version 1.0.
 # (See accompanying file LICENSE_1_0.txt or copy at
 # http://www.boost.org/LICENSE_1_0.txt)
 
+log.message('Welcome to the Boost Sandbox template.')
+
+library_name = template.options.get('library', template.options.alnum_lowercase, None,
+    '(all lowercase, use underscores to separate words, e.g. "my_library"): ')
+
 library_name_list = library_name.split("_")
 library_name_list_capitalized = list()
 for item in library_name_list[:]:
@@ -26,7 +24,7 @@
 """
 
 author_list = template.options.get('author', template.options.any, None,
-    'list of authors (comma separated, no spaces outside names, e.g., "My Name,Notmy R. Name": ')
+    '(comma separated, no spaces outside names, e.g., "My Name,Notmy R. Name": ')
 author_reversed = list()
 for name in author_list.rsplit(','):
     first_space_last = name.rpartition(" ")