La expansión macro falla de manera extraña

La expansión macro falla de manera extraña

Aquí está mi 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}

Si comenta la línea, \exyfunciona como se esperaba. De lo contrario, los errores comienzan con

[{
    "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
}]

que está más allá de mi macro-fu. ¿Alguien puede ayudar? Cabe señalar que este no es el problema original. Para producir un MWE sin necesidad de comprar fuentes, seguí eliminando hasta que no hubo ningún error, luego volví a agregar para obtener esto. El problema original era:

\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}}

reemplazar \testcon \Etccon resultados similares.

Respuesta1

Tenga en cuenta que siempre debe mostrar los errores TeX en formato de varias líneas, ya que los saltos de línea son vitales para comprender el mensaje, marcancualel comando no está definido

! Undefined control sequence.
\reserved@a ->\@nil 
                    
l.29 ...exy{one \test}{two \test s}{three \test s}
                                                  
?

Utilizó una definición primitiva de TeX, lo que resultó en un comando frágil que se rompe en un contexto de expansión. Si lo usa, \NewDocumentCommandobtendrá \protectedcomandos seguros en tales construcciones.

Esto se ejecuta sin errores.


\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}

pero produce

Underfull \hbox (badness 10000) in paragraph at lines 29--30

Debido a la mala colocación \\que nunca se debe utilizar al final de un párrafo. (Sería mejor usar \par)

Respuesta2

yo no usaríaxstring . El principal problema de su código es que el comando \Etces (muy) frágil.

Mi propuesta es utilizarexpl3 para contar comas y signos de interrogación, dividiendo el texto en ellos y contando los elementos (y restando uno).

El argumento está completamente expandido (pero el comando robusto no) y "purificado", por lo que comandos como \textnormaldesaparecen.

\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}

ingrese la descripción de la imagen aquí

información relacionada