\section
我的目标是用新的标签参数 重新定义命令:\section[Title in TOC]{Title}{label}
\documentclass{article}
\let\oldsection\section
\renewcommand{\section}[3][]{\oldsection[#1]{#2}\label{sec:#3}}
\begin{document}
\tableofcontents
\section{Myhello}{myhello}
\section[Hello in TOC]{Hello}{hello}
See section \ref{sec:myhello}.
\end{document}
我想这样做https://stackoverflow.com/a/1812477/2062965.\renewcommand
比使用更好的风格吗\def
?
答案1
无法使用高级 LaTeX 命令来实现您的语法,例如\renewcommand
提供您正在寻找的可选参数语法。
对于用户命令,LaTeX2e 仅提供一种非常简单的方法来定义可选参数:您可以将第一个参数设为可选,并为其定义一个默认值。您无法使用此机制来实现标题的情况:如果仅给出了标题,则对标题和目录使用相同的值。如果您查看您的实现,您会发现您将一个空参数传递给可选参数,从而\oldsection
导致稍后出现一个空的目录标题。
如果没有给出目录的可选参数,LaTeX 内核中的标题命令会进行更复杂的工作,使用标题参数两次。如果您想扩展/更改界面,您也需要提供该参数。但正如@egreg 评论的那样,这首先可能是一个值得怀疑的收获。
实现这一目标的一种好方法是使用 的扩展可能性xparse
。我稍微改变了你的输入,使标签参数成为可选的(只是为了展示它的作用xparse
),所以现在实现的语法是:
\section * [TOC] {title} [label]
必要的代码如下所示,它有点落后,因为取决于给出的可选参数和给出或未给出的星号,\oldsection
会调用不同版本,因为该命令不知道约定xparse
。
\documentclass{article}
\usepackage{xparse}
\let\oldsection\section % save the old command
\RenewDocumentCommand\section {s o m o}
{
\IfNoValueTF{#2}
{ % no TOC arg
\IfBooleanTF{#1}
{ \oldsection*{#3} } % star given
{ \oldsection {#3} } % no star given
}
{ % optional TOC there
\IfBooleanTF{#1}
{ \oldsection*[#2]{#3} }
{ \oldsection[#2]{#3} }
}
\IfNoValueF{#4} % optional label given, if not we do nothing
{
\label{sec:#4}
}
}
\begin{document}
\tableofcontents
\section{Myhello}[myhello]
\section[Hello in TOC]{Hello}[hello]
See section \ref{sec:myhello}.
\end{document}
更新
刚刚意识到我允许使用 * 和可选 TOC 参数,并将两者传递给\oldsection
。这实际上不起作用,因为在 2e 中,使用星号时标题不支持可选参数。
因此,这里有一个略有不同的定义:如果同时使用星号和可选参数,那么我们将使用可选参数手动生成目录条目。或者引发错误或直接忽略它。
\RenewDocumentCommand\section {s o m o}
{
\IfBooleanTF{#1}
{ \oldsection*{#3}
\IfNoValueF{#2} % if TOC arg is given create a TOC entry
{ \addcontentsline{toc}{section}{#2} }
}
{ % no star given
\IfNoValueTF{#2}
{ \oldsection {#3} } % no TOC arg
{ \oldsection[#2]{#3} }
}
\IfNoValueF{#4} % optional label given, if not we do nothing
{ \label{sec:#4} }
}
答案2
\section
有三种语法形式:
\section{TXT}
\section[TOC]{TXT}
\section*{TXT}
\label
对于第三种形式来说没有多大意义,因为带星号的\section
s 没有编号。
\documentclass{article}
\makeatletter
\newcommand*{\old@section}{}
\let\old@section\section
\renewcommand*{\section}{%
\@ifstar\old@section\new@section
}
\newcommand*{\new@section}{%
\@ifnextchar[\new@@section\new@@@section % ]
}
\def\new@@section[#1]#2#3{%
\old@section[{#1}]{#2}\label{sec:#3}%
}
\newcommand*{\new@@@section}[2]{%
\old@section{#1}\label{sec:#2}%
}
\makeatother
\begin{document}
\tableofcontents % uses \section*{...}
\section{Myhello}{myhello}
\section[Hello in TOC]{Hello}{hello}
See section \ref{sec:myhello}.
\end{document}
评论:
\@ifstar
有两个参数。它检查参数和可选空格后的下一个标记是否为星号*
。如果是,则使用下一个参数并自动删除星号。否则调用第二个参数。\@ifnextchar[
接受三个参数。如果参数和可选空格后的标记与第一个参数相同,则调用第二个参数,否则调用第三个参数。不会自动删除“下一个字符”。