Termos de glossário condicional aninhados usando glossários \ifglsused em \newglossaryentry

Termos de glossário condicional aninhados usando glossários \ifglsused em \newglossaryentry

Se eu quiser expandir condicionalmente uma entrada do glossário com base ou relacionada a outro termo do glossário, acho que a \ifglsused{}{}{}declaração condicional é muito útil.

Para satisfazer as modificações dos pais no caso em que o termo pai ainda não tenha sido usado, eu uso \glsdisp{}{}para garantir que o pré-requisito seja 'usado', mas não seja exibido conforme programado no primeiro uso.

Conforme demonstrado no \ifglsused{TNF}{\glsdisp{TNF}{\TNFalpha}}{\glsdisp{TNF}{tumor necrosis factor--\textalpha~(\TNFalpha)}}item do MWE abaixo, isso funciona bem.

Curiosamente, esta avaliação idêntica falha quando faz parte do \newglossaryentry{}ie dentro da first={}declaração do próprio termo filho.

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} 

Atualização: resolvi esse problema criando uma nova chave de glossário (que especifica a base) e uma nova função que executa a mesma lógica de uso e exibição independentemente da criação da entrada do glossário. O modelo de função no qual me baseei está aqui: Crie novos campos em glossários newglossaryentry

Portanto, uma vez que a razão por trás desta questão - expansões de glossário aninhadas com duplicação mínima - é resolvida através de uma abordagem completamente diferente, eu ainda estaria interessado em aprender sobre as nuances denewglossaryentry

  • Estou supondo que isso significa que de alguma forma first={}está sendo avaliado antes de \gls{}realmente chamá-lo e, portanto, nenhum uso do booleano foi alterado, garantindo assim uma avaliação falsa perpétua sem falhar, mas seria ótimo saber.

  • Meu próximo palpite seria que isso tem algo a ver com o status protegido do \gls{} ou mesmo apenas com a ordem em que o código é avaliado.

Responder1

Existem duas questões principais aqui.

Expansão de campo

Demanual do usuário:

Quando você define novas entradas de glossário, a expansão é executada por padrão, exceto para as chaves name, description, descriptionplural, symbole (todas essas chaves têm expansão suprimida por ).symbolpluralsort\glssetnoexpandfield

(O motivo dessas exceções é a compatibilidade com versões anteriores que costumavam gravar essas informações no arquivo de glossário. A supressão de expansão ajudou a proteger comandos frágeis no processo de gravação.)

Para ver isso em ação, podemos usar os glossariescomandos de depuração (descritos apenas nocódigo documentado, não no manual do usuário). \showglonamemostrará a definição do namecampo, \showglofirstmostrará a definição do firstcampo e \showglotextmostrará a definição do textcampo (um argumento necessário em cada caso, e esse é o rótulo de entrada). (Eu reduzi o 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}

Isso não cria nenhuma saída, mas mostra as definições na transcrição. (Quando executados no modo interativo do TeX, esses comandos interromperão a execução como se fossem mensagens de erro.) Abaixo estão as partes relevantes da transcrição.

O valor do firstcampo para a TNFentrada:

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

O valor do firstcampo para a TNFalphaentrada:

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

Então aqui o \TNFalphacomando foi expandido e o espaço inquebrável também, ~mas \textalphanão é expandido porque está protegido.

O valor do namecampo para a TNFentrada:

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

O valor do namecampo para a TNFalphaentrada:

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

Aqui \TNFalphanão foi expandido porque a namechave não é expandida por padrão.

A textchave não foi usada explicitamente, então ela pegou seu valor no namecampo, mas neste caso a expansão é executada.

O valor do textcampo para a TNFentrada:

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

O valor do textcampo para a TNFalphaentrada:

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

Ao contrário do namecampo, \TNFalphaagora foi ampliado.

Portanto, se você usar \ifglsuseddentro da firstchave, por padrão ela será avaliadaquando a entrada é definida. Se o exemplo acima for alterado para que a definição TNFalphaseja agora:

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

Então \showglofirst{TNFalpha}ainda produz o mesmo resultado:

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

Isso ocorre porque quando TNFalphaé definido, TNFnão foi usado, então sua definição se expande para a parte falsa (terceiro argumento) de \ifglsused.

Links aninhados

Se você adicionar \glsdisp(ou qualquer comando semelhante) ao firstcampo, terá links aninhados. Ambos \glsdispe \glsinternamente usam o mesmo comando \@gls@linkpara lidar com o hiperlink e agrupar o texto do link dentro de \glstextformat. Portanto, aninhar esses comandos pode causar problemas.

A solução mais simples é desligar a expansão dos campos firste firstplural, retirar \glsdispo valor do campo e apenas usar \glsunsetpara marcar a TNFentrada como tendo sido utilizada. Assim:

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

Isso produz:

fator de necrose tumoral alfa (TNF-alfa). TNF.

Se você trocá-los para que você tenha

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

em vez de

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

então o resultado é

fator de necrose tumoral (TNF). TNF-alfa.

Editar:As configurações de expansão são verificadas sempre que uma nova entrada é definida, mas você só precisa ativar a expansão novamente se tiver uma entrada que precise ter os campos expandidos. Por exemplo:

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

Esse tipo de definição parece um pouco estranho quando feito explicitamente assim, mas às vezes é feito por comandos que usam internamente o \newglossaryentry. No exemplo acima, \stuffprecisa ser expandido quando a entrada é definida, pois \stuffé apenas um comando temporário cuja definição está sempre mudando. Se você não tiver essa situação, basta colocar todos os seus \glsetnoexpandfieldcomandos antes de começar a definir qualquer uma das suas entradas.

Mudança de caso

Os comandos de maiúsculas da primeira letra, como \Glso uso \makefirstucfornecido pormfirstuc. Este comando tenta lidar com a possibilidade de o argumento conter um comando de formatação, mas como não há uma maneira genérica de determinar a sintaxe de um comando, especificamente qual argumento é texto e qual é um rótulo, \makefirstucé necessário aplicar algumas restrições para para funcionar corretamente.

  1. Se o argumento começar com \protect, isso será descartado e \makefirstucaplicado ao restante. Por exemplo, \makefirstuc{\protect\textbf{foo}}é o mesmo que \makefirstuc{\textbf{foo}}.
  2. O argumento de \makefirstucpode começar apenas com texto. Por exemplo, \makefirstuc{foo}apenas faz \MakeUppercase fooo que resulta em Foo. Considerando \makefirstuc{{fo}o}que does \MakeUppercase{fo}owhich resulta em FOo.
  3. Se o argumento de \makefirstuccomeçar com uma sequência de controle sem argumento, essa sequência de controle será considerada uma sequência de controle de caracteres, como \aeou, \oe a mudança de maiúsculas e minúsculas será aplicada a ela. Por exemplo, \makefirstuc{\ae foo}does \MakeUppercase\ae foowhich resulta em Æfoo. Isso significa que

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

    faz \MakeUppercase\fooo que produz FOO.

  4. Se o argumento de \makefirstuccomeçar com uma sequência de controle seguida por um grupo, a sequência de controle será considerada um comando de formatação. O material agrupado é considerado texto e a alteração de maiúsculas e minúsculas é aplicada a ele. Por exemplo, \makefirstuc{\textbf{foo}}é equivalente a \textbf{\MakeUppercase foo}que resulta emFah.

Nenhuma expansão é executada no argumento de, \makefirstucpois isso poderia fazer com que comandos simples de bloco de texto com um único argumento fossem expandidos para algo muito complicado de analisar.

Retornando ao MWE, \Gls{TNFalpha}na primeira utilização (ou \Glsfirst{TNFalpha}) tentativas

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

Isto se enquadra no caso 4 (sequência de controle seguida por um grupo). Então isso tenta fazer

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

qual é a causa da sua mensagem de erro. A única maneira de resolver o problema é definir um comando onde o primeiro argumento seja o texto que requer a mudança de maiúsculas e minúsculas. Por exemplo:

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

Como \TNFalphajá começa com maiúscula, não há necessidade de se preocupar em lidar com o caso quando a condicional in \ifnotusedseleciona o segundo argumento.

informação relacionada