YHTML-Template

YHTML-Template — это переносимая Коммон Лисп библиотека, базирующаяся на исходном коде HTML-TEMPLATE Эдмунда Вайца (Edi Weitz). С её помощью работающая программа "наполняет" текстовые шаблоны конкретным содержанием. Является ли фактический результат текстом в формате HTML или нет, неважно. Хотя в основном, библиотека используется именно для генерации HTML.

Поскольку прототипом послужил модуль Перл HTML::Template (см. также в Википедии), в части синтаксиса шаблонов обе библиотеки имеют немало общего. Похожий синтаксис шаблонов применяются и в phpBB — популярном пакете для создания форумов.

Исходный код библиотеки-прототипа и документация на английском находятся здесь http://weitz.de/html-template/. В YHTML-Template в этот код с доработан с целью придать синтаксису больший "Лисп-оттенок". Внесены также новые конструкции, см. ниже.

YHTML-Template сочетает возможности двух типов шаблонов.

Активный (pull) шаблон
Внутри шаблона может быть код, извлекающий данные нетривиальным путем.
Пассивный (push) шаблон
Файл шаблона можно открывать в браузере или любом редакторе HTML.

Пример шаблона

<html>
<head><title><!-- TMPL_EVAL title --></title></head>
<body>
  <p>Вывод списка:</p>
  <ul>
  <!-- TMPL_LOOP items -->
    <li><!-- TMPL_EVAL item --></li>
  <!-- TMPL_LOOPELSE -->
    <li>(нет данных)</li>
  <!-- /TMPL_LOOP items -->
  </ul>
</body>
</html>

Стандартный синтаксис шаблона

Стандартный синтаксис псевдотегов шаблона выглядит словно комментарий HTML.
Открывающий тег:   <!-- TMPL_tag form... ; comment -->
Закрывающий тег:   <!-- /TMPL_tag comment -->

form
Форма (S-выражение) языка Лисп с ограниченным набором допустимых специальных операторов; макросы недопустимы вообще. Большинство псевдотегов воспринимают только одну форму. В качестве её значения может выступать объект Лисп определённого типа. Например, в псевдотегах TMPL_FOR, TMPL_LOOP и TMPL_CALL допустима последовательность, т.е. список или вектор.
comment
Произвольный текст комментария, тянущийся вплоть до завершающего маркера -->.

Достоинства и недостатки

Возможность HTML::Template HTML-TEMPLATE YHTML-Template phpBB
Получение значения переменной дададада
Присваивание значения переменной нетнетданет
Обращение напрямую к полям структур, вызов функций и методов нетнетдада
Цикл по списку или массиву for/foreach/dolist дададада
Цикл по счётчику repeat/dotimes нетдаданет
Вложение шаблонов дададада
Передача параметров в подшаблон нетнетданет

Загрузка исходных текстов

Исходные файлы доступны в любом из дистрибутивов:

Инструкции по развёртыванию находятся в файле INSTALLATION.TXT (на английском языке).

Отличия от HTML-TEMPLATE

  1. HTML-TEMPLATE допускает в псевдотегах единственный "атрибут" — строку, возможно, ограниченную одинарными (') или двойными (") кавычками. Напротив, в YHTML-Template такой синтаксис применяется лишь для открывающего псевдотега TMPL_INCLUDE, а в остальных местах допустимы произвольные формы Лисп, считываемые стандартной функцией read.
    HTML-TEMPLATE в качестве шаблонных переменных предлагает ключи, т.е. символы пакета keyword; поскольку с точки зрения идеологии Лисп ключи являются константами, их использование в качестве переменных семантически неадекватно.
  2. Символы внутри форм шаблона подчиняются стандартному синтаксису Лисп: перед печатным именем символа допустимо имя пакета. По умолчанию символы включается в пакет *template-package* (новая специальная переменная).
  3. Формы шаблона интерпретируются во время исполнения программы посредством новой функции template-eval. Она оценивает выражения, аналогично стандартной функции eval, но в упрощённом варианте:
  4. Новый псевдотег TMPL_EVAL, предназначенный в качестве замены TMPL_VAR, для него реализована новая функция подстановки create-eval-printer.
    TMPL_VAR поддерживается для совместимости.
  5. Расширено множество возможных значений переменной *format-non-strings*. Если оно есть T, подставляемый текст формируется из объекта, как и прежде, с помощью princ-to-string, т.е. (format nil "~A" ...).
    Если значение есть истина, но не равно T, оно должно быть функцией с единственным параметром и двумя возвращаемыми значениями:
    (1) строка, полученная из аргумента и представляющая окончательный или промежуточный текст,
    (2) признак "не-модифицировать", указывающий, применять ли к первому значению функцию *string-modifier*.
    Истинное второе значение "защищает" первое значение от дальнейшего конвертирования, например, замену литер на escape-последовательности. Первое значение в этом случае выступает как окончательный результат (полезно, когда внутри программы это значение вычисляется из определённого формата, например, из LHTML).
  6. Новый псевдотег TMPL_ELIF позволяет писать более короткие шаблоны. Полный синтаксис "условного оператора" теперь такой:
    <!-- TMPL_IF condition_1 -->
    body_1
    <!-- TMPL_ELIF condition_2 -->
    body_2
     ...
    <!-- TMPL_ELSE -->
    else_body
    <!-- /TMPL_IF -->
  7. Новый псевдотег TMPL_LOOPELSE позволяет указать текст выдаваемый когда длина аргумента-последовательности, по которому идёт цикл, равна нулю.
    <!-- TMPL_LOOP sequence -->
    body_1
    <!-- TMPL_LOOPELSE -->
    else_body
    <!-- /TMPL_LOOP -->
  8. Новый псевдотег TMPL_FOR реализует цикл общего вида. Он моделирует специальные операторы Коммон Лисп dolist, dotimes и loop for across.
    <!-- TMPL_FOR var sequence-or-integer -->
    body
    <!-- TMPL_FORELSE -->
    else_body
    <!-- /TMPL_FOR -->
  9. Новый псевдотег TMPL_LET, связывающий динамические переменные с произвольным значением подобно специальные оператору let Коммон Лисп.
    <!-- TMPL_LET { var1 | (var1 expr1) } ... -->
      body
    <!-- /TMPL_LET -->
  10. Расширен синтаксис псевдотега TMPL_INCLUDE:
    <!-- TMPL_INCLUDE filename [(var expr)] ... -->
    Это позволяет передавать аргументы при вызове подшаблона.
    Вдобавок вызов (create-template-printer pathname) происходит во время прогона внутри лексического замыкания, созданного вызывающим принтером, и изменение файла pathname приводит к его повторной компиляции, так как дата в кэше сопоставляется с датой, возвращённой file-write-date.
    (Оригинальная версия возвращала замыкание, созданное в момент компиляции вызывающего шаблона и проверка на up-to-date не производилась, а значит, изменение файла подшаблона не приводило к его перекомпиляции.)
  11. Новая специальная переменная *ignore-tag-rest* контролирует, допустим ли перед маркером "-->" произвольный текст.
    Когда значение есть истина (умолчание), текст может быть помещён Примеры:
       <!-- TMPL_EVAL (+ row-number 1) Increase by one -->
       <!-- TMPL_FOR var '(1 2 3) ; Loop over items -->
       <!-- /TMPL_LOOP ; rows -->
    Указанный текст служит для улучшения читабельности шаблона и игнорируется анализатором. Дело вкуса — начинать такой текст с точки запятой (;).
    Когда значение переменной *ignore-tag-rest* есть ложь, анализатор, обнаружив "лишние" аргументы, сигналит об ошибке.
  12. Новая специальная переменная *ignore-comments* контролирует удаление комментариев, заключённых в <!--...-->, в том числе нераспознанных шаблонных тегов, из результирующего HTML-кода.
    Пример:
     (let ((*ignore-comments* t))
       ... "The <!-- comment --> brown fox" ...)
      => "The  brown fox"
     

Режим совместимости с HTML-TEMPLATE

Чтобы работать в YHTML-Template с шаблонам в синтаксисе HTML-TEMPLATE, проделайте следующее.

  1. Установите значение новой специальной переменной *attributes-are-lisp-forms* равным NIL.