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

Блоковые переменные


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

\newcommand{\abcd}{\parbox{6cm}% {Когда в товарищах согласья нет, на лад их дело не пойдет, и выйдет из него не дело — только м\'ука.}}

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

Давайте приведем пример того, как можно этим пользоваться. Выше мы приводили пример псевдорисунка — наклонной решетки, и там же мы отметили, что экономнее было бы создать наклонный отрезок раз и навсегда, а затем только повторять его. Теперь мы можем объяснить, как это сделать. Создадим блоковую переменную под названием \blok, написав в преамбуле следующее:

\newsavebox{\blok}

Теперь сверстаем тот текст, который будет храниться в нашей блоковой переменной, и запишем его в эту переменную.
Для этих целей используется команда \sbox с двумя обязательными аргументами: первый — имя блоковой переменной, второй — текст, который в нее записывается. Итак:

\sbox{\blok}{\line(1,5){10}} А теперь можно воспользоваться нашей блоковой переменной. Чтобы напечатать содержимое блоковой переменной, используется команда \usebox с одним обязательным аргументом — именем переменной. В нашем случае мы используем блоковую переменную в аргументе команды \multiput:



\begin{picture}(100,50) \multiput(0,0)(10,0){10}% {\usebox{\blok}} \multiput(0,0)(2,10){6}% {\line(1,0){90}} \end{picture} Можно было бы сделать аналогичный трюк и с горизонтальными линейками решетки, но большой экономии это не даст: горизонтальные и вертикальные линейки на псевдорисунках LaTeX не собирает из отдельных символов, а создает "в один присест" с помощью команд \hrule и \vrule, что и так достаточно быстро.

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

Наряду с командой \sbox есть еще и команда \savebox, относящаяся к ней примерно так же, как \makebox относится к \mbox: между первым и вторым обязательным аргументами команды \savebox могут присутствовать необязательные аргументы, имеющие тот же смысл и записывающиеся так же, как необязательные аргументы команды \makebox. Например,

\savebox{\пример}[4cm][r]{Слово} даст тот же результат, что и

\sbox{\пример}{\makebox[4cm][r]{Слово}} Наряду с LaTeX'овской командой \usebox есть похожая на нее, но не идентичная, TeX'овская команда \copy. Используется она так:

\sbox{\blok}{Рак} Однажды Лебедь, \copy\blok{} и Щука\ldots
Обратите внимание, что при использовании команды \copy имя блоковой переменной не заключается в фигурные скобки! Различие между \copy и \usebox такое же, как между \hbox и \mbox: будучи употребленными внутри абзаца (или, скажем, в аргументе команд \put, \hbox или \mbox), эти две команды действуют совершенно одинаково, а вот будучи употребленным между абзацами, LaTeX'овское \usebox начинает новый абзац, в то время как TeX'овское \copy просто подверстывает блок к странице, нового абзаца не начиная.




Эту разницу следует иметь в виду, когда вы работаете с командой \leaders: выгоднее сверстать блок один раз и записать его в блоковую переменную, а затем в команде \leaders писать просто \copy. Пример:



\savebox{\blok}[1cm]{$*$} \hbox to \textwidth {\leaders\copy\blok\hfil}
В этой ситуации по TeXническим причинам сказать \usebox нельзя.

Для тех, кто будет читать следующую лекцию, скажем еще об одной конструкции, связанной с блоковыми переменными. Именно, если \blok — блоковая переменная, то можно " измерить" ширину, высоту и глубину блока, записанного в этой переменной, с помощью TeX'овских команд \wd, \ht и \dp. Точнее говоря, сочетания \wd\blok, \ht\blok и \dp\blok можно использовать в точности так же, как TeX'овские параметры со значением длины, значения которых равны ширине, высоте и глубине блока:



\sbox{\blok}{12345}\copy\blok\\ \hbox to \wd\blok{\hfil 345}\\ \hbox to \wd\blok{\hfil 45}
Для большинства элементарных приложений в LaTeX'е вполне хватает возможностей измерения блоков, предоставляемых командой \settowidth и ее аналогами, но в лекции 9 нам встретятся ситуации, в которых без \wd не обойтись.

  1)   Но не \hrule или \vrule: это команды TeX'а, а не LaTeX'а.
  2)   Пустых строк, однако, быть не должно.
  3)   Если мы заставим такую пружину растянуться или сжаться больше, чем сказано, то получим сообщение "Underfull \hbox" или "Overfull \hbox"; см.\ ниже.


Содержание раздела