如何在 LaTeX3 中使用 \NewDocumentEnvironment 和 \NewDocumentCommand 重新创建 \newenvironment 和 \newcommand

如何在 LaTeX3 中使用 \NewDocumentEnvironment 和 \NewDocumentCommand 重新创建 \newenvironment 和 \newcommand

为了更好地了解如何处理动态参数和“块”(例如传递给命令/环境的参数和块),我想尝试编写一个包装函数,该函数的功能\NewDocumentEnvironment\NewDocumentCommand它们的功能基本相同。但是我希望 API 是:

\myenvironment{foo}{<args>}{startblock}{endblock}
\mycommand{foo}{<args>}{block}

即即使 API 带有\NewDocumentCommand{\foo}反斜杠\foo,我还是想这样做foo

以下是该系统的 MWE:

\documentclass[a4paper]{article}

\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\begin{document}

\NewDocumentCommand{\mycommand}{mmm} {
  \NewDocumentCommand{#1}{#2}{#3}
}

\mycommand{myenvironment}{mmmO{}} {
  \NewDocumentEnvironment{#1}{#2}{#3}{#4}
}

\myenvironment{foo}{m}{
  \typeout{#1}
}{}

\begin{foo}{abc}

\end{foo}

\end{document}

我不确定的事情是:

  1. 传递如下参数\NewDocumentEnvironment{#1}{#2}{#3}{#4}
  2. 处理“块”,因为我在传递参数时所处理的只是简单的单行/字符串/键值对。
  3. 穿过时如何处理foo转换。\foo

\myenvironment想知道如何使用上述和的定义来使其工作\mycommand

\begin{foo}{abc}

\end{foo}

答案1

避免在里面做一般定义。当你完成代码部分时document记得发出。\ExplSyntaxOff

可以make\NewDocumentCommand接受字符串而不是控制序列。问题是:为什么?一般来说,它只是混淆了代码。

无论如何,\exp_args:Nc是要使用的结构。它告诉 LaTeX 从下一个标记后面的括号参数构建一个控制序列,然后它消失。在“旧式” TeX 编程中,它与

\expandafter\token\csname string\endcsname

另请注意,您\myenvironment选修的最后一个参数,因此应该用括号[]而不是大括号给出{}

\documentclass[a4paper]{article}

\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\mycommand}{m +m +m}
 {
  \exp_args:Nc \NewDocumentCommand{#1}{#2}{#3}
 }

\mycommand{myenvironment}{m +m +m +O{}}
 {
  \NewDocumentEnvironment{#1}{#2}{#3}{#4}
 }

\ExplSyntaxOff

\myenvironment{foo}{m}
 {%
  \typeout{#1}%
 }

\mycommand{baz}{m}{X#1X}

\begin{document}

\baz{Y}

\begin{foo}{abc}
Something inside
\end{foo}

\end{document}

答案2

我不明白你为什么要对参数进行标记,只是为了传递它们。相反,只需咖喱\NewDocumentCommand

\documentclass{article}

\usepackage{xparse}

\newcommand\mycommand[1]{\expandafter\NewDocumentCommand\csname#1\endcsname}
\newcommand\myenvironment{\NewDocumentEnvironment}

\begin{document}

\mycommand{hello}{}{world}

\hello

\myenvironment{foo}{m}{
  \typeout{#1}
}{}

\begin{foo}{abc}

\end{foo}

\end{document}

答案3

\mycommand宏应定义为

\NewDocumentCommand{\mycommand}{mm+m} {%
  \expandafter\NewDocumentCommand\csname #1\endcsname{#2}{#3}%
}

因为#1必须成为参数名称,所以典型的\expandafter\NewDocumentCommand\csname #1\endcsname

第三个论点‘必须’是+m为了允许的定义代码\foo,它更有可能包含多个段落。

对于的第三和第四个参数也是如此\myenvironment

\documentclass[a4paper]{article}

\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{xparse}


\begin{document}

\NewDocumentCommand{\mycommand}{mm+m} {%
  \expandafter\NewDocumentCommand\csname #1\endcsname{#2}{#3}%
}

\mycommand{myenvironment}{mm+m+O{}} {%
  \NewDocumentEnvironment{#1}{#2}{#3}{#4}
}

\myenvironment{foo}{m}{%
  \typeout{#1}
}{}

\begin{foo}{abc}

\end{foo}

\mycommand{foobar}{om}{%
  \IfValueT{#1}{Yes, there is an opt. argument: #1}

  Mandatory Argument: #2

}

\foobar{Hello World}

\foobar[And now for something completely different]{Hello World}

\end{document}

enter image description here

答案4

\documentclass[a4paper]{article}

\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}

\NewDocumentCommand{\mycommand}{ m +m +m } {
  \expandafter\NewDocumentCommand\expandafter{\csname#1\endcsname}{#2}{#3}
}

\mycommand{myenvironment} { m +m +m +m } {
  \NewDocumentEnvironment{#1}{#2}{#3}{#4}
}

\myenvironment{foo}{ m }{
  \typeout{#1}
}{}

\begin{document}


\begin{foo}{abc}

\end{foo}

\end{document}

相关内容