вторник, 14 января 2014 г.

minted: Оформляем исходный код в LaTeX

Помнится, ещё на студенческой скамье я встречал задачу оформления исходного кода в LaTeX. В ту пору я использовал пакет listings. И я страдал. О, как же я страдал! Русские буквы не хотели дружить с UTF-8, а глаза мои текли кровавыми слезами при взгляде на итоговое форматирование. И вот, вновь я встретился с этой тяжёлой задачей. В поисках решения я наткнулся на замечательный пост в записках дебианщика Как оформить исходный код программ в LaTeX без адских страданий. Название подсказывало мне, что развлечение это не простое. Я аккуратно перепробовал все рецепты из статьи, но ни один меня не устроил. И в самом конце поста я обнаружил ссылку на замечательный пакет minted, который должен был положить конец моим страданиям.

Пакет minted базируется на Python-овской библиотеке Pygments, которая умеет на отличненько раскрашивать код, поддерживается около 300 разных языков и форматов разметки. Для начала нам понадобится её установить (предполагаем, что Python и easy_install уже имеются):

easy_install Pygments

Переходим в любимый LaTeX-редактор и начинаем писать код (опять-таки предполагаем, что версия нашего LaTeX-дистрибутива включает пакет minted и все его зависимости):

\documentclass[11pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[english,russian]{babel}
\usepackage{minted}

\begin{document}
\begin{minted}{csharp}
using System;
namespace HelloWorld
{
  class Hello 
  {
    static void Main() 
    {
      Console.WriteLine("Hello, World!");
    }
  }
}
\end{minted}
\end{document}

При трансляции запускаем latex/pdflatex c ключём -shell-escape. Получаем красивый результат:

Проблемы возникнут, если мы захотим в UTF-8 кодировке использовать русские буквы. Но мне удалось найти другой замечательный пост, в котором приводилось немного магии в преамбуле для поддержки кириллицы. Оттранслируем следующий файл:

\documentclass[11pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[english,russian]{babel}
\usepackage{minted}

\makeatletter
\newcommand{\minted@write@detok}[1]{%
  \immediate\write\FV@OutFile{\detokenize{#1}}}%

\newcommand{\minted@FVB@VerbatimOut}[1]{%
  \@bsphack
  \begingroup
    \FV@UseKeyValues
    \FV@DefineWhiteSpace
    \def\FV@Space{\space}%
    \FV@DefineTabOut
    %\def\FV@ProcessLine{\immediate\write\FV@OutFile}% %Old, non-Unicode version
    \let\FV@ProcessLine\minted@write@detok %Patch for Unicode
    \immediate\openout\FV@OutFile #1\relax
    \let\FV@FontScanPrep\relax
%% DG/SR modification begin - May. 18, 1998 (to avoid problems with ligatures)
    \let\@noligs\relax
%% DG/SR modification end
    \FV@Scan}
    \let\FVB@VerbatimOut\minted@FVB@VerbatimOut

\renewcommand\minted@savecode[1]{
  \immediate\openout\minted@code\jobname.pyg
  \immediate\write\minted@code{\expandafter\detokenize\expandafter{#1}}%
  \immediate\closeout\minted@code}
\makeatother

\begin{document}
\begin{minted}{csharp}
using System;
namespace HelloWorld
{
  class Hello 
  {
    static void Main() 
    {
      Console.WriteLine("Привет, мир!");
    }
  }
}
\end{minted}
\end{document}

И возрадуемся появлению русских букв:

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

\begin{minted}[mathescape,
               linenos,
               numbersep=5pt,
               gobble=2,
               frame=lines,
               framesep=2mm]{csharp}
string title = "This is a Unicode π in the sky"
/*
Defined as $\pi=\lim_{n\to\infty}\frac{P_n}{d}$ where $P$ is the perimeter
of an $n$-sided regular polygon circumscribing a
circle of diameter $d$.
*/
const double pi = 3.1415926535
\end{minted}

Больше информации вы найдёте на GitHub-е и в документации