Сделать команду надежной (нерушимой)

Сделать команду надежной (нерушимой)

Если вы определите \bletterс помощью \DeclareRobustCommand\bletter[1]{\textbf{#1}}, то это будет работать даже в командах раздела. Но если вы захотите использовать его в команде \edefили \xdef, \bletterто это будет сломано (кроме случаев, когда вы определите \let\protect\noexpand). Это означает:

\xdef\boldyletter{\bletter{y}}выдаст сообщение об ошибке.

Есть ли команда, определяющая всегда непреодолимые команды?

решение1

Вы можете использовать

\NewDocumentCommand\bletter{m}{\textbf{#1}} 

что создает определение e-tex \protected, которое не расширяется в edef.

Но вы никогда не должны использовать \xdefLaTeX для неизвестных входных данных, используйте \protected@xdefтогда надежные команды LaTeX будут защищены.

решение2

Просто используйте \protected\defпримитив для объявления вашего \bletterмакроса:

\protected\def\bletter#1{\textbf{#1}}

Макросы \protectedне раскрываются во время \edef, \xdef, \write, \messageи т.д.

решение3

Извините, что отвечаю на свой собственный вопрос, но я понятия не имею, как поделиться своим решением с сообществом.

\def\RJDeclareRobustCommand#1% #1 name of new command, #2 same instructions as \newcommand
 {%
  \gdef#1%
   {%
    \begingroup%
     \let\relax\aftergroup% this has to be redefined before processing \csname @\string#1\endcsname
     \ifx\aftergroup\relax% this is false in expandations
      \expandafter\aftergroup\csname RJ@\expandafter\@gobble\string#1\endcsname%
     \else%  \expandafter\aftergroup\expandafter\noexpand\csname\expandafter\@gobble\string#1@RJ\endcsname%
     \fi%
    \endgroup%
   }%
  \expandafter\gdef\csname\expandafter\@gobble\string#1@RJ\endcsname%
   {%
    \begingroup%
     \let\relax\aftergroup% this has to be redefined before processing \csname @\string#1\endcsname
     \ifx\aftergroup\relax% this is false in expandations
      \expandafter\aftergroup\csname RJ@\expandafter\@gobble\string#1\endcsname%
     \else%
      \expandafter\aftergroup\expandafter\aftergroup\expandafter\aftergroup%
       \expandafter\noexpand\csname\expandafter\@gobble\string#1@RJ\endcsname%
     \fi%
    \endgroup%
   }%
%  read the instructions (see \new@command)
  \expandafter\new@command\csname RJ@\expandafter\@gobble\string#1\endcsname%
 }%
%

\RJDeclareRobustCommand\bletter[1]{\textbf{#1}}будет прочным.

\xdef\boldyletter{\bletter{y}}отлично работает даже в команде \xdef\boldxyletter{x\boldyletter}}.

решение4

Большое спасибо за очень полезные ответы. Они также были для меня вызовом, который я с радостью принял.

Для использования новой команды в заголовке главы необходимо, помимо прочего, добавить и переопределить команду в \pdfstringdef. Это не было учтено в моем старом коде. При добавлении этого требования мне также удалось оптимизировать код.

Ниже приведен тестовый пример с новым кодом. Новые команды, а не их аргументы, будут игнорироваться в закладках.

\documentclass[a4paper,12pt]{report}
\RequirePackage[pdftex,colorlinks,linkcolor=blue,%
                urlcolor=blue,bookmarksnumbered]{hyperref}
%
\makeatletter
%
\let\RJ@aftergroup\aftergroup%
\let\RJ@begingroup\begingroup%
\let\RJ@endgroup\endgroup%
\let\RJ@let\let%
%
\@ifundefined{pdfstringdefPreHook}{}%
 {%
  \gdef\Addpdfstringdef#1%
   {%
    \global\@temptokena\expandafter%
     {\pdfstringdefPreHook#1}%
    \xdef\pdfstringdefPreHook{\the\@temptokena}%
   }%     
%     
  \Addpdfstringdef%
   {%
    \let\RJ@aftergroup\@empty%
    \let\RJ@begingroup\@empty%
    \let\RJ@endgroup\@empty%
    \let\RJ@let\@empty%%
   }%  
 }% 
%
\def\RJ@DRCentry#1%
 {%
  \RJ@begingroup%
   \RJ@let\relax\RJ@aftergroup%
   \ifx\RJ@aftergroup\relax% 
    \expandafter\RJ@aftergroup\csname RJ@\expandafter\@gobble\string#1\endcsname%
   \else%
    \expandafter\noexpand\csname RJ\expandafter\@gobble\string#1JR\endcsname%
   \fi%
  \RJ@endgroup%
 }%
%
\def\RJ@DeclareRobustCommand#1% #1 name of new command, #2 same instructions as \newcommand
 {%
  \gdef#1%
   {%
    \ifx\RJ@aftergroup\@empty%
    \else%
     \expandafter\RJ@DRCentry\expandafter#1%  
    \fi%
   }%
%
  \expandafter\gdef\csname RJ\expandafter\@gobble\string#1JR\endcsname%
   {%
    \ifx\RJ@aftergroup\relax%
     \gdef\next{\RJ@DRCentry{#1}}%
     \RJ@aftergroup\next%
    \else%
     \expandafter\noexpand\csname RJ\expandafter\@gobble\string#1JR\endcsname%
    \fi%
   }%
%
  \@ifundefined{pdfstringdefPreHook}{}%
   {%
    \expandafter\Addpdfstringdef\expandafter%
     {\expandafter\let\csname RJ\expandafter\@gobble\string#1JR\endcsname\@empty}%
     }%
    \expandafter\new@command\csname RJ@\expandafter\@gobble\string#1\endcsname%
 }%
%
\RJ@DeclareRobustCommand\iletter[1]{\textit{\huge #1}}%
%
\xdef\yiletter{\iletter{y}}%
\xdef\xyiletter{\iletter{x}\yiletter}%
\xdef\xyziletter{\xyiletter\iletter{z}}%
\xdef\jiletter{\iletter{j\iletter{i}}}%

\begin{document}

 \tableofcontents

 \newpage

 test \iletter{j\iletter{i}}, \jiletter{} test \iletter{a}, \yiletter, \xyiletter, \xyziletter{} test

 \section{italic \iletter{y}, \xyziletter}

  The following chapter heading is for comparison purposes only .

 \section{italic \textit{\huge y}, \textit{\huge xyz}}

  more text

\end{document}

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