Hlavní navigace

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

23. 5. 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.

Opis vstupu

Nejjednodušší a bezproblémovou variantou je využít některý ze standardních příkazů, který vypne interpretaci příkazů a text opíše do výsledné sazby. Pro krátké kousky kódu zařazené do textu je k dispozici příkaz  \verb.

Chová se neobvykle, protože jeho argument není uzavřen do obvyklých složených závorek, ale zahájen a ukončen stejným znakem. Důvodem je, že opisovaný kód může obsahovat složené závorky. Abyste do něj nemuseli zasahovat a složené závorky nějak chránit, prostě si k zahájení a ukončení vyberete znak, který se v daném kódu nevyskytuje. Populární je například „#“:

Dokument zahájíme příkazem \verb#\begin{document}#,
za nímž následuje vlastní text.

Vysázená podoba

Pro delší ukázky je k dispozici prostředí verbatim , které svůj obsah opíše do sázeného dokumentu. Opět neinterpretuje příkazy, zachovává konce řádků i mezery, text zkrátka bude vypadat přesně stejně jako ve zdrojovém kódu pro LaTeX.

Ukázka kódu v jazyce Java:

\begin{verbatim}
if (city.getName() != null) {
    name = city.getName();
} else {
    name="Neznámé město";
}
\end{verbatim}

Vysázená podoba

\verb iverbatim  přepnou na neproporcionální písmo. Všechny znaky jsou tedy stejně široké a je zachováno i jejich zarovnání pod sebou. Kód vypadá stejně, jako když jej otevřete v editoru.

Nevýhodou těchto základních nástrojů je, že o moc víc neumí. Zbývá už jen jedna vlastnost: když na konec jejich názvu přidáte hvězdičku, zvýrazní mezery v kódu a vysází místo nich „kancelářské sponky“. To se může hodit, pokud na počtu mezer záleží a chcete, aby si je čtenář mohl jednoduše přepočítat.

\verb*#x  ->   y#

Vysázená podoba

Balík fancyvrb

Pokud vám sazba kódu opisováním vyhovuje, ale standardní \verb a verbatim jsou pro vás příliš omezující, doporučuji vaší pozornosti balík fancyvrb. Definuje příkaz \Verb a prostředí Verbatim, které se chovají podobně, ale přidávají ledacos navíc.

Balík nabízí ještě třetí možnost: příkaz \VerbatimInput{ soubor} načte kód ze zadaného souboru a „opíše“ jej do sázeného textu. Díky němu nemusíte ukázkový kód kopírovat do dokumentu, ale můžete jej vložit rovnou ze souboru, kde jste jej odladili.

Dá se také vybrat jen jeho část. Slouží k tomu parametry firstline a lastline, kterými určíte číslo prvního a/nebo posledního řádku. Parametry se vkládají jako nepovinný argument, tedy v hranatých závorkách. Mají obecný tvar název=hodnota a oddělují se čárkami. Například vložení části souboru priklad.java od 8. do 15. řádku by zajistil příkaz

\VerbatimInput[firstline=8,lastline=15]{priklad.java}

Mechanismus parametrů, kterými ovlivňujete vzhled opisovaného textu, je obecný. Můžete je přidat i k prostředí Verbatim i k příkazu \Verb, ale zrovna omezování sázených řádků dává smysl jen v kombinaci s  \VerbatimInput.

Ve zdrojovém kódu bývá zvykem odsazovat vnořené bloky. Zařadíte-li do dokumentu část kódu, která je celá odsazena, nemusí to vypadat dobře. Proto je k dispozici parametr gobble, který odstraní z každého řádku zadaný počet úvodních znaků. Byl-li například kód odsazen o čtyři mezery a vy chcete toto odsazení při sazbě zrušit, použijte  gobble=4.

Abyste snadněji mohli komentovat konkrétní místa v kódu, hodí se jeho řádky očíslovat. K tomu slouží parametr numbers s hodnotami left nebo right podle toho, na které straně chcete čísla mít. Čísluje se od jedničky. Počítají se i řádky vynechané pomocí firstline, takže první řádek ve výše uvedeném příkladu ponese číslo 8.

To lze samozřejmě změnit parametrem firstnumber. Hodnotou může být konkrétní číslo, nebo klíčové slovo last, které zajistí, že číslování naváže na poslední opisovaný kód. Díky němu lze elegantně prezentovat kód po kouskách a prokládat jej vysvětlujícím textem.

S číslováním souvisejí ještě parametry numbersep=0.5em, který určuje mezeru mezi čísly řádků a kódem, stepnumber=5 umožňuje číslovat jen každý 5. řádek a numberblanklines=false vypne číslování prázdných řádků. Pokud by se vám nelíbilo, jak čísla vypadají, bude změna složitější. Je třeba změnit příkaz \theFancyVerbLine, příklad najdete v dokumentaci balíku.

Další důležitou vlastností je oddělení ukázek kódu od okolního textu. Parametrem vspace můžete řídit velikost svislé mezery, která se vloží nad a pod kód. Zajímavější ale nejspíš budou rámečky, které ovládá parametr frame. Nemáte úplnou kontrolu, k dispozici jsou následující možnosti:

  • none  – žádné, výchozí hodnota,
  • single  – rámeček kolem kódu,
  • leftline  – svislá čára vlevo,
  • topline  – vodorovná čára nad kódem,
  • botomline  – vodorovná čára pod kódem,
  • lines  – vodorovná čára nad a pod kódem.

Několik parametrů ovlivňuje vzhled rámečku: framerule=0.5pt je jeho tloušťka, rulecolor=\color{teal} nastaví barvu rámečku a framesep=1.5ex šířku mezery mezi ním a kódem.

Kromě rámečku lze k ukázce kódu přidat i popisek, například název souboru. Slouží k tomu parametr label. Se znalostí výše uvedeného si můžeme vytvořit příkaz pro vložení ukázky kódu z externího souboru, jehož jméno se zároveň využije jako popisek:

\newcommand{\ukazka}[1]{\VerbatimInput[
    numbers=left,
    frame=lines,
    rulecolor=\color{teal},
    framesep=1.5ex,
    label={#1}]{#1}}

Výsledek \ukazka{mesta.java} pak vypadá následovně:

Vysázená podoba

K vizuálnímu odlišení kódu od okolního textu můžete využít i vlastnosti jeho písma. Jsou k dispozici čtyři parametry pro jednotlivé charakteristiky: fontfamily , fontseries ,fontshape a fontsize . S výjimkou posledního bych doporučoval na ně nesahat. Jen pokud vám například kód připadá příliš velký, můžete použít třeba fontsize=\small .

Kromě toho máte ještě k dispozici parametr formatcom. Do něj lze zadat příkazy, které se mají provést na začátku opisovaného textu. Nabízí se například nastavení barvy textu:  formatcom=\color{teal}.

Občas by se hodilo v kódu něco zvýraznit, což v prostředí tohoto typu bývá problém. Balík fancyvrb nabízí pro tento účel parametr commandchars. Jeho hodnotou jsou tři znaky: první bude interpretován jako zahájení příkazu, druhý jako zahájení skupiny a třetí jako ukončení skupiny. Jejich pomocí můžete do kódu vkládat příkazy LaTeXu, které budou vykonány, a odlišit díky nim významnou pasáž změnou barvy nebo písma.

Dokumentace balíku obsahuje ukázku, jak v opisovaném textu aktivovat tradiční znaky zpětné lomítko, levá a pravá složená závorka: commandchars=\\\{\}. V kódu pak lze používat běžné příkazy LaTeXu, které se budou provádět. Pohybujeme se tu po šikmé ploše, protože pokud se některý ze znaků vyskytne v kódu, nebude už opsán, ale interpretován jako speciální znak. Což se typicky týká složených závorek, které najdete v každém druhém programovacím jazyce.

Vhodnější je použít obyčejná písmena s exotickými akcenty, u kterých je téměř vyloučeno, že by se v kódu objevila. V následujícím příkladu používáme A s háčkem místo \, K s háčkem pro zahájení skupiny a U s háčkem pro její ukončení. Zdrojový kód je sice dost bizarní, ale funguje to:

\begin{Verbatim}[commandchars=ǍǨǓ]
if (ǨǍcolorǨpurpleǓcity.getName()Ǔ != null) {
\end{Verbatim}

Vysázená podoba

Zvýraznit v kódu mezery lze pomocí showspaces=true , totéž pro tabulátory zajistí showtabs=true . Zmiňme ještě možnost přidat ke kódu návěští pro křížové odkazy pomocí reflabel= návěští. Možnosti balíku fancyvrb jsme sice ještě nevyčerpali, ale pro běžnou praxi by dosavadní výčet měl stačit.

Zbývá ještě popsat, jak nastavit výchozí parametry. V dokumentu bývá větší počet ukázek a je velmi záhodno, aby jejich vzhled byl konzistentní. Opisovat několik parametrů u každé z nich nechceme, takže si buď lze vytvořit vlastní příkaz, jako například výše uvedená \ukazka, nebo pomocí nástrojů, které balík nabízí, změnit výchozí podobu.

Tím základním je příkaz \RecustomVerbatimEnvironment. Má tři parametry: prvním je název prostředí, jehož vlastnosti chcete nastavit. Druhým název prostředí, od kterého je má přebrat, a třetím nastavení parametrů, které má přidat či změnit k převzatým. Řekněme, že bych chtěl standardně sázet kód modrozelenou barvou, jeho řádky číslovat a připravit si výše uvedené úchylné znaky pro vkládání příkazů. Použil bych v preambuli:

\RecustomVerbatimEnvironment{Verbatim}{Verbatim}{
    numbers=left,
    formatcom=\color{teal},
    commandchars=ǍǨǓ}

U jednotlivých zdrojových kódů pak přidám jen ty parametry, které jsou pro ně specifické, například popisek nebo úpravu číslování řádků. Lze si také definovat vlastní opisovací prostředí. Příkaz se jmenuje \DefineVerbatimEnvironment a jeho parametry jsou podobné: název definovaného prostředí, jméno „vzorového“ prostředí a úpravy parametrů. Řekněme, že v dokumentu budu mít ukázky z jazyků Java a XML, které chci odlišit barvou. Nadefinoval bych si tedy dvě prostředí (v XML nepočítám se zvýrazňováním, takže vynechám  commandchars):

\DefineVerbatimEnvironment{java}{Verbatim}{
    numbers=left,
    formatcom=\color{teal},
    commandchars=ǍǨǓ}

\DefineVerbatimEnvironment{xml}{Verbatim}{
    numbers=left,
    formatcom=\color{olive}}

Existuje také \RecustomVerbatimCommand, kterým lze upravit výchozí parametry pro příkazy \VerbatimInput a \Verb. Neexistuje však \DefineVerbatimCommand. Kdybych si chtěl vytvořit příkazy \javaInput a \xmlInput, musel postupovat podobně jako u výše uvedeného příkazu \ukazka. Abych si zachoval možnost přidávat či měnit parametry, doplním volitelný parametr. Kód by mohl vypadat nějak takto:

\RecustomVerbatimCommand{\VerbatimInput}{VerbatimInput}{
    numbers=left,
    frame=lines}
\newcommand{\javaInput}[2][]{\VerbatimInput[
    formatcom=\color{teal},
    commandchars=ǍǨǓ,
    #1]{#2}}
\newcommand{\xmlInput}[2][]{\VerbatimInput[
    formatcom=\color{olive},
    #1]{#2}}

Příště

Balík fancyvrb dovede ledacos, ale pořád je to „jen“ opisování zdrojového kódu s přidanou hodnotou. Pokročilejší variantu pro sazbu zdrojových kódů představuje balík listings, který si představíme v příštím článku.

(Autorem obrázků je Pavel Satrapa.)

Byl pro vás článek přínosný?

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.