使用附加参数重新定义部分

使用附加参数重新定义部分

\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对于第三种形式来说没有多大意义,因为带星号的\sections 没有编号。

\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[接受三个参数。如果参数和可选空格后的标记与第一个参数相同,则调用第二个参数,否则调用第三个参数。不会自动删除“下一个字符”。

相关内容