嵌套在包宏中的 xstrings \IfSubStr 中的参数扩展问题

嵌套在包宏中的 xstrings \IfSubStr 中的参数扩展问题

感谢您对这个问题的任何建议。这是当 xstrings 测试函数深埋在代码中时使用 xstrings 进行测试的变体。我已在此网站和其他地方阅读了十几个或更多示例,但所有建议的解决方案都不适合我,可能是因为我使用的调用 xstrings 函数的特定包。

我很乐意用其他东西替换 xstrings,但如果可能的话,我想避免使用 Latex 3/expl3/whatever,因为文档很长,我对这些新东西没有任何经验,也不知道还会有什么变化。也就是说,我发现最小和本地解决方案对我来说最容易实现。

我正在使用 LuaLaTeX 中的 gregorio tex 包排版格里高利圣咏。下面是 MWE,但需要一些背景知识。

Gregorio Tex 读取一个纯文本文件(称为 .gabc 文件,其中包含乐谱表示),并将其转换为 tex 代码以打印实际乐谱。.gabc 文件包含一个带有标签的标题(例如 name:代表乐曲名称),后跟 %%,然后是音乐的实际标记。

Gregorio Tex 提供了一个命令 \gresetheadercapture,它将捕获特定标签的值并将其作为参数传递给用户定义的命令。这允许根据与乐谱相关的值(例如名称、音乐模式、文本的圣经引文等)打印标题等。我已尽可能地精简了此示例。

我正在使用从 gabc 文件中读取的圣歌名称(\thelatinname)和圣歌类型(\thechantpart)在文档中的每个乐谱上方打印一个标题,该标题使用 gresetheadercapture 来读取。

问题是我想根据颂歌的类型稍微改变标题;具体来说,如果是“Varia”类型,则从标题中省略颂歌部分。所以我会得到这样的标题

循序渐进:基督是事实

但简单来说,例如,

不当行为

用于“Varia”类型的圣歌。

咏唱类型名称中可以有空格,但始终是纯字母,没有其他特殊字符。Varia 是唯一包含字母 V 的类型。

为了实现这一点,我使用 xstrings \IfSubStr 进行测试,以查看 \thechantpart 是否包含大写字母 V。由于软件何时扩展哪些参数以及扩展程度存在问题,因此测试失败,我不知所措,无法调试或修复此问题。显然,这很复杂,因为在命令 \gregorioscore 运行之前什么都不会发生,因此我不确定我自己的命令是否根据它们之前的包执行的内容扩展参数。

实际上,无论我做什么,测试结果总是错误的。

xstrings 包有几个用于更改参数扩展方式的标志:\fullexpandarg、\expandarg、\normalexpandarg 和 \noexpandarg。这些标志都不会以任何方式改变结果,它们的可选标志 \exploregroup 也是如此。这 8 个命令的组合均会失败。

这是 MWE tex 文件,后面跟着 MWE.gabc 文件。输出的标题中不应该包含 Varia:,但实际上却包含。

% !TEX TS-program = lualatex
% !TEX encoding = UTF-8

\documentclass[12pt,twoside]{book}

\usepackage[autocompile]{gregoriotex}
\usepackage{xstring}

%Set the testing flag to 2 to look for any changes.
\gdef\hasVaria{2} %

%Routine to process the type of chant as \thechantpart.
%  Check if \thechantpart is the string Varia.
%  If so, set \hasVaria to 1 for later use.
\newcommand\mkchantindex[1]{%
\gdef\thechantpart{#1}

 \message{thechantpart macro is !\thechantpart!}
   \message{Test result:}
   \begingroup
     \normalexpandarg
     \exploregroups
       \IfSubStr{\thechantpart}{V}{\message{true}\gdef\hasVaria{1}}{\message{false}\gdef\hasVaria{0}}
    \noexploregroups
    \fullexpandarg
  \message{hasVaria is !\hasVaria!}
  \endgroup
}


%Routine to get the Latin title and typeset the chant title
%  If the hasVaria flag is 1, omit the chant part from the title.
\newcommand\mklatinlabel[1]{%
\gdef\thelatinname{#1}
      \ifnum\hasVaria=1%
          \printtitle{\thelatinname}\nopagebreak%
      \else
         \printtitle{\thechantpart:\ \thelatinname}\nopagebreak%
      \fi
}

\newcommand{\printtitle}[1]{\noindent  #1\par}

%Direct gregorio tex to pass the contents of the named tag to the named subroutine as
% a string
\gresetheadercapture{latin-name}{mklatinlabel}{string}
\gresetheadercapture{office-part}{mkchantindex}{string}  

\begin{document}

\message{First hasVaria = !\hasVaria!\par}

\gregorioscore{MWEchant}

\message{Last hasVaria = !\hasVaria!}

\end{document}

文件 MWEchant.gabc:

% !TEX root = ./MWE.tex
name:Chant;
office-part:Varia;
latin-name:Improperia;
%%
(c4) This(c) is(d) some(e) chant(d.) (::)

执行 gresetheadercapture 例程期间参数扩展出现问题发布...

答案1

您可以规范化 catcodes,然后简单地与\ifx

\documentclass[12pt,twoside]{book}

\usepackage[autocompile]{gregoriotex}
\usepackage{xstring}

%Set the testing flag to 2 to look for any changes.
\gdef\hasVaria{2} %

%Routine to process the type of chant as \thechantpart.
%  Check if \thechantpart is the string Varia.
%  If so, set \hasVaria to 1 for later use.
\newcommand\mkchantindex[1]{%
  \edef\thechantpart{\detokenize{#1}}}

%Routine to get the Latin title and typeset the chant title
%  If the hasVaria flag is 1, omit the chant part from the title.
\edef\Variapart{\detokenize{Varia}}
\newcommand\mklatinlabel[1]{%
\gdef\thelatinname{#1}
      \ifx\thechantpart\Variapart
\message{VARIA}%
          \printtitle{\thelatinname}\nopagebreak%
      \else
\message{NOT VARIA}%
         \printtitle{\thechantpart:\ \thelatinname}\nopagebreak%
      \fi
}

\newcommand{\printtitle}[1]{\noindent  #1\par}

%Direct gregorio tex to pass the contents of the named tag to the named subroutine as
% a string
\gresetheadercapture{latin-name}{mklatinlabel}{string}
\gresetheadercapture{office-part}{mkchantindex}{string}  

\begin{document}

\message{First hasVaria = !\hasVaria!\par}

\gregorioscore{MWEchant}

\message{Last hasVaria = !\hasVaria!}

\end{document}

相关内容