1

Consider the following MWE:

\documentclass{article}

\usepackage{amsthm}
\usepackage{xparse}

\newtheorem{theorem}{Theorem}
\newtheorem{definition}{Definition}

\ExplSyntaxOn

\tl_new:N \l_theorem_name_tl

\keys_define:nn { keys-loop } {
  thmname
    .tl_set:N = \l_theorem_name_tl,
}

\clist_map_inline:nn { {thmname=theorem}, {thmname=definition} } {
  \keys_set:nn { keys-loop } { #1 }

  % At this level \l_theorem_name_tl is 'theorem' the first time and
  % 'definition' the second time.
  \cs_set_eq:cc {inner\l_theorem_name_tl} {\l_theorem_name_tl}
  \cs_set_eq:cc {endinner\l_theorem_name_tl} {end\l_theorem_name_tl}

  \RenewDocumentEnvironment{ \l_theorem_name_tl }{ O{} }{
    % Now \l_theorem_name_tl is 'definition' both the first and second time?
    % What is going on?
    \begin{inner\l_theorem_name_tl}
      This
  }{
    \end{inner\l_theorem_name_tl}
  }
}

\ExplSyntaxOff

\begin{document}

\begin{theorem}
  is a theorem.
\end{theorem}

\begin{definition}
  is a definition.
\end{definition}

\begin{innertheorem}
  is a theorem.
\end{innertheorem}

\begin{innerdefinition}
  is a definition.
\end{innerdefinition}

\end{document}

which produces

enter image description here

Why does the first theorem become a definition?

1
  • The \l_theorem_name_tl contains the latest content it was set to in \clist_map_inline (definition). So when you use \begin{theorem} it calls \begin{inner\l_theorem_name_tl} which expands to \begin{innerdefinition}. You need to send the content of \l_theorem_name_tl to RenewDocumentEnvironment, not the macro itself. – Simon Oct 7 '20 at 8:08
2

You need to use the content of \l_theorem_name_tl

\documentclass{article}

\usepackage{amsthm}
\usepackage{xparse}

\newtheorem{theorem}{Theorem}
\newtheorem{definition}{Definition}

\ExplSyntaxOn

\tl_new:N \l_theorem_name_tl

\keys_define:nn { keys-loop }
{
    thmname .tl_set:N = \l_theorem_name_tl,
}

\cs_new_protected:Npn \noibe_keyset:n #1
{
    \clist_map_inline:nn {#1}
    {
        \keys_set:nn { keys-loop } {##1}
        \noibe_cs_set_eq:V \l_theorem_name_tl
        \noibe_renew_env:V \l_theorem_name_tl
    }
}

\cs_new_protected:Npn \noibe_cs_set_eq:n #1
{
    \cs_set_eq:cc { inner#1 } {#1}
    \cs_set_eq:cc { endinner#1 } { end#1 }
}
\cs_generate_variant:Nn \noibe_cs_set_eq:n { V }

\cs_new_protected:Npn \noibe_renew_env:n #1
{
    \RenewDocumentEnvironment{#1}{ O{} }
    {
        \begin{inner#1}
            This
    }
    {
        \end{inner#1}
    }
}
\cs_generate_variant:Nn \noibe_renew_env:n { V }

\NewDocumentCommand{\setkeys}{ m }
{
    \noibe_keyset:n {#1}
}

\setkeys{thmname=theorem, thmname=definition}

\ExplSyntaxOff

\begin{document}

\begin{theorem}
  is a theorem.
\end{theorem}

\begin{definition}
  is a definition.
\end{definition}

\begin{innertheorem}
  is a theorem.
\end{innertheorem}

\begin{innerdefinition}
  is a definition.
\end{innerdefinition}

\end{document}

enter image description here

3
  • I would probably ditch \clist_map_inline:nn and then use \setkeys twice. I think it would give a cleaner interface. – Simon Oct 7 '20 at 8:30
  • 1
    You really should ditch \clist_map_inline:nn here. There is no advantage but some drawbacks. While \keys_set:nn handles active commas correctly, the clist functions do not. Also the code is considerably slower this way. Instead I'd use \keys_define:nn { noibe } { thmname .code:n = \noibe_cs_set_eq:n {#1} \noibe_renew_env:n {#1} } and \cs_new:Npn \noibe_keyset:n { \keys_set:nn { noibe } }. – Skillmon Oct 29 '20 at 20:14
  • I absolutely agree. – Simon Oct 30 '20 at 7:58
0

I don't know why you pass things through \keys_set:nn. In your MWE this is completely unnecessary and only complicates things. Instead, you can directly use your code inside \clist_map_inline:nn and access the environment names with #1.

\documentclass{article}

\usepackage{amsthm}
\usepackage{xparse}

\newtheorem{theorem}{Theorem}
\newtheorem{definition}{Definition}

\ExplSyntaxOn

\clist_map_inline:nn { theorem, definition }
  {
    \cs_set_eq:cc { inner #1 } {#1}
    \cs_set_eq:cc { endinner #1 } { end #1 }

    \RenewDocumentEnvironment {#1}{ O{} }
      {
        \begin{inner#1}
          This
      }
      {
        \end{inner#1}
      }
  }

\ExplSyntaxOff

\begin{document}

\begin{theorem}
  is a theorem.
\end{theorem}

\begin{definition}
  is a definition.
\end{definition}

\begin{innertheorem}
  is a theorem.
\end{innertheorem}

\begin{innerdefinition}
  is a definition.
\end{innerdefinition}

\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.