Я пытаюсь написать свой универсальный язык разметок. Использование M4 сопровождается множеством неудоств, в частности, долгой отладкой. Из-за этого прогресс с языком разметок немного встал.
Единый язык разметок удобен тем, что можно писать один текст, и из него генерировать много текстов в различных форматах (html, tex, wiki, simple). В частности, такая возможность мне очень необходима при написании файлов помощи DEmbro — как минимум планируется документация на вики и в REPL режиме.
Недавно я придумал, как этот язык разметок можно организовать на DEmbro. В качестве основы я взял свои идеи по созданию аналога функции printf в DEmbro, и... реализовал всё самое главное в течении нескольких минут (единственная большая функция занимает 8 строк: она тут). Осталось только написать нужный набор команд, но это не составит труда (пример того, что уже начато для googlecode wiki тут).
Опишу идею и её реализацию. Размеченный текст представляет из себя просто обычный текст, в котором иногда встречаются специальные команды, влияющие на отображение этого текста. Почему бы мне не написать команду на DEmbro, которая читает размеченный текст, обычную составляющую просто выводит, а специальные фрагменты выделяет и выполняет их так, как будто это код на DEmbro? Сразу придумался синтаксис: фигурные скобки выделяют в тексте специальные фрагменты. Получается следующее
variable *doing?
: \page *doing? off ;
: {page}
*doing? on
begin *doing? @ while
" {" source-cut str.
" }" source-cut evaluate
repeat ;
Команда {page} выделяет в цикле фрагменты исходника, зажатые между фигурными скобками, и выполняет их. Команда \page обрывает этот цикл. Как этим пользоваться: допустим, мы хотим добавить в язык разметок команду b для генерации жирного шрифта в формате HTML. Тогда пишем следующее:
: b " <b>" str. ;
: \b " </b>" str. ;
(Разница слешей в последней команде нелепа, но в DEmbro я больше привык закрывающие команды писать именно с таким наклоном, потому что другой «занят» под деление.)
Теперь можно смело использовать:
{page}
Это просто текст.
{b}А это уже жирный текст{\b}
{\page}
(Это программа на DEmbro, которая выведет текст, преобразованный в html-форматированный.)
Если есть желание использовать вместо фигурных скобок другие, легко написать другую page-команду, например:
: [page]
*doing? on
begin *doing? @ while
" [" source-cut str.
" ]" source-cut evaluate
repeat ;
При этом каким-либо образом переопределять команды \page, b, \b и другие не нужно: можно смело писать
[page]
Это просто текст.
[b]А это уже жирный текст[\b]
[\page]
В зависимости от удобства можно дописать вариант page с любыми ограничителями (не обязательно даже односимвольными).
Между фигурными/квадратными скобками не обязательно писать лишь одну команду, можно сразу несколько. Например,
: i " <i>" str. ;
: \i " </i>" str. ;
: u " <u>" str. ;
: \u " </u>" str. ;
[page]
Это просто текст.
[b i u]А это уже жирный курсивный подчёркнутый текст[\u \i \b]
[b i][u] И это тоже, несмотря на непарность конструкций[\u \i \b]
[\page]
Более того, т.к. в управляющем коде допустимо писать любой DEmbro-код, можно прямо в нём объявлять команды, переменные, вычислять время и т.д.
{page}
{: _ " " ; ( Тут мы объявили команду, печатающую пробел)
: int int->str DOC-GENERATOR << ^ ; ( Тут мы объявили команду int, которая печатает число)}
Значение таймера на момент генерации страницы: {timer int}
Числа от {8 dup int} до {0 dup int}: {
:noname swap begin 2dup <= while dup int _ 1- repeat ; execute
}
{\page}
Последний пример (объявление noname-функции) наталкивает меня на идею компилируемых размеченных текстов. Т.е. сейчас это всё работает только в режиме интерпретации, но, возможно, было бы удобно создавать команды, в которые вкомпилированы генераторы размеченных страниц, зависящие от переданных параметров и окружения.
В итоге я осознал, что больше не буду использовать M4 в своих разработках (по крайней мере в качестве языка разметок), а буду дальше развивать свой язык разметок (или даже макропроцессор) на DEmbro.
Пара слов по поводу кода, который находится сейчас среди модулей DEmbro (ссылки были выше). В нём используется та же идея, что описана тут, только слова разложены по пространствам имён, и сделана возможность сменить команду вывода на свою. В будущем конвертирование из моего формата в необходимый будет происходить как-то так:
HTML " sample.dep" evaluate-file ^
TEX " sample.dep" evaluate-file ^
GOOGLECODE " sample.dep" evaluate-file ^
SIMPLE " sample.dep" evaluate-file ^
Текущий пример для googlecode можно посмотреть тут
sample.dep -> test.wiki -> так это выглядит в итоге
Читать дальше......