我正在尝试编写一些 Latex expl3 函数。我是新手,所以问题可能很明显,但是……
我想编写宏,在其中调用一个带有一个参数的命令并计算给定参数被传递了多少次。然后我将总数输出到排序列表中。一切正常,但在我的列表中,法语口音消失了。以下是一段最简洁的代码:
\documentclass[oneside,12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{expl3}
\ExplSyntaxOn
%% creates a new token list
\prop_new:N \g_jbmlist_prop
\int_new:N \l_curval_int
\newcommand\addmaterial[1]{%
\group_begin:
% create key in g_jbmlist_prop if new and sets to 0.
\prop_gput_if_new:Nnn \g_jbmlist_prop {#1} 0
% defines int variable l_curval_int as the value of the prop.
\int_set:Nn \l_curval_int { \prop_item:Nn \g_jbmlist_prop {#1} }
\int_incr:N \l_curval_int % increments the value
\prop_gput:NnV \g_jbmlist_prop {#1} {\l_curval_int} % put it back.
\group_end:
}
\NewDocumentCommand{\outputmatlistitems}{}{
% \prop_show:N \g_jbmlist_prop
\group_begin:
% \int_new:N \l_curval_int
% declare a new list
\seq_new:N \l_tmpjba_seq
% new function to push into list
\cs_set:Npn \push_to_seq:nn ##1##2 {
\seq_put_right:Nn \l_tmpjba_seq {##1}
}
% push g_jbmlist_prop into it.
\prop_map_function:NN \g_jbmlist_prop \push_to_seq:nn
% sort the sequence
\seq_sort:Nn \l_tmpjba_seq
{
\str_compare:nNnTF { ##1 } > { ##2 }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
% define the way items will be displayed.
\cs_set:Npn \output_item:n ##1 {
% prints
\item {\expandafter ##1}: \prop_item:Nn \g_jbmlist_prop {##1}
}
% output the sorted sequence
\begin{itemize}
\seq_map_function:NN \l_tmpjba_seq \output_item:n
\end{itemize}
\group_end:
}
\ExplSyntaxOff
% \geometry{a4paper,inner=2.1cm,outer=2.1cm,top=2cm,bottom=2cm}
\begin{document}
En Français "maître" était accentué.
\addmaterial{scotch}
\addmaterial{règle}
\addmaterial{règle}
\outputmatlistitems
\end{document}
我得到:
清单中应包含以下内容:
- 规则:2
- 苏格兰威士忌:1
我的环境是 Mac,带有 pdfTeX 3.141592653-2.6-1.40.24(TeX Live 2022),以防万一。
答案1
问题是,排版 a 的键prop
不可靠。我使用两个属性列表,按项目索引。
然而,我警告你,字符串排序实际上并不起作用。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\addmaterial}{m}
{
\bobmorane_material_add:n { #1 }
}
\NewDocumentCommand{\outputmatlistitems}{}
{
\bobmorane_material_output:
}
\prop_new:N \g_bobmorane_material_items_prop
\prop_new:N \g_bobmorane_material_counts_prop
\seq_new:N \l__bobmorane_material_sort_seq
\cs_new_protected:Nn \bobmorane_material_add:n
{
\prop_gput_if_new:Nnn \g_bobmorane_material_items_prop { #1 } { #1 }
\prop_if_in:NnTF \g_bobmorane_material_counts_prop { #1 }
{
\prop_gput:Nnx \g_bobmorane_material_counts_prop { #1 }
{
\int_eval:n { \prop_item:Nn \g_bobmorane_material_counts_prop { #1 } + 1 }
}
}
{
\prop_gput:Nnn \g_bobmorane_material_counts_prop { #1 } { 1 }
}
}
\cs_new_protected:Nn \bobmorane_material_output:
{
\seq_clear:N \l__bobmorane_material_sort_seq
\prop_map_inline:Nn \g_bobmorane_material_counts_prop
{
\seq_put_right:Nn \l__bobmorane_material_sort_seq { ##1 }
}
\seq_sort:Nn \l__bobmorane_material_sort_seq
{
\str_compare:nNnTF { ##1 } > { ##2 }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
\begin{itemize}
\seq_map_function:NN \l__bobmorane_material_sort_seq \__bobmorane_material_output:n
\end{itemize}
}
\cs_new_protected:Nn \__bobmorane_material_output:n
{
\item
\prop_item:Nn \g_bobmorane_material_items_prop { #1 }
:
\prop_item:Nn \g_bobmorane_material_counts_prop { #1 }
}
\ExplSyntaxOff
\begin{document}
\addmaterial{aabbb}
\addmaterial{riri}
\addmaterial{scotch}
\addmaterial{règle}
\addmaterial{riri}
\addmaterial{règle}
\outputmatlistitems
\end{document}
答案2
下面l3prop
通过将非字符串化版本也存储在 prop 中来解决字符串化问题。
我们必须付出的代价是数据映射变得更加复杂(\use_i:nn
以及\use_ii:nn
获得可打印的版本和数字,以及在这里和那里\exp_after:wN
扩展\l_tmpa_tl
变量)。
我还用\prop_item:Nn
更快的方法来替换你的用法\prop_get:NnN
(你只应\prop_item:Nn
在必须通过扩展来工作时使用),对于你的用法也是如此\..._map_function:NN
,我已经用版本替换了它\..._map_inline:Nn
。
\documentclass[oneside,12pt,a4paper]{article}
% \usepackage[utf8]{inputenc} % no longer needed with recent LaTeX versions
\usepackage{expl3}
\ExplSyntaxOn
%% creates a new token list
\prop_new:N \g_jbmlist_prop
\int_new:N \l_curval_int
% declare a new list
\seq_new:N \l_tmpjba_seq
\newcommand\addmaterial[1]{%
\group_begin:
% create key in g_jbmlist_prop if new and sets to 0.
\prop_gput_if_new:Nnn \g_jbmlist_prop {#1} { {#1} {0} }
% defines int variable l_curval_int as the value of the prop.
\prop_get:NnN \g_jbmlist_prop {#1} \l_tmpa_tl
\prop_gput:Nne \g_jbmlist_prop {#1}
{
{ \exp_not:n {#1} }
\int_eval:n { \exp_after:wN \use_ii:nn \l_tmpa_tl + \c_one_int }
}
\group_end:
}
\NewDocumentCommand{\outputmatlistitems}{}{
% \prop_show:N \g_jbmlist_prop
\group_begin:
% push g_jbmlist_prop into it.
\prop_map_inline:Nn \g_jbmlist_prop
{ \seq_put_right:Nx \l_tmpjba_seq { \exp_not:o { \use_i:nn ##2 } } }
% sort the sequence
\seq_sort:Nn \l_tmpjba_seq
{
\str_compare:nNnTF { ##1 } > { ##2 }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
% define the way items will be displayed.
% output the sorted sequence
\begin{itemize}
\seq_map_inline:Nn \l_tmpjba_seq
{
\item ##1:
\prop_get:NnN \g_jbmlist_prop {##1} \l_tmpa_tl
\exp_after:wN \use_ii:nn \l_tmpa_tl
}
\end{itemize}
\group_end:
}
\ExplSyntaxOff
% \geometry{a4paper,inner=2.1cm,outer=2.1cm,top=2cm,bottom=2cm}
\begin{document}
En Français "maître" était accentué.
\addmaterial{scotch}
\addmaterial{règle}
\addmaterial{règle}
\outputmatlistitems
\end{document}