Перейти к основному содержимому

Структура конфигурации

Любой конфиг TDC — это один корневой элемент <tdc>. Внутри него живут две вещи: необязательный <env> (параметры генерации, последовательности и фикстуры) и обязательный <block> (макет каждой выходной карточки).

<tdc version="0.1.0" comment="демо-конфиг">
<env count="5" seed="demo">
<sequence name="Id">
<gen type="increment" value="1"/>
</sequence>
</env>
<block>
<line><data>id=${{Id}}</data></line>
</block>
</tdc>
./run demo.tdc
id=1
id=2
id=3
id=4
id=5

<block> отработал ровно count="5" раз; на каждой итерации ${{Id}} брал следующее значение последовательности Id (см. последовательности).

Вывод приведён для наглядности

Терминальный вывод на этой странице — это примеры, и конкретные значения могут отличаться в зависимости от версии ядра. Стабильна форма: фиксированный seed воспроизводит те же самые карточки байт в байт (см. детерминизм).

<tdc> — корень

<tdc> ровно один, и только как корень. Документ без корневого <tdc> завершается ошибкой error[TDC001]: document has no <tdc> root element. Он содержит необязательный <env> (о нём ниже) и обязательный <block>.

АтрибутОбязательныйЧто делает
version / vнетМинимальная версия DSL, которую требует файл
regex_max_lengthнетГлобальный лимит длины для type="regex"
commentнетСвободный комментарий, который движок игнорирует

version (алиас v)

Объявляет минимальную версию DSL, на которую рассчитан файл. Если version — или его короткий алиас v — выше версии работающего движка, файл сразу отклоняется: более новый DSL может использовать генераторы, условия или синтаксис, которых старый движок не понимает, а молча выдать неверные данные хуже, чем остановиться. Используйте атрибут, когда конфиг опирается на возможность, добавленную в конкретном релизе, и вам нужна понятная ошибка на устаревшем движке, а не запутанная.

<tdc version="9.9.9">
<block><line><data>hello</data></line></block>
</tdc>
./run future.tdc
error[TDC005]: TDC document version "9.9.9" is newer than this runtime (0.1.0)
note: Update TDC before processing this file; newer DSL features may not exist in this runtime.

Версию можно и не указывать — это разрешено для совместимости со старыми конфигами.

regex_max_length

Глобальный потолок (по умолчанию 32) на длину, которой может достичь любой результат type="regex". Паттерн, способный его превысить, отклоняется до генерации, так что один разросшийся квантификатор не сможет тихо выдать по мегабайту на строку. Задайте атрибут на <tdc>, когда несколько длинных паттернов делят один конфиг и вам нужно единое место, где можно поднять потолок.

<tdc regex_max_length="64">
<env count="3" seed="demo">
<sequence name="Token"><gen type="regex" value="[A-Z0-9]{40}"/></sequence>
</env>
<block>
<line><data>${{Token}}</data></line>
</block>
</tdc>
./run token.tdc
MURI40FXS16A2ABROOBQFGMSDBLWP3TCDTA16VVK
NPJ3PVSU1NGARTRDQHT92IHGWJZVUST4531IOEAW
66WWVKTAA2XWUQJBJA8P0SNZ6W3Q75R3CP12JIXW

Без поднятого потолка тот же паттерн падает ещё до того, как сгенерирована первая строка, — потолок по умолчанию равен 32:

./run token.tdc (без regex_max_length)
error[TDC097]: invalid regex generator pattern: regex can produce 40 characters, which exceeds regex_max_length=32
--> token.tdc:3:57
|
3 |         <sequence name="Token"><gen type="regex" value="[A-Z0-9]{40}"/></sequence>
|                                                         ^^^^^^^^^^^^
|
note: Use finite regex: bounded quantifiers such as {n} or {n,m}; unbounded *, +, and {n,} are rejected.

aborted: 1 error

Ограничение лишь позволяет уже конечному результату быть длиннее — оно никогда не делает бесконечный паттерн конечным. Полный разбор — на странице генератора regex.

comment

Свободная заметка для того, кто читает конфиг. Движок полностью её игнорирует — она никогда не попадает в вывод. Используйте её, чтобы записать, для чего нужен файл, или кто за него отвечает.

<tdc comment="стартовые аккаунты для импорта в staging">
<env count="2" seed="demo">
<sequence name="Id"><gen type="increment" value="100"/></sequence>
</env>
<block><line><data>acct-${{Id}}</data></line></block>
</tdc>
./run accounts.tdc
acct-100
acct-101

<block> обязателен

<block> описывает макет одной карточки и — единственный дочерний тег, без которого <tdc> не может обойтись. Конфигу с <env>, но без <block> нечего рендерить:

./run no-block.tdc
error[TDC002]: <tdc> has no <block> child — nothing to render

<env> — параметры, последовательности, фикстуры

<env> (сокращение от environment) хранит параметры генерации, объявления последовательностей и фикстуры — текст, который печатается до, после или между карточками. Тег необязателен: если нужно лишь повторить одну фиксированную строку count раз, его можно опустить. Но как только понадобились последовательности, параметры или фикстуры, они все живут здесь.

АтрибутПо умолчаниюЧто задаёт
count10Сколько карточек генерировать
seedслучайныйСид генератора случайных чисел
localenЛокаль для данных type="template"
inject${{%}}Шаблон интерполяции значений
commentСвободный комментарий, который движок игнорирует
Переопределения из CLI побеждают

--count, --seed и --locale в командной строке переопределяют значения из <env>, так что один и тот же файл может выдавать разные объёмы данных. См. справочник по CLI.

count

Сколько раз рендерится <block> — по одной карточке на итерацию. По умолчанию 10. Задавайте его, чтобы определить размер набора данных; переопределяйте для конкретного запуска через --count, когда нужно быстро прогнать 3 строки на дым из конфига, который обычно выдаёт тысячи.

<env count="3" seed="demo">
<sequence name="Id"><gen type="increment" value="1"/></sequence>
</env>
./run ids.tdc
id=1
id=2
id=3

Для большинства генераторов короткий прогон — честный префикс длинного: первые три строки при count="3" совпадают с первыми тремя при count="1000". Исключения (макеты с точными пропорциями и уникальностью) разобраны в детерминизме и пропорциях.

seed

Фиксирует генератор случайных чисел, делая конфиг воспроизводимым: один и тот же сид и один и тот же конфиг всегда дают ровно те же карточки. Используйте его всякий раз, когда набор данных должен быть стабильным — снапшот-тест, общая фикстура, воспроизведение бага. Опустите его — и каждый запуск будет новым; вы теряете возможность воспроизвести конкретный вывод.

<env count="3" seed="demo" local="en">
<sequence name="Name"><gen type="template" value="person.male.firstName"/></sequence>
</env>

Запустите дважды — байт в байт одинаково:

./run names.tdc (запуск 1 | запуск 2)
James      James
Robert     Robert
Michael    Michael

Смените сид — получите другой, но столь же стабильный набор. Полная история, включая межъязыковую гарантию, — в детерминизме и пропорциях.

local — локаль данных

Задаёт локаль, которую использует генератор template, когда подбирает имена, города и прочие локализованные данные. По умолчанию en, так что примеры выше дают английские имена без дополнительной настройки.

<env count="3" seed="demo" local="en">
<sequence name="Name"><gen type="template" value="person.male.firstName"/></sequence>
</env>
./run names.tdc (local=en)
James
Robert
Michael

Переключение локали — вот что заставляет тот же макет выдавать данные на другом языке: это демонстрация локализации. С local="ru" тот же самый конфиг берёт данные из русского набора имён:

./run names.tdc (local=ru)
Иван
Пётр
Алексей

Меняются только данные — структура, поведение сида и всё остальное остаётся тем же. Какие локали доступны, зависит от установленных пакетов данных.

inject — маркер интерполяции

Задаёт токен, который отмечает подстановку значения внутри <data>. По умолчанию ${{%}}, где % обозначает имя последовательности. Меняйте его, когда сам вывод должен содержать литеральное ${{...}} — генерация конфига CI, шаблона Handlebars или другого файла TDC, — чтобы ваши маркеры не сталкивались с маркерами цели. Строка должна содержать ровно один %.

<env count="2" seed="demo" inject="[%]">
<sequence name="Id"><gen type="increment" value="1"/></sequence>
</env>
<block>
<line><data>id=[Id]</data></line>
</block>
./run bracket.tdc
id=1
id=2

Меняется только синтаксис подстановки, но не данные. Подробнее об интерполяции — в выводе и форматировании.

comment

То же, что и на <tdc>: свободная заметка, которую движок игнорирует. Удобно, чтобы пояснить, почему выбран тот или иной seed или count, прямо там, где живут параметры.

Последовательности

<env> — это место, куда идут объявления <sequence>: каждое из них — именованный столбец значений, который подаётся в выходной блок. Им посвящена отдельная страница: Последовательности.

Фикстуры — текст вокруг карточек

Фикстуры — это текстовые слоты, которые печатаются вокруг сгенерированных карточек: заголовки, разделители и обёртки для отдельных строк. Они позволяют одному конфигу выдать целый файл — JSON-массив с его [ и ], CSV со строкой заголовка, — а не только голые карточки.

ФикстураПечатает
<before>Один раз, до всего прогона
<after>Один раз, после всего прогона
<before_block>Перед каждой карточкой
<after_block>После каждой карточки
<delimiter_block>Между карточками (но не после последней)
<before_line>Перед каждой строкой карточки
<after_line>После каждой строки карточки
<delimiter_line>Между строками карточки
<tdc>
<env count="3" seed="demo">
<before><line><data>[</data></line></before>
<after><line><data>]</data></line></after>
<delimiter_block><line><data>,</data></line></delimiter_block>
<sequence name="Id"><gen type="increment" value="1"/></sequence>
</env>
<block>
<line><data> {"id": ${{Id}}}</data></line>
</block>
</tdc>
./run array.tdc
[
{"id": 1}
,
{"id": 2}
,
{"id": 3}
]

[ и ] напечатались по одному разу, а запятая встала между карточками, но не после последней — валидный JSON. Одна оговорка: в фикстурах интерполяция не выполняется — они лежат вне итерации по карточкам, так что ${{...}} внутри фикстуры не подставляется. Детали на стороне карточек — в выводе и форматировании.

Порядок объявления важен

Дочерняя последовательность — та, у которой есть parent="…" — должна быть объявлена после своего родителя в <env>. Движок разрешает зависимости сверху вниз, так что дочерней последовательности, идущей первой, не против чего фильтровать. Полная модель — в иерархических зависимостях.

<env> нельзя писать самозакрывающимся

Запись <env … /> — это ошибка TDC014:

./run selfclose.tdc
error[TDC014]: <env> must not be self-closing — write <env> ... </env>

Это защита от бага с тихой потерей данных: самозакрывающийся <env> раньше терял и count, и seed, так что конфиг, просивший три карточки с сидом, молча выдавал десять на случайном сиде. Всегда используйте полную форму <env> … </env>.

Дальше