Вложенные условные термины глоссария с использованием Глоссариев \ifglsused в \newglossaryentry

Вложенные условные термины глоссария с использованием Глоссариев \ifglsused в \newglossaryentry

Если я хочу условно расширить запись глоссария, основанную на другом термине глоссария или связанную с ним, я считаю, что условное \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для правильной работы необходимо применять некоторые ограничения.

  1. Если аргумент начинается с \protect, то он отбрасывается и \makefirstucприменяется к остатку. Например, \makefirstuc{\protect\textbf{foo}}то же самое, что и \makefirstuc{\textbf{foo}}.
  2. Аргумент \makefirstucможет начинаться только с текста. Например, \makefirstuc{foo}just does \MakeUppercase foo, который приводит к Foo. Тогда как \makefirstuc{{fo}o}does \MakeUppercase{fo}o, который приводит к FOo.
  3. Если аргумент \makefirstucначинается с управляющей последовательности без аргумента, то предполагается, что эта управляющая последовательность является управляющей последовательностью символов, такой как \aeили , \oи к ней применяется изменение регистра. Например, \makefirstuc{\ae foo}does \MakeUppercase\ae foo, что приводит к Æfoo. Это означает, что

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

    делает \MakeUppercase\foo, что производит FOO.

  4. Если аргумент \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выбирает второй аргумент.

Связанный контент