使用 titleformat 重新定义部分样式

使用 titleformat 重新定义部分样式

我想通过 titlesec 包定义我自己的章节样式,就在章节之后,章节标题显示章节标题和章节标题。

简单代码示例:

\documentclass[]{book}
\usepackage{fancyhdr}
\usepackage{titlesec}

\pagestyle{fancy}


\titleformat{\chapter}[block]{\filleft}
{\chaptername~ \thechapter}{1em}{\bf}[\vspace{-0.6em}\rule{\linewidth}{1pt}]
%
%
\titleformat{\section}[block]{\filleft}
{\thesection}{1em}{}[\vspace{-0.6em}\rule{\linewidth}{1pt}]

\begin{document}

\chapter{ch01}
\section{sec01}
\end{document}

在此处输入图片描述

答案1

解决方案是改变定义以\chapter将当前章节名称保存在宏中并在章节标题的格式中重复使用它:

\documentclass[]{book}
\usepackage{fancyhdr}
\usepackage{titlesec}

\pagestyle{fancy}

\usepackage{xparse}


\titleformat{\chapter}[block]{\filleft}
{\chaptername~ \thechapter}{1em}{\bfseries}[\vspace{-0.6em}\rule{\linewidth}{1pt}]

\makeatletter
\newcommand*\Current@Chapter{}
\let\CHAPTERBAK\chapter
\newcommand\star@processor[1]
  {%
    \IfBooleanTF{#1}
      {\def\ProcessedArgument{*}}
      {\def\ProcessedArgument{}}%
  }
\newcommand\opt@processor[1]
  {%
    \if\relax\detokenize{#1}\relax
      \def\ProcessedArgument{}%
    \else
      \def\ProcessedArgument{[#1]}%
    \fi
  }
\RenewDocumentCommand \chapter { >{\star@processor}s >{\opt@processor}O{} m }
  {%
    \gdef\Current@Chapter{\chaptername~\thechapter\ #3}%
    \CHAPTERBAK#1#2{#3}
  }

\titleformat{\section}[block]{\filleft}
{\Current@Chapter\ \thesection}{1em}{}[\vspace{-0.6em}\rule{\linewidth}{1pt}]
\makeatother

\begin{document}
\tableofcontents

\chapter{ch01}
\section{sec01}
\end{document}

解释:

首先,我们定义一个宏,用于保存当前章节的名称和编号。这是通过 完成的\newcommand*\Current@Chapter{}。我使用\newcommand来确保没有冲突,因为\newcommand检查宏的名称是否已定义。

接下来我们将把的当前定义保存\chapter到名为的宏\CHAPTERBAK\let\CHAPTERBAK\chapter

然后,我定义两个宏来解析新定义的参数\chapter。这两个宏称为\star@processor\opt@processor\star@processor将获取 的星号参数\chapter(因此是可选的*)。并将\opt@processor获取可选括号中的参数。宏定义中将#1\ProcessedArgument中定义的内容\star@processor和中的#2内容。\ProcessedArgument\opt@processor

xparse包为\NewDocumentCommand我们提供了定义新命令的简单接口。我们可以使用参数处理器,方法是使用>{\<processor>}作为参数定义标记的前缀。应该\<processor>采用一个参数,即给定的参数。但是,您可以使用采用两个参数并以作为前缀的宏>{\<processor>{<first argument>}},那么第二个参数将是要定义的宏的给定参数。

参数s是一个可选的星号,如果它存在(因此\chapter*被使用),则测试\IfBooleanTF{#1}将扩展真正的分支,因此\def\ProcessedArgument{*}被使用\star@processor

类型O{}参数是括号中的可选参数,默认为空(您可以在括号中指定其他默认值)。如果它是空的,\ProcessedArgument则将被定义为空\opt@processor,否则参数将被设置为[#1],因此#2\chapter宏中的参数将为空或由括号分隔的参数。

现在我们可以轻松定义\chapter来执行我们想要的操作。首先,它将重新定义\Current@Chapter为 包含\chaptername~\thechapter\ #3,其中#3是 的强制参数\chapter。之后\chapter将原始调用\chapter\CHAPTERBAK

我们现在\titleformat{\section}可以\Current@Chapter在前缀中包含它。

相关内容