如何将两个参数传递给新命令或宏?

如何将两个参数传递给新命令或宏?

首先,我要感谢 Stack Exchange 上的每一位贡献者,因为他们为 LaTeX 提供了巨大的帮助。我在 SE 上搜索了所有解决方案,但还没有找到解决方案。这是我的项目:

我正在制作一本按照传统仪式唱晚祷的小册子,使用格雷戈里奥项目和 LuaLatex。一些已完成工作的 pdf 示例可在此处找到:

http://docs.sspx.org.za/index.php/s/1LRq234nkQGavAW

布局几乎是自动完成的,只需对导入对句的文件名进行简单修改即可。我准备将所有源代码放在网上,以便其他人可以使用并提供其他翻译 [我自己做了英语和波兰语,但其他人可以提供更多语言]。不过,我想稍微清理一下源代码,让其他人尽可能轻松地做出贡献。其中一部分将是一个简单的宏,用于确定要排版礼仪年的哪个星期日。

对于那些了解传统拉丁礼仪的人来说,对句每个星期日都会改变,但晚祷的整体结构保持不变。我想要做的是选择简单地将一年中的星期日指定为变量,然后让 LaTeX 计算其余部分。然而,我在将一个命令的参数传递给另一个命令时遇到了很多麻烦。

这是我目前关于如何选择对句的工作示例(使用假想情况使示例更简短,实际宏有 52 个选择,给出的实际上是另一个目录中的 .gabc 文件的名称)。我正在使用 xstring 包,它具有 \IfEqCase 命令,我可以按以下方式嵌套它:

\newcommand{\whichantifon}[2]{%
   \IfEqCase{#1}{%
     {advent}{\IfEqCase{#2}{%
       {i}{First Sunday of Advent, Magnificat-4a}
       {ii}{Second Sunday of Advent, Magnificat-6F}
      }}% end advent cases
     {pentecost}{\IfEqCase{#2}{%
      {i}{First Sunday after Pentecost, Magnifcat-1d}
      {ii}{Second Sunday after Pentecost, Magnifcat-3a}
      }}% end pentecost cases
  }% end choose instruction
}%end command

使用此宏,我可以做如下的事情来提取适当的对句和模式:

\whichantifon{advent}{i}

我想要做的是将这个选择的结果传递给另一个宏,该宏实际上使用来自这个选择的两个参数进行圣歌的排版:

\canticum{\whichantifon{advent}{i}}

为了获得一个可行的示例,我放了一个简单的 \def,就像这样,它做了最少的排版:

\def\canticum#1, #2{%
    This is the #1, and Magnificat #2}%

这个想法是,简单的逗号(\whichantifon 扩展的一部分)将成为此 \canticum 的两个参数的分隔符,我认为这是一种优雅的解决方案,否则我将不得不有两个非常冗长的选择宏。然而它不起作用,或者说它只是部分起作用。

如果我有以下定义了上述宏的文档,我可以获得以下输出:

\whichantifon{advent}{i}

因此,这部分工作得很好:

First Sunday of Advent, Magnificat-4a

但是如果我尝试如上所述的简单 \canticum:

\canticum{\whichantifon{advent}{i}}

我收到以下错误:

   ERROR: Paragraph ended before \canticum was complete.

显然是“命令参数中出现了一个空行,但不应该包含空行”。但是,如果我将第一个宏的输出复制/粘贴到 \canticum,它就可以正常工作。我在 SE 上到处寻找 \expandafter 和其他技巧,但都不起作用。我甚至尝试过使用字符串分隔符和其他包,但结果却更加复杂,没有解决方案。

我一直认为 LaTeX 只是一种宏扩展器或替换语言。然而,它似乎在某些时候或以完全不直观的方式不进行替换。例如,\def 的参数何时扩展?在它自己求值之前还是之后?它似乎需要在定义之前求值参数,但似乎不是这样工作的。

我真正想要做的是让一个函数返回两个参数,用作另一个函数的输入。这当然不是一个非常合适的函数,所以我的方法可能是错误的。

真正的困难在于每个星期日都有两条信息,即对句和 Magnificat 的音调,这两条信息决定了文档中要排版的内容。理想情况下,贡献者只需提供一条信息 [哪个星期日],而 latex 将提供其余信息(因为实际文件和音调已经在项目文件夹中)。

任何帮助或链接都可以解决此难题,甚至不同的方法,我都欢迎。如果有帮助,我可以发布指向 git repo 的链接作为“正在进行的工作”。

感谢您至少阅读了这个问题!

答案1

[请始终提供测试文件,而不仅仅是片段]

最简单的方法是将格式化命令作为参数传递给选择器,我在这里将其设为可选

\newcommand\canticum[2]{%
    This is the #1, and Magnificat #2}%

\newcommand{\whichantifon}[3][\canticum]{%
   \IfEqCase{#2}{%
     {advent}{\IfEqCase{#3}{%
       {i}{#1{First Sunday of Advent}{Magnificat-4a}}
       {ii}{#1{Second Sunday of Advent}{Magnificat-6F}}
      }}% end advent cases
     {pentecost}{\IfEqCase{#3}{%
      {i}{#1{First Sunday after Pentecost}{Magnifcat-1d}}
      {ii}{#1{Second Sunday after Pentecost}{Magnifcat-3a}}
      }}% end pentecost cases
  }% end choose instruction
}%end command

所以默认情况下

\whichantifon{advent}{i}

将使用\canticum ,但你可以传入任何其他两个参数命令

\newcommand\zzz[2]{\fbox{#1}---\fbox{#2}}
\whichantifon[\zzz]{advent}{i}

答案2

大卫·卡莱尔 (David Carlisle) 给出了出色的解决方案,这里提供了完整的解决方案(抱歉没有在问题中包含完整版本):

\documentclass{article}
\usepackage{xstring}

\newcommand\canticum[2]{%
    This is the #1, and Magnificat tone is #2}%

\newcommand{\whichantifon}[3][\canticum]{%
   \IfEqCase{#2}{%
     {advent}{\IfEqCase{#3}{%
       {i}{#1{First Sunday of Advent}{4a}}
       {ii}{#1{Second Sunday of Advent}{6F}}
      }}% end advent cases
     {pentecost}{\IfEqCase{#3}{%
      {i}{#1{First Sunday after Pentecost}{1d}}
      {ii}{#1{Second Sunday after Pentecost}{3a}}
      }}% end pentecost cases
  }% end choose instruction
}%end command

\begin{document}

\whichantifon{advent}{i}

\whichantifon{pentecost}{ii}

\whichantifon{advent}{ii}

\end{document}

这给出了预期的结果:

This is the First Sunday of Advent, and Magnificat tone is 4a
This is the Second Sunday after Pentecost, and Magnificat tone is 3a
This is the Second Sunday of Advent, and Magnificat tone is 6F

非常感谢 David Carlisle 的精彩回答。稍后当该项目准备公开时,我会在此处添加链接。

答案3

在使用\whichantifon{advent}{i}之前,我们需要完全展开。但是它不可扩展,因为它基于不可扩展。因此,我们需要先定义完全可扩展:\canticum\whichantifon\IfEqCase\eqcase

\def\eqcase#1#2{\eqcaseA{#1}#2\end{}}
\def\eqcaseA#1#2#3{\ifx\end#2\else
   \ifnum\pdfstrcmp{#1}{#2}=0 #3\eqcaseFIN\fi
   \eqcaseB{#1}\fi
}
\def\eqcaseB#1\fi{\fi\eqcaseA{#1}}
\def\eqcaseFIN#1\end#2{\fi\fi}

现在,我们可以定义\whichantifon

\def\whichantifon#1#2{%
   \eqcase{#1}{%
     {advent}{\eqcase{#2}{%
       {i}{First Sunday of Advent, Magnificat-4a}
       {ii}{Second Sunday of Advent, Magnificat-6F}
      }}% end advent cases
     {pentecost}{\eqcase{#2}{%
      {i}{First Sunday after Pentecost, Magnifcat-1d}
      {ii}{Second Sunday after Pentecost, Magnifcat-3a}
      }}% end pentecost cases
  }% end choose instruction
}%end command

我们可以定义\canticum宏(注意第二个参数以句点分隔):

\def\canticum#1, #2.{This is the #1, and Magnificat #2}

用法如下:

\edef\tmp{\whichantifon{advent}{i}}\expandafter\canticum\tmp.

参数在\tmp使用时会完全展开\edef,然后使用。请注意后面的句号,\tmp因为它是第二个参数的分隔符。

相关内容