Регистрация | Войти
Lisp — программируемый язык программирования
RSS
Новая версия cl-closure-template
archimag - 09.12.2012 14:15, Сообщений - 36
Привет,

Я в последнее время на CL практически не писал, но всё же у меня есть план и я ему следую (медленно). Первый шаг - привести cl-closure-template в более божеский вид. Я делал это время от времени и вот закончил важную стадию:
  • Переписан парсер, теперь для представления AST используются не s-выражения, а настоящие объекты
  • Соответственно, пришлось переписать практически всё (хоть работа и была не очень сложной)
  • Полностью переписан JavaScript-backend без использования parenscript.
Новая версия уже на github. У меня большая просьба, кто использует cl-closure-template - протестировать на своих проектах. В принципе, разницы в поведении быть не должно, всё работает также (за исключением небольшого отличия в обработке whitespaces, теперь она ближе к оригиналу, в большинстве случаев это не критично), но мало ли.

P.S. Недавно в библиотеку был добавлен python-backend, его пока пришлось отключить - необходимо адаптировать под новый формат AST.
[#]
LOR'ский комментатор новостей:

Ссылку надо бы добавить.
motopeh - 09.12.2012 15:06
[#]
Есть пара проблем.

Вот тут сломалось:
<div class="row{if not $category} no-toggle{/if}">

И не работает
(defmethod compile-template ((backend javascript-backend) (templates list))
Прозреваю что вместо namespace-map написан (namespace-name namespace).
andy128k - 09.12.2012 15:36
[#] Ответ на комментарий от andy128k 09.12.2012 15:36
Ещё

Error: TypeError: Math.length is not a function

Для кода
  {if $item.shared_by and length($item.shared_by)}
сгенерировало
    if (($env$.item["shared_by"] && Math.length($env$.item["shared_by"]))) {
andy128k - 09.12.2012 15:40
[#] Ответ на комментарий от andy128k 09.12.2012 15:36
> <div class="row{if not $category} no-toggle{/if}">

Хм, не могу воспроизвести:
(defvar *tmpl*
  "{namespace test} {template hello}<div class=\"row{if not $category} no-toggle{/if}\">{/template}"
)


(closure-template:compile-template :javascript-backend *tmpl*)
Получаю:
if (typeof test === 'undefined') { test = {}; }

test.$isEmpty$ = function (obj) {
    for (var prop in obj) if (obj.hasOwnProperty(prop)) return false;
    return true;
}
;

test.$escapeHTML$ = function (obj) {
    if (typeof obj == 'string') return String(obj).split('&').join('&amp;').split( '<').join('&lt;').split('>').join('&gt;').split('\"').join('&quot;').split('\'').join('&#039;');
    else return obj;
}
;

test.$round$ = function (number, ndigits) {
    if (ndigits) {
        var factor = Math.pow(10.0, ndigits);
        return Math.round(number * factor) / factor;
    
}

    else return Math.round(number)
}
;

test.$objectFromPrototype$ = function (obj) {
    function C () {}
    C.prototype = obj;
    return new C;
}
;

test.hello = function($env$, $target$) {
    if (!$env$) { $env$ = {}; }
    var $result$ = $target$ || [];

    $result$.push("<div class=\"row");
    if (!$env$.category) {
        $result$.push("no-toggle");
    
}

    $result$.push("\">");

    if (!$target$) return $result$.join('');
    else return null;
}
;
archimag - 09.12.2012 15:56
[#] Ответ на комментарий от archimag 09.12.2012 15:56
Можешь :)

У тебя тоже получается class="rowno-toggle" вместо class="row no-toggle"
andy128k - 09.12.2012 15:58
[#] Ответ на комментарий от andy128k 09.12.2012 15:58
> У тебя тоже получается class="rowno-toggle" вместо class="row no-toggle"

А, ну это как раз связано с изменение обработки whitespaces. Так и задумано. Вставь {sp} перед no-toggle.
archimag - 09.12.2012 16:06
[#] Ответ на комментарий от andy128k 09.12.2012 15:40
> Error: TypeError: Math.length is not a function

Fixed.
archimag - 09.12.2012 16:16
[#]
Спасибо; CL бэкенд в трёх проектах работает как раньше, JS не использовал, Python бы пригодился.
orivej - 09.12.2012 17:05
[#] Ответ на комментарий от orivej 09.12.2012 17:05
> Python бы пригодился.

Вообще, есть ещё такая вещь: https://github.com/archimag/python-closure-templates, парсер там только медленный, приходиться кэшировать (этого в либе нет).
archimag - 09.12.2012 17:30
[#] Ответ на комментарий от archimag 09.12.2012 17:30
> python-closure-templates

На тестовом шаблоне, с которым легко справляется версия на CL, parseNamespace (вызов lepl) уходит видимо в бесконечную рекурсию. Могу подготовить минимальный пример. Ещё версия на Python не поддерживает дефисы в именах шаблонов. И называется pyclosuretempALtes.
orivej - 09.12.2012 17:54
[#] Ответ на комментарий от orivej 09.12.2012 17:54
> parseNamespace (вызов lepl) уходит видимо в бесконечную рекурсию
> Могу подготовить минимальный пример

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

> Ещё версия на Python не поддерживает дефисы в именах шаблонов. 

Ну новая версия для JavaScript-backend-а тоже не поддерживает :) Вообще эта была такая вольность, по сравнению с оригинальной спецификацией. Для либы на Python в ней особого смысла нет. Я вообще подумал, что надо уходить от этого и делать всё строго как сказали, т.е. никаких дефисов.
archimag - 09.12.2012 18:08
[#] Ответ на комментарий от orivej 09.12.2012 17:54
Хотя нет: если убрать дефисы из всех имён, то парсер справляется и дальше шаблоны работают.
orivej - 09.12.2012 18:13
[#] Ответ на комментарий от archimag 09.12.2012 18:08
Я вообще подумал, что надо уходить от этого и делать всё строго как сказали, т.е. никаких дефисов.

Тогда ещё в CL-шаблонах нужно начинать все имена шаблонов с точки: "You must create a unique name for each template and begin the template name with a dot, which indicates that the template name is relative to the file's namespace."
orivej - 09.12.2012 18:30
[#] Ответ на комментарий от orivej 09.12.2012 18:30
> which indicates that the template name is relative to the file's namespace

Мне это сразу показалось каким-то дибилизмом.
archimag - 09.12.2012 18:32
[#] Ответ на комментарий от archimag 09.12.2012 18:32
Мне это сразу показалось каким-то дибилизмом.

Точно :)  Ну ладно, буду знать, что если python-closure-templates долго парсит шаблон, ошибка наверняка в шаблоне, и что для Python (и JS) нужно убирать дефисы.
orivej - 09.12.2012 19:22
[#]
Неожиданно :)
Мы тут вточили:
1. поддержку плагиновых директив для {print}.
2. поддержку генерации RequireJS модуля
3. Компиляцию через ASDF для Common Lisp backend,

Придется подождать готовности  и переделать.

Вопрос - а почему отказался от Parenscript?
amartynov - 10.12.2012 12:31
[#] Ответ на комментарий от amartynov 10.12.2012 12:31
> Неожиданно :)

Ну, скажем, это было нужно сделать.  Разбирать код перемалывающий s-выражения удовольствие не из приятных.

> Мы тут вточили

Это интересно.

> Вопрос - а почему отказался от Parenscript?

Перестал видеть смысл. Код фактически не упрощается (а может быть даже усложняется). Плюс изменения в parenscript порой порождают ошибки в cl-closure-templates. Меньше зависимостей и больше контроля.
archimag - 10.12.2012 15:51
[#] Ответ на комментарий от archimag 10.12.2012 15:51
>Разбирать код перемалывающий s-выражения удовольствие не из приятных.

Молодежь прекрасно это сделала :) Но тоже не без затрат.

>> Мы тут вточили

> Это интересно.

Можно посмотреть на 2 и 3 пункт в https://github.com/alexey-martynov/cl-closure-template, я просто не успел прислать реквест.
ASDF должен примениться как есть, а вот с RequireJS могут быть проблемы. Я домой приду, посмотрю, что можно сделать, скорее всего, там все просто.

PS. А сходу квотить тут можно при ответе?
amartynov - 10.12.2012 16:17
[#] Ответ на комментарий от amartynov 10.12.2012 16:17
> Можно посмотреть на 2 и 3 пункт в https://github.com/alexey-martynov/cl-closure-template

Лучше дождусь реквеста, времени не хватает :) Это обновление делал несколько месяцев по часу в неделю.

> Молодежь прекрасно это сделала :)

Где такая молодежь, если не секрет?
archimag - 10.12.2012 16:38
[#] Ответ на комментарий от amartynov 10.12.2012 16:17
> PS. А сходу квотить тут можно при ответе?

Нет. Вообще у меня есть большой план переписать весь lisper.ru, можно будет и форум подремонтировать ;)
archimag - 10.12.2012 17:02
[#] Ответ на комментарий от archimag 10.12.2012 16:38
> Лучше дождусь реквеста, времени не хватает

Тогда будет сразу 2 - для нового и для старого вариантов

> Где такая молодежь, если не секрет?

Да есть тут у нас в Питере такие интерны :) Учим потихоньку.
amartynov - 10.12.2012 18:38
[#] Ответ на комментарий от archimag 10.12.2012 16:38

Заслал реквест относительно зарефакторенного варианта.

В заначке есть еще одна вещь для Emacs - компиляция через Common Lisp backend через Slime, но это чуть позже.

PS. Клевая засада - редактирование сообщений в Firefox нереально глючит :( Косячит фокус контрола редактирования, из-под Linux совсем не смог редактировать.

amartynov - 11.12.2012 00:06
[#] Ответ на комментарий от amartynov 11.12.2012 00:06
> редактирование сообщений в Firefox нереально глючит

Какой Firefox? У меня 10 в Gentoo всё вроде нормально :(

Ну вот когда-нибудь приведу всё в божеский вид, буду тогда патчи просить :)
archimag - 11.12.2012 00:15
[#] Ответ на комментарий от archimag 11.12.2012 00:15
17-й

В Linux просто невозможно получить курсор и ввод. Под Windows легче, но он все время теряется при нажатии любой кнопочки в тулбаре. В районе 13-го, кстати, все работало. Сегодня еще попрошу потестить в Chrome.
amartynov - 11.12.2012 07:45
[#] Ответ на комментарий от orivej 09.12.2012 18:13
Предложение (даже 2): имена в camel case совершенно неестественно выглядят в Common Lisp. Может добавить name converter, который для Common Lisp backend превратит их в имена с дефисами?

Более того, было бы прикольно иметь его настраиваемым, через параметр compile-template или через динамическую переменную.

Могу сделать такую штуку и предложить на рассмотрение, если идея нравится. Как минимум, хотелось бы иметь настройки.
amartynov - 11.12.2012 09:21
[#] Ответ на комментарий от amartynov 11.12.2012 07:45
17-й Firefox под Gentoo, никаких проблем нет. В safe-mode тоже.
orivej - 11.12.2012 10:54
[#] Ответ на комментарий от orivej 11.12.2012 10:54
Полагаю, что привет надо передавать в Debian. :( Ну и черт с ним пока. Есть резервные варианты.
amartynov - 11.12.2012 11:05
[#] Ответ на комментарий от amartynov 11.12.2012 09:21
> Предложение (даже 2): имена в camel case совершенно неестественно выглядят в Common Lisp.
> Может добавить name converter, который для Common Lisp backend превратит их в имена с дефисами?

Не совсем понял о чём речь, ведь так и происходит? 

Хотелось бы пример увидеть.
archimag - 11.12.2012 11:54
[#] Ответ на комментарий от amartynov 11.12.2012 00:06
> одна вещь для Emacs - компиляция через Common Lisp backend через Slime

О, заценил :) Удобно.
archimag - 11.12.2012 16:16
[#] Ответ на комментарий от archimag 11.12.2012 11:54
Формально, если мы следуем стандартам, должно быть так:

{namespace ns}

{template .sampleTemplate}
...
{/template}

В результате, будет функция ns:sampletemplate, что довольно несимпатично. Гораздо лучше ns:sample-template.

Потому как сейчас, если
{template samplte-template}
{/template}

То и в Javascript она так и будет называться - sample-template :)
amartynov - 11.12.2012 18:11
[#] Ответ на комментарий от amartynov 10.12.2012 12:31
> Компиляцию через ASDF для Common Lisp backend

Поясните, как этим пользоваться? Если у меня в системе есть шаблон и она зависит от closure-template, то получается рекурсия.
Система не загружается, потому как ASDF не знает как обработать шаблон. И closure-template не грузится потому как syntax error в asd-файле и до depends-on дело не доходит.
andy128k - 17.12.2012 19:08
[#] Ответ на комментарий от andy128k 17.12.2012 19:08
> Поясните, как этим пользоваться?

Вот пример:

(defsystem #:test
  :defsystem-depends-on (#:closure-template)
  :components ((:closure-template "test"))
)

Обрати внимание, что вместо :depends-on используется :defsystem-depends-on. :depends-on может быть свойством любого компонента, а :defsystem-depends-on это только свойство всей системы и используется для загрузки зависимостей ещё до того, как начнётся обрабатываться определение системы. Наиболее очевидное применение - загрузка расширений asdf, хотя можно и просты зависимости так грузить. Подробности смотри здесь, раздел "5.3.4 Defsystem depends on".
archimag - 19.12.2012 02:40
[#] Ответ на комментарий от archimag 19.12.2012 02:40
Спасибо!
(Теперь ещё больше поводов ждать обновления quicklisp)
andy128k - 19.12.2012 10:44
[#] Ответ на комментарий от amartynov 11.12.2012 18:11

С формированием имен честно протупил :(

Итого, сейчас для шаблона у которого:
1. namespace - "closureTemplate.Example"
2. имя - "helloName"

Будут сгенерированы следующие имена:
1. Common Lisp: "closuretemplate.example:hello-name"
2. Javascript: "closureTemplate.Example.helloName
3. RequireJS: пространство имен будет пропущено (оно появится при загрузке по выбору клиента), имя функции - "helloName".

Как видно, есть некоторая неконсистентность - имя пакета не "лиспофицируется".

Есть предложение его лиспофицировать тоже. Какие-либо возражения?

PS. Работа над кастомными директовами для print пока еще идет.

amartynov - 02.01.2013 23:25
[#] Ответ на комментарий от amartynov 02.01.2013 23:25
> Есть предложение его лиспофицировать тоже. Какие-либо возражения?

Возражений нет. Собственно, там же есть функция #'closure-template::lispify-name, но

CL-USER> (closure-template::lispify-name "closureTemplate.Example")
:CLOSURE-TEMPLATE.-EXAMPLE

Т.е. перед EXAMPLE добавляется ненужный "-". 
archimag - 02.01.2013 23:43
[#] Ответ на комментарий от archimag 02.01.2013 23:43
А это не проблема. К концу праздников сделаю и заодно исправлю ведущий дефис. 
amartynov - 03.01.2013 10:08
@2009-2013 lisper.ru