![如何在 LaTeX3 中使用 \NewDocumentEnvironment 和 \NewDocumentCommand 重新创建 \newenvironment 和 \newcommand](https://linux22.com/image/372886/%E5%A6%82%E4%BD%95%E5%9C%A8%20LaTeX3%20%E4%B8%AD%E4%BD%BF%E7%94%A8%20%5CNewDocumentEnvironment%20%E5%92%8C%20%5CNewDocumentCommand%20%E9%87%8D%E6%96%B0%E5%88%9B%E5%BB%BA%20%5Cnewenvironment%20%E5%92%8C%20%5Cnewcommand.png)
为了更好地了解如何处理动态参数和“块”(例如传递给命令/环境的参数和块),我想尝试编写一个包装函数,该函数的功能\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}
我不确定的事情是:
- 传递如下参数
\NewDocumentEnvironment{#1}{#2}{#3}{#4}
- 处理“块”,因为我在传递参数时所处理的只是简单的单行/字符串/键值对。
- 穿过时如何处理
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}
答案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}