Работа в системе LaTeX

Создание новых команд

Разбить на страницы
Показывать лекцию целиком

Средства LaTeX'а, описываемые в этой лекции, позволяют сократить число нажатий на клавиши при наборе сложных текстов. Именно, мы расскажем, как создавать новые команды (или, если угодно, сокращенные обозначения), заменяющие собой длинные фрагменты из текста и TeX'овских команд. Официально такие новые команды называются макроопределениями, а в разговорной речи — макросами.

Макроопределения

Команды без аргументов

Начнем с примера. Пусть вы пишете текст, в котором регулярно встречается математический значок $$\stackrel{\rm def}{=}$$ (он означает " равно по определению"). Пользуясь тем, что вы узнали из лекции 2 , нетрудно понять, что генерируется этот значок внутри математической формулы такой последовательностью команд:

\stackrel{\mathrm{def}}{=}

Часто писать такой длинный набор команд утомительно. Вот бы в LaTeX'е была предусмотрена команда, скажем, \eqdef, генерирующая символ бинарного отношения $$\eqdef$$,! Правда, такой команды нет, но мы ее можем создать. Для этого следует написать так:

\newcommand{\eqdef}{\stackrel{\mathrm{def}}{=}}

После того как TeX прочтет эту строку, он всюду, встречая команду \eqdef, будет реагировать точно так же, как если бы он видел текст \stackrel{\mathrm{def}}{=}. Например, формула $${x^2\eqdef x\cdot x}$$ теперь получается так:

x^2\eqdef x\cdot x

Новая команда TeX'а, которую мы определили, называется макросом (еще говорят: макроопределение, макрокоманда, макро). Рассмотрим точные правила для создания макросов средствами LaTeX'а.

Для создания макросов используется команда \newcommand. Эта команда имеет два обязательных аргумента. Первый из них — имя, которое вы придумали для вашего макроса. Имена макросов должны подчиняться тем же правилам, что имена TeX'овских команд, либо backslash и после него одна не-буква, либо backslash и после него — последовательность букв. Второй обязательный аргумент команды \newcommand, называемый " замещающим текстом", сообщает TeX'у смысл макроса: на этот текст ваш макрос будет замещаться в процессе трансляции (как говорят, макрос будет "разворачиваться").

При пользовании командой \newcommand нельзя в качестве имени макроса выбирать имя уже существующей команды или окружения (если вы попробуете так сделать, LaTeX выдаст сообщение об ошибке).

Во втором аргументе команды \newcommand (иными словами, в "замещающем тексте") вместе с каждой открывающей фигурной скобкой должна присутствовать соответствующая ей закрывающаяФигурные скобки, входящие в состав команд \{ \}, в счет при этом не идут., так что определения наподобие

\newcommand{\nachatkursiv}}
\newcommand{\konchitkursiv}{}}

приведут в лучшем случае к сообщению об ошибке (и желаемого эффекта не дадут). Если вам кажется, что такие ограничения стеснительны, можете изучить по книге [2], как их обходить; для большинства практических целей возможности создания макроопределений, предоставляемые LaTeX'ом, вполне достаточны.

К сожалению, некоторые русификации TeX'а не позволяют использовать в именах макросов русские буквы.

Еще одно ограничение: имя новой команды не должно начинаться на end.

Наконец, в замещающем тексте макроопределения нельзя пользоваться командой \verb или окружением {verbatim}.

Если команда \newcommand дана внутри группы, то смысл определяемой ею новой команды будет забыт TeX'ом по выходе из группы. Если новая команда определяется в преамбуле, то, естественно, она будет понятна TeX'у на протяжении всего документа.

Давайте теперь разберем несколько примеров, обращая внимание на типичные ошибки.

Макросы хороши как средство скорописи. Например, если в вашем тексте часто встречается знак $$\bigtriangleup$$, то вам может надоесть все время писать длинную команду \bigtriangleup. Коли так, придумайте сокращенное обозначение (скажем, \btu ), напишите в преамбуле

\newcommand{\btu}{\bigtriangleup}

и вы сможете писать формулы наподобие

$$(A\bigtriangleup B)\cap C= (A\cap C)\bigtriangleup (B\cap C)$$
$(A\btu B)\cap C=
(A\cap C)\btu (B\cap C)$

Ранее было рассказано, что делать, чтобы создать согласующееся с нашими традициями обозначение для тангенса. Теперь мы понимаем, что это был пример макроопределения (если вам интересно знать, что значит команда \mathop в замещающем тексте).

В лекции 2 вы найдете массу других примеров громоздких конструкций, для которых имеет смысл создать макросы.

А теперь — пример типичной ошибки. Пусть в тексте, который вы набираете, регулярно встречаются фразы наподобие

Подмногообразия проективного пространства $$\mathbf{P}^n$$ - основной объект изучения алгебраической геометрии,

и пусть для сокращения письма вы написали в преамбуле

\newcommand{\Pn}{$\mathbf P^n$}

Теперь можно писать, например, так:

... пространства~\Pn{} - основной объект...

Однако для набора формулы $$x\in\mathbf P^n$$ написать $x\in\Pn$ не удастся: появится сообщение о том, что символ ^ и команда \mathbf преступно употреблены вне математической формулы. Причина проста: TeX исправно подставляет вместо \Pn тот "замещающий текст", который вы ему сообщили во втором аргументе команды \newcommand. В результате этого при развертывании макроса \Pn текст $x\in\Pn$ превращается в незаконный текст $x\in$\mathbf P^n$$, в котором математическая формула заканчивается со вторым из знаков доллара, а символ ^ оказывается посреди обычного текста. Чтобы можно было напечатать $$\mathbf{P}^n$$ не только изолированно, не надо включать знаки доллара в определение:

\newcommand{\Pn}{\mathbf{P}^n}

При этом придется, конечно, ставить знаки доллара вокруг \Pn в тех случаях, когда в тексте встречается просто $$\mathbf{P}^n$$, но зато наш макрос можно будет использовать и как составную часть более сложных формул.

Есть, впрочем, и более удачный способ борьбы с этой проблемой: определите \Pn как

\newcommand{\Pn}{\ensuremath{\mathbf{P}^n}}

(без всяких знаков доллара) — и вы сможете спокойно пользоваться своей новой командой \Pn как в тексте, так и в формулах:

Пусть \Pn~ — $n$---мерное проективное пространство,
а $X\subset \Pn$~ — неприводимое многообразие...

(знаки ~ мы поставили, чтобы строчка не смогла начаться с тире —c.103). Команда \ensuremath всегда обрабатывает свой аргумент как математическую формулу, независимо от того, в тексте или в формуле вы ее используете.

Создавать макросы полезно не только для сокращения числа нажатий на клавиши при наборе формул. Вот пример, когда макросы помогают и при наборе обычного текста. Предположим, в нашем тексте много задач, причем условие каждой из задач начинает новый абзац (как обычно и бывает). Предположим также (временно), что эти задачи никак не нумеруются. Слово "Задача", с которого начинается условие, хочется как-то выделить в тексте; предположим, мы решили выделять его жирным шрифтом. Давайте создадим макрос, который будет делать все это за нас, чтобы можно было не печатать каждый раз слово "Задача", а просто написать \z. Первым обычно приходит в голову что-нибудь такое:

\newcommand{\z}{\bfseries Задача}

Посмотрите, что из этого выйдет:

$$\parindent=0cm \newcommand{\z}{\bfseries Задача}\z. Пять парней за пять дней съели пять окуней. За сколько дней пятнадцать парней съедят пятнадцать окуней$$?
\z. Пять парней за пять дней
съели пять окуней. За сколько
дней пятнадцать парней
съедят пятнадцать окуней?

Почему же жирным шрифтом напечаталось не только слово "Задача", но и весь дальнейший текст? Ответ: TeX опять пунктуально заменил \z на "замещающий текст", в результате чего получилось вот что:

\bfseries Задача. Пять парней ...

Команда \bfseries оказалась не внутри группы, и весь текст напечатался жирным шрифтом. Чтобы не попадаться в такую ловушку, надо помнить, что при развертывании макроса фигурные скобки, ограничивающие замещающий текст в команде \newcommand, отбрасываются. Правильнее было бы дать такое определение:

\newcommand{\z}{\bfseries {Задача}}"

На сей раз \z будет заменяться на {\bfseries Задача} (отбрасывается внешняя пара фигурных скобок, ограничивающая второй аргумент команды \newcommand, и только она!). А можно (это, пожалуй, даже лучше) написать и так:

\newcommand{\z}{\textbf{Задача}}

Впрочем, наш макрос \z еще не идеален. Во-первых, после слова, напечатанного жирным шрифтом, точку лучше поставить тоже жирным шрифтом, поэтому разумно и ее включить в макроопределение. Далее, согласно общему правилу игнорирования пробелов после имени команды, состоящего из букв, в тексте при этом нельзя будет написать

\z Пять парней...

так как при этом пропадет пробел между словом "Задача." и следующим словом. Можно этот пробел, как водится, всякий раз специально организовывать и писать

\z{} Пять парней...

но лучше вставить и пробел прямо в определение:

\newcommand{\z}{\textbf{Задача. }}

Теперь запись \z Пять парней... даст то, что нужно. Впрочем, если угодно, вот еще один штрих. Если вы в какой-нибудь момент забудете оставить пустую строку перед очередной задачей, то слово "Задача" при этом будет не начинать абзац, а продолжать предшествующий текст. Чтобы этого раз и навсегда избежать, можно вставить команду "закончить абзац" в наше макроопределение. Как вы помните, эта команда называется \par:

\newcommand{\z}{\par\textbf{Задача. }}

Если перед нашим макросом \z пустая строка все-таки будет, то лишняя команда \par ни на что не повлияет, а если ее не будет, то \par сыграет роль недостающей пустой строки.

Если какой-то элемент текста оформлен с помощью макроса, становится удобно менять это оформление. Например, если вдруг понадобилось оформлять все задачи так, чтобы соответствующие абзацы начинались без отступа, достаточно внести небольшое изменение в наше определение команды \z:

\newcommand{\z}{\par\noindent\textbf{Задача. }}

Если бы каждую задачу мы оформляли вручную, нам пришлось бы перед каждым словом "Задача" вписывать команду \noindent. В дальнейшем, познакомившись с LaTeX'овскими " счетчиками", мы усовершенствуем наш макрос \z таким образом, чтобы он еще и автоматически нумеровал задачи.

Мы уже говорили, что переопределить значение уже существующей команды с помощью \newcommand невозможно. Иногда, однако, это бывает необходимо. Пример тому приведен в лекции 3 : если мы хотим, чтобы в заголовках глав печаталось именно слово "Глава", а не " Chapter", то необходимо определить по-новому команду \chaptername. Для такого рода целей используется команда \renewcommand. Она устроена точно так же, как \newcommand, с тем отличием, что в качестве ее первого аргумента надо указывать имя уже существующей команды; в этом случае по выполнении команды \newcommand значение этой команды изменится: она превратится в сокращенное обозначение для текста, указанного в качестве ее второго аргумента. Например, если написать

\renewcommand{\alpha}{Ку-ку}

то команда \alpha будет генерировать не то, что обычно (букву $$\alpha$$ в математической формуле и сообщение об ошибке, если эта команда употреблена вне математической формулы), а текст "Ку-ку".

Если команда \renewcommand дана внутри группы, то созданное ею переопределение значения команды забудется по выходе из этой группы. Если в качестве первого аргумента команды \renewcommand указать имя несуществующей команды, то вы получите сообщение об ошибке.

Команда \renewcommand при неаккуратном обращении может привести к неприятностям. Дело в том, что нередко команды LaTeX'а определяются в терминах других команд LaTeX'а, причем знать эти сложные связи рядовой пользователь вовсе не обязан. На практике такое незнание может привести к тому, что безобидное на первый взгляд использование в своих целях имени какой-нибудь команды, которая в вашем тексте ни разу не встречается, вызовет необъяснимо неправильную работу других команд. Поэтому используйте \renewcommand только тогда, когда вы полностью отдаете себе отчет в своих действиях.

Выше мы часто называли макросы просто командами, и это — не просто небрежность речи: на самом деле принципиальной разницы между макросами и TeX'овскими командами почти нет. В частности, почти все команды LaTeX'а, о которых говорилось и еще будет говориться в нашей книге, являются именно макросами; в отличие от макросов, создаваемых нами с помощью \newcommand, их смысл уже известен TeX'у к моменту запуска программы, так что определять их каждый раз не нужно. Макросы, в свою очередь, могут ссылаться на другие макросы (кстати, команда \stackrel, на которую ссылалась наша команда \eqdef, также является макросом) - и так далее, пока не дойдет до так называемых "примитивных команд" TeX'а. Из команд, о которых мы вам рассказывали, примитивными являются считанные единицы: \left, \right, \noindent и некоторые другие.

Команды с аргументами

Мы уже научились создавать новые команды, не требующие аргументов. Но мы хорошо знаем, что многие LaTeX'овские команды принимают аргументы, и часто возникает потребность создать новую команду с такими возможностями. Пусть, например, в вашем тексте часто встречается "символ Лежандра", выглядящий так: $$\smb{a}{l}.$$ Для получения этого символа в исходном тексте надо написать (внутри формулы, естественно) так:

\left(\frac{a}{l}\right)

Хорошо бы создать команду \smb с двумя аргументами, чтобы можно было написать в формуле "\smb{a}{l}" и получить на печати $$\smb{a}{l}.$$ Что ж, LaTeX предоставляет нам возможность сделать и это. Для создания команды с аргументами используется все та же команда \newcommand, но с необязательным аргументомМожно (и разумно) использовать в этой ситуации команду \newcommand* (" вариант со звездочкой"). См. по этому поводу ниже.. Посмотрите, как можно определить команду \smb:

\newcommand{\smb}[2]{\left(\frac{#1}{#2}\right)}

Разберем, что означает эта запись. В квадратных скобках стоит количество аргументов в нашем макросе (в нашем случае 2). Далее, в самом "замещающем тексте" появились значки "#1" и "#2" . При развертывании макроса на их место будут подставляться соответственно первый и второй аргументы нашей новой команды \smb. Например, если в формуле написать

\smb{a+b}{c}

то будет напечатано $$\smb{a+b}{c}.$$

Теперь рассмотрим точные правила. Необязательный аргумент команды \newcommand, который должен быть расположен между двумя обязательными, указывает, сколько аргументов будет требовать создаваемая вами команда (макрос). Это количество аргументов не может быть более 9. В "замещающем тексте" места, на которые при развертывании макроса будут подставляться аргументы, обозначаются символами "#1" для первого аргумента, "#2" для второго аргумента и т.д. Эти символы могут идти в любом порядке и присутствовать любое количество раз (в том числе и ни разу). Когда мы будем использовать нашу новую команду в тексте, после ее имени в фигурных скобках должны будут следовать аргументы, ровно в том количестве и в том порядке, который мы указывали в необязательном аргументе команды \newcommand, каждый — в своей паре фигурных скобок (как обязательные аргументы любой другой LaTeX'овской команды). При развертывании макроса на место его и его аргументов будет подставлен " замещающий текст", в котором вместо "#1" всюду стоит первый аргумент, вместо "#2" — второй аргумент и т.д.

Проиллюстрируем все сказанное примером. Пусть мы определили команду \shuffle следующим образом:

\newcommand{\shuffle}[4]{К#4к#2#1л}

Тогда будет получаться, например, такое:

$$\parindent=0cm \newcommand{\shuffle}[4]{К#4к#2#1л}\shuffle{ди}{о}{го}{ро} Гена и его друзья.$$
\shuffle{ди}{о}{го}{ро}
Гена и его друзья.

В самом деле, первым аргументом команды \shuffle будет ди, вторым о, третьим го, четвертым ро; при развертывании появится сначала буква К, затем четвертый аргумент, затем буква к, затем второй, первый и наконец буква л — как если бы слово Крокодил присутствовало в исходном тексте.

Ни аргументы LaTeX'овских команд (в том числе и определенных вами), ни "замещающий текст" в \newcommand не должны содержать "несбалансированных" (не имеющих пары) фигурных скобок (это не относится к \{ и \} ).

Если вы хотите создать макрос с аргументами, имя которого совпадает с именем уже существующей команды, то надо воспользоваться командой \renewcommand с необязательным аргументом. Место постановки и значение этого необязательного аргумента, а также правила употребления символов #1, #2 и т.д. при этом будут такие же, как для команды \newcommand.

Приведем еще один пример практически полезного макроса с аргументами. При написании этой книги автор широко пользовался ссылками на страницу, автоматически генерируемыми с помощью команды \pageref. Например, если какое-то место в тексте было помечено с помощью команды \label{units}, то ссылка на соответствующую страницу выглядела так:

Как мы уже отмечали на с. \pageref{units}, ...

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

\newcommand{\str}[1]{стр. \pageref{#1}}

и ссылки на страницы стало возможно оформлять так:

Как мы уже отмечали
на \str{units}, ...

(Автор вначале не знал, что надо писать "с.", а не " стр.", но мгновенно исправился, всего лишь удалив две буквы из определения команды \str!)

Команда \newcommand со звездочкой

У команд \newcommand и \renewcommand существуют варианты " со звездочкой", называемые \newcommand* и \renewcommand. Они работают точно так же, как их тезки без звездочек, со следующим отличием: если команда с аргументами определена с помощью \newcommand* или \renewcommand*, то в ее аргументе не может содержаться пустая строка или команда \par. Если ваша команда определена с помощью \newcommand или \renewcommand без звездочки, то никаких ограничений на этот счет нет.

Смысл этого запрета таков. В большинстве случаев команды с аргументами, которые вы определяете, все равно не будут предусматривать подстановку вместо аргумента фрагмента текста, содержащего пустую строку или \par, так что этот запрет ни на чем не скажется (во всех примерах, приведенных в этой книге к настоящему моменту, можно совершенно безболезненно заменить \newcommand и \renewcommand на их варианты " со звездочкой"). А вот диагностика ошибок при наличии такого запрета облегчается. В самом деле, представим себе, что вы забыли набрать закрывающую фигурную скобку в аргументе команды (весьма распространенная ошибка!), как в следующем примере (забыта фигурная скобка в самой первой формуле; команду \smb мы определили в учебных целях раньше):

Символ Лежандра $\smb{a{l}$, где $a$ не делится
на $l$,
равен по определению $1$, если $a$ является квадратичным
вычетом по модулю $l$, и $-1$ в противном случае.

Вопрос о том, как зависит $\smb{a}{l}$ от $l$ при
фиксированном $a$, является весьма важным и трудным.
Великий немецкий математик К.-Ф.Гаусс...

Если пустые строки в аргументе команды \smb не запрещены (так оно и будет, если определять \smb с помощью \newcommand без звездочки), то TeX будет терпеливо ждать, когда ему встретится закрывающая фигурная скобка, парная к первой из открывающих фигурных скобок в первой строке, а пока таковой нет — рассматривать весь читаемый им текст как составную часть первого аргумента команды \smb. В конце концов TeX либо доложит, что он прочел уже весь файл, а закрывающей фигурной скобки так и не нашел, либо прервет работу, объявив, что ему не хватило памяти.

Если же мы определим \smb с помощью \newcommand*, написав

\newcommand*{\smb}[2]{\left(\frac{#1}{#2}\right)}

то ошибка не пойдет дальше текущего абзаца: как только TeX увидит пустую строку среди текста, рассматриваемого им как аргумент команды, он тут же прервет дальнейшее чтение и выдаст следующее стандартное сообщение об ошибке:

Runaway argument?
{a{l}$, где$a$ не делится на $l$, равен п\ETC.
! Paragraph ended before \smb was complete.
<to be read again>
                   \par
l.8

?

Нажав пару раз на "ввод", мы сможем благополучно продолжить обработку текста. В первом абзаце пропадет все после слов "Символ Лежандра", зато второй и последующие абзацы будут обработаны нормально (пока TeX не наткнется на очередную ошибку...).

Команды \newcommand* и \renewcommand* обладают еще одним преимуществом перед своими вариантами без звездочек: при их использовании происходит (небольшая) экономия памяти.

Рекомендуем вам определять и переопределять команды с аргументами при помощи \newcommand* и \renewcommand*. Варианты без звездочек используйте только тогда, когда вы действительно намерены подставлять в аргумент своего макроса текст, состоящий из нескольких абзацев.

Счетчики

Теперь мы научимся самостоятельно организовывать автоматическую нумерацию, подобно тому, как LaTeX автоматически нумерует главы, страницы, формулы и т.д. Для этого нам надо познакомиться с понятием счетчика. Счетчик — это специальная переменная, значение которой является целым числом. Ей можно присваивать различные значения, выводить значение счетчика на печать, а также организовывать с помощью счетчиков автоматическую генерацию ссылок. Рассмотрим последовательно, как все это делается.

Создание счетчиков и простейшие операции с ними

Каждый LaTeX'овский счетчик имеет свое имя — последовательность букв (без знака \ ). Прописные и строчные буквы в именах счетчиков различаются; если в используемой вами русификации русские буквы нельзя употреблять в именах команд, то нельзя их употреблять и в именах счетчиков. Чтобы можно было работать со счетчиком, надо его создать командой \newcounter, имеющей один обязательный аргумент — имя, которое вы придумали для счетчика. Например, команда

\newcounter{abcd}

создает новый счетчик с именем abcd. Если имя, которое вы придумали для счетчика, уже занято (так может случиться, даже если команда \newcounter в вашем тексте всего одна: некоторые счетчики в LaTeX'е уже определены в момент начала обработки вашего текста), то LaTeX создавать счетчик с таким именем откажется и выдаст сообщение об ошибке.

В отличие от многих других LaTeX'овских команд, команда для создания нового счетчика является "глобальной": даже если она давалась внутри группы, LaTeX не забудет о существовании определенного ею счетчика и после выхода из этой группы. Это отличает \newcounter от \newcommand и \renewcommand.

Что же можно делать со счетчиком? Во-первых, можно менять его численное значение (на программистском жаргоне: "присваивать счетчику различные значения"). При создании счетчика его значение устанавливается в $$0$$ ; чтобы установить какое-то другое значение, используется команда \setcounter, имеющая два обязательных аргумента: первый — имя счетчика, второй — значение, которое счетчику присваивается. Если, например, написать

\setcounter{abcd}{1998}

то после того, как TeX прочтет эту команду, значение счетчика abcd установится равным $$1998.$$ Значение, которое присваивается счетчику, может быть и отрицательным, но обязано быть целым.

Другой способ изменить значение счетчика — это прибавить к нему какое-то целое число. Для этого используется команда \addtocounter. Эта команда также имеет два обязательных аргумента: первый — имя счетчика, второй — число, которое прибавляется к счетчику. Например, после выполнения команд

\setcounter{abcd}{100}
\addtocounter{abcd}{-27}

значением счетчика abcd будет число $$73.$$

Команды, изменяющие значение счетчика, также являются " глобальными": если с их помощью внутри группы значение счетчика было изменено, то по выходе из группы его прежнее значение не восстановится.

Перейдем к самому главному: как вывести значение счетчика на печать. Самый распространенный случай — печать значения счетчика обычными (" арабскими") цифрами. Для этого используется команда \arabic:

$$\parindent=0cm \newcounter{abcd}\setcounter{abcd}{40} Шел по улице отряд - \arabic{abcd} мальчиков подряд.$$
\setcounter{abcd}{40}
Шел по улице отряд -
\arabic{abcd}
мальчиков подряд.

Значение счетчика печатается текущим шрифтом: если значение счетчика равно, скажем, 2003, то на команду \arabic{abcd} TeX отреагирует так же, как если бы на ее месте в исходном тексте было написано 2003.

Чтобы напечатать значение счетчика римскими цифрами, надо воспользоваться командой \Roman (если мы хотим, чтобы римские цифры записывались прописными латинскими буквами) или \roman (чтобы записать римскую цифру строчными латинскими буквами):

$$\parindent=0cm \newcounter{abcd}\setcounter{abcd}{14} Людовика \Roman{abcd} звали ``Король-Солнце''.$$
\setcounter{abcd}{14}
Людовика \Roman{abcd} звали
``Король-Солнце''.

Естественно, при печати значения счетчика римскими цифрами это значение должно быть положительным числом.

Можно, наконец, напечатать букву латинского алфавита, порядковый номер которой равен значению счетчика. Для этого используются команды \alph (для печати строчной буквы) и \Alph (для печати прописной буквы):

$$\parindent=0cm \newcounter{abcd}\setcounter{abcd}{7} Наконец я узнаю, какая буква стоит в латинском алфавите на седьмом месте! Вот она: \alph{abcd}.$$
\setcounter{abcd}{7}
Наконец я узнаю, какая буква
стоит в латинском алфавите
на седьмом месте!
Вот она: \alph{abcd}.

Если значение счетчика при пользовании этими командами превышает количество букв в латинском алфавите, то LaTeX выдает сообщение об ошибке.

В LaTeX'е отсутствует команда, позволяющая напечатать русскую букву с номером, равным значению счетчика. Средствами TeX'а такую команду нетрудно создать.

Наконец, можно напечатать один из девяти символов, используемых иногда в англоязычных странах для обозначения последовательных сносок (вместо цифр). Для этого используется команда \fnsymbol, применять которую можно только внутри формул:

$$\parindent=0cm \newcounter{abcd}\setcounter{abcd}{0} Для сносок в Англии применяют такие символы: $\addtocounter{abcd}{1}\fnsymbol{abcd}$, $\addtocounter{abcd}{1}\fnsymbol{abcd}$, $\addtocounter{abcd}{1}\fnsymbol{abcd}$, а дальше попробуйте сами.$$
\setcounter{abcd}{0}
Для сносок в Англии
применяют такие символы:
$\addtocounter{abcd}{1}
\fnsymbol{abcd}$,
$\addtocounter{abcd}{1}
\fnsymbol{abcd}$,
$\addtocounter{abcd}{1}
\fnsymbol{abcd}$,
а дальше попробуйте сами.

Обратите внимание, как три идентичных фрагмента исходного текста дали на печати три разных символа.

В командах для изменения значений счетчиков можно вместо явного указания чисел использовать значения других счетчиков, для чего употребляется команда \value. Например, в результате выполнения команд

\newcounter{efgh}
\setcounter{abcd}{10}
\setcounter{efgh}{100}
\addtocounter{efgh}{-\value{abcd}}

значение счетчика efgh станет равно $$90.$$ Можно даже писать, например,

\setcounter{efgh}{1000}
\tolerance=\value{efgh}

но большого смысла в таких трюках, как правило, нет.

Применим наши познания к делу. Ранее мы обещали вам так усовершенствовать макрос \z, начинающий новый абзац и печатающий жирным шрифтом слово "Задача", чтоб он еще и автоматически нумеровал эти задачи, так, что можно было бы просто писать в исходном тексте

\z Найти сумму...
\z Решить уравнение...
\z Поезд вышел из пункта А...

и при этом знать, что номера LaTeX проставит сам. Теперь мы в состоянии решить эту проблему. Во-первых, для этого надо создать счетчик, значение которого в каждый момент будет равно номеру последней обработанной задачи; во-вторых, в определении команды \z надо предусмотреть, чтобы всякий раз значение этого счетчика увеличивалось на единицу, а затем печаталось в качестве номера задачи. В качестве имени счетчика выберем бесхитростное "zadacha":

\newcounter{zadacha}

(напомним, что при выполнении этой команды счетчику zadacha будет присвоено значение $$0$$ ). Теперь модифицируем определение макроса \z так:

\newcommand{\z}{\par\addtocounter{zadacha}{1}%
\textbf{Задача \arabic{zadacha}.} }

Напомним, что команда \par означает "завершить предыдущий абзац, если он еще не был завершен"; без нее можно обойтись, если мы будем ставить команду \z только после пустой строки. Знак процента мы поставили, чтобы убрать лишний пробел, порождаемый концом строки. Теперь при первом исполнении команды \z значение счетчика zadacha станет равно $$1$$ и будет напечатано "Задача 1.", при втором исполнении этой команды значение счетчика станет равно уже $$2$$ и напечатается "Задача 2."... и т.д., что нам и нужно!

Отношение подчинения между счетчиками

Команда \z, как мы ее определили ранее, нумерует задачи автоматически, но при этом нумерация получается " сплошной". Часто, однако, требуется, чтобы в каждом разделе документа нумерация задач начиналась заново, так что шестая задача в разделе с номером 3 была озаглавлена Задача 3.6, а первая задача в разделе с номером 4 — Задача 4.1. Сейчас мы узнаем, как этого добиться.

Выше мы упоминали, что к моменту начала обработки LaTeX'ом нашего текста некоторые счетчики уже определены. В частности, это счетчики, содержащие номера текущих разделов документа. Их имена совпадают с именами команд, генерирующих эти разделы: chapter (если классом предусмотрено разбиение на главы), section, subsection и т.д. При каждом исполнении, например, команды \section значение счетчика section увеличивается на 1, и значение этого счетчика в каждый момент равно номеру текущего раздела. Поэтому, если в определении команды \z написать

\arabic{section}.\arabic{zadacha}.

то перед номером задачи будет печататься номер текущего раздела и точка.

Но как же все-таки сделать, чтобы в каждом разделе нумерация задач начиналась заново? Можно, конечно, в начале каждого раздела присваивать счетчику zadacha значение $$0$$ с помощью \setcounter, но это некрасиво и ненадежно (а вдруг забудем?). Лучше сразу определить счетчик zadacha так:

\newcounter{zadacha}[section]

При этом счетчик zadacha будет подчинен счетчику section: всякий раз, когда значение счетчика section увеличивается на единицу командой \section, значение счетчика zadacha будет устанавливаться в нуль, и тем самым счет задач будет в каждом разделе начинаться заново. Одновременно надо в очередной раз исправить определение команды \z и написать

\newcommand{\z}{\par\addtocounter{zadacha}{1}%
\textbf{Задача \arabic{section}.\arabic{zadacha}.} }

При этом нумерация задач будет начинаться заново в каждом разделе, и вторая задача третьего раздела будет иметь номер 3.2.

Теперь сообщим точные правила создания счетчика, подчиненного другому счетчику. Они просты: команда \newcounter может принимать один необязательный аргумент ( после обязательного) — имя того счетчика, которому будет подчинен определяемый нами счетчик. Разумеется, в момент выполнения команды \newcounter с необязательным аргументом счетчик, имя которого дается в квадратных скобках, должен уже существовать.

Надо еще уточнить, в каких случаях значение подчиненного счетчика устанавливается в нуль. В самом деле, пусть счетчик slave подчинен счетчику master; тогда команда

\addtocounter{master}{1}

никоим образом не повлияет на значение подчиненного счетчика \slave: изменение значений счетчика влияет на значения подчиненных ему счетчиков только в том случае, если значение подчиняющего счетчика изменялось с помощью специальных команд. Таких команд всего две, из них чаще всего используется \refstepcounter: она увеличивает на единицу значение указанного ей счетчика, а значения всех подчиненных ему счетчиков устанавливает в нуль. Пусть, например, в нашем тексте определены два счетчика:

\newcounter{master}
\newcounter{slave}[master]

Тогда после выполнения команд

\setcounter{master}{10}
\setcounter{slave}{10}

значения обоих счетчиков станут равны $$10$$, после выполнения команды

\addtocounter{master}{1}

значение счетчика master станет равно $$11$$ и значение счетчика slave не изменится, а вот после выполнения команды

\refstepcounter{master}

значение счетчика master станет равно $$12$$, в то время как значение счетчика slave станет равно нулю.

Наряду с \refstepcounter существует еще одна команда, изменяющая значение счетчика таким образом, что значения всех подчиненных ему счетчиков устанавливаются в нуль. Эта команда называется \stepcounter ; она также увеличивает на единицу значение счетчика, имя которого является ее аргументом, и при этом обнуляет все подчиненные ему счетчики, но она непригодна для организации автоматических ссылок, вследствие чего область ее применения более ограничена.

Хороший пример использования подчиненных счетчиков дают стандартные LaTeX'овские классы документов. Например, в классе book перед началом обработки текста выполняются следующие команды:

\newcounter{part}
\newcounter{chapter}
\newcounter{section}[chapter]
\newcounter{subsection}[section]
\newcounter{subsubsection}[subsection]
\newcounter{paragraph}[subsubsection]
\newcounter{subparagraph}[paragraph]

Стало быть, нумерация глав не зависит от нумерации частей (если третья часть книги завершается десятой главой, то четвертая часть начинается с одиннадцатой главы), а нумерация разделов уже начинается заново в каждой главе.

Организация автоматических ссылок

Вернемся последний раз к нашей команде \z. Раз она автоматически нумерует задачи, то неплохо было бы, если б пронумерованные ею задачи можно было метить командой \label и ссылаться на эти метки командой \ref ссылка на счетчик, определенный пользователем} (проблема именно в ней, поскольку команда \pageref, дающая номер страницы, сработает в любом случае). Если коротко, то решение этой проблемы таково: увеличивать на единицу значение счетчика \ctr{zadacha} надо не с помощью команды \addtocounter, которой мы пользовались до сих пор, а с помощью команды \refstepcounter, о которой уже шла речь по другому поводу в предыдущем разделе. Если мы определим команду \z так:

\newcommand{\z}{\par\refstepcounter{zadacha}%
\textbf{Задача \arabic{section}.\arabic{zadacha}.} }

то после этого можно будет написать, например, так:

\z Решить уравнение...
\z Доказать...\label{prove}
\z Найти сумму...

Если теперь в другом месте текста мы сошлемся на помеченную задачу так:

В задаче \ref{prove} предлагалось доказать...

то будет печататься ее номер (тот самый, который LaTeX автоматически ей присвоил). Впрочем, с такими автоматическими ссылками не все будет благополучно: если помеченная нами задача была второй по счету в разделе номер 3, то называться она будет Задача 3.2, а вот ссылка на нее, сгенерированная командой \ref, будет выглядеть просто

В задаче 2 предлагалось доказать...

в то время как хотелось бы автоматически получить В задаче 3.2. Иными словами, надо изменить текст, генерируемый командой \ref. Чтобы узнать, как этого добиться, нам придется познакомиться с еще одной LaTeX'овской конструкцией, связанной со счетчиками.

Мы уже знаем, что значение LaTeX'овского счетчика можно вывести на печать командами \arabic, \roman и т.п. Однако, кроме этого, с каждым счетчиком связана индивидуальная команда, определяющая, в какой форме его значение будет выводиться на печать, и именно в соответствии с этой командой печатается ссылка, сгенерированная с помощью \label и \ref. Имя этой команды получается, если поставить the перед именем счетчика. Например, команда для вывода на печать номера раздела называется \thesection, для вывода на печать номера главы — \thechapter, команды для вывода на печать определенных нами счетчиков slave и master — \theslave и \themaster. При создании счетчика автоматически определяется и соответствующая the-команда. Именно, при создании счетчика по имени, скажем, abcd автоматически определяется команда \theabcd таким образом:

\newcommand{\theabcd}{\arabic{abcd}}

В дальнейшем эту команду можно переопределять:

$$\parindent=0cm \newcommand{\theabcd}{\arabic{abcd}} \renewcommand{\theabcd}% {\Roman{abcd}} \setcounter{abcd}{14} Людовика \theabcd{} звали ``Король-Солнце''.$$
\renewcommand{\theabcd}%
{\Roman{abcd}}
\setcounter{abcd}{14}
Людовика \theabcd{} звали
``Король-Солнце''.

Мы же, чтобы при ссылках перед номером задачи печатался номер раздела, в котором находится эта задача, и точка, переопределим команду \thezadacha так:

\renewcommand{\thezadacha}{\thesection.\arabic{zadacha}}

Если включить эту команду в преамбулу документа, то ссылки на сгенерированные нашей командой \z номера задач будут выглядеть должным образом.

В нашем переопределении команды \thezadacha мы воспользовались командой \thesection, чтобы наши макросы правильно работали с любым классом документов. Дело в том, что при разумном оформлении номер раздела, предшествующий при ссылке номеру задачи, должен печататься таким же образом, как и номер раздела при ссылке на раздел, а это в разных классах делается по-разному: в классе article, например, \thesection — это то же самое, что и \arabic{section} (иными словами, ссылка на раздел, сгенерированная командой \ref, печатает просто номер раздела), а в классе report команда \ref при печати ссылки на раздел печатает не номер раздела, а номер главы, точку и номер раздела. Поскольку мы написали \thesection, все эти тонкости будут учтены автоматически.

Приведем еще один (игрушечный) пример использования счетчиков в макроопределениях, отчасти чтобы еще раз продемонстрировать применение подчиненных счетчиков, а отчасти чтобы убедить читателя, что не боги горшки обжигают. Именно, давайте разработаем свои собственные команды для создания разделов документа, не полагаясь на \chapter, \section и т.п. из стандартных LaTeX'овских классов. Для простоты предположим, что заголовки глав и разделов будут укладываться в одну строку, и не будем заботиться о том, насколько удачным выйдет оформление заголовков. Итак, пусть наш документ делится на главы, которые, в свою очередь, делятся на разделы. Каждую главу будем начинать с новой страницы, перед каждым разделом оставлять 1cm (если, конечно, раздел не начинает новой страницы). Наконец, предусмотрим, чтобы главы и разделы автоматически нумеровались с возможностью создания автоматических ссылок на эти номера. Команды для создания главы и раздела назовем \glava и \razdel ; это будут команды, требующие одного аргумента — названия главы или раздела.

Чтобы номера глав и разделов генерировались автоматически, нам необходимо создать счетчики, содержащие эти номера. Пусть счетчик с номером главы называется glava, а счетчик с номером раздела — razdel (имена счетчиков могут совпадать с именами команд). Имея в виду, что нумерация разделов в каждой главе будет начинаться заново, напишем в преамбуле так:

\newcounter{glava}
\newcounter{razdel}[glava]

Теперь определим команду \glava:

\newcommand*{\glava}[1]{\clearpage % с новой страницы
\vspace*{4cm}% оставить место сверху
\refstepcounter{glava}% новый номер главы
{\LARGE\rmfamily\bfseries\upshape % шрифт для заголовка
Глава \theglava. #1% заголовок
\par % кончить заголовок
\vspace{5mm plus 1mm minus .5mm}% Промежуток между
% заголовком и текстом
}% завершить группу, внутри которой менялся шрифт
}% конец макроопределения

Поскольку номер главы устанавливается командой \refstepcounter, при этом будет начата заново и нумерация разделов, а на номера глав можно будет делать автоматические ссылки с помощью \label и \ref. В определении шрифта для заголовков мы в явном виде установили все четыре атрибута, чтобы быть уверенными, что он будет какой надо (если бы мы, например, не сказали \upshape, а предыдущая глава заканчивалась курсивом, определенным командой \itshape, данной вне группы, то заголовок напечатался бы жирным курсивом).

Обратите также внимание на команду \theglava. Мы воспользовались ею, поскольку не хотим на этом этапе предрешать, в каком виде номер главы будет представлен в заголовке: в виде арабской цифры, римской цифры или еще как-нибудь. Если в дальнейшем нам захочется изменить вид этого представления, то не придется менять, с риском ошибиться, длинное определение команды \glava, а будет достаточно переопределить команду \theglava. Заметьте, что промежуток между заголовком и текстом мы сделали растяжимым, чтобы помочь TeX'у найти правильное разбиение на страницы.

Определение команды \razdel можно дать, например, так:

\newcommand{\razdel}[1]{\par % завершить предыдущий абзац
\pagebreak[2]\vspace{1cm plus 3mm minus .5mm} % см. ниже
\refstepcounter{razdel}% новый номер раздела
{\Large\rmfamily\bfseries\upshape % шрифт для заголовка
\therazdel{} #1% заголовок
\par % закончить заголовок
}% завершить группу, внутри которой менялся шрифт
\nopagebreak % чтобы не оторвать текст от
             % заголовка
\vspace{2mm plus 1mm}% Промежуток между заголовком
                     % и текстом
}% конец макроопределения

Пояснений тут требует команда \pagebreak[2]. Мы включили ее в макроопределение, чтобы поменьше разделов начиналось внизу страницы. В самом деле, команда \pagebreak[2] предлагает TeX'у начать в этом месте новую страницу; если так и будет сделано, то дополнительный вертикальный промежуток, созданный командой \vspace, пропадет, и заголовок раздела начнется с самого верха новой страницы; если же разрыва страницы все-таки не произойдет, то перед заголовком раздела будет вертикальный промежуток в один сантиметр (обладающий указанными в макроопределении растяжимостью и сжимаемостью).

Нам осталось только задать вид, в котором будут представляться на печати номера глав и разделов. Иными словами, надо переопределить должным образом команды \theglava и \therazdel (в момент создания счетчиков они, как мы помним, были автоматически определены таким образом, что \theglava и \therazdel — номера главы и раздела, набранные арабскими цифрами). Предположим, мы решили, что номера глав будут печататься римскими цифрами, а номер второго раздела четвертой главы будет иметь вид IV-2. Тогда требуемые переопределения таковы:

\renewcommand{\theglava}{\Roman{glava}}
\renewcommand{\therazdel}{\theglava--\arabic{razdel}}

Еще одно замечание: точки после номера главы мы включили в определение команды \glava, а не \theglava, чтобы можно было пользоваться автоматическими ссылками: если бы \theglava определялось как

\Roman{glava}.

то исходный текст

в главе \ref{metka} мы пишем...

дал бы на печати

в главе IV. мы пишем

что нелепо.

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

Счетчики, которые уже определены

Мы уже мельком упоминали, что при начале работы LaTeX'а некоторые счетчики определены сразу. Например, это те счетчики, которые перечислены выше. Кроме того, заранее определен счетчик page, отвечающий за нумерацию страниц, а также счетчик footnote, ответственный за нумерацию сносок. Нумерацией плавающих иллюстраций и таблиц занимаются счетчики, называемые figure и table. В одном из разделов перечислены все эти заранее определенные счетчики и указано, каким счетчикам они подчинены (это иногда зависит от класса документа).

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

\renewcommand{\thechapter}{\Roman{chapter}}

Если вы хотите, чтоб сноски нумеровались не цифрами, а латинскими буквами, то можно в преамбуле написать:

\renewcommand{\thefootnote}{\alph{footnote}}

Модификация оформления перечней

Начнем с {itemize}. Чтобы поменять значки, которыми помечаются элементы перечня, надо переопределить команду \labelitemi. Если, например, мы хотим, чтобы элементы перечня отмечались не черными кружками, а галочками $$\surd$$, то достаточно написать в преамбуле

\renewcommand{\labelitemi}{$\surd$}

. Если окружение {itemize} расположено внутри другого окружения {itemize}, как в примере на {itemize}, то значки для пометки элементов перечня будут уже, вообще говоря, другими: их вид задается командой \labelitemii ; вид значков для пометок элементов itemize на третьем и четвертом уровнях вложенности задается командами \labelitemiii и \labelitemiv ; их также можно переопределять.

Правильнее было бы определять заголовки для itemize чуть хитрее. Например, наше определение \labelitemi лучше дать так:

\renewcommand{\labelitemi}{$\mathsurround=0pt \surd$}

Если дать определение именно так, то вокруг галочки не появится дополнительный пробел даже в случае, если вы в какой-то момент решите установить ненулевое значение параметра \mathsurround. Поскольку формула образует группу, в дальнейшем предыдущее значение \mathsurround восстановится. Полезно иметь в виду этот прием, если вы пользуетесь математическими символами в качестве типографских значков.

Теперь рассмотрим окружение {enumerate}. Коль скоро оно автоматически нумерует элементы перечня, можно предположить, что это окружение связано с LaTeX'овскими счетчиками. Так оно на самом деле и есть: это окружение использует счетчик enumi. Если одно {enumerate} вложено в другое, то используются счетчики enumii, enumiii и enumiv для нумерации элементов перечня на втором, третьем и четвертом уровнях вложенности. С другой стороны, сами значки, помечающие элементы перечня, порождаются командами \labelenumi, \labelenumii, \labelenumiii и \labelenumiv — в зависимости от уровня вложенности. Например, команда \labelenumi определена так:

\newcommand{\labelenumi}{\theenumi.}

в то время как the-команда, определяющая представление счетчика enumi на печати, определена просто как

\newcommand{\theenumi}{\arabic{enumi}}

Стало быть, если мы не меняем стандартного стиля оформления, то элементы перечня {enumerate} (не вложенного в другой {enumerate} ) будут нумероваться цифрами с точкой. Если же мы хотим, скажем, чтобы после цифры шла не точка, а скобка (как в нашей книге), то можно в преамбуле написать

\renewcommand{\labelenumi}{\theenumi)}

Если же мы к тому же хотим, чтобы элементы перечня нумеровались римскими цифрами, то можно написать еще и так:

\renewcommand{\theenumi}{\Roman{enumi}}

Аналогичным образом можно менять оформление нумерованных перечней на других уровнях вложенности.

Если вы хотите изменить оформление перечня более серьезным образом (например, установить другую величину полей, или сделать так, чтобы значки, помечающие элементы перечня, были выровнены по левому, а не по правому краю), то вам придется подождать до лекции 9.

Параметры со значением длины

Наряду со счетчиками — переменными с целочисленными значениями, — при создании собственных макроопределений возникает нужда и в переменных, значениями которых являются длины. Например, в предыдущем разделе мы, разрабатывая команду \razdel, в явном виде задали промежуток между заголовком раздела и остальным текстом. Если этот промежуток нам почему-либо захочется изменить, то придется снова залезать в определение команды \razdel. Было бы удобнее, если бы в нашем распоряжении был параметр под названием, скажем, \otstup, так что можно было бы в определении команды \razdel написать

\vspace{\otstup}

и потом отдельно написать, допустим,

\otstup=1cm plus 3mm minus .5mm

Правда, в богатом наборе TeX'овских и LaTeX'овских параметров требуемого нам параметра \otstup нет, но это не страшно, поскольку его можно создать. Для этого используется команда \newlength:

\newlength{\otstup}

После того, как вы (допустим, в преамбуле) дали эту команду, будет определен новый параметр со значением длины; его можно будет обычным образом использовать в аргументах команд наподобие \vspace, и ему можно будет обычным образом присваивать значения.

Теперь — точные правила. Команда \newlength имеет один обязательный аргумент — имя команды, обозначающей определяемый вами параметр. Это имя должно подчиняться обычным правилам для TeX'овских команд (backslash, после которого следует либо одна не-буква, либо последовательность букв). Если это имя уже занято, LaTeX выдаст сообщение об ошибке. Определение нового параметра, совершаемое командой \newlength, является "глобальным": даже если эта команда была дана внутри группы, TeX будет помнить о существовании этого параметра и по выходе из группы. По этой причине разумное место для команды \newlength — преамбула.

Определенный нами параметр со значением длины приобретает такой же статус, как уже существующие TeX'овские и LaTeX'овские параметры ( \parindent, \textwidth и другие). Рассмотрим, что можно делать с этими параметрами.

Во-первых, параметрам со значением длины можно присваивать значения. Делается это точно так же, как это объяснялось ранее на примере параметра \parindent: для присваивания значения надо написать имя параметра, знак равенства, а после знака равенства — величину присваиваемой длины. Пробелы после указания единицы длины TeX'ом игнорируются (скорее всего, вы будете присваивать значения параметрам в преамбуле документа или между абзацами, где лишние пробелы никого не волнуют). Длина должна быть выражена в единицах, воспринимаемых TeX'ом. Даже если вы присваиваете нулевую длину, какая-то единица длины должна быть явно указана (например, 0pt). Кроме того, можно воспользоваться LaTeX'овской командой \setlength, имеющей два обязательных аргумента: первый — имя параметра, второй — значение длины, присваиваемое этому параметру. Таким образом, команды

\parindent=1.5em

и

\setlength{\parindent}{1.5em}

равносильны. Наконец, присваивания, сделанные внутри группы, забываются по выходе из этой группы.

В предыдущем абзаце мы умолчали об одной возможной неприятности. Дело в том, что если после команды присваивания, не использующей \setlength, следует (пусть даже после пробела) слово plus или minus, то TeX, скорее всего, выдаст сообщение об ошибке, поскольку решит, что длина должна иметь, помимо " естественного размера", еще и plus - или minus -компоненту. Если вы пишете текст на русском языке, вероятность такого стечения обстоятельств ничтожна, но тем не менее забывать о такой опасности не следует, особенно если команда присваивания входит в макроопределение: вы же не знаете заранее, в какое место может попасть новый макрос. Чтобы застраховаться от этой неприятности раз и навсегда, пользуйтесь командой \setlength, хоть это и длиннее.

Параметры со значением длины можно использовать всюду, где в аргументе LaTeX'овской команды требуется указать размер. Пусть, например, в преамбуле документа написано

\newlength{\primer}

Тогда посмотрите на следующий пример:

$$\newlength{\primer} \parindent=0mm \primer=10mm 9\hspace{\primer}9 {\primer=20mm 8\hspace{\primer}8} 9\hspace{\primer}9$$
\primer=10mm
9\hspace{\primer}9

{\primer=20mm
8\hspace{\primer}8}

9\hspace{\primer}9

Обратите внимание, что, если присваивание параметру нового значения происходило внутри группы, то по выходе из группы новое значение забывается, а прежнее — восстанавливается.

Параметры со значением длины можно указывать с коэффициентом - положительной или отрицательной десятичной дробью (можно использовать как десятичную точку, так и десятичную запятую). Например, если значение параметра \primer равно $$10 мм$$, то команда \hspace{2.71\primer} сделает пробел длиной $$27.1\,\rm мм.$$

Параметры со значением длины (возможно, с числовыми коэффициентами) могут также стоять в правой части оператора присваивания (или во втором аргументе команды \setlength ):

\primer=1.45\parindent
\setlength{\primer}{.45\tabcolsep}

Можно также прибавлять длину к значению параметра: если значение параметра \abcd равно $$x$$, то после выполнения команды

\addtolength{\abcd}{"$y$\verb"}

где $$y$$ - длина, значение параметра "\abcd" станет равно $$x+y.$$ В качестве $$y$$ в этой команде может использоваться как явно указанная длина (например, 1.2in), так и параметр со значением длины (возможно, с числовым коэффициентом). Наконец, LaTeX предоставляет полезную команду

\settowidth{"\textit{параметр}\verb"}{"\textit{текст}\verb"}

которая присваивает параметру значение, равное ширине текста. Вот пример:

$$\newlength{\primer} \parindent=0mm \settowidth{\primer} \settowidth{\primer}{\Large слово } {\Large слово }слово \hspace{\primer}слово $$
\settowidth{\primer}{\Large
слово }
{\Large слово }слово

\hspace{\primer}слово

(обратите внимание, что у нас получилось выравнивание без помощи {tabbing} или {tabular}).

Существуют также команды \settoheight и \settodepth, аналогичные \settowidth. Команда \settoheight присваивает параметру значение, равное максимальному расстоянию, на которое текст возвышается над строкой (точнее, над ее базисной линией). \settodepth присваивает параметру значение, равное максимальному расстоянию, на которое текст опускается ниже базисной линии.

Ранее у нас шла речь о том, что некоторые используемые в TeX'е длины могут обладать растяжимостью или сжимаемостью. Параметрам, созданным с помощью команды \newlength, также можно присваивать значения, содержащие plus и/или minus -компоненту. Если, например, мы хотим, чтобы параметр \primer имел естественный размер $$2\,\text{см}$$, растяжимость $$4\,\text{мм}$$ и сжимаемость в один пункт, то можно написать так:

\setlength{\primer}{2cm plus 4mm minus 1pt}

Создание новых окружений

Новые окружения: общий случай

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

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

\begin{tabular}{|p{7cm}|}
\hline
Этот текст будет заключен в рамку. Как видите,
окружение, предназначенное для верстки таблиц,
можно использовать и для этих целей.\\
\hline
\end{tabular}

При этом будет напечатано вот что:

$$\begin{tabular}{|p{7cm}|} \hline Этот текст будет заключен в рамку. Как видите, окружение, предназначенное для верстки таблиц, можно использовать и для этих целей.\\ \hline \end{tabular}$$

Если таких рамок с текстом у вас много, то можно сократить число нажатий на клавиши, определив окружение с именем, скажем, {ramka}, так, чтоб можно было бы просто писать

\begin{ramka}
Этот текст будет ...
... этих целей.
\end{ramka}

Определяется это окружение так:

\newenvironment{ramka}{\begin{tabular}{|p{7cm}|}
                       \hline}{\\\hline\end{tabular}}

В общем случае команда \newenvironment имеет такой формат:

\newenvironment{имя}{открывающие\_команды}{закрывающие\_команды}

Здесь имя — имя определяемого окружения, открывающие\_команды — команды и/или текст, подставляемые вместо команды \begin с именем окружения, закрывающие\_команды — команды и/или текст, подставляемые вместо команды \end с именем окружения.

Вместо окружения, определяемого с помощью \newenvironment, можно с тем же успехом создать два макроса: один — для открывающих\_команд, другой — для закрывающих. Например, в нашем случае с рамкой можно было бы написать

\newcommand{\nachalo}{\begin{tabular}{|p{7cm}|}\hline}
\newcommand{\konec}{\\\hline\end{tabular}}

и создавать рамки так:

\nachalo
Этот текст...
\konec

Преимущество оформления такого рода конструкций в виде окружений состоит в том, что при этом легче контролировать ошибки: если вы напишете \begin{ramka} и при этом забудете написать соответствующую команду \end{ramka}, то LaTeX выдаст сообщение об ошибке, в котором именно это вам и скажет; если же вы забудете команду \konec, то сообщения об ошибке будут менее понятными. Кроме того, нелишне напомнить, что команды \begin и \end, ограничивающие окружение, ограничивают группу: все неглобальные определения и изменения параметров, происходящие внутри окружения, забываются по выходе из него.

Новые окружения можно определять так, чтобы они принимали аргументы. Пусть, например, в зависимости от обстоятельств нам нужны рамки разной ширины. Тогда разумно модифицировать определение окружения {ramka} таким образом, чтобы ширина текста в рамке передавалась ему как аргумент. Соответствующее определение будет выглядеть так:

\newenvironment{ramka}[1]{\begin{tabular}{|p{#1}|}
                       \hline}{\\\hline\end{tabular}}

После этого можно писать, например,

\begin{ramka}{6cm}
Текст...
\end{ramka}

или даже

\begin{ramka}{.85\textwidth}
Текст...
\end{ramka}

Общие правила таковы. Чтобы создать окружение с аргументами, надо воспользоваться командой \newenvironment c необязательным аргументом. Этот необязательный аргумент ставится между первым и вторым обязательными; как и в случае с \newcommand, он означает количество аргументов, которые будет требовать окружение, и это количество не может превышать девяти; места, куда будут вставлены аргументы, по-прежнему обозначаются #1,...,#9, причем эти значки можно употреблять только в открывающих командах (т.е. во втором обязательном аргументе команды \newenvironment )

С помощью \newenvironment нельзя переопределить уже существующее окружение (если вы все же попробуете так сделать, LaTeX выдаст сообщение об ошибке). Если вам действительно необходимо такое переопределение, надо пользоваться командой \renewenvironment, работающей точно так же, как и \newenvironment, с тем различием, что в качестве первого аргумента ей можно передавать только имя уже существующего окружения.

У команд для переопределения окружения также существуют " варианты со звездочкой": \newenvironment* и \renewenvironment*. Если окружение с аргументами определено с помощью одной из этих команд, то в его аргументе запрещены пустые строки или команды \par.

Окружения типа " теорема"

Если вы пишете математический текст, то в этом тексте будет содержаться немалое количество теорем, лемм, определений и тому подобных вещей. Эти элементы математического текста желательно оформлять специальным образом. Например, формулировки теорем часто печатают, для ясности, другим шрифтом, само слово "теорема" также выделяют (третьим) шрифтом и т.д. Чтобы задать такое оформление, в исходном тексте приходится написать довольно много TeX'овских команд, и лучше не повторять этот длинный набор команд много раз, а создать заменяющее его макроопределение, что, в свою очередь, может потребовать некоторого труда (чем-то подобным мы занимались в предыдущих разделах, когда разрабатывали команду \z ). Если же вы или редакция, с которой вы имеете дело, не слишком требовательны к деталям оформления, то соответствующие макросы (точнее говоря, новые окружения) легко создать из полуфабрикатов, предоставляемых нам для этих целей LaTeX'ом.

Окружения, используемые в LaTeX'е для оформления фрагментов текста типа "теорема", заранее не определены. Дело в том, что количество различных типов объектов наподобие теоремы, присутствующих в одном тексте, может быть достаточно велико (предложение, утверждение, лемма, определение, замечание,...), так что LaTeX в целях экономии машинной памяти и исходя из того, что на все вкусы таких окружений все равно не напасешься, определять их предоставляет вам. Как это делать, удобнее всего разобрать на примере.

Пусть в нашем тексте присутствуют "предложения". Давайте создадим окружение {predl} таким образом, чтобы можно было, например, писать

$$\newtheorem{predl}{Предложение}\begin{predl} Волга впадает в Каспийское море. \end{predl} \textbf{Доказательство.} См. любую географическую карту.$$
\begin{predl}
Волга впадает в Каспийское море.
\end{predl}
\textbf{Доказательство.}
См. любую географическую карту.

Для создания такого окружения используется команда \newtheorem:

\newtheorem{predl}{Предложение}

Как видите, команда \newtheorem имеет два обязательных аргумента: первый - название окружения, которое мы создаем, второй - заголовок нашей "теоремы".

Теперь обсудим, как работают окружения, созданные при помощи команды \newtheorem (будем называть их просто окружениями типа "теорема"). Во-первых, как вы уже заметили, формулировка печатается курсивом, а заголовок — полужирным шрифтом. Во-вторых, абзац, идущий после нашего окружения, начинается с абзацным отступом, если после закрывающей окружение команды \end идет пустая строка, и без отступа в противном случае (так что в этом отношении окружения типа "теорема" ведут себя совершенно аналогично таким окружениям, как {quote}, {itemize} и т.п.). В-третьих, окружение типа " теорема" может иметь необязательный аргумент (как обычно, в квадратных скобках). Текст, стоящий в этих квадратных скобках, будет напечатан в скобках после заголовка "теоремы" и ее номера. Обычно это используется для указания ученого, чьим именем названа "теорема":

$$\newtheorem{predl}{Предложение} \setcounter{predl}{1} \begin{predl}[Пифагор] Пифагоровы штаны на все стороны равны. \end{predl}$$

При пользовании классами документов, предоставляемыми Американским математическим обществом, появляются дополнительные возможности влиять на оформление "теорем". См. следующий пункт.

Вместе с окружением типа "теорема" автоматически создается и счетчик, хранящий его номер. Имя этого счетчика совпадает с именем окружения (так что в нашем примере счетчик называется predl); чтобы изменить представление на печати номеров наших "теорем", можно обычным образом переопределить соответствующую the-команду. Например, если мы хотим, чтобы предложения нумеровались прописными латинскими буквами, надо в преамбуле написать:

\renewcommand{\thepredl}{\Alph{predl}}

" Теоремы", определяемые описанным выше способом, будут иметь сплошную нумерацию на протяжении всего документа. Как мы уже понимаем, это далеко не всегда удобно. Часто хотелось бы сделать так, чтоб, например, в каждом разделе нумерация " теорем" начиналась заново. Для таких целей предусмотрена команда \newtheorem с необязательным аргументом. Этот аргумент ставится после двух обязательных и представляет собой имя того счетчика, которому будет подчинен счетчик нашей " теоремы". Пусть, например, в нашем тексте есть не только предложения, но и теоремы (без кавычек), и мы хотим, чтобы нумерация теорем начиналась заново в каждом разделе. Тогда можно написать в преамбуле так:

\newtheorem{theorem}{Теорема}[section]

После этого можно будет писать, например, вот что:

$$\newtheorem{theorem}{Теорема}[section] \setcounter{section}{5} \begin{theorem} Сумма углов треугольника равна $180^{\circ}$. \end{theorem}$$
\begin{theorem}
Сумма углов треугольника
равна $180^{\circ}$.
\end{theorem}

Обратите внимание, что, если "теорема" определена таким образом (со счетчиком, подчиненным другому счетчику), то представление ее номера на печати изменяется: при определении

\newtheorem{xyz}[abcd]

(счетчик "теоремы" типа xyz подчинен счетчику abcd) команда \thexyz будет определена как

\theabcd.\arabic{xyz}

(если вы хотите, чтобы нумерация "теоремы" представлялась на печати иначе, вы опять-таки можете переопределить the-команду).

Наконец, LaTeX предоставляет еще одну возможность нумерации определяемых вами "теорем". Предположим, что кроме теорем в вашем тексте есть еще и леммы, и при этом вы хотите, чтобы леммы и теоремы нумеровались совместно: теорема 2.1, теорема 2.2, затем лемма 2.3, затем теорема 2.4 и т.д. Тогда, предполагая, что окружение {theorem} уже определено, как выше, можно определить окружение {lemma} так:

\newtheorem{lemma}[theorem]{Лемма}

В этом случае необязательный аргумент команды \newtheorem располагается между двумя обязательными; этот аргумент - имя того окружения типа "теорема", совместно с которым будет нумероваться определяемая вами "теорема".

Команду \newtheorem можно использовать или с одним необязательным аргументом, или с другим, но не с обоими вместе.

Окружения типа "теорема" в пакете amsthm

Все LaTeX'овские "теоремы", определяемые пользователем при помощи окружения {newtheorem}, оформляются в одном и том же стиле, что не всегда приемлемо. Пакет {amsthm}, распространяемый Американским математическим обществом, позволяет внести в это оформление некоторое разнообразие. Итак, предположим, что вы его подключили. Что нового, по сравнению с "чистым" LaTeX'ом, можно сделать?

Во-первых, в этом пакете определен "вариант со звездочкой" команды \newtheorem. Именно, если определить очередной тип " теорем" с помощью \newtheorem* вместо \newtheorem, то "теоремы" указанного типа не будут нумероваться.

Во-вторых, для управления стилем оформления окружений типа "теорема" предназначена команда \theoremstyle, аргументом (единственным) которой может быть слово plain , definition или remark. Если в преамбуле дать эту команду с одним из трех допустимых аргументов, то все "теоремы", определяемые с помощью \newtheorem после этой команды \theoremstyle, будут оформлены в соответствующем стиле; чтоб определить тип теорем, оформляемый в другом стиле, надо написать еще одну команду \theoremstyle (с другим аргументом, разумеется), а уж после нее — очередную \newtheorem. Стиль plain рекомендуется для собственно теорем, предложениий и лемм, definition — для определений, remark — для замечанийВ стиле plain заголовок печатается жирным шрифтом, а текст " теоремы" — курсивом, в стиле definition заголовок печатается жирным шрифтом, а текст " определения" — прямым, в стиле remark заголовок печатается курсивом, а текст "замечания" — прямым шрифтом.. Если в преамбуле нет ни одной команды \theoremstyle, подразумевается стиль plain.

В-третьих, в пакете amsthm предусмотрено также окружение proof, предназначенное для оформления доказательств. Это окружение автоматически ставит слово Proof в начало доказательства и автоматически же завершает доказательство символом $$\square.$$ Если вас не устраивает, что слово "доказательство" пишется по-английски, нужно переопределить с помощью \renewcommand команду \proofname. Если символ $$\square$$ нужен вам сам по себе (например, как знак завершения какого-то рассуждения, не выделенного в качестве доказательства нумерованного утверждения), можно воспользоваться командой \qed.

Окружение proof допускает и необязательный аргумент: если написать, скажем,

\begin{Proof}[Доказательство основной теоремы]

то вместо слова Proof появится текст, записанный нами в квадратных скобках.

Страницы:

Средства LaTeX'а, описываемые в этой лекции, позволяют сократить число нажатий на клавиши при наборе сложных текстов. Именно, мы расскажем, как создавать новые команды (или, если угодно, сокращенные обозначения), заменяющие собой длинные фрагменты из текста и TeX'овских команд. Официально такие новые команды называются макроопределениями, а в разговорной речи — макросами.

Макроопределения

Команды без аргументов

Начнем с примера. Пусть вы пишете текст, в котором регулярно встречается математический значок $$\stackrel{\rm def}{=}$$ (он означает " равно по определению"). Пользуясь тем, что вы узнали из лекции 2 , нетрудно понять, что генерируется этот значок внутри математической формулы такой последовательностью команд:

\stackrel{\mathrm{def}}{=}

Часто писать такой длинный набор команд утомительно. Вот бы в LaTeX'е была предусмотрена команда, скажем, \eqdef, генерирующая символ бинарного отношения $$\eqdef$$,! Правда, такой команды нет, но мы ее можем создать. Для этого следует написать так:

\newcommand{\eqdef}{\stackrel{\mathrm{def}}{=}}

После того как TeX прочтет эту строку, он всюду, встречая команду \eqdef, будет реагировать точно так же, как если бы он видел текст \stackrel{\mathrm{def}}{=}. Например, формула $${x^2\eqdef x\cdot x}$$ теперь получается так:

x^2\eqdef x\cdot x

Новая команда TeX'а, которую мы определили, называется макросом (еще говорят: макроопределение, макрокоманда, макро). Рассмотрим точные правила для создания макросов средствами LaTeX'а.

Для создания макросов используется команда \newcommand. Эта команда имеет два обязательных аргумента. Первый из них — имя, которое вы придумали для вашего макроса. Имена макросов должны подчиняться тем же правилам, что имена TeX'овских команд, либо backslash и после него одна не-буква, либо backslash и после него — последовательность букв. Второй обязательный аргумент команды \newcommand, называемый " замещающим текстом", сообщает TeX'у смысл макроса: на этот текст ваш макрос будет замещаться в процессе трансляции (как говорят, макрос будет "разворачиваться").

При пользовании командой \newcommand нельзя в качестве имени макроса выбирать имя уже существующей команды или окружения (если вы попробуете так сделать, LaTeX выдаст сообщение об ошибке).

Во втором аргументе команды \newcommand (иными словами, в "замещающем тексте") вместе с каждой открывающей фигурной скобкой должна присутствовать соответствующая ей закрывающаяФигурные скобки, входящие в состав команд \{ \}, в счет при этом не идут., так что определения наподобие

\newcommand{\nachatkursiv}}
\newcommand{\konchitkursiv}{}}

приведут в лучшем случае к сообщению об ошибке (и желаемого эффекта не дадут). Если вам кажется, что такие ограничения стеснительны, можете изучить по книге [2], как их обходить; для большинства практических целей возможности создания макроопределений, предоставляемые LaTeX'ом, вполне достаточны.

К сожалению, некоторые русификации TeX'а не позволяют использовать в именах макросов русские буквы.

Еще одно ограничение: имя новой команды не должно начинаться на end.

Наконец, в замещающем тексте макроопределения нельзя пользоваться командой \verb или окружением {verbatim}.

Если команда \newcommand дана внутри группы, то смысл определяемой ею новой команды будет забыт TeX'ом по выходе из группы. Если новая команда определяется в преамбуле, то, естественно, она будет понятна TeX'у на протяжении всего документа.

Давайте теперь разберем несколько примеров, обращая внимание на типичные ошибки.

Макросы хороши как средство скорописи. Например, если в вашем тексте часто встречается знак $$\bigtriangleup$$, то вам может надоесть все время писать длинную команду \bigtriangleup. Коли так, придумайте сокращенное обозначение (скажем, \btu ), напишите в преамбуле

\newcommand{\btu}{\bigtriangleup}

и вы сможете писать формулы наподобие

$$(A\bigtriangleup B)\cap C= (A\cap C)\bigtriangleup (B\cap C)$$
$(A\btu B)\cap C=
(A\cap C)\btu (B\cap C)$

Ранее было рассказано, что делать, чтобы создать согласующееся с нашими традициями обозначение для тангенса. Теперь мы понимаем, что это был пример макроопределения (если вам интересно знать, что значит команда \mathop в замещающем тексте).

В лекции 2 вы найдете массу других примеров громоздких конструкций, для которых имеет смысл создать макросы.

А теперь — пример типичной ошибки. Пусть в тексте, который вы набираете, регулярно встречаются фразы наподобие

Подмногообразия проективного пространства $$\mathbf{P}^n$$ - основной объект изучения алгебраической геометрии,

и пусть для сокращения письма вы написали в преамбуле

\newcommand{\Pn}{$\mathbf P^n$}

Теперь можно писать, например, так:

... пространства~\Pn{} - основной объект...

Однако для набора формулы $$x\in\mathbf P^n$$ написать $x\in\Pn$ не удастся: появится сообщение о том, что символ ^ и команда \mathbf преступно употреблены вне математической формулы. Причина проста: TeX исправно подставляет вместо \Pn тот "замещающий текст", который вы ему сообщили во втором аргументе команды \newcommand. В результате этого при развертывании макроса \Pn текст $x\in\Pn$ превращается в незаконный текст $x\in$\mathbf P^n$$, в котором математическая формула заканчивается со вторым из знаков доллара, а символ ^ оказывается посреди обычного текста. Чтобы можно было напечатать $$\mathbf{P}^n$$ не только изолированно, не надо включать знаки доллара в определение:

\newcommand{\Pn}{\mathbf{P}^n}

При этом придется, конечно, ставить знаки доллара вокруг \Pn в тех случаях, когда в тексте встречается просто $$\mathbf{P}^n$$, но зато наш макрос можно будет использовать и как составную часть более сложных формул.

Есть, впрочем, и более удачный способ борьбы с этой проблемой: определите \Pn как

\newcommand{\Pn}{\ensuremath{\mathbf{P}^n}}

(без всяких знаков доллара) — и вы сможете спокойно пользоваться своей новой командой \Pn как в тексте, так и в формулах:

Пусть \Pn~ — $n$---мерное проективное пространство,
а $X\subset \Pn$~ — неприводимое многообразие...

(знаки ~ мы поставили, чтобы строчка не смогла начаться с тире —c.103). Команда \ensuremath всегда обрабатывает свой аргумент как математическую формулу, независимо от того, в тексте или в формуле вы ее используете.

Создавать макросы полезно не только для сокращения числа нажатий на клавиши при наборе формул. Вот пример, когда макросы помогают и при наборе обычного текста. Предположим, в нашем тексте много задач, причем условие каждой из задач начинает новый абзац (как обычно и бывает). Предположим также (временно), что эти задачи никак не нумеруются. Слово "Задача", с которого начинается условие, хочется как-то выделить в тексте; предположим, мы решили выделять его жирным шрифтом. Давайте создадим макрос, который будет делать все это за нас, чтобы можно было не печатать каждый раз слово "Задача", а просто написать \z. Первым обычно приходит в голову что-нибудь такое:

\newcommand{\z}{\bfseries Задача}

Посмотрите, что из этого выйдет:

$$\parindent=0cm \newcommand{\z}{\bfseries Задача}\z. Пять парней за пять дней съели пять окуней. За сколько дней пятнадцать парней съедят пятнадцать окуней$$?
\z. Пять парней за пять дней
съели пять окуней. За сколько
дней пятнадцать парней
съедят пятнадцать окуней?

Почему же жирным шрифтом напечаталось не только слово "Задача", но и весь дальнейший текст? Ответ: TeX опять пунктуально заменил \z на "замещающий текст", в результате чего получилось вот что:

\bfseries Задача. Пять парней ...

Команда \bfseries оказалась не внутри группы, и весь текст напечатался жирным шрифтом. Чтобы не попадаться в такую ловушку, надо помнить, что при развертывании макроса фигурные скобки, ограничивающие замещающий текст в команде \newcommand, отбрасываются. Правильнее было бы дать такое определение:

\newcommand{\z}{\bfseries {Задача}}"

На сей раз \z будет заменяться на {\bfseries Задача} (отбрасывается внешняя пара фигурных скобок, ограничивающая второй аргумент команды \newcommand, и только она!). А можно (это, пожалуй, даже лучше) написать и так:

\newcommand{\z}{\textbf{Задача}}

Впрочем, наш макрос \z еще не идеален. Во-первых, после слова, напечатанного жирным шрифтом, точку лучше поставить тоже жирным шрифтом, поэтому разумно и ее включить в макроопределение. Далее, согласно общему правилу игнорирования пробелов после имени команды, состоящего из букв, в тексте при этом нельзя будет написать

\z Пять парней...

так как при этом пропадет пробел между словом "Задача." и следующим словом. Можно этот пробел, как водится, всякий раз специально организовывать и писать

\z{} Пять парней...

но лучше вставить и пробел прямо в определение:

\newcommand{\z}{\textbf{Задача. }}

Теперь запись \z Пять парней... даст то, что нужно. Впрочем, если угодно, вот еще один штрих. Если вы в какой-нибудь момент забудете оставить пустую строку перед очередной задачей, то слово "Задача" при этом будет не начинать абзац, а продолжать предшествующий текст. Чтобы этого раз и навсегда избежать, можно вставить команду "закончить абзац" в наше макроопределение. Как вы помните, эта команда называется \par:

\newcommand{\z}{\par\textbf{Задача. }}

Если перед нашим макросом \z пустая строка все-таки будет, то лишняя команда \par ни на что не повлияет, а если ее не будет, то \par сыграет роль недостающей пустой строки.

Если какой-то элемент текста оформлен с помощью макроса, становится удобно менять это оформление. Например, если вдруг понадобилось оформлять все задачи так, чтобы соответствующие абзацы начинались без отступа, достаточно внести небольшое изменение в наше определение команды \z:

\newcommand{\z}{\par\noindent\textbf{Задача. }}

Если бы каждую задачу мы оформляли вручную, нам пришлось бы перед каждым словом "Задача" вписывать команду \noindent. В дальнейшем, познакомившись с LaTeX'овскими " счетчиками", мы усовершенствуем наш макрос \z таким образом, чтобы он еще и автоматически нумеровал задачи.

Мы уже говорили, что переопределить значение уже существующей команды с помощью \newcommand невозможно. Иногда, однако, это бывает необходимо. Пример тому приведен в лекции 3 : если мы хотим, чтобы в заголовках глав печаталось именно слово "Глава", а не " Chapter", то необходимо определить по-новому команду \chaptername. Для такого рода целей используется команда \renewcommand. Она устроена точно так же, как \newcommand, с тем отличием, что в качестве ее первого аргумента надо указывать имя уже существующей команды; в этом случае по выполнении команды \newcommand значение этой команды изменится: она превратится в сокращенное обозначение для текста, указанного в качестве ее второго аргумента. Например, если написать

\renewcommand{\alpha}{Ку-ку}

то команда \alpha будет генерировать не то, что обычно (букву $$\alpha$$ в математической формуле и сообщение об ошибке, если эта команда употреблена вне математической формулы), а текст "Ку-ку".

Если команда \renewcommand дана внутри группы, то созданное ею переопределение значения команды забудется по выходе из этой группы. Если в качестве первого аргумента команды \renewcommand указать имя несуществующей команды, то вы получите сообщение об ошибке.

Команда \renewcommand при неаккуратном обращении может привести к неприятностям. Дело в том, что нередко команды LaTeX'а определяются в терминах других команд LaTeX'а, причем знать эти сложные связи рядовой пользователь вовсе не обязан. На практике такое незнание может привести к тому, что безобидное на первый взгляд использование в своих целях имени какой-нибудь команды, которая в вашем тексте ни разу не встречается, вызовет необъяснимо неправильную работу других команд. Поэтому используйте \renewcommand только тогда, когда вы полностью отдаете себе отчет в своих действиях.

Выше мы часто называли макросы просто командами, и это — не просто небрежность речи: на самом деле принципиальной разницы между макросами и TeX'овскими командами почти нет. В частности, почти все команды LaTeX'а, о которых говорилось и еще будет говориться в нашей книге, являются именно макросами; в отличие от макросов, создаваемых нами с помощью \newcommand, их смысл уже известен TeX'у к моменту запуска программы, так что определять их каждый раз не нужно. Макросы, в свою очередь, могут ссылаться на другие макросы (кстати, команда \stackrel, на которую ссылалась наша команда \eqdef, также является макросом) - и так далее, пока не дойдет до так называемых "примитивных команд" TeX'а. Из команд, о которых мы вам рассказывали, примитивными являются считанные единицы: \left, \right, \noindent и некоторые другие.

Команды с аргументами

Мы уже научились создавать новые команды, не требующие аргументов. Но мы хорошо знаем, что многие LaTeX'овские команды принимают аргументы, и часто возникает потребность создать новую команду с такими возможностями. Пусть, например, в вашем тексте часто встречается "символ Лежандра", выглядящий так: $$\smb{a}{l}.$$ Для получения этого символа в исходном тексте надо написать (внутри формулы, естественно) так:

\left(\frac{a}{l}\right)

Хорошо бы создать команду \smb с двумя аргументами, чтобы можно было написать в формуле "\smb{a}{l}" и получить на печати $$\smb{a}{l}.$$ Что ж, LaTeX предоставляет нам возможность сделать и это. Для создания команды с аргументами используется все та же команда \newcommand, но с необязательным аргументомМожно (и разумно) использовать в этой ситуации команду \newcommand* (" вариант со звездочкой"). См. по этому поводу ниже.. Посмотрите, как можно определить команду \smb:

\newcommand{\smb}[2]{\left(\frac{#1}{#2}\right)}

Разберем, что означает эта запись. В квадратных скобках стоит количество аргументов в нашем макросе (в нашем случае 2). Далее, в самом "замещающем тексте" появились значки "#1" и "#2" . При развертывании макроса на их место будут подставляться соответственно первый и второй аргументы нашей новой команды \smb. Например, если в формуле написать

\smb{a+b}{c}

то будет напечатано $$\smb{a+b}{c}.$$

Теперь рассмотрим точные правила. Необязательный аргумент команды \newcommand, который должен быть расположен между двумя обязательными, указывает, сколько аргументов будет требовать создаваемая вами команда (макрос). Это количество аргументов не может быть более 9. В "замещающем тексте" места, на которые при развертывании макроса будут подставляться аргументы, обозначаются символами "#1" для первого аргумента, "#2" для второго аргумента и т.д. Эти символы могут идти в любом порядке и присутствовать любое количество раз (в том числе и ни разу). Когда мы будем использовать нашу новую команду в тексте, после ее имени в фигурных скобках должны будут следовать аргументы, ровно в том количестве и в том порядке, который мы указывали в необязательном аргументе команды \newcommand, каждый — в своей паре фигурных скобок (как обязательные аргументы любой другой LaTeX'овской команды). При развертывании макроса на место его и его аргументов будет подставлен " замещающий текст", в котором вместо "#1" всюду стоит первый аргумент, вместо "#2" — второй аргумент и т.д.

Проиллюстрируем все сказанное примером. Пусть мы определили команду \shuffle следующим образом:

\newcommand{\shuffle}[4]{К#4к#2#1л}

Тогда будет получаться, например, такое:

$$\parindent=0cm \newcommand{\shuffle}[4]{К#4к#2#1л}\shuffle{ди}{о}{го}{ро} Гена и его друзья.$$
\shuffle{ди}{о}{го}{ро}
Гена и его друзья.

В самом деле, первым аргументом команды \shuffle будет ди, вторым о, третьим го, четвертым ро; при развертывании появится сначала буква К, затем четвертый аргумент, затем буква к, затем второй, первый и наконец буква л — как если бы слово Крокодил присутствовало в исходном тексте.

Ни аргументы LaTeX'овских команд (в том числе и определенных вами), ни "замещающий текст" в \newcommand не должны содержать "несбалансированных" (не имеющих пары) фигурных скобок (это не относится к \{ и \} ).

Если вы хотите создать макрос с аргументами, имя которого совпадает с именем уже существующей команды, то надо воспользоваться командой \renewcommand с необязательным аргументом. Место постановки и значение этого необязательного аргумента, а также правила употребления символов #1, #2 и т.д. при этом будут такие же, как для команды \newcommand.

Приведем еще один пример практически полезного макроса с аргументами. При написании этой книги автор широко пользовался ссылками на страницу, автоматически генерируемыми с помощью команды \pageref. Например, если какое-то место в тексте было помечено с помощью команды \label{units}, то ссылка на соответствующую страницу выглядела так:

Как мы уже отмечали на с. \pageref{units}, ...

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

\newcommand{\str}[1]{стр. \pageref{#1}}

и ссылки на страницы стало возможно оформлять так:

Как мы уже отмечали
на \str{units}, ...

(Автор вначале не знал, что надо писать "с.", а не " стр.", но мгновенно исправился, всего лишь удалив две буквы из определения команды \str!)

Команда \newcommand со звездочкой

У команд \newcommand и \renewcommand существуют варианты " со звездочкой", называемые \newcommand* и \renewcommand. Они работают точно так же, как их тезки без звездочек, со следующим отличием: если команда с аргументами определена с помощью \newcommand* или \renewcommand*, то в ее аргументе не может содержаться пустая строка или команда \par. Если ваша команда определена с помощью \newcommand или \renewcommand без звездочки, то никаких ограничений на этот счет нет.

Смысл этого запрета таков. В большинстве случаев команды с аргументами, которые вы определяете, все равно не будут предусматривать подстановку вместо аргумента фрагмента текста, содержащего пустую строку или \par, так что этот запрет ни на чем не скажется (во всех примерах, приведенных в этой книге к настоящему моменту, можно совершенно безболезненно заменить \newcommand и \renewcommand на их варианты " со звездочкой"). А вот диагностика ошибок при наличии такого запрета облегчается. В самом деле, представим себе, что вы забыли набрать закрывающую фигурную скобку в аргументе команды (весьма распространенная ошибка!), как в следующем примере (забыта фигурная скобка в самой первой формуле; команду \smb мы определили в учебных целях раньше):

Символ Лежандра $\smb{a{l}$, где $a$ не делится
на $l$,
равен по определению $1$, если $a$ является квадратичным
вычетом по модулю $l$, и $-1$ в противном случае.

Вопрос о том, как зависит $\smb{a}{l}$ от $l$ при
фиксированном $a$, является весьма важным и трудным.
Великий немецкий математик К.-Ф.Гаусс...

Если пустые строки в аргументе команды \smb не запрещены (так оно и будет, если определять \smb с помощью \newcommand без звездочки), то TeX будет терпеливо ждать, когда ему встретится закрывающая фигурная скобка, парная к первой из открывающих фигурных скобок в первой строке, а пока таковой нет — рассматривать весь читаемый им текст как составную часть первого аргумента команды \smb. В конце концов TeX либо доложит, что он прочел уже весь файл, а закрывающей фигурной скобки так и не нашел, либо прервет работу, объявив, что ему не хватило памяти.

Если же мы определим \smb с помощью \newcommand*, написав

\newcommand*{\smb}[2]{\left(\frac{#1}{#2}\right)}

то ошибка не пойдет дальше текущего абзаца: как только TeX увидит пустую строку среди текста, рассматриваемого им как аргумент команды, он тут же прервет дальнейшее чтение и выдаст следующее стандартное сообщение об ошибке:

Runaway argument?
{a{l}$, где$a$ не делится на $l$, равен п\ETC.
! Paragraph ended before \smb was complete.
<to be read again>
                   \par
l.8

?

Нажав пару раз на "ввод", мы сможем благополучно продолжить обработку текста. В первом абзаце пропадет все после слов "Символ Лежандра", зато второй и последующие абзацы будут обработаны нормально (пока TeX не наткнется на очередную ошибку...).

Команды \newcommand* и \renewcommand* обладают еще одним преимуществом перед своими вариантами без звездочек: при их использовании происходит (небольшая) экономия памяти.

Рекомендуем вам определять и переопределять команды с аргументами при помощи \newcommand* и \renewcommand*. Варианты без звездочек используйте только тогда, когда вы действительно намерены подставлять в аргумент своего макроса текст, состоящий из нескольких абзацев.

Счетчики

Теперь мы научимся самостоятельно организовывать автоматическую нумерацию, подобно тому, как LaTeX автоматически нумерует главы, страницы, формулы и т.д. Для этого нам надо познакомиться с понятием счетчика. Счетчик — это специальная переменная, значение которой является целым числом. Ей можно присваивать различные значения, выводить значение счетчика на печать, а также организовывать с помощью счетчиков автоматическую генерацию ссылок. Рассмотрим последовательно, как все это делается.

Создание счетчиков и простейшие операции с ними

Каждый LaTeX'овский счетчик имеет свое имя — последовательность букв (без знака \ ). Прописные и строчные буквы в именах счетчиков различаются; если в используемой вами русификации русские буквы нельзя употреблять в именах команд, то нельзя их употреблять и в именах счетчиков. Чтобы можно было работать со счетчиком, надо его создать командой \newcounter, имеющей один обязательный аргумент — имя, которое вы придумали для счетчика. Например, команда

\newcounter{abcd}

создает новый счетчик с именем abcd. Если имя, которое вы придумали для счетчика, уже занято (так может случиться, даже если команда \newcounter в вашем тексте всего одна: некоторые счетчики в LaTeX'е уже определены в момент начала обработки вашего текста), то LaTeX создавать счетчик с таким именем откажется и выдаст сообщение об ошибке.

В отличие от многих других LaTeX'овских команд, команда для создания нового счетчика является "глобальной": даже если она давалась внутри группы, LaTeX не забудет о существовании определенного ею счетчика и после выхода из этой группы. Это отличает \newcounter от \newcommand и \renewcommand.

Что же можно делать со счетчиком? Во-первых, можно менять его численное значение (на программистском жаргоне: "присваивать счетчику различные значения"). При создании счетчика его значение устанавливается в $$0$$ ; чтобы установить какое-то другое значение, используется команда \setcounter, имеющая два обязательных аргумента: первый — имя счетчика, второй — значение, которое счетчику присваивается. Если, например, написать

\setcounter{abcd}{1998}

то после того, как TeX прочтет эту команду, значение счетчика abcd установится равным $$1998.$$ Значение, которое присваивается счетчику, может быть и отрицательным, но обязано быть целым.

Другой способ изменить значение счетчика — это прибавить к нему какое-то целое число. Для этого используется команда \addtocounter. Эта команда также имеет два обязательных аргумента: первый — имя счетчика, второй — число, которое прибавляется к счетчику. Например, после выполнения команд

\setcounter{abcd}{100}
\addtocounter{abcd}{-27}

значением счетчика abcd будет число $$73.$$

Команды, изменяющие значение счетчика, также являются " глобальными": если с их помощью внутри группы значение счетчика было изменено, то по выходе из группы его прежнее значение не восстановится.

Перейдем к самому главному: как вывести значение счетчика на печать. Самый распространенный случай — печать значения счетчика обычными (" арабскими") цифрами. Для этого используется команда \arabic:

$$\parindent=0cm \newcounter{abcd}\setcounter{abcd}{40} Шел по улице отряд - \arabic{abcd} мальчиков подряд.$$
\setcounter{abcd}{40}
Шел по улице отряд -
\arabic{abcd}
мальчиков подряд.

Значение счетчика печатается текущим шрифтом: если значение счетчика равно, скажем, 2003, то на команду \arabic{abcd} TeX отреагирует так же, как если бы на ее месте в исходном тексте было написано 2003.

Чтобы напечатать значение счетчика римскими цифрами, надо воспользоваться командой \Roman (если мы хотим, чтобы римские цифры записывались прописными латинскими буквами) или \roman (чтобы записать римскую цифру строчными латинскими буквами):

$$\parindent=0cm \newcounter{abcd}\setcounter{abcd}{14} Людовика \Roman{abcd} звали ``Король-Солнце''.$$
\setcounter{abcd}{14}
Людовика \Roman{abcd} звали
``Король-Солнце''.

Естественно, при печати значения счетчика римскими цифрами это значение должно быть положительным числом.

Можно, наконец, напечатать букву латинского алфавита, порядковый номер которой равен значению счетчика. Для этого используются команды \alph (для печати строчной буквы) и \Alph (для печати прописной буквы):

$$\parindent=0cm \newcounter{abcd}\setcounter{abcd}{7} Наконец я узнаю, какая буква стоит в латинском алфавите на седьмом месте! Вот она: \alph{abcd}.$$
\setcounter{abcd}{7}
Наконец я узнаю, какая буква
стоит в латинском алфавите
на седьмом месте!
Вот она: \alph{abcd}.

Если значение счетчика при пользовании этими командами превышает количество букв в латинском алфавите, то LaTeX выдает сообщение об ошибке.

В LaTeX'е отсутствует команда, позволяющая напечатать русскую букву с номером, равным значению счетчика. Средствами TeX'а такую команду нетрудно создать.

Наконец, можно напечатать один из девяти символов, используемых иногда в англоязычных странах для обозначения последовательных сносок (вместо цифр). Для этого используется команда \fnsymbol, применять которую можно только внутри формул:

$$\parindent=0cm \newcounter{abcd}\setcounter{abcd}{0} Для сносок в Англии применяют такие символы: $\addtocounter{abcd}{1}\fnsymbol{abcd}$, $\addtocounter{abcd}{1}\fnsymbol{abcd}$, $\addtocounter{abcd}{1}\fnsymbol{abcd}$, а дальше попробуйте сами.$$
\setcounter{abcd}{0}
Для сносок в Англии
применяют такие символы:
$\addtocounter{abcd}{1}
\fnsymbol{abcd}$,
$\addtocounter{abcd}{1}
\fnsymbol{abcd}$,
$\addtocounter{abcd}{1}
\fnsymbol{abcd}$,
а дальше попробуйте сами.

Обратите внимание, как три идентичных фрагмента исходного текста дали на печати три разных символа.

В командах для изменения значений счетчиков можно вместо явного указания чисел использовать значения других счетчиков, для чего употребляется команда \value. Например, в результате выполнения команд

\newcounter{efgh}
\setcounter{abcd}{10}
\setcounter{efgh}{100}
\addtocounter{efgh}{-\value{abcd}}

значение счетчика efgh станет равно $$90.$$ Можно даже писать, например,

\setcounter{efgh}{1000}
\tolerance=\value{efgh}

но большого смысла в таких трюках, как правило, нет.

Применим наши познания к делу. Ранее мы обещали вам так усовершенствовать макрос \z, начинающий новый абзац и печатающий жирным шрифтом слово "Задача", чтоб он еще и автоматически нумеровал эти задачи, так, что можно было бы просто писать в исходном тексте

\z Найти сумму...
\z Решить уравнение...
\z Поезд вышел из пункта А...

и при этом знать, что номера LaTeX проставит сам. Теперь мы в состоянии решить эту проблему. Во-первых, для этого надо создать счетчик, значение которого в каждый момент будет равно номеру последней обработанной задачи; во-вторых, в определении команды \z надо предусмотреть, чтобы всякий раз значение этого счетчика увеличивалось на единицу, а затем печаталось в качестве номера задачи. В качестве имени счетчика выберем бесхитростное "zadacha":

\newcounter{zadacha}

(напомним, что при выполнении этой команды счетчику zadacha будет присвоено значение $$0$$ ). Теперь модифицируем определение макроса \z так:

\newcommand{\z}{\par\addtocounter{zadacha}{1}%
\textbf{Задача \arabic{zadacha}.} }

Напомним, что команда \par означает "завершить предыдущий абзац, если он еще не был завершен"; без нее можно обойтись, если мы будем ставить команду \z только после пустой строки. Знак процента мы поставили, чтобы убрать лишний пробел, порождаемый концом строки. Теперь при первом исполнении команды \z значение счетчика zadacha станет равно $$1$$ и будет напечатано "Задача 1.", при втором исполнении этой команды значение счетчика станет равно уже $$2$$ и напечатается "Задача 2."... и т.д., что нам и нужно!

Отношение подчинения между счетчиками

Команда \z, как мы ее определили ранее, нумерует задачи автоматически, но при этом нумерация получается " сплошной". Часто, однако, требуется, чтобы в каждом разделе документа нумерация задач начиналась заново, так что шестая задача в разделе с номером 3 была озаглавлена Задача 3.6, а первая задача в разделе с номером 4 — Задача 4.1. Сейчас мы узнаем, как этого добиться.

Выше мы упоминали, что к моменту начала обработки LaTeX'ом нашего текста некоторые счетчики уже определены. В частности, это счетчики, содержащие номера текущих разделов документа. Их имена совпадают с именами команд, генерирующих эти разделы: chapter (если классом предусмотрено разбиение на главы), section, subsection и т.д. При каждом исполнении, например, команды \section значение счетчика section увеличивается на 1, и значение этого счетчика в каждый момент равно номеру текущего раздела. Поэтому, если в определении команды \z написать

\arabic{section}.\arabic{zadacha}.

то перед номером задачи будет печататься номер текущего раздела и точка.

Но как же все-таки сделать, чтобы в каждом разделе нумерация задач начиналась заново? Можно, конечно, в начале каждого раздела присваивать счетчику zadacha значение $$0$$ с помощью \setcounter, но это некрасиво и ненадежно (а вдруг забудем?). Лучше сразу определить счетчик zadacha так:

\newcounter{zadacha}[section]

При этом счетчик zadacha будет подчинен счетчику section: всякий раз, когда значение счетчика section увеличивается на единицу командой \section, значение счетчика zadacha будет устанавливаться в нуль, и тем самым счет задач будет в каждом разделе начинаться заново. Одновременно надо в очередной раз исправить определение команды \z и написать

\newcommand{\z}{\par\addtocounter{zadacha}{1}%
\textbf{Задача \arabic{section}.\arabic{zadacha}.} }

При этом нумерация задач будет начинаться заново в каждом разделе, и вторая задача третьего раздела будет иметь номер 3.2.

Теперь сообщим точные правила создания счетчика, подчиненного другому счетчику. Они просты: команда \newcounter может принимать один необязательный аргумент ( после обязательного) — имя того счетчика, которому будет подчинен определяемый нами счетчик. Разумеется, в момент выполнения команды \newcounter с необязательным аргументом счетчик, имя которого дается в квадратных скобках, должен уже существовать.

Надо еще уточнить, в каких случаях значение подчиненного счетчика устанавливается в нуль. В самом деле, пусть счетчик slave подчинен счетчику master; тогда команда

\addtocounter{master}{1}

никоим образом не повлияет на значение подчиненного счетчика \slave: изменение значений счетчика влияет на значения подчиненных ему счетчиков только в том случае, если значение подчиняющего счетчика изменялось с помощью специальных команд. Таких команд всего две, из них чаще всего используется \refstepcounter: она увеличивает на единицу значение указанного ей счетчика, а значения всех подчиненных ему счетчиков устанавливает в нуль. Пусть, например, в нашем тексте определены два счетчика:

\newcounter{master}
\newcounter{slave}[master]

Тогда после выполнения команд

\setcounter{master}{10}
\setcounter{slave}{10}

значения обоих счетчиков станут равны $$10$$, после выполнения команды

\addtocounter{master}{1}

значение счетчика master станет равно $$11$$ и значение счетчика slave не изменится, а вот после выполнения команды

\refstepcounter{master}

значение счетчика master станет равно $$12$$, в то время как значение счетчика slave станет равно нулю.

Наряду с \refstepcounter существует еще одна команда, изменяющая значение счетчика таким образом, что значения всех подчиненных ему счетчиков устанавливаются в нуль. Эта команда называется \stepcounter ; она также увеличивает на единицу значение счетчика, имя которого является ее аргументом, и при этом обнуляет все подчиненные ему счетчики, но она непригодна для организации автоматических ссылок, вследствие чего область ее применения более ограничена.

Хороший пример использования подчиненных счетчиков дают стандартные LaTeX'овские классы документов. Например, в классе book перед началом обработки текста выполняются следующие команды:

\newcounter{part}
\newcounter{chapter}
\newcounter{section}[chapter]
\newcounter{subsection}[section]
\newcounter{subsubsection}[subsection]
\newcounter{paragraph}[subsubsection]
\newcounter{subparagraph}[paragraph]

Стало быть, нумерация глав не зависит от нумерации частей (если третья часть книги завершается десятой главой, то четвертая часть начинается с одиннадцатой главы), а нумерация разделов уже начинается заново в каждой главе.

Организация автоматических ссылок

Вернемся последний раз к нашей команде \z. Раз она автоматически нумерует задачи, то неплохо было бы, если б пронумерованные ею задачи можно было метить командой \label и ссылаться на эти метки командой \ref ссылка на счетчик, определенный пользователем} (проблема именно в ней, поскольку команда \pageref, дающая номер страницы, сработает в любом случае). Если коротко, то решение этой проблемы таково: увеличивать на единицу значение счетчика \ctr{zadacha} надо не с помощью команды \addtocounter, которой мы пользовались до сих пор, а с помощью команды \refstepcounter, о которой уже шла речь по другому поводу в предыдущем разделе. Если мы определим команду \z так:

\newcommand{\z}{\par\refstepcounter{zadacha}%
\textbf{Задача \arabic{section}.\arabic{zadacha}.} }

то после этого можно будет написать, например, так:

\z Решить уравнение...
\z Доказать...\label{prove}
\z Найти сумму...

Если теперь в другом месте текста мы сошлемся на помеченную задачу так:

В задаче \ref{prove} предлагалось доказать...

то будет печататься ее номер (тот самый, который LaTeX автоматически ей присвоил). Впрочем, с такими автоматическими ссылками не все будет благополучно: если помеченная нами задача была второй по счету в разделе номер 3, то называться она будет Задача 3.2, а вот ссылка на нее, сгенерированная командой \ref, будет выглядеть просто

В задаче 2 предлагалось доказать...

в то время как хотелось бы автоматически получить В задаче 3.2. Иными словами, надо изменить текст, генерируемый командой \ref. Чтобы узнать, как этого добиться, нам придется познакомиться с еще одной LaTeX'овской конструкцией, связанной со счетчиками.

Мы уже знаем, что значение LaTeX'овского счетчика можно вывести на печать командами \arabic, \roman и т.п. Однако, кроме этого, с каждым счетчиком связана индивидуальная команда, определяющая, в какой форме его значение будет выводиться на печать, и именно в соответствии с этой командой печатается ссылка, сгенерированная с помощью \label и \ref. Имя этой команды получается, если поставить the перед именем счетчика. Например, команда для вывода на печать номера раздела называется \thesection, для вывода на печать номера главы — \thechapter, команды для вывода на печать определенных нами счетчиков slave и master — \theslave и \themaster. При создании счетчика автоматически определяется и соответствующая the-команда. Именно, при создании счетчика по имени, скажем, abcd автоматически определяется команда \theabcd таким образом:

\newcommand{\theabcd}{\arabic{abcd}}

В дальнейшем эту команду можно переопределять:

$$\parindent=0cm \newcommand{\theabcd}{\arabic{abcd}} \renewcommand{\theabcd}% {\Roman{abcd}} \setcounter{abcd}{14} Людовика \theabcd{} звали ``Король-Солнце''.$$
\renewcommand{\theabcd}%
{\Roman{abcd}}
\setcounter{abcd}{14}
Людовика \theabcd{} звали
``Король-Солнце''.

Мы же, чтобы при ссылках перед номером задачи печатался номер раздела, в котором находится эта задача, и точка, переопределим команду \thezadacha так:

\renewcommand{\thezadacha}{\thesection.\arabic{zadacha}}

Если включить эту команду в преамбулу документа, то ссылки на сгенерированные нашей командой \z номера задач будут выглядеть должным образом.

В нашем переопределении команды \thezadacha мы воспользовались командой \thesection, чтобы наши макросы правильно работали с любым классом документов. Дело в том, что при разумном оформлении номер раздела, предшествующий при ссылке номеру задачи, должен печататься таким же образом, как и номер раздела при ссылке на раздел, а это в разных классах делается по-разному: в классе article, например, \thesection — это то же самое, что и \arabic{section} (иными словами, ссылка на раздел, сгенерированная командой \ref, печатает просто номер раздела), а в классе report команда \ref при печати ссылки на раздел печатает не номер раздела, а номер главы, точку и номер раздела. Поскольку мы написали \thesection, все эти тонкости будут учтены автоматически.

Приведем еще один (игрушечный) пример использования счетчиков в макроопределениях, отчасти чтобы еще раз продемонстрировать применение подчиненных счетчиков, а отчасти чтобы убедить читателя, что не боги горшки обжигают. Именно, давайте разработаем свои собственные команды для создания разделов документа, не полагаясь на \chapter, \section и т.п. из стандартных LaTeX'овских классов. Для простоты предположим, что заголовки глав и разделов будут укладываться в одну строку, и не будем заботиться о том, насколько удачным выйдет оформление заголовков. Итак, пусть наш документ делится на главы, которые, в свою очередь, делятся на разделы. Каждую главу будем начинать с новой страницы, перед каждым разделом оставлять 1cm (если, конечно, раздел не начинает новой страницы). Наконец, предусмотрим, чтобы главы и разделы автоматически нумеровались с возможностью создания автоматических ссылок на эти номера. Команды для создания главы и раздела назовем \glava и \razdel ; это будут команды, требующие одного аргумента — названия главы или раздела.

Чтобы номера глав и разделов генерировались автоматически, нам необходимо создать счетчики, содержащие эти номера. Пусть счетчик с номером главы называется glava, а счетчик с номером раздела — razdel (имена счетчиков могут совпадать с именами команд). Имея в виду, что нумерация разделов в каждой главе будет начинаться заново, напишем в преамбуле так:

\newcounter{glava}
\newcounter{razdel}[glava]

Теперь определим команду \glava:

\newcommand*{\glava}[1]{\clearpage % с новой страницы
\vspace*{4cm}% оставить место сверху
\refstepcounter{glava}% новый номер главы
{\LARGE\rmfamily\bfseries\upshape % шрифт для заголовка
Глава \theglava. #1% заголовок
\par % кончить заголовок
\vspace{5mm plus 1mm minus .5mm}% Промежуток между
% заголовком и текстом
}% завершить группу, внутри которой менялся шрифт
}% конец макроопределения

Поскольку номер главы устанавливается командой \refstepcounter, при этом будет начата заново и нумерация разделов, а на номера глав можно будет делать автоматические ссылки с помощью \label и \ref. В определении шрифта для заголовков мы в явном виде установили все четыре атрибута, чтобы быть уверенными, что он будет какой надо (если бы мы, например, не сказали \upshape, а предыдущая глава заканчивалась курсивом, определенным командой \itshape, данной вне группы, то заголовок напечатался бы жирным курсивом).

Обратите также внимание на команду \theglava. Мы воспользовались ею, поскольку не хотим на этом этапе предрешать, в каком виде номер главы будет представлен в заголовке: в виде арабской цифры, римской цифры или еще как-нибудь. Если в дальнейшем нам захочется изменить вид этого представления, то не придется менять, с риском ошибиться, длинное определение команды \glava, а будет достаточно переопределить команду \theglava. Заметьте, что промежуток между заголовком и текстом мы сделали растяжимым, чтобы помочь TeX'у найти правильное разбиение на страницы.

Определение команды \razdel можно дать, например, так:

\newcommand{\razdel}[1]{\par % завершить предыдущий абзац
\pagebreak[2]\vspace{1cm plus 3mm minus .5mm} % см. ниже
\refstepcounter{razdel}% новый номер раздела
{\Large\rmfamily\bfseries\upshape % шрифт для заголовка
\therazdel{} #1% заголовок
\par % закончить заголовок
}% завершить группу, внутри которой менялся шрифт
\nopagebreak % чтобы не оторвать текст от
             % заголовка
\vspace{2mm plus 1mm}% Промежуток между заголовком
                     % и текстом
}% конец макроопределения

Пояснений тут требует команда \pagebreak[2]. Мы включили ее в макроопределение, чтобы поменьше разделов начиналось внизу страницы. В самом деле, команда \pagebreak[2] предлагает TeX'у начать в этом месте новую страницу; если так и будет сделано, то дополнительный вертикальный промежуток, созданный командой \vspace, пропадет, и заголовок раздела начнется с самого верха новой страницы; если же разрыва страницы все-таки не произойдет, то перед заголовком раздела будет вертикальный промежуток в один сантиметр (обладающий указанными в макроопределении растяжимостью и сжимаемостью).

Нам осталось только задать вид, в котором будут представляться на печати номера глав и разделов. Иными словами, надо переопределить должным образом команды \theglava и \therazdel (в момент создания счетчиков они, как мы помним, были автоматически определены таким образом, что \theglava и \therazdel — номера главы и раздела, набранные арабскими цифрами). Предположим, мы решили, что номера глав будут печататься римскими цифрами, а номер второго раздела четвертой главы будет иметь вид IV-2. Тогда требуемые переопределения таковы:

\renewcommand{\theglava}{\Roman{glava}}
\renewcommand{\therazdel}{\theglava--\arabic{razdel}}

Еще одно замечание: точки после номера главы мы включили в определение команды \glava, а не \theglava, чтобы можно было пользоваться автоматическими ссылками: если бы \theglava определялось как

\Roman{glava}.

то исходный текст

в главе \ref{metka} мы пишем...

дал бы на печати

в главе IV. мы пишем

что нелепо.

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

Счетчики, которые уже определены

Мы уже мельком упоминали, что при начале работы LaTeX'а некоторые счетчики определены сразу. Например, это те счетчики, которые перечислены выше. Кроме того, заранее определен счетчик page, отвечающий за нумерацию страниц, а также счетчик footnote, ответственный за нумерацию сносок. Нумерацией плавающих иллюстраций и таблиц занимаются счетчики, называемые figure и table. В одном из разделов перечислены все эти заранее определенные счетчики и указано, каким счетчикам они подчинены (это иногда зависит от класса документа).

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

\renewcommand{\thechapter}{\Roman{chapter}}

Если вы хотите, чтоб сноски нумеровались не цифрами, а латинскими буквами, то можно в преамбуле написать:

\renewcommand{\thefootnote}{\alph{footnote}}

Модификация оформления перечней

Начнем с {itemize}. Чтобы поменять значки, которыми помечаются элементы перечня, надо переопределить команду \labelitemi. Если, например, мы хотим, чтобы элементы перечня отмечались не черными кружками, а галочками $$\surd$$, то достаточно написать в преамбуле

\renewcommand{\labelitemi}{$\surd$}

. Если окружение {itemize} расположено внутри другого окружения {itemize}, как в примере на {itemize}, то значки для пометки элементов перечня будут уже, вообще говоря, другими: их вид задается командой \labelitemii ; вид значков для пометок элементов itemize на третьем и четвертом уровнях вложенности задается командами \labelitemiii и \labelitemiv ; их также можно переопределять.

Правильнее было бы определять заголовки для itemize чуть хитрее. Например, наше определение \labelitemi лучше дать так:

\renewcommand{\labelitemi}{$\mathsurround=0pt \surd$}

Если дать определение именно так, то вокруг галочки не появится дополнительный пробел даже в случае, если вы в какой-то момент решите установить ненулевое значение параметра \mathsurround. Поскольку формула образует группу, в дальнейшем предыдущее значение \mathsurround восстановится. Полезно иметь в виду этот прием, если вы пользуетесь математическими символами в качестве типографских значков.

Теперь рассмотрим окружение {enumerate}. Коль скоро оно автоматически нумерует элементы перечня, можно предположить, что это окружение связано с LaTeX'овскими счетчиками. Так оно на самом деле и есть: это окружение использует счетчик enumi. Если одно {enumerate} вложено в другое, то используются счетчики enumii, enumiii и enumiv для нумерации элементов перечня на втором, третьем и четвертом уровнях вложенности. С другой стороны, сами значки, помечающие элементы перечня, порождаются командами \labelenumi, \labelenumii, \labelenumiii и \labelenumiv — в зависимости от уровня вложенности. Например, команда \labelenumi определена так:

\newcommand{\labelenumi}{\theenumi.}

в то время как the-команда, определяющая представление счетчика enumi на печати, определена просто как

\newcommand{\theenumi}{\arabic{enumi}}

Стало быть, если мы не меняем стандартного стиля оформления, то элементы перечня {enumerate} (не вложенного в другой {enumerate} ) будут нумероваться цифрами с точкой. Если же мы хотим, скажем, чтобы после цифры шла не точка, а скобка (как в нашей книге), то можно в преамбуле написать

\renewcommand{\labelenumi}{\theenumi)}

Если же мы к тому же хотим, чтобы элементы перечня нумеровались римскими цифрами, то можно написать еще и так:

\renewcommand{\theenumi}{\Roman{enumi}}

Аналогичным образом можно менять оформление нумерованных перечней на других уровнях вложенности.

Если вы хотите изменить оформление перечня более серьезным образом (например, установить другую величину полей, или сделать так, чтобы значки, помечающие элементы перечня, были выровнены по левому, а не по правому краю), то вам придется подождать до лекции 9.

Параметры со значением длины

Наряду со счетчиками — переменными с целочисленными значениями, — при создании собственных макроопределений возникает нужда и в переменных, значениями которых являются длины. Например, в предыдущем разделе мы, разрабатывая команду \razdel, в явном виде задали промежуток между заголовком раздела и остальным текстом. Если этот промежуток нам почему-либо захочется изменить, то придется снова залезать в определение команды \razdel. Было бы удобнее, если бы в нашем распоряжении был параметр под названием, скажем, \otstup, так что можно было бы в определении команды \razdel написать

\vspace{\otstup}

и потом отдельно написать, допустим,

\otstup=1cm plus 3mm minus .5mm

Правда, в богатом наборе TeX'овских и LaTeX'овских параметров требуемого нам параметра \otstup нет, но это не страшно, поскольку его можно создать. Для этого используется команда \newlength:

\newlength{\otstup}

После того, как вы (допустим, в преамбуле) дали эту команду, будет определен новый параметр со значением длины; его можно будет обычным образом использовать в аргументах команд наподобие \vspace, и ему можно будет обычным образом присваивать значения.

Теперь — точные правила. Команда \newlength имеет один обязательный аргумент — имя команды, обозначающей определяемый вами параметр. Это имя должно подчиняться обычным правилам для TeX'овских команд (backslash, после которого следует либо одна не-буква, либо последовательность букв). Если это имя уже занято, LaTeX выдаст сообщение об ошибке. Определение нового параметра, совершаемое командой \newlength, является "глобальным": даже если эта команда была дана внутри группы, TeX будет помнить о существовании этого параметра и по выходе из группы. По этой причине разумное место для команды \newlength — преамбула.

Определенный нами параметр со значением длины приобретает такой же статус, как уже существующие TeX'овские и LaTeX'овские параметры ( \parindent, \textwidth и другие). Рассмотрим, что можно делать с этими параметрами.

Во-первых, параметрам со значением длины можно присваивать значения. Делается это точно так же, как это объяснялось ранее на примере параметра \parindent: для присваивания значения надо написать имя параметра, знак равенства, а после знака равенства — величину присваиваемой длины. Пробелы после указания единицы длины TeX'ом игнорируются (скорее всего, вы будете присваивать значения параметрам в преамбуле документа или между абзацами, где лишние пробелы никого не волнуют). Длина должна быть выражена в единицах, воспринимаемых TeX'ом. Даже если вы присваиваете нулевую длину, какая-то единица длины должна быть явно указана (например, 0pt). Кроме того, можно воспользоваться LaTeX'овской командой \setlength, имеющей два обязательных аргумента: первый — имя параметра, второй — значение длины, присваиваемое этому параметру. Таким образом, команды

\parindent=1.5em

и

\setlength{\parindent}{1.5em}

равносильны. Наконец, присваивания, сделанные внутри группы, забываются по выходе из этой группы.

В предыдущем абзаце мы умолчали об одной возможной неприятности. Дело в том, что если после команды присваивания, не использующей \setlength, следует (пусть даже после пробела) слово plus или minus, то TeX, скорее всего, выдаст сообщение об ошибке, поскольку решит, что длина должна иметь, помимо " естественного размера", еще и plus - или minus -компоненту. Если вы пишете текст на русском языке, вероятность такого стечения обстоятельств ничтожна, но тем не менее забывать о такой опасности не следует, особенно если команда присваивания входит в макроопределение: вы же не знаете заранее, в какое место может попасть новый макрос. Чтобы застраховаться от этой неприятности раз и навсегда, пользуйтесь командой \setlength, хоть это и длиннее.

Параметры со значением длины можно использовать всюду, где в аргументе LaTeX'овской команды требуется указать размер. Пусть, например, в преамбуле документа написано

\newlength{\primer}

Тогда посмотрите на следующий пример:

$$\newlength{\primer} \parindent=0mm \primer=10mm 9\hspace{\primer}9 {\primer=20mm 8\hspace{\primer}8} 9\hspace{\primer}9$$
\primer=10mm
9\hspace{\primer}9

{\primer=20mm
8\hspace{\primer}8}

9\hspace{\primer}9

Обратите внимание, что, если присваивание параметру нового значения происходило внутри группы, то по выходе из группы новое значение забывается, а прежнее — восстанавливается.

Параметры со значением длины можно указывать с коэффициентом - положительной или отрицательной десятичной дробью (можно использовать как десятичную точку, так и десятичную запятую). Например, если значение параметра \primer равно $$10 мм$$, то команда \hspace{2.71\primer} сделает пробел длиной $$27.1\,\rm мм.$$

Параметры со значением длины (возможно, с числовыми коэффициентами) могут также стоять в правой части оператора присваивания (или во втором аргументе команды \setlength ):

\primer=1.45\parindent
\setlength{\primer}{.45\tabcolsep}

Можно также прибавлять длину к значению параметра: если значение параметра \abcd равно $$x$$, то после выполнения команды

\addtolength{\abcd}{"$y$\verb"}

где $$y$$ - длина, значение параметра "\abcd" станет равно $$x+y.$$ В качестве $$y$$ в этой команде может использоваться как явно указанная длина (например, 1.2in), так и параметр со значением длины (возможно, с числовым коэффициентом). Наконец, LaTeX предоставляет полезную команду

\settowidth{"\textit{параметр}\verb"}{"\textit{текст}\verb"}

которая присваивает параметру значение, равное ширине текста. Вот пример:

$$\newlength{\primer} \parindent=0mm \settowidth{\primer} \settowidth{\primer}{\Large слово } {\Large слово }слово \hspace{\primer}слово $$
\settowidth{\primer}{\Large
слово }
{\Large слово }слово

\hspace{\primer}слово

(обратите внимание, что у нас получилось выравнивание без помощи {tabbing} или {tabular}).

Существуют также команды \settoheight и \settodepth, аналогичные \settowidth. Команда \settoheight присваивает параметру значение, равное максимальному расстоянию, на которое текст возвышается над строкой (точнее, над ее базисной линией). \settodepth присваивает параметру значение, равное максимальному расстоянию, на которое текст опускается ниже базисной линии.

Ранее у нас шла речь о том, что некоторые используемые в TeX'е длины могут обладать растяжимостью или сжимаемостью. Параметрам, созданным с помощью команды \newlength, также можно присваивать значения, содержащие plus и/или minus -компоненту. Если, например, мы хотим, чтобы параметр \primer имел естественный размер $$2\,\text{см}$$, растяжимость $$4\,\text{мм}$$ и сжимаемость в один пункт, то можно написать так:

\setlength{\primer}{2cm plus 4mm minus 1pt}

Создание новых окружений

Новые окружения: общий случай

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

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

\begin{tabular}{|p{7cm}|}
\hline
Этот текст будет заключен в рамку. Как видите,
окружение, предназначенное для верстки таблиц,
можно использовать и для этих целей.\\
\hline
\end{tabular}

При этом будет напечатано вот что:

$$\begin{tabular}{|p{7cm}|} \hline Этот текст будет заключен в рамку. Как видите, окружение, предназначенное для верстки таблиц, можно использовать и для этих целей.\\ \hline \end{tabular}$$

Если таких рамок с текстом у вас много, то можно сократить число нажатий на клавиши, определив окружение с именем, скажем, {ramka}, так, чтоб можно было бы просто писать

\begin{ramka}
Этот текст будет ...
... этих целей.
\end{ramka}

Определяется это окружение так:

\newenvironment{ramka}{\begin{tabular}{|p{7cm}|}
                       \hline}{\\\hline\end{tabular}}

В общем случае команда \newenvironment имеет такой формат:

\newenvironment{имя}{открывающие\_команды}{закрывающие\_команды}

Здесь имя — имя определяемого окружения, открывающие\_команды — команды и/или текст, подставляемые вместо команды \begin с именем окружения, закрывающие\_команды — команды и/или текст, подставляемые вместо команды \end с именем окружения.

Вместо окружения, определяемого с помощью \newenvironment, можно с тем же успехом создать два макроса: один — для открывающих\_команд, другой — для закрывающих. Например, в нашем случае с рамкой можно было бы написать

\newcommand{\nachalo}{\begin{tabular}{|p{7cm}|}\hline}
\newcommand{\konec}{\\\hline\end{tabular}}

и создавать рамки так:

\nachalo
Этот текст...
\konec

Преимущество оформления такого рода конструкций в виде окружений состоит в том, что при этом легче контролировать ошибки: если вы напишете \begin{ramka} и при этом забудете написать соответствующую команду \end{ramka}, то LaTeX выдаст сообщение об ошибке, в котором именно это вам и скажет; если же вы забудете команду \konec, то сообщения об ошибке будут менее понятными. Кроме того, нелишне напомнить, что команды \begin и \end, ограничивающие окружение, ограничивают группу: все неглобальные определения и изменения параметров, происходящие внутри окружения, забываются по выходе из него.

Новые окружения можно определять так, чтобы они принимали аргументы. Пусть, например, в зависимости от обстоятельств нам нужны рамки разной ширины. Тогда разумно модифицировать определение окружения {ramka} таким образом, чтобы ширина текста в рамке передавалась ему как аргумент. Соответствующее определение будет выглядеть так:

\newenvironment{ramka}[1]{\begin{tabular}{|p{#1}|}
                       \hline}{\\\hline\end{tabular}}

После этого можно писать, например,

\begin{ramka}{6cm}
Текст...
\end{ramka}

или даже

\begin{ramka}{.85\textwidth}
Текст...
\end{ramka}

Общие правила таковы. Чтобы создать окружение с аргументами, надо воспользоваться командой \newenvironment c необязательным аргументом. Этот необязательный аргумент ставится между первым и вторым обязательными; как и в случае с \newcommand, он означает количество аргументов, которые будет требовать окружение, и это количество не может превышать девяти; места, куда будут вставлены аргументы, по-прежнему обозначаются #1,...,#9, причем эти значки можно употреблять только в открывающих командах (т.е. во втором обязательном аргументе команды \newenvironment )

С помощью \newenvironment нельзя переопределить уже существующее окружение (если вы все же попробуете так сделать, LaTeX выдаст сообщение об ошибке). Если вам действительно необходимо такое переопределение, надо пользоваться командой \renewenvironment, работающей точно так же, как и \newenvironment, с тем различием, что в качестве первого аргумента ей можно передавать только имя уже существующего окружения.

У команд для переопределения окружения также существуют " варианты со звездочкой": \newenvironment* и \renewenvironment*. Если окружение с аргументами определено с помощью одной из этих команд, то в его аргументе запрещены пустые строки или команды \par.

Окружения типа " теорема"

Если вы пишете математический текст, то в этом тексте будет содержаться немалое количество теорем, лемм, определений и тому подобных вещей. Эти элементы математического текста желательно оформлять специальным образом. Например, формулировки теорем часто печатают, для ясности, другим шрифтом, само слово "теорема" также выделяют (третьим) шрифтом и т.д. Чтобы задать такое оформление, в исходном тексте приходится написать довольно много TeX'овских команд, и лучше не повторять этот длинный набор команд много раз, а создать заменяющее его макроопределение, что, в свою очередь, может потребовать некоторого труда (чем-то подобным мы занимались в предыдущих разделах, когда разрабатывали команду \z ). Если же вы или редакция, с которой вы имеете дело, не слишком требовательны к деталям оформления, то соответствующие макросы (точнее говоря, новые окружения) легко создать из полуфабрикатов, предоставляемых нам для этих целей LaTeX'ом.

Окружения, используемые в LaTeX'е для оформления фрагментов текста типа "теорема", заранее не определены. Дело в том, что количество различных типов объектов наподобие теоремы, присутствующих в одном тексте, может быть достаточно велико (предложение, утверждение, лемма, определение, замечание,...), так что LaTeX в целях экономии машинной памяти и исходя из того, что на все вкусы таких окружений все равно не напасешься, определять их предоставляет вам. Как это делать, удобнее всего разобрать на примере.

Пусть в нашем тексте присутствуют "предложения". Давайте создадим окружение {predl} таким образом, чтобы можно было, например, писать

$$\newtheorem{predl}{Предложение}\begin{predl} Волга впадает в Каспийское море. \end{predl} \textbf{Доказательство.} См. любую географическую карту.$$
\begin{predl}
Волга впадает в Каспийское море.
\end{predl}
\textbf{Доказательство.}
См. любую географическую карту.

Для создания такого окружения используется команда \newtheorem:

\newtheorem{predl}{Предложение}

Как видите, команда \newtheorem имеет два обязательных аргумента: первый - название окружения, которое мы создаем, второй - заголовок нашей "теоремы".

Теперь обсудим, как работают окружения, созданные при помощи команды \newtheorem (будем называть их просто окружениями типа "теорема"). Во-первых, как вы уже заметили, формулировка печатается курсивом, а заголовок — полужирным шрифтом. Во-вторых, абзац, идущий после нашего окружения, начинается с абзацным отступом, если после закрывающей окружение команды \end идет пустая строка, и без отступа в противном случае (так что в этом отношении окружения типа "теорема" ведут себя совершенно аналогично таким окружениям, как {quote}, {itemize} и т.п.). В-третьих, окружение типа " теорема" может иметь необязательный аргумент (как обычно, в квадратных скобках). Текст, стоящий в этих квадратных скобках, будет напечатан в скобках после заголовка "теоремы" и ее номера. Обычно это используется для указания ученого, чьим именем названа "теорема":

$$\newtheorem{predl}{Предложение} \setcounter{predl}{1} \begin{predl}[Пифагор] Пифагоровы штаны на все стороны равны. \end{predl}$$

При пользовании классами документов, предоставляемыми Американским математическим обществом, появляются дополнительные возможности влиять на оформление "теорем". См. следующий пункт.

Вместе с окружением типа "теорема" автоматически создается и счетчик, хранящий его номер. Имя этого счетчика совпадает с именем окружения (так что в нашем примере счетчик называется predl); чтобы изменить представление на печати номеров наших "теорем", можно обычным образом переопределить соответствующую the-команду. Например, если мы хотим, чтобы предложения нумеровались прописными латинскими буквами, надо в преамбуле написать:

\renewcommand{\thepredl}{\Alph{predl}}

" Теоремы", определяемые описанным выше способом, будут иметь сплошную нумерацию на протяжении всего документа. Как мы уже понимаем, это далеко не всегда удобно. Часто хотелось бы сделать так, чтоб, например, в каждом разделе нумерация " теорем" начиналась заново. Для таких целей предусмотрена команда \newtheorem с необязательным аргументом. Этот аргумент ставится после двух обязательных и представляет собой имя того счетчика, которому будет подчинен счетчик нашей " теоремы". Пусть, например, в нашем тексте есть не только предложения, но и теоремы (без кавычек), и мы хотим, чтобы нумерация теорем начиналась заново в каждом разделе. Тогда можно написать в преамбуле так:

\newtheorem{theorem}{Теорема}[section]

После этого можно будет писать, например, вот что:

$$\newtheorem{theorem}{Теорема}[section] \setcounter{section}{5} \begin{theorem} Сумма углов треугольника равна $180^{\circ}$. \end{theorem}$$
\begin{theorem}
Сумма углов треугольника
равна $180^{\circ}$.
\end{theorem}

Обратите внимание, что, если "теорема" определена таким образом (со счетчиком, подчиненным другому счетчику), то представление ее номера на печати изменяется: при определении

\newtheorem{xyz}[abcd]

(счетчик "теоремы" типа xyz подчинен счетчику abcd) команда \thexyz будет определена как

\theabcd.\arabic{xyz}

(если вы хотите, чтобы нумерация "теоремы" представлялась на печати иначе, вы опять-таки можете переопределить the-команду).

Наконец, LaTeX предоставляет еще одну возможность нумерации определяемых вами "теорем". Предположим, что кроме теорем в вашем тексте есть еще и леммы, и при этом вы хотите, чтобы леммы и теоремы нумеровались совместно: теорема 2.1, теорема 2.2, затем лемма 2.3, затем теорема 2.4 и т.д. Тогда, предполагая, что окружение {theorem} уже определено, как выше, можно определить окружение {lemma} так:

\newtheorem{lemma}[theorem]{Лемма}

В этом случае необязательный аргумент команды \newtheorem располагается между двумя обязательными; этот аргумент - имя того окружения типа "теорема", совместно с которым будет нумероваться определяемая вами "теорема".

Команду \newtheorem можно использовать или с одним необязательным аргументом, или с другим, но не с обоими вместе.

Окружения типа "теорема" в пакете amsthm

Все LaTeX'овские "теоремы", определяемые пользователем при помощи окружения {newtheorem}, оформляются в одном и том же стиле, что не всегда приемлемо. Пакет {amsthm}, распространяемый Американским математическим обществом, позволяет внести в это оформление некоторое разнообразие. Итак, предположим, что вы его подключили. Что нового, по сравнению с "чистым" LaTeX'ом, можно сделать?

Во-первых, в этом пакете определен "вариант со звездочкой" команды \newtheorem. Именно, если определить очередной тип " теорем" с помощью \newtheorem* вместо \newtheorem, то "теоремы" указанного типа не будут нумероваться.

Во-вторых, для управления стилем оформления окружений типа "теорема" предназначена команда \theoremstyle, аргументом (единственным) которой может быть слово plain , definition или remark. Если в преамбуле дать эту команду с одним из трех допустимых аргументов, то все "теоремы", определяемые с помощью \newtheorem после этой команды \theoremstyle, будут оформлены в соответствующем стиле; чтоб определить тип теорем, оформляемый в другом стиле, надо написать еще одну команду \theoremstyle (с другим аргументом, разумеется), а уж после нее — очередную \newtheorem. Стиль plain рекомендуется для собственно теорем, предложениий и лемм, definition — для определений, remark — для замечанийВ стиле plain заголовок печатается жирным шрифтом, а текст " теоремы" — курсивом, в стиле definition заголовок печатается жирным шрифтом, а текст " определения" — прямым, в стиле remark заголовок печатается курсивом, а текст "замечания" — прямым шрифтом.. Если в преамбуле нет ни одной команды \theoremstyle, подразумевается стиль plain.

В-третьих, в пакете amsthm предусмотрено также окружение proof, предназначенное для оформления доказательств. Это окружение автоматически ставит слово Proof в начало доказательства и автоматически же завершает доказательство символом $$\square.$$ Если вас не устраивает, что слово "доказательство" пишется по-английски, нужно переопределить с помощью \renewcommand команду \proofname. Если символ $$\square$$ нужен вам сам по себе (например, как знак завершения какого-то рассуждения, не выделенного в качестве доказательства нумерованного утверждения), можно воспользоваться командой \qed.

Окружение proof допускает и необязательный аргумент: если написать, скажем,

\begin{Proof}[Доказательство основной теоремы]

то вместо слова Proof появится текст, записанный нами в квадратных скобках.

Вернуться к учебному плану