% -------------------------------------------------------------------------- % the EXSHEETS package % % Yet another package for the creation of exercise sheets % % -------------------------------------------------------------------------- % Clemens Niederberger % Web: https://bitbucket.org/cgnieder/exsheets/ % E-Mail: contact@mychemistry.eu % -------------------------------------------------------------------------- % Copyright 2011-2019 Clemens Niederberger % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Clemens Niederberger. % -------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % -------------------------------------------------------------------------- % HEADINGS FOR QUESTIONS AND SOLUTIONS % the 6 base coffins: \ProvidesFile{exsheets_headings.def} [ \c_exsheets_date_tl \c_space_tl v\c_exsheets_version_tl \c_space_tl ExSheets~ headings~ object] % the object variables: \bool_new:N \l__exsheets_heading_runin_bool \bool_new:N \l__exsheets_heading_inline_bool \bool_new:N \l__exsheets_heading_indent_first_bool \bool_new:N \l__exsheets_heading_toc_reversed_bool \dim_new:N \l__exsheets_heading_above_dim \dim_new:N \l__exsheets_heading_below_dim \fp_new:N \l__exsheets_heading_scale_fp \tl_new:N \l__exsheets_heading_main_tl \tl_new:N \l__exsheets_heading_pre_code_tl \tl_new:N \l__exsheets_heading_post_code_tl \tl_new:N \l__exsheets_heading_title_format_tl \tl_new:N \l__exsheets_heading_title_pre_code_tl \tl_set:Nn \l__exsheets_heading_title_pre_code_tl { \use:n } \tl_new:N \l__exsheets_heading_title_post_code_tl \tl_new:N \l__exsheets_heading_number_format_tl \tl_new:N \l__exsheets_heading_number_pre_code_tl \tl_set:Nn \l__exsheets_heading_number_pre_code_tl { \use:n } \tl_new:N \l__exsheets_heading_number_post_code_tl \tl_new:N \l__exsheets_heading_subtitle_format_tl \tl_new:N \l__exsheets_heading_subtitle_pre_code_tl \tl_set:Nn \l__exsheets_heading_subtitle_pre_code_tl { \use:n } \tl_new:N \l__exsheets_heading_subtitle_post_code_tl \tl_new:N \l__exsheets_heading_points_format_tl \tl_new:N \l__exsheets_heading_points_pre_code_tl \tl_set:Nn \l__exsheets_heading_points_pre_code_tl { \use:n } \tl_new:N \l__exsheets_heading_points_post_code_tl \tl_new:N \l__exsheets_heading_points_post_hook_tl \tl_new:N \l__exsheets_heading_joined_coffins_tl \tl_new:N \l__exsheets_heading_attached_coffins_tl \seq_new:N \l__exsheets_heading_joined_coffins_seq \seq_new:N \l__exsheets_heading_attached_coffins_seq % internal object functions: % the following is shamelessly adapted from the `needspace' package by % Peter Wilson and Herries Press \cs_new:Npn \exsheets_needspace:n #1 { \group_begin: \dim_set:Nn \l__exsheets_tmpa_dim { #1 } \skip_vertical:n { \c_zero_dim + \l__exsheets_tmpa_dim } \tex_penalty:D -100 \skip_vertical:n { \c_zero_dim - \l__exsheets_tmpa_dim } \skip_vertical:N \l__exsheets_tmpa_dim \tex_penalty:D 9999 \skip_vertical:n { - \l__exsheets_tmpa_dim } \skip_vertical:N \c_zero_dim \group_end: } \AtBeginDocument { \cs_if_exist:NF \needspace { \cs_set_eq:NN \needspace \exsheets_needspace:n } } \cs_generate_variant:Nn \seq_set_split:Nnn { NnV } \cs_new:Npn \__exsheets_join:N #1 { \seq_map_inline:Nn #1 { \tl_if_blank:nF { ##1 } { \exp_after:wN \__exsheets_join_coffin_sequence:w ##1 } } } \cs_new:Npn \__exsheets_join_coffin_sequence:w #1[#2,#3] #4[#5,#6] (#7,#8) { \__exsheets_join_coffins:nnnnnnnn {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8} } \cs_new:Npn \__exsheets_join_coffins:nnnnnnnn #1#2#3#4#5#6#7#8 { \coffin_join:cnncnnnn { l__exsheets_heading_#1_coffin } {#2} {#3} { l__exsheets_heading_#4_coffin } {#5} {#6} {#7} {#8} } \cs_new:Npn \__exsheets_attach:N #1 { \seq_map_inline:Nn #1 { \tl_if_blank:nF {##1} { \exp_after:wN \__exsheets_attach_coffin_sequence:w ##1 } } } \cs_new:Npn \__exsheets_attach_coffin_sequence:w #1[#2,#3]#4[#5,#6](#7,#8) { \__exsheets_attach_coffins:nnnnnnnn {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8} } \cs_new:Npn \__exsheets_attach_coffins:nnnnnnnn #1#2#3#4#5#6#7#8 { \coffin_attach:cnncnnnn { l__exsheets_heading_#1_coffin } {#2} {#3} { l__exsheets_heading_#4_coffin } {#5} {#6} {#7} {#8} } \prop_new:N \l__exsheets_heading_coffins_prop \prg_new_conditional:Npnn \exsheets_if_heading_coffin:n #1 {T,F,TF} { \coffin_if_exist:cTF {l__exsheets_heading_#1_coffin} { \prg_return_true: } { \prg_return_false: } } \cs_new_protected:Npn \exsheets_new_heading_coffin:n #1 { \coffin_new:c {l__exsheets_heading_#1_coffin} } \cs_new_protected:Npn \exsheets_set_heading_coffin:nn #1#2 { \exsheets_if_heading_coffin:nF {#1} { \exsheets_new_heading_coffin:n {#1} } \prop_put:Nnn \l__exsheets_heading_coffins_prop {#1} {#2} } \NewDocumentCommand \DeclareExSheetsHeadingContainer {m+m} { \exsheets_set_heading_coffin:nn {#1} {#2} } \exsheets_new_heading_coffin:n {main} \exsheets_new_heading_coffin:n {pre} \exsheets_new_heading_coffin:n {post} \exsheets_new_heading_coffin:n {title} \exsheets_new_heading_coffin:n {number} \exsheets_new_heading_coffin:n {points} \exsheets_new_heading_coffin:n {subtitle} \cs_new_protected:Npn \exsheets_heading_format:nn #1#2 { \bool_if:NT \l__exsheets_inside_question_bool { \tl_use:c {l_exsheets_heading_#1_question_format_tl} {#2} } \bool_if:NT \l__exsheets_inside_solution_bool { \tl_use:c {l_exsheets_heading_#1_solution_format_tl} {#2} } } % the `exsheets-heading' object: % #1 = title, % #2 = number, % #3 = points % #4 = bonus % #5 = id \DeclareObjectType {exsheets-heading} {5} % the `default' template interface: \DeclareTemplateInterface {exsheets-heading} {default} {5} { inline : boolean = false , runin : boolean = false , indent-first : boolean = false , toc-reversed : boolean = false , vscale : real = 1 , above : length = 2pt , below : length = 2pt , main : tokenlist = , pre-code : tokenlist = , post-code : tokenlist = , title-format : tokenlist = , title-pre-code : tokenlist = , title-post-code : tokenlist = , number-format : tokenlist = , number-pre-code : tokenlist = , number-post-code : tokenlist = , subtitle-format : tokenlist = , subtitle-pre-code : tokenlist = , subtitle-post-code : tokenlist = , points-format : tokenlist = , points-pre-code : tokenlist = , points-post-code : tokenlist = , join : tokenlist = , attach : tokenlist = } % the `default' template code: \DeclareTemplateCode {exsheets-heading} {default} {5} { inline = \l__exsheets_heading_inline_bool , runin = \l__exsheets_heading_runin_bool , indent-first = \l__exsheets_heading_indent_first_bool , toc-reversed = \l__exsheets_heading_toc_reversed_bool , vscale = \l__exsheets_heading_scale_fp , above = \l__exsheets_heading_above_dim , below = \l__exsheets_heading_below_dim , main = \l__exsheets_heading_main_tl , pre-code = \l__exsheets_heading_pre_code_tl , post-code = \l__exsheets_heading_post_code_tl , title-format = \l__exsheets_heading_title_format_tl , title-pre-code = \l__exsheets_heading_title_pre_code_tl , title-post-code = \l__exsheets_heading_title_post_code_tl , number-format = \l__exsheets_heading_number_format_tl , number-pre-code = \l__exsheets_heading_number_pre_code_tl , number-post-code = \l__exsheets_heading_number_post_code_tl , subtitle-format = \l__exsheets_heading_subtitle_format_tl , subtitle-pre-code = \l__exsheets_heading_subtitle_pre_code_tl , subtitle-post-code = \l__exsheets_heading_subtitle_post_code_tl , points-format = \l__exsheets_heading_points_format_tl , points-pre-code = \l__exsheets_heading_points_pre_code_tl , points-post-code = \l__exsheets_heading_points_post_code_tl , join = \l__exsheets_heading_joined_coffins_tl , attach = \l__exsheets_heading_attached_coffins_tl } { \AssignTemplateKeys \bool_if:NT \l__exsheets_heading_inline_bool { \cs_set_eq:NN \exsheets_par: \scan_stop: } \seq_set_split:NnV \l__exsheets_heading_joined_coffins_seq { ; } \l__exsheets_heading_joined_coffins_tl \seq_set_split:NnV \l__exsheets_heading_attached_coffins_seq { ; } \l__exsheets_heading_attached_coffins_tl \bool_if:nTF { \l__exsheets_heading_runin_bool || \l__exsheets_heading_inline_bool } { \hcoffin_set:Nn \l__exsheets_heading_main_coffin { \tl_if_blank:VTF \l__exsheets_heading_main_tl { \tl_use:N \l__exsheets_heading_title_format_tl \strut } { \tl_use:N \l__exsheets_heading_main_tl } } } { \hcoffin_set:Nn \l__exsheets_heading_main_coffin { \parbox { \linewidth } { \tl_if_blank:VTF \l__exsheets_heading_main_tl { \tl_use:N \l__exsheets_heading_title_format_tl \strut } { \tl_use:N \l__exsheets_heading_main_tl } } } } \hcoffin_set:Nn \l__exsheets_heading_title_coffin { \tl_use:N \l__exsheets_heading_title_format_tl \strut \tl_use:N \l__exsheets_heading_title_pre_code_tl { \exsheets_heading_format:nn {title} {#1} } \tl_use:N \l__exsheets_heading_title_post_code_tl } \hcoffin_set:Nn \l__exsheets_heading_number_coffin { \tl_if_blank:VTF \l__exsheets_heading_number_format_tl { \tl_use:N \l__exsheets_heading_title_format_tl } { \tl_use:N \l__exsheets_heading_number_format_tl } \strut \tl_use:N \l__exsheets_heading_number_pre_code_tl { \exsheets_heading_format:nn {title} {#2} } \tl_use:N \l__exsheets_heading_number_post_code_tl } \hcoffin_set:Nn \l__exsheets_heading_subtitle_coffin { \exsheets_if_question_subtitle:T { \strut \tl_use:N \l__exsheets_heading_subtitle_pre_code_tl { \group_begin: \exsheets_heading_format:nn {subtitle} { \exsheets_get_question_property:nn {subtitle} {#5} } \group_end: } \tl_use:N \l__exsheets_heading_subtitle_post_code_tl } } \hcoffin_set:Nn \l__exsheets_heading_points_coffin { \bool_if:NTF \l__exsheets_parse_points_bool { \bool_if:nF { \fp_compare_p:n { #3 = 0 } && \fp_compare_p:n { #4 = 0 } } { \tl_use:N \l__exsheets_heading_points_format_tl \group_begin: \tl_use:N \l__exsheets_heading_title_format_tl \strut \group_end: \tl_use:N \l__exsheets_heading_points_pre_code_tl { \tl_use:N \tl_use:N \l__exsheets_points_format_tl { \fp_compare:nF { #3 = 0 } { \bool_if:nTF { \l__exsheets_points_separate_bonus_bool || \fp_compare_p:n { #4 = 0 } } { \exsheets_parse_points:n {#3} \exsheets_points_name:n {#3} } { \exsheets_parse_points:n {#3} } } \fp_compare:nF { #4 = 0 } { \tl_use:N \l__exsheets_points_pre_bonus_marker_tl \bool_if:nTF { \l__exsheets_points_separate_bonus_bool || \fp_compare_p:n { #3 = 0 } } { \exsheets_print_bonus:n {#4} \tl_use:N \l__exsheets_points_post_bonus_marker_tl } { \exsheets_parse_bonus:n {#4} \tl_use:N \l__exsheets_points_post_bonus_marker_tl \exsheets_points_name:n { #3 + #4 } } } } } \tl_use:N \l__exsheets_heading_points_post_code_tl } } {% points/parse = false \tl_use:N \l__exsheets_heading_points_format_tl \group_begin: \tl_use:N \l__exsheets_heading_title_format_tl \strut \group_end: \tl_if_eq:xnF {#3} {0} { \tl_use:N \l__exsheets_heading_points_pre_code_tl { \exsheets_print_points:n {#3} } \tl_use:N \l__exsheets_heading_points_post_code_tl } } } % this allows users to provide their own point system while also using % exsheets' positioning mechanism: \tl_use:N \l__exsheets_heading_points_post_hook_tl \bool_if:nT { !\l__exsheets_heading_runin_bool && !\l__exsheets_heading_inline_bool } { \coffin_resize:Nnn \l__exsheets_heading_main_coffin { \linewidth } { \fp_to_decimal:N \l__exsheets_heading_scale_fp \coffin_ht:N \l__exsheets_heading_main_coffin + \l__exsheets_heading_below_dim } } \hcoffin_set:Nn \l__exsheets_heading_pre_coffin { \tl_use:N \l__exsheets_heading_pre_code_tl } \hcoffin_set:Nn \l__exsheets_heading_post_coffin { \tl_use:N \l__exsheets_heading_post_code_tl } \coffin_join:NnnNnnnn \l__exsheets_heading_main_coffin {l} {t} \l__exsheets_heading_pre_coffin {l} {b} {0pt} {0pt} \coffin_join:NnnNnnnn \l__exsheets_heading_main_coffin {l} {b} \l__exsheets_heading_post_coffin {l} {t} {0pt} {0pt} \prop_map_inline:Nn \l__exsheets_heading_coffins_prop { \hcoffin_set:cn {l__exsheets_heading_##1_coffin} {##2} } \__exsheets_join:N \l__exsheets_heading_joined_coffins_seq \__exsheets_attach:N \l__exsheets_heading_attached_coffins_seq \bool_if:NTF \l__exsheets_heading_inline_bool { \exsheets_questions_debug:n {#5} } { \skip_vertical:N \l__exsheets_heading_above_dim \exsheets_needspace:n { \coffin_ht:N \l__exsheets_heading_main_coffin + \coffin_dp:N \l__exsheets_heading_main_coffin + \l__exsheets_heading_below_dim + \baselineskip } \exsheets_questions_debug:n {#5} \noindent } \skip_set:Nn \parfillskip { 0pt plus 1fil } \bool_if:nT { \l__exsheets_questions_totoc_bool && \l__exsheets_inside_question_bool } { \use:c {phantomsection} \addcontentsline { toc } { \l__exsheets_questions_toclevel_tl } { \bool_if:NTF \l__exsheets_heading_toc_reversed_bool { #2 \ #1 } { #1 \ #2 } } } \bool_if:nT { \l__exsheets_solutions_totoc_bool && !\l__exsheets_inside_question_bool } { \use:c {phantomsection} \addcontentsline { toc } { \l__exsheets_solutions_toclevel_tl } { \bool_if:NTF \l__exsheets_heading_toc_reversed_bool { #2 \ #1 } { #1 \ #2 } } } \coffin_typeset:Nnnnn \l__exsheets_heading_main_coffin { H } { l } { 0pt }{ 0pt } \bool_if:nT { !\l__exsheets_heading_runin_bool && !\l__exsheets_heading_inline_bool } { \skip_vertical:N \l__exsheets_heading_below_dim \dim_compare:nF { \parskip = 0pt } { \skip_vertical:n { -\parskip } } \bool_if:NTF \l__exsheets_heading_indent_first_bool { \@afterindenttrue\@afterheading } { \@afterindentfalse\@afterheading } } } % the two basic instances: % BLOCK: \DeclareInstance { exsheets-heading } { block } { default } { join = { title[r,B] number[l,B] (1ex,0pt) } , attach = { main[l,vc] title[l,vc] (0pt,0pt) ; main[r,vc] points[l,vc] (\marginparsep,0pt) } } % RUNIN: \DeclareInstance { exsheets-heading } { runin } { default } { runin = true , number-post-code = \c_space_tl , attach = { main[l,vc] points[l,vc] (\linewidth + \marginparsep,0pt) } , join = { main[r,vc] title[r,vc] (0pt,0pt) ; main[r,vc] number[l,vc] (1ex,0pt) } } \file_input_stop: