В жизни каждого начинающего программиста-самоучки есть момент, когда смотреть очередное видео из серии «Основы %language_name%» уже не интересно, а проситься в джуниоры ещё рано. В этот момент хочется опробовать свои силы на каком-нибудь «почти настоящем» проекте. Под катом — история о том, как я придумал такой проект и что из этого вышло.

image

Так у сложилось, что в нашей стране учителя информатики любят Pascal. И в педагогических вузах студентов, как правило, учат именно ему. Не имею ничего против этого языка, однако, будучи студентом одного педагогического вуза, мне захотелось изучить что-нибудь более мейнстримовое.

После знакомства с некоторыми языками программирования и проектами уровня «Hello world!» на них, мне попался на глаза Python.

Знакомство с его синтаксисом и возможностями привело меня в восторг. Я прочитал все книги по питону, какие только нашел, изучил сотни туториалов, пересмотрел несколько видео. Понятное дело, мне не терпелось применить свои знания на практике. Поэтому, когда на одном из предметов лабы разрешили сдавать на любом языке, я доставил некоторое количество проблем преподавателю (судя по всему, раньше никто из студентов такими изысками преподавателей не баловал). Сделав несколько таких лабораторных проектов, захотелось двигаться дальше и приступить к «настоящему» проекту.

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

Идея


Картинка дала идею, однако такой вариант «сделанного в СССР» языка разметки показался не очень хорошим. Коротко требования к языку можно сформулировать следующим образом:

  • Все команды должны быть доступны в стандартной русской раскладке;
  • Компиляция в HTML;
  • «Нет!» закрывающимся тегам.

Первое требование было продиктовано самой концепцией, второе — желанием увидеть результаты работы на практике. Что касается третьего требования — ещё со школы не любил писать дублирующие закрывающие теги (вроде </body> и </bold>), хотя их необходимость неоспорима. Поэтому было решено ввести универсальный «закрыватель», который закрывал бы любые теги.

Синтаксис


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

В общем виде команды языка ЯГТР можно описать следующим образом:

\команда::атрибуты::(текст)

Часть с атрибутами является необязательной. Использование :: для отделения атрибутов может показаться необоснованным решением (например [] или {} были бы более наглядными), но это жертва, принесенная в дар «русскоязычности» раскладки.

Реализация


Как уже говорилось выше, сварщик я не настоящий и компиляторов никогда не писал. Хотя в целом принципы их работы представлял.

И вот тут мне пригодились знания по теории автоматов, полученные в рамках университетского курса «Теоретические основы информатики». Помнится, тогда они мне казались бесполезными — быть может, дело в том, как этот курс читался.

Алгоритм работы компилятора разбивался на 2 этапа:

  • Получение из исходного текста списка токенов;
  • Использование полученного списка для генерации кода.

Для получения списка токенов исходный текст просматривался практически посимвольно, если встречался «граничный» символ, то текущий токен добавлялся в список. Границами токенов могли служить: \, (, ), %, команды, символ конца строки и др.

На втором этапе компиляции использовался конечный автомат, который хранил текущее состояние и, возможно, стек состояний. Рассмотрим на примере.

Код должен был выглядеть примерно следующим образом:

\пар(Этот текст будет \ж(полужирным), а этот - \к(курсивом))


Что после компиляции должно было превратиться в

<p>Этот текст будет <b>полужирным</b>, а этот - <i>курсивом</i></p>

Для реализации автомата были созданы:

  • TokenList — список, хранящий токены;
  • STATE — текущее состояние автомата;
  • statement — стек состояний

Изобразить это можно следующей схемой:


Пусть на вход автомату первым подается токен \пар. Так как этот токен является командой языка, то он задает новое состояние (<p), которое и становится текущим, а предыдущее состояние (<body>) сохраняется в стек состояний.


Обратите внимание: новым состоянием становится именно <p, а не <p> — это связано с тем, что названия состояний используются для генерации кода, а перед символом > могут быть некоторые атрибуты тега. Фактически, есть два различных состояния: <p и <p>, в последнее автомат переходит, когда на вход ему подается токен "(". Подобная схема применялась для всех команд, поэтому было принято считать первые состояния «неполными тегами», а вторые — «полными тегами».

Если на вход поступает токен ")", а текущее состояние является «полным тегом», то в генерируемый файл добавляется парный тег (например тег </p>), а текущим состоянием становится снятое с вершины стека последнее состояние.
Разбор заканчивается, когда после очередной ")" оказалось, что стек состояния пуст.

Текст между :: и :: считается атрибутами тегов. Предполагалось, что для их парсинга будет использоваться свой алгоритм разбора, поэтому сначала он просто добавлялся между именем тега и символом >. С одной стороны это позволило использовать внутри команд ЯГТР синтаксис HTML, с другой — этот текст никак не анализировался, поэтому не было гарантий, что в нем нет ошибок с точки зрения HTML.

Результаты


В целом результаты работы можно оценить как неоднозначные.

Изначально целью проекта было прокачать свои навыки в программировании на python и создать продукт, который было бы не стыдно показать потенциальному работодателю (ну и потешить ЧСВ, конечно). И если с первой частью более менее хорошо (лучше освоил язык, плюс немного разобрался с github'ом), то со второй не так всё гладко.

Некоторые проблемы, которые так и не были решены:

  1. Проблемы с реализацией аналога тега <pre>;
  2. Анализ атрибутов не реализован — фактически, они просто подставляются в тег HTML;
  3. Идея отказа от переключения раскладки оказалась (пока?) несостоятельной — атрибуты и стили всё равно приходится писать на английском, реализации какого-нибудь ЯКТС нет даже в проекте;
  4. Неоднозначное решение: компилятор на интерпретируемом языке;
  5. Реализованы не все теги;
  6. Написать «настоящий сайт» на ЯГТР можно, но знать HTML всё равно необходимо.

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

С другой стороны, появились и некоторые новые мысли. В частности, хотелось бы разобраться как правильно организовать опции компилятора через аргументы командной строки. Или как создать текстовый редактор с подсветкой синтаксиса ЯГТР. Но тут я даже не знаю с какого края ухватиться.

Итого: определенный опыт разработки был получен, однако успешным проект не назовешь. Ну и да, появление «убийцы HTML» откладывается на неопределенное время.

Исходники компилятора лежат на GitHub. Вопросы, замечания, предложения, критика и помощь принимаются.
Поделиться с друзьями
-->

Комментарии (69)


  1. lolmaus
    08.09.2016 20:14

    Не <a>, а <я>! Anchor = якорь.


    1. pehat
      08.09.2016 21:01
      +23

      Да сколько ж можно! <а> — это абзац, <p> по-буржуйски.


      1. san-smith
        09.09.2016 03:10

        мопед картинка не моя, я только в пост разместил.

        А если серьезно — вопрос о том, как назвать очередную команду оказался нетривиальным. Хотелось, чтобы команды были понятными, но краткими, а иногда просто было сложно придумать русскоязычный аналог.
        Например, как адекватно перевести на русский <a> и <link>? Ведь и то, и другое — ссылка.


        1. CrazyNiger
          09.09.2016 08:16

          — это ссылка, а — это anchor (якорь). Он может быть использован не только для перехода в другое место, но и как маркер на странице, к которому можно перейти.


          1. san-smith
            09.09.2016 08:21
            -1

            Нет, я про другое: <a> — это тег HTML, который используется для создания ссылок на файлы (например, другие страницы сайта), а <link> — тег, который используется для подключения, например, файлов со стилями.
            Но ведь фактически, и то, и другое — ссылки. Как адекватно перевести названия этих команд на русский?


          1. san-smith
            09.09.2016 08:27

            Похоже понял, что вы имели в виду (видимо теги «съело»).
            Возможно вы правы и такой вариант именования команд был бы более верным. Хотя я всегда думал, что <a> — это ссылка (зато теперь понятно, почему «а» — спасибо за ликбез).


        1. Toshiro
          09.09.2016 16:34

          Нормально краткими вы их не сделаете никак просто из-за структуры языка. Средняя длинна слова в англ. яз. 4 символа, поэтому многие сокращения это почти само слово. В рус. яз. же средняя длина слова 7 символов.

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


  1. Delphinum
    08.09.2016 20:14
    +13

    Вы переизобрели синтаксис LaTeX.


    1. san-smith
      09.09.2016 02:40
      +2

      Вообще говоря да, я сознательно использовал похожие на латех команды. Но можно ли говорить, что это синтаксис LaTeX?


      1. Delphinum
        09.09.2016 13:17

        Но можно ли говорить, что это синтаксис LaTeX?

        я сознательно использовал похожие на латех команды

        Вы сами отвечаете на свой вопрос. Это не синтаксис LaTeX, это похожие на LaTeX команды.


  1. Mingun
    08.09.2016 20:37

    Или как создать текстовый редактор с подсветкой синтаксиса ЯГТР. Но тут я даже не знаю с какого края ухватиться.

    Для начала можно попробовать посмотреть на генераторы парсеров по грамматикам — например, на pegjs. Далее можно попробовать свои силы в написании плагина к какому-нибудь редактору. В частности, например, для NetBeans-а еще нет подсветки pegjs, а сделать ее не очень сложно. Самое интересное, что на основе примера интеграции новой подсветки языка можно реализовать подсветку грамматики pegjs с помощью самого pegjs (если сначала портировать его на java. Впрочем, можно воспользоваться и другим парсер-комбинатором, но это не так эпично)! Я и сам хочу этим заняться, но пока поглощен другим проектом.


    1. JediPhilosopher
      09.09.2016 14:40
      +1

      Можно взять готовый компонент Scintilla — это такой крутой встраиваемый редактор с подсветкой синтаксиса, например Notepad++ или FlashDevelop поверх него сделаны. Очень мощная и в то же время довольно простая штука для создания редакторов для каких-то своих форматов исходного кода.


      1. Mingun
        09.09.2016 18:47

        Да, Scintilla прекрасный компонент, больше всего он мне нравится тем, что сворачивает код железно везде, а не игнорирует какие-то странные случаи, как, к сожалению делает NetBeans для Java-классов на верхнем уровне файла (кто им сказал, что их не нужно сворачивать? В одном файле, вообще-то, несколько package-private классов может быть и невозможность их свернуть очень огорчает) или MSVS (почему-то иногда не считает нужным сворачивать блоки в фигурных скобках внутри функций. Километровые if-ы и switch-и читать просто "удовольствие"). Плюс нормальные маркеры свертывания, а не как в каждой IDE изголяются кто во что горазд — то линию "от сих до сих" прячут, пока не наведешь мышь (кому она мешает?), то вместо нормальных ± какие-то стрелки понатыкают. SciTE до сих пор мой любимый редактор именно из-за этой простоты и детерминированности, всяким Sublime-ам и Atom-ам до него еще расти и расти в этом плане.


        К сожалению, код Scintilla (когда я его смотрел в последний раз, но это было несколько лет назад. Зная, как не любят писать документацию к существующему коду, сомневаюсь, что что-то изменилось) практически недокументирован и разбираться в нем тяжело, да это и более низкий уровень. Вряд ли подойдет новичку.


  1. rockin
    08.09.2016 21:10
    -3

    >> А ещё на клавиатуре были бы только русские буквы
    {} и <> в русской раскладке отсутствуют :)
    p.s. с альтом — хак


    1. lorc
      08.09.2016 21:49
      +7

      Статью не читай @ комментарий пиши.


      1. AVX
        08.09.2016 22:16
        -3

        зануда_mode
        Вы не правильно используете знак «коммерческое at», он по смыслу совсем для других целей.
        Например:
        мыло @ сервер
        5А @ 220v
        130W @ 25?
        зануда_mode_off
        P.S. как и многие другие. Что за мода пошла?


        1. CodeRush
          08.09.2016 23:02
          +7

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


          1. AVX
            09.09.2016 09:13
            +2

            Спасибо, не знал про это. Но всё равно не могу воспринимать символ собаки как-то по-другому. Я бы лучше слэш использовал.


            1. saluev
              09.09.2016 15:22

              Не можете или не хотите?
              Слеш в Интернете уже используется — в значении, близком к «или».


              1. AVX
                09.09.2016 16:53

                Вот чёрт! Тогда вспомним bash и используем два амперсанда, так логика будет соблюдена. Да пусть даже один.


                1. saluev
                  09.09.2016 17:30

                  Не совсем. Чтобы логика была соблюдена, нужна скорее точка с запятой. «И» подразумевает одновременное выполнение условий.


      1. rockin
        08.09.2016 22:49
        -1

        В вашей раскладке перепутаны @ и &
        :D

        А статью я как раз прочитал. Но самый цимес нашёл именно в символах, ради которых всё равно раскладку переключать (подавляющему большинству).
        Не надо повторять тот ад, что мне пришлось пережить, когда я погружался в адинце-«программирование».


        1. san-smith
          09.09.2016 02:43

          Картинка к посту придумана не мной. Собственно, изначальной идеей и было, чтобы в языке не нужно было переключать раскладку. Поэтому {} и [] в языке не используются.


    1. MacIn
      08.09.2016 21:59

      Это смотря какая раскладка.


    1. AlexMal
      09.09.2016 02:44

      Да, все равно надо будет переключаться.


      1. san-smith
        09.09.2016 02:47
        +1

        В ЯГТР не используются [] и {}, так что переключаться не обязательно. Другое дело, что если нужны будут атрибуты (например для \рис) и стили, то тут да — фактически придется писать код на HTML.


  1. slonopotamus
    08.09.2016 21:48
    +1

    Вот это поворот. Теперь я знаю что обратный слэш и в русской раскладке можно набрать. Правда зачем…


  1. AVX
    08.09.2016 21:53

    Ничего особо нового. В студенческие времена часто писал на vb6, используя всё на русском — и переменные, и функции. Смотрелось прикольно, но только и всего. Никакой разницы, на каком языке называть функции, переменные, и т.п. — только неудобства для зарубежных разработчиков (всё же английский знают больше народа, нежели русский, хоть сколько бы я ни был патриотом). ИМХО, для программирования лучше просто не использовать вовсе какой-либо второй язык — только английский. Потому что надо отделять код от данных, а данные уже забивать можно на каком угодно языке. Правда, для небольших проектов это не оправданно, но там и потери на переключение раскладки будут небольшими — не сравнить с изобретением нового html.


    1. alibertino
      09.09.2016 02:48

      ИМХО, для программирования лучше просто не использовать вовсе какой-либо второй язык — только английский.

      только неудобства для зарубежных разработчиков

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


    1. san-smith
      09.09.2016 02:52
      +2

      На самом деле язык создавался just for fun.
      Важнее было прокачать навыки программирования, а тут просто попалась на глаза интересная идея.


      1. AVX
        09.09.2016 09:19

        Надо было в теги добавить «ненормальное программирование».


        1. san-smith
          09.09.2016 09:21

          Сделано.


  1. Survtur
    08.09.2016 22:41
    +2

    Вроде бы с аргументами командной строки в питоне все просто — модуль, кажется, argparse. В документации хорошие и понятные примеры.


    1. GamePad64
      09.09.2016 09:43

      С появлением docopt, остальное кажется монструозным.


      1. Survtur
        09.09.2016 16:04

        Есть минус: не включено в стандартный комплект.


        1. GamePad64
          09.09.2016 16:35

          Docopt однофайловый, можно просто скопировать к себе в проект.


  1. rst256
    09.09.2016 02:54

    А как насчет экранирования, например когда код на подобии такого:
    \пар(Этот текст ( будет \ж(полужирным), а этот - \к(курсивом))
    \пар(Этот текст \пар( будет \ж(полужирным), а этот - \к(курсивом))


    Для создания редактора с подсветкой синтаксиса ЯГТР, можно использовать библиотеку wx там есть достаточно мощный редактор кода Scintilla:


    А это пример кода с аналогичным функционалом на lua:

    utf8=require'lua-utf8'
    
    s=[[\пар(Этот текст будет \ж::class='bold'::(полужирным), а этот - \к(курсивом)\изо`align='center'`)]]
    
    
    --хеш для тегов с телом
    local complex_tags = {
    	['пар']='p', ['ж']='b', ['к']='i'
    }
    
    --хеш для тегов без тела
    local simple_tags = {
    	['бр']='br', ['изо']='img'
    }
    
    --паттерны для разбора тегов, без начального символа "\" 
    local complex_tag_pattern = [[:?:?([^:%)%(\]*):?:?(%b())]]
    local simple_tag_pattern = [[:?:?([^:%)%(\]*):?:?]]
    
    --рекурсивная функция в которой все и происходит 
    local function pp(str)
    	--обрабатываем теги без тела
    	for ya_tag, html_tag in pairs(simple_tags) do
    		str=utf8.gsub(str, [[\]]..ya_tag..simple_tag_pattern,
    			function(attrs)
    				local s = '<'..html_tag
    				if #attrs>0 then s=s..' '..attrs end
    				s=s..'>'
    				return s
    		end)
    	end
    
    	--тоже но уже для тегов с телом
    	for ya_tag, html_tag in pairs(complex_tags) do
    		str=utf8.gsub(str, [[\]]..ya_tag..complex_tag_pattern,
    			function(attrs, body)
    				local s = '<'..html_tag
    				if #attrs>0 then s=s..' '..attrs end
    				s=s..'>'..pp(utf8.sub(body, 2, -2))..'</'..html_tag..'>'
    				return s
    		end)
    	end
    
    	return str
    end
    
    --выводим результат
    print(pp(s))
    


    1. san-smith
      09.09.2016 03:00

      А как насчет экранирования, например когда код на подобии такого:
      \пар(Этот текст ( будет \ж(полужирным), а этот — \к(курсивом))

      Для экранирования используется \ — так, чтобы ввести символ "(" нужно писать \(

      \пар(Этот текст \пар( будет \ж(полужирным), а этот — \к(курсивом))

      А в данном случае компилятор выдаст ошибку — для внешнего \пар не будет найдена закрывающая ")".

      По поводу примера: с lua не знаком, ничего сказать не могу. Но могу сказать, что сначала тоже думал использовать регулярные выражения, но не осилил.


  1. gof
    09.09.2016 03:00

    случайно, не знакомый автора этой статьи?


    1. san-smith
      09.09.2016 03:01

      Нет, эта статья раньше мне не попадалась.


      1. sidorares
        09.09.2016 03:15
        +2

        осталось объединить эти две статьи в «если бы React и JSX сделали в СССР»


  1. altervision
    09.09.2016 03:14

    А почему не на Brainfuck?


    1. san-smith
      09.09.2016 03:14

      Просто потому что хотел научиться программировать на Python.


  1. 7j7
    09.09.2016 03:27

    Ты слуцайно не фанат 1C?


    1. san-smith
      09.09.2016 03:29
      +1

      Нет, не фанат.


  1. AleXP3
    09.09.2016 06:14
    +2

    Хе-хе ;-)

    image

    _ГОСТ 27974-88_

    А если серьезно, то Алгол-68 можно назвать _«предтечей html»_.


    1. san-smith
      09.09.2016 06:16
      +3

      Всё-таки Алгол — язык программирования, а HTML — язык разметки.


      1. AleXP3
        09.09.2016 06:25

        Бесспорно так. Это разные сущности конечно.

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


  1. yamatoko
    09.09.2016 07:21
    -2

    поздравляю, вы что-то изобрели.


    1. MrShoor
      09.09.2016 08:11
      +9

      поздравляю, вы что-то написали в комментарии.


  1. Lamaster
    09.09.2016 11:15

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


    1. Lamaster
      09.09.2016 12:01

      замены тега

      <html>


    1. yara_73
      09.09.2016 13:42

      Извините, а в каком смысле употребляется в данном контексте слово рекурсивная? И как оно применяется к парным тегам, просто немного не уловил мысль. Спасибо!


      1. Lamaster
        09.09.2016 16:31

        В том смысле, что сиблинги блока и внутренний контент влияют на него самого


    1. Lain_13
      13.09.2016 10:19

      Ну давайте не забывать, что во время «отрисовки» страницы всё ещё докачиваются картинки, посторонний мусор и выполняются скрипты. Когда у тебя 40 метров картинок и 5 метров скриптов (и лишь за 1 из них стоит поблагодарить рекламу) для отображения сайт-визитки, то как-то не удивительно, что отрисовка этой всей бодяги занимает больше, чем скачивание.


  1. redc0de
    09.09.2016 11:41

    Насчет pre можно использовать подход LaTeX, ну или похожий на него


    \начало пфт
    Текст Предварительно Форматированного Текста
    Следующая строка
    \конец пфт


    1. san-smith
      09.09.2016 16:10

      Тогда выбивается из системы: команда в общем случае выглядит \команда::аргументы::(текст), а подход латеха сильно отличается.


      1. redc0de
        09.09.2016 16:41

        Ну если стандарт позволит то можно попробовать так:


        \пфт(
        Многострочный текст,
        здесь
        
        monospace
        )


        1. san-smith
          09.09.2016 16:47

          На самом деле, проблема немного в другом зарыта. Так как символ ")" используется в качестве «закрывателя» команд, то для его вывода на экран используется последовательность \).
          Вопрос следующий: если я захочу вставить символ ")" внутри команды \пфт, мне ставить перед ним "\"? Если да, то какой же это преформатированный текст? А если нет, то как определить конец команды?


          1. redc0de
            10.09.2016 12:49

            Ну да, в контексте \команда::аргументы::(текст) это сложно реализовать, нужно придумывать многострочный вариант команды, как в первом комментарии. Получается такой блок, где все аттрибуты также наследуются


            1. san-smith
              10.09.2016 13:09

              На самом деле, такая команда фактически уже есть: ведь текст между :: и :: пока вставляется в документ как есть. Можно придумать аналог, но это выбивается из общей картины. Кстати, строго говоря, вариант

              \начало пфт
              Текст Предварительно Форматированного Текста
              Следующая строка
              \конец пфт
              — это почти то же самое, что и пара ::, только здесь начало и конец отличаются, а случае с ::, они являются признаком и начала, и конца.


  1. punkkk
    09.09.2016 12:38
    +1

    Проиграл с цвет «военноморсокгофлота», спасибо.)


  1. friday
    09.09.2016 14:16
    +1

    Теперь одинэсники тоже смогут верстать? :-)


  1. Igor-dis
    09.09.2016 16:07

    Python — хороший язык. Но и идею русификации тоже далеко откладывать не надо, потому как она может стать снова актуальной. Учитывая курс на импортозамещение, русификация ЯП становится вполне логичной. Да и традиции имеются.

    image


  1. hiddenman
    09.09.2016 16:48
    +2

    Помню, захотелось мне в далеком 1998 году тоже свой язык для своего фидошного проекта. Т.к. я ничего не знал, книжек не было, учителей тоже, а проект был изначально вообще под DOS, то я просто случайно нашел в Borland Pascal валидаторы (по сути regexp-ы) и с их помощью вполне успешно написал свой.овно-язычок.
    Он даже в байт-код (я такого слова еще не знал) компилировался, чтобы не разбирать его при каждом запуске.
    Даже скриптов понаписывал на нем. Эх, если бы я тогда учился где-то у нормальных преподов, может и вышел бы из меня толк.

    Целые трактаты писал, было время и желание, сейчас так делать уже лень :-)
    https://github.com/hiddenman/pointmaster/blob/master/trunk/utf8/script/example.pms


  1. Landgraph
    10.09.2016 14:28

    Автор «адаптировал» к русской раскладке формат RTF =)


    1. san-smith
      10.09.2016 14:45

      Сейчас посмотрел пример на Википедии:
      {\rtf1
      Привет!
      \par
      {\i Это} некий
      отформатированный {\b текст}.\par
      }

      Даже не знаю, как по мне — общего только то, что команда начинается с символа \. А вообще, выше правильно заметили, что синтаксис больше похож на латех.


  1. trigger1
    12.09.2016 11:06
    -2

    Я бы тебе руки оторвал за эту ересь, да еще и бесполезную…


    1. san-smith
      12.09.2016 17:14

      Как гласит народная мудрость, «Не любо — не слушай, а врать не мешай».
      Тем более, что лично для меня это было полезно.