在 LaTeX3 中使用 clist 索引

在 LaTeX3 中使用 clist 索引

朋友们,我正在尝试移植我的旧密码到 LaTeX3 实现。感谢 egreg、Joseph 和 David,我取得了很大的进步!但后来,我陷入了困境。

从上面的链接,我正在移植我的歌本项目。如你所知,我的歌曲有多个索引,我过去常常事先对它们进行硬编码。如果不添加更多条件,代码就无法扩展。

我的想法是:有一个列表(逗号分隔的列表,或者用 L3 术语来说,一个clist)保存索引名称,另一个列表保存缩写名称。如果我想将单词作为缩写添加Hello world到索引中F,我会在缩写列表中搜索我的项目的位置,然后检查其名称对应项。

从现在起,这个词指数将用于引用标识数组元素的整数指针,而不是我们在排版中拥有的信息列表。

和往常一样,egreg 拯救了我,并帮我编写了一个 L3 代码来查找 a 中的项目clist并返回其索引i。该代码具有以下方法:

  • i > 0: 中第一次出现该项目clist。需要注意的是clist的索引以 开头1
  • i = 0:列表中未找到该项目。

我正在努力使用此查找代码中的值来从其他列表中获取项目\clist_item:Nn。让我们看一些代码:

% arara: pdflatex: { shell: on }
% arara: pdflatex
\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{xparse}
\usepackage{imakeidx}

\ExplSyntaxOn

\clist_new:N \l_vozes_extensions_clist
\clist_new:N \l_vozes_abbreviations_clist
\int_new:N \l_vozes_index_step_int
\bool_new:N \l_vozes_index_found_bool

\cs_new:Npn \vozes_getitemindex:Nn #1 #2
 {
  \int_zero:N \l_vozes_index_step_int
  \bool_set_false:N \l_vozes_index_found_bool
  \clist_map_inline:Nn #1
   {
    \int_incr:N \l_vozes_index_step_int
    \tl_if_eq:nnT { #2 } { ##1 }
    { \clist_map_break:n {  \bool_set_true:N \l_vozes_index_found_bool } }
   }
   \bool_if:NTF{ \l_vozes_index_found_bool }{ \int_to_arabic:n { \l_vozes_index_step_int } }{ 0 }
}

\cs_new:Npn \vozes_newthematicindex:nnnn #1 #2 #3 #4
{
   \clist_put_right:Nn  \l_vozes_extensions_clist { #1 }
   \clist_put_right:Nn \l_vozes_abbreviations_clist { #3 }
   \makeindex[name=#1,title=#2,columns=#4]
}

\NewDocumentCommand{\newthematicindex}{ m m m m }{
   \vozes_newthematicindex:nnnn { #1 }{ #2 }{ #3 }{ #4 }
}

\NewDocumentCommand{\thematicindex}{ m m }{
   %\clist_item:Nn \l_vozes_extensions_clist {
   % \vozes_getitemindex:Nn \l_vozes_abbreviations_clist { #1 }
   %}
   \index[ \clist_item:Nn \l_vozes_extensions_clist { 1 } ]{ #2 }
}

\NewDocumentCommand{\printthematicindex}{ m }{
   %\clist_item:Nn \l_vozes_extensions_clist {
   % \vozes_getitemindex:Nn \l_vozes_abbreviations_clist { #1 }
   %}
   \printindex[ \clist_item:Nn \l_vozes_extensions_clist { 1 } ]
}

\ExplSyntaxOff

\newthematicindex{ifoo}{The list of Foo}{F}{2}
\newthematicindex{ibar}{Bar is cool}{B}{2}
\newthematicindex{ifb}{Foo and Bar}{FB}{2}

\begin{document}

Hello.

\thematicindex{F}{Hello Foo}
\thematicindex{B}{Hello Bar}
\thematicindex{FB}{Hello Foobar}

\printthematicindex{F}
\printthematicindex{B}
\printthematicindex{FB}

\end{document}

当然,这段代码不起作用。:)有问题的部分在注释部分:

%\clist_item:Nn \l_vozes_extensions_clist {
% \vozes_getitemindex:Nn \l_vozes_abbreviations_clist { #1 }
%}

我对整数值一头雾水。:(说到这,我想知道如何将命令的返回保存到变量中,我应该使用\def吗?

最后一个问题:混合使用 L2 和 L3 是好的做法吗?\ExplSyntaxOff每次我有 L2 代码时都应该这样做吗,或者没有任何副作用?

任何启示都值得赞赏。:)

答案1

\clist_item:Nn期望第二个参数中有一个数字指定,但它\vozes_getitemindex:Nn没有提供,因为它是一组用于提供整数的指令。

这里有一种方法:计算整数并将其输入到\clist_item:Nn。但是,存在不可扩展的故障\clist_item:Nn;因此序列似乎是更好的选择。

% arara: pdflatex: { shell: on }
% arara: pdflatex
\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{xparse}
\usepackage{imakeidx}

\ExplSyntaxOn

\seq_new:N \g_vozes_extensions_seq
\seq_new:N \g_vozes_abbreviations_seq
\int_new:N \l_vozes_index_step_int
\bool_new:N \l_vozes_index_found_bool

\cs_new_protected:Npn \vozes_getitemindex:Nn #1 #2
 {
  \int_zero:N \l_vozes_index_step_int
  \bool_set_false:N \l_vozes_index_found_bool
  \seq_map_inline:Nn #1
   {
    \int_incr:N \l_vozes_index_step_int
    \tl_if_eq:nnT { #2 } { ##1 }
    { \seq_map_break:n {  \bool_set_true:N \l_vozes_index_found_bool } }
   }
   \bool_if:NF{ \l_vozes_index_found_bool }{ \int_zero:N \l_vozes_index_step_int } 
}

\cs_new_protected:Npn \vozes_newthematicindex:nnnn #1 #2 #3 #4
{
   \seq_gput_right:Nn  \g_vozes_extensions_seq { #1 }
   \seq_gput_right:Nn \g_vozes_abbreviations_seq { #3 }
   \makeindex[name=#1,title=#2,columns=#4]
}

\NewDocumentCommand{\getitemindex}{mm}
 {
  \vozes_getitemindex:Nn #1 { #2 }
  \int_to_arabic:n { \l_vozes_index_step_int }
 }

\NewDocumentCommand{\newthematicindex}{ m m m m }{
   \vozes_newthematicindex:nnnn { #1 }{ #2 }{ #3 }{ #4 }
}

\NewDocumentCommand{\thematicindex}{ m m }{
   \vozes_getitemindex:Nn \g_vozes_abbreviations_seq { #1 }
   \index[ \seq_item:Nn \g_vozes_extensions_seq { \l_vozes_index_step_int } ] { #2 }
}

\NewDocumentCommand{\printthematicindex}{ m }{
   \vozes_getitemindex:Nn \g_vozes_abbreviations_seq { #1 }
   \printindex[ \seq_item:Nn \g_vozes_extensions_seq { \l_vozes_index_step_int } ]
}

\ExplSyntaxOff

\newthematicindex{ifoo}{The list of Foo}{F}{2}
\newthematicindex{ibar}{Bar is cool}{B}{2}
\newthematicindex{ifb}{Foo and Bar}{FB}{2}

\begin{document}

Hello.

\thematicindex{F}{Hello Foo}
\thematicindex{B}{Hello Bar}
\thematicindex{FB}{Hello Foobar}

\printthematicindex{F}
\printthematicindex{B}
\printthematicindex{FB}

\end{document}

使用属性列表的更有效的实现:

% arara: pdflatex
\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{xparse}
\usepackage{imakeidx}

\ExplSyntaxOn

\prop_new:N \g_vozes_abbreviations_prop

\cs_new_protected:Npn \vozes_newthematicindex:nnnn #1 #2 #3 #4
{
 \prop_gput:Nnn \g_vozes_abbreviations_prop { #3 } { #1 }
 \makeindex[name=#1,title=#2,columns=#4]
}

\NewDocumentCommand{\newthematicindex}{ m m m m }
 {
  \vozes_newthematicindex:nnnn { #1 }{ #2 }{ #3 }{ #4 }
 }

\NewDocumentCommand{\thematicindex}{ m m }
 {
  \index[ \prop_get:Nn \g_vozes_abbreviations_prop { #1 } ] { #2 }
 }

\NewDocumentCommand{\printthematicindex}{ m }
 {
  \printindex[ \prop_get:Nn \g_vozes_abbreviations_prop { #1 } ]
 }

\ExplSyntaxOff

\newthematicindex{ifoo}{The list of Foo}{F}{2}
\newthematicindex{ibar}{Bar is cool}{B}{2}
\newthematicindex{ifb}{Foo and Bar}{FB}{2}

\begin{document}

Hello.

\thematicindex{F}{Hello Foo}
\thematicindex{B}{Hello Bar}
\thematicindex{FB}{Hello Foobar}

\printthematicindex{F}
\printthematicindex{B}
\printthematicindex{FB}

\end{document}

相关内容