定义参数命令 - 嵌套 csname 的问题

定义参数命令 - 嵌套 csname 的问题

我正在尝试定义一个参数命令:特别是代码

\definecoloredblock{example}{black}{bg=red!50!white,fg=black}{bg=red!30!white,fg=black}

应定义命令\example\@exampleA\@exampleB。 (参见下面的代码)

\makeatletter
% definecolorblock <blockname> <titlecolor> <titlebg> <bodybg>
\def\definecoloredblock#1#2#3#4{%
  \expandafter\def\csname @#1A\endcsname[##1]%
  \expandafter{%
    \block{\textcolor{#2}{##1}}%
  }

  \expandafter\def\csname @#1B\endcsname%
  \expandafter{%
    \vspace*{-3ex}%
    \block{\vspace*{-5ex}}%
  }

  \expandafter\def\csname #1\endcsname%
  {%
    \expandafter\begingroup%
    \expandafter{\setbeamercolor{block title}{#3}}% 
    \expandafter{\setbeamercolor{block body}{#4}}%
    \expandafter\@ifnextchar\expandafter[%
    \csname @#1A\endcsname%
    \csname @#1B\endcsname%
    % ]
  }

  \expandafter\def\csname end#1\endcsname%
  \expandafter{%
    \endblock%
    \endgroup%
  }
}
\makeatother

\definecoloredblock{example}{black}{bg=red!50!white,fg=black}{bg=red!30!white,fg=black}

这段代码没有显示任何错误,但是当我尝试使用它时,例如:

\documentclass[10pt]{beamer}

\begin{document}
  \begin{frame}{Frame title}
    \begin{example}[Fake example]
      Some text
    \end{example}
  \end{frame}
\end{document}

我收到错误

! Use of \@exampleB doesn't match its definition.
\beamer@doifinframe ...me title} \begin {example}[
                                                  Fake example] Some 
text...
l.44 \end{frame}

\csname我该如何解决我的问题?我猜这与之后有关\@ifnextchar


预期输出

请参阅 egreg 的答案以了解解决方案。

答案1

您对 的使用\expandafter大部分是错误的。请注意,定义期间不会扩展任何内容。

\expandafter\def\csname...\endcsname和 for的简写形式\csname...\endcsname,更易于使用。

\documentclass{article}

\makeatletter
% definecolorblock <blockname> <titlecolor> <titlebg> <bodybg>
\def\definecoloredblock#1#2#3#4{%
  \@namedef{@#1A}[##1]{%
    \block{\textcolor{#2}{##1}}%
  }%
  \@namedef{@#1B}{%
    \vspace*{-3ex}%
    \block{\vspace*{-5ex}}%
  }
  \@namedef{#1}{%
    \begingroup
    \setbeamercolor{block title}{#3}%
    \setbeamercolor{block body}{#4}%
    \@ifnextchar[{\@nameuse{@#1A}}{\@nameuse{@#1B}}%]
  }
  \@namedef{end#1}{%
    \endblock
    \endgroup
  }%
}
\makeatother

\definecoloredblock{example}{black}{bg=red!50!white,fg=black}{bg=red!30!white,fg=black}

\makeatletter
\show\example
\show\@exampleA
\show\@exampleB
\show\endexample
\makeatother

\stop

以下是控制台中的内容

> \example=macro:
->\begingroup \setbeamercolor {block title}{bg=red!50!white,fg=black}\setbeamer
color {block body}{bg=red!30!white,fg=black}\@ifnextchar [{\@nameuse {@exampleA
}}{\@nameuse {@exampleB}}.
l.29 \show\example

? 
> \@exampleA=macro:
[#1]->\block {\textcolor {black}{#1}}.
l.30 \show\@exampleA

? 
> \@exampleB=macro:
->\vspace *{-3ex}\block {\vspace *{-5ex}}.
l.31 \show\@exampleB

? 
> \endexample=macro:
->\endblock \endgroup .
l.32 \show\endexample

? 
 )
No pages of output.

但是,它对于工作来说更容易使用xparse。请注意,我更改了定义环境的名称,因为example已经在中定义了beamer。使用\def会面临多种风险。

\documentclass{beamer}
\usepackage{xparse}

\NewDocumentCommand{\definecoloredblock}{mmmm}{%
  \NewDocumentEnvironment{#1}{o}
    {% start code
     \setbeamercolor{block title}{#3}%
     \setbeamercolor{block body}{#4}%
     \IfNoValueTF{##1}
       {\vspace*{-3ex}\block{\vspace*{-5ex}}}% no optional argument
       {\block{\textcolor{#2}{##1}}}%
    }
    {% end code
     \endblock
    }
}

\definecoloredblock
  {myexample}
  {black}
  {bg=red!50!white,fg=black}
  {bg=red!30!white,fg=black}

\begin{document}

\begin{frame}

Text

\begin{myexample}
Text in the block
\end{myexample}

Text

\begin{myexample}[Title]
Text in the block
\end{myexample}

\end{frame}

\end{document}

在此处输入图片描述

答案2

尽可能猜测其含义,

\documentclass[10pt]{beamer}

\begin{document}
\makeatletter

\def\definecoloredblock#1{%
  \expandafter\@definecoloredblock
      \csname#1\expandafter\endcsname
      \csname end#1\expandafter\endcsname
      \csname @#1A\expandafter\endcsname
      \csname @#1B\endcsname}

\def\@definecoloredblock#1#2#3#4#5#6#7{%
 \def#3[##1]{%
    \block{\textcolor{#5}{##1}}%
  }%
  \def#4{%
    \vspace*{-3ex}%
    \block{\vspace*{-5ex}}%
  }%
 \def#1{%
    \setbeamercolor{block title}{#6}% 
    \setbeamercolor{block body}{#7}%
    \@ifnextchar[#3#4%
    %]
  }%
  \def#2{%
    \endblock
  }%
}

\definecoloredblock{example}{black}{bg=red!50!white,fg=black}{bg=red!30!white,fg=black}



\makeatother






  \begin{frame}{Frame title}
    \begin{example}[Fake example]
      Some text
    \end{example}
  \end{frame}
\end{document}

相关内容