l3keys und rekursive Befehle

l3keys und rekursive Befehle

Ich versuche, eine l3keysListe namens zu erstellen mykeys, die verwendet wird, um das Verhalten des Befehls zu steuern mycommand:n. Zunächst ist es nur die Identität. Durch Setzen command=\textitsollte sie in \textit(zusammengesetzt mit Identität) geändert werden. Im Allgemeinen command=\foosollte die Einstellung neu definiert werden mycommand:n, um #1↦ zu werden \foo{mycommand:n{#1}}. So wie es jetzt ist, schlägt es jedoch ziemlich kläglich fehl.Ist es möglich, dass das funktioniert?

\documentclass{article}

\usepackage{expl3}

\ExplSyntaxOn

\cs_new:Npn \identity:n #1 { #1 }


\keys_define:nn { mykeys }
{
    command .multichoice:,
    command / none .code:n = {
        \cs_set_eq:NN \mycommand:n \identity:n %this resets \mycommand:n
                                               %to become the identity
    },
    command / unknown .code:n = {
        \cs_set:Npx \mycommand:n ##1
        {
            #1 { \mycommand:n { ##1 } }
        }
    }
}

\keys_set:nn { mykeys } { command=none }

\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn

\mycommand:n{test1} % should produce test1

\keys_set:nn { mykeys } { command=\textit }

\mycommand:n{test2} % should produce \textit{test2}

\keys_set:nn { mykeys } { command=\textbf }

\mycommand:n{test3} % should produce \textbf{\textit{test3}}

\ExplSyntaxOff

\end{document}

Antwort1

Ich bin nicht besonders begeistert von der Schnittstelle, aber hier würde ich die Befehle für die Anwendung in einer Reihenfolge speichern

\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn

\seq_new:N \l__mycommand_cmds_seq
\tl_new:N \l__mycommand_tmp_tl

\keys_define:nn { mykeys }
  {
    command .code:n = 
      {
        \str_if_eq:nnTF {#1} { none }
          { \seq_clear:N \l__mycommand_cmds_seq }
          { \seq_put_right:Nn \l__mycommand_cmds_seq {#1} }
      }
  }
\keys_set:nn { mykeys } { command = none }

\cs_new_protected:Npn \mycommand_main:n #1
  {
    \group_begin:
      \tl_set:Nn \l__mycommand_tmp_tl {#1}
      \seq_map_inline:Nn \l__mycommand_cmds_seq
        {
          \tl_set:Nx \l__mycommand_tmp_tl
            { \exp_not:n {##1} { \exp_not:V \l__mycommand_tmp_tl } }
        }
    \exp_args:NV \group_end:
    \l__mycommand_tmp_tl
  }

\NewDocumentCommand \mysetup { +m } { \keys_set:nn { mykeys } {#1} }
\NewDocumentCommand \mycommand { m }
  { \mycommand_main:n {#1} }
\ExplSyntaxOff

\begin{document}

\mycommand{test1} % should produce test1

\mysetup{command = \textit}

\mycommand{test2} % should produce \textit{test2}

\mysetup{command = \textbf}

\mycommand{test3} % should produce \textbf{\textit{test3}}

\end{document}

Man könnte im Rahmen der Keyval-Einstellung einen Einzeltoken-/Makrotest durchführen, aber das ist wahrscheinlich übertrieben.

Man könnte die „funktionale“ Token-Liste während der Keyval-Einstellung erstellen, aber ich vermute, dass es beim Debuggen nützlich sein könnte, die Sequenz zur Überprüfung verfügbar zu haben.

Antwort2

Bildbeschreibung hier eingeben

Solange die beteiligten Befehle ihre Implementierung nach einer einzigen Erweiterung offenlegen, können Sie etwa Folgendes tun:

\documentclass{article}

\usepackage{expl3}

\ExplSyntaxOn

\cs_new:Npn \identity:n #1 { #1 }

\cs_new:Npn\wrap_def:NN#1#2{
  \exp_after:wN\cs_set:Npn
   \exp_after:wN#2\exp_after:wN##\exp_after:wN1\exp_after:wN{
   \exp_after:wN#1\exp_after:wN{#2{##1}}}
  }





\keys_define:nn { mykeys }
{
    command .multichoice:,
    command / none .code:n = {
        \cs_set_eq:NN \mycommand:n \identity:n %this resets \mycommand:n
                                               %to become the identity
    },
    command / unknown .code:n = {
        \wrap_def:NN #1 \mycommand:n
    }
}

\keys_set:nn { mykeys } { command=none }

\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn

\mycommand:n{test1} % should produce test1

\keys_set:nn { mykeys } { command=\textit }


\mycommand:n{test2} % should produce \textit{test2}

\keys_set:nn { mykeys } { command=\textbf }

\mycommand:n{test3} % should produce \textbf{\textit{test3}}

\ExplSyntaxOff

\end{document}

Antwort3

Umsetzung von Davids Vorschlag:

\documentclass{article}

\usepackage{expl3}

\ExplSyntaxOn

\tl_new:N \l_gaussler_command_start_tl
\tl_new:N \l_gaussler_command_end_tl

\keys_define:nn { mykeys }
 {
  command .multichoice:,
  command / none .code:n =
   {
    \tl_clear:N \l_gaussler_command_start_tl
    \tl_clear:N \l_gaussler_command_end_tl
    \cs_set_protected:Nn \gaussler_thecommand:n { ##1 }
   },
  command / unknown .code:n =
   {
    \tl_put_left:Nn \l_gaussler_command_start_tl { \exp_not:N #1 \gaussler_command_open: }
    \tl_put_right:Nn \l_gaussler_command_end_tl { \gaussler_command_close: }
    \cs_set_protected:Nx \gaussler_thecommand:n
     {
      \tl_use:N \l_gaussler_command_start_tl
      ##1 
      \tl_use:N \l_gaussler_command_end_tl
     }
   }
 }
\cs_new:Nn \gaussler_command_open: { \if_true: { \else: } \fi: }
\cs_new:Nn \gaussler_command_close: { \if_false: { \else: } \fi: }

\keys_set:nn { mykeys } { command=none }

\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn

\gaussler_thecommand:n{test1} % should produce test1

\keys_set:nn { mykeys } { command=\textit }

\gaussler_thecommand:n{test2} % should produce \textit{test2}

\keys_set:nn { mykeys } { command=\textbf }

\gaussler_thecommand:n{test3} % should produce \textbf{\textit{test3}}

\keys_set:nn { mykeys } { command=none }

\gaussler_thecommand:n{test4}

\ExplSyntaxOff

\end{document}

Bildbeschreibung hier eingeben

verwandte Informationen