这是我的 mwe.tex
\documentclass[12pt]{report}
\usepackage{xifthen}
\usepackage{xstring}
\def\test{\textnormal{test}}
\newcounter{wordCount}
\setcounter{wordCount}{0}
\newcounter{AllWord}
\setcounter{AllWord}{0}
\NewDocumentCommand{\exy}{ m m m}{%
\StrCount{#2}{,}[\comma]
\StrCount{#2}{?}[\qmark]
\ifthenelse{\qmark > 0}{%
\addtocounter{wordCount}{\comma + \qmark}
\addtocounter{AllWord}{\comma + \qmark}
}{%
\addtocounter{wordCount}{\comma + \qmark + 1}
\addtocounter{AllWord}{\comma + \qmark + 1}
}
\textbf{#2} (#3), ``#1''\\%
}
\begin{document}
\test\par
\exy{one \test}{two \test s}{three \test s}
\end{document}
如果你注释掉该行,\exy
它会按预期工作。否则错误以
[{
"resource": "/c:/Users/hsmye/LaTeX/Gaelic/vocab/mwe.tex",
"owner": "LaTeX",
"severity": 8,
"message": "Undefined control sequence.\n\\reserved@a ->\\@nil",
"source": "LaTeX",
"startLineNumber": 27,
"startColumn": 1,
"endLineNumber": 27,
"endColumn": 65536
}]
这超出了我的宏能力。有人能帮忙吗?应该注意的是,这不是原始问题。为了生成不需要购买字体的 MWE,我一直取出直到没有错误,然后加回来得到这个。原始问题是:
\newfontfamily{\EtGoudy}{P22 Goudy Ampersands}
\DeclareTextFontCommand{\GoudyEt}{\EtGoudy}
\newfontfamily{\cVirgi}{P22 Virginian}
\DeclareTextFontCommand{\Virgic}{\cVirgi}
\def\dispEt{\GoudyEt{c}\kern -3pt{\vspace{-0.01ex}\huge\Virgic{c}}.}
\def\Etc{\textnormal{\dispEt}}
替换\test
为\Etc
,结果类似。
答案1
注意,你应该总是以多行形式显示 TeX 错误,因为换行符对于理解消息至关重要,它们标记哪个命令未定义
! Undefined control sequence.
\reserved@a ->\@nil
l.29 ...exy{one \test}{two \test s}{three \test s}
?
您使用了 TeX 基元定义,导致命令在扩展上下文中中断。如果您使用,\NewDocumentCommand
您将\protected
在此类构造中获得安全的命令。
运行没有错误
\documentclass[12pt]{report}
\usepackage{xifthen}
\usepackage{xstring}
\NewDocumentCommand\test{}{\textnormal{test}}
\newcounter{wordCount}
\setcounter{wordCount}{0}
\newcounter{AllWord}
\setcounter{AllWord}{0}
\NewDocumentCommand{\exy}{ m m m}{%
\StrCount{#2}{,}[\comma]%%%%%%%%%%%%%%
\StrCount{#2}{?}[\qmark]%%%%%%%%%%%%%%
\ifthenelse{\qmark > 0}{%
\addtocounter{wordCount}{\comma + \qmark}%%%%%%%%%%%%%%
\addtocounter{AllWord}{\comma + \qmark}%%%%%%%%%%%%%%
}{%
\addtocounter{wordCount}{\comma + \qmark + 1}%%%%%%%%%%%%%%
\addtocounter{AllWord}{\comma + \qmark + 1}%%%%%%%%%%%%%%
}%%%%%%%%%%%%%%
\textbf{#2} (#3), ``#1''\\%
}
\begin{document}
\test\par
\exy{one \test}{two \test s}{three \test s}
\end{document}
但产生
Underfull \hbox (badness 10000) in paragraph at lines 29--30
由于位置错误\\
,不应在段落末尾使用。(最好使用\par
)
答案2
我不会使用xstring
。代码中的主要问题是命令\Etc
(非常)脆弱。
我的建议是使用来expl3
计算逗号和问号,通过在它们处拆分文本并计算项目(并减一)。
该参数已完全扩展(但强命令尚未扩展)并被“净化”,因此诸如的命令\textnormal
消失了。
\documentclass[12pt]{report}
\newcommand\test{\textnormal{test}}
\NewDocumentCommand\dispEt{}{\GoudyEt{c}\kern -3pt{\huge\Virgic{c}}.}
\NewDocumentCommand\Etc{}{\textnormal{\dispEt}}
\newcommand\GoudyEt{}% just for testing
\newcommand{\Virgic}{}% just for testing
\newcounter{wordCount}
\newcounter{AllWord}
\ExplSyntaxOn
\NewDocumentCommand{\exy}{m m m}
{
\hsmyers_xyz_exy:nnen { #1 } { #2 } { \text_purify:n { \text_expand:n { #2 } } } { #3 }
}
\int_new:N \l_hsmyers_xyz_comma_int
\int_new:N \l_hsmyers_xyz_qmark_int
\cs_new_protected:Nn \hsmyers_xyz_exy:nnnn
{
\hsmyers_xyz_count:nnN { , } { #3 } \l_hsmyers_xyz_comma_int
\hsmyers_xyz_count:nnN { ? } { #3 } \l_hsmyers_xyz_qmark_int
\int_compare:nTF { \l_hsmyers_xyz_qmark_int > 0 }
{
\addtocounter{wordCount}
{
\int_eval:n { \l_hsmyers_xyz_comma_int + \l_hsmyers_xyz_qmark_int }
}
\addtocounter{AllWord}
{
\int_eval:n { \l_hsmyers_xyz_comma_int + \l_hsmyers_xyz_qmark_int }
}
}{%
\addtocounter{wordCount}
{
\int_eval:n { \l_hsmyers_xyz_comma_int + \l_hsmyers_xyz_qmark_int + 1}
}
\addtocounter{AllWord}
{
\int_eval:n { \l_hsmyers_xyz_comma_int + \l_hsmyers_xyz_qmark_int + 1}
}
}
\textbf{#2}~#4,~``#1''
}
\cs_generate_variant:Nn \hsmyers_xyz_exy:nnnn { nne }
\cs_new_protected:Nn \hsmyers_xyz_count:nnN
{
\seq_set_split:Nnn \l_tmpa_seq { #1 } { #2 }
\int_set:Nn #3 { \seq_count:N \l_tmpa_seq - 1 }
}
\ExplSyntaxOff
\begin{document}
\test\par
\exy{one \Etc}{two \test \Etc{} s}{three \Etc{} s}
wordCount=\the\value{wordCount}
AllWord=\the\value{AllWord}
\exy{one \test}{two, three?}{three \test s}
wordCount=\the\value{wordCount}
AllWord=\the\value{AllWord}
\end{document}