expl3を使用してソートするためにマクロを\ indexに展開する
カスタムマクロを使用してテキストでマークアップされた要件を持つドキュメントがあります\Req{}
。このマクロは、フォームの識別子のコンマ区切りリストを[A-F]:[0-9]{4,5}([0-9]{1,2})?
取得し、識別子を出力して、\index
それぞれを呼び出します。識別子の数値部分の順序でインデックスを出力する必要があるため、識別子の数値部分をソートキーに埋め込んでに渡そうとしてい\index{thing!sort-key@text}
ます。これはによって実行され\padreq:n
ます:
\documentclass{article}
\usepackage{expl3}
\usepackage{imakeidx}
\usepackage{xparse}
\makeindex[name=a2b, columns=1]
\ExplSyntaxOn
% #1 length
% #2 padee
\cs_new:Nn \padint:nn
{ % From : https://tex.stackexchange.com/a/412238/104401
\prg_replicate:nn { #1 - \tl_count:f { \int_to_arabic:n { #2 } } } { 0 }
\int_to_arabic:n { #2 }
}
\cs_generate_variant:Nn \tl_count:n { f }
% takes x.y, pads to 00000x.0y
\cs_new:Nn \padreq:n
{
% temp variables
\seq_clear_new:N \l_padreq_tmp_seq
\tl_clear_new:N \l_padreq_tmp_tl
% split arg 1
\seq_set_split:Nnn \l_padreq_tmp_seq {.} {#1}
\seq_log:N \l_padreq_tmp_seq
% Take the first item...
\seq_pop_left:NNT \l_padreq_tmp_seq \l_padreq_tmp_tl
{ % ... and pad it
%\padint:nn{5}{\l_padreq_tmp_tl}
\padint:nn{5}{\l_padreq_tmp_tl}
}
% Add the middle '.'
.
% Take next split item, which is optional
\seq_pop_left:NNTF \l_padreq_tmp_seq {\l_padreq_tmp_tl}
{ % and pad it
\padint:nn{2}{\l_padreq_tmp_tl}
}
{ % or set a default of 00 if missing
00
}
}
\cs_generate_variant:Nn \padreq:n { x }
\DeclareDocumentCommand{\Req}{m}
{
% Split the csv input
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
% output back to the document, with formatting
[ \seq_use:Nn \l_tmpa_seq {,~} ]
% Index each value, creating a sort key for \index
\seq_map_inline:Nn \l_tmpa_seq {
% Split by colon
% colons with expl3 https://tex.stackexchange.com/a/501346/104401
\use:x {\exp_not:N\seq_set_split:Nnn \exp_not:N\l_tmpb_seq {\c_colon_str} {##1}}
% Pad the 2nd item in the split sequence
\tl_set:Nn \l_tmpa_tl {\padreq:x{\seq_item:Nn \l_tmpb_seq 2}}
\newline ##1~--~\l_tmpa_tl % debug, typesets correctly
\index[a2b]{MWE!\l_tmpa_tl@##1}
}
}
\ExplSyntaxOff
\begin{document}
Hello. \Req{C:230, A:10}
\par
World. \Req{B:101.1}
\printindex[a2b]
\end{document}
これにより、次のa2b.idxが生成されます。
\indexentry{MWE!\padreq:x {230}@C:230}{1}
\indexentry{MWE!\padreq:x {10}@A:10}{1}
\indexentry{MWE!\padreq:x {101.1}@B:101.1}{1}
一方、makeindexはそれを文字通り処理するので、idxファイルに対して評価する必要があると思います。
印刷されたインデックスはABCの順序である必要がありますが、最終的にはBACになります。
症状はこの未回答の質問と同じですが、\ index引数でexpl3Expandingマクロを使用しています。
私のソリューション(パディング、コロン、一般的なexpl3 bodging)には十分なコピーと貼り付けの修正があり、私が試したすべてが違いをもたらさなかったか、完全に壊れたため、明らかな何かが欠けているように感じます。私は何が間違っているのですか?
回答
\padreq:n
機能は拡張可能ではありません。その出力をトークンリストに保存し、インデックスエントリの作成に使用できます。.
ただし、あるべきではありません。
\documentclass{article}
\usepackage{expl3}
\usepackage{imakeidx}
\usepackage{xparse}
\makeindex[name=a2b, columns=1]
\ExplSyntaxOn
% variables and variants
\seq_new:N \l_padreq_tmp_seq
\tl_new:N \l_padreq_paddedargs_tl
\cs_generate_variant:Nn \tl_count:n { f }
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
% #1 length
% #2 padee
\cs_new:Nn \padint:nn
{ % From : https://tex.stackexchange.com/a/412238/104401
\prg_replicate:nn { #1 - \tl_count:f { \int_to_arabic:n { #2 } } } { 0 }
\int_to_arabic:n { #2 }
}
\cs_generate_variant:Nn \padint:nn { ne }
% takes x.y, pads to 00000x.0y
\cs_new_protected:Nn \padreq:n
{
% split arg 1
\seq_set_split:Nnn \l_padreq_tmp_seq {.} {#1}
%\seq_log:N \l_padreq_tmp_seq
% pad the arguments
\tl_set:Nx \l_padreq_paddedargs_tl
{
% pad the first argument
\padint:ne { 5 } { \seq_item:Nn \l_padreq_tmp_seq { 1 } }
% Take next split item, which is optional
\int_compare:nTF { \seq_count:N \l_padreq_tmp_seq = 1 }
{% no second argument, add a default
00000
}
{
\padint:ne { 5 } { \seq_item:Nn \l_padreq_tmp_seq { 2 } }
}
}
}
\cs_generate_variant:Nn \padreq:n { e }
\DeclareDocumentCommand{\Req}{m}
{
% Split the csv input
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
% output back to the document, with formatting
[ \seq_use:Nn \l_tmpa_seq {,~} ]
% Index each value, creating a sort key for \index
\seq_map_inline:Nn \l_tmpa_seq
{
% Split by colon
\seq_set_split:NVn \l_tmpb_seq \c_colon_str {##1}
% Pad the 2nd item in the split sequence
\padreq:e { \seq_item:Nn \l_tmpb_seq { 2 } }
\index[a2b] {\l_padreq_paddedargs_tl@##1}
}
}
\ExplSyntaxOff
\begin{document}
Hello. \Req{C:230, A:10}
\par
World. \Req{B:101.1}
\printindex[a2b]
\end{document}
これは私が.idx
ファイルで取得するものです:
\indexentry{0023000000@C:230}{1}
\indexentry{0001000000@A:10}{1}
\indexentry{0010100001@B:101.1}{1}


に変更A:10
するとA:410
、

次のコードがその仕事をするはずです。
\documentclass{article}
\usepackage{expl3}
\usepackage{imakeidx}
\usepackage{xparse}
\makeindex[name=a2b, columns=1]
\ExplSyntaxOn
% #1 length
% #2 padee
\cs_new:Nn \__aejh_padint:nn
{ % From : https://tex.stackexchange.com/a/412238/104401
\prg_replicate:nn { #1 - \tl_count:f { \int_to_arabic:n { #2 } } } { 0 }
\int_to_arabic:n { #2 }
}
\cs_generate_variant:Nn \tl_count:n { f }
% Will contain the result (that is to say the key constructed on padding)
\tl_clear_new:N \l__aejh_result_tl
\cs_generate_variant:Nn \seq_set_split:Nnn { N V n }
\DeclareDocumentCommand { \Req } { m }
{
\clist_map_inline:Nn { #1 }
{
% Split by colon : we need to use the *value* of \c_colon_str
\seq_set_split:NVn \l_tmpa_seq \c_colon_str { ##1 }
% We retrieve the second item (after the colon)
% Fortunately \seq_item:Nn is fully expandable
\tl_set:Nx \l_tmpa_tl { \seq_item:Nn \l_tmpa_seq 2 }
% We split on an optional dot: \l_tmpb_seq will be of length 1 or 2
\seq_set_split:NnV \l_tmpb_seq { . } \l_tmpa_tl
% We retrive (by poping) the first part
\seq_pop_left:NN \l_tmpb_seq \l_tmpb_tl
% We pad the first part. Fortunately, \__aejh_padint:nn is fully expandable.
\tl_set:Nx \l__aejh_result_tl { \__aejh_padint:nn { 5 } { \l_tmpb_tl } }
% We add the dot
\tl_put_right:Nn \l__aejh_result_tl { . }
% We add the second part, after padding
\seq_pop_left:NNTF \l_tmpb_seq \l_tmpb_tl
{ \tl_put_right:Nx \l__aejh_result_tl { \__aejh_padint:nn 2 { \l_tmpb_tl } } }
{ \tl_put_right:Nn \l__aejh_result_tl { 00 } }
\index [a2b] { MWE ! \l__aejh_result_tl @ ##1 }
}
}
\ExplSyntaxOff
\begin{document}
Hello. \Req{C:230, A:10}
\par
World. \Req{B:101.1}
\printindex[a2b]
\end{document}