加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
exam-zh-chinese-english.sty 20.23 KB
一键复制 编辑 原始数据 按行查看 历史
kangweixia_xdyy 提交于 2024-03-23 16:08 . 修改版本号
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
%
% Copyright (c) 2024 Kangwei Xia, Lijun Guo
% Released under the LaTeX Project Public License v1.3c License.
% Repository: https://gitee.com/xkwxdyy/exam-zh
%
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{expl3}
\ProvidesExplPackage {exam-zh-chinese-english} {2024-03-23} {v0.2.3}
{exam-zh chinese and english module}
\PassOptionsToPackage { tcolorbox } { most }
\RequirePackage { tcolorbox }
\RequirePackage { varwidth }
\keys_define:nn { exam-zh }
{ select .meta:nn = { exam-zh / select } {#1} }
% 选择环境 select
\str_new:N \l__examzh_select_mark_position_str % mark 的方位
\keys_define:nn { exam-zh / select }
{
mark-symbol .tl_set:N = \l__examzh_select_mark_symbol_tl,
mark-position .code:n =
{
\str_set:Nn \l__examzh_select_mark_position_str {#1}
},
mark-xshift .dim_set:N = \l__examzh_select_mark_xshift_dim,
mark-yshift .dim_set:N = \l__examzh_select_mark_yshift_dim,
separator .tl_set:N = \l__examzh_select_separator_tl,
pre-content .tl_set:N = \l__examzh_select_pre_content_tl,
post-content .tl_set:N = \l__examzh_select_post_content_tl,
show-mark .bool_set:N = \l__examzh_select_show_mark_bool
}
\keys_set:nn { exam-zh / select }
{
mark-symbol = $\checkmark$,
mark-position = right,
mark-xshift = 0pt,
mark-yshift = 0pt,
separator = \hspace{1em},
pre-content = (,
post-content = ),
show-mark = false
}
\seq_new:N \l__examzh_select_seq % 储存输入的内容
\NewDocumentEnvironment { select } { O{ } +b }
{
% 可选参数
\keys_set:nn { exam-zh / select } {#1}
}
{
% 检测 mark-position 的输入
\__examzh_chinese_select_coffin_position_test:
% 对输入用 \item 进行分割
\seq_set_split:Nnn \l__examzh_select_seq { \sitem } {#2}
\seq_if_empty:NF \l__examzh_select_seq
{ \seq_pop_left:NN \l__examzh_select_seq \l_tmpa_tl }
% 将内容和 mark 符号存入 coffin 并拼接输出
\__examzh_chinese_select_coffin_set_print:N
\l__examzh_select_seq
}
\cs_new:Npn \__examzh_chinese_select_coffin_set_print:N #1
% #1:\l__examzh_select_seq
{
% 前置内容
\l__examzh_select_pre_content_tl
% 主体部分
\seq_map_indexed_inline:Nn #1
% ##1: index
% ##2: content
{
% coffin 的声明
\__examzh_chinese_select_coffin_new:n {##1}
% 看 seq 的项是否开头是 *,是的话去掉 * 和空格存到 content coffin 并且在 mark coffin 里加入 mark,不是的话就只存到 content coffin
\__examzh_chinese_select_coffin_set:nn {##1} {##2}
\bool_if:NT \l__examzh_select_show_mark_bool
{
% 拼接 content coffin 和 mark coffin
\__examzh_chinese_select_coffin_join:n {##1}
}
% 输出 content coffin
\__examzh_chinese_select_coffin_typeset:n {##1}
}
% 后置内容
\l__examzh_select_post_content_tl
}
\cs_new:Npn \__examzh_chinese_select_coffin_new:n #1
{
% 检测是否存在,没有的话就 new 一个
\coffin_if_exist:cF { l__examzh_select_content_ \int_to_roman:n {#1} _ coffin }
{ \coffin_new:c { l__examzh_select_content_ \int_to_roman:n {#1} _ coffin } }
\coffin_if_exist:cF { l__examzh_select_mark_ \int_to_roman:n {#1} _ coffin }
{ \coffin_new:c { l__examzh_select_mark_ \int_to_roman:n {#1} _ coffin } }
}
\cs_new:Npn \__examzh_chinese_select_coffin_set:nn #1#2
% #1: index
% #2: content
{
\tl_if_head_eq_meaning:nNTF {#2} *
{
% 将去掉 * 号后的内容保存进 \l_tmpa_tl
\tl_set:Nx \l_tmpa_tl { \tl_tail:n {#2} }
% 去掉 * 和内容之间的空格
\tl_trim_spaces:N \l_tmpa_tl
% 将处理后的内容存到 content coffin 里
\hcoffin_set:cn { l__examzh_select_content_ \int_to_roman:n {#1} _ coffin }
{ \l_tmpa_tl }
% 将 marksymbol 存到对应的第 #1 个 mark coffin 里
\hcoffin_set:cn { l__examzh_select_mark_ \int_to_roman:n {#1} _ coffin }
{ \l__examzh_select_mark_symbol_tl }
}
{
% 不带 * 的直接存 coffin
\hcoffin_set:cn { l__examzh_select_content_ \int_to_roman:n {#1} _ coffin }
{#2}
}
}
\msg_new:nnn { exam-zh / chinese } { select-no-mark-position }
{
There~is~no~position~named~#1 .\\
Please~read~the~manual~carefully.
}
\cs_new:Npn \__examzh_chinese_select_coffin_position_test:
{
\str_case:VnF \l__examzh_select_mark_position_str
{
{ top } { }
{ above } { }
{ bottom } { }
{ below } { }
{ left } { }
{ right } { }
}
{
\msg_error:nnx { exam-zh / chinese } { select-no-mark-position } { \l__examzh_select_mark_position_str }
}
}
\cs_new:Npn \__examzh_chinese_select_coffin_join:n #1
% #1: index
{
\use:c { __examzh_chinese_select_coffin_join_ \l__examzh_select_mark_position_str :n } {#1}
}
\cs_new:Npn \__examzh_chinese_select_coffin_join_top:n #1
{
\coffin_join:cnncnnnn
{ l__examzh_select_content_ \int_to_roman:n {#1} _ coffin }
{ hc } { t }
{ l__examzh_select_mark_ \int_to_roman:n {#1} _ coffin }
{ hc } { b }
{ \l__examzh_select_mark_xshift_dim }
{ \l__examzh_select_mark_yshift_dim + 2pt }
}
\cs_set_eq:NN
\__examzh_chinese_select_coffin_join_above:n
\__examzh_chinese_select_coffin_join_top:n
\cs_new:Npn \__examzh_chinese_select_coffin_join_bottom:n #1
{
\coffin_join:cnncnnnn
{ l__examzh_select_content_ \int_to_roman:n {#1} _ coffin }
{ hc } { H }
{ l__examzh_select_mark_ \int_to_roman:n {#1} _ coffin }
{ hc } { t }
{ \l__examzh_select_mark_xshift_dim }
{ \l__examzh_select_mark_yshift_dim - 2pt }
}
\cs_set_eq:NN
\__examzh_chinese_select_coffin_join_below:n
\__examzh_chinese_select_coffin_join_bottom:n
\cs_new:Npn \__examzh_chinese_select_coffin_join_left:n #1
{
\coffin_join:cnncnnnn
{ l__examzh_select_content_ \int_to_roman:n {#1} _ coffin }
{ l } { H }
{ l__examzh_select_mark_ \int_to_roman:n {#1} _ coffin }
{ r } { H }
{ \l__examzh_select_mark_xshift_dim }
{ \l__examzh_select_mark_yshift_dim }
}
\cs_new:Npn \__examzh_chinese_select_coffin_join_right:n #1
{
\coffin_join:cnncnnnn
{ l__examzh_select_content_ \int_to_roman:n {#1} _ coffin }
{ r } { H }
{ l__examzh_select_mark_ \int_to_roman:n {#1} _ coffin }
{ l } { H }
{ \l__examzh_select_mark_xshift_dim }
{ \l__examzh_select_mark_yshift_dim }
}
\cs_new:Npn \__examzh_chinese_select_coffin_typeset:n #1
{
\int_compare:nNnTF {#1} = {1}
{
\coffin_typeset:cnnnn
{ l__examzh_select_content_ \int_to_roman:n {#1} _ coffin }
{l} {H} {0pt} {0pt}
}
{
\l__examzh_select_separator_tl
\coffin_typeset:cnnnn
{ l__examzh_select_content_ \int_to_roman:n {#1} _ coffin }
{l} {H} {0pt} {0pt}
}
}
% 连线题 lineto
\clist_clear_new:N \l__examzh_lineto_list_set_clist
\int_zero_new:N \l__examzh_lineto_node_index_int
\keys_define:nn { exam-zh }
{ lineto .meta:nn = { exam-zh / lineto } {#1} }
\keys_define:nn { exam-zh / lineto }
{
xsep .dim_set:N = \l__examzh_lineto_node_xsep_dim,
ysep .dim_set:N = \l__examzh_lineto_node_ysep_dim,
name .tl_set:N = \l__examzh_lineto_name_tl,
list-style .tl_set:N = \l__examzh_lineto_list_style_tl
}
\keys_set:nn { exam-zh / lineto }
{
xsep = .25\linewidth,
ysep = 1cm,
name = \int_to_roman:n { \l__examzh_lineto_node_index_int }
}
\NewDocumentEnvironment { lineto } { O{ } }
{
\begin{center}
\begin{tikzpicture}[#1]
}
{
\end{tikzpicture}
\end{center}
}
\NewDocumentCommand { \linelistset } { O{} m }
{
\int_incr:N \l__examzh_lineto_node_index_int
\group_begin:
\keys_set:nn { exam-zh / lineto } {#1}
\clist_set:Nn \l__examzh_lineto_list_set_clist {#2}
\int_step_inline:nnn {1}
{ \clist_count:N \l__examzh_lineto_list_set_clist }
{
\use:x
{
\exp_not:N \node
[
name = \l__examzh_lineto_name_tl - ##1,
\l__examzh_lineto_list_style_tl
]
at
(
\l__examzh_lineto_node_index_int * \l__examzh_lineto_node_xsep_dim,
- \int_eval:n { ##1 - 1 } * \l__examzh_lineto_node_ysep_dim
)
{ \clist_item:Nn \l__examzh_lineto_list_set_clist {##1} };
}
}
\group_end:
}
\NewDocumentCommand { \lineconnect }{ O{} +m }
{
\clist_set:Nn \l_tmpa_clist {#2}
\int_step_inline:nn { \clist_count:N \l_tmpa_clist - 1 }
{
\use:x
{
\exp_not:N \draw
[line~cap = round, #1]
( \clist_item:Nn \l_tmpa_clist {##1} .east )
--
( \clist_item:Nn \l_tmpa_clist { ##1 + 1 } .west );
}
}
}
% 语文的文章 材料
\keys_define:nn { exam-zh / material }
{
title .tl_set:N = \l__examzh_material_title_content_tl,
title-format .tl_set:N = \l__examzh_material_title_format_tl,
title-material-sep .skip_set:N = \l__examzh_material_title_material_sep_skip,
format .tl_set:N = \l__examzh_material_format_tl,
top-sep .skip_set:N = \l__examzh_material_top_sep_skip,
bottom-sep .skip_set:N = \l__examzh_material_bottom_sep_skip,
author .tl_set:N = \l__examzh_material_author_content_tl,
author-format .tl_set:N = \l__examzh_material_author_format_tl,
title-author-sep .skip_set:N = \l__examzh_material_title_author_sep_skip,
source .tl_set:N = \l__examzh_material_source_content_tl,
source-format .tl_set:N = \l__examzh_material_source_format_tl,
}
\keys_set:nn { exam-zh / material }
{
title-format = \zihao{4},
author-format = \small,
format = \kaishu,
title-author-sep = 2em,
top-sep = 0pt,
bottom-sep = 0pt,
title-material-sep = 0pt,
}
\NewDocumentEnvironment { material } { O{ } +b }
{
\par
\keys_set:nn { exam-zh / material } {#1}
\addvspace { \l__examzh_material_top_sep_skip }
\__examzh_material_title_author_type:
\group_begin:
\l__examzh_material_format_tl
#2
\group_end:
}
{
\tl_if_empty:NF \l__examzh_material_source_content_tl
{
\par
\group_begin:
\hfill
\begin{varwidth}{\textwidth}
\raggedleft
\l__examzh_material_source_format_tl
\l__examzh_material_source_content_tl
\end{varwidth}
\group_end:
}
\par
\addvspace { \l__examzh_material_bottom_sep_skip }
\par
}
\cs_new:Npn \__examzh_material_title_author_type:
{
\tl_if_empty:NF \l__examzh_material_title_content_tl
{
\noindent \hfill
\group_begin:
\l__examzh_material_title_format_tl
\l__examzh_material_title_content_tl
\group_end:
\tl_if_empty:NF \l__examzh_material_author_content_tl
{
\hspace { \l__examzh_material_title_author_sep_skip }
\group_begin:
\l__examzh_material_author_format_tl
\l__examzh_material_author_content_tl
\group_end:
}
\hfill \null
\par
\addvspace { \l__examzh_material_title_material_sep_skip }
}
}
% 古诗
\bool_new:N \l__examzh_poem_type_minipage_bool
\bool_set_true:N \l__examzh_poem_type_minipage_bool
\int_new:N \l__examzh_poem_zhu_index_int
\seq_new:N \g__examzh_poem_zhu_store_seq
\str_new:N \l__examzh_poem_zhu_circlednumber_base_str
\keys_define:nn { exam-zh / poem }
{
title .tl_set:N = \l__examzh_poem_title_content_tl,
title-format .tl_set:N = \l__examzh_poem_title_format_tl,
title-poem-sep .skip_set:N = \l__examzh_poem_title_poem_sep_skip,
format .tl_set:N = \l__examzh_poem_format_tl,
top-sep .skip_set:N = \l__examzh_poem_top_sep_skip,
bottom-sep .skip_set:N = \l__examzh_poem_bottom_sep_skip,
author .tl_set:N = \l__examzh_poem_author_content_tl,
author-format .tl_set:N = \l__examzh_poem_author_format_tl,
title-author-sep .skip_set:N = \l__examzh_poem_title_author_sep_skip,
type .choice:,
type / minipage .code:n = { \bool_set_true:N \l__examzh_poem_type_minipage_bool },
type / chinese .code:n = { \bool_set_false:N \l__examzh_poem_type_minipage_bool },
align .choices:nn =
{ l , c , r }
{ \tl_set:Nx \l__examzh_poem_align_tl { \l_keys_choice_tl } },
zhu-circlednumber-base .choices:nn =
{ tikz, font }
{ \str_set:Nx \l__examzh_poem_zhu_circlednumber_base_str { \l_keys_choice_tl } }
}
\keys_set:nn { exam-zh / poem }
{
title-format = \zihao{5},
author-format = \small,
format = \kaishu,
title-author-sep = 2em,
top-sep = 0pt,
bottom-sep = 1em,
title-poem-sep = 0.25\baselineskip,
type = chinese,
align = l,
zhu-circlednumber-base = font
}
\NewDocumentEnvironment { poem } { O{ } +b }
{
\par
\keys_set:nn { exam-zh / poem } {#1}
\addvspace { \l__examzh_poem_top_sep_skip }
\__examzh_poem_begin:
\__examzh_poem_title_author_type:
\group_begin:
\l__examzh_poem_format_tl
\use:x
{
\exp_not:N \tabular
{ \l__examzh_poem_align_tl }
}
#2
\endtabular
\group_end:
\par
\addvspace { 1em }
}
{
\__examzh_poem_end:
\par
\addvspace { \l__examzh_poem_bottom_sep_skip }
\par
}
\cs_new:Npn \__examzh_poem_title_author_type:
{
\tl_if_empty:NF \l__examzh_poem_title_content_tl
{
% \noindent \hfill
\group_begin:
\l__examzh_poem_title_format_tl
\l__examzh_poem_title_content_tl
\group_end:
\tl_if_empty:NF \l__examzh_poem_author_content_tl
{
\hspace { \l__examzh_poem_title_author_sep_skip }
\group_begin:
\l__examzh_poem_author_format_tl
\l__examzh_poem_author_content_tl
\group_end:
}
% \hfill \null
\par
\addvspace { \l__examzh_poem_title_poem_sep_skip }
}
}
\cs_new:Npn \__examzh_poem_begin:
{
\bool_if:NTF \l__examzh_poem_type_minipage_bool
{
\noindent
\minipage { \linewidth }
\cs_set:Npn \thempfootnote { \examzh_footnote_number:N \c@mpfootnote}
\center
}
{
\int_zero:N \l__examzh_poem_zhu_index_int
\seq_clear:N \g__examzh_poem_zhu_store_seq
\center
}
}
\cs_new:Npn \__examzh_poem_end:
{
\bool_if:NTF \l__examzh_poem_type_minipage_bool
{
\endcenter
\endminipage
}
{
\endcenter
\seq_if_empty:NF \g__examzh_poem_zhu_store_seq
{
\vspace*{-0.7em}
\small
\begin{description}[leftmargin = 2em]
\item[{[注]}]
\seq_map_indexed_inline:Nn \g__examzh_poem_zhu_store_seq
% ##1: index
% ##2: content
{
\__examzh_chinese_circled_number:n {##1} ~ ##2
}
\end{description}
}
}
}
\NewDocumentCommand { \zhu } { o m }
{
\bool_if:NTF \l__examzh_poem_type_minipage_bool
{
\footnote {#2}
}
{
\IfNoValueF {#1}
{
\int_gset:Nn \l__examzh_poem_zhu_index_int {#1 - 1}
}
\__examzh_poem_type_chinese_zhu:n {#2}
}
}
\cs_new:Npn \__examzh_poem_type_chinese_zhu:n #1
{
\int_gincr:N \l__examzh_poem_zhu_index_int
\int_set_eq:NN \l_tmpa_int \l__examzh_poem_zhu_index_int
\unskip
% 输出符号
\textsuperscript
{ \__examzh_chinese_circled_number:n { \l__examzh_poem_zhu_index_int } }
% 将参数存起来
\seq_gput_right:Nx \g__examzh_poem_zhu_store_seq
{ #1 }
}
\cs_new:Npn \__examzh_chinese_circled_number:n #1
{
\str_case:Vn \l__examzh_poem_zhu_circlednumber_base_str
{
{ tikz } { \__examzh_chinese_tikz_circled_number:n {#1} }
{ font } { \__examzh_chinese_tikz_circled_number:n {#1} }
}
}
% 基于字体的带圈数字
\cs_new:Npn \__examzh_chinese_font_circled_number:n #1
{
\int_set:Nn \l_tmpa_int {#1}
\int_compare:nNnTF { \l_tmpa_int } = { 0 }
{ \int_set:Nn \l_tmpa_int { "24EA } }
{
\int_compare:nNnTF { \l_tmpa_int } < { 21 }
{ \int_add:Nn \l_tmpa_int { "245F } }
{
\int_compare:nNnTF { \l_tmpa_int } < { 36 }
{ \int_add:Nn \l_tmpa_int { "3250 } }
{
\int_compare:nNnTF { \l_tmpa_int } < { 51 }
{ \int_add:Nn \l_tmpa_int { "32B0 } }
{
\msg_error:nnn { exam-zh / poem }
{ invalid-circled-number } { \int_use:N \l_tmpa_int }
}
}
}
}
\group_begin:
\CJKfamily+ { }
\symbol { \l_tmpa_int }
\group_end:
}
\msg_new:nnn { exam-zh / poem } { invalid-circled-number }
{ Invalid~ circled~ number~ #1. }
% tikz 绘制带圈数字
\fp_new:N \l__examzh_chinese_tikz_circled_number_xscale_fp % 水平压缩系数
\fp_new:N \l__examzh_chinese_tikz_circled_number_yscale_fp % 垂直压缩系数
\dim_new:N \l__examzh_chinese_tikz_circled_number_total_hegiht_dim % 数字的总高度
\dim_new:N \l__examzh_chinese_tikz_circled_number_radius_dim % 半径
\cs_new:Npn \__examzh_chinese_tikz_circled_number_aux:n #1
{
% 根据数字大小设置压缩系数
\fp_set:Nn \l__examzh_chinese_tikz_circled_number_xscale_fp
{
\int_compare:nNnTF {#1} < { 10 }
{ 0.9 }
{
\int_compare:nNnTF {#1} < { 100 }
{ 0.7 }
{ 0.5 }
}
}
\fp_set:Nn \l__examzh_chinese_tikz_circled_number_yscale_fp
{
\int_compare:nNnTF {#1} < { 10 }
{ 0.9 }
{
\int_compare:nNnTF {#1} < { 100 }
{ 0.8 }
{ 0.6 }
}
}
% 获取数字的高度
\hbox_set:Nn \l_tmpa_box {#1}
\dim_set:Nn \l__examzh_chinese_tikz_circled_number_total_hegiht_dim
{ \box_ht:N \l_tmpa_box + \box_dp:N \l_tmpa_box }
% 设置圆的半径
\dim_set:Nn \l__examzh_chinese_tikz_circled_number_radius_dim
{ \dim_eval:n { \l__examzh_chinese_tikz_circled_number_total_hegiht_dim / 2 + 0.34 ex } }
% 绘制
\tikz [ baseline ]
{
\node
[ inner~sep = 0pt, outer~sep = 0pt ]
at (0, \dim_use:N \l__examzh_chinese_tikz_circled_number_total_hegiht_dim / 2 )
{
\hbox_set:Nn \l_tmpa_box
{
\int_compare:nNnTF {#1} > {9}
{ \textbf {#1} }
{#1}
}
\makebox[0.35em][c]
{
% \scalebox { \fp_use:N \l__examzh_chinese_tikz_circled_number_xscale_fp }
% [ \fp_use:N \l__examzh_chinese_tikz_circled_number_yscale_fp ]
\box_scale:Nnn \l_tmpa_box
{ \fp_use:N \l__examzh_chinese_tikz_circled_number_xscale_fp }
{ \fp_use:N \l__examzh_chinese_tikz_circled_number_yscale_fp }
\box_use_drop:N \l_tmpa_box
}
};
\draw (0, \l__examzh_chinese_tikz_circled_number_total_hegiht_dim / 2 )
circle ( \l__examzh_chinese_tikz_circled_number_radius_dim );
}
}
\cs_new:Npn \__examzh_chinese_tikz_circled_number:n #1
{
\__examzh_chinese_tikz_circled_number_aux:n { \int_eval:n {#1} }
}
% 作文框
\NewDocumentEnvironment { writingbox } { O{ } +b }
{
\begin{tcolorbox}
[
% 直角
sharp~corners = all,
% 颜色
colback = white,
colbacktitle = white,
% colframe = white,
coltitle = black,
% 边框粗细
boxrule = 1pt,
titlerule = 0pt,
% 间距
toptitle = 4pt,
% 字体
fonttitle = \centering,
% 首行缩进
parbox = false,
before~upper = \indent,
% 跨页
breakable,
enhanced~jigsaw,
#1
]
#2
}
{
\end{tcolorbox}
}
\endinput
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化