<?xml version="1.0"?>
<!--
SPDX-FileCopyrightText: Copyright The SCons Foundation (https://scons.org)
SPDX-License-Identifier: MIT
SPDX-FileType: DOCUMENTATION

This file is processed by the bin/SConsDoc.py module.
-->

<!DOCTYPE sconsdoc [
<!ENTITY % scons SYSTEM '../../doc/scons.mod'>
%scons;
<!ENTITY % builders-mod SYSTEM '../../doc/generated/builders.mod'>
%builders-mod;
<!ENTITY % functions-mod SYSTEM '../../doc/generated/functions.mod'>
%functions-mod;
<!ENTITY % tools-mod SYSTEM '../../doc/generated/tools.mod'>
%tools-mod;
<!ENTITY % variables-mod SYSTEM '../../doc/generated/variables.mod'>
%variables-mod;
]>

<sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">

<tool name="textfile">
<summary>
<para>
Set &consvars; for the &b-link-Textfile; and &b-link-Substfile; builders.
</para>
</summary>
<sets>
<item>LINESEPARATOR</item>
<item>SUBSTFILEPREFIX</item>
<item>SUBSTFILESUFFIX</item>
<item>TEXTFILEPREFIX</item>
<item>TEXTFILESUFFIX</item>
<item>FILE_ENCODING</item>
</sets>
<uses>
<item>SUBST_DICT</item>
</uses>
</tool>

<builder name="Textfile">
<summary>
<para>
The &b-Textfile; builder generates a single text file from
a template consisting of a list of strings, replacing text
using the &cv-link-SUBST_DICT; &consvar; (if set) -
see &b-link-Substfile; for a description of replacement.
The strings will be separated in the target file using the
value of the
&cv-link-LINESEPARATOR; &consvar;;
the line separator is not emitted after the last string.
Nested lists of source strings
are flattened.
Source strings need not literally be Python strings:
they can be Nodes or Python objects that convert cleanly
to &f-link-Value; nodes.
</para>

<para>
The prefix and suffix specified by the &cv-link-TEXTFILEPREFIX;
and &cv-link-TEXTFILESUFFIX; &consvars;
(by default an empty string and <filename>.txt</filename>, respectively)
are automatically added to the target if they are not already present.
</para>
<para>
By default, the target file encoding is "utf-8" and can be changed by &cv-link-FILE_ENCODING;
Examples:
</para>

<example_commands>
# builds/writes foo.txt
env.Textfile(target='foo.txt', source=['Goethe', 42, 'Schiller'])

# builds/writes bar.txt
env.Textfile(target='bar', source=['lalala', 'tanteratei'], LINESEPARATOR='|*')

# nested lists are flattened automatically
env.Textfile(target='blob', source=['lalala', ['Goethe', 42, 'Schiller'], 'tanteratei'])

# files may be used as input by wrapping them in File()
env.Textfile(
    target='concat',  # concatenate files with a marker between
    source=[File('concat1'), File('concat2')],
    LINESEPARATOR='====================\n',
)
</example_commands>

<para>Results:</para>

<para><filename>foo.txt</filename></para>
<screen>
  Goethe
  42
  Schiller
</screen>

<para><filename>bar.txt</filename></para>
<screen>
  lalala|*tanteratei
</screen>

<para><filename>blob.txt</filename></para>
<screen>
  lalala
  Goethe
  42
  Schiller
  tanteratei
</screen>

</summary>
</builder>

<builder name="Substfile">
<summary>
<para>
The &b-Substfile; builder creates a single text file from
a template consisting of a file or set of files (or nodes),
replacing text using the &cv-link-SUBST_DICT; &consvar; (if set).
If a set, they are concatenated into the target file
using the value of the
&cv-link-LINESEPARATOR; &consvar; as a separator between contents;
the separator is not emitted after the contents of the last  file.
Nested lists of source files
are flattened. See also &b-link-Textfile;.
</para>

<para>
By default, the target file encoding is "utf-8" and can be changed by &cv-link-FILE_ENCODING;
Examples:
</para>

<para>
If a single source file name is specified and has a <filename>.in</filename> suffix,
the suffix is stripped and the remainder of the name is used as the default target name.
</para>

<para>
The prefix and suffix specified by the &cv-link-SUBSTFILEPREFIX;
and &cv-link-SUBSTFILESUFFIX; &consvars;
(an empty string by default in both cases)
are automatically added to the target if they are not already present.
</para>

<para>
If a construction variable named &cv-link-SUBST_DICT; is present,
it may be either a Python dictionary or a sequence of
(<replaceable>key</replaceable>, <replaceable>value</replaceable>) tuples.
If it is a dictionary it is converted into a list of tuples
with unspecified order,
so if one key is a prefix of another key
or if one substitution could be further expanded by another substitution,
it is unpredictable whether the expansion will occur.
</para>

<para>
Any occurrences of a key in the source
are replaced by the corresponding value,
which may be a Python callable function or a string.
If the value is a callable, it is called with no arguments to get a string.
Strings are <emphasis>subst</emphasis>-expanded
and the result replaces the key.
</para>

<example_commands>
env = Environment(tools=['default'])

env['prefix'] = '/usr/bin'
script_dict = {'@prefix@': '/bin', '@exec_prefix@': '$prefix'}
env.Substfile('script.in', SUBST_DICT=script_dict)

conf_dict = {'%VERSION%': '1.2.3', '%BASE%': 'MyProg'}
env.Substfile('config.h.in', conf_dict, SUBST_DICT=conf_dict)

# UNPREDICTABLE - one key is a prefix of another
bad_foo = {'$foo': '$foo', '$foobar': '$foobar'}
env.Substfile('foo.in', SUBST_DICT=bad_foo)

# PREDICTABLE - keys are applied longest first
good_foo = [('$foobar', '$foobar'), ('$foo', '$foo')]
env.Substfile('foo.in', SUBST_DICT=good_foo)

# UNPREDICTABLE - one substitution could be further expanded
bad_bar = {'@bar@': '@soap@', '@soap@': 'lye'}
env.Substfile('bar.in', SUBST_DICT=bad_bar)

# PREDICTABLE - substitutions are expanded in order
good_bar = (('@bar@', '@soap@'), ('@soap@', 'lye'))
env.Substfile('bar.in', SUBST_DICT=good_bar)

# the SUBST_DICT may be in common (and not an override)
substutions = {}
subst = Environment(tools=['textfile'], SUBST_DICT=substitutions)
substitutions['@foo@'] = 'foo'
subst['SUBST_DICT']['@bar@'] = 'bar'
subst.Substfile(
    'pgm1.c',
    [Value('#include "@foo@.h"'), Value('#include "@bar@.h"'), "common.in", "pgm1.in"],
)
subst.Substfile(
    'pgm2.c',
    [Value('#include "@foo@.h"'), Value('#include "@bar@.h"'), "common.in", "pgm2.in"],
)

</example_commands>
</summary>
</builder>

<cvar name="LINESEPARATOR">
<summary>
<para>
The separator used by the &b-link-Substfile; and &b-link-Textfile; builders.
This value is used between sources when constructing the target.
It defaults to the current system line separator.
</para>
</summary>
</cvar>

<cvar name="SUBST_DICT">
<summary>
<para>
The dictionary used by the &b-link-Substfile; or &b-link-Textfile; builders
for substitution values.
It can be anything acceptable to the <function>dict()</function> constructor,
so in addition to a dictionary,
lists of tuples are also acceptable.
</para>
</summary>
</cvar>

<cvar name="SUBSTFILEPREFIX">
<summary>
<para>
The prefix used for &b-link-Substfile; file names,
an empty string by default.
</para>
</summary>
</cvar>

<cvar name="SUBSTFILESUFFIX">
<summary>
<para>
The suffix used for &b-link-Substfile; file names,
an empty string by default.
</para>
</summary>
</cvar>

<cvar name="TEXTFILEPREFIX">
<summary>
<para>
The prefix used for &b-link-Textfile; file names,
an empty string by default.
</para>
</summary>
</cvar>

<cvar name="TEXTFILESUFFIX">
<summary>
<para>
The suffix used for &b-link-Textfile; file names;
<filename>.txt</filename> by default.
</para>
</summary>
</cvar>

<cvar name="FILE_ENCODING">
<summary>
<para>
File encoding used for files written by &b-link-Textfile; and &b-link-Substfile;.
Set to "utf-8" by default.
</para>
<para>
<emphasis>New in version  4.5.0.</emphasis>
</para>
</summary>
</cvar>

</sconsdoc>
