Как добавить префикс и перенос текста строки заголовка в оглавлении (для глав) в классе книги?

Как добавить префикс и перенос текста строки заголовка в оглавлении (для глав) в классе книги?

Я ищу способ включить текст «Глава» в качестве префикса к нумерации глав в ToC для класса книг И сделать так, чтобы название главы переносилось к левому краю в списке ToC. Я встраиваю это в общий ресурс, в настоящее время состоящий из двух частей: одна как файл класса только с пакетами, а другая как файл настроек .tex, который \input в преамбуле. Я пробовал два разных подхода в файле настроек. Первый ниже не фиксирует требуемый патч правильно.

\documentclass{book}

\usepackage{xpatch}
\usepackage{hyperref}

\makeatletter
\xpatchcmd{\@chapter}
    {\addcontentsline{toc}{chapter}{\numberline {#1}}}
    {\addcontentsline{toc}{chapter}{\numberline {Chapter~\thechapter{}.~#1}}}
    {\typeout{Success}}
    {\typeout{Failed!}}
\makeatother

\begin{document}

\tableofcontents

\chapter{This is First}

Some day this will work.

\chapter{This is Second}

Perhaps soon!

\end{document}

При втором подходе слово «Глава» помещается на свое место в оглавление, но текст в более длинном заголовке главы 2 не переносится, как требуется в строке оглавления.

\documentclass{book}

\usepackage{tocloft}

\begin{document}

\newlength{\tocchapwidth}
\settowidth{\tocchapwidth}{\chaptername\ }
\addtolength{\cftchapnumwidth}{\tocchapwidth}
\renewcommand{\cftchappresnum}{\chaptername\ }
\renewcommand{\cftchapaftersnum}{.}
\renewcommand{\cftchapaftersnumb}{~}
\renewcommand{\cftchapdotsep}{\cftdotsep}

\tableofcontents

\chapter{This is First}

Some day this will work.

\chapter{This is Second, a Rather Long and Windy Road Leading to a Door Going to Nowhere Fast}

Perhaps soon!

\end{document}

Это попытка выполнить требования к форматированию для документа диссертации. В настоящее время у нас есть грубый обходной путь — мы вводим название главы, включая префикс, например \chapter{Глава 2.~Это вторая ...} (и подавляем вывод номеров глав в ToC с помощью пакета titlesec).

Кроме того, хотя я не включаю его во второй пример, документ требует пакет hyperref. Из отдельного постинга я делаю вывод, что мне, возможно, придется внести исправления в его команду Hy@... chapter, но даже мои попытки сделать это не увенчались успехом.

Я недостаточно хорошо знаком с LaTeX3, но буду рад включить такие изменения. Наконец, я должен надеяться, что любой предложенный вариант будет достаточно легко работать с Overleaf, где большая часть тех, кто будет использовать пакет, вероятно, будет выполнять свою работу.

решение1

С вашим первым подходом связано несколько проблем.

Прежде всего, даже в первоначальном определении book.clsнет:

\addcontentsline{toc}{chapter}{\numberline {#1}}

в определении \@chapter, но:

\addcontentsline{toc}{chapter}{\protect\numberline{\thechapter}#1}

Таким образом, отсутствует \protectправильный аргумент to \numberline, а первый аргумент \@chapterиспользуется без фигурных скобок.

Вторая проблема в том, что после загрузки hyperrefопределения \@chapterизменений. Поэтому патч должен бытьдозагрузка hyperref.

BTW: Чтобы увидеть оригинальное определение, просто добавьте \show\@chapterперед \xpatchcmd. Это выведет текущее определение до внесения исправлений \@chapterв log-файл.

Третья проблема заключается в том, что замена:

\addcontentsline{toc}{chapter}{\protect\numberline {Chapter~\thechapter{}.~#1}}

Вставил бы не только Chapter~<number>.числовой аргумент, но и заголовок. Так что должно быть как минимум:

\addcontentsline{toc}{chapter}{\numberline {Chapter~\thechapter{}.}#1}

Но для этого определения вам также понадобится изменение \l@chapterдля увеличения пространства, зарезервированного для числа. Может быть, вместо этого вы не хотите резервировать пространство для числа и вместо этого хотите использовать:

\addcontentsline{toc}{chapter}{Chapter~\thechapter{}.~#1}

Итак, с:

\documentclass{book}

\usepackage{xpatch}

\makeatletter
\xpatchcmd{\@chapter}
  {\addcontentsline{toc}{chapter}{\protect\numberline{\thechapter}#1}}
  {\addcontentsline{toc}{chapter}{Chapter~\thechapter{}.~#1}}
  {\typeout{Success}}
  {\typeout{Failed!}}
\makeatother

\usepackage{hyperref}

\begin{document}

\tableofcontents

\chapter{This is First}

Some day this will work.

\chapter{This is Second}

Perhaps soon!

\end{document}

Вы получаете:

Глава 1. Это…

Альтернативой с использованием Chapter <number>.в качестве аргумента \numberlineможет быть, например:

\documentclass{book}

\usepackage{xpatch}

\makeatletter
\xpatchcmd{\@chapter}
  {\addcontentsline{toc}{chapter}{\protect\numberline{\thechapter}#1}}
  {\addcontentsline{toc}{chapter}{\protect\numberline{Chapter~\thechapter{}.}#1}}
  {\typeout{\string\@chapter\space patch success}}
  {\typeout{\string\@chapter\space patch failed!}}
\xpatchcmd{\l@chapter}
  {\setlength\@tempdima{1.5em}}
  {\setlength\@tempdima{6em}}% increase reserved number width
  {\typeout{\string\l@chapter\space patch success}}
  {\typeout{\string\l@chapter\space patch failed!}}
\makeatother

\usepackage{hyperref}

\begin{document}

\tableofcontents

\chapter{This is First}

Some day this will work.

\chapter{This is Second}

Perhaps soon!

\end{document}

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

\chapter{This is Second Chapter with very long Titel Needing more than one
  Line in the Table of Contents}

Так что, ИМХО, этот мой второй подход — то, что вам нужно.


Проблема вашего второго подхода в том, что вы не учитываете точку .и пробел ~после числа при увеличении \cftchapnumwidth. Вот одно из возможных исправлений вашей настройки:

\documentclass{book}

\usepackage{tocloft}

\begin{document}

\newlength{\tocchapwidth}
\renewcommand{\cftchappresnum}{\chaptername\ }
\settowidth{\tocchapwidth}{\cftchappresnum}
\renewcommand{\cftchapaftersnum}{.~}
\newlength{\tocchapafternumwidth}
\settowidth{\tocchapafternumwidth}{\cftchapaftersnum}
\addtolength{\cftchapnumwidth}{\tocchapwidth}
\addtolength{\cftchapnumwidth}{\tocchapafternumwidth}
\renewcommand{\cftchapdotsep}{\cftdotsep}

\tableofcontents

\chapter{This is First}

Some day this will work.

\chapter{This is Second, a Rather Long and Windy Road Leading to a Door Going to Nowhere Fast}

Perhaps soon!

\end{document}

используя токлофт

Но если вы внимательно посмотрите на это предложение, оно все еще не верно, потому что вы измеряете текст в текущем шрифте документа, а не в шрифте, используемом для записей глав. Так что предыдущий код только кажется правильным, но это не так. Для правильного кода вы должны учитывать \cftchapfontпри измерении ширины текста. (И теперь вам не нужно увеличивать ширину также на пробел, если ширина числа без префикса Chapterи постфикса .уже была достаточной). Так что лучший код будет примерно таким:

\documentclass{book}

\usepackage{tocloft}

\newlength{\tocchapwidth}
\newlength{\tocchapafternumwidth}
\renewcommand{\cftchappresnum}{\chaptername\ }
\renewcommand{\cftchapaftersnum}{.}
\renewcommand{\cftchapdotsep}{\cftdotsep}
\AtBeginDocument{% final font setup is done in \begin{document} so we delay all text measuring
  \settowidth{\tocchapwidth}{\cftchapfont\cftchappresnum}%
  \settowidth{\tocchapafternumwidth}{\cftchapfont\cftchapaftersnum}%
  \addtolength{\cftchapnumwidth}{\tocchapwidth}%
  \addtolength{\cftchapnumwidth}{\tocchapafternumwidth}%
}

\begin{document}
\tableofcontents

\chapter{This is First}

Some day this will work.

\chapter{This is Second, a Rather Long and Windy Road Leading to a Door Going to Nowhere Fast}

Perhaps soon!

\end{document}

Проблема с приложением

Примечание: Оба примера не подходят для документов с приложением, поскольку в этом случае Chapterв приложении не будет правильного термина.

Создание рекомендуемого предложения без tocloftподходящего для документов с приложением было бы легко. Вам просто нужно заменить жестко закодированное Chapterна \@chapappи увеличить ширину:

\documentclass{book}

\usepackage{xpatch}

\makeatletter
\xpatchcmd{\@chapter}
  {\addcontentsline{toc}{chapter}{\protect\numberline{\thechapter}#1}}
  {\addcontentsline{toc}{chapter}{\protect\numberline{\@chapapp~\thechapter{}.}#1}}
  {\typeout{\string\@chapter\space patch success}}
  {\typeout{\string\@chapter\space patch failed!}}
\xpatchcmd{\l@chapter}
  {\setlength\@tempdima{1.5em}}
  {\setlength\@tempdima{7em}}% increase reserved number width
  {\typeout{\string\l@chapter\space patch success}}
  {\typeout{\string\l@chapter\space patch failed!}}
\makeatother

\usepackage{hyperref}

\begin{document}

\tableofcontents

\chapter{This is First}

Some day this will work.

\chapter{This is Second}

Perhaps soon!

\appendix
\chapter{This is a Rather Long and Windy Road Leading to a Door Going
  to Nowhere Fast}

\end{document}

Для tocloftрешения этой проблемы можно использовать что-то вроде:

\documentclass{book}

\usepackage{tocloft}

\newlength{\tocchapwidth}
\newlength{\tocappwidth}
\newlength{\tocchapafternumwidth}
\renewcommand{\cftchappresnum}{\chaptername\ }
\renewcommand{\cftchapaftersnum}{.}
\renewcommand{\cftchapdotsep}{\cftdotsep}
\AtBeginDocument{%
  \settowidth{\tocchapwidth}{\cftchapfont\chaptername}%
  \settowidth{\tocappwidth}{\cftchapfont\appendixname}%
  \ifdim\tocappwidth>\tocchapwidth
    \addtolength{\cftchapnumwidth}{\tocappwidth}%
  \else
    \addtolength{\cftchapnumwidth}{\tocchapwidth}%
  \fi
  \settowidth{\tocchapafternumwidth}{\cftchapfont\cftchapaftersnum}%
  \addtolength{\cftchapnumwidth}{\tocchapafternumwidth}%
}
\AddToHook{cmd/appendix/after}{%
  \addtocontents{toc}{%
    \protect\renewcommand{\protect\cftchappresnum}{\protect\appendixname{} }%
  }%
}
\begin{document}
\tableofcontents

\chapter{This is First}

Some day this will work.

\chapter{This is Second, a Rather Long and Windy Road Leading to a Door Going to Nowhere Fast}

Perhaps soon!

\appendix
\chapter{A Rather Long Appendix Heading and Windy Road Leading to a Door Going to Nowhere Fast}


\end{document}

Связанный контент