воскресенье, 16 сентября 2012 г.

lstlistings и кириллица

При использовании кириллицы в листингах возникает ряд проблем, решение которых разбросано где-то по интернетам. Здесь я опишу некоторые приёмы, позволяющие решить возникающие проблемы.

Основные проблемы, с которыми сталкиваются люди при попытке использовать кириллицу в листингах - не компилится исходник и теряются пробелы в комментах. Лично я ещё столкнулся с тем, что комменты и строки в кириллице не подсвечиваются нужным цветом.


Итак, задача: напечатать в документе листинг программы

#include <stdio.h>

/**
 * Программа выведет сообщение "Привет, мир"
 */
int main()
{
    printf("Привет, мир\n");        // печатаем сообщение

}


Кодировка utf8. Как обычно помещаем это внутрь lstlisting, но при компиляции возникает ошибка.

Поэтому первое, что делаем - включаем поддержку расширенных символов:
\lstset{extendedchars=\true}

Отлично, теперь оно компилируется, но результат не совсем тот, который нужен:
Видим здесь 2 проблемы: в комментариях съелись пробелы и криво расставлены кавычки. Первая проблема решается легко добавлением опции keepspaces=true. Нормально решить вторую не получится в принципе. Но можно сделать костыль двумя способами.

Первый вариант костыля - ставить пробел сразу после кавычки и тогда они постаявятся перед буквой 'П'. Но такой вариант делает комментарий неправильным. Поэтому можно воспользоваться вторым вариантом - escapechar. Эта команда задаёт символ, после которого тест трактуется как стандартный текст в Latex со всеми вытекающими. К сожалению, при использовании цветных комментов это ничем не поможет. Есть вариант как раскрасить однострочные комменты - опция texcl=true, но если цвет однострочного коммента отличается от многострочного - то Вам не повезло. В результате получаем следующий код:

Опции пакета:
\lstset{tabsize=2,
    breaklines,
    columns=fullflexible,
    flexiblecolumns,
    numbers=left,
    numberstyle={\footnotesize},
    extendedchars=\true
}
\lstdefinelanguage{MyC}{
  language=C,
  ndkeywordstyle=\color{darkgray}\bfseries,
  identifierstyle=\color{black},
  morecomment=[n]{/**}{*/},
  commentstyle=\color{blue}\ttfamily,
  stringstyle=\color{red}\ttfamily,
  morestring=[b]",
  showstringspaces=false,
  morecomment=[l][\color{gray}]{//},
  keepspaces=true,
  escapechar=\%,
  texcl=true
}


Сам листинг:
\begin{lstlisting}[language=MyC]
#include <stdio.h>

/**
 * %Программа выведет сообщение <<Привет, мир>>%
 */
int main()
{
    printf("Привет, мир\n");        // печатаем сообщение

}
\end{lstlisting}


Выглядеть результат будет так:
Проблему с цветом решить так и не удалось. В случае использования однобайтовых кодировок можно воспользоваться приёмом вроде

literate={а}{{\selectfont\char224}}1

но для  utf8 оно не подойдёт.

5 комментариев:

  1. 1) \true и false это одно и то же. Лучше ставить просто true. Проблема будет решена без escapechar=\%.
    2) Там можно было в listings просто скатываться в нормальный TeX и писать там формулы + задавать цвета через \color{}
    3) Переходи на LuaTeX, там этой проблемы нет.

    ОтветитьУдалить
    Ответы
    1. http://dl.dropbox.com/u/3100167/.vobla/latex/books-examples/listings.pdf

      Удалить
    2. Да, я документацию читал.

      1) Насчёт true - у меня не работает. Причём самое забавное, что работает с false. escapechar нужен только для комментов или для \color, собственно это и есть пункт 2). Просто это костыль. lstlistings почему-то не воспринимает UTF символы как символы вообще.

      3) В принципе, я уже давно подумываю на что-нибудь перейти с latex, но ради 1-2 плюшек не очень хочется всё менять.

      Удалить
    3. Все и не придется. LaTeX, стар, беден и ограничен. После перехода на XeTeX, ничего менять не пришлось вообще. Но увы, там это проблема до конца не решена. Как и аналогичная проблема с предметным указателем.

      Удалить
  2. @w-49516

    LaTeX, стар, беден и ограничен.
    ЛаТеХ взрослый, богатый возможностями и делает то, что нужно. Сделать подобное надо ещё суметь, и не надо ломать то, что уже есть. Оно очень даже хорошее и на нём написано огромное количество документов.

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

    По теме: кириллица в listings делается либо через escapechar, либо конвертацией в koi8r. Последний вариант работает без вопросов.

    ОтветитьУдалить