Подпись мешает механизму первого/последующего использования глоссариев

Подпись мешает механизму первого/последующего использования глоссариев

Это дополнительный вопрос по темеГлоссарии в списке рисунков переполнены, где спрашивалось, как glossariesможно использовать первую схему использования пакета с термином глоссария в подписи к рисунку. Я дал ответ, который работает до тех пор, пока пакет captionне загружен.

\documentclass{article}

\usepackage{caption}
\usepackage[colorlinks]{hyperref}
\usepackage{glossaries}

\makeglossaries
\newglossaryentry{acr}{%
  name        = {ACR-name},%
  description = {ACR-description},%
  first       = {ACR-first-description},%
}

\renewcommand{\glsdisplayfirst}[4]{#1 (1) #4}
\renewcommand{\glsdisplay}[4]{#1 (2+) #4}
\begin{document}
% \listoffigures %% even without \listoffigures the problem shows up

\begin{figure}[h]
  \caption[Short title \glshyperlink{acr}]{Long title \gls{acr}}
\end{figure}

\printglossary
\end{document}

Как можно заметить, без captionподписи к рисунку указана первая форма использования записи глоссария, как и требуется, а с captionней — последующая форма использования.

Как мне сохранить его работоспособность во время использования caption?

решение1

LaTeX помещает заголовок во временную царапину \hbox, измеряет ее ширину. Если ширина меньше ширины линии,коробкаповторно используется для набора заголовка. Поэтому \glsвызывается один раз. Однако если ширина заголовка превышает ширину строки, текст заголовка устанавливается дважды, на этот раз как абзац. Затем \glsвызывается дважды, и вы получаете вывод для второй версии элемента глоссария.

Пакет captionделает поведение более предсказуемым. Если опция singlelinecheckустановлена ​​(по умолчанию), то текст подписи всегда устанавливается дважды, первый раз для измерения ширины, чтобы проверить, помещается ли текст в одну строку, а затем текст устанавливается снова для конечного результата. С singlelinecheck=false, измерение отключено, и текст устанавливается только один раз, но центрирование текста подписи теряется.

Обходной путь — поместить результат \gls{acr}во временный контейнер и использовать этот контейнер внутри \caption:

\documentclass{article}

\usepackage{caption}
\usepackage{glossaries}

\newsavebox\glsscratchbox

\makeglossaries
\newglossaryentry{acr}{%
  name        = {ACR-name},%
  description = {ACR-description},%
  first       = {ACR-first-description},%
}

\renewcommand{\glsdisplayfirst}[4]{#1 (1) #4}
\renewcommand{\glsdisplay}[4]{#1 (2+) #4}
\begin{document}
\listoffigures %% even without \listoffigures the problem shows up

\begin{figure}[h]
  \sbox\glsscratchbox{\gls{acr}}
  \caption[Short title \glshyperlink{acr}]{Long title \unhcopy\glsscratchbox}
\end{figure}

\printglossary
\end{document}

(Эта команда \unhcopyиспользуется вместо \usebox(это \copy). Она удаляет внешний \hboxслой и позволяет набирать пробелы так же, как и другие пробелы в строке. В противном случае ( \usebox) пробел внутри повторно используемого блока всегда будет иметь естественную ширину.)

Результат

Решение для \glsв подписи с пакетомcaption

Обновление: добавлено упрощение из комментария Акселя Зоммерфельдта.

Пакет glossariesдолжен запомнить первые использования аббревиатур. Идея состоит в том, чтобы отключить это, если ширина подписи измеряется, но не, если текст подписи набирается окончательно.

Пакет captionнеобходим, так как он отделяет тест от финального шага набора текста. Также он предоставляет макрос \caption@prepareslc, который предшествует измерению и вызывается перед измерением. \glsunsetДля измерения временно отключено.

\documentclass{article}

\usepackage{glossaries}
\usepackage{caption}

\makeatletter
\g@addto@macro\caption@prepareslc{%
  \let\glsunset\@gobble
}
\makeatother

\makeglossaries
\newglossaryentry{acr}{%
  name        = {ACR-name},%
  description = {ACR-description},%
  first       = {ACR-first-description},%
}

\renewcommand{\glsdisplayfirst}[4]{#1 (1) #4}
\renewcommand{\glsdisplay}[4]{#1 (2+) #4}
\begin{document}
\listoffigures

\begin{figure}[h]
  \caption[Short title \glshyperlink{acr}]{Long title \gls{acr}}
\end{figure}

\printglossary
\end{document}

Уточнение

Если \gls{acr}используется, то для акронима устанавливается глобальный флаг, acrчтобы запомнить состояние использования акронима. Таким образом, последующие вызовы могут использовать более короткую форму. Предыдущее решение пропускало установку состояния, если измеряется только текст подписи. Таким образом, состояние не изменилось, когда текст подписи был окончательно установлен.

Однако есть ситуация, которая проскальзывает. Текст заголовка содержит \glsодну и ту же аббревиатуру несколько раз, включая ее первое использование. Тогда предыдущее решение будет содержать первую форму использования аббревиатуры для использований аббревиатуры на этапе измерения, поскольку настройка состояния там отключена.

Это исправлено путем разрешения изменений нормального состояния акронимов на этапе измерения, но с сохранением первых использований. Затем они сбрасываются перед окончательным набором текста подписи.

Дополнительные замечания:

  • \if@capmeasureВводится переключатель . Обычно он установлен на \iffalse. Когда проверяется ширина текста внутри \caption, то он устанавливается на \iftrue.
  • Пакет captionнеобходим, поскольку он отделяет тест от финального шага набора текста. Также он предоставляет макрос \caption@prepareslc, который предшествует измерению. Оба выполняются в одной и той же локальной группе. Поэтому достаточно добавить \@capmeasurefalseв \caption@prepareslc. Переключатель автоматически сбрасывается после окончания группы.
  • После измерения состояние первых использований аббревиатуры сбрасывается.
  • Пакет glossaries' \glsunsetпропатчен для соблюдения настроек \if@capmeasureи запоминания первых использований аббревиатур.

Полный пример:

\documentclass{article}

\usepackage{glossaries}
\usepackage{caption}

\makeatletter
\newif\if@capmeasure
\g@addto@macro\caption@prepareslc{%
  \global\let\after@capmeasure\@empty
  \aftergroup\after@capmeasure
  \@capmeasuretrue
}
\CheckCommand*{\glsunset}[1]{%
  \glsdoifexists{#1}{%
    \expandafter \global \csname glo@#1@flagtrue\endcsname   
  }%
}
\renewcommand*{\glsunset}[1]{%
  \glsdoifexists{#1}{%
    \if@capmeasure
      \expandafter\ifx\csname ifglo@#1@flag\expandafter\endcsname
      \csname iftrue\endcsname
      \else 
        % first use
        \g@addto@macro\after@capmeasure{\glsreset{#1}}%
      \fi
    \fi
    \global\csname glo@#1@flagtrue\endcsname
  }%
}
\makeatother

\makeglossaries
\newglossaryentry{acr}{%
  name        = {ACR-name},%
  description = {ACR-description},%
  first       = {ACR-first-long-description},%
}

\renewcommand{\glsdisplayfirst}[4]{#1\textsuperscript{(1)}#4}
\renewcommand{\glsdisplay}[4]{#1\textsuperscript{(2+)}#4}
\begin{document}
\listoffigures

\begin{figure}[h]
  \caption[Short title \glshyperlink{acr}]%
  {Long title \textit{\gls{acr}} and \gls{acr}}
\end{figure}

\printglossary
\end{document}

Результат с уточнением

решение2

Используя glossaries-extraу вас есть две альтернативы. Смотритездесь.

  1. Вы всегда можете вызвать \glsxtrshortвнутри подписей. Они не будут вызывать первое использование по понятным причинам. У вас также есть параметры noindexи hyper=false, если вы хотите также избегать ссылок и не хотите, чтобы эти записи отображались в списке глоссария, созданном с помощью \printglossaries. Что приводит нас к:
  2. Предсказание этого использования glossaries-extraвключает семейство \glsfmtshortкоманд. Они идентичны соответствующим \glsxtrshort[noindex,hyper=false]командам. Таким образом, у вас есть несколько похожих команд, охватывающих каждую из форм единственного и множественного числа, кратких, длинных и полных форм, а также строчные, заглавные первые буквы и полные заглавные формы.

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