前两天看到一个模板实现了如下的一个接口
latex
\titleimage{
chapteroddimage = {odd1,odd2,odd3,odd4,odd5,odd6},
partoddimage = {odd1,odd2,odd3,odd4,odd5,odd6},
chapterevenimage = {songeven,even1,even2},
partevenimage={songeven,even1,even2},
}
功能就是为 part
, chapter
... 设置背景图片
大概思路是,将
latex
chapterimage = {odd1,odd2,odd3,odd4,odd5,odd6}
这个列表里面的图片名依次赋值到
latex
\@chapter@image@1 -> odd1
\@chapter@image@2 -> odd2
\@chapter@image@3 -> odd3
\@chapter@image@4 -> odd4
...
然后通过
latex
\includegraphics{\@chapter@image@<\value{chapter}>}
<\value{chapter}>
指的是当前 chapter
的计数器的值,这样就能动态的设置每一个 chapter 的背景图片,这个思路不光是可以应用到章节背景图,其它的地方也能适用.
回到问题,现在想要给所有 chapter
都设置成同样的图片,那么就需要如下设置
latex
chapterimage = {
image, image, image, image, image, image, image,
image, image, image, image, image, image, ...
}
这样,其实是会有很多重复的配置
想要把它优化一下,如下
latex
chapter-image = {1, 3-6, 8}{left.png},
chapter-image = {2, 7, 9-12}{right.jpg}
下面就来实现它
首先是需要有一个函数,它需要接受两个参数. 来解析 {2, 7, 9-12}{right.jpg}
latex3
\__module_chapter_image_parser:nn
这个函数要实现的功能是,读取 {2, 7, 9-12}
,然后定义对应的变量储存
latex3
\g__module_chapter_image_2_tl -> right.png
\g__module_chapter_image_7_tl -> right.png
\g__module_chapter_image_9_tl -> right.png
\g__module_chapter_image_10_tl -> right.png
\g__module_chapter_image_11_tl -> right.png
\g__module_chapter_image_12_tl -> right.png
很简单吧
那么就需要一个辅助函数,用于将 {1-3, 7, 9-12}
转化为 {1, 2, 3, 7, 9, 10, 11, 12}
latex3
\cs_set_nopar:Npn \__module_range_to_list:nN #1#2 {
\seq_set_split:Nnn \l__module_tmpa_seq { , } { #1 }
\seq_map_inline:Nn \l__module_tmpa_seq
{
\tl_if_in:nnTF { ##1 }{ - }
{
\seq_set_split:Nnn \l__module_tmpb_seq { - } { ##1 }
\int_step_inline:nnn
{ \seq_item:Nn \l__module_tmpb_seq { 1 } }
{ \seq_item:Nn \l__module_tmpb_seq { 2 } }
{
\clist_put_right:Nn #2 { ####1 }
}
}
{
\clist_put_right:Nn #2 { ##1 }
}
}
}
具体流程为
- 按逗号
,
分割成列表 - 遍历该队列
- 如果存在
-
,说明为1-6
这样的range
,那么按-
分割,以两端的数字为起始,通过整数循环依次放进目标数组 - 如果不存在
-
,说明为5
这样的单个数字,直接放进目标数组
- 如果存在
- 返回目标数组
现在就可以遍历上面返回的目标数组完成变量的赋值了
latex3
\cs_set_nopar:Npn \__module_chapter_image_parser:nn #1#2
{
\clist_clear:N \l__module_tmpa_clist
\__module_range_to_list:nN { #1 } \l__module_tmpa_clist
\clist_map_inline:Nn \l__module_tmpa_clist
{
\tl_gset:cn { g__module_chapter_image_##1_tl } { #2 }
}
}
使用
latex3
\__module_chapter_image_parser:nn {1, 3-5, 7} {image.png}
就可以实现
latex3
\g__module_chapter_image_1_tl -> image.png
\g__module_chapter_image_3_tl -> image.png
\g__module_chapter_image_4_tl -> image.png
\g__module_chapter_image_5_tl -> image.png
\g__module_chapter_image_7_tl -> image.png
问题又来了,如果就想要每个 chapter
都不一样呢,那岂不是要
latex3
\__module_chapter_image_parser:nn {1} {image1.png}
\__module_chapter_image_parser:nn {2} {image2.png}
\__module_chapter_image_parser:nn {3} {image3.png}
\__module_chapter_image_parser:nn {4} {image4.png}
\__module_chapter_image_parser:nn {5} {image5.png}
\__module_chapter_image_parser:nn {6} {image6.png}
\__module_chapter_image_parser:nn {7} {image7.png}
\__module_chapter_image_parser:nn {8} {image8.png}
...
所以是需要兼容一下这个接口
latex3
\cs_set_nopar:Npn \__module_chapter_image_parser:nn #1#2
{
\clist_clear:N \l__module_tmpa_clist
\tl_if_eq:nnTF { #1 } { * }
{
\clist_set:Nn \l__module_tmpa_clist { #2 }
\int_step_inline:nn { \clist_count:N \l__module_tmpa_clist } {
\tl_gset:cn { g__module_chapter_image_##1_tl }
{
\clist_item:Nn \l__module_tmpa_clist { ##1 }
}
}
}
{
\__module_range_to_list:nN { #1 } \l__module_tmpa_clist
\clist_map_inline:Nn \l__module_tmpa_clist
{
\tl_gset:cn { g__module_chapter_image_##1_tl } { #2 }
}
}
}
现在就可以
latex3
\__module_chapter_image_parser:nn { * }
{
image1.png,
image2.png,
image3.png,
image4.png,
image5.png,
image6.png,
...
}
接下来是将其封装为 key-value
形式
latex3
\keys_define:nn { module }
{
chapter-image.code:n = \__module_chapter_image_parser:nn #1
}
\NewDocumentCommand{\setup}{ m }{ \keys_set:nn { module } {#1} }
使用方式如下
latex3
\setup{%
chapter-image = {1, 3-5, 7-9}{image.png},
chapter-image = {2, 6, 10-15}{cover.jpg},
% chapter-image = {*}{image1, image2, image3, image4}
}
完整源码如下
latex3
\documentclass{article}
\usepackage[margin = 2cm]{geometry}
\ExplSyntaxOn
\seq_new:N \l__module_tmpa_seq
\seq_new:N \l__module_tmpb_seq
\clist_new:N \l__module_tmpa_clist
\cs_set_nopar:Npn \__module_range_to_list:nN #1#2 {
\seq_set_split:Nnn \l__module_tmpa_seq { , } { #1 }
\seq_map_inline:Nn \l__module_tmpa_seq
{
\tl_if_in:nnTF { ##1 }{ - }
{
\seq_set_split:Nnn \l__module_tmpb_seq { - } { ##1 }
\int_step_inline:nnn
{ \seq_item:Nn \l__module_tmpb_seq { 1 } }
{ \seq_item:Nn \l__module_tmpb_seq { 2 } }
{
\clist_put_right:Nn #2 { ####1 }
}
}
{
\clist_put_right:Nn #2 { ##1 }
}
}
}
\cs_set_nopar:Npn \__module_chapter_image_parser:nn #1#2
{
\clist_clear:N \l__module_tmpa_clist
\tl_if_eq:nnTF { #1 } { * }
{
\clist_set:Nn \l__module_tmpa_clist { #2 }
\int_step_inline:nn { \clist_count:N \l__module_tmpa_clist } {
\tl_gset:cn { g__module_chapter_image_##1_tl }
{
\clist_item:Nn \l__module_tmpa_clist { ##1 }
}
}
}
{
\__module_range_to_list:nN { #1 } \l__module_tmpa_clist
\clist_map_inline:Nn \l__module_tmpa_clist
{
\tl_gset:cn { g__module_chapter_image_##1_tl } { #2 }
}
}
}
\keys_define:nn { module }
{
chapter-image.code:n = \__module_chapter_image_parser:nn #1
}
\NewDocumentCommand{\setup}{m}{ \keys_set:nn { module } {#1} }
\NewDocumentCommand{\showimg}{m}{ \tl_use:c {g__module_chapter_image_#1_tl} }
\ExplSyntaxOff
\begin{document}
\setup{%
chapter-image = {1, 3-5, 7-9}{image.png},
chapter-image = {2, 6, 10-15}{cover.jpg},
% chapter-image = {*}{image1, image2, image3, image4}
}
\showimg{1}
\showimg{4}
\showimg{10}
\end{document}