问题的mwe如下:
\documentclass[fontset=fandol]{ctexart}
\ctexset{section/format+={\raggedright}}
\parindent=0pt
\begin{document}
\tableofcontents
\section{aaaa}
\section{bbbb}
\section{cccc}
\section*{ddd}
\bigskip
我希望「目录」居中,但是「aaaa、bbbb、cccc、dddd等」保持左对齐
问题是「目录」是用\texttt{section*}进行的样式控制,如果分离\texttt{section}和\texttt{section*}的样式,这样会影响\texttt{section*\{dddd\}}的正常功能
自然可以用\texttt{tocloft}宏包调整,但是这和\texttt{ctexset}的设置“相容性”并不好(为了一个简单的目录居中,我居然需要多调用一个目录定制功能很强的包来实现,有一种杀鸡用牛刀的感觉),我感觉不是这个case下的"最佳实践"。
在这个并不算太复杂的需求中,是否有更好的办法来实现呢?
\end{document}「目录」是用\texttt{section*}进行的样式控制可见article.cls中的设置:
$ Line 503~508
\newcommand\tableofcontents{%
\section*{\contentsname
\@mkboth{%
\MakeUppercase\contentsname}{\MakeUppercase\contentsname}}%
\@starttoc{toc}%
}
基于tocloft的方案 可能 可以是:
\renewcommand\cftaftertoctitle{\hfill}
\renewcommand\cfttoctitlefont{\hfill\huge\bfseries}尝试直接把\section*{...}替换为普通居中文本:
\documentclass[fontset=fandol]{ctexart}
\ctexset{section/format+={\raggedright}}
\renewcommand*{\tableofcontents}{%
{\hfill\textbf{\Large\contentsname}\hfill}
\UseName{@starttoc}{toc}%
}
\parindent=0pt
\begin{document}
\tableofcontents
\section{aaaa}
\section{bbbb}
\section{cccc}
\section*{ddd}
\end{document}但这个时候原本放在\section*内的:
\@mkboth%
{\MakeUppercase\contentsname}%
{\MakeUppercase\contentsname}%会影响header的「目录」二字变为「AAAA」
这不是我预期的行为,如下图:

\documentclass[fontset=fandol]{ctexart}
\ctexset{section/format+={\raggedright}}
\parindent=0pt
\begin{document}
\begingroup\ctexset{section/format+=\centering}
\tableofcontents
\endgroup
\section{aaaa}
\section{bbbb}
\section{cccc}
\section*{ddd}
\end{document}一般情况下 \section 等命令不建议放在组中(因为它们可能为了实现某些效果会重定义 \par),但只在目录里这么做还是问题不大的,目录条目一般都会使用自定义的格式,而不像普通段落那样。
注意到\tableofcontents命令里面调用如下(texdoc classes)

因此最简单的办法是临时renewcommand即可(目录的\section*可以整些不一样的样式)

\documentclass[]{ctexart}
\ctexset{section/format+=\raggedright}
\begin{document}
{
\RenewDocumentCommand{\section}{som}
{\bigskip\centering\bfseries#3\par\bigskip}
\tableofcontents
}
\section{111}
\section{222}
\section{333}
\end{document}multitoc兼容:

\documentclass[]{ctexart}
\usepackage[toc]{multitoc}
\ctexset{section/format+=\raggedright}
\begin{document}
{
\RenewDocumentCommand{\section}{som}
{\bigskip\centering\bfseries#3\par\bigskip}
\tableofcontents
}
\section{111}
\section{222}
\section{333}
\end{document}来自Eureka的答案:
\documentclass[fontset=fandol]{ctexart}
\ctexset{section/format+={\raggedright}}
\renewcommand*{\tableofcontents}{%
{\hfill\textbf{\Large\contentsname}\hfill}
\UseName{@mkboth}%
{\MakeUppercase\contentsname}%
{\MakeUppercase\contentsname}%
\UseName{@starttoc}{toc}%
}
\parindent=0pt
\begin{document}
\tableofcontents
\section{aaaa}
\section{bbbb}
\section{cccc}
\section*{ddd}
\end{document}
不过这里添加的代码量也相比稍长...
BTW,这里的样式为了保持一致,需要用到:
latexdef \section
\section:
\long macro:->\@startsection {section}{1}{\z@ }{-3.5ex \@plus -1ex \@minus -.2ex}{2.3ex \@plus .2ex}{\normalfont \Large \bfseries }