meta-command - 需要扩展帮助

meta-command - 需要扩展帮助

为了在由大约 50 个用户编辑的文档(导入的子文档)中强制执行标签规定,我必须重新调整现有的文档结构命令部分、章节等,以遵循预定义的标签方案(使用层次结构级别作为前缀以避免冲突)。

例子胜于文字,下面是我目前对章节的定义(省略细节)。基本上,\chapter\chapter*都扩展了一个可选参数,用于定义一个自动以“ chap:”为前缀的标签,重复使用旧\chapter命令。此外,还定义了一个创建参考的命令,其中通过布尔变量选择短参考文本和长参考文本\iflongrefs

\RequirePackage{letltxmacro}
\RequirePackage{xargs}

\newcommand*\section@namelong{Section}%
\newcommand*\section@nameshort{Sect.}%
\newcommand*\section@prefix{sect}%

\LetLtxMacro{\section@old}{\section}%
\renewcommand\section{\@ifstar \section@star \section@nostar}%
\newcommandx*\section@nostar[3][1=,3=]{%
    \ifx &#1&%
        \section@old{#2}%
    \else%
        \section@old[#1]{#2}%
    \fi%
    \ifx &#3&%
    \else%
        \label{\section@prefix:#3}%
    \fi%
}%
\newcommandx*\section@star[2][2=]{%
    \section@old*{#1}%
    \ifx &#2&%
    \else%
        \label{\section@prefix:#2}%
    \fi%
}%

\newcommand*\sectionref[1]{
    \iflongrefs
        \section@namelong~\ref{\section@prefix:#1}
    \else
        \section@nameshort\,\ref{\section@prefix:#1}
    \fi
}

现在,我需要对部分、小节等进行类似的定义……当然,我可以复制并粘贴此内容,并相应地将其替换\section@XXX\part@XXX等。但是我更喜欢更优雅的解决方案,例如封装(重新)定义的“高阶命令” \extend。对章节的调用\extend应类似于下面给出的行,并生成上面看到的所有代码。

\extend{section}{Section}{Sect.}{sect}

我该如何实现它?阅读各种论坛帖子,我觉得\expandafter这是可行的方法,但我对示例的理解不够,无法让它为我工作。有什么帮助吗?

答案1

在...的帮助下电子工具箱(但仅仅是为了方便):只需将所有改为\section#1但使用\csdef\csuse;重要的是通过加倍#符号来引用元宏内部定义的宏的参数。

\documentclass{article}
\makeatletter
\RequirePackage{etoolbox}
\RequirePackage{xargs}

\newif\iflongrefs

\newcommand{\extend}[4]{%
  \csdef{#1@namelong}{#2}%
  \csdef{#1@nameshort}{#3}%
  \csdef{#1@prefix}{#4}%
  \csletcs{#1@old}{#1}%
  \csdef{#1}{\@ifstar{\csuse{#1@star}}{\csuse{#1@nostar}}}%
  \expandafter\newcommandx\expandafter*\csname#1@nostar\endcsname[3][1=,3=]{%
    \ifx &##1&%
        \csuse{#1@old}{##2}%
    \else
        \csuse{#1@old}[##1]{##2}%
    \fi
    \ifx &##3&%
    \else
      \label{\csuse{#1@prefix}:##3}%
    \fi
  }%
  \expandafter\newcommandx\expandafter*\csname#1@star\endcsname[2][2=]{%
    \csuse{#1@old}*{##1}%
    \ifx &##2&%
    \else
      \label{\csuse{#1@prefix}:##2}%
    \fi
  }
  \csdef{#1ref}##1{%
    \iflongrefs
        \csuse{#1@namelong}~\ref{\csuse{#1@prefix}:##1}%
    \else
        \csuse{#1@nameshort}\,\ref{\csuse{#1@prefix}:##1}%
    \fi
  }%
}
\makeatother

\extend{section}{Section}{Sect.}{sect}
\extend{subsection}{Subection}{Subsect.}{subsect}

\begin{document}

\section{abc}

\section[aaa]{abc}[def]


\sectionref{def}

{\longrefstrue\sectionref{def}}

\subsection[uuu]{vvv}[www]

\subsectionref{www}

\end{document}

请注意,这\LetLtxMacro不是必需的,因为\section和朋友是不是定义为具有可选参数。

已添加 – xparse 版本

代替参数你可能想使用现代解析包裹:

\RequirePackage{etoolbox}
\RequirePackage[log-declarations = false]{xparse}

\newcommand{\extend}[4]{%
  \csdef{#1@namelong}{#2}%
  \csdef{#1@nameshort}{#3}%
  \csdef{#1@prefix}{#4}%
  \csletcs{#1@old}{#1}%
  \expandafter\DeclareDocumentCommand\csname#1\endcsname{s o m o}{
    \IfBooleanTF{##1}
      {\csuse{#1@old}*{##3}
%       \IfNoValueTF{##4}
%         {}
%         {\label{\csuse{#1@prefix}:##4}}
      }
      {\IfNoValueTF{##2}
         {\csuse{#1@old}{##3}}
         {\csuse{#1@old}[##2]{##3}}
       \IfNoValueTF{##4}
         {}
         {\label{\csuse{#1@prefix}:##4}}
      }
  }
  \expandafter\DeclareDocumentCommand\csname#1ref\endcsname{m}{
    \iflongrefs
        \csuse{#1@namelong}~\ref{\csuse{#1@prefix}:##1}
    \else
        \csuse{#1@nameshort}\,\ref{\csuse{#1@prefix}:##1}
    \fi
  }%
}

这三行注释是因为不清楚标签对于\section*命令的用途是什么。

相关内容