Организация автоматических ссылок
Вернемся последний раз к нашей команде \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}} В дальнейшем эту команду можно переопределять:
\renewcommand{\theabcd}% {\Roman{abcd}} \setcounter{abcd}{14} Людовика \theabcd{} звали ``Король-Солнце''. |
\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, вы сможете усовершенствовать эти определения.