Hastache 0.6.0. Новый мейнтейнер
Вышла новая версия hastache 0.6.0. Самое заметное изменение — переход от использования ByteString к использованию Text.
А самое заметное изменение для меня самого в том, что теперь у hastache новый мейнтейнер, который вот эту новую версию и выпустил. Это Daniil Frumin. Я отошел от разработки hastache просто по причине отсутствия у меня активных проектов с его использованием, а людям надо, кто-то пользуется, вот Daniil и попросился на эту роль. Теперь у меня такое странное чувство по этому поводу. С одной стороны приятно, что там что-то такое написал, а вот теперь оно совсем своей жизнью зажило. С другой стороны, эх времени бы мне немного свободного, сесть и переписать все совсем по другому, по правильному, API можно еще немного обобщить, парсер переписать...
Новый движок моего блога
В очередной раз переделал движок своего блога. Теперь у меня чисто статический блог, лежащий в Amazon S3. Предыдущая версия благополучно и без единого нарекания отработала свои год и 9 месяцев. Теперь настало время перемен.
Мне кажется, что суммарное время, которое я трачу на программирование движков своего блога, уже превышает время на то чтобы что-то сюда писать. И уж во всяком случае это явно сравнимые величины.
Окончательным толчком к переходу на чисто статический блог послужило недавнее появление у Amazon S3 функции редиректов, без редиректов всё-таки сложно обойтись. Также, для такого простого сайта как личный блог, держать целый сервер, базу данных, как-то всё это администрировать — явное переусложнение. В последнее время я больше склоняюсь к простым решениям.
Для интересующихся некоторые технические подробности:
Генератор
Тут для меня без вариантов — Haskell. Самый главный действующий персонаж тоже понятен — Hastache, не зря же я его писал.
Организация
Технически каждая запись в блоге выглядит так: отдельная директория с именем типа «2011-02-28 16:03 new engine», внутри лежит файл def.json с заголовком и тегами этой записи, файл text.html с текстом, и какие-нибудь дополнительные файлы (если они в этой записи нужны). Такие вот ракетные технологии блогостроения. Text.html — это не просто чистый html, это ещё и кое-какая дополнительная разметка, например для вставки математических формул ( рулит) или исходного кода с подсветкой синтаксиса (highlighting-kate). Дополнительная разметка большей частью представлена секциями Hastache.
Типографика
Ммм, это прямо моя прелесть. Не понимаю чего никто переносов в вебе не делает, намного ведь приятней выглядит, особенно если текст растянут по ширине. Технически сами переносы уже сто лет как доступны во всех браузерах. У меня теперь всё с переносами, красота да и только. Переносы расставляет самописанная библиотека (работает по алгоритму Ляна-Кнута), я её написал для qrmania.ru, и вот опять пригодилась. Надо бы выложить в Hackage, но пока QA-отдел в моей голове этого не позволяет.
Работа с S3
Сначала думал обойдусь s3cmd, но в итоге написал собственный синхронизатор для S3, благо для Haskell есть библиотека aws. Кстати, я в неё закоммитил работу с редиректами S3, но эта версия в настоящий момент ещё не выложена в Hackage, кому срочно надо берите прямо с GitHub.
Доступ к элементам списка по номеру в Hastache
Это конечно очень приятно когда что-то полезное делаешь. Пользователей Hastache в мире может и не очень много, но они точно есть. Вот недавно Christiaan Baaij прислал сообщение о функции которая есть во многих реализациях шаблонизатора Mustache, а в Hastache нет. Это обращение к элементам списка по номеру, т.е. как-то так:
|
|
Полезная штука, мне ни разу пока не пригодилась (поэтому и не сделал), однако легко можно придумать ей применение и кому-то такое точно понадобится.
Пользоваться так:
|
|
Результат:
|
|
Алгоритм Ахо-Корасик на Haskell
Выложил в open source свою реализацию алгоритма Ахо-Корасик на Haskell. Код на GitHub. Пакет в HackageDB.
Алгоритм Ахо-Корасик — алгоритм поиска подстрок, созданный Альфредом Ахо и Маргарет Корасик в 1975 году. Этот алгоритм предназначен для одновременного поиска сразу большого количества подстрок. Алгоритм состоит из двух фаз: сначала строится конечный автомат по всем подстрокам которые нужно будет искать, и дальше через этот построенный автомат пропускается текст, в котором эти подстроки нужно найти.
Моя реализация обобщена для любых последовательностей значений, для которых реализован тайп-класс Hashable (т.е. искать можно не только строки, но и, скажем, последовательность из чисел).
Примеры использования
Самый простой вызов:
|
|
|
|
К искомым строкам можно привязать произвольные данные:
|
|
|
|
Созданный автомат можно запускать по шагам (если нужен поиск не по спискам, а по чему-нибудь другому):
|
|
|
|
Некоторые подробности реализации
Построение конечного автомата у меня сделано в монаде ST. Это монада используется, когда вам нужны вычисления с изменяемыми данными, но при этом никакой внешний мир не нужен (т.е. монады IO для вас слишком много), соответственно снаружи монады мы имеем чистый интерфейс, а внутри у нас есть мутабельные переменные и массивы. Там я написал простейшую FIFO очередь в этой монаде, можно почитать кому интересно.Сам поиск с использованием созданного автомата сделан уже в чистых функциях, это можно видеть в примерах выше.
Ссылки по теме
Примеры использования Hastache
Выложил примеров для hastache: README.md (этот файл, кстати, хасташем же и собирается — mkReadme.hs). Эти же примеры россыпью файлов: examples.
Libqrencode-js: генерация QR-кодов на JavaScript
А вот какую офигенскую штуку я выложил!
Это генератор QR-кодов на чистом как хрусталь JavaScript, никаких серверных компонентов, всё прямо в браузере. Вот сразу демонстрашка для побаловаться.
Причем это не абы что, это порт продвинутой C-шной библиотеки libqrencode, которая работает в серверной части на подавляющем большинстве сайтов для генерации QR-кодов, и имеет биндинги ко всему на свете. Для JavaScript уже есть генераторы QR-кодов, но все очень сырые, в отличии от libqrencode который уже несколько лет пишется и, как я уже говорил, много где используется.
Процесс портирования C-шной библиотеки на JavaScript, это, скажу я вам, просто песня. Есть совершенно замечательный проект emscripten — компилятор LLVM в JavaScript. Вот с помощью него волшебство и произошло. Я написал небольшую C-шную обертку над libqrencode, скомпилировал всё вместе в LLVM-код с помощью Clang, передал в emscripten и написал JavaScript обертку над результатом его работы. Получилось хорошо.
Лицензия LGPL (вирусом от libqrencode). Пользуйтесь!
Hastache растёт и развивается
Новости хасташестроения:
Во-первых, Akaspin прислал полезный патч, позволяющий с помощью mkGenericContext создавать контексты для типов с полями MonadIO m => (Byte)String -> m (Byte)String, за что ему выдаётся очередной плюс в карму. Сам я о такой возможности думал, но не осилил, ура опенсорсу. Пример использования тут.
Во-вторых, я обобщил конструктор MuLambda до MuVar a => MuLambda (ByteString -> a), раньше можно было только ByteString возвращать, а теперь любой тип, для которого есть инстанс класса MuVar. Удобно, как-то я раньше не сообразил так сделать.
В-третьих, Сам Bryan O'Sullivan (один из авторов книги Real World Haskell), прислал небольшой патч для hastache и посоветовал использовать blaze-builder для записи результата работы шаблонизатора. Blaze-builder предназначен для генерации Lazy ByteString с контролем минимального размера фрагментов этой строки. За счет этого достигается существенное увеличение скорости дальнейшей работы с этой строкой. Вместо кучи мелких блоков (а именно так и получается при работе hastache), имеем несколько крупных, которые, к примеру, по сети уедут быстрее (за счет минимизации количества системных вызовов). Так что теперь и обычный результат hastache состоит из удобных крупных блоков внутри Lazy ByteString, и, также, можно получить непосредственно объект Builder библиотеки blaze-builder и дальше уже работать прямо с ним.
Hastache — вложенные контексты
Akaspin зарепортил один неприятный баг в hastache, за что ему выражается всяческая благодарность с занесением в карму. Проблема заключалась в том, что достаточно часто нужно иметь возможность обратиться из вложенного блока шаблона к переменной определенной где-то выше в иерархии контекстов. В оригинальном Mustache такая функция есть, а я это дело благополучно проворонил. Исправляюсь. Можно почитать подробности, и посмотреть ещё один пример из тестов.