是什么导致了四个月前还不存在的神秘错误“缺少 \endcsname 插入”?

是什么导致了四个月前还不存在的神秘错误“缺少 \endcsname 插入”?

我正在运行 MacTeX 2022,并应用了所有更新。我有一个大型项目,上次正确构建是在 2022 年 9 月 3 日。今天我Missing \endcsname inserted在某一行上遇到了一个神秘的错误,我找不到原因。按下H控制台显示\let控制序列错误地存在,\csname...\endcsname但我的代码中没有\let。MWE 代码已从源项目直接复制并粘贴到 MWE.sty.tex文件中。唯一的变化是不断重命名某些变量。MWE 完全复制了错误。

自 2022 年 9 月以来,此代码一直未被触及,因此自 9 月以来的更新中出现的问题可能是罪魁祸首。我看到的唯一可能相关的事情是使用\MakeUppercase(因为我知道最近对此进行了一些修改)或密钥处理机制。是什么导致了此错误?

编辑:我需要单词alternatebasederived在通过 回显到控制台时全部小写,typeout但在用于调用相应宏时首字母大写。这就是为什么我最初使用 的原因,\MakeUppercase现在似乎不起作用。我无法\MakeTitlecase工作。

这是 MWE 包文件。将其命名为keymwe.sty

% !TEX program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\usepackage{pgfopts}
\usepackage{iftex}
\RequireLuaTeX
\newcommand*{\keymwe@selectunits}{}
\newcommand*{\keymwe@selectprecision}{}
\newcommand*{\keymwe@selectapproximate}[2]{#1}
\newcommand*{\keymwe@selectprecise}[2]{#2}
\newcommand*{\keymwe@selectbaseunits}[3]{#1}
\newcommand*{\keymwe@selectderivedunits}[3]{#2}
\newcommand*{\keymwe@selectalternateunits}[3]{#3}
\NewDocumentCommand{\AlwaysUseBaseUnits}{}
  {\renewcommand*{\keymwe@selectunits}{\keymwe@selectbaseunits}}%
\NewDocumentCommand{\AlwaysUseDerivedUnits}{}
  {\renewcommand*{\keymwe@selectunits}{\keymwe@selectderivedunits}}%
\NewDocumentCommand{\AlwaysUseAlternateUnits}{}
  {\renewcommand*{\keymwe@selectunits}{\keymwe@selectalternateunits}}%
\NewDocumentCommand{\AlwaysUseApproximateConstants}{}
  {\renewcommand*{\keymwe@selectprecision}{\keymwe@selectapproximate}}%
\NewDocumentCommand{\AlwaysUsePreciseConstants}{}
  {\renewcommand*{\keymwe@selectprecision}{\keymwe@selectprecise}}%
\NewDocumentCommand{\HereUseBaseUnits}{ m }{\begingroup\AlwaysUseBaseUnits#1\endgroup}%
\NewDocumentCommand{\HereUseDerivedUnits}{ m }{\begingroup\AlwaysUseDerivedUnits#1\endgroup}%
\NewDocumentCommand{\HereUseAlternateUnits}{ m }{\begingroup\AlwaysUseAlternateUnits#1\endgroup}%
\NewDocumentCommand{\HereUseApproximateConstants}{ m }{\begingroup\AlwaysUseApproximateConstants#1\endgroup}%
\NewDocumentCommand{\HereUsePreciseConstants}{ m }{\begingroup\AlwaysUsePreciseConstants#1\endgroup}%
\NewDocumentEnvironment{UseBaseUnits}{}{\AlwaysUseBaseUnits}{}%
\NewDocumentEnvironment{UseDerivedUnits}{}{\AlwaysUseDerivedUnits}{}%
\NewDocumentEnvironment{UseAlternateUnits}{}{\AlwaysUseAlternateUnits}{}%
\NewDocumentEnvironment{UseApproximateConstants}{}{\AlwaysUseApproximateConstants}{}%
\NewDocumentEnvironment{UsePreciseConstants}{}{\AlwaysUsePreciseConstants}{}%
\newif\ifusingpreciseconstants
\pgfkeys{%
  /keymwe/options/.cd,
  initial@setup/.style={%
    /keymwe/options/buffered@units/.initial=alternate,%
  },%
  initial@setup,%
  preciseconstants/.is if=usingpreciseconstants,%
  units/.is choice,%
  units/.default=derived,%
  units/alternate/.style={/keymwe/options/buffered@units=alternate},%
  units/base/.style={/keymwe/options/buffered@units=base},%
  units/derived/.style={/keymwe/options/buffered@units=derived},%
  .unknown/.code={%
    \typeout{}%
    \typeout{keymwe: You used unknown option '\pgfkeyscurrentname'.}%
  },%
}%
\ProcessPgfPackageOptions{/keymwe/options}

\newcommand*{\keymwe@do@setup}{%
  \csname AlwaysUse\expanded{\noexpand\MakeUppercase%
    \pgfkeysvalueof{/keymwe/options/buffered@units}}Units\endcsname%
  \typeout{keymwe: You will get \pgfkeysvalueof{/keymwe/options/buffered@units}\space units.}%
  \ifusingpreciseconstants
    \AlwaysUsePreciseConstants
    \typeout{keymwe: You will get precise constants.}%
  \else
    \AlwaysUseApproximateConstants
    \typeout{keymwe: You will get approximate constants.}%
  \fi
  \typeout{}%
}%
\keymwe@do@setup
\NewDocumentCommand{\keymwesetup}{ m }%
  {%
    \IfValueT{#1}%
      {%
        \pgfqkeys{/keymwe/options}{#1}
        \typeout{}%
        \typeout{keymwe: keymwesetup options...}
        \keymwe@do@setup
      }%
  }%

这是使用测试包的 MWE 文档。将其命名为keymwe.tex

% !TEX program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\documentclass{article}

\usepackage{keymwe}

\begin{document}

Hello, world.

\end{document}

答案1

定义一个可扩展的字符串大小写转换函数。这里

\ExplSyntaxOn
\NewExpandableDocumentCommand{\Titlecasestring}{m}
 {
  \str_uppercase:f { \str_head:e { #1 } } \str_tail:e { #1 }
 }
\cs_generate_variant:Nn \str_head:n { e }
\cs_generate_variant:Nn \str_tail:n { e }
\ExplSyntaxOff

首先\str_head:e展开参数,然后取出所获字符串中的第一个项。这里使用字符串是因为构造要在 内部使用\csname

完整代码。

\usepackage{pgfopts}
\usepackage{iftex}
\RequireLuaTeX
\newcommand*{\keymwe@selectunits}{}
\newcommand*{\keymwe@selectprecision}{}
\newcommand*{\keymwe@selectapproximate}[2]{#1}
\newcommand*{\keymwe@selectprecise}[2]{#2}
\newcommand*{\keymwe@selectbaseunits}[3]{#1}
\newcommand*{\keymwe@selectderivedunits}[3]{#2}
\newcommand*{\keymwe@selectalternateunits}[3]{#3}

\NewDocumentCommand{\AlwaysUseBaseUnits}{}
  {\renewcommand*{\keymwe@selectunits}{\keymwe@selectbaseunits}}
\NewDocumentCommand{\AlwaysUseDerivedUnits}{}
  {\renewcommand*{\keymwe@selectunits}{\keymwe@selectderivedunits}}
\NewDocumentCommand{\AlwaysUseAlternateUnits}{}
  {\renewcommand*{\keymwe@selectunits}{\keymwe@selectalternateunits}}
\NewDocumentCommand{\AlwaysUseApproximateConstants}{}
  {\renewcommand*{\keymwe@selectprecision}{\keymwe@selectapproximate}}
\NewDocumentCommand{\AlwaysUsePreciseConstants}{}
  {\renewcommand*{\keymwe@selectprecision}{\keymwe@selectprecise}}
\NewDocumentCommand{\HereUseBaseUnits}{ m }{\begingroup\AlwaysUseBaseUnits#1\endgroup}
\NewDocumentCommand{\HereUseDerivedUnits}{ m }{\begingroup\AlwaysUseDerivedUnits#1\endgroup}
\NewDocumentCommand{\HereUseAlternateUnits}{ m }{\begingroup\AlwaysUseAlternateUnits#1\endgroup}
\NewDocumentCommand{\HereUseApproximateConstants}{ m }{\begingroup\AlwaysUseApproximateConstants#1\endgroup}
\NewDocumentCommand{\HereUsePreciseConstants}{ m }{\begingroup\AlwaysUsePreciseConstants#1\endgroup}
\NewDocumentEnvironment{UseBaseUnits}{}{\AlwaysUseBaseUnits}{}
\NewDocumentEnvironment{UseDerivedUnits}{}{\AlwaysUseDerivedUnits}{}
\NewDocumentEnvironment{UseAlternateUnits}{}{\AlwaysUseAlternateUnits}{}
\NewDocumentEnvironment{UseApproximateConstants}{}{\AlwaysUseApproximateConstants}{}
\NewDocumentEnvironment{UsePreciseConstants}{}{\AlwaysUsePreciseConstants}{}
\newif\ifusingpreciseconstants
\pgfkeys{
  /keymwe/options/.cd,
  initial@setup/.style={
    /keymwe/options/buffered@units/.initial=alternate,
  },
  initial@setup,
  preciseconstants/.is if=usingpreciseconstants,
  units/.is choice,
  units/.default=derived,
  units/alternate/.style={/keymwe/options/buffered@units=alternate},
  units/base/.style={/keymwe/options/buffered@units=base},
  units/derived/.style={/keymwe/options/buffered@units=derived},
  .unknown/.code={%
    \typeout{}%
    \typeout{keymwe: You used unknown option '\pgfkeyscurrentname'.}%
  },
}
\ProcessPgfPackageOptions{/keymwe/options}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\Titlecasestring}{m}
 {
  \str_uppercase:f { \str_head:e { #1 } } \str_tail:e { #1 }
 }
\cs_generate_variant:Nn \str_head:n { e }
\cs_generate_variant:Nn \str_tail:n { e }
\ExplSyntaxOff

\newcommand*{\keymwe@do@setup}{%
  \csname AlwaysUse\Titlecasestring{\pgfkeysvalueof{/keymwe/options/buffered@units}}Units\endcsname
  \typeout{keymwe: You will get \pgfkeysvalueof{/keymwe/options/buffered@units}\space units.}%
  \ifusingpreciseconstants
    \AlwaysUsePreciseConstants
    \typeout{keymwe: You will get precise constants.}%
  \else
    \AlwaysUseApproximateConstants
    \typeout{keymwe: You will get approximate constants.}%
  \fi
  \typeout{}%
}%
\keymwe@do@setup
\NewDocumentCommand{\keymwesetup}{ m }%
  {%
    \IfValueT{#1}%
      {%
        \pgfqkeys{/keymwe/options}{#1}%
        \typeout{}%
        \typeout{keymwe: keymwesetup options...}%
        \keymwe@do@setup
      }%
  }

相关内容