Диплом бакалавра в LaTeX, или ДСТУ 3008-95 в 150 строк

в 7:53, , рубрики: latex, tex, диплом, дипломная работа, метки: , , ,

image
Всем привет. Недавно меня тоже настигла переломная веха студенческой жизни — бакалаврская дипломная работа. Среди многих формальных деталей этого замечательного явления особо заметным стоит нормоконтроль. Нет, я понимаю и всячески поддерживаю, что стандарты необходимы, в том числе стандарты на оформление академического текста. Просто наши стандарты, в отличие от западных, достаточно идиотичны. Они не экономят ни чернила, ни бумагу, они не упрощают поиск литературы по номенклатуре, а усложняют чтение названия. Не говоря уже о том, что текст стандарта спроектирован и описан людьми, работающими в редакторе Microsoft Word. Опять-таки, я не имею ничего против Word, это мощнейшая система. Но технический текст в нем набирать неудобно, и по гибкости он во много раз проигрывает бессмертному творению Дональда Кнута — LaTeX.

Итак, мое написание диплома началось с того, что я потратил 4 часа на настройку преамбулы под нормы украинского стандарта оформления ДСТУ 3008-95. Насколько мне известно, он почти полностью соответствует русскому ГОСТу. Я знал, что существуют готовые решения (например, disser), но после пары проб предпочел настроить каждую деталь самостоятельно. Для тренировки. Тренировка удалась — я узнал бездну новых вещей о LaTeX, этого монстра невозможно выучить полностью :-)

Под катом я полностью опишу процесс настройки каждой конкретной детали и использование их при написании, а также разные мелочи, упрощающие написание диплома еще больше. Сразу предупреждаю: где-то мои решения могут показаться костылями. Где-то они не слишком универсальны. Я это знаю, понимаю, принимаю и приветствую критику и предложения в комментариях ;-)

Заготовка

Начнем с заготовки. Я предполагаю, что у вас устанавлен дистрибутив (MiKTeX на Windows или любой аналогичный на Linux/Mac) и настроены кириллические шрифты PsCyr по инструкции. Не забудьте включить установку дополнительных пакетов «на лету» — вам их понадобится много :)

Стандарт предполагает написание всего текста 14 шрифтом Times New Roman с полуторным интервалом. Последнее — терминология Microsoft Word :) Чтобы составить её аналог в LaTeX, подключим пакет extsizes, который добавляет в параметры класса документа 14pt, и настроим все остальное, как написано ниже:

documentclass[a4paper,14pt,russian]{extreport}
 
usepackage{extsizes}
usepackage{cmap} % для кодировки шрифтов в pdf
usepackage[T2A]{fontenc}
usepackage[utf8]{inputenc}
usepackage[russian]{babel}
usepackage{pscyr}
 
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
 
begin{document}
 
end{document}

Установка linespread{1.3} (увеличить межстрочный интервал в 1.3 раза) примерно соответствует тому, что в мире Word называют «полуторный интервал». Пакет cmap включает в полученный PDF (я пользуюсь pdfLaTeX) таблицу символов, так что кириллический текст в PDF становится возможно копировать и искать без искажения кодировок. Что касается исходных файлов, то их я храню в кодировке UTF-8, для ваших привычных настроек измените значение параметра при inputenc. Предназначение остальных пакетов прокомментирую чуть позже, когда буду обсуждать непосредственно написание диплома, а не преамбулу с оформлением.

Нумерация страниц

Нумерация страниц должна быть проставлена в верхнем правом углу. В моем случае она начинается с №5, так как первые 4 страницы занимают титульная, лист задания, календарный план и прочая бюрократия. Формы для них были присланы в doc/docx, и их гораздо проще распечатать как есть, нежели тратить время на имитирование этого оформления в LaTeX ;)

Подключим пакет fancyhdr, предназначенный для оформления верхних и нижних колонтитулов страницы, и поотключаем в нем всякие умолчания. Страница становится абсолютно чистой, за исключением номера (thepage) в правом углу верхнего колонтитула.

usepackage{fancyhdr}
pagestyle{fancy}
fancyhf{}
fancyhead[R]{thepage}
fancyheadoffset{0mm}
fancyfootoffset{0mm}
setlength{headheight}{17pt}
renewcommand{headrulewidth}{0pt}
renewcommand{footrulewidth}{0pt}
fancypagestyle{plain}{ 
    
fancyhf{}
    rhead{thepage}}
setcounter{page}{5} % начать нумерацию страниц с №5

Стоит отметить, что первая страница главы (chapter) по умолчанию использует стиль страницы plain. Его приходится тоже переопределить в терминах fancyhdr, чтобы номера проставлялись и на первых страницах глав (см. команду fancypagestyle).

Подписи под изображениями и таблицами

Настроим формат подписей, для чего прежде всего подключим пакет caption. Поскольку я люблю детальные иллюстрации с несколькими взаимосвязанными подчастями, подключим также и пакет subcaption. По стандарту название рисунка располагается под рисунком, а название таблицы — над таблицы. Следить за этими расположениями вам придется самостоятельно (см. ниже), но пакету можно подсказать об этом законе, чтобы он оптимизировал выделение пустого места соответствующим образом.

usepackage[tableposition=top]{caption}
usepackage{subcaption}
DeclareCaptionLabelFormat{gostfigure}{Рисунок #2}
DeclareCaptionLabelFormat{gosttable}{Таблица #2}
DeclareCaptionLabelSeparator{gost}{~---~}
captionsetup{labelsep=gost}
captionsetup[figure]{labelformat=gostfigure}
captionsetup[table]{labelformat=gosttable}
renewcommand{thesubfigure}{asbuk{subfigure}}

Здесь с помощью команды DeclareCaptionLabelFormat настраивается новый пользовательский формат оформления подписи, который потом назначается для всех рисунков и таблиц документа. Его первый параметр #1 — это стандартный текст метки (я предпочел не настраивать его отдельной строкой, а написать явно, не используя #1), второй параметр #2 — номер рисунка/таблицы.
DeclareCaptionLabelSeparator настраивает разделитель между меткой подписи (caption label) и непосредственно её текстом, который задаете вы. В нашем случае это среднее тире.

Отдельно стоит прокомментировать последнюю строку. Так как я разделяю иногда иллюстрации на подчасти, что позволяет делать пакет subfigure, эти подчасти нужно нумеровать. Принято нумеровать их маленькими буквами по порядку — однако в нашем случае это должны быть буквы кириллицы, а не латиницы! Кириллическое представление счетчиков (по аналогии с известными представлениями arabic, roman, latin и др.) уже реализовано в пакете babel. Называется оно соответственно asbuk для маленьких кириллических букв, и Asbuk для больших.

Приведу пример типичного оформления рисунка:

begin{figure}[ht]
centering
    begin{subfigure}[b]{0.3textwidth}    
    centering
        $$begin{array}{l}
        F to x ;|; y ;|; (S) \
        T to F ;|; T ast F \
        S to T ;|; S + T \    
        end{array}$$
        caption{}
    end{subfigure} %    
    begin{subfigure}[b]{0.6textwidth}
    centering
        includegraphics[scale=0.7]{parseTree.png}
        caption{}
    end{subfigure}
 
    caption{(a) Продукции грамматики $G$ для порождения арифметических выражений; 
             (б) Дерево разбора строки $x+yast y$ в грамматике $G$.}
    label{fig_parsetree}
end{figure}

И таблицы:

begin{table}[ht]
caption{Расчет весомости параметров ПП}
label{tab_weight}
centering
    begin{tabular}{|c|c|c|c|c|c|c|c|c|}
    hline multirow{2}{*}{Параметр $x_i$} & multicolumn{4}{c|}{Параметр $x_j$} & 
        multicolumn{2}{c|}{Первый шаг} & multicolumn{2}{c|}{Второй шаг} \
    cline{2-9} & $X_1$ & $X_2$ & $X_3$ & $X_4$ & $w_i$ & 
        ${K_text{в}}_i$ & $w_i$ & ${K_text{в}}_i$ \
    hline $X_1$ & 1 & 1 & 1.5 & 1.5 & 5 & 0.31 & 19 & 0.32 \
    hline $X_2$ & 1 & 1 & 1.5 & 1.5 & 5 & 0.31 & 19 & 0.32 \
    hline $X_3$ & 0.5 & 0.5 & 1 & 0.5 & 2.5 & 0.16 & 9.25 & 0.16 \
    hline $X_4$ & 0.5 & 0.5 & 1.5 & 1 & 3.5 & 0.22 & 12.25 & 0.20 \
    hline multicolumn{5}{|c|}{Итого:} & 16 & 1 & 59.5 & 1 \
    hline
    end{tabular}
end{table}

Стоит отметить использование команд multirow и multicolumn для создания красивых таблиц. Они соответствуют параметрам HTML <table>: rowspan и colspan, соответственно. Правда, первый требует подключения пакета multirow.

Результат оформления показан ниже.
Для рисунка:
Диплом бакалавра в LaTeX, или ДСТУ 3008 95 в 150 строк

Для таблицы:
Диплом бакалавра в LaTeX, или ДСТУ 3008 95 в 150 строк

Заголовки

Заголовки по стандарту ДСТУ 3008-95 — это просто песня. Или, скорее, скорбная дума. Все требования по выравниваю заголовков были оформлены некой творческой душой в терминах Word: пропуск тут одна строка, тут две строки, а там полуторный интервал, а здесь двойной… В итоге после некоторого времени, проведенного в попытках придумать красивое решение, мне пришлось подобрать все константы отступов и интервалов вручную и захардкодить их в пикселях пунктах. Считаю, что это самый отвратительный стиль программирования, к которому я прибегнул за всю свою «карьеру». Хотя в данном случае LaTeX никакого отношения к программированию и не имеет :)

Для форматирования заголовков используем пакет titlesec. По стандарту главы (они же разделы) пишутся по центру, предваряются строкой «Глава N», а подразделы и пункты нумеруются в пределах главы, и выравниваются по абзацному отступу. Все набирается полужирным начертанием, при этом заголовки глав — еще и в верхнем регистре.

Оформление заголовка настраивается командой titleformat. У нее есть следующие параметры:

  • первый — уровень настраиваемого заголовка (например, chapter или section);
  • второй необязательный — форма заголовка. Описывает глобальный стиль его размещения — будет ли он «висеть» по центру, печататься обычной жирной строкой перед текстом, входить в текст, располагаться на полях, или еще как-то иначе. Полный список форм приведен в мануале по пакету, я здесь пользуюсь только формой display для оформления chapter;
  • третий параметр — команды, вызывающиеся перед печатью всего заголовка;
  • четвертый параметр — оформление метки;
  • пятый параметр — расстояние между меткой и текстом заголовка (горизонтальное или вертикальное в зависимости от формы);
  • шестой параметр — команды, вызывающиеся перед печатью текста заголовка;
  • седьмой необязательный — команды, вызывающиеся после печати текста заголовка.

Эти команды позволяют достичь всего необходимого оформления, за исключением обязательной капитализации текста заголовка главы. Команда MakeUppercase работает исключительно с одним параметром, и её нельзя применять наподобие bffamily, чтобы переключить формат печати «отныне и навеки до конца группы». Таким образом, я смог применить её для капитализации метки заголовка (слова «Глава» или «Приложение»), но текст заголовка пришлось печатать капсом самостоятельно. Ну ничего, нажать Запретную Кнопку несколько раз оказалось не так уж и страшно :)

usepackage{titlesec}
 
titleformat{chapter}[display]
    {filcenter}
    {MakeUppercase{chaptertitlename} thechapter}
    {8pt}
    {bfseries}{}
 
titleformat{section}
    {normalsizebfseries}
    {thesection}
    {1em}{}
 
titleformat{subsection}
    {normalsizebfseries}
    {thesubsection}
    {1em}{}
 
% Настройка вертикальных и горизонтальных отступов
titlespacing*{chapter}{0pt}{-30pt}{8pt}
titlespacing*{section}{parindent}{*4}{*4}
titlespacing*{subsection}{parindent}{*4}{*4}

Обратите внимание на parindent в настройке отступов для подразделов, заставляющий их выравниваться по абзацному отступу.

И вот как все это теперь выглядит при печати обыкновенными chapter и section:
Диплом бакалавра в LaTeX, или ДСТУ 3008 95 в 150 строк

Поля

Настроить поля страницы — самая простая из сегодняшних задач:

usepackage{geometry}
geometry{left=3cm}
geometry{right=1.5cm}
geometry{top=2.4cm}
geometry{bottom=2.4cm}

Списки

Требования на списки в стандарте следующие:

  • нумерованные списки на первом уровне помечаются как «а)», «б)», «в)»… На втором — как «1)», «2)», «3)». Да-да, я тоже не вижу тут ни капли логики.
  • ненумерованные списки помечаются дефисами.

К сожалению, LaTeX обожает окружать окружения itemize и enumerate огромным количеством пространства, порождая для них специальный межабзацный отступ. Чтобы побороть эту порочную привычку, можно воспользоваться пакетом enumitem и задать ему опцию nolistsep, отключающую все дополнительные отступы. Правда, enumitem не знает ничего про новенькое представление счетчиков asbuk, о котором я рассказывал выше, так что необходимо указать на него командой AddEnumerateCounter. Её третий параметр — пример самого широкого представления (пакет будет ориентироваться на эту ширину при печати). Мне почему-то (безосновательно) кажется, что самая широкая буква кириллического алфавита в Times New Roman — это именно «м». В любом случае, человек, который создает нумерованный список длиной от «а» до «м» или ниже, заслуживает пристального внимания здравоохранительных органов, как по мне :)

usepackage{enumitem}
makeatletter
    AddEnumerateCounter{asbuk}{@asbuk}{м)}
makeatother
setlist{nolistsep}
renewcommand{labelitemi}{-}
renewcommand{labelenumi}{asbuk{enumi})}
renewcommand{labelenumii}{arabic{enumii})}

Оглавление

Оглавление — вторая по болезненности стадия процесса настройки преамбулы. Его приходится настраивать по образцу, стандарт не слишком-то многословен на этот счет. Последствием настройки по образцу является еще одна куча «магических констант» среди интервалов.

Список разнообразных мелочей, которые надо учесть, включает:

  • слово «Стр.» над колонкой с номерами страниц;
  • выделение глав жирным шрифтом и верхнем регистром (и предварительным «Глава N»);
  • включение в оглавление специальных разделов («Вступление», «Список сокращений», «Выводы», «Список литературы»...) на уровне обычных глав, но без слова «Глава» и нумерации;
  • включение в оглавление подразделов и пунктов, но не подпунктов и ниже;
  • и разнообразные красивые выравнивания.

К счастью, существует пакет tocloft. Копировать его документацию в текст данной заметки я не собираюсь, он включает бесчисленное множество команд, которые настраивают буквально каждый пиксель в оглавлении. Все эти команды — подстановки в стиле «а вот это напечатай между текстом названия подраздела и началом пунктирной линии». Я использую в преамбуле 9 таких команд, которые в общем и целом настраивают внешний вид оглавления:

usepackage{tocloft}
renewcommand{cfttoctitlefont}{hspace{0.38textwidth} bfseriesMakeUppercase}
renewcommand{cftbeforetoctitleskip}{-1em}
renewcommand{cftaftertoctitle}{mbox{}hfill \ mbox{}hfill{footnotesize Стр.}vspace{-2.5em}}
renewcommand{cftchapfont}{normalsizebfseries MakeUppercase{chaptername} }
renewcommand{cftsecfont}{hspace{31pt}}
renewcommand{cftsubsecfont}{hspace{11pt}}
renewcommand{cftbeforechapskip}{1em}
renewcommand{cftparskip}{-1mm}
renewcommand{cftdotsep}{1}
setcounter{tocdepth}{2} % задать глубину оглавления — до subsection включительно

Эти команды настраивают все необходимые мелочи из вышеприведенного списка, кроме одной. Со специальными разделами придется обходиться особым образом.

Специальные разделы (аннотация, вступление, список сокращений, выводы, список литературы)

Перечисленные разделы оформляются особенно. Во-первых, каждый из них начинается с новой страницы. Это не проблема — команду newpage знает каждый. Во-вторых, их заголовок оформляется по центру страницы полужирным шрифтом верхнего регистра… и отделяется от текста двумя строками. И наконец, в довершение этой ахинеи, специальные разделы находятся в оглавлении на уровне глав, но не нумеруются, и главами не являются. Чувствуете, как кому-то было нечего делать?

Команда chapter* по очевидным причинам не подходит: начатые ею главы не включаются в оглавление. Кроме того, нужно как-то оформить двойной перенос строки перед текстом — ну не писать же newline вручную каждый раз?

Мы не ищем легких путей. Я решил создать свой собственный вид секции. Как оказалось, это не так-то и сложно.
Чтобы определить секцию (я назвал его likechapter), для начала стоит определить соответствующую оформляющую команду. Оформить центрирование и капитализацию названия секции — раз плюнуть. Что я и сделал — команда likechapterheading печатает как надо переданное ей название секции.

newcommand{empline}{mbox{}newline}
newcommand{likechapterheading}[1]{ 
    
begin{center}
    textbf{MakeUppercase{#1}}
    end{center}
    empline}

Однако секцию нужно еще и включить в оглавление и выровнять по уровню главы. И вот здесь уже нужно чуть извернуться.

Теоретически добавление новой строки в оглавление делается командой addcontentsline. У нее три параметра:

  1. Тип перечня, в который добавить строку. В нашем случае это toc — оглавление (table of contents).
  2. Уровень, на котором разместить строку.
  3. Добавляемый текст строки.

С первым и третьим все понятно. Но в качестве второго нельзя написать просто «chapter», так как услужливый tocloft, настроенный нами же чуть выше, напечатает перед строкой слово «Глава». Выход один — идти до конца и определять собственный уровень секции.

Когда LaTeX печатает определенный уровень в оглавлении, он вызывает внутреннюю команду l@XXX, где XXX — название уровня (chapter, section и т.д.). У этой команды два параметра — текст заголовка и номер страницы. Цель команды — напечатать непосредственно строку оглавления с пунктирной линией, отступами и всем полагающимся. Если мы желаем определить собственный вид уровня, нам достаточно определить такую команду для своего названия уровня. Тогда LaTeX в процессе обработки команды addcontentsline посмотрит на её второй параметр, найдет среди своих определений соответствующую l@XXX, где XXX — подставленный этот самый второй параметр, и тем самым закончит печать строки в оглавлении.

Осталось определить команду l@likechapter (попутно настроив для нее период между точками в пунктирной линии, как в tocloft), и закончить определение заголовка likechapter:

makeatletter
    renewcommand{@dotsep}{2}
    newcommand{l@likechapter}[2]{{bfseries@dottedtocline{0}{0pt}{0pt}{#1}{#2}}}
makeatother
newcommand{likechapter}[1]{    
    
likechapterheading{#1}    
    addcontentsline{toc}{likechapter}{MakeUppercase{#1}}}


Теперь можно и посмотреть на результат трудов. Вот так выглядит начало оглавления:
Диплом бакалавра в LaTeX, или ДСТУ 3008 95 в 150 строк

Специальный раздел показывать смысла нет, полагаю. Это просто жирный капитализированный текст по центру страницы, напечатанный с помощью likechapter{Вступление}.

Список литературы

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

Кстати, уверен, что уже настроенные BibTeX-файлы в уже упоминавшемся проекте disser почти полностью решают эту задачу.

Но пока здесь мы рассматриваем конкретно мою преамбулу. Для верстки списка литературы я пользовался старым добрым окружением thebibliography и командами bibitem в чистом виде. Для их небольшой настройки необходимо было проделать следующее:

usepackage[square,numbers,sort&compress]{natbib}
renewcommand{bibnumfmt}[1]{#1.hfill} % нумерация источников в самом списке — через точку
renewcommand{bibsection}{likechapter{Список литературы}} % заголовок специального раздела
setlength{bibsep}{0pt}

Теперь заголовок «Список литературы» оформляется как likechapter, и соответствующим образом помещается в оглавление. Пакет natbib красиво сжимает числа при ссылке в нечто вроде "[2, 6-9]".

Счетчик страниц, рисунков, таблиц, источников

Стандарт требует, чтобы аннотация к работе начиналась со строки «Дипломная работа: 107 с., 14 рис., 19 табл., 2 приложения, 28 источников». Естественно, LaTeX не был бы лучшей системой верстки современности, если бы в нем не было средств автоматического подсчета всех этих величин и вставки нужного числа в текст командой.

Начнем со страниц. Здесь дела обстоят проще всего: подключаем пакет lastpage, а в тексте просто ссылаемся на новую определяемую им метку LastPage с помощью pageref*:

usepackage{lastpage}
% ...
Дипломная работа: pageref*{LastPage}~с., ...


С рисунками и таблицами мог бы помочь пакет totcount, который и был написан для таких целей — подсчитывать количество разнообразных объектов в документе. К сожалению, по состоянию на настоящий момент у него есть серьезный недостаток: счетчики обычно сбрасываются в конце каждой главы при несквозной нумерации, так что на выходе в случае документа типа report, а не article мы получаем не общее количество рисунков, а лишь количество рисунков в последней главе. Автор уведомлен о баге, а пока он работает, необходимо было найти workaround.

Рецепт был найден на просторах StackOverflow. Мы определим для каждого типа объектов собственный счетчик, а потом значение этого счетчика запишем в aux-файл (в конце компиляции, командой AtEndDocument). При следующей компиляции оно возьмется из файла, и определенная нами команда подставит в текст необходимое число. Таким образом, после двух запусков pdfLaTeX мы получим текст с корректным значением счетчика.

newcounter{totfigures}
newcounter{tottables}
makeatletter
    AtEndDocument{%
      addtocounter{totfigures}{value{figure}}%
      addtocounter{tottables}{value{table}}%
      immediatewrite@mainaux{%
        stringgdefstringtotfig{numbervalue{totfigures}}%
        stringgdefstringtottab{numbervalue{tottables}}%    
      }%
    }
makeatother
% ...
Дипломная работа: pageref*{LastPage}~с., totfig~рис., tottab~табл...


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

Автоматизацией занимается пакет etoolbox. В нем (помимо всего прочего) есть замечательная команда pretocmd, которая позволяет приписать к определению любой команды спереди какой-то дополнительный код. В данном случае мы желаем, чтобы перед любым вызовом chapter изменялось значение счетчика.

usepackage{etoolbox}
pretocmd{chapter}{addtocounter{totfigures}{value{figure}}}{}{}
pretocmd{chapter}{addtocounter{tottables}{value{table}}}{}{}

Отмечу, что вручную команды изменения счетчиков все же приходится вызвать еще дважды. Один раз в самом конце документа (см. выше AtEndDocument). И один раз перед началом приложений, которые классифицируются как главы, но не вызываются с помощью chapter (см. ниже).

Наконец, с источниками можно поступить точно так же: определить счетчик, автоматически увеличивать его и сбросить в aux-файл в конце компиляции. Только на этот раз хачить придется команду bibitem:

newcounter{totreferences}
pretocmd{bibitem}{addtocounter{totreferences}{1}}{}{}


Теперь не забыть добавить в команду AtEndDocument (см. выше) аналогичную строчку:

stringgdefstringtotref{numbervalue{totreferences}}%

и можно писать в тексте "totref~источников..."

Приложения

С приложениями пришлось повозиться. В первую очередь из-за оглавления: никак не получалось настроить tocloft так, чтобы он печатал для главы слово «Глава», а для приложения — слово «Приложение», несмотря на то, что оно заявлено как chapter. При этом печатать необходимое слово в самом заголовке получается без проблем, благодаря команде chaptertitlename, определенной в пакете titlesec.

Не мудрствуя лукаво, я соорудил костыль. Я решил оформлять приложения как… параграфы. Все равно настоящие параграфы в тексте я нигде не использовал. Дело было за малым — настроить отображение paragraph в заголовке идентично chapter, и добавить соответствующую строку в оглавление на уровне likechapter.

usepackage[title,titletoc]{appendix}
 
titleformat{paragraph}[display]
    {filcenter}
    {MakeUppercase{chaptertitlename} thechapter}
    {8pt}
    {bfseries}{}
titlespacing*{paragraph}{0pt}{-30pt}{8pt}
 
newcommand{append}[1]{ 
    
clearpage
    stepcounter{chapter}    
    paragraph{MakeUppercase{#1}}
    empline
    addcontentsline{toc}{likechapter}{MakeUppercase{chaptertitlename~Asbuk{chapter};#1}}}


Теперь это можно использовать так:

begin{appendices}
renewcommandthechapter{Asbuk{chapter}}
setcounter{chapter}{0}
 
append{Код программного продукта}
...
end{appendices}


Обратите внимание на невыносимую легкость бытия: приложения по сути представляют собой paragraph-ы, оформляются в оглавление как likechapter-ы, но при этом для их подсчета я использую счетчик chapter, потому что по сути-то приложения являются главами :) В качестве представления счетчика взят Asbuk, так как приложения принято нумеровать заглавными кириллическими буквами.

Теперь поподробнее о том, как оформить каждое из двух обязательных приложений, указанных в дипломной работе бакалавра.

Приложение А: Иллюстративный материал доклада

Первым обязательным приложением являются слайды презентации. Презентацию я создавал в Microsoft Power Point, здесь против отличного продукта у меня никаких претензий не возникает пока. Возможно, наступит скоро в жизни переломный момент, когда я и презентации буду делать в LaTeX, но пока что я еще не на той стадии. Основным доводом является то, что большое количество формул в презентации я набираю на LaTeX-подобном языке разметки, встроенном в Microsoft Office версий 2007 и выше ;)

Итак, презентация готова, сохранена в pptx-файл рядом с исходниками диплома. Как бы теперь ее автоматически вставлять в PDF диплома прямо при компиляции? Способ был найден, и очень простой. Сконвертируем презентацию в PDF и вставим этот PDF внутрь генерируемого с помощью замечательного пакета pdfpages.

Я решил отображать по два слайда на страницу, окруженные рамками. В процессе работы пришлось учесть два момента. Во-первых, страницы с приложением тоже нужно нумеровать — так что надо не забыть давать команды пакету fancyhdr, чтобы он отработал и на включаемых страницах. Во-вторых, на первой странице приложения находятся не только два первых слайда презентации, но и заголовок «Приложение А». Как первую, так и вторую трудность решает параметр pagecommand, присутствующий в списке опций нашей основной команды includepdf. Готовый исходный код:

usepackage{pdfpages}
% ...
includepdfset{nup=1x2,frame=true,delta=10mm 10mm,noautoscale=true}
includepdf[pages=1-2,scale=0.55,offset=10mm -20mm,pagecommand={append{Иллюстративный материал доклада}}]{defence.pdf}
includepdf[pages=3-,scale=0.55,offset=10mm 0mm,pagecommand={fancyhead[R]{thepage}}]{defence.pdf}
 


И результат:
Диплом бакалавра в LaTeX, или ДСТУ 3008 95 в 150 строк

Приложение Б: Код программного продукта

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

С подсветкой исходного кода прекрасно справляется пакет listings. Ему только надо немного помочь: указать каким шрифтом печатать код (опция basicstyle), попросить переносить слова в строках (опция breaklines), и подкорректировать набор ключевых слов языка программирования (опция morekeywords) — в нем реализовано распознавание C# 2.0, а я писал на C# 4.0. Со всем остальным пакет справится сам, даже подгрузить текст исходника из лежащего рядом файла.

usepackage{listings}
%...
append{Код программного продукта}
lstset{language=[Sharp]C,
   morekeywords={yield,var,get,set,from,select,partial},
   breaklines=true,
   basicstyle=footnotesizettfamily}
linespread{1} % вернем временно единичный межстрочный интервал
lstinputlisting{MyCoolProjectClass.cs}

Организация рабочего пространства

На этом перевод стандарта ДСТУ 3008-95 на LaTeX закончился. Последние несколько строк в моей преамбуле касаются того, как удобнее всего оказалось организовать работу с многочисленными разделами и подразделами в дипломной работе.

Весь документ, конечно же, разобьем на множество файликов — по одному tex-файлу на подраздел (section). Каждую главу будем хранить в отдельной подпапке, с названием вроде chapter_ProgramSynthesis. В этой папке будет лежать файл chapter_ProgramSynthesis.tex, содержащий в себе сборку подразделов главы, собственно файлы sec_XXX.tex с конкретными подразделами и все нужные дополнительные материалы (например, картинки).

Чтобы включить в тело основного документа файл главы и разрешить ему, в свою очередь, включать в себя подфайлы и искать путь к материалам в своей подпапке, воспользуемся пакетом import. В нем есть прекрасная команда subimport, которая принимает два параметра — папку, которая временно становится путем поиска файлов, и непосредственно включаемый файл. Для включения глав в диплом определим вспомогательную команду, и можем теперь легко ссылаться на главы по имени.

В основном файле diploma.tex:

usepackage{import}
newcommand{includechapter}[1]{subimport{chapter_#1/}{chapter_#1}}
newcommand{inputintro}{input{sec_Intro} newpage}
% ...
includechapter{ProgramSynthesis}

В файле chapter_ProgramSynthesis/chapter_ProgramSynthesis.tex:

chapter{ТЕХНОЛОГИЯ PROGRAM SYNTHESIS}
 
inputintro
input{sec_Basics}
input{sec_Stages}
input{sec_Example}
input{sec_Conclusions}


Файлы sec_Basics.tex и прочие лежат в той же подпапке chapter_ProgramSynthesis. Ссылка на картинки из той же подпапки происходит непосредственно — см. пример определения иллюстрации в начале статьи.

Команду inputintro я определил из чистого перфекционизма: раз я подраздел «Вступление» всегда называю sec_Intro.tex и начинаю после него новую страницу, зачем писать дублирующийся код? :-)

Заключение

На этом титаническое описание 150-строчной преамбулы можно считать законченным. Еще раз: не предполагаю, что всю эту работу стоит использовать в «чистом» виде как эталон для соблюдения стандарта — гораздо проще воспользоваться готовыми решениями. Зато надеюсь, что по мере чтения данной статьи многие энтузиасты LaTeX почерпнут для себя много новых интересных средств и возможностей, обогатят копилку инструментов полезными пакетами, и, возможно, возьмут на заметку прием-другой.

В конце концов, мы и любим LaTeX именно за эту безграничную мощь, не так ли? ;) Удачной вам верстки!

Автор: Skiminok

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js