LaTeX3 和 LaTeX2e 之间程序化交互的最佳实践是什么?

LaTeX3 和 LaTeX2e 之间程序化交互的最佳实践是什么?

我非常喜欢使用 LaTeX3 来编写我的 LaTeX 程序,我使用得越多,就越容易使用,我越不想回到 LaTeX2e 甚至纯 TeX!但我时不时地会发现自己需要与 LaTeX2e 交互在编程层面。例如,某些 LaTeX2e 包可能设置了条件,我想在用 LaTeX3 编写的包中测试这些条件。我可以使用 LaTeX2e 方法执行此操作:

\ifcondition
  <stuff>
\else
  <other stuff>
\fi

\expandafter但我不喜欢这样,部分原因是如果我想确保\else和不会干扰内部代码,我必须记住担心s \fi。所以我宁愿坚持使用 LaTeX3 语法。

我目前的上述代码是:

\prg_new_conditional:Npnn \latex_if:N #1 {p,T,F,TF}
{
  \if_meaning:w #1 \iftrue
  \prg_return_true: \else: \prg_return_false: \fi:
}

这是一个合理的方法吗,或者有更好的方法吗?

同样,(我希望我能在这里回答两个问题,因为它们是如此密切相关)我应该如何与 LaTeX2e 宏交互?假设一个包定义了一个宏\def\something{This is some text we'll save for later.},我想使用 LaTeX3 来处理它。我认为我应该将其视为一个标记列表(tl),对吗?这样做有什么陷阱吗?

答案1

\latex_if:NTF \ifmmode当使用时,您的代码将返回 false ,\ifmmode因为不是与 相同\iftrue,即使我们处于数学模式。它仅适用于已定义的条件,例如\if@minipage,因为这是由 引入的\newif,所以它要么是 ,\iftrue要么是\iffalse

你的函数应该对定义的条件和原始条件都以相同的方式工作,以获得最大的灵活性;你可能需要这样做

\bool_if:nTF { \latex_if_p:n {@minipage} || \latex_if_p:n {mmode} }
 {true code}
 {false code}

(这不太可能,但是表明了这个想法)。

我会采取不同的做法:

\prg_new_conditional:Npnn \latex_if:n #1 {p,T,F,TF}
 {
  \use:c{if#1} \prg_return_true: \else: \prg_return_false: \fi:
 }

用作

\latex_if:nTF {mmode} {code for math mode} {code for non math mode}

如果你愿意,你可以这样做

\prg_new_conditional:Npnn \latex_if:N #1 {p,T,F,TF}
 {
  #1 \prg_return_true: \else: \prg_return_false: \fi:
 }

但这有一个缺点,就是要求\makeatletter何时\if@minipage进行测试。

答案2

对于你的第一个问题,我会说答案是肯定的,这是正确的方法,而且很简洁。但是,如果我们假设该论证始终是 2e 条件,那么定义可以变得更简单:

\prg_new_conditional:Npnn \latex_if:N #1 {p,T,F,TF}
{
   #1 \prg_return_true: \else: \prg_return_false: \fi:
}

感谢@egreg 指出这一点。

它还允许您在谓词中使用那些 2e 布尔值,例如,

\bool_if:nTF
   {
     \latex_if_p:N \if@minipage ||
     \latex_if_p:N \ifinner     ||
     ...

但当然\latex_if_p:N \ifinner可以直接使用 expl3 equiv,即\mode_if_inner_p:

我不太热衷于这样的建议(如评论中所建议的):

 \bool_if:nTF
    {
      \if@minipage 1 \else 0 \fi || %compatible to LaTeX2e
      \ifinner 1 \else 0 \fi || %compatible to LaTeX2e

为什么?很简单,它公开了 expl3 布尔实现的内部实现细节,这是一个不好。如果它真的应该返回\prg_return_true:,但即使如此... :-)

至于第二个问题,答案是:视情况而定。显然,任何本质上是“标记列表”的 2e 宏都应该按此方式操作,因此,是的,它将是一个“tl”,并且不应该存在任何陷阱。

当然,您可以提供一个明确的接口,在完成后将其转换为 l3 名称并转换回 2e 名称,但在我看来,在这种情况下,您只会增加犯错的几率(以及额外的处理时间)。

更复杂的是任何带有参数的宏。

如果你只是想使用它,那么我认为值得考虑在一开始就定义一个符合 expl3 的名称并始终使用它。在这种情况下,代码会更简洁。

如果由于某种原因您需要对其进行操作,那么所有\cs_...功能都应该可以工作,而对于其余功能则需要根据具体情况进行查看。

以上就是我的想法,也许其他人还有其他想法。

相关内容