![Termos de glossário condicional aninhados usando glossários \ifglsused em \newglossaryentry](https://rvso.com/image/305883/Termos%20de%20gloss%C3%A1rio%20condicional%20aninhados%20usando%20gloss%C3%A1rios%20%5Cifglsused%20em%20%5Cnewglossaryentry.png)
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
Quando você define novas entradas de glossário, a expansão é executada por padrão, exceto para as chaves
name
,description
,descriptionplural
,symbol
e (todas essas chaves têm expansão suprimida por ).symbolplural
sort
\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 glossaries
comandos de depuração (descritos apenas nocódigo documentado, não no manual do usuário). \showgloname
mostrará a definição do name
campo, \showglofirst
mostrará a definição do first
campo e \showglotext
mostrará a definição do text
campo (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 first
campo para a TNF
entrada:
> \glo@TNF@first=macro:
->tumor necrosis factor (TNF).
O valor do first
campo para a TNFalpha
entrada:
> \glo@TNFalpha@first=macro:
->tumor necrosis factor alpha\protect \nobreakspace {}(TNF--{\textalpha }).
Então aqui o \TNFalpha
comando foi expandido e o espaço inquebrável também, ~
mas \textalpha
não é expandido porque está protegido.
O valor do name
campo para a TNF
entrada:
> \glo@TNF@name=macro:
->TNF.
O valor do name
campo para a TNFalpha
entrada:
> \glo@TNFalpha@name=macro:
->\TNFalpha .
Aqui \TNFalpha
não foi expandido porque a name
chave não é expandida por padrão.
A text
chave não foi usada explicitamente, então ela pegou seu valor no name
campo, mas neste caso a expansão é executada.
O valor do text
campo para a TNF
entrada:
> \glo@TNF@text=macro:
->TNF.
O valor do text
campo para a TNFalpha
entrada:
> \glo@TNFalpha@text=macro:
->TNF--{\textalpha }.
Ao contrário do name
campo, \TNFalpha
agora foi ampliado.
Portanto, se você usar \ifglsused
dentro da first
chave, por padrão ela será avaliadaquando a entrada é definida. Se o exemplo acima for alterado para que a definição TNFalpha
seja 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, TNF
nã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 first
campo, terá links aninhados. Ambos \glsdisp
e \gls
internamente usam o mesmo comando \@gls@link
para 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 first
e firstplural
, retirar \glsdisp
o valor do campo e apenas usar \glsunset
para marcar a TNF
entrada 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:
Se você trocá-los para que você tenha
\gls{TNF}. \gls{TNFalpha}.
em vez de
\gls{TNFalpha}. \gls{TNF}.
então o resultado é
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, \stuff
precisa 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 \glsetnoexpandfield
comandos antes de começar a definir qualquer uma das suas entradas.
Mudança de caso
Os comandos de maiúsculas da primeira letra, como \Gls
o uso \makefirstuc
fornecido 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.
- Se o argumento começar com
\protect
, isso será descartado e\makefirstuc
aplicado ao restante. Por exemplo,\makefirstuc{\protect\textbf{foo}}
é o mesmo que\makefirstuc{\textbf{foo}}
. - O argumento de
\makefirstuc
pode começar apenas com texto. Por exemplo,\makefirstuc{foo}
apenas faz\MakeUppercase foo
o que resulta em Foo. Considerando\makefirstuc{{fo}o}
que does\MakeUppercase{fo}o
which resulta em FOo. Se o argumento de
\makefirstuc
começar com uma sequência de controle sem argumento, essa sequência de controle será considerada uma sequência de controle de caracteres, como\ae
ou,\o
e a mudança de maiúsculas e minúsculas será aplicada a ela. Por exemplo,\makefirstuc{\ae foo}
does\MakeUppercase\ae foo
which resulta em Æfoo. Isso significa que\newcommand{\foo}{foo}\makefirstuc{\foo}
faz
\MakeUppercase\foo
o que produz FOO.Se o argumento de
\makefirstuc
começ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, \makefirstuc
pois 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 \TNFalpha
já começa com maiúscula, não há necessidade de se preocupar em lidar com o caso quando a condicional in \ifnotused
seleciona o segundo argumento.