Términos de glosario condicional anidados usando glosarios \ifglused en \newglossaryentry

Términos de glosario condicional anidados usando glosarios \ifglused en \newglossaryentry

Si quiero ampliar condicionalmente una entrada del glosario basada en otro término del glosario o relacionada con él, encuentro que la \ifglsused{}{}{}declaración condicional es muy útil.

Para satisfacer las modificaciones de los padres en el caso de que el término principal aún no se haya usado, lo uso \glsdisp{}{}para asegurarme de que el requisito previo se "use" pero no se muestre como programado en el primer uso.

Como se demuestra con \ifglsused{TNF}{\glsdisp{TNF}{\TNFalpha}}{\glsdisp{TNF}{tumor necrosis factor--\textalpha~(\TNFalpha)}}el elemento del MWE a continuación, esto funciona bien.

Curiosamente, esta evaluación idéntica falla cuando forma parte del \newglossaryentry{}ie dentro de la first={}declaración del propio término secundario.

MWE:

\documentclass{article}
\usepackage[utf8]{inputenc}

\setlength\parindent{0pt}

%=========================================================================================================================================
% PACKAGES REQUIRED FOR GLOSSARIES
%=========================================================================================================================================

% Glossaries must be loaded before amsmath as per details in the following forum answer
% https://tex.stackexchange.com/questions/85696/what-causes-this-strange-interaction-between--and-amsmath
\usepackage[nogroupskip,toc,acronym]{glossaries} % must come after href   
\usepackage{scrwfile}%http://www.dickimaw-books.com/cgi-bin/faq.cgi?action=view&categorylabel=glossaries#glsnewwriteexceeded
\usepackage{siunitx,microtype,textcomp,textgreek}
\usepackage{etoolbox}
\makeglossaries

\newglossaryentry{TNF}{ 
    type={acronym}, 
    sort={tumor necrosis factor},  
    name={TNF}, 
    short={TNF}, 
    long={tumor necrosis factor}, 
    first={tumor necrosis factor (TNF)}, 
    description={tumor necrosis factor}     
}

\newcommand{\TNFalpha}{TNF--{\textalpha}}
\newglossaryentry{TNFalpha}{ 
    type={acronym}, 
    sort={tumor necrosis factor alpha},  
    name={TNF--{\textalpha}}, 
    short={TNF--{\textalpha}}, 
    long={tumor necrosis factor alpha}, 
    first={\ifglsused{TNF}{\glsdisp{TNF}{\TNFalpha}}{\glsdisp{TNF}{tumor necrosis factor--\textalpha~(\TNFalpha)}}}, 
    description={tumor necrosis factor alpha}
}

\begin{document}

    \begin{itemize}
        %\item \gls{TNFalpha}
        \item \gls{TNF}
        \item \gls{TNFalpha}
        \item \glsentryfirst{TNFalpha}
        \item \ifglsused{TNF}{\glsdisp{TNF}{\TNFalpha}}{\glsdisp{TNF}{tumor necrosis factor--\textalpha~(\TNFalpha)}}
    \end{itemize}

\end{document} 

Actualización: resolví este problema creando una nueva clave de glosario (que especifica la base) y una nueva función que realiza el mismo uso y muestra la lógica independientemente de la creación de la entrada del glosario. La plantilla de función en la que basé esto está aquí: Crear nuevos campos en glosarios newglossaryentry

Entonces, dado que la razón detrás de esta pregunta (expansiones de glosario anidadas con duplicación mínima) se resuelve mediante un enfoque completamente diferente, todavía me interesaría conocer los matices denewglossaryentry

  • Supongo que esto significa que de alguna manera first={}se está evaluando antes \gls{}de llamarlo y, por lo tanto, no se ha cambiado ningún uso booleano, lo que garantiza una evaluación falsa perpetua sin fallar, pero sería genial saberlo.

  • Mi siguiente suposición sería que esto tiene algo que ver con el estado protegido de \gls{} o incluso simplemente con el orden en que se evalúa el código.

Respuesta1

Hay dos cuestiones principales aquí.

Expansión de campo

Desde elmanual de usuario:

Cuando define nuevas entradas del glosario, la expansión se realiza de forma predeterminada, excepto las teclas name, description, descriptionplural, symboly (todas estas teclas tienen la expansión suprimida mediante ).symbolpluralsort\glssetnoexpandfield

(El motivo de estas excepciones es la compatibilidad con versiones anteriores que solían escribir esa información en el archivo del glosario. La supresión de la expansión ayudó a proteger comandos frágiles en el proceso de escritura).

Para ver esto en acción, podemos usar los glossariescomandos de depuración (solo se describen en elcódigo documentado, no en el manual del usuario). \showglonamemostrará la definición del namecampo, \showglofirstmostrará la definición del firstcampo y \showglotextmostrará la definición del textcampo (se requiere un argumento en cada caso, y esa es la etiqueta de entrada). (He recortado el MWE).

\documentclass{article}

\usepackage{textgreek}
\usepackage[nogroupskip,toc,acronym]{glossaries}
\makeglossaries

\newglossaryentry{TNF}{ 
  type={acronym}, 
  sort={tumor necrosis factor},  
  name={TNF}, 
  first={tumor necrosis factor (TNF)}, 
  description={tumor necrosis factor}
}   

\newcommand{\TNFalpha}{TNF--{\textalpha}}
\newglossaryentry{TNFalpha}{
    type={acronym},
    sort={tumor necrosis factor alpha},
    name={\TNFalpha},
    first={tumor necrosis factor alpha~(\TNFalpha)},   
    description={tumor necrosis factor alpha}
}

\begin{document}
\showglofirst{TNF}
\showglofirst{TNFalpha}

\showgloname{TNF}
\showgloname{TNFalpha}

\showglotext{TNF}
\showglotext{TNFalpha}

\end{document}

Esto no crea ningún resultado, pero muestra las definiciones en la transcripción. (Cuando se ejecutan en el modo interactivo de TeX, estos comandos interrumpirán la ejecución como si fueran mensajes de error). A continuación se muestran las partes relevantes de la transcripción.

El valor del firstcampo para la TNFentrada:

> \glo@TNF@first=macro:
->tumor necrosis factor (TNF).

El valor del firstcampo para la TNFalphaentrada:

> \glo@TNFalpha@first=macro:
->tumor necrosis factor alpha\protect \nobreakspace  {}(TNF--{\textalpha }).

Entonces aquí el \TNFalphacomando se ha expandido y también el espacio irrompible, ~pero \textalphano se expande porque está protegido.

El valor del namecampo para la TNFentrada:

> \glo@TNF@name=macro:
->TNF.

El valor del namecampo para la TNFalphaentrada:

> \glo@TNFalpha@name=macro:
->\TNFalpha .

Aquí \TNFalphano se ha expandido porque la nameclave no está expandida de forma predeterminada.

La textclave no se usó explícitamente, por lo que tomó su valor del namecampo, pero en este caso se realiza la expansión.

El valor del textcampo para la TNFentrada:

> \glo@TNF@text=macro:
->TNF.

El valor del textcampo para la TNFalphaentrada:

> \glo@TNFalpha@text=macro:
->TNF--{\textalpha }.

A diferencia del namecampo, \TNFalphaahora se ha ampliado.

Por lo tanto, si usa \ifglsuseddentro de la firstclave, por defecto será evaluadacuando la entrada está definida. Si se cambia el ejemplo anterior para que la definición de TNFalphasea ahora:

\newglossaryentry{TNFalpha}{
    type={acronym},
    sort={tumor necrosis factor alpha},
    name={\TNFalpha}, 
    first={\ifglsused{TNF}{\TNFalpha}{tumor necrosis factor alpha~(\TNFalpha)}}, 
    description={tumor necrosis factor alpha}
}

Entonces \showglofirst{TNFalpha}todavía produce el mismo resultado:

> \glo@TNFalpha@first=macro:
->tumor necrosis factor alpha\protect \nobreakspace  {}(TNF--{\textalpha }).

Esto se debe a que cuando TNFalphase define TNFno se ha utilizado, por lo que la definición se expande a la parte falsa (tercer argumento) de \ifglsused.

Enlaces anidados

Si agrega \glsdisp(o cualquier comando similar) al firstcampo, terminará con enlaces anidados. Ambos \glsdispe \glsinternamente usan el mismo comando \@gls@linkpara manejar el hipervínculo y envolver el texto del vínculo dentro \glstextformat. Entonces anidar estos comandos puede causar problemas.

La solución más sencilla es desactivar la expansión de los campos firsty firstplural, eliminar \glsdispdel valor del campo y simplemente utilizarla \glsunsetpara marcar la TNFentrada como utilizada. Como esto:

\documentclass{article}

\usepackage{textgreek}
\usepackage[nogroupskip,toc,acronym]{glossaries}
\makeglossaries

\newglossaryentry{TNF}{ 
  type={acronym}, 
  sort={tumor necrosis factor},  
  name={TNF}, 
  first={tumor necrosis factor (TNF)}, 
  description={tumor necrosis factor}
}   

\glssetnoexpandfield{first}
\glssetnoexpandfield{firstpl}

\newcommand{\TNFalpha}{TNF--{\textalpha}}
\newglossaryentry{TNFalpha}{
    type={acronym},
    sort={tumor necrosis factor alpha},
    name={\TNFalpha}, 
    first={\ifglsused{TNF}{\TNFalpha}{\glsunset{TNF}tumor necrosis factor alpha~(\TNFalpha)}},
    description={tumor necrosis factor alpha}
}

\begin{document}
\gls{TNFalpha}. \gls{TNF}.

\end{document} 

Esto produce:

factor de necrosis tumoral alfa (TNF-alfa). TNF.

Si los intercambias para tener

\gls{TNF}. \gls{TNFalpha}.

en lugar de

\gls{TNFalpha}. \gls{TNF}.

entonces el resultado es

factor de necrosis tumoral (TNF). TNF-alfa.

Editar:La configuración de expansión se verifica cada vez que se define una nueva entrada, pero solo necesita activar la expansión nuevamente si tiene una entrada cuyos campos necesitan expandirse. Por ejemplo:

\newcommand{\stuff}{foo}
\newglossaryentry{stuff1}{name={\stuff},description={stuff1}}
\renewcommand{\stuff}{bar}
\newglossaryentry{stuff2}{name={\stuff},description={stuff2}}

Este tipo de definición parece un poco extraño cuando se hace explícitamente de esta manera, pero a veces se realiza mediante comandos que usan internamente \newglossaryentry. En el ejemplo anterior, \stuffes necesario expandirlo cuando la entrada se define ya que \stuffes solo un comando temporal cuya definición sigue cambiando. Si no tiene esta situación, puede simplemente poner todos sus \glsetnoexpandfieldcomandos antes de comenzar a definir cualquiera de sus entradas.

Cambio de caso

Los comandos en mayúscula con la primera letra, como \Glsel uso \makefirstucproporcionado pormfirstuc. Este comando intenta abordar la posibilidad de que el argumento pueda contener un comando de formato, pero debido a que no existe una forma genérica de determinar la sintaxis de un comando, específicamente qué argumento es texto y cuál es una etiqueta, \makefirstucse deben aplicar algunas restricciones para para funcionar correctamente.

  1. Si el argumento comienza con \protect, se descarta y \makefirstucse aplica al resto. Por ejemplo, \makefirstuc{\protect\textbf{foo}}es lo mismo que \makefirstuc{\textbf{foo}}.
  2. El argumento de \makefirstucpuede comenzar solo con texto. Por ejemplo, \makefirstuc{foo}simplemente hace \MakeUppercase foolo que resulta en Foo. Mientras que \makefirstuc{{fo}o}lo \MakeUppercase{fo}oque resulta en FOo.
  3. Si el argumento de \makefirstuccomienza con una secuencia de control sin argumento, se supone que esa secuencia de control es una secuencia de control de caracteres como \aeo \oy se aplica el cambio de caso a eso. Por ejemplo, \makefirstuc{\ae foo}lo \MakeUppercase\ae fooque resulta en Æfoo. Esto significa que

    \newcommand{\foo}{foo}\makefirstuc{\foo}
    

    hace \MakeUppercase\foolo que produce FOO.

  4. Si el argumento de \makefirstuccomienza con una secuencia de control seguida de un grupo, se supone que la secuencia de control es un comando de formato. Se supone que el material agrupado es texto y se le aplica el cambio de mayúsculas y minúsculas. Por ejemplo, \makefirstuc{\textbf{foo}}es equivalente a \textbf{\MakeUppercase foo}lo que resulta enFoh.

No se realiza ninguna expansión en el argumento de \makefirstucya que esto podría causar que comandos simples de bloques de texto con un solo argumento se expandan hasta convertirse en algo demasiado complicado de analizar.

Regreso al MWE, \Gls{TNFalpha}en el primer (o \Glsfirst{TNFalpha}) intento de uso

\makefirstuc{\ifglsused{TNF}{\TNFalpha}{\glsunset{TNF}tumor necrosis
factor alpha~(\TNFalpha)}}

Esto cae en el caso 4 (secuencia de control seguida por un grupo). Entonces esto intenta hacer

{\ifglsused{\MakeUppercase TNF}{\TNFalpha}{\glsunset{TNF}tumor necrosis 
factor alpha~(\TNFalpha)}}

cuál es la causa de su mensaje de error. La única forma de resolver el problema es definir un comando donde el primer argumento sea el texto que requiere el cambio de mayúsculas y minúsculas. Por ejemplo:

% \ifnotused{not used}{used}{label}
\newcommand*{\ifnotused}[3]{%
  \ifglsused{#3}{#2}{\glsunset{#3}#1}%
}

\newcommand{\TNFalpha}{TNF--{\textalpha}}
\newglossaryentry{TNFalpha}{
    type={acronym},
    sort={tumor necrosis factor alpha},
    name={\TNFalpha}, 
    first={\ifnotused{tumor necrosis factor alpha~(\TNFalpha)}{\TNFalpha}{TNF}},
    description={tumor necrosis factor alpha}
}

Dado \TNFalphaque ya comienza con mayúscula, no hay necesidad de preocuparse por lidiar con el caso en el que el condicional \ifnotusedselecciona el segundo argumento.

información relacionada