Если я хочу условно расширить запись глоссария, основанную на другом термине глоссария или связанную с ним, я считаю, что условное \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
покажет определение поля first
и \showglotext
покажет определение text
поля (в каждом случае требуется один аргумент, и это метка записи). (Я сократил 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}
Это не создает никаких выходных данных, но показывает определения в расшифровке. (При запуске в интерактивном режиме 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}
just does\MakeUppercase foo
, который приводит к Foo. Тогда как\makefirstuc{{fo}o}
does\MakeUppercase{fo}o
, который приводит к FOo. Если аргумент
\makefirstuc
начинается с управляющей последовательности без аргумента, то предполагается, что эта управляющая последовательность является управляющей последовательностью символов, такой как\ae
или ,\o
и к ней применяется изменение регистра. Например,\makefirstuc{\ae foo}
does\MakeUppercase\ae foo
, что приводит к Æfoo. Это означает, что\newcommand{\foo}{foo}\makefirstuc{\foo}
делает
\MakeUppercase\foo
, что производит FOO.Если аргумент
\makefirstuc
начинается с управляющей последовательности, за которой следует группа, то управляющая последовательность считается командой форматирования. Сгруппированный материал считается текстом, и к нему применяется изменение регистра. Например,\makefirstuc{\textbf{foo}}
эквивалентно тому\textbf{\MakeUppercase foo}
, что приводит кФооо.
Расширение аргумента не выполняется, \makefirstuc
поскольку это может привести к тому, что простые команды текстового блока с одним аргументом будут расширены до чего-то слишком сложного для анализа.
Возвращаясь к MWE, \Gls{TNFalpha}
при первом использовании (или \Glsfirst{TNFalpha}
) попытках
\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
выбирает второй аргумент.