l3keysと再帰コマンド

l3keysと再帰コマンド

コマンドの動作を制御するために使用されるl3keysというリストを作成しようとしています。 最初は、これは単なるアイデンティティです。 設定により、これを (アイデンティティで構成) に変更する必要があります。 一般に、設定は↦になるように再定義する必要があります。 ただし、現状では、まったく惨めに失敗します。mykeysmycommand:ncommand=\textit\textitcommand=\foomycommand:n#1\foo{mycommand:n{#1}}これを動作させることは可能ですか?

\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}

答え1

私は特にインターフェースに興味はありませんが、ここではアプリケーションのコマンドを順番に保存します

\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}

keyval 設定の一部として単一トークン/マクロ テストを実行することもできますが、これはやり過ぎである可能性があります。

keyval 設定中に「機能的な」トークン リストを構築することはできますが、シーケンスを検査できるようにしておくとデバッグに役立つのではないかと思います。

答え2

ここに画像の説明を入力してください

関係するコマンドが1回の展開後に実装を公開する限り、次のようなことができます。

\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}

答え3

David の提案を実行する:

\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}

ここに画像の説明を入力してください

関連情報