Диплом бакалавра в LaTeX, или ДСТУ 3008-95 в 150 строк
Всем привет. Недавно меня тоже настигла переломная веха студенческой жизни — бакалаврская дипломная работа. Среди многих формальных деталей этого замечательного явления особо заметным стоит нормоконтроль. Нет, я понимаю и всячески поддерживаю, что стандарты необходимы, в том числе стандарты на оформление академического текста. Просто наши стандарты, в отличие от западных, достаточно идиотичны. Они не экономят ни чернила, ни бумагу, они не упрощают поиск литературы по номенклатуре, а усложняют чтение названия. Не говоря уже о том, что текст стандарта спроектирован и описан людьми, работающими в редакторе Microsoft Word. Опять-таки, я не имею ничего против Word, это мощнейшая система. Но технический текст в нем набирать неудобно, и по гибкости он во много раз проигрывает бессмертному творению Дональда Кнута — LaTeX.
Итак, мое написание диплома началось с того, что я потратил 4 часа на настройку преамбулы под нормы украинского стандарта оформления ДСТУ 3008-95. Насколько мне известно, он почти полностью соответствует русскому ГОСТу. Я знал, что существуют готовые решения (например, disser), но после пары проб предпочел настроить каждую деталь самостоятельно. Для тренировки. Тренировка удалась — я узнал бездну новых вещей о LaTeX, этого монстра невозможно выучить полностью :-)
Под катом я полностью опишу процесс настройки каждой конкретной детали и использование их при написании, а также разные мелочи, упрощающие написание диплома еще больше. Сразу предупреждаю: где-то мои решения могут показаться костылями. Где-то они не слишком универсальны. Я это знаю, понимаю, принимаю и приветствую критику и предложения в комментариях ;-)
ЗаготовкаНачнем с заготовки. Я предполагаю, что у вас установлен дистрибутив (MiKTeX на Windows или любой аналогичный на Linux/Mac) и настроены кириллические шрифты PsCyr по инструкции. Не забудьте включить установку дополнительных пакетов «на лету» — вам их понадобится много :)
Стандарт предполагает написание всего текста 14 шрифтом Times New Roman с полуторным интервалом. Последнее — терминология Microsoft Word :) Чтобы составить её аналог в LaTeX, подключим пакет extsizes , который добавляет в параметры класса документа 14pt, и настроим все остальное, как написано ниже:
\usepackage < extsizes > \usepackage < cmap >% для кодировки шрифтов в pdf \usepackage [ T2A ] < fontenc > \usepackage [ utf8 ] < inputenc > \usepackage [ russian ] < babel > \usepackage
\usepackage < graphicx >% для вставки картинок \usepackage < amssymb,amsfonts,amsmath,amsthm >% математические дополнения от АМС \usepackage < indentfirst >% отделять первую строку раздела абзацным отступом тоже \usepackage [ usenames,dvipsnames ] < color >% названия цветов \usepackage < makecell > \usepackage < multirow >% улучшенное форматирование таблиц \usepackage < ulem >% подчеркивания
\linespread < 1.3 >% полуторный интервал \renewcommand < \rmdefault > < ftm >% Times New Roman \frenchspacing
Установка \linespread (увеличить межстрочный интервал в 1.3 раза) примерно соответствует тому, что в мире Word называют «полуторный интервал». Пакет cmap включает в полученный PDF (я пользуюсь pdfLaTeX) таблицу символов, так что кириллический текст в PDF становится возможно копировать и искать без искажения кодировок. Что касается исходных файлов, то их я храню в кодировке UTF-8, для ваших привычных настроек измените значение параметра при inputenc . Предназначение остальных пакетов прокомментирую чуть позже, когда буду обсуждать непосредственно написание диплома, а не преамбулу с оформлением.
Нумерация страницНумерация страниц должна быть проставлена в верхнем правом углу. В моем случае она начинается с №5, так как первые 4 страницы занимают титульная, лист задания, календарный план и прочая бюрократия. Формы для них были присланы в doc/docx, и их гораздо проще распечатать как есть, нежели тратить время на имитирование этого оформления в LaTeX ;)
Подключим пакет fancyhdr , предназначенный для оформления верхних и нижних колонтитулов страницы, и поотключаем в нем всякие умолчания. Страница становится абсолютно чистой, за исключением номера ( \thepage ) в правом углу верхнего колонтитула.
Стоит отметить, что первая страница главы (chapter) по умолчанию использует стиль страницы plain. Его приходится тоже переопределить в терминах fancyhdr , чтобы номера проставлялись и на первых страницах глав (см. команду \fancypagestyle ).
Подписи под изображениями и таблицамиЗдесь с помощью команды \DeclareCaptionLabelFormat настраивается новый пользовательский формат оформления подписи, который потом назначается для всех рисунков и таблиц документа. Его первый параметр #1 — это стандартный текст метки (я предпочел не настраивать его отдельной строкой, а написать явно, не используя #1), второй параметр #2 — номер рисунка/таблицы. \DeclareCaptionLabelSeparator настраивает разделитель между меткой подписи (caption label) и непосредственно её текстом, который задаете вы. В нашем случае это среднее тире.
Отдельно стоит прокомментировать последнюю строку. Так как я разделяю иногда иллюстрации на подчасти, что позволяет делать пакет subfigure , эти подчасти нужно нумеровать. Принято нумеровать их маленькими буквами по порядку — однако в нашем случае это должны быть буквы кириллицы, а не латиницы! Кириллическое представление счетчиков (по аналогии с известными представлениями arabic , roman , latin и др.) уже реализовано в пакете babel . Называется оно соответственно \asbuk для маленьких кириллических букв, и \Asbuk для больших.
Приведу пример типичного оформления рисунка:
Стоит отметить использование команд \multirow и \multicolumn для создания красивых таблиц. Они соответствуют параметрам HTML <table>: rowspan и colspan , соответственно. Правда, первый требует подключения пакета multirow .
Результат оформления показан ниже. Для рисунка:
ЗаголовкиЗаголовки по стандарту ДСТУ 3008-95 — это просто песня. Или, скорее, скорбная дума. Все требования по выравниваю заголовков были оформлены некой творческой душой в терминах Word: пропуск тут одна строка, тут две строки, а там полуторный интервал, а здесь двойной… В итоге после некоторого времени, проведенного в попытках придумать красивое решение, мне пришлось подобрать все константы отступов и интервалов вручную и захардкодить их в пикселях пунктах. Считаю, что это самый отвратительный стиль программирования, к которому я прибегнул за всю свою «карьеру». Хотя в данном случае LaTeX никакого отношения к программированию и не имеет :)
Для форматирования заголовков используем пакет titlesec . По стандарту главы (они же разделы) пишутся по центру, предваряются строкой «Глава N», а подразделы и пункты нумеруются в пределах главы, и выравниваются по абзацному отступу. Все набирается полужирным начертанием, при этом заголовки глав — еще и в верхнем регистре.
- первый — уровень настраиваемого заголовка (например, chapter или section);
- второй необязательный — форма заголовка. Описывает глобальный стиль его размещения — будет ли он «висеть» по центру, печататься обычной жирной строкой перед текстом, входить в текст, располагаться на полях, или еще как-то иначе. Полный список форм приведен в мануале по пакету, я здесь пользуюсь только формой display для оформления chapter;
- третий параметр — команды, вызывающиеся перед печатью всего заголовка;
- четвертый параметр — оформление метки;
- пятый параметр — расстояние между меткой и текстом заголовка (горизонтальное или вертикальное в зависимости от формы);
- шестой параметр — команды, вызывающиеся перед печатью текста заголовка;
- седьмой необязательный — команды, вызывающиеся после печати текста заголовка.
Обратите внимание на \parindent в настройке отступов для подразделов, заставляющий их выравниваться по абзацному отступу.
И вот как все это теперь выглядит при печати обыкновенными \chapter и \section :
Списки- нумерованные списки на первом уровне помечаются как «а)», «б)», «в)»… На втором — как «1)», «2)», «3)». Да-да, я тоже не вижу тут ни капли логики.
- ненумерованные списки помечаются дефисами.
Оглавление — вторая по болезненности стадия процесса настройки преамбулы. Его приходится настраивать по образцу, стандарт не слишком-то многословен на этот счет. Последствием настройки по образцу является еще одна куча «магических констант» среди интервалов.
- слово «Стр.» над колонкой с номерами страниц;
- выделение глав жирным шрифтом и верхнем регистром (и предварительным «Глава N»);
- включение в оглавление специальных разделов («Вступление», «Список сокращений», «Выводы», «Список литературы». ) на уровне обычных глав, но без слова «Глава» и нумерации;
- включение в оглавление подразделов и пунктов, но не подпунктов и ниже;
- и разнообразные красивые выравнивания.
Эти команды настраивают все необходимые мелочи из вышеприведенного списка, кроме одной. Со специальными разделами придется обходиться особым образом.
Специальные разделы (аннотация, вступление, список сокращений, выводы, список литературы)Перечисленные разделы оформляются особенно. Во-первых, каждый из них начинается с новой страницы. Это не проблема — команду \newpage знает каждый. Во-вторых, их заголовок оформляется по центру страницы полужирным шрифтом верхнего регистра… и отделяется от текста двумя строками. И наконец, в довершение этой ахинеи, специальные разделы находятся в оглавлении на уровне глав, но не нумеруются, и главами не являются. Чувствуете, как кому-то было нечего делать?
Команда \chapter* по очевидным причинам не подходит: начатые ею главы не включаются в оглавление. Кроме того, нужно как-то оформить двойной перенос строки перед текстом — ну не писать же \newline вручную каждый раз?
Мы не ищем легких путей. Я решил создать свой собственный вид секции. Как оказалось, это не так-то и сложно. Чтобы определить секцию (я назвал её likechapter ), для начала стоит определить соответствующую оформляющую команду. Оформить центрирование и капитализацию названия секции — раз плюнуть. Что я и сделал — команда \likechapterheading печатает как надо переданное ей название секции.
Однако секцию нужно еще и включить в оглавление и выровнять по уровню главы. И вот здесь уже нужно чуть извернуться.
- Тип перечня, в который добавить строку. В нашем случае это toc — оглавление (table of contents).
- Уровень, на котором разместить строку.
- Добавляемый текст строки.
Когда LaTeX печатает определенный уровень в оглавлении, он вызывает внутреннюю команду \l@XXX , где XXX — название уровня (chapter, section и т.д.). У этой команды два параметра — текст заголовка и номер страницы. Цель команды — напечатать непосредственно строку оглавления с пунктирной линией, отступами и всем полагающимся. Если мы желаем определить собственный вид уровня, нам достаточно определить такую команду для своего названия уровня. Тогда LaTeX в процессе обработки команды \addcontentsline посмотрит на её второй параметр, найдет среди своих определений соответствующую \l@XXX , где XXX — подставленный этот самый второй параметр, и тем самым закончит печать строки в оглавлении.
Осталось определить команду \l@likechapter (попутно настроив для нее период между точками в пунктирной линии, как в tocloft ), и закончить определение заголовка \likechapter :
Теперь можно и посмотреть на результат трудов. Вот так выглядит начало оглавления:
Специальный раздел показывать смысла нет, полагаю. Это просто жирный капитализированный текст по центру страницы, напечатанный с помощью \likechapter .
Список литературыПри верстке ссылок на источники я решил не пользоваться BibTeX, о чем потом тысячу раз пожалел. Необходимость аккуратно вручную расставлять все эти слеши, точки, запятые и тире при описании очередного номера журнала просто убивает. Но, к сожалению, BibTeX я до того не пользовался, и разбираться с настройкой его оформления желание к концу преамбулы уже иссякло. А жаль.
Кстати, уверен, что уже настроенные BibTeX-файлы в уже упоминавшемся проекте disser почти полностью решают эту задачу.
Но пока здесь мы рассматриваем конкретно мою преамбулу. Для верстки списка литературы я пользовался старым добрым окружением thebibliography и командами \bibitem в чистом виде. Для их небольшой настройки необходимо было проделать следующее:
Теперь заголовок «Список литературы» оформляется как likechapter, и соответствующим образом помещается в оглавление. Пакет natbib красиво сжимает числа при ссылке в нечто вроде "[2, 6-9]".
Счетчик страниц, рисунков, таблиц, источниковСтандарт требует, чтобы аннотация к работе начиналась со строки «Дипломная работа: 107 с., 14 рис., 19 табл., 2 приложения, 28 источников». Естественно, LaTeX не был бы лучшей системой верстки современности, если бы в нем не было средств автоматического подсчета всех этих величин и вставки нужного числа в текст командой.
Начнем со страниц. Здесь дела обстоят проще всего: подключаем пакет lastpage , а в тексте просто ссылаемся на новую определяемую им метку LastPage с помощью \pageref* :
С рисунками и таблицами мог бы помочь пакет totcount, который и был написан для таких целей — подсчитывать количество разнообразных объектов в документе. К сожалению, по состоянию на настоящий момент у него есть серьезный недостаток: счетчики обычно сбрасываются в конце каждой главы при несквозной нумерации, так что на выходе в случае документа типа report, а не article мы получаем не общее количество рисунков, а лишь количество рисунков в последней главе. Автор уведомлен о баге, а пока он работает, необходимо было найти workaround.
Рецепт был найден на просторах StackOverflow. Мы определим для каждого типа объектов собственный счетчик, а потом значение этого счетчика запишем в aux-файл (в конце компиляции, командой \AtEndDocument ). При следующей компиляции оно возьмется из файла, и определенная нами команда подставит в текст необходимое число. Таким образом, после двух запусков pdfLaTeX мы получим текст с корректным значением счетчика.
У этого решения есть фатальный недостаток: увеличивать значение счетчика приходится вручную на каждом рисунке или таблице. Можно чуть упростить жизнь, добавляя к счетчику количество рисунков/таблиц лишь в конце каждой главы (из соответствующего системного счетчика), но все равно копипаст по коду будет присутствовать. Этот процесс, тем не менее, можно автоматизировать.
Автоматизацией занимается пакет etoolbox . В нем (помимо всего прочего) есть замечательная команда \pretocmd , которая позволяет приписать к определению любой команды спереди какой-то дополнительный код. В данном случае мы желаем, чтобы перед любым вызовом \chapter изменялось значение счетчика.
Отмечу, что вручную команды изменения счетчиков все же приходится вызвать еще дважды. Один раз в самом конце документа (см. выше \AtEndDocument ). И один раз перед началом приложений, которые классифицируются как главы, но не вызываются с помощью \chapter (см. ниже).
Наконец, с источниками можно поступить точно так же: определить счетчик, автоматически увеличивать его и сбросить в aux-файл в конце компиляции. Только на этот раз хачить придется команду \bibitem :
ПриложенияС приложениями пришлось повозиться. В первую очередь из-за оглавления: никак не получалось настроить tocloft так, чтобы он печатал для главы слово «Глава», а для приложения — слово «Приложение», несмотря на то, что оно заявлено как \chapter . При этом печатать необходимое слово в самом заголовке получается без проблем, благодаря команде \chaptertitlename , определенной в пакете titlesec .
Не мудрствуя лукаво, я соорудил костыль. Я решил оформлять приложения как… параграфы. Все равно настоящие параграфы в тексте я нигде не использовал. Дело было за малым — настроить отображение \paragraph в заголовке идентично \chapter , и добавить соответствующую строку в оглавление на уровне likechapter.
Обратите внимание на невыносимую легкость бытия: приложения по сути представляют собой paragraph-ы, оформляются в оглавление как likechapter-ы, но при этом для их подсчета я использую счетчик chapter, потому что по сути-то приложения являются главами :) В качестве представления счетчика взят \Asbuk , так как приложения принято нумеровать заглавными кириллическими буквами.
Теперь поподробнее о том, как оформить каждое из двух обязательных приложений, указанных в дипломной работе бакалавра.
Приложение А: Иллюстративный материал докладаПервым обязательным приложением являются слайды презентации. Презентацию я создавал в Microsoft Power Point, здесь против отличного продукта у меня никаких претензий не возникает пока. Возможно, наступит скоро в жизни переломный момент, когда я и презентации буду делать в LaTeX, но пока что я еще не на той стадии. Основным доводом является то, что большое количество формул в презентации я набираю на LaTeX-подобном языке разметки, встроенном в Microsoft Office версий 2007 и выше ;)
Итак, презентация готова, сохранена в pptx-файл рядом с исходниками диплома. Как бы теперь ее автоматически вставлять в PDF диплома прямо при компиляции? Способ был найден, и очень простой. Сконвертируем презентацию в PDF и вставим этот PDF внутрь генерируемого с помощью замечательного пакета pdfpages .
Я решил отображать по два слайда на страницу, окруженные рамками. В процессе работы пришлось учесть два момента. Во-первых, страницы с приложением тоже нужно нумеровать — так что надо не забыть давать команды пакету fancyhdr , чтобы он отработал и на включаемых страницах. Во-вторых, на первой странице приложения находятся не только два первых слайда презентации, но и заголовок «Приложение А». Как первую, так и вторую трудность решает параметр pagecommand , присутствующий в списке опций нашей основной команды \includepdf . Готовый исходный код:
Приложение Б: Код программного продуктаВставляемый исходный код хочется подсветить и напечатать мелким моноширинным шрифтом, чтобы он не занимал добрую половину диплома и не тратил на себя зря бумагу. В приложениях это дозволяется.
С подсветкой исходного кода прекрасно справляется пакет listings . Ему только надо немного помочь: указать каким шрифтом печатать код (опция basicstyle ), попросить переносить слова в строках (опция breaklines ), и подкорректировать набор ключевых слов языка программирования (опция morekeywords ) — в нем реализовано распознавание C# 2.0, а я писал на C# 4.0. Со всем остальным пакет справится сам, даже подгрузит текст исходника из лежащего рядом файла.
Организация рабочего пространстваНа этом перевод стандарта ДСТУ 3008-95 на LaTeX закончился. Последние несколько строк в моей преамбуле касаются того, как удобнее всего оказалось организовать работу с многочисленными разделами и подразделами в дипломной работе.
Весь документ, конечно же, разобьем на множество файликов — по одному tex-файлу на подраздел (section). Каждую главу будем хранить в отдельной подпапке, с названием вроде chapter_ProgramSynthesis . В этой папке будет лежать файл chapter_ProgramSynthesis.tex , содержащий в себе сборку подразделов главы, собственно файлы sec_XXX.tex с конкретными подразделами и все нужные дополнительные материалы (например, картинки).
Чтобы включить в тело основного документа файл главы и разрешить ему, в свою очередь, включать в себя подфайлы и искать путь к материалам в своей подпапке, воспользуемся пакетом import . В нем есть прекрасная команда \subimport , которая принимает два параметра — папку, которая временно становится путем поиска файлов, и непосредственно включаемый файл. Для включения глав в диплом определим вспомогательную команду, и можем теперь легко ссылаться на главы по имени.
В основном файле diploma.tex :
В файле chapter_ProgramSynthesis/chapter_ProgramSynthesis.tex :
Файлы sec_Basics.tex и прочие лежат в той же подпапке chapter_ProgramSynthesis . Ссылка на картинки из той же подпапки происходит непосредственно — см. пример определения иллюстрации в начале статьи.
Команду \inputintro я определил из чистого перфекционизма: раз я подраздел «Вступление» всегда называю sec_Intro.tex и начинаю после него новую страницу, зачем писать дублирующийся код? :-)
ЗаключениеНа этом титаническое описание 150-строчной преамбулы можно считать законченным. Еще раз: не предполагаю, что всю эту работу стоит использовать в «чистом» виде как эталон для соблюдения стандарта — гораздо проще воспользоваться готовыми решениями. Зато надеюсь, что по мере чтения данной статьи многие энтузиасты LaTeX почерпнут для себя много новых интересных средств и возможностей, обогатят копилку инструментов полезными пакетами, и, возможно, возьмут на заметку прием-другой.
В конце концов, мы и любим LaTeX именно за эту безграничную мощь, не так ли? ;) Удачной вам верстки!