Memperluas makro ke dalam \ index untuk mengurutkan menggunakan expl3
Saya memiliki dokumen dengan persyaratan yang ditandai dalam teks dengan makro khusus \Req{}
, yang mengambil daftar pengenal formulir yang dipisahkan koma [A-F]:[0-9]{4,5}([0-9]{1,2})?
, mengeluarkan pengenal dan panggilan \index
untuk masing-masing. Saya membutuhkan indeks untuk menjadi keluaran yang diurutkan oleh bagian numerik dari pengenal, jadi saya mencoba memasukkan bagian numerik dari pengenal ke dalam kunci sortir untuk diteruskan \index{thing!sort-key@text}
. Ini dilakukan oleh \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}
Ini menghasilkan a2b.idx dari:
\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}
sedangkan, menurut saya, makeindex akan memperlakukannya secara harfiah dan perlu dievaluasi untuk file idx.
Indeks yang dicetak harus dalam urutan ABC, tetapi berakhir dengan BA C.
Gejalanya sama dengan pertanyaan yang belum terjawab ini, tetapi saya menggunakan argumen expl3 Memperluas makro di \ index .
Sekarang ada cukup perbaikan salin dan tempel dalam solusi saya (padding, titik dua, bodging expl3 umum) sehingga saya merasa saya kehilangan sesuatu yang jelas, karena semua yang saya coba tidak membuat perbedaan atau merusaknya sepenuhnya. Apa yang saya lakukan salah?
Jawaban
The \padreq:n
Fungsi tidak diperluas. Anda dapat menyimpan hasilnya dalam daftar token dan menggunakannya untuk menghasilkan entri indeks. Namun, seharusnya tidak ada .
.
\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}
Inilah yang saya dapatkan di .idx
file:
\indexentry{0023000000@C:230}{1}
\indexentry{0001000000@A:10}{1}
\indexentry{0010100001@B:101.1}{1}


Jika saya berubah A:10
menjadi A:410
, saya mendapatkan

Kode berikut harus melakukan pekerjaan itu.
\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}