Главная / Заметки / Попытка сбежать от Латеха
23 февраля 2023 г.
TL;DR: Я пытался создать свою программу для того, чтобы хоть в каком-то объёме заменить Латех, чтобы она могла на основе Markdown со всеми схемами, диаграммами, формулами могла создать ODT-документ. К сожалению, этого сделать не получилось.
По учёбе мне часто приходится делать различные отчёты: по лабораторным, практическим работам. Время от времени — различные расчётно-графические и курсовые работы. Сделать само задание для меня не составляет труда. Самое трудное — всё это оформить.
Проблема эта возникла практически с первого дня моего обучения в университете. Во-первых, у меня тогда не было подходящего оборудования: ноутбука у меня не было, а компьютер находился на родине в Полтавке. Более-менее для этих целей подходил планшет, который связывался по Интернету с моим компьютером, но возникла другая проблема: пользоваться планшетом в таком режиме дико неудобно. Дело в том, что не было мышки, а изображение на планшет отдавалось с частотой примерно 8 кадров в секунду. В таком режиме никакими графическими приблудами пользоваться было просто невозможно.
Во-вторых, ни один редактор схем алгоритмов (в том числе LibreOffice Draw) не позволял в символ вставить формулу, записанную на математическом языке, а не с использованием синтаксиса языка Си. В случае с LibreOffice Draw всё было несколько проще, поскольку формулу можно наложить на символ. Не факт, что будет ровно, но наложить получится. Но такое положение дел меня не устраивало.
Всё это сподвигло меня на поиск решения проблемы. Как-то я хотел написать на Си программу, которая бы по текстовому описанию рисовала схемы алгоритмов и вставляла формулы. Подумав, я решил, что такую программу написать не смогу, и я решил поискать готовое решение. Этим готовым решением оказалось использование LaTeX и TikZ.
TikZ меня не сильно устроил. Дело в том, что символы получались слишком большие. Тогда я решил попробовать использовать MetaPost и библиотеку Metaflow. Схемы, которые я делал с их применением, были более компактными, а значит, меньше занимали места на странице.
Затем я вернулся обратно на TikZ. Я даже вручную, руководствуясь результатами поиска в Интернете и исходными кодами различных пакетов TikZ, написал код для недостающих символов.
Набив многочисленные шишки на создании схем алгоритмов как при помощи TikZ, так и при помощи Metaflow, я понял, что это очень сложный способ создания подобного рода рисунков. К тому же, не везде его можно было задействовать: таскать с собой дистрибутив LaTeX довольно сложно, и не факт, что он запустится. Поэтому я для себя решил: надо бежать от Латеха. Бежать в сторону LibreOffice и создания документов в нём на основе простого текста. Так родилась идея создания программы odtgen.
Я пытался сначала создать свой собственный формат исходных файлов, но в итоге обратил свой взор на Markdown. Подобрал библиотеку для обработки текстов на Markdown, MD4C. Прикрутил ещё несколько библиотек для формирования ODT-документа (а документ в формате ODT представляет из себя сжатые XML-файлы плюс встроенные ресурсы в виде картинок, хранящиеся в ZIP-файле). Постепенно odtgen могла генерировать достаточно качественные ODT-файлы, оформленные отчасти в соответствии с ГОСТ 7.32-2017.
Несмотря, однако, на то, что программа худо-бедно работала, у неё был ворох серьёзных недостатков. Во-первых, она не могла нормально, без Латеха, генерировать формулы. Во-вторых, нельзя было вставить сноски: это не позволяла библиотека Markdown. В-третьих, отсутствовала возможность вставки перекрёстных ссылок. В общем, беда.
Затем я решил попробовать совместить уже готовые инструменты при помощи скриптов командной оболочки: Pandoc и LibreOffice. Через Python можно обращаться к работающему LibreOffice и через него править документ. Всё просто замечательно! Однако возникла беда с формулами: не все формулы нормально отрисовывались. Возьмём пример из Gostdown:
\begin{eqnarray*}
B & =& \sum_{j \neq i} \mu_j\frac{\mathbf{r}_j-\mathbf{r}_i}{r^3_{ij}} \left
\{-\frac{2(\beta+\gamma)}{c^2}\sum_{k \neq i}\frac{\mu_k}{r_{ik}}
-\frac{2\beta-1}{c^2}\sum_{k \neq j}\frac{\mu_k}{r_{jk}} +
\gamma\left(\frac{v_i}{c}\right)^2 + \right. \\
& + & \left. (1+\gamma)\left(\frac{v_j}{c}\right)^2 -
\frac{2(1+\gamma)}{c^2} {\mathbf{\dot r}}_i \cdot {\mathbf{\dot r}}_j
-\frac{3}{2c^2} \left[(\mathbf{r}_i-\mathbf{r}_j)\cdot\frac{\mathbf{\dot
r}_j}{r_{ij}}\right]^2 +\frac{1}{2c^2}({\mathbf{r}}_j-{\mathbf{r}}_i) \cdot
{\mathbf{\ddot r}}_j \right \} + \\
& + & \frac{1}{c^2} \sum_{j \neq i} \frac{\mu_j}{r^3_{ij}} \left\{
\left[{\mathbf{r}}_i-{\mathbf{r}}_j \right] \cdot
\left[(2+2\gamma){\mathbf{\dot r}}_i -(1+2\gamma){\mathbf{\dot r}}_j \right]
\right\}(\mathbf{\dot r}_i-\mathbf{\dot r}_j) + \frac{3+4\gamma}{2c^2}
\sum_{j \neq i} \mu_j \frac{\mathbf{\ddot r_j}}{r_{ij}} \\
\end{eqnarray*}
Вот как должен выглядеть результат преобразования этой формулы. Так он выглядит при использовании системы Gostdown, которая завязана на использовании Microsoft Word:

А вот как он выглядит в LibreOffice:

Как можно заметить, формула не хочет нормально отображаться. Дело в том, что LibreOffice использует StarMath в качестве внутреннего представления, и через его абстрактное синтаксическое древо производит отрисовку формулы. А обработчик StarMath в обязательном порядке требует, чтобы у операторов всегда были операнды. Преобразователь LaTeX в MathML, встроенный в LibreOffice, к сожалению, не учитывает этой особенности, и поэтому приводит к такому результату.
Поэтому я решил переписать odtgen с нуля на другом языке программирования. Я выбрал Go, потому что на нём была библиотека для обработки Markdown, которая удовлетворяла моим нуждам. Но с библиотекой для LaTeX задалась проблема, и пришлось использовать внешний LaTeX.
В итоге я понял, что есть лишь два варианта: либо использовать LibreOffice и прочие графические инструменты, либо использовать Латех. Всё, что между ними, либо содержит костыли, либо работает не так, как мне нужно.
Тем более, актуальность этой проблемы лично для меня несколько сбавилась, поскольку я обзавёлся ноутбуком.