summaryrefslogtreecommitdiff
path: root/macros/xetex/latex/exam-zh/tex/exam-zh-question.sty
diff options
context:
space:
mode:
Diffstat (limited to 'macros/xetex/latex/exam-zh/tex/exam-zh-question.sty')
-rw-r--r--macros/xetex/latex/exam-zh/tex/exam-zh-question.sty278
1 files changed, 226 insertions, 52 deletions
diff --git a/macros/xetex/latex/exam-zh/tex/exam-zh-question.sty b/macros/xetex/latex/exam-zh/tex/exam-zh-question.sty
index 825a6ad991..6651de7383 100644
--- a/macros/xetex/latex/exam-zh/tex/exam-zh-question.sty
+++ b/macros/xetex/latex/exam-zh/tex/exam-zh-question.sty
@@ -9,22 +9,34 @@
\RequirePackage{expl3}
\RequirePackage{xparse}
-\ProvidesExplPackage {exam-zh-question} {2022-07-28} {v0.1.13}
+\ProvidesExplPackage {exam-zh-question} {2022-08-09} {v0.1.15}
{exam-zh question module}
+
\RequirePackage { amsthm }
\@ifpackageloaded { tcolorbox }
{ \tcbuselibrary { breakable } }
{ \RequirePackage [ most ] { tcolorbox } }
-\RequirePackage { zref-savepos }
-\RequirePackage { ulem }
+% \RequirePackage { zref-savepos }
+\RequirePackage { xeCJKfntef }
+
+% https://github.com/CTeX-org/forum/issues/264#issuecomment-1200087776
+\disable@package@load { etex }
+ {
+ \cs_set_eq:NN \globcount \newcount
+ \cs_set_eq:NN \globdimen \newdimen
+ }
+\RequirePackage { linegoal }
+
\ExplSyntaxOff
+
\usetikzlibrary{shapes.misc}
\ExplSyntaxOn
+
\NewDocumentCommand \questionsetup { m }
{ \keys_set:nn { exam-zh / question } { #1 } }
\NewDocumentCommand \fillinsetup { m }
@@ -267,9 +279,10 @@
\prg_generate_conditional_variant:Nnn \regex_extract_once:nnN { nxN } { F }
\cs_new:Npn \__examzh_question_begin_fillin_type_set:
{
- \regex_count:nVN { \[ } %]
+ \regex_count:nVN { \[ } % \]
\l__examzh_question_combine_fillin_args_tl
\l__examzh_question_begin_fillin_args_bracket_num_int
+ \use_none:n { \] } % 消去 \[ 的高亮影响
% \int_use:N \l__examzh_question_begin_fillin_args_bracket_num_int
\int_compare:nNnT { \l__examzh_question_begin_fillin_args_bracket_num_int } = {2}
{
@@ -687,6 +700,12 @@
% fillin 的下划线样式控制
\str_new:N \l__examzh_fillin_type_str
+% fillin type = paren 的括号类型
+\bool_new:N \l__examzh_fillin_paren_banjiao_bool
+
+% fillin 的 width 设置断行时是自动铺满行还是严格按照长度来
+\bool_new:N \l__examzh_fillin_width_fill_bool
+
% 不显示答案时显示的类型
\str_new:N \l__examzh_fillin_no_answer_type_str
@@ -700,25 +719,37 @@
\str_set:Nn \l__examzh_fillin_type_str {#1}
},
show-answer .bool_set:N = \l__examzh_question_show_fillin_answer_bool,
- width .skip_set:N = \l__examzh_fillin_F_width_skip,
+ width .dim_set:N = \l__examzh_fillin_F_width_dim,
+ width-type .choice:,
+ width-type / fill .code:n =
+ { \bool_set_true:N \l__examzh_fillin_width_fill_bool },
+ width-type / normal .code:n =
+ { \bool_set_false:N \l__examzh_fillin_width_fill_bool },
color .tl_set:N = \l__examzh_fillin_color_tl,
text-color .tl_set:N = \l__examzh_fillin_text_color_tl,
no-answer-type .choices:nn =
{ blacktriangle, counter, none }
{ \str_set:Nx \l__examzh_fillin_no_answer_type_str { \l_keys_choice_tl } },
no-answer-counter-index .int_gset:N = \g__examzh_fillin_no_answer_counter_int,
- no-answer-counter-label .tl_set:N = \l__examzh_fillin_label_tl
+ no-answer-counter-label .tl_set:N = \l__examzh_fillin_label_tl,
+ paren-type .choice:,
+ paren-type / banjiao .code:n =
+ { \bool_set_true:N \l__examzh_fillin_paren_banjiao_bool },
+ paren-type / quanjiao .code:n =
+ { \bool_set_false:N \l__examzh_fillin_paren_banjiao_bool },
}
\keys_set:nn { exam-zh / fillin }
{
type = line,
show-answer = false,
- width = 3em plus 1em minus 1em,
+ width = 3em,
color = black,
text-color = black,
no-answer-type = blacktriangle,
no-answer-counter-index = 1,
- no-answer-counter-label = \arabic*
+ no-answer-counter-label = \arabic*,
+ paren-type = banjiao,
+ width-type = fill,
}
\keys_define:nn { exam-zh }
@@ -756,8 +787,7 @@
}
}
{
- \keys_set:nn { exam-zh / fillin }
- {#2}
+ \keys_set:nn { exam-zh / fillin } {#2}
\bool_if:NTF \l__examzh_question_show_fillin_answer_bool
{
% 显示答案
@@ -776,7 +806,7 @@
\__examzh_fillin_no_answer_typeset:
}
}
- \group_end:
+ \group_end:
\space \ignorespaces
}
\msg_new:nnn { exam-zh / fillin } { no-such-noanswertype }
@@ -924,22 +954,45 @@
}
\cs_new:Npn \__examzh_fillin_uline_F:
{
- \uline { \hspace* { \l__examzh_fillin_F_width_skip } }
- }
-\cs_new:Nn \__examzh_fillin_uline:
- {
- \bgroup
- \color{ \l__examzh_fillin_text_color_tl }
- \markoverwith{\textcolor{black}{\rule[-0.7ex]{2pt}{0.4pt}}}
- \ULon
+ % \uline { \hspace* { \l__examzh_fillin_F_width_dim } }
+ \__examzh_fillin_breakable_hspace:NN \CJKunderline \allowbreak
+ }
+% \cs_new:Nn \__examzh_fillin_uline:
+ % {
+ % \bgroup
+ % \color{ \l__examzh_fillin_text_color_tl }
+ % \markoverwith{\textcolor{black}{\rule[-0.7ex]{2pt}{0.4pt}}}
+ % \ULon
+% xeCJKfntef.sty
+% xeCJK: 修复下划线中数学公式的错误处理
+% https://github.com/CTeX-org/ctex-kit/commit/ad44c6674bb377653544349f23b7c629bc9e4677
+\RenewDocumentCommand \CJKunderline { s t- s o }
+ {
+ \xeCJK_ulem_group_begin:
+ \xeCJK_fntef_boot:nnNNNn { underline } { uline } #1#2#3 {#4}
+ \xeCJK_fntef_initial:nnn
+ { \l__xeCJK_uline_depth_tl }
+ { \l__xeCJK_uline_sep_tl }
+ {
+ \l__xeCJK_uline_format_tl
+ \tex_vrule:D
+ height \dim_eval:n { \l__xeCJK_uline_thickness_tl }
+ depth \c_zero_dim
+ width .2em
+ }
+ % 给 CJKunderline 加了颜色控制
+ \color { \l__examzh_fillin_text_color_tl }
+ \xeCJK_ulem_on:n
}
+ % }
\cs_new:Npn \__examzh_fillin_uline_breakline_T:
{
- % \CJKunderline*
+ \CJKunderline*
% \uline
- \__examzh_fillin_uline:
+ % \__examzh_fillin_uline:
{
\hspace* { 0.5em plus .5em minus .5em }
+ % \color{ \l__examzh_fillin_text_color_tl }
\l_tmpa_tl
% 答案很长时,不能完全显示,答案很长时,不能完全显示
\hspace* { 0.5em plus .5em minus .5em }
@@ -947,27 +1000,65 @@
}
\cs_new:Npn \__examzh_fillin_paren_T:
{
- (
- \hspace* { 0.5em plus .5em minus .5em }
- \group_begin:
- \box_use_drop:N \l_tmpa_box
- \group_end:
- \hspace* { 0.5em plus .5em minus .5em }
- )
+ \bool_if:NTF \l__examzh_fillin_paren_banjiao_bool
+ {
+ (
+ \hspace* { 0.5em plus .5em minus .5em }
+ \group_begin:
+ \box_use_drop:N \l_tmpa_box
+ \group_end:
+ \hspace* { 0.5em plus .5em minus .5em }
+ )
+ }
+ {
+ (
+ \hspace* { 0.5em plus .5em minus .5em }
+ \group_begin:
+ \box_use_drop:N \l_tmpa_box
+ \group_end:
+ \hspace* { 0.5em plus .5em minus .5em }
+ )
+ }
}
\cs_new:Npn \__examzh_fillin_paren_breakline_T:
{
- (
- \hspace* { 0.5em plus .5em minus .5em }
- \group_begin:
- \l_tmpa_tl
- \group_end:
- \hspace* { 0.5em plus .5em minus .5em }
- )
+ \bool_if:NTF \l__examzh_fillin_paren_banjiao_bool
+ {
+ (
+ \hspace* { 0.5em plus .5em minus .5em }
+ \group_begin:
+ \l_tmpa_tl
+ \group_end:
+ \hspace* { 0.5em plus .5em minus .5em }
+ )
+ }
+ {
+ (
+ \hspace* { 0.5em plus .5em minus .5em }
+ \group_begin:
+ \l_tmpa_tl
+ \group_end:
+ \hspace* { 0.5em plus .5em minus .5em }
+ )
+ }
}
+\box_new:N \c__examzh_banjiao_right_brace_box
+\box_new:N \c__examzh_quanjiao_right_brace_box
+\hbox_set:Nn \c__examzh_banjiao_right_brace_box { ) }
+\hbox_set:Nn \c__examzh_quanjiao_right_brace_box { ) }
+\dim_const:Nn \c__examzh_banjiao_right_brace_width_dim % (
+ { \box_wd:N \c__examzh_banjiao_right_brace_box }
+\dim_const:Nn \c__examzh_quanjiao_right_brace_width_dim % (
+ { \box_wd:N \c__examzh_quanjiao_right_brace_box }
\cs_new:Npn \__examzh_fillin_paren_F:
{
- ( \hspace* { \l__examzh_fillin_F_width_skip} )
+ \bool_if:NTF \l__examzh_fillin_paren_banjiao_bool
+ {
+ ( \__examzh_fillin_breakable_hspace:NN \use:n \nobreak \kern-\c__examzh_banjiao_right_brace_width_dim ) \allowbreak
+ }
+ {
+ ( \__examzh_fillin_breakable_hspace:NN \use:n \nobreak \kern-\c__examzh_quanjiao_right_brace_width_dim )\allowbreak
+ }
}
\cs_new:Npn \__examzh_fillin_blank_T:
{
@@ -987,7 +1078,8 @@
}
\cs_new:Npn \__examzh_fillin_blank_F:
{
- \hspace* { \l__examzh_fillin_F_width_skip }
+ % \hspace* { \l__examzh_fillin_F_width_dim }
+ \__examzh_fillin_breakable_hspace:NN \use:n \allowbreak
}
\tikzset
{
@@ -1037,6 +1129,77 @@
\hspace* { 0.5em plus .5em minus .5em }
}
+% 通过循环来达到自动断行的空白下划线
+\cs_generate_variant:Nn \dim_sub:Nn { NV }
+\cs_generate_variant:Nn \dim_add:Nn { NV }
+\cs_generate_variant:Nn \dim_set:Nn { NV, Nx }
+% 用来检测是否处于 list 环境中
+\bool_new:N \l__if_list_bool
+\int_new:N \l__list_depth_int
+\cs_generate_variant:Nn \dim_set:Nn { Nx }
+\AddToHook { cmd / list / after }
+ {
+ \bool_set_true:N \l__if_list_bool
+ \int_incr:N \l__list_depth_int
+ \dim_if_exist:cF { l__list_leftmargin_ \int_to_roman:n { \l__list_depth_int } _dim }
+ {
+ \dim_new:c { l__list_leftmargin_ \int_to_roman:n { \l__list_depth_int } _dim }
+ }
+ % 用来储存相应层级的 \leftmargin 值
+ \dim_set_eq:cN { l__list_leftmargin_ \int_to_roman:n { \l__list_depth_int } _dim } \leftmargin
+ }
+\AddToHook { cmd / endlist / before }
+ { \int_zero:N \l__list_depth_int }
+
+\cs_new:Npn \__examzh_fillin_breakable_hspace:NN #1#2
+ % #1: CJKunderline / use:n
+ % #2: \allowbreak
+ {
+ % 比较 \l__examzh_fillin_F_width_dim 和 linegoal
+ \dim_compare:nNnTF { \l__examzh_fillin_F_width_dim } > { \linegoal }
+ {
+ % 超过 linegoal 就排一段 linegoal,然后 \l__examzh_fillin_F_width_dim 减去 linegoal 长度
+ \dim_set:NV \l_tmpa_dim \linegoal
+ % 是否处于 list 环境中
+ \bool_if:NTF \l__if_list_bool
+ {
+ % 加上 1 到 当前层级的 leftmargin 才能让 list 中的 linegoal 正常
+ \int_step_inline:nn { \l__list_depth_int }
+ {
+ \dim_add:Nn \l_tmpa_dim { \dim_use:c { l__list_leftmargin_ \int_to_roman:n { ##1 } _dim } }
+ }
+ #1 { \hspace { \l_tmpa_dim } }
+ }
+ {
+ % 正文中
+ #1 { \hspace { \linegoal } }
+ }
+ \dim_sub:NV \l__examzh_fillin_F_width_dim \l_tmpa_dim
+ \dim_while_do:nNnn { \l__examzh_fillin_F_width_dim } > { \linewidth }
+ {
+ % 循环:\l__examzh_fillin_F_width_dim 和 \linewidth 比较,大的话就排一个,然后减掉 linewidth
+ \\ #1 { \hspace* { \linewidth } }
+ \dim_sub:Nn \l__examzh_fillin_F_width_dim { \linewidth }
+ }
+ % \\ #1 { \hspace* { \linewidth } }
+ \dim_compare:nNnT { \l__examzh_fillin_F_width_dim } < { \linewidth }
+ {
+ % 最后一行是否 fill
+ \bool_if:NTF \l__examzh_fillin_width_fill_bool
+ {
+ \\ #1 { \hspace* { \linewidth } }
+ }
+ {
+ \\ #1 { \hspace* { \l__examzh_fillin_F_width_dim } }
+ }
+ }
+ }
+ {
+ #1 { \hspace* { \l__examzh_fillin_F_width_dim } }
+ }
+ #2
+ }
+
\dim_new:N \l__examzh_blacktriangle_length_dim
\dim_set:Nn \l__examzh_blacktriangle_length_dim { .7em }
@@ -1149,9 +1312,11 @@
% \ignorespaces
% 是否要新起一段开始
\bool_if:NT \l__examzh_solution_par_break_bool { \par }
- \group_begin:
+ % \group_begin:
+ \begingroup
\color { \l__examzh_solution_text_color_tl } #1
- \group_end:
+ \endgroup
+ % \group_end:
\bool_if:NT \l__examzh_solution_show_qed_bool
{ \popQED }
% \endtrivlist
@@ -1164,6 +1329,7 @@
\NewDocumentCommand { \score } { O{} m }
{
\group_begin:
+ \keys_set:nn { exam / question } {#1}
\mode_if_math:TF
{
\__examzh_score_math_version:n { #2 }
@@ -1179,20 +1345,24 @@
{
\__examzh_math_cdotfill:n
{
- \l__examzh_score_format_tl
- \l__examzh_score_pre_content_tl
- #1
- \l__examzh_score_post_content_tl
+ \group_begin:
+ \l__examzh_score_format_tl
+ \l__examzh_score_pre_content_tl
+ #1
+ \l__examzh_score_post_content_tl
+ \group_end:
}
}
{
\__examzh_math_nodotfill:n
{
{
- \l__examzh_score_format_tl
- \l__examzh_score_pre_content_tl
- #1
- \l__examzh_score_post_content_tl
+ \group_begin:
+ \l__examzh_score_format_tl
+ \l__examzh_score_pre_content_tl
+ #1
+ \l__examzh_score_post_content_tl
+ \group_end:
}
}
}
@@ -1201,14 +1371,18 @@
{
\bool_if:NTF \l__examzh_score_show_leader_bool
{
- \__examzh_cdotfill:
- \l__examzh_score_format_tl
- \l__examzh_score_pre_content_tl #1 \l__examzh_score_post_content_tl
+ \group_begin:
+ \__examzh_cdotfill:
+ \l__examzh_score_format_tl
+ \l__examzh_score_pre_content_tl #1 \l__examzh_score_post_content_tl
+ \group_end:
}
{
\hfill
- \l__examzh_score_format_tl
- \l__examzh_score_pre_content_tl #1 \l__examzh_score_post_content_tl
+ \group_begin:
+ \l__examzh_score_format_tl
+ \l__examzh_score_pre_content_tl #1 \l__examzh_score_post_content_tl
+ \group_end:
}
\par \noindent \ignorespaces
}