Proč to dělá tohle?
   
Proč to dělá tohle? CSTUG


Proč jsou ignorovány parametry odstavce

TeX při uspořádávání textu nepracuje tak, že by bral slovo za slovem, či řádku za řádkou. Nejmenší jednotkou, kterou TeX formátuje, jsou celé odstavce. Odstavec je načten celý do paměti a není dále zpracováván, dokud není načtena značka konce odstavce. Právě v ten okamžik se uplatní parametry odstavce. Chyby použití parametrů formátování odstavce často vznikají právě proto, že se zapomíná na to, v jaké posloupnosti se odstavec zpracovává.

Předpokládejme následující větu v LaTeXu:

  {\raggedright % zarovnávání  textu  vlevo
  Tento text by měl být na výstupu zarovnán
  pouze vlevo.  Chceme,  aby  se  tak stalo
  pouze  v~tomto  odstavci,  a~ proto  zde
  ukončíme skupinu.}

Další text je zpracován normálně...

TeX otevře skupinu a nastaví parametry formátování odstavce tak, aby byl text uvnitř této skupiny zarovnáván pouze vlevo, poté uloží dvě věty textu, uzavře skupinu a nastaví původní parametry odstavce. Poté načte prázdný řádek, který je zpracován stejně jako příkaz \par; vysází dvě věty textu. Jelikož však skupina byla ukončena před načtením konce odstavce, nastavení parametrů uvnitř skupiny ztratilo význam a odstavec bude vysázen s běžnými parametry.

Aby nastavené parametry zůstaly v platnosti po celou dobu zpracovávání odstavce, je třeba ukončit odstavec uvnitř skupiny. Nahradíme-li poslední tři řádky v předchozím příkladě za:

  ukončíme skupinu.\par}
  Další text je zpracován normálně...
ukončí se odstavec ve chvíli, kdy jsou parametry odstavce nastavené v uzavřené skupině stále v platnosti.


Proč se v LaTeXu užívá ochran (protection)

LaTeX si ukládá některá data, jež bude zpracovávat až později. Těmito daty jsou zejména argumenty některých příkazů, takzvané pohyblivé argumenty. Pohyblivé proto, že s daty se nějakým způsobem manipuluje. Jedná se argumenty těch příkazů, které zapisují do obsahu, seznamu tabulek atd., tj. data, která jsou zapisována do pomocného souboru, z něhož jsou později opět čtena. Jinými daty jsou ta, která se mohou objevit v záhlavích. Nejvýznamnějšími příkazy tohoto typu jsou popisy obrázků a tabulek (captions) a veškeré nadpisy. Úplný seznam lze najít v Lamportově manuálu (viz Knihy o TeXu a příbuzná literatura).

Co se za tím vším skutečně skrývá? Příkazy, jež se použijí v pohyblivých argumentech, jsou v průběhu ukládání plně expandovány. Někdy je výsledkem takového rozvoje špatný TeXovský kód, což se projeví až při jeho následném čtení. Příkazem \protect\cmd je LaTeXu řečeno, aby uložil \cmd bez expanze, jako \cmd.

Co je to ,,křehký příkaz`` (fragile command)? To je příkaz, který je během ukládání rozvinut do chybného TeXovského kódu.

Co je to ,,robustní příkaz`` (robust command)? To je příkaz, který je během ukládání rozvinut do správného TeXovského kódu.

Nikdo se (samozřejmě) z takto nepřehledné situace neraduje. Skupina projektu LaTeX3 při práci na LaTeXu 2e odstranila potřebu některých ochran, avšak techniky, které jsou jim dostupné v současném LaTeXu, činí věc poměrně složitou. Dlouhodobým cílem této skupiny zůstává odstranění všech ochran.


Proč \verb nefunguje uvnitř ...

Funkce příkazu LaTeXu pro sazbu textu v tom tvaru, v němž je uveden ve zdrojovém souboru (verbatim), je založena na využití změny kategorie (category codes) jednotlivých znaků. Knuth v této souvislosti říká: ,,Je potřeba věnovat jistou péči tomu, aby vše proběhlo ve správném sledu...``. Kategorie znaku se od okamžiku, kdy je mu přiřazena, nemění. Proto \verb předpokládá, že je prvním příkazem, který se dívá na svůj textový parametr. Není-li tomu tak, TeX již přiřadil kategorie jednotlivým znakům a \verb již nemá šanci kategorii měnit. Například:

    \verb+\error+
bude fungovat (vysází se ,,\error``), ale
    \newcommand{\unbrace}[1]{#1}
    \unbrace{\verb+\error+}
fungovat nebude (pokusí se spustit příkaz \error).

Proto se také v manuálu LaTeXu tolik naléhá na to, aby se příkaz verbatim neobjevil v argumentu žádného jiného příkazu. Tyto příkazy jsou nejen křehké (fragile), ale dokonce zcela nepoužitelné jako parametr jiných příkazů, bez ohledu na ochranu pomocí Proč se v LaTeXu užívá ochran (protection).


Chyby související se změnou velikosti písmen

TeX poskytuje dva primitivní příkazy umožňující konverzi textu do malých písmen, \lowercase, a velkých písmen, \uppercase. Tyto příkazy se nepoužívají příliš často, ale dokáží nadělat v dokumentu zmatek.

Oba příkazy nerozvíjejí text, který je jejich parametrem -- výsledkem příkazu \uppercase{abc} je ,,ABC``, avšak výsledek příkazu \uppercase{\abc} je \abc ať už \abc znamená cokoli. Příkazy jednoduše interpretují tabulku ekvivalentů mezi velkými a malými formami znaků. Nemají například smysl pro matematiku, a tak

  \uppercase{About $y=f(x)$}
dává
  ABOUT $Y=F(X)$
což zřejmě není to, co jsme původně zamýšleli.

Stejný problém může vzniknout s názvy prostředí v LaTeXu, když LaTeX užívá implicitně \uppercase. Například standardní třídy užívají \uppercase k nastavení záhlaví podle argumentu příkazů \chapter\section, takže kapitola, jejíž nadpis obsahuje malou tabulku vyjádřenou pomocí \begin{tabular} ... \end{tabular}, nastaví obsah záhlaví na \begin{TABULAR}, atd., což je však prostředí, které vůbec neexistuje.


Proč je znak # v makrech uveden dvakrát

Při psaní makra je třeba mít na paměti, že ## zastupuje # obdobně jako #1 zastupuje cokoli, co je prvním argumentem makra.

Definujeme-li a poté použijeme makro:

  \def\a#1{...#1...#1...#1...}  \a{b}
makro po expanzi dává ,,...b...b...b...``, což jsme očekávali. Avšak dosadíme-li nyní za ,,...``:
  \def\a#1{---#1---\def\x #1{xxx#1}}
\a{b} se rozvine na ,,---b---\def\x b{xxxb}``. Definuje se zde makro \x, které je ohraničené znakem b a které nemá žádný argument. Může se to zdát divné, ačkoli jde jen o zvláštní případ předchozího příkladu. Chceme-li, aby v \a bylo definováno makro \x s jedním argumentem, musíme upravit předchozí makro takto:
  \def\a#1{---#1---\def\x ##1{xxx##1}}
\a{b} se nyní rozvine do tvaru ,,---b---\def\x #1{xxx#1}``, neboť #1 bude nahrazeno znakem `b' a ## bude nahrazeno #.

Pro definici vnořenou uvnitř definice uvnitř definice se použije ####1, jelikož v každé úrovni je ## nahrazeno #. V další úrovni je nutné použít osm #, atd.


CSTUG
(c) 12.05.2000 18:52 Libor Škarvada, Tomáš Hudec, Aleš Vítek
Připomínky, opravy a zejména odpovědi na další časté otázky posílejte na adresu cstug-faq@cstug.cz
Připomínky k HTML verzi posílejte na adresu libor@fi.muni.cz nebo hudec@fi.muni.cz.