如果我想有条件地扩展基于或与另一个词汇表术语相关的词汇表条目,我发现条件\ifglsused{}{}{}
语句非常有用。
为了在父术语尚未使用的情况下满足父修改,我会\glsdisp{}{}
确保先决条件被“使用”,但不会按照第一次使用时编程的方式显示。
\ifglsused{TNF}{\glsdisp{TNF}{\TNFalpha}}{\glsdisp{TNF}{tumor necrosis factor--\textalpha~(\TNFalpha)}}
正如下面 MWE 中的项目 所示,这可以正常工作。
有趣的是,当它是子术语本身声明 \newglossaryentry{}
中的 ie的一部分时,这个相同的评估会失败。first={}
梅威瑟:
\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}
更新:我通过创建一个新的词汇表键(指定基础)和新函数解决了这个问题,该函数独立于词汇表条目的创建执行相同的使用和显示逻辑。我基于此的函数模板如下: 在词汇表中创建新字段 newglossaryentry
因此,由于这个问题背后的原因 - 嵌套的词汇表扩展和最少的重复 - 是通过完全不同的方法解决的,我仍然有兴趣了解newglossaryentry
我猜测,这意味着在实际调用它
first={}
之前,以某种方式进行评估\gls{}
,因此没有改变任何有用的布尔值,从而保证了永久的错误评估而不会失败,但如果知道的话就太好了。我的下一个猜测是,这与 \gls{} 的受保护状态有关,或者仅仅与代码的评估顺序有关?
答案1
这里有两个主要问题。
字段扩展
来自用户手册:
当您定义新的词汇表条目时,默认执行扩展,但
name
、description
、descriptionplural
、symbol
和 键除外(这些键都通过 抑制扩展)。symbolplural
sort
\glssetnoexpandfield
(这些例外的原因是为了向后兼容以前将这些信息写入词汇表文件的早期版本。扩展抑制有助于在写入过程中保护脆弱的命令。)
为了实际操作,我们可以使用glossaries
调试命令(仅在记录代码,不在用户手册中)。\showgloname
将显示字段的定义name
,将显示字段\showglofirst
的定义,将显示字段的定义(每种情况下都需要一个参数,即条目标签)。(我已经精简了 MWE。)first
\showglotext
text
\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}
这不会产生任何输出,但它会显示记录中的定义。(在 TeX 的交互模式下运行时,这些命令会中断运行,就像它们是错误消息一样。)以下是记录的相关部分。
first
该条目的字段值TNF
:
> \glo@TNF@first=macro:
->tumor necrosis factor (TNF).
first
该条目的字段值TNFalpha
:
> \glo@TNFalpha@first=macro:
->tumor necrosis factor alpha\protect \nobreakspace {}(TNF--{\textalpha }).
因此这里的\TNFalpha
命令已经扩展,不可破坏的空间也已扩展,~
但\textalpha
由于受到保护所以不会扩展。
name
该条目的字段值TNF
:
> \glo@TNF@name=macro:
->TNF.
name
该条目的字段值TNFalpha
:
> \glo@TNFalpha@name=macro:
->\TNFalpha .
这里\TNFalpha
没有展开,因为这个name
键默认没有展开。
该text
键没有明确使用,因此它从字段中获取其值name
,但在这种情况下会执行扩展。
text
该条目的字段值TNF
:
> \glo@TNF@text=macro:
->TNF.
text
该条目的字段值TNFalpha
:
> \glo@TNFalpha@text=macro:
->TNF--{\textalpha }.
与name
现场不同,\TNFalpha
现已扩大。
因此,如果您在键\ifglsused
内使用first
,则默认情况下将对其进行评估当条目被定义时如果将上面的例子改为,则 的定义TNFalpha
现在为:
\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}
}
然后\showglofirst{TNFalpha}
仍然产生相同的结果:
> \glo@TNFalpha@first=macro:
->tumor necrosis factor alpha\protect \nobreakspace {}(TNF--{\textalpha }).
这是因为当TNFalpha
定义时,TNF
尚未使用,因此其定义扩展为的错误部分(第三个参数)\ifglsused
。
嵌套链接
如果您\glsdisp
向字段添加(或任何类似的命令)first
,则最终会得到嵌套链接。\glsdisp
和\gls
内部都使用相同的命令\@gls@link
来处理超链接并将链接文本包装在 内\glstextformat
。 因此嵌套这些命令可能会导致问题。
最简单的解决方案是关闭first
和firstplural
字段的扩展,\glsdisp
从字段值中删除,只使用来\glsunset
标记TNF
条目已被使用。像这样:
\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}
得出的结果为:
如果你把它们交换一下,你就有
\gls{TNF}. \gls{TNFalpha}.
代替
\gls{TNFalpha}. \gls{TNF}.
那么结果是
编辑:每次定义新条目时都会检查扩展设置,但如果您有一个需要扩展字段的条目,则只需再次打开扩展即可。例如:
\newcommand{\stuff}{foo}
\newglossaryentry{stuff1}{name={\stuff},description={stuff1}}
\renewcommand{\stuff}{bar}
\newglossaryentry{stuff2}{name={\stuff},description={stuff2}}
这种定义在明确地这样做时看起来有点奇怪,但有时它是由内部使用 的命令完成的\newglossaryentry
。在上面的例子中,\stuff
当条目定义为 时需要扩展\stuff
只是一个临时命令,其定义不断变化。如果没有这种情况,那么您可以将所有\glsetnoexpandfield
命令放在开始定义任何条目之前。
大小写转换
首字母大写命令,例如\Gls
使用\makefirstuc
提供的mfirstuc
。此命令确实尝试处理参数可能包含格式化命令的可能性,但由于没有通用的方法来确定命令的语法,特别是哪个参数是文本,哪个是标签,因此\makefirstuc
必须应用一些限制才能正常工作。
- 如果参数以 开头
\protect
,则将其丢弃,并\makefirstuc
应用于余数。例如,\makefirstuc{\protect\textbf{foo}}
与 相同\makefirstuc{\textbf{foo}}
。 - 的参数
\makefirstuc
可以仅以文本开头。例如,\makefirstuc{foo}
执行 执行\MakeUppercase foo
结果为 Foo。而\makefirstuc{{fo}o}
执行\MakeUppercase{fo}o
执行结果为 FOo。 如果的参数
\makefirstuc
以没有参数的控制序列开头,则该控制序列将被视为字符控制序列(例如\ae
或)\o
,并将大小写更改应用于该序列。例如,\makefirstuc{\ae foo}
执行\MakeUppercase\ae foo
which 会导致 Æfoo。这意味着\newcommand{\foo}{foo}\makefirstuc{\foo}
执行
\MakeUppercase\foo
此操作会产生 FOO。如果 的参数
\makefirstuc
以控制序列开头,后跟一个组,则控制序列被视为格式化命令。分组材料被视为文本,并将大小写更改应用于文本。例如,\makefirstuc{\textbf{foo}}
相当于 ,\textbf{\MakeUppercase foo}
其结果是F哦。
没有对 的参数进行扩展,\makefirstuc
因为这可能导致具有单个参数的简单文本块命令扩展为过于复杂而无法解析的内容。
\Gls{TNFalpha}
首次使用(或\Glsfirst{TNFalpha}
)尝试时返回 MWE
\makefirstuc{\ifglsused{TNF}{\TNFalpha}{\glsunset{TNF}tumor necrosis
factor alpha~(\TNFalpha)}}
这属于情况 4(控制序列后跟一个组)。因此,这试图做到
{\ifglsused{\MakeUppercase TNF}{\TNFalpha}{\glsunset{TNF}tumor necrosis
factor alpha~(\TNFalpha)}}
这就是导致错误消息的原因。解决该问题的唯一方法是定义一个命令,其中第一个参数是需要更改大小写的文本。例如:
% \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}
}
由于\TNFalpha
已经以大写字母开头,因此无需担心处理条件\ifnotused
选择第二个参数的情况。