Akyn: синтаксис (переменные)

Как я уже писал, несколько дней назад я заменил шаблонизатор на своём сайте на новый. Вы просили, чтобы я рассказал как он устроен, я постараюсь. Сразу, едином наскоком у меня это сделать не получилось, поэтому я решил попробовать сделать это по частям. Начну с синтаксиса. Сразу скажу, что в будущем мне хотелось бы кое-что в нём изменить.

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

Шаблонизатор работает с файлами (у меня на сайте всё работает на файлах), в простейшем случае файл содержит одни шаблон, в более сложном — несколько секций шаблона. Секции записываются между двумя тегами комментария с именем секции внутри (обратите внимание на закрывающий тег):

<!--имя секции-->
HTML-код секции
<!--/имя секции-->

Самое простое, что есть в шаблоне — переменные. Они записываются как {$name}. Переменная уникальна в своей секции или шаблоне (если шаблон без секций). Установить переменную можно присвоив шаблону свойство с её именем. У меня открытие шаблона сделано в глобальном toolkit и всё описанное выглядит вот так:

$t = rt::t('menu', 'меню сверху');
$t->link = '/';
echo $t;

В данном примере в секции «меню сверху» шаблона «menu» переменной link я присвоил значение ’/’. Шаблон выполнится при любом преобразовании объекта в string (например, когда я сделаю echo). Если переменной присвоить null, то атрибут тега, в котором она находится пропадёт. А если переменная входит в тег, то удалится сам тег. В следующем шаблоне, если я присвою переменной «hide» null, пропадёт тег «b» и атрибут title тега «a»:

<a href="/" title="{$hide}"><{$hide}b>текст<{$hide}/b>

Минимальная логика, которая есть в шаблоне на данный момент — возможность подстановки значения переменных из списка и отрицание переменной. Выглядит это вот так: {$var?value1?value2?value3}, значений valueN может быть сколько угодно, нумерация начинается с нуля, значения выбираются по номеру (для тех кто в теме — и по модулю длины выбираемой последовательности). Пустое значение считается null-значением, со всеми его свойствами, которые я рассмотрел выше.

Частный случай такой конструкции — конструкция {$!var}, которая на значение эквивалентное false вернёт пусто (не null), а на значение эквивалентное true — null.

Эта условная конструкция полезна шаблону тем, что позволяет сосредоточить максимум данных о шаблоне в самом шаблоне, например, в циклических конструкциях туда можно поместить имена стилей, которые должны применяться. Отрицание полезно в случаях подобных этому:

<{$hide}b><{$!hide}i>Текст<{$!hide>/i><{$hide}/b>

тут, в зависимости от состояния переменной hide, появится либо тег «b», либо «i».

Переменные подставляются в момент выполнения шаблона, так что иметь значение будет последнее выставленное значение.

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

Читайте также

Акын: блоки
Я тут, если помните, принялся описывать свой шаблонизатор «Акын», многие просили. Сейчас попробую продолжить.
2008
PythonFuck: разбор
Как я писал в конце прошлого года, есть такое развлечение — не используя алфовитно-цифровые символы, писать осмысленные программы на разных языках программирования. Для конкретного языка это называется «имя языка»+«Fuck».
2020

Комментарии 44

lusever.ru № 1
Этакая смесь phpBB и smarty.
web.moikrug.ru № 3
А джанговский (djangoproject.com) шаблонный движок вы не смотрели?

Так же как джанго и питон делают php и абсолютно любые существующие фреймворки на нем — куском говна, так же и джанговский шаблонизатор кхм… интересен.
unamentem.ya.ru № 5
yet another template language. Хотел дать ссылку на статью о том, почему _не нужно_ писать энжайны шаблонов (особенно на пхп), да потерял. Ну и бог с ней.
Евгений Степанищев (bolknote.ru) автор № 10
Комментарий для lusever.ru:

Т.е. у меня секции делаются HTML-комментарием, а в phpBB «циклы тоже» делаются HTML-комментарием? Вы мою статью-то читали?
Alisey (alisey.myopenid.com) № 13
Мне нравится Haml.
Идея в том, чтобы объединить HTML и язык шаблона в единый, более удобный язык, в котором не будет ни визуального шума HTML, ни синтаксической «разности импедансов» между языком шаблона и XML-подобной разметкой.

http://en.wikipedia.org/wiki/Haml
Евгений Степанищев (bolknote.ru) автор № 14
Мне нравится скорость обработки. И я не понимаю зачем нужен голый HTML, если всё равно не видно как это выглядит. Например, циклы не видны.
Alisey (alisey.myopenid.com) № 15
Комментарий для Евгения Степанищева:

Мне тут прекрасно виден цикл:

#content
 — @entries.each do |entry|
.entry
%h3.title= entry.title
%p.date= entry.posted.strftime(«%A, %B %d, %Y»)
%p.body= entry.body

Шаблонизаторы пишутся для удобства программирования и чтения, а не для того чтоб ускорить код. Ну а скорость — это OCalm, C, ассемблер в конце концов.
Евгений Степанищев (bolknote.ru) автор № 16
Комментарий для alisey.myopenid.com:

Он не виден в HTML, поэтому я не понимаю зачем мне нужен язык шаблонизатора, который выглядит как HTML.

Шаблонизаторы пишутся для того, чтобы было удобно менять оформление сайта. Если шаблонизатор был написан так, что он тормозит у меня на shared-хостинге, я его использовать не буду.
Alisey (alisey.myopenid.com) № 17

Комментарий для Евгения Степанищева:

Если шаблонизатор был написан так, что он тормозит у меня на shared-хостинге, я его использовать не буду.

Вы утверждаете что Haml тормозит на Shared-хостинге? По моему это такое же голословное утверждение, как если бы я сказал что не тормозит.
И, если это сразу не было понятно, я говорил только про синтаксис. Ваша заметка про синтаксис, правильно?

Замечание про «язык шаблонизатора, который выглядит как HTML» я не понял.

astur (astur.net.ru) № 18
Комментарий для lusever.ru:

Бессмысленно сравнивать этот Akyn со Smarty. Они же для совершенно разных ситуаций.
Smarty предполагает ситуацию, когда верстальщик и программер — это два абсолютно разных человека, один из которых боится увидеть код PHP, а другого уже тошнит от HTML. Ради такой заточки в Smarty стольким пожертвовано, что просто ужат. Smarty  — это круто, когда сайт ведут между делом, на бегу, а когда сайт тщательно и вдумчиво сопровождает специалист, все плюсы Smarty становятся минусами.
Евгений Степанищев (bolknote.ru) автор № 19
Как человеку, знакомому с PHP, мне Smarty кажется куда более страшным языком программирования (а не шаблонизации), чем PHP :)
unamentem.ya.ru № 20
Комментарий для alisey.myopenid.com:

Alisey, Haml — это какой-то извращённый еРуби, собственно уши рельс там во всех мантрах видны.
Одно дело, когда язык программирования эмбедят в хтмл шаблоны (когда эмбедят пхп в язык шаблонов пхп — это к Болку хехе), но когда парадигму эмбеднутого руби переносят в отдельный темплейт язык, который потом переносят в другие языки — это какой-то совершенный анальный мазохизм. Особенно если учесть, что руби — ну никак не самый лучший пример для подражания.
Alisey (alisey.myopenid.com) № 21
Комментарий для unamentem.ya.ru:

Ваши «доводы» сводятся к тому, что Haml говно и Руби говно. Какие-то нифига не убедительные доводы, спробуйте ще.
Alisey (alisey.myopenid.com) № 22
Конструкция Текст/i> не очень хорошо читается.
Проблема с ней в том, что $hide — по сути одно условие. А в коде это 4 отдельных условия.

У подхода есть и хорошая сторона, но плохая, на мой взгляд перевешивает.
Евгений Степанищев (bolknote.ru) автор № 23
Комментарий для alisey.myopenid.com:

Да, знаю, что не очень хорошо, именно её и хочется изменить, но пока не знаю как.
unamentem.ya.ru № 24
Комментарий для alisey.myopenid.com:

Руби не говно, просто он, мягко говоря, «слабо логичен». Например, параноидально классифицируя и объектно-ориентируя всё вокруг, запросто засовывает типичный функциональный код в notoriously известный метод inject. И не слушает заветы старого лингвиста Ларри Уолла: мы не будем совать в языковые примитивы «предложения» — пишите их сами. Haml же — карго-культ вокруг рельсов, которые построены на карго-культе языка руби. Ещё более смешными выглядят попытки «портирования» этого «руби-независимого еРуби» в языки типа PHP, т.е. заточеные _СПЕЦИАЛЬНО_ для эмбеда кода в шаблоны.
Евгений Степанищев (bolknote.ru) автор № 25
Комментарий для alisey.myopenid.com:

Данное условие отражает недостаки Akyn — HTML не парсится, значит найти парный тег невозможно.
unamentem.ya.ru № 29
Я в курсе про наличие там тернари оператора, но учить премудрости пхп в своё время не стал (слава богу).

Вот смотри, какое количество минусов в таком куске кода. Во-первых, текст мы пишем два раза — отстой. Ду нот репит ёселф, блаблабла. Следовательно, тебе нужно что-то рубевского блока или кложуры из других языков (далее идёт псевдокод): Текст

Но мы опять повторяемся. Во-первых, дважды впрыскиваем текст, во-вторых, сам бог велел создать хтмл с повторением тэга, т.е. оборачивающим наш текст. Логично написать так: Текст

Фактически, это уже тот самый каргокульт еруби/хамла, потому что от рельсов его почти ничего не отличает. Основная проблема же этого куска — это не хтмл. Проблема номер два — не дай бог нам потребуется добавить атрибут тагу — нужно переписывать хелпер, чтобы он понимал атрибуты.

Чё я хотел сказать-то. В основе любого энжайна темплейтов должна лежать парадигма. Идеология. Практическая задача, требующая уникального решения. В чём парадигма твоего акына?
vomixamxam (vomixamxam.ya.ru) № 30
Коллега, у меня есть шаблонизатор, который развивает твою идею — шаблон вообще не содержит логики, весь HTML содержится в шаблонах и остаётся валидным HTML'ем для IDE и браузеров. Хочу тебе его показать. А? )
alexeit.myopenid.com № 31
Комментарий для Евгения Степанищева:

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

пример: я не хочу на уровне кода думать как отобразить список страниц. это не моя проблема как разработчика бизнесс логики. я говорю шаблону что всего страниц 20, сейчас открыта страница номер 7, ссылка на страницу следующая " http://example.com/users.php?page=%22. дальше шаблон уже сам думает или нарисовать это вот так
12 … 6[7]8 … 19 20, или сделать дропдаун, или сделать 1 next >.

есть огромная куча логики которую я помещаю в шаблоны. логики связанной с внешним видом страницы.

сам использую php -> xml * xslt -> html

ps: где-то пол года ждал когда же я смогу тут комментировать используя мой хитрый юзернейм из ЖЖ (_alexei_). не работает поддержка таких open id у тебя. сколько раз уже хотел прокоментировать, но забивал, сегодня решил сделать наконец простой open id.
Евгений Степанищев (bolknote.ru) автор № 34
Если вам нужен язык шаблонов, поддерживающий математику, логику и т.д., могу порекомедовать PHP, Perl, Ruby, мне очень нравится Python.

Твой хитрый username должен работать: меня иногда комментирует _dofin_, всё ок.
alexanderich.livejournal.com № 35
Наверное и сейчас зажигают костры трением со спичками в кармане, те, кому так удобней. Пардон, за иронию.
Евгений Степанищев (bolknote.ru) автор № 36
Рассматривать надо задачу, а не сферического коня в вакууме. Вы же исходите из каких-то своих знаний о моей задаче.
unamentem.ya.ru № 37
Комментарий для Евгения Степанищева:

Болк, так не видно задачи. Есть какие-то рамки, которые выглядят условными — «хочу чтобы мининимум логики». Что такое минимум логики? Почему минимум такой, а не такой? Почему не использовать минимум логики, меняя CSS, например?
Я привёл пример такой логики выше, а не ушёл в сторону. Ты же рассказываешь, как у тебя хитро (но не совсем правильно) работаю в акыне переменные. Вопрос в том, нахрена они вообще?! И почему только переменные? Почему не циклы? Не обычные условия? (Ты ведь даже в своём примере очень криво пытаешься имитировать условие if-then, при этом не признаваясь в себе, что ты, в виду условных рамок, под переменными подразумеваешь в том числе и условный оператор, хоть и крайне неудобный — внятно изложил?)
Евгений Степанищев (bolknote.ru) автор № 38
Комментарий для unamentem.ya.ru:

Давай я до конца всё изложу, а там посмотрим какие вопросы возникнул. Я же объяснил — это первая часть изложения.
rin-nas.moikrug.ru № 39
Самая здравая мысль была здесь: /all/1929#n5228
Через некоторое время использования самописного шаблонизатора приходит понимание (скорости, гибкости и возможножностей уже не хватает), что лучший шаблонизатор -- это сам PHP, если уметь его грамотно использовать.
Несколько лет тому назад я показал, как это можно делать в шаблонизаторе PHPTemplate: http://forum.dklab.ru/viewtopic.php?t=16364
Евгений Степанищев (bolknote.ru) автор № 41
Мне удобно живётся со своим шаблонизатором, я его никому не навязываю. Люди попросили показать что там у меня, я показываю. Обсуждать что-то тут нет никакого смысла, разве что в пределах концепции почему так, а не иначе, но не саму концепцию.
rin-nas.moikrug.ru № 42

Комментарий для Евгения Степанищева:

Евгений, пусть кажый пользуется тем, что ему удобнее :)

Если переменной присвоить null, то атрибут тега, в котором она находится пропадёт. А если переменная входит в тег, то удалится сам тег.

Некоторые мысли в пределах вашей концепции. :)
В прошлом я делал шаблонизатор (похожий на ваш), специально заточеный под HTML -- он автоматически квотирует значения, в зависимости от контекста, обрабатывает условные блоки и даже умеет вставлять и вырезать параметры из URL! Вместо проверки на null у меня идет проверка конструкцией strval($value) === '' (удобно использовать значения из $_REQUEST, получается, что '', null и false это одно и тоже), а для условного парсинга тага используется служебный атрибут if. Парные таги вместе с содержимым (блоки) вырезаются/невырезаются с помощью служебного атрибута @if в парном таге. На практике пользоваться такой штукой оказалось очень удобно, но пришлось отказаться и вернуться к PHP, т.к. скорость меня не устроила.

rin-nas.moikrug.ru № 44
Я посмотрел сегодня свои исходники -- с состоянием NULL я слукавил. :)
Поведение для удаления атрибута тага / параметра URL у меня такое же -- удаляется только для NULL. Иначе невозможно послать на сервер пустое значение из поля ввода формы, что неправильно.