Sazba zdrojových kódů v LaTeXu: balík minted

6. 6. 2024
Doba čtení: 7 minut

Sdílet

Autor: Root.cz s využitím DALL-E
Součástí odborných textů běžně bývají ukázky programového kódu či konfiguračních souborů. Nejčastěji bývají sázeny neproporcionálním písmem, ale jsou i jiné možnosti. Pojďme se podívat, co v této oblasti nabízí LaTeX.

Třetím rozšiřujícím balíkem, který pomůže se sazbou zdrojových kódů, je minted. Podobně jako listings je specializován pro tento účel, rozpoznává v kódu lexikální prvky daného jazyka a vizuálně je odlišuje. Podporovaných jazyků nabízí ještě víc než listings. V čem je mezi nimi rozdíl?

minted to nedělá sám, ale volá si externí zvýrazňovač syntaxe Pygments. Jeho uvedení do provozu a zásahy do konfigurace proto mohou být náročnější. Výhodou je podrobnější analýza kódu, bezproblémové zpracování českých znaků a také vás z výchozí podoby kódu nebudou bolet oči.

Dobrá zpráva: pokud používáte Overleaf, vše máte připraveno a balík můžete rovnou nasadit. V případě lokální instalace je třeba instalovat program Pygments a LaTeX spouštět s volbou -shell-escape, aby povolil volání externích programů. Není to úplně bezpečné…

Možnosti pro vložení kódu odpovídají předchozím balíkům: prostředí minted pro víceřádkové ukázky a příkazy \mintinline pro vložení do řádku textu a \inputminted k načtení kódu z externího souboru. Tentokrát ale vždy musíte v povinném argumentu uvést jazyk vkládaného kódu, například:

Ukázka jazyka Java:

\begin{minted}{java}
if (city.getName() != null) {
    name = city.getName();
} else { /* nezdařilo se */
    name="Neznámé město";
}

Vysázená podoba

Příkaz\mintinline opět používá libovolný znak k vymezení začáku a konce kódu: \mintinline{java}#if (x<0)# . Lze použít i složené závorky, pokud nejsou v kódu obsaženy. Načtení externího souboru zajistí \inputminted{java}{mesta.java} .

Jak vidíte, ve výchozí podobě se kód sází neproporcionálním písmem (takže jsou zachovány sloupce znaků) a hýří barvami. Pro změnu písma je připraven parametr fontfamily. Opakuje se koncept pojmenovaných parametrů, jejichž syntaxe název=hodnota je shodná s předchozími dvěma balíky.

Jako hodnotu mu zadejte jméno rodiny pode NFSS. Drobným zádrhelem je, že balík fontspec je standardně nenastavuje. Pokus o použití běžného jména, které máte v příkazech typu \setmainfont či \newfontfamily proto skončí chybovou hláškou o nedostupnosti písma v požadovaném kódování. Spraví to parametr NFSSFamily při vložení písma. Přiřadí rodině název pro NFSS, který následně můžete předat minted.

V ukázkách používám písmo Alegreya. V záhlaví dokumentu proto mám:

\setmainfont{Alegreya}[NFSSFamily=Alegreya]

Jméno pro NFSS může být libovolné, pro přehlednost ale doporučuji držet se jména rodiny. K zahájení prostředí přidám parametr

\begin{minted}[fontfamily=Alegreya]{java}

a dostanu:

Vysázená podoba

Pokud se vám nelíbí, jak vysázený kód vypadá, mám pro vás dobrou a špatnou zprávu. Dobrou zprávou je, že jeho vzhled je řízen stylem, takže změnou stylu lze snadno upravit výslednou podobu. Slouží k tomu parametr style , například se můžete zbavit barev přechodem na černobílý styl: style=bw .

Tuto změnu obvykle chceme pro všechny kódy, takže bude vhodnější použít příkaz \usemintedstyle, který zadaný styl nastaví globálně. Na webu najdete vzorník existujících stylů, umírněnější barvy nabízí například styl trac. Po přidání

\usemintedstyle{trac}

do záhlaví dokumentu se výše uvedený příklad změní na

Vysázená podoba

Ťeď ta špatná zpráva: když si nevyberete mezi existujícími styly, vaši situaci to dost zkomplikuje. Jednoduchý parametr typu „identifikátory mají vypadat takto“ bohužel neexistuje.

O podobě kódu rozhoduje externí formátovač Pygments a musíte pro něj vyrobit styl podle svého gusta. V lokální instalaci to znamená najít, kde se jeho styly nacházejí, některý zkopírovat a upravit. Overleaf vám to ale neumožní, dotyčné soubory jsou mimo váš dosah. Musíte nasadit hmaty a chvaty, abyste jej přiměli ke spolupráci.

Balík minted také umožňuje vkládat plovoucí ukázky kódů pomocí prostředí listing. Jedná se o přímou analogii standardních prostředí figure a table. Používá se úplně stejně, včetně nepovinného parametru určujícího možné umístění a příkazů \caption\label:

\begin{listing}[htp]
    \inputminted{java}{mesta.java}
    \caption{Nalezení jména města}
    \label{mesta.java}
\end{listing}

Seznam plovoucích zdrojových kódů (vytvořený z příkazů \caption v prostředí listing) vložíte pomocí \listoflistings. Jeho název lze nastavit změnou příkazu \listoflistingscaption. Nadpisy jednotlivých plovoucích kódů pak pomocí  \listingscaption:

\renewcommand{\listoflistingscaption}{Seznam zdrojových kódů}
\renewcommand{\listingscaption}{Kód}

Dále už pojedeme ve starých kolejích. Balík minted interně využívá fancyvrb, takže řada jeho parametrů je shodných. Dají se nastavovat individuálně u jednotlivých vkládaných kódů, nebo plošně pro všechny. To má na starosti příkaz \setminted{ parametry}. Lze jej používat opakovaně, pozdější výskyty přidávají čí mění parametry těch předchozích. Nastavení může být specifické pro konkrétní jazyk, jehož název uvedete v nepovinném parametru. Například chceme barevně odlišit ukázky kódu v jazyce XSLT, takže jim předepíšeme jiný styl:

\setminted[xslt]{style=manni}

Vložený kód začne řádkem určeným parametrem firstline a skončí řádkem lastline. Odsazení lze zrušit pomocí gobble. Tentokrát je navíc k dispozici parametr autogobble, který si sám spočítá počet odstraňovaných znaků podle nejméně odsazeného řádku. O zobrazení mezer a tabulátorů se postarají showspacesshowtabs.

Číslování řádků zajistí parametr numbers s hodnotami left, right, both nebo none. stepnumber říká, po kolika řádcích zobrazovat číslo, numbersep je velikost mezery mezi číslem a kódem.

firstnumber umožňuje nastavit číslo prvního řádku. Hodnota last opět naváže na číslování předchozí ukázky. Je s ní spojena jedna zajímavá vychytávka: Pokud balík vložíte s volbou langlinenos, pak last naváže na číslování předchozí ukázky stejného jazyka. Můžete tak střídat ukázky kódů v různých jazycích a průběžně pokračovat v jejich číslování prakticky bez námahy.

Řízení rámečků je shodné s balíkem fancyvrb. Shodné jsou dostupné hodnoty parametru frame i významy parametrů framerule, framesep a rulecolor. Tentokrát lze nastavit i barvu pozadí pomocí bgcolor. Hodnotou v tomto případě není příkaz pro změnu barvy, ale jen její jméno, například bgcolor=black!7. O jednoduchý popisek se postará label. V dokumentaci autor doporučuje zvážit použití některého z pokročilejších balíků pro rámování, jako je mdframed nebo tcolorbox.

Zvýraznění části kódu je zde nejjednodušší, ale zároveň nejomezenější. Zvýrazňují se celé řádky, do kódu nelze vkládat příkazy LaTeXu, které by se prováděly. Parametrem highlightcolor určíte barvu pozadí zvýrazněných řádků a highlightlines identifikuje řádky, kterých se to týká. Lze použít samotné číslo i interval od-do. Může jich být několik, v tom případě hodnotu uzavřete do složených závorek a specifikace řádků oddělujte čárkami. Čísla odpovídají zobrazeným.

Zdrojový kód

\begin{minted}[
    firstnumber=last,
    highlightcolor=green!10,
    highlightlines={8,10-12}]{xslt}
<xsl:template match="cenik">
    <table>
    <xsl:apply-templates>
        <xsl:sort select="nazev"/>
    </xsl:apply-templates>
    </table>
</xsl:template>
\end{minted}

povede k výsledku:

Vysázená podoba

Také balík minted umožňuje vytvářet vlastní prostředí s přednastavenými parametry a jazykem. Slouží k tomu příkaz:

\newminted{ jazyk}{ parametry}

Vytvoří prostředí pojmenované jazykcode, které se chová stejně jako prostředí minted s daným jazykem a parametry. Například:

\newminted{xslt}{style=manni,numbers=none}

\begin{xsltcode}
<xsl:template ...
\end{xsltcode}

Takto vytvořenému prostředí nelze při použití předávat žádné další parametry. Je neměnné. Příkaz \newminted ale ve skutečnosti vytvoří prostředí dvě, to druhé má na konci navíc hvězdičku a slouží právě pro tyto případy. U něj se parametry předávají jako povinný argument. Pokud bych po výše provedeném \newminted chtěl XSLT kód přece jen číslovat, použil bych:

\begin{xsltcode*}{numbers=left}
...
\end{xsltcode*}

Dá se definovat i jméno vytvářeného prostředí, slouží k tomu nepovinný argument příkazu  \newminted:

\newminted[xsl]{xslt}{style=manni,numbers=none}

vytvoří prostředí xsl (bez parametrů) a xsl* (s parametry). Podobným způsobem lze zkracovat i další varianty pro vkládání kódu. \newmintedfile{ jazyk}{ parametry} definuje příkaz \ jazykfile pro načtení kódu ze souboru a \newmintinline{ jazyk}{ parametry} zavede \ jazykinline pro vkládání krátkých ukázek kódu do textu.

Co použít?

Jak je vidět, nadstavbové možnosti zmiňované trojice balíků jsou dost podobné – umí vkládat soubory, vybírat z nich řádky, číslovat, barvit, vykreslovat rámečky a podobně. Liší se však v tom základním, v prezentaci kódu. Podle ní si nejspíš vyberete svého favorita.

Osobně mám rád, když je kód sázen běžným písmem, takže fancyvrb je ze hry. U minted mi vadí závislost na prvcích mimo TeX, která jej činí poněkud nepředvídatelným, obtížněji přenositelným a potenciálně nebezpečným. Navíc mi nevyhovuje žádný ze standardních stylů.

Dávám tedy přednost balíku listings, který v mých očích představuje zlatou střední cestu. Jeho analýza kódu sice není tak podrobná, ale připadá mi dostačující a možnosti přizpůsobení výsledného vzhledu mi vyhovují. Nepotřebuje ke své činnosti nic dalšího a když člověk překoná úvodní překážky s českými znaky, práce s ním je bezproblémová.

(Autorem obrázků je Pavel Satrapa.)

Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

Pavel Satrapa působí na Ústavu nových technologií a aplikované informatiky na Technické univerzitě v Liberci, píše knihy a motá se kolem tuzemské akademické sítě CESNET.