expl3 にキー値オプションを含むキー値オプションを保存するにはどうすればよいですか?

expl3 にキー値オプションを含むキー値オプションを保存するにはどうすればよいですか?

キー値構文を使用するコマンドがあります。たとえば、必要に応じて、さまざまなオプションを含む画像が含まれます。

私はexpl3キー値処理を使用しています。

キー値設定をグローバル トークン リストに保存して、次回コマンドを実行するときにデフォルトとして再利用できるようにしたいと思います。マクロをキー値オプション セットのグローバルにしたくないので、これを行う明白な方法を見つけることができませんでした。グローバルにすると、さまざまな点で複雑になるためです。必要なのは、関連するキー値をグローバル トークン リストに保存して、再利用できるようにすることです。(トークン リストでなくてもかまいません。それが明白な選択に思えただけです。)

ブール値とカンマ区切りのリストは問題なく保存できるようですが、それ自体がキー値オプションのリストであるトークン リストで問題が発生しています。たとえば、 はgraphics={<key-value options>}に設定を渡すために使用されます\includegraphics。しかし、これを機能させることができません。

これは(比較的)最小限の例であり、金星でなぜこれをやろうとしているのかがまったく分かりませんが、それが小型化なのです。

\documentclass{article}
\usepackage{xparse,graphicx}
\begin{document}
\ExplSyntaxOn
\tl_new:N \l_pre_graphics_tl
\tl_new:N \g_pre_img_options_tl
\tl_new:N \g_pre_img_tl
\cs_new_protected_nopar:Nn \pre_key_tl_save:Nn
{
  \tl_if_empty:cF {l_pre_#2_tl}
    {
      \tl_gput_right:No #1 { #2 = }
      \tl_gput_right:NV #1 \c_left_brace_str
      \tl_gput_right:Nv #1 { l_pre_#2_tl }
      \tl_gput_right:NV #1 \c_right_brace_str
      \tl_gput_right:Nn #1 { , }
    }
}
\cs_generate_variant:Nn \tl_gput_right:Nn {Nv}
% includegraphics bit courtesy of egreg (chat 2015-01-08)
\cs_new:Npn \pre_includegraphics:nn #1 #2
 {
  \includegraphics[#1]{#2}
 }
\cs_generate_variant:Nn \pre_includegraphics:nn { VV }
\keys_define:nn { pre / img }
{
  graphics .tl_set:N = \l_pre_graphics_tl,
}
\NewDocumentCommand \incimg { o m }
{
  \group_begin:
    \tl_if_empty:NF \g_pre_img_options_tl
    {
      \keys_set:nV { pre / img } \g_pre_img_options_tl
    }
    \IfValueT{#1}{ \keys_set:nn { pre / img } { #1 } }
    \pre_key_tl_save:Nn \g_pre_img_options_tl { graphics }
    \tl_set:Nn \g_pre_img_tl { #2 }
    \pre_includegraphics:VV \l_pre_graphics_tl \g_pre_img_tl
  \group_end:
}
\ExplSyntaxOff

\incimg[
  graphics={width=\textwidth},
]{example-image-a}
\incimg[
  graphics={width=\textwidth},
]{example-image-a}
\end{document}

エラーメッセージには、人間に助けを求めるようにと書かれていたので、ここに来ました...。

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! LaTeX error: "kernel/misplaced-equals-sign"
! 
! Misplaced equals sign in key-value input 194
! 
! See the LaTeX3 documentation for further information.
! 
! For immediate help type H <return>.
!...............................................  

l.194 ]{example-image-a}

? h
|'''''''''''''''''''''''''''''''''''''''''''''''                                                                                              
| LaTeX is attempting to parse some key-value input but found two equals signs                                                                
| not separated by a comma.                                                                                                                   
|...............................................                                                                                              
? h                                                                                                                                           
Sorry, I already gave what help I could...                                                                                                    
Maybe you should try asking a human?                                                                                                          
An error might have occurred before I noticed any problems.                                                                                   
``If all else fails, read the instructions.''                                                                                                 

?   

使用する前にトークンリストを表示すると、

> \g_pre_img_options_tl=graphics={width=\textwidth },.

これは、リストを中括弧で囲む必要があることを私の単純な頭では示唆しています。しかし、これを実行しようとする私の試みは、これまでのところ成功していません。LaTeX がキーとして意図されていないもの (例\g_pre_img_options) を探すか、括弧が消えてしまうかのどちらかです。

答え1

あなたが何を達成しようとしているのかを完全には理解していませんし、私が何を推測しているかはわかりませんが、私なら同じ方法で行うとは思いません。いずれにせよ、このドキュメントをコンパイルできる変更を次に示します。

\cs_new_protected_nopar:Nn \pre_key_tl_save:Nn
{
  \tl_if_empty:cF {l_cfr_#2_tl}
    {
      \tl_gput_right:No #1 { #2 = }
      \tl_gput_right:NV #1 \c_left_brace_str
      \tl_gput_right:Nv #1 { l_pre_#2_tl }
      \tl_gput_right:NV #1 \c_right_brace_str
      \tl_gput_right:Nn #1 { , }
    }
}

これは間違っているように思えます。たとえ私がそれをはっきりと理解していなくても、それは、まず、多くの異なる部分で問題を複雑にしすぎていること、そして、実際にそれを行うことができないという事実(追加は、\c_left_brace_str開始グループ catcode 1 を追加するのではなく{、 に似た catcode “other” を追加することです)。正しい を使用した\string{単純な議論の方が簡単です。x\exp_not:*

\cs_new_protected_nopar:Nn \pre_key_tl_save:Nn
 {
  \tl_if_empty:cF {l_cfr_#2_tl}
   {
    \tl_gput_right:Nx #1 { #2 = { \exp_not:v { l_pre_#2_tl } } , }
   }
 }

この変更により、少なくともコンパイルは行われますが、これですべてが解決するかどうかはわかりません。


文字列とマクロの値を別のマクロに追加したいとします。最も簡単な方法は、引数を使って一度にすべてを実行することですx。文字通り、やりたいことを実行するのですが、正しいです。\tl_put_right:Nxの2番目の引数を展開します\edef。つまり、展開します。すべてなので、必要な瞬間に停止するだけで済みます。引数を代入した後は、

\tl_gput_right:Nx \g_pre_img_options_tl { graphics = { \exp_not:v { l_pre_grahpics_tl } } , }

を見たなら\edef\foo{graphics={foo}}、 の内容が何で\fooあるかが分かります。文字も、「その他」(「=」) も、中括弧や も、何も展開されません{}つまり、魔法は の中にあります\exp_not:v { l_pre_grahpics_tl }。expl3 引数のおかげで、\exp_not:V \l_pre_grahpics_tlは とまったく同じになり、 は と同じになり、\exp_not:n { width=\textwidth }はそこで展開を停止します (\exp_not:nです\unexpanded)。

そうすれば、展開後の上の行xは、

\tl_gput_right:Nn \g_pre_img_options_tl { graphics = { width = \textwidth } , }

そうでなかったら、\unexpanded{width=\textwidth}TeX は他のマクロと同様に拡張しようとしたかもしれません\textwidth。これは (現時点ではわかりませんが) 拡張された可能性があり\dimen <number>、一般に、そのような拡張は発生してほしくありません。

申し訳ありませんが、この回答は決して完璧ではありませんが、誰でも自由に編集できます。

関連情報