summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/exsheets
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/exsheets
Initial commit
Diffstat (limited to 'macros/latex/contrib/exsheets')
-rw-r--r--macros/latex/contrib/exsheets/README38
-rw-r--r--macros/latex/contrib/exsheets/exsheets-listings.sty147
-rw-r--r--macros/latex/contrib/exsheets/exsheets.sty3238
-rw-r--r--macros/latex/contrib/exsheets/exsheets_configurations.cfg32
-rw-r--r--macros/latex/contrib/exsheets/exsheets_en.pdfbin0 -> 665754 bytes
-rw-r--r--macros/latex/contrib/exsheets/exsheets_en.tex2650
-rw-r--r--macros/latex/contrib/exsheets/exsheets_headings.cfg361
-rw-r--r--macros/latex/contrib/exsheets/exsheets_headings.def474
-rw-r--r--macros/latex/contrib/exsheets/grading-table.pdfbin0 -> 26255 bytes
-rw-r--r--macros/latex/contrib/exsheets/grading-table.tex48
10 files changed, 6988 insertions, 0 deletions
diff --git a/macros/latex/contrib/exsheets/README b/macros/latex/contrib/exsheets/README
new file mode 100644
index 0000000000..d6ca6030ca
--- /dev/null
+++ b/macros/latex/contrib/exsheets/README
@@ -0,0 +1,38 @@
+--------------------------------------------------------------------------
+EXSHEETS 2017/02/08 v0.21i
+bundled packages:
+the EXSHEETS package
+ Yet another package for the creation of exercise sheets
+the EXSHEETS-LISTINGS package
+ Using listings in exsheets
+
+--------------------------------------------------------------------------
+Clemens Niederberger
+Web: https://bitbucket.org/cgnieder/exsheets/
+E-Mail: contact@mychemistry.eu
+--------------------------------------------------------------------------
+Copyright 2011-2017 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.
+--------------------------------------------------------------------------
+The exsheets bundle consists of the files
+ - exsheets.sty, exsheets-listings.sty,
+ exsheets_headings.def, exsheets_headings.cfg,
+ exsheets_configurations.cfg,
+ exsheets_en.tex, exsheets_en.pdf
+
+ - README
+--------------------------------------------------------------------------
+If you have any ideas, questions, suggestions or bugs to report, please
+feel free to contact me.
+--------------------------------------------------------------------------
diff --git a/macros/latex/contrib/exsheets/exsheets-listings.sty b/macros/latex/contrib/exsheets/exsheets-listings.sty
new file mode 100644
index 0000000000..8e77c4aff4
--- /dev/null
+++ b/macros/latex/contrib/exsheets/exsheets-listings.sty
@@ -0,0 +1,147 @@
+% ----------------------------------------------------------------------------
+% the EXSHEETS-LISTINGS package
+%
+% Using listings with exsheets
+%
+% ----------------------------------------------------------------------------
+% Clemens Niederberger
+% Web: https://bitbucket.org/cgnieder/exsheets/
+% E-Mail: contact@mychemistry.eu
+% ----------------------------------------------------------------------------
+% Copyright 2011-2017 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.
+% ----------------------------------------------------------------------------
+\RequirePackage{exsheets,listings}
+% we need this loaded before expl3 syntax is activated:
+\lst@RequireAspects{writefile}
+\ExplSyntaxOn
+\ProvidesExplPackage{exsheets-listings}
+ {\c_exsheets_date_tl}
+ {\c_exsheets_version_tl}
+ {listings~ in~ exsheets}
+
+% ----------------------------------------------------------------------------
+% variables:
+\int_new:N \g__exsheets_listings_question_int
+\int_new:N \g__exsheets_listings_solution_int
+
+\tl_new:N \l__exsheets_listings_question_pre_tl
+\tl_new:N \l__exsheets_listings_question_post_tl
+\tl_new:N \l__exsheets_listings_question_options_tl
+\tl_new:N \l__exsheets_listings_question_code_tl
+\tl_new:N \l__exsheets_listings_solution_pre_tl
+\tl_new:N \l__exsheets_listings_solution_post_tl
+\tl_new:N \l__exsheets_listings_solution_options_tl
+\tl_new:N \l__exsheets_listings_solution_code_tl
+\tl_new:N \l__exsheets_listings_question_points_tl
+
+% ----------------------------------------------------------------------------
+% listings style for questions and solutions:
+\keys_define:nn {exsheets}
+ {
+ question / listings .tl_set:N = \l__exsheets_listings_question_code_tl ,
+ solution / listings .tl_set:N = \l__exsheets_listings_solution_code_tl
+ }
+
+% ----------------------------------------------------------------------------
+% expansion help:
+\cs_new:Npn \__exsheets_question_expandopt:Nnnnn #1#2#3#4#5
+ { #1{#2}[#3]{#4}#5 }
+\cs_generate_variant:Nn \__exsheets_question_expandopt:Nnnnn { NnVox }
+
+\cs_new:Npn \__exsheets_question_expand_opt_and_body:Nnnn #1#2#3#4
+ { #1{#2}[#3]#4 }
+\cs_generate_variant:Nn \__exsheets_question_expand_opt_and_body:Nnnn { NnVx }
+
+% ----------------------------------------------------------------------------
+% lstquestion environment:
+\keys_define:nn { exsheets / listings / question }
+ {
+ pre .tl_set:N = \l__exsheets_listings_question_pre_tl ,
+ post .tl_set:N = \l__exsheets_listings_question_post_tl ,
+ options .tl_set:N = \l__exsheets_listings_question_options_tl ,
+ points .tl_set:N = \l__exsheets_listings_question_points_tl ,
+ listings .tl_set:N = \l__exsheets_listings_question_code_tl ,
+ }
+
+\keys_define:nn { exsheets / listings / solution }
+ {
+ pre .tl_set:N = \l__exsheets_listings_solution_pre_tl ,
+ post .tl_set:N = \l__exsheets_listings_solution_post_tl ,
+ options .tl_set:N = \l__exsheets_listings_solution_options_tl ,
+ listings .tl_set:N = \l__exsheets_listings_solution_code_tl ,
+ }
+
+\cs_new:Npn \exsheets_listings_new_lstenvironment:nnnnnnn #1#2#3#4#5#6#7
+ {
+ \lstnewenvironment{#2}[1][]
+ {
+ \keys_set:nn {exsheets/listings/question} {#1,#4,##1}
+ \int_gincr:N \g__exsheets_listings_question_int
+ \lst@BeginWriteFile
+ { \c_sys_jobname_str - ex \int_use:N \g__exsheets_listings_question_int . lst }
+ }
+ {
+ \lst@EndWriteFile
+ \__exsheets_question_expandopt:NnVox
+ \begin {#3}
+ \l__exsheets_listings_question_options_tl
+ { \l__exsheets_listings_question_points_tl }
+ {
+ \exp_not:V \l__exsheets_listings_question_pre_tl
+ \exp_not:N \lstinputlisting
+ [ \exp_not:V \l__exsheets_listings_question_code_tl ]
+ { \c_sys_jobname_str - ex \int_use:N \g__exsheets_listings_question_int . lst }
+ \exp_not:V \l__exsheets_listings_question_post_tl
+ }
+ \end {#3}
+ }
+ \lstnewenvironment{#5}[1][]
+ {
+ \keys_set:nn { exsheets / listings / solution } { #1,#7,##1 }
+ \int_gincr:N \g__exsheets_listings_solution_int
+ \lst@BeginWriteFile
+ { \c_sys_jobname_str - sol \int_use:N \g__exsheets_listings_solution_int . lst }
+ }
+ {
+ \lst@EndWriteFile
+ \__exsheets_question_expand_opt_and_body:NnVx
+ \begin {#6}
+ \l__exsheets_listings_solution_options_tl
+ {
+ \exp_not:V \l__exsheets_listings_solution_pre_tl
+ \exp_not:N \lstinputlisting
+ [ \exp_not:V \l__exsheets_listings_solution_code_tl ]
+ { \c_sys_jobname_str - sol \int_use:N \g__exsheets_listings_solution_int . lst }
+ \exp_not:V \l__exsheets_listings_solution_post_tl
+ }
+ \end {#6}
+ }
+ }
+
+\NewDocumentCommand \NewLstQuSolPair { O{}mmO{}mmO{} }
+ { \exsheets_listings_new_lstenvironment:nnnnnnn {#1}{#2}{#3}{#4}{#5}{#6}{#7} }
+
+\NewLstQuSolPair{lstquestion}{question}{lstsolution}{solution}
+
+\tex_endinput:D
+
+HISTORY
+2013/09/18 - first draft, see http://tex.stackexchange.com/a/133969/5049
+2013/10/11 - first official version bundled with ExSheets
+2017/02/08 - change deprecated \c_job_name_tl into the new \c_sys_jobname_str
+
diff --git a/macros/latex/contrib/exsheets/exsheets.sty b/macros/latex/contrib/exsheets/exsheets.sty
new file mode 100644
index 0000000000..73136dadac
--- /dev/null
+++ b/macros/latex/contrib/exsheets/exsheets.sty
@@ -0,0 +1,3238 @@
+% ----------------------------------------------------------------------------
+% the EXSHEETS package
+%
+% Yet another package for the creation of exercise sheets
+%
+% ----------------------------------------------------------------------------
+% Clemens Niederberger
+% Web: http://www.mychemistry.eu/forums/forum/exsheets
+% E-Mail: contact@mychemistry.eu
+% ----------------------------------------------------------------------------
+% Copyright 2011-2017 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.
+% ----------------------------------------------------------------------------
+\RequirePackage { expl3 , xparse }
+\ExplSyntaxOn
+
+\tl_const:Nn \c_exsheets_date_tl {2017/02/08}
+\tl_const:Nn \c_exsheets_version_tl {0.21i}
+\tl_const:Nn \c_exsheets_info_tl
+ {Yet~ another~ package~ for~ the~ creation~ of~ exercise~ sheets~ and~ exams.}
+
+\ProvidesExplPackage
+ {exsheets}
+ {\c_exsheets_date_tl}
+ {\c_exsheets_version_tl}
+ {\c_exsheets_info_tl}
+
+% ----------------------------------------------------------------------------
+% variants of kernel functions:
+\cs_generate_variant:Nn \prop_get:NnN { NV , Nx , cV , cx }
+\cs_generate_variant:Nn \prop_get:NnNF { NV , Nx , cV , cx }
+\cs_generate_variant:Nn \prop_get:NnNT { NV , Nx , cV , cx }
+\cs_generate_variant:Nn \prop_get:NnNTF { NV , Nx , cV , cx }
+\cs_generate_variant:Nn \prop_gput:Nnn { Nf , Nff , Nfx , Nx , Nxx , NxV , cx , cxx }
+\cs_generate_variant:Nn \prop_gput_if_new:Nnn { Nxx }
+\cs_generate_variant:Nn \tl_if_blank:nTF { x }
+\cs_generate_variant:Nn \tl_if_eq:nnF { x }
+\cs_generate_variant:Nn \int_to_arabic:n { V }
+\cs_generate_variant:Nn \seq_set_split:Nnn { NnV }
+\cs_generate_variant:Nn \quark_if_no_value:nTF { V }
+
+% ----------------------------------------------------------------------------
+% temporary variables
+\tl_new:N \l__exsheets_tmpa_tl
+\tl_new:N \l__exsheets_tmpb_tl
+\tl_new:N \l__exsheets_tmpc_tl
+\int_new:N \l__exsheets_tmpa_int
+\int_new:N \l__exsheets_tmpb_int
+\int_new:N \l__exsheets_tmpc_int
+\int_new:N \l__exsheets_tmpd_int
+\int_new:N \l__exsheets_tmpe_int
+\int_new:N \g__exsheets_tmpa_int
+\dim_new:N \l__exsheets_tmpa_dim
+\dim_new:N \l__exsheets_tmpb_dim
+\seq_new:N \l__exsheets_tmpa_seq
+\fp_new:N \l__exsheets_tmpa_fp
+\clist_new:N \l__exsheets_tmpa_clist
+\bool_new:N \l__exsheets_tmpa_bool
+
+% ----------------------------------------------------------------------------
+% messages
+\msg_new:nnn {exsheets} {file-not-found}
+ {
+ You've~ requested~ the~ file~ `\tl_to_str:n {#1}'~ but~ I~ cannot~ find~
+ it~ \msg_line_context: .
+ }
+
+\msg_new:nnn {exsheets} {totalpoints}
+ {
+ You~ need~ to~ activate~ `points/parse'~ if~ you~ want~ to~ use~
+ \token_to_str:N \totalpoints .~ I~ will~ do~ nothing~ instead.
+ }
+
+\msg_new:nnn {exsheets} {parse-points}
+ {
+ You~ need~ to~ activate~ `points/parse'~ if~ you~ want~ to~ use~
+ \token_to_str:N #1 .~ I~ will~ do~ nothing~ instead.
+ }
+
+\msg_new:nnn {exsheets} {headings}
+ {
+ You~ requested~ the~ headings~ instance~ `#1'~ \msg_line_context: \c_space_tl
+ which~ is~ not~ defined.~ Is~ this~ a~ typo?~ Anyway,~ I~ will~ use~ the~
+ instance~ `block'~ instead~ and~pretend~ nothing~ happened.
+ }
+
+\msg_new:nnn {exsheets} {random-file}
+ {
+ You~ asked~ me~ to~ select~ #1~ questions~ from~ file~ #2~ which~
+ contains~ #3~ questions.~ I'll~ select~ all~ of~ them.
+ }
+
+\msg_new:nnn {exsheets} {random-selectable}
+ {
+ You~ asked~ me~ to~ select~ #1~ questions~ from~ file~ #2~ which~
+ contains~ #3~ questions.~ #4~ of~ these~ are~ selectable,~ so~ I'll~
+ select~ all~ of~ them.
+ }
+
+\msg_new:nnn {exsheets} {only-inside-question}
+ {
+ The~ command~ `~ \token_to_str:N #1 \c_space_tl'~ can~ only~ be~ used~
+ inside~ the~ question~ environment.
+ }
+
+\msg_new:nnn {exsheets} {loading-configurations}
+ { Loading~ custom~ configurations~ file~ `exsheets_configurations.cgf'. }
+
+\msg_new:nnn {exsheets} {deprecated-command}
+ {
+ The~ command~ `#1'~ is~ deprecated.~ Use~ `#2'~ instead.
+ }
+
+\msg_new:nnn {exsheets} {dropped-option}
+ { The~ option~ `#1'~ has~ been~ dropped. }
+
+\msg_new:nnn {exsheets} {grade-missing}
+ { The~ grade~ `#1'~ has~ never~ been~ declared. }
+
+\msg_new:nnn {exsheets} {grade-parse}
+ {
+ I~ cannot~ calculate~ the~ points~ for~ grade~ `#1'~ since~ you're~ using~
+ the~ option~ `points/parse=false'.
+ }
+
+\msg_new:nnn {exsheets} {variations}
+ {
+ The~ number~ of~ variations~ must~ at~ least~ be~ `2'.~ You~ chose~ `#1'~
+ hence~ I'm~ doing~ nothing.
+ }
+
+\msg_new:nnn {exsheets} {variant}
+ {
+ You~ must~ choose~ an~ integer~ between~ `1'~ and~ `#1'.~ You~ chose~
+ `#2'~ hence~ I'm~ doing~ nothing.
+ }
+
+\cs_new_protected:Npn \exsheets_deprecate_cs:Npnn #1#2#
+ { \__exsheets_deprecate_cs:Nnnn #1 {#2} }
+\cs_new_protected:Npn \__exsheets_deprecate_cs:Nnnn #1#2#3#4
+ {
+ \cs_new_protected:Npn #1 #2
+ {
+ \tl_if_blank:nTF {#3}
+ { \msg_warning:nnnn {exsheets} { deprecated-command } {#1} {#4} }
+ { \msg_warning:nnnn {exsheets} { deprecated-command } {#1} {#3} }
+ #4
+ }
+ }
+
+\cs_new_protected:Npn \exsheets_option_dropped:n #1
+ { \msg_warning:nnn {exsheets} {dropped-option} {#1} }
+
+% ----------------------------------------------------------------------------
+\RequirePackage
+ { xtemplate , l3keys2e , etoolbox , environ , pgfcore }
+
+% ----------------------------------------------------------------------------
+% write to aux file:
+\cs_new_protected:Npn \exsheets_write_to_aux_x:n #1
+ { \if@filesw \iow_now:Nx \@auxout {#1} \fi }
+
+% prevent compilatin errors when exsheets is removed from a document:
+\AtBeginDocument{
+ \exsheets_write_to_aux_x:n
+ {
+ \exp_not:N \providecommand \exp_not:N \exsheets@question@property[3]{} ^^J
+ \exp_not:N \providecommand \exp_not:N \exsheets@save@number[2]{} ^^J
+ \exp_not:N \providecommand \exp_not:N \exsheets@sum@of@points[1]{} ^^J
+ \exp_not:N \providecommand \exp_not:N \exsheets@sum@of@bonus[1]{} ^^J
+ \exp_not:N \providecommand \exp_not:N \exsheets@used@id[2]{} ^^J
+ }
+}
+
+% ----------------------------------------------------------------------------
+% variables:
+\bool_new:N \l__exsheets_print_number_bool
+\bool_set_true:N \l__exsheets_print_number_bool
+\bool_new:N \l__exsheets_solutions_by_ref_bool
+\bool_new:N \l__exsheets_questions_totoc_bool
+\bool_new:N \l__exsheets_solutions_totoc_bool
+\bool_new:N \l__exsheets_auto_label_bool
+\bool_new:N \l__exsheets_no_skip_after_bool
+\bool_new:N \l__exsheets_points_questions_default_bool
+\bool_set_false:N \l__exsheets_points_questions_default_bool
+\bool_new:N \l__exsheets_parse_points_bool
+\bool_set_true:N \l__exsheets_parse_points_bool
+\bool_new:N \l__exsheets_points_name_bool
+\bool_set_true:N \l__exsheets_points_name_bool
+\bool_new:N \l__exsheets_points_separate_bonus_bool
+\bool_new:N \l__exsheets_grades_half_bool
+\bool_new:N \g__exsheets_questions_use_bool
+\bool_gset_true:N \g__exsheets_questions_use_bool
+\bool_new:N \l__exsheets_questions_use_bool
+\bool_set_true:N \l__exsheets_questions_use_bool
+\bool_new:N \l__exsheets_questions_deactivate_bool
+\bool_new:N \l__exsheets_save_question_body_to_aux_bool
+\bool_set_false:N \l__exsheets_save_question_body_to_aux_bool
+\bool_new:N \l__exsheets_solutions_use_bool
+\bool_set_true:N \l__exsheets_solutions_use_bool
+\bool_new:N \l__exsheets_use_this_question_bool
+\bool_new:N \l__exsheets_questions_print_bool
+\bool_set_true:N \l__exsheets_questions_print_bool
+\bool_new:N \l__exsheets_inside_question_bool
+\bool_new:N \l__exsheets_only_print_points_bool
+\bool_new:N \l__exsheets_exam_bool
+\bool_set_false:N \l__exsheets_exam_bool
+\bool_new:N \l__exsheets_questions_runin_bool
+\bool_set_false:N \l__exsheets_questions_runin_bool
+\bool_new:N \l__exsheets_questions_debug_bool
+\bool_set_false:N \l__exsheets_questions_debug_bool
+\bool_new:N \l__exsheets_select_questions_bool
+\bool_new:N \l__exsheets_include_all_bool
+\bool_new:N \l__exsheets_include_random_bool
+\bool_new:N \l__exsheets_include_by_id_bool
+\bool_set_true:N \l__exsheets_include_all_bool
+\bool_new:N \l__exsheets_include_questions_no_duplicates_bool
+\bool_new:N \l__exsheets_use_selection_bool
+\bool_new:N \l__exsheets_solutions_print_bool
+\bool_set_false:N \l__exsheets_solutions_print_bool
+\bool_new:N \l__exsheets_solutions_print_section_bool
+\bool_set_false:N \l__exsheets_solutions_print_section_bool
+\bool_new:N \l__exsheets_solutions_print_chapter_bool
+\bool_set_false:N \l__exsheets_solutions_print_chapter_bool
+\bool_new:N \l__exsheets_solutions_print_all_bool
+\bool_set_false:N \l__exsheets_solutions_print_all_bool
+\bool_new:N \l__exsheets_inside_solution_bool
+\bool_set_false:N \l__exsheets_inside_solution_bool
+\bool_new:N \l__exsheets_solutions_runin_bool
+\bool_set_false:N \l__exsheets_solutions_runin_bool
+\bool_new:N \l__exsheets_print_byID_sorted_bool
+\bool_set_true:N \l__exsheets_print_byID_sorted_bool
+\bool_new:N \l__exsheets_blank_width_bool
+\bool_new:N \l__exsheets_blank_linespread_bool
+
+\tl_new:N \l__exsheets_points_name_tl
+\tl_set:Nn \l__exsheets_points_name_tl {P.}
+\tl_new:N \l__exsheets_points_name_plural_tl
+\tl_set:Nn \l__exsheets_points_name_plural_tl {P.}
+\tl_new:N \l__exsheets_bonus_name_tl
+\tl_set:Nn \l__exsheets_bonus_name_tl {P.}
+\tl_new:N \l__exsheets_bonus_name_plural_tl
+\tl_set:Nn \l__exsheets_bonus_name_plural_tl {P.}
+\tl_new:N \l__exsheets_points_number_format_tl
+\tl_new:N \l__exsheets_bonus_number_format_tl
+\tl_new:N \l__exsheets_points_pre_bonus_marker_tl
+\tl_set:Nn \l__exsheets_points_pre_bonus_marker_tl { \space(+ }
+\tl_new:N \l__exsheets_points_post_bonus_marker_tl
+\tl_set:Nn \l__exsheets_points_post_bonus_marker_tl { ) }
+\tl_new:N \l__exsheets_points_format_tl
+\tl_set:Nn \l__exsheets_points_format_tl { \use:n }
+\tl_new:N \l__exsheets_qu_counter_pattern_tl
+\tl_set:Nn \l__exsheets_qu_counter_pattern_tl { qu. }
+\tl_new:N \l__exsheets_qu_counter_interpretation_tl
+\tl_new:N \l__exsheets_counter_patterns_tl
+\tl_new:N \l__exsheets_heading_instance_tl
+\tl_set:Nn \l__exsheets_heading_instance_tl {block}
+\tl_new:N \l__exsheets_question_heading_instance_tl
+\tl_new:N \l__exsheets_solution_heading_instance_tl
+\tl_new:N \l_exsheets_heading_title_question_format_tl
+\tl_new:N \l_exsheets_heading_title_solution_format_tl
+\tl_new:N \l_exsheets_heading_subtitle_question_format_tl
+\tl_new:N \l_exsheets_heading_subtitle_solution_format_tl
+\tl_new:N \l__exsheets_questions_toclevel_tl
+\tl_set:Nn \l__exsheets_questions_toclevel_tl {subsection}
+\tl_new:N \l__exsheets_solutions_toclevel_tl
+\tl_set:Nn \l__exsheets_solutions_toclevel_tl {subsection}
+\tl_new:N \l__exsheets_new_chapter_hook_tl
+\tl_new:N \l__exsheets_new_section_hook_tl
+\tl_new:N \g__exsheets_use_current_question_tl
+\tl_new:N \l__exsheets_questions_name_tl
+\tl_set:Nn \l__exsheets_questions_name_tl {Question}
+\tl_new:N \l__exsheets_exercise_name_tl
+\tl_set:Nn \l__exsheets_exercise_name_tl {Exercise}
+\tl_new:N \l__exsheets_questions_pre_hook_tl
+\tl_new:N \l__exsheets_questions_post_hook_tl
+\tl_new:N \l__exsheets_questions_pre_body_hook_tl
+\tl_new:N \l__exsheets_questions_post_body_hook_tl
+\tl_new:N \l__exsheets_after_begin_question_tl
+\tl_new:N \CurrentQuestionID
+\tl_new:N \l__exsheets_questions_id_tl
+\tl_new:N \l__exsheets_questions_subtitle_tl
+\tl_new:N \g__exsheets_questions_current_id_tl
+\tl_new:N \l__exsheets_questions_title_tl
+\tl_new:N \l__exsheets_questions_label_tl
+\tl_new:N \l__exsheets_questions_points_tl
+\tl_new:N \l__exsheets_include_id_tl
+\tl_new:N \l__exsheets_solutions_name_tl
+\tl_set:Nn \l__exsheets_solutions_name_tl {Solution}
+\tl_new:N \l__exsheets_solutions_pre_body_hook_tl
+\tl_new:N \l__exsheets_solutions_post_body_hook_tl
+\tl_new:N \l__exsheets_solutions_pre_hook_tl
+\tl_new:N \l__exsheets_solutions_post_hook_tl
+\tl_new:N \l__exsheets_blank_linespread_tl
+\tl_set:Nn \l__exsheets_blank_linespread_tl { 1 }
+\tl_new:N \l__exsheets_blank_scale_tl
+\tl_set:Nn \l__exsheets_blank_scale_tl { 1 }
+\tl_new:N \l__exsheets_use_solution_tl
+\tl_new:N \l_exsheets_solutions_name_style_tl
+\tl_set:Nn \l_exsheets_solutions_name_style_tl { \normalsize \bfseries }
+
+\int_zero_new:N \l__exsheets_variations_int
+\int_new:N \g__exsheets_questions_id_int
+\int_gzero:N \g__exsheets_questions_id_int
+\int_new:N \g__exsheets_questions_used_int
+\int_zero_new:N \l__exsheets_include_random_int
+\int_new:N \l__exsheets_questions_set_int
+\int_new:N \g__exsheets_select_random_int
+\int_new:N \g__exsheets_selection_number_int
+\int_new:N \l__exsheets_counter_ch_int
+\int_new:N \l__exsheets_current_ch_int
+\int_new:N \l__exsheets_counter_sec_int
+\int_new:N \l__exsheets_current_sec_int
+\int_new:N \l_exsheets_counter_qu_int
+
+\fp_new:N \g__exsheets_points_sum_fp
+\fp_new:N \l__exsheets_points_default_fp
+\fp_set:Nn \l__exsheets_points_default_fp {1}
+\fp_new:N \l__exsheets_question_points_fp
+\fp_new:N \g_exsheets_total_points_fp
+\fp_new:N \g__exsheets_bonus_sum_fp
+\fp_new:N \l__exsheets_question_bonus_fp
+\fp_new:N \g_exsheets_total_bonus_fp
+\fp_new:N \l__exsheets_grade_round_fp
+\fp_zero:N \l__exsheets_grade_round_fp
+\fp_new:N \g__exsheets_this_question_points_fp
+\fp_new:N \g__exsheets_this_question_bonus_fp
+
+\dim_new:N \l__exsheets_questions_skip_below_dim
+\dim_set:Nn \l__exsheets_questions_skip_below_dim { .5\baselineskip }
+\dim_new:N \l__exsheets_solutions_skip_below_dim
+\dim_set:Nn \l__exsheets_solutions_skip_below_dim { .5\baselineskip }
+\dim_new:N \l__exsheets_blank_dim
+\dim_new:N \l__exsheets_blank_line_increment_dim
+\dim_new:N \l__exsheets_blank_line_minimum_length_dim
+
+\seq_new:N \l__exsheets_use_tags_seq
+\seq_new:N \g_exsheets_included_questions_seq
+
+\prop_new:N \l__exsheets_relgrades_prop
+\prop_new:N \l__exsheets_class_prop
+\prop_new:N \g__exsheets_tags_prop
+\prop_new:N \g__exsheets_questions_id_prop
+\prop_new:N \g__exsheets_questions_subtitle_prop
+\prop_new:N \g__exsheets_questions_used_prop
+\prop_new:N \g_exsheets_question_identification_prop
+\prop_new:N \g__exsheets_included_questions_prop
+\prop_new:N \g__exsheets_solutions_content_prop
+\prop_new:N \g__exsheets_solutions_questions_id_prop
+\prop_new:N \g__exsheets_solutions_names_prop
+\prop_new:N \g__exsheets_solutions_counter_prop
+
+\clist_new:N \l__exsheets_include_id_clist
+\clist_new:N \l__exsheets_exclude_id_clist
+\clist_new:N \questionsincludedlast
+
+\box_new:N \l__exsheets_blank_box
+
+% ----------------------------------------------------------------------------
+% how are questions/solutions/... counted?
+\RequirePackage {cntformats}
+
+\cs_if_exist:NT \thechapter
+ {
+ \AddCounterPattern* [exsheets] {chapter} {ch}
+ \ReadCounterFrom [exsheets] {chapter} \l__exsheets_counter_ch_int
+ }
+
+\AddCounterPattern* [exsheets] {section} {se}
+\ReadCounterFrom [exsheets] {section} \l__exsheets_counter_sec_int
+
+\NewCounterPattern* [exsheets] {question} {qu}
+\ReadCounterFrom [exsheets] {question} \l_exsheets_counter_qu_int
+
+% ----------------------------------------------------------------------------
+% (also) package options:
+\keys_define:nn {exsheets}
+ {
+ counter-format .code:n =
+ \SaveCounterPattern [exsheets]
+ \l__exsheets_qu_counter_pattern_tl
+ \l__exsheets_qu_counter_interpretation_tl
+ {#1} ,
+ counter-format .initial:n = qu. ,
+ counter-within .code:n = \@addtoreset {question} {#1} ,
+ headings .tl_set:N = \l__exsheets_heading_instance_tl ,
+ load-headings .code:n =
+ \exsheets_option_dropped:n {load-headings} ,
+ question/headings-format .tl_set:N =
+ \l_exsheets_heading_title_question_format_tl ,
+ solution/headings-format .tl_set:N =
+ \l_exsheets_heading_title_solution_format_tl ,
+ headings-format .meta:n =
+ {
+ question/headings-format = {#1} ,
+ solution/headings-format = {#1}
+ } ,
+ headings-format .initial:n = \normalsize\bfseries ,
+ question/subtitle-format .tl_set:N =
+ \l_exsheets_heading_subtitle_question_format_tl ,
+ solution/subtitle-format .tl_set:N =
+ \l_exsheets_heading_subtitle_solution_format_tl ,
+ subtitle-format .meta:n =
+ {
+ question/subtitle-format = {#1} ,
+ solution/subtitle-format = {#1}
+ } ,
+ subtitle-format .initial:n = \normalsize\itshape ,
+ load-tasks .code:n =
+ \exsheets_option_dropped:n {load-tasks} ,
+ use-ref .bool_set:N = \l__exsheets_solutions_by_ref_bool ,
+ totoc .choice: ,
+ totoc / true .code:n =
+ \bool_set_true:N \l__exsheets_questions_totoc_bool
+ \bool_set_true:N \l__exsheets_solutions_totoc_bool ,
+ totoc / false .code:n =
+ \bool_set_false:N \l__exsheets_questions_totoc_bool
+ \bool_set_false:N \l__exsheets_solutions_totoc_bool ,
+ totoc .default:n = true ,
+ questions-totoc .bool_set:N = \l__exsheets_questions_totoc_bool ,
+ solutions-totoc .bool_set:N = \l__exsheets_solutions_totoc_bool ,
+ toc-level .code:n =
+ \tl_set:Nn \l__exsheets_questions_toclevel_tl {#1}
+ \tl_set:Nn \l__exsheets_solutions_toclevel_tl {#1} ,
+ questions-toc-level .tl_set:N = \l__exsheets_questions_toclevel_tl ,
+ solutions-toc-level .tl_set:N = \l__exsheets_solutions_toclevel_tl ,
+ skip-below .code:n =
+ \dim_set:Nn \l__exsheets_questions_skip_below_dim {#1}
+ \dim_set:Nn \l__exsheets_solutions_skip_below_dim {#1} ,
+ no-skip-below .bool_set:N = \l__exsheets_no_skip_after_bool ,
+ auto-label .bool_set:N = \l__exsheets_auto_label_bool ,
+ label-format .code:n =
+ \cs_set:Npn \exsheets_label_format:n ##1 {#1}
+ \exsheets_update_referencing_commands: ,
+ label-cmd .code:n =
+ \cs_set:Npn \__exsheets_label:n {#1}
+ \exsheets_update_referencing_commands: ,
+ ref-cmd .code:n =
+ \cs_set:Npn \__exsheets_ref:n {#1}
+ \exsheets_update_referencing_commands: ,
+ page-ref-cmd .code:n =
+ \cs_set:Npn \__exsheets_pageref:n {#1}
+ \exsheets_update_referencing_commands: ,
+ chapter-hook .tl_set:N = \l__exsheets_new_chapter_hook_tl ,
+ section-hook .tl_set:N = \l__exsheets_new_section_hook_tl %,
+% use-saved-counter-format .bool_set:N = \l__exsheets_use_saved_pattern_bool
+ }
+
+% TODO: remove this in a v1.0:
+% process package options:
+\ProcessKeysOptions {exsheets}
+
+% ----------------------------------------------------------------------------
+% points for exercises
+\cs_new_protected:Npn \__exsheets_set_points_name:nNN #1#2#3
+ {
+ \tl_if_in:nnTF {#1} { / }
+ { \__exsheets_set_points_name_aux:wNN #1 \q_mark #2#3 }
+ { \__exsheets_set_points_name_aux:wNN #1 / \q_mark #2#3 }
+ }
+
+\cs_new_protected:Npn \__exsheets_set_points_name_aux:wNN #1/#2 \q_mark #3#4
+ {
+ \tl_set:Nn #3 {#1}
+ \tl_set:Nn #4 { #1#2 }
+ }
+
+\cs_new_protected:Npn \exsheets_set_points_name:n #1
+ {
+ \__exsheets_set_points_name:nNN {#1}
+ \l__exsheets_points_name_tl
+ \l__exsheets_points_name_plural_tl
+ }
+
+\cs_new_protected:Npn \exsheets_set_bonus_name:n #1
+ {
+ \__exsheets_set_points_name:nNN {#1}
+ \l__exsheets_bonus_name_tl
+ \l__exsheets_bonus_name_plural_tl
+ }
+
+% FIXME: \fp_add will deprecate!
+\cs_new_protected:Npn \exsheets_add_points:n #1
+ {
+ \fp_gadd:Nn \g__exsheets_points_sum_fp {#1}
+ \fp_gadd:Nn \g__exsheets_this_question_points_fp {#1}
+ }
+\cs_generate_variant:Nn \exsheets_add_points:n { V }
+
+\cs_new_protected:Npn \exsheets_add_bonus:n #1
+ {
+ \fp_gadd:Nn \g__exsheets_bonus_sum_fp {#1}
+ \fp_gadd:Nn \g__exsheets_this_question_bonus_fp {#1}
+ }
+\cs_generate_variant:Nn \exsheets_add_bonus:n { V }
+
+\cs_new_protected:Npn \exsheets@sum@of@points #1
+ { \fp_gset:Nn \g_exsheets_total_points_fp {#1} }
+
+\cs_new_protected:Npn \exsheets@sum@of@bonus #1
+ { \fp_gset:Nn \g_exsheets_total_bonus_fp {#1} }
+
+\cs_new:Npn \__exsheets_parse_points:nN #1#2
+ {
+ \group_begin:
+ \tl_use:N #2
+ {
+ \bool_if:NTF \l__exsheets_parse_points_bool
+ { \exsheets_num:n {#1} }
+ { \use:n {#1} }
+ }
+ \group_end:
+ }
+\cs_new:Npn \exsheets_parse_points:n #1
+ {
+ \__exsheets_parse_points:nN {#1}
+ \l__exsheets_points_number_format_tl
+ }
+\cs_generate_variant:Nn \exsheets_parse_points:n { V }
+
+\cs_new:Npn \exsheets_parse_bonus:n #1
+ {
+ \__exsheets_parse_points:nN {#1}
+ \l__exsheets_bonus_number_format_tl
+ }
+\cs_generate_variant:Nn \exsheets_parse_bonus:n { V }
+
+\cs_new:Npn \exsheets_num:n #1
+ { \fp_to_decimal:n {#1} }
+\cs_generate_variant:Nn \exsheets_num:n { V,x }
+
+\cs_new:Npn \__exsheets_print_points_name:nNN #1#2#3
+ {
+ \bool_if:NT \l__exsheets_points_name_bool
+ {
+ \,
+ \hbox:n
+ {
+ \bool_if:NTF \l__exsheets_parse_points_bool
+ {
+ \tl_if_eq:nnTF {#1} { ?? }
+ { \tl_use:N #3 }
+ {
+ \fp_compare:nTF { #1 = 1 }
+ { \tl_use:N #2 }
+ { \tl_use:N #3 }
+ }
+ }
+ { \tl_use:N #3 }
+ }
+ }
+ }
+
+\cs_new:Npn \exsheets_points_name:n #1
+ {
+ \__exsheets_print_points_name:nNN {#1}
+ \l__exsheets_points_name_tl
+ \l__exsheets_points_name_plural_tl
+ }
+\cs_generate_variant:Nn \exsheets_points_name:n { V }
+
+\cs_new:Npn \exsheets_bonus_name:n #1
+ {
+ \__exsheets_print_points_name:nNN {#1}
+ \l__exsheets_bonus_name_tl
+ \l__exsheets_bonus_name_plural_tl
+ }
+\cs_generate_variant:Nn \exsheets_bonus_name:n { V }
+
+\NewDocumentCommand \addpoints { sm }
+ {
+ \bool_if:NTF \l__exsheets_inside_question_bool
+ {
+ \exsheets_add_points:n {#2}
+ \IfBooleanF {#1} { \exsheets_print_points:n {#2} }
+ }
+ { \msg_error:nnn {exsheets} {only-inside-question} {\addpoints} }
+ }
+
+\NewDocumentCommand \addbonus { sm }
+ {
+ \bool_if:NTF \l__exsheets_inside_question_bool
+ {
+ \exsheets_add_bonus:n {#2}
+ \IfBooleanF {#1} { \exsheets_print_bonus:n {#2} }
+ }
+ { \msg_error:nnn {exsheets} {only-inside-question} {\addbonus} }
+ }
+
+\NewDocumentCommand \points { sm }
+ {
+ \IfBooleanTF {#1}
+ { \exsheets_parse_points:n {#2} }
+ { \exsheets_print_points:n {#2} }
+ }
+
+\NewDocumentCommand \bonus { sm }
+ {
+ \IfBooleanTF {#1}
+ { \exsheets_parse_bonus:n {#2} }
+ { \exsheets_print_bonus:n {#2} }
+ }
+
+\cs_new_protected:Npn \exsheets_print_points:n #1
+ {
+ \group_begin:
+ \tl_use:N \l__exsheets_points_format_tl
+ {
+ \exsheets_parse_points:n {#1}
+ \exsheets_points_name:n {#1}
+ }
+ \group_end:
+ }
+\cs_generate_variant:Nn \exsheets_print_points:n { V }
+
+\cs_new_protected:Npn \exsheets_print_bonus:n #1
+ {
+ \exsheets_parse_bonus:n {#1}
+ \exsheets_bonus_name:n {#1}
+ }
+\cs_generate_variant:Nn \exsheets_print_bonus:n { V }
+
+\NewDocumentCommand \pointssum { s }
+ {
+ \bool_if:NTF \l__exsheets_parse_points_bool
+ {
+ \IfBooleanTF {#1}
+ { \exsheets_parse_points:n { \g_exsheets_total_points_fp } }
+ { \exsheets_print_points:n { \g_exsheets_total_points_fp } }
+ }
+ { \msg_warning:nnn {exsheets} {parse-points} {\pointssum} }
+ }
+
+\NewDocumentCommand \bonussum { s }
+ {
+ \bool_if:NTF \l__exsheets_parse_points_bool
+ {
+ \IfBooleanTF {#1}
+ { \exsheets_parse_bonus:n { \g_exsheets_total_bonus_fp } }
+ { \exsheets_print_bonus:n { \g_exsheets_total_bonus_fp } }
+ }
+ { \msg_warning:nnn {exsheets} {parse-points} {\bonussum} }
+ }
+
+\NewDocumentCommand \currentpointssum { s }
+ {
+ \bool_if:NTF \l__exsheets_parse_points_bool
+ {
+ \IfBooleanTF {#1}
+ { \exsheets_parse_points:n { \g__exsheets_points_sum_fp } }
+ { \exsheets_print_points:n { \g__exsheets_points_sum_fp } }
+ }
+ { \msg_warning:nnn {exsheets} {parse-points} {\currentpointssum} }
+ }
+
+\NewDocumentCommand \currentbonussum { s }
+ {
+ \bool_if:NTF \l__exsheets_parse_points_bool
+ {
+ \IfBooleanTF {#1}
+ { \exsheets_parse_bonus:n { \g__exsheets_bonus_sum_fp } }
+ { \exsheets_print_bonus:n { \g__exsheets_bonus_sum_fp } }
+ }
+ { \msg_warning:nnn {exsheets} {parse-points} {\currentbonussum} }
+ }
+
+\NewDocumentCommand \totalpoints { s }
+ {
+ \group_begin:
+ \tl_use:N \l__exsheets_points_format_tl
+ {
+ \exsheets_totalpoints:
+ \IfBooleanF {#1}
+ {
+ \bool_if:nT
+ {
+ \l__exsheets_points_separate_bonus_bool ||
+ \fp_compare_p:n { \g_exsheets_total_bonus_fp = 0 }
+ }
+ { \exsheets_points_name:n { \g_exsheets_total_points_fp } }
+ }
+ \exsheets_totalbonus:
+ \IfBooleanF {#1}
+ {
+ \fp_compare:nF { \g_exsheets_total_bonus_fp = 0 }
+ {
+ \bool_if:NTF \l__exsheets_points_separate_bonus_bool
+ { \exsheets_bonus_name:n { \g_exsheets_total_bonus_fp } }
+ {
+ \exsheets_points_name:n
+ { \g_exsheets_total_points_fp + \g_exsheets_total_bonus_fp }
+ }
+ }
+ }
+ }
+ \group_end:
+ }
+
+\exsheets_deprecate_cs:Npnn \sumpoints {} { \totalpoints* }
+
+\cs_new_protected:Npn \exsheets_totalpoints:
+ {
+ \bool_if:NTF \l__exsheets_parse_points_bool
+ {
+ \fp_compare:nTF { \g_exsheets_total_points_fp = 0 }
+ { ?? \, \exsheets_points_name:n { ?? } }
+ {
+ \exsheets_parse_points:n
+ { \g_exsheets_total_points_fp }
+ }
+ }
+ { \msg_warning:nn {exsheets} {totalpoints} }
+ }
+
+\cs_new:Npn \exsheets_totalbonus:
+ {
+ \bool_if:NT \l__exsheets_parse_points_bool
+ {
+ \fp_compare:nF { \g_exsheets_total_bonus_fp = 0 }
+ {
+ \tl_use:N \l__exsheets_points_pre_bonus_marker_tl
+ \exsheets_parse_bonus:n
+ { \g_exsheets_total_bonus_fp }
+ \tl_use:N \l__exsheets_points_post_bonus_marker_tl
+ }
+ }
+ }
+
+\keys_define:nn { exsheets / points }
+ {
+ name .code:n =
+ \exsheets_set_points_name:n {#1}
+ \exsheets_set_bonus_name:n {#1} ,
+ name-plural .code:n =
+ \tl_set:Nn \l__exsheets_points_name_plural_tl {#1}
+ \tl_set:Nn \l__exsheets_bonus_name_plural_tl {#1} ,
+ bonus-name .code:n = \exsheets_set_bonus_name:n {#1} ,
+ bonus-plural .tl_set:N = \l__exsheets_bonus_name_plural_tl ,
+ pre-bonus .tl_set:N = \l__exsheets_points_pre_bonus_marker_tl ,
+ post-bonus .tl_set:N = \l__exsheets_points_post_bonus_marker_tl ,
+ use-name .bool_set:N = \l__exsheets_points_name_bool ,
+ format .tl_set:N = \l__exsheets_points_format_tl ,
+ number-format .tl_set:N = \l__exsheets_points_number_format_tl ,
+ bonus-format .tl_set:N = \l__exsheets_bonus_number_format_tl ,
+ parse .bool_set:N = \l__exsheets_parse_points_bool ,
+ separate-bonus .bool_set:N = \l__exsheets_points_separate_bonus_bool
+ }
+
+% ----------------------------------------------------------------------------
+% variations of an exam, see http://tex.stackexchange.com/q/57012/5049 for
+% inspiration of the following features
+\cs_new_protected:Npn \exsheets_set_variations:n #1
+ {
+ \int_compare:nNnTF {#1} < { 2 }
+ { \msg_warning:nnn {exsheets} {variations} {#1} }
+ {
+ \int_set:Nn \l__exsheets_variations_int {#1}
+ \int_zero:N \l__exsheets_tmpa_int
+ \int_do_while:nNnn
+ { \l__exsheets_tmpa_int } < { \l__exsheets_variations_int }
+ {
+ \int_incr:N \l__exsheets_tmpa_int
+ \__exsheets_generate_variation_auxiliary:n
+ { \l__exsheets_tmpa_int }
+ \__exsheets_reset_variation_auxiliary:x
+ { \int_use:N \l__exsheets_tmpa_int }
+ }
+ \__exsheets_generate_variation_auxiliary:n
+ { \l__exsheets_variations_int + 1 }
+ \exsheets_variant:n { 1 }
+ }
+ }
+
+\cs_new_protected:Npn \exsheets_variant:n #1
+ {
+ \bool_if:nTF
+ {
+ \int_compare_p:nNn {#1} > { 0 } &&
+ \int_compare_p:nNn {#1} < { \l__exsheets_variations_int + 1 }
+ }
+ {
+ \int_zero:N \l__exsheets_tmpa_int
+ \int_do_while:nNnn
+ { \l__exsheets_tmpa_int } < { \l__exsheets_variations_int }
+ {
+ \int_incr:N \l__exsheets_tmpa_int
+ \__exsheets_reset_variation_auxiliary:x
+ { \int_use:N \l__exsheets_tmpa_int }
+ }
+ \cs_set:cpn { __exsheets_variation_ \int_to_roman:n {#1} :n } ##1
+ {
+ ##1
+ \cs_set:Npn \exsheets_last_variant: {##1}
+ \use:c { __exsheets_variation_ \int_to_roman:n { #1 + 1 } :n }
+ }
+ }
+ {
+ \msg_warning:nnxx {exsheets} {variant}
+ { \int_use:N \l__exsheets_variations_int } {#1}
+ }
+ }
+
+\cs_new_protected:Npn \exsheets_vary:w
+ { \__exsheets_variation_i:n }
+
+\cs_new:Npn \exsheets_last_variant: { }
+
+\cs_new_protected:Npn \__exsheets_generate_variation_auxiliary:n #1
+ {
+ \cs_if_exist:cTF { __exsheets_variation_ \int_to_roman:n {#1} :n }
+ { \cs_set:cpn { __exsheets_variation_ \int_to_roman:n {#1} :n } { } }
+ { \cs_new:cpn { __exsheets_variation_ \int_to_roman:n {#1} :n } { } }
+ }
+
+\cs_new_protected:Npn \__exsheets_reset_variation_auxiliary:n #1
+ {
+ \cs_set:cpn { __exsheets_variation_ \int_to_roman:n {#1} :n } ##1
+ { \use:c { __exsheets_variation_ \int_to_roman:n { #1 + 1 } :n } }
+ }
+\cs_generate_variant:Nn \__exsheets_reset_variation_auxiliary:n { x }
+
+\NewDocumentCommand \SetVariations { m }
+ { \exsheets_set_variations:n {#1} }
+
+\NewDocumentCommand \variant { m }
+ { \exsheets_variant:n {#1} }
+
+\NewDocumentCommand \vary { }
+ { \exsheets_vary:w }
+
+\NewDocumentCommand \lastvariant { }
+ { \exsheets_last_variant: }
+
+% initiate: two variations, first is default
+\SetVariations { 2 }
+\variant { 1 }
+
+% ----------------------------------------------------------------------------
+% grades distribution
+\cs_new:Npn \__exsheets_fp_round_to_half:n #1
+ { round( 2*(#1),0)/2 }
+
+\cs_new:Npn \__exsheets_grades_round:n #1
+ { round ( #1 , \l__exsheets_grade_round_fp ) }
+
+\cs_new:Npn \__exsheets_grade_rounded:
+ {
+ \bool_if:NTF { \l__exsheets_grades_half_bool }
+ { \__exsheets_fp_round_to_half:n }
+ { \__exsheets_grades_round:n }
+ { \g_exsheets_total_points_fp * \l__exsheets_tmpa_fp }
+ }
+
+\cs_new:Npn \exsheets_strip_braces:N #1
+ { \exp_after:wN \__exsheets_strip_braces:w \exp_after:wN #1#1 \q_stop }
+\cs_new_protected:Npn \__exsheets_strip_braces:w #1#2 \q_stop
+ { \tl_set:Nn #1 {#2} }
+
+\cs_new_protected:Npn \__exsheets_declare_relgrades:n #1
+ {
+ \clist_set:Nn \l__exsheets_tmpa_clist {#1}
+ \clist_map_inline:Nn \l__exsheets_tmpa_clist
+ { \__exsheets_declare_relgrade:w ##1 \q_stop }
+ }
+
+\cs_new_protected:Npn \__exsheets_declare_relgrade:w #1 = #2 \q_stop
+ {
+ \tl_set:Nn \l__exsheets_tmpa_tl {#1}
+ \tl_set:Nn \l__exsheets_tmpb_tl {#2}
+ \tl_trim_spaces:N \l__exsheets_tmpa_tl
+ \exsheets_strip_braces:N \l__exsheets_tmpa_tl
+ \tl_trim_spaces:N \l__exsheets_tmpb_tl
+ \exsheets_strip_braces:N \l__exsheets_tmpb_tl
+ \prop_put:NVV \l__exsheets_relgrades_prop
+ \l__exsheets_tmpa_tl
+ \l__exsheets_tmpb_tl
+ }
+
+\NewDocumentCommand \DeclareRelGrades { m }
+ { \__exsheets_declare_relgrades:n {#1} }
+\@onlypreamble \DeclareRelGrades
+
+\cs_new_protected:Npn \__exsheets_grade:nn #1#2
+ {
+ \prop_get:NnNTF \l__exsheets_relgrades_prop {#2} \l__exsheets_tmpa_fp
+ {
+ \bool_if:NTF \l__exsheets_parse_points_bool
+ {
+ \exsheets_parse_points:n
+ { min( \__exsheets_grade_rounded: , \g_exsheets_total_points_fp ) }
+ \int_compare:nT { #1 = 1 }
+ {
+ \exsheets_points_name:n
+ { min( \__exsheets_grade_rounded: , \g_exsheets_total_points_fp ) }
+ }
+ }
+ { \msg_warning:nnn {exsheets} {grade-parse} {#1} \textbf{??} }
+ }
+ { \msg_warning:nnn {exsheets} {grade-missing} {#1} \textbf{??} }
+ }
+
+\NewDocumentCommand \grade { sm }
+ {
+ \IfBooleanTF {#1}
+ { \__exsheets_grade:nn { 0 } {#2} }
+ { \__exsheets_grade:nn { 1 } {#2} }
+ }
+
+\keys_define:nn { exsheets / grades }
+ {
+ round .fp_set:N = \l__exsheets_grade_round_fp ,
+ half .bool_set:N = \l__exsheets_grades_half_bool
+ }
+
+% ----------------------------------------------------------------------------
+% Aufgaben und Lösungen
+\cs_new:Npn \exsheets_glue:N #1
+ { \cleaders \vbox:n {} \skip_vertical:N #1 }
+
+% classes, topics and other group concepts:
+\cs_new_protected:Npn \exsheets_new_question_class:nn #1#2
+ {
+ \prop_put:Nnn \l__exsheets_class_prop {#2} {#1}
+ \prop_new:c { g__exsheets_questions_#1_prop }
+ \prop_new:c { g__exsheets_#2_prop }
+ \prop_new:c { g__exsheets_#2_active_prop }
+ \bool_new:c { l__exsheets_questions_#1_bool }
+ \bool_new:c { g__exsheets_use_#2_bool }
+ \bool_new:c { l__exsheets_#1_active_bool }
+ \tl_new:c { l__exsheets_questions_#1_tl }
+ \keys_define:nn {exsheets}
+ {
+ use-#2 .code:n =
+ {
+ \bool_gset_true:c { g__exsheets_use_#2_bool }
+ \use:c { __exsheets_activate_#2:n } {##1}
+ } ,
+ question / #1 .code:n =
+ \bool_set_true:c { l__exsheets_questions_#1_bool }
+ \tl_set:cn { l__exsheets_questions_#1_tl } {##1}
+ }
+ \cs_new_protected:cpn { __exsheets_activate_#2:n } ##1
+ {
+ \prop_gclear:c { g__exsheets_#2_active_prop }
+ \seq_set_split:Nnn \l__exsheets_tmpa_seq { , } {##1}
+ \seq_map_inline:Nn \l__exsheets_tmpa_seq
+ {
+ \prop_gput:cnn { g__exsheets_#2_active_prop }
+ {####1} { \__exsheets_dummy: }
+ }
+ }
+ \cs_new_protected:cpn { __exsheets_questions_use_#2: }
+ {
+ % is there a #1 provided?
+ \bool_if:cT { l__exsheets_questions_#1_bool }
+ {
+ % add #1 to questions property
+ \prop_gput:cxx { g__exsheets_questions_#1_prop }
+ { \int_to_arabic:n { \g__exsheets_questions_id_int } }
+ { \exp_not:v { l__exsheets_questions_#1_tl } }
+ % add to #2 list, if it's a new one
+ \prop_get:cxNF { g__exsheets_#2_prop }
+ { \exp_not:v { l__exsheets_questions_#1_tl } }
+ \l__exsheets_tmpa_tl
+ {
+ \prop_gput:cxn { g__exsheets_#2_prop }
+ { \exp_not:v { l__exsheets_questions_#1_tl } }
+ { \__exsheets_dummy: }
+ }
+ }
+ % are we using #2?
+ \bool_if:cT { g__exsheets_use_#2_bool }
+ {
+ % is this question an active one?
+ \prop_get:cxNTF { g__exsheets_#2_active_prop }
+ { \exp_not:v { l__exsheets_questions_#1_tl } }
+ \l__exsheets_tmpa_tl
+ {
+ \bool_set_true:c { l__exsheets_#1_active_bool }
+ \bool_set_true:N \l__exsheets_use_this_question_bool
+ }
+ {
+ \bool_set_false:c { l__exsheets_#1_active_bool }
+ \bool_set_false:N \l__exsheets_questions_print_bool
+ }
+ }
+ }
+ \cs_new_protected:cpn { __exsheets_solutions_use_#2: }
+ {
+ % are we using #2?
+ \bool_if:cT { g__exsheets_use_#2_bool }
+ {
+ % is the question to this solution an active one?
+ % get question number from ID
+ \prop_get:NVN \g__exsheets_questions_id_prop
+ \g__exsheets_questions_current_id_tl
+ \l__exsheets_tmpa_tl
+ % get question #1 from number
+ \prop_get:cVN { g__exsheets_questions_#1_prop }
+ \l__exsheets_tmpa_tl
+ \l__exsheets_tmpb_tl
+ % test if #1 is active
+ \prop_get:cVNF { g__exsheets_#2_active_prop }
+ \l__exsheets_tmpb_tl
+ \l__exsheets_tmpc_tl
+ { \bool_set_false:N \l__exsheets_solutions_use_bool }
+ % \bool_show:N \l__exsheets_solutions_use_bool
+ }
+ }
+ }
+
+\cs_new_protected:Npn \exsheets_declare_question_class:nn #1#2
+ {
+ \prop_if_in:NnTF \l__exsheets_class_prop {#2}
+ {}
+ { \exsheets_new_question_class:nn {#1} {#2} }
+ }
+
+\NewDocumentCommand \DeclareQuestionClass { mm }
+ { \exsheets_declare_question_class:nn {#1} {#2} }
+\@onlypreamble \DeclareQuestionClass
+
+% #1: class name
+\cs_new:Npn \exsheets_get_question_class:n #1
+ {
+ \cs_if_exist:cT { l__exsheets_questions_#1_tl }
+ { \tl_use:c { l__exsheets_questions_#1_tl } }
+ }
+
+% #1: class name
+\DeclareExpandableDocumentCommand \GetQuestionClass { m }
+ { \exsheets_get_question_class:n {#1} }
+
+% #1: class name
+\prg_new_conditional:Npnn \exsheets_if_question_class:n #1 {T,F,TF}
+ {
+ \tl_if_blank:fTF { \exsheets_get_question_class:n {#1} }
+ { \prg_return_false: }
+ { \prg_return_true: }
+ }
+\cs_generate_variant:Nn \tl_if_blank:nTF {f}
+
+% #1: class name
+\cs_new_protected:Npn \exsheets_print_question_class:nTF #1#2#3
+ {
+ \exsheets_if_question_class:nTF {#1}
+ {
+ \cs_set_protected:Npn \__exsheets_print_question_class:n ##1 {#2}
+ \__exsheets_print_question_class:n
+ { \exsheets_get_question_class:n {#1} }
+ }
+ {#3}
+ }
+
+\NewDocumentCommand \PrintQuestionClassTF { mmm }
+ { \exsheets_print_question_class:nTF {#1} {#2} {#3} }
+\NewDocumentCommand \PrintQuestionClassT { mm }
+ { \exsheets_print_question_class:nTF {#1} {#2} { } }
+\NewDocumentCommand \PrintQuestionClassF { mm }
+ { \exsheets_print_question_class:nTF {#1} { } {#2} }
+
+% ----------------------------------------------------------------------------
+% question tags:
+% #1: ID
+% #2: tags
+\cs_new_protected:Npn \exsheets_set_question_tags:nn #1#2
+ { \prop_gput:Nnn \g__exsheets_tags_prop {#1} {#2} }
+\cs_generate_variant:Nn \exsheets_set_question_tags:nn {V}
+
+\cs_new_protected:Npn \exsheets_set_this_question_tags:n #1
+ { \exsheets_set_question_tags:Vn \g__exsheets_questions_current_id_tl {#1} }
+
+\keys_define:nn {exsheets}
+ {
+ use-tags .code:n = \seq_set_split:Nnn \l__exsheets_use_tags_seq {,} {#1} ,
+ question / tags .code:n =
+ \exsheets_after_begin_question:n { \exsheets_set_this_question_tags:n {#1} }
+ }
+
+% #1: ID
+\prg_new_protected_conditional:Npnn \exsheets_check_question_tags:n #1 {T,F,TF}
+ {
+ \bool_set_false:N \l__exsheets_tmpa_bool
+ \seq_if_empty:NTF \l__exsheets_use_tags_seq
+ { \bool_set_true:N \l__exsheets_tmpa_bool }
+ {
+ \prop_get:NnN \g__exsheets_tags_prop {#1} \l__exsheets_tmpa_tl
+ \seq_map_inline:Nn \l__exsheets_use_tags_seq
+ {
+ \tl_if_in:NnT \l__exsheets_tmpa_tl {##1}
+ {
+ \bool_set_true:N \l__exsheets_tmpa_bool
+ \seq_map_break:
+ }
+ }
+ }
+ \bool_if:NTF \l__exsheets_tmpa_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \exsheets_check_question_tags:nF {V}
+
+% ----------------------------------------------------------------------------
+% die 'question' Umgebung
+\cs_new:Npn \IfInsideQuestionTF
+ { \bool_if:NTF \l__exsheets_inside_question_bool }
+\cs_new:Npn \IfInsideQuestionT
+ { \bool_if:NT \l__exsheets_inside_question_bool }
+\cs_new:Npn \IfInsideQuestionF
+ { \bool_if:NF \l__exsheets_inside_question_bool }
+
+\cs_new_eq:NN \exsheets_par: \par
+
+\cs_new_protected:Npn \exsheets_after_begin_question:n #1
+ { \tl_put_right:Nn \l__exsheets_after_begin_question_tl {#1} }
+
+\cs_new_protected:Npn \exsheets_add_space:N #1
+ {
+ \bool_if:nF
+ {
+ % \l__exsheets_heading_runin_bool ||
+ \l__exsheets_heading_inline_bool ||
+ \l__exsheets_no_skip_after_bool
+ }
+ {
+ \exsheets_par:
+ \dim_compare:nNnT { \parskip } = { 0pt }
+ { \exsheets_glue:N #1 }
+ }
+ }
+
+% #1: pre question hook
+% #2: post question hook
+\NewEnviron { __exsheets_questions_internal: } [2]
+ {
+ \__exsheets_start_question_if_used:n {#1}
+ \bool_if:nT
+ {
+ % \l__exsheets_questions_print_bool &&
+ \g__exsheets_questions_use_bool &&
+ !\l__exsheets_questions_deactivate_bool
+ }
+ {
+ \exsheets_if_current_question_is_used:T
+ {
+ % label:
+ \tl_if_blank:VTF \l__exsheets_questions_label_tl
+ {
+ \bool_if:NT \l__exsheets_auto_label_bool
+ {
+ \exsheets_label:V \g__exsheets_questions_current_id_tl
+ \exsheets_set_ref_properties:V \CurrentQuestionID
+ }
+ }
+ {
+ \exsheets_label:V \l__exsheets_questions_label_tl
+ \exsheets_set_ref_properties:V \l__exsheets_questions_label_tl
+ }
+ \__exsheets_save_number_in:N \g_exsheets_question_identification_prop
+ % TODO: don't print, only save if \l__exsheets_questions_print_bool is false
+ \__exsheets_save_and_print_question_body:VVV
+ \BODY
+ \l__exsheets_questions_pre_body_hook_tl
+ \l__exsheets_questions_post_body_hook_tl
+ \exsheets_set_question_properties:x
+ {
+ \tl_if_blank:VF \l__exsheets_questions_subtitle_tl
+ { subtitle = { \exp_not:V \l__exsheets_questions_subtitle_tl } , }
+ counter = \l__exsheets_qu_counter_interpretation_tl ,
+ % number = \int_to_arabic:V \g__exsheets_questions_id_int ,
+ \bool_if:NF \l__exsheets_points_questions_default_bool
+ {
+ \fp_compare:nT { \g__exsheets_this_question_points_fp > 0 }
+ { points = \fp_to_decimal:N \g__exsheets_this_question_points_fp , }
+ \fp_compare:nT { \g__exsheets_this_question_bonus_fp > 0 }
+ { bonus-points = \fp_to_decimal:N \g__exsheets_this_question_bonus_fp }
+ }
+ }
+ \bool_if:NT \l__exsheets_questions_print_bool {#2}
+ }
+ }
+ }
+
+% #1: body
+% #2: pre body hook
+% #3: post body hook
+\cs_new_protected:Npn \__exsheets_save_and_print_question_body:nnn #1#2#3
+ {
+ \group_begin:
+ \bool_if:NF \l__exsheets_save_question_body_to_aux_bool
+ { \@fileswfalse }
+ \exsheets_set_question_properties:n { question-body = {#1} }
+ \group_end:
+ \bool_if:NT \l__exsheets_questions_print_bool
+ {
+ #2 { #1 } #3
+ \exsheets_add_space:N \l__exsheets_questions_skip_below_dim
+ }
+ }
+\cs_generate_variant:Nn \__exsheets_save_and_print_question_body:nnn { VVV }
+
+\prg_new_conditional:Npnn \exsheets_if_question_subtitle: { p,T,F,TF }
+ {
+ \tl_if_blank:VTF \l__exsheets_questions_subtitle_tl
+ { \prg_return_false: }
+ { \prg_return_true: }
+ }
+
+\cs_new:Npn \IfQuestionSubtitleTF { \exsheets_if_question_subtitle:TF }
+\cs_new:Npn \IfQuestionSubtitleT { \exsheets_if_question_subtitle:T }
+\cs_new:Npn \IfQuestionSubtitleF { \exsheets_if_question_subtitle:F }
+
+\cs_new_protected:Npn \__exsheets_read_points:w #1 ! #2 ! #3 \q_stop
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \bool_set_true:N \l__exsheets_only_print_points_bool
+ \tl_set:Nn \l__exsheets_questions_points_tl {#2}
+ }
+ {
+ \bool_set_false:N \l__exsheets_only_print_points_bool
+ \__exsheets_read_points_aux:w #1++ \q_stop
+ }
+ }
+
+\cs_new_protected:Npn \__exsheets_read_points_aux:w #1+#2+#3 \q_stop
+ {
+ \tl_if_blank:nTF {#1}
+ { \fp_zero:N \l__exsheets_question_points_fp }
+ { \fp_set:Nn \l__exsheets_question_points_fp {#1} }
+ \tl_if_blank:nTF {#2}
+ { \fp_zero:N \l__exsheets_question_bonus_fp }
+ {
+ \tl_if_blank:nTF {#3}
+ { \fp_zero:N \l__exsheets_question_bonus_fp }
+ { \fp_set:Nn \l__exsheets_question_bonus_fp {#2} }
+ }
+ }
+\cs_new_protected:Npn \__exsheets_read_points:n #1
+ {
+ \bool_if:NTF \l__exsheets_parse_points_bool
+ { \__exsheets_read_points:w #1!! \q_stop }
+ { \tl_set:Nn \l__exsheets_questions_points_tl {#1} }
+ }
+
+\cs_new:Npn \exsheets_label_format:n #1 { qu:#1 }
+\cs_new:Npn \__exsheets_label:n { \label }
+\cs_new:Npn \exsheets_label:n { }
+\cs_generate_variant:Nn \exsheets_label:n { V }
+\cs_new:Npn \__exsheets_ref:n { \ref }
+\cs_new:Npn \exsheets_ref:n { }
+\cs_new:Npn \__exsheets_pageref:n { \pageref }
+\cs_new:Npn \exsheets_pageref:n { }
+
+\cs_new_protected:Npn \exsheets_update_referencing_command:NN #1#2
+ {
+ \cs_set:Npx #1 ##1
+ { \exp_not:o {#2} { \exsheets_label_format:n {##1} } }
+ }
+
+\cs_new_protected:Npn \exsheets_update_referencing_commands:
+ {
+ \exsheets_update_referencing_command:NN \exsheets_label:n \__exsheets_label:n
+ \exsheets_update_referencing_command:NN \exsheets_ref:n \__exsheets_ref:n
+ \exsheets_update_referencing_command:NN \exsheets_pageref:n \__exsheets_pageref:n
+ }
+
+\cs_new_protected:Npn \exsheets_set_ref_properties:n #1
+ {
+ \exsheets_set_question_properties:x
+ {
+ ref = \exp_not:o { \exsheets_ref:n {#1} } ,
+ pageref = \exp_not:o { \exsheets_pageref:n {#1} }
+ }
+ }
+\cs_generate_variant:Nn \exsheets_set_ref_properties:n { V }
+
+\exsheets_update_referencing_commands:
+
+\cs_new_protected:Npn \__exsheets_determine_question_usage:
+ {
+ \tl_gclear:N \g__exsheets_use_current_question_tl
+ \prop_map_inline:Nn \l__exsheets_class_prop
+ {
+ \use:c { __exsheets_questions_use_##1: }
+ \bool_if:nTF
+ {
+ (
+ \l__exsheets_use_this_question_bool
+ &&
+ \bool_if_p:c { l__exsheets_##2_active_bool }
+ )
+ ||
+ ! \bool_if_p:c { g__exsheets_use_##1_bool }
+ }
+ { \tl_gput_right:Nn \g__exsheets_use_current_question_tl { y } }
+ { \tl_gput_right:Nn \g__exsheets_use_current_question_tl { n } }
+ }
+ }
+
+\prg_new_protected_conditional:Npnn \exsheets_if_current_question_is_used: { T,F,TF }
+ {
+ \tl_if_in:NnTF \g__exsheets_use_current_question_tl { n }
+ { \prg_return_false: }
+ { \prg_return_true: }
+ }
+
+% #1: options
+\cs_new_protected:Npn \__exsheets_question_start:n #1
+ {
+ \bool_set_true:N \l__exsheets_inside_question_bool
+ \bool_if:NT \l__exsheets_questions_use_bool
+ { \bool_gset_true:N \g__exsheets_questions_use_bool }
+ % Optionen:
+ \tl_if_blank:nF {#1} { \keys_set:nn { exsheets / question } {#1} }
+ % ID:
+ \__exsheets_determine_question_usage:
+ \bool_if:nT
+ {
+ (\l__exsheets_questions_deactivate_bool && \l__exsheets_select_questions_bool)
+ ||
+ !\l__exsheets_select_questions_bool
+ }
+ {
+ \int_gincr:N \g__exsheets_questions_id_int
+ \tl_if_blank:VTF \l__exsheets_questions_id_tl
+ {
+ \tl_gset:Nx \g__exsheets_questions_current_id_tl
+ { \int_use:N \g__exsheets_questions_id_int }
+ }
+ {
+ \tl_gset:Nx \g__exsheets_questions_current_id_tl
+ { \tl_use:N \l__exsheets_questions_id_tl }
+ }
+ }
+ \tl_use:N \l__exsheets_after_begin_question_tl
+ \tl_clear:N \l__exsheets_after_begin_question_tl
+ }
+
+% #1: points or blank
+\cs_new_protected:Npn \__exsheets_question_points:n #1
+ {
+ % Punktevergabe:
+ \fp_gzero:N \g__exsheets_this_question_points_fp
+ \fp_gzero:N \g__exsheets_this_question_bonus_fp
+ \tl_if_blank:nTF {#1}
+ {
+ \__exsheets_read_points:n { 0 }
+ \bool_if:NT \l__exsheets_points_questions_default_bool
+ {
+ \fp_set_eq:NN
+ \l__exsheets_question_points_fp
+ \l__exsheets_points_default_fp
+ % check if moving this to a later point has negative effects...
+ % \exsheets_set_question_properties:x
+ % { points = \fp_to_tl:N \l__exsheets_points_default_fp }
+ }
+ }
+ {
+ \fp_gset_eq:NN
+ \g__exsheets_this_question_points_fp
+ \l__exsheets_question_points_fp
+ \fp_gset_eq:NN
+ \g__exsheets_this_question_bonus_fp
+ \l__exsheets_question_bonus_fp
+ \__exsheets_read_points:n {#1}
+ % check if moving this to a later point has negative effects...
+ % \exsheets_set_question_properties:n { points = #2 }
+ }
+ }
+
+% #1: pre question hook
+\cs_new_protected:Npn \__exsheets_start_question_if_used:n #1
+ {
+ \tl_if_blank:VT \l__exsheets_question_heading_instance_tl
+ {
+ \tl_set_eq:NN
+ \l__exsheets_question_heading_instance_tl
+ \l__exsheets_heading_instance_tl
+ }
+ % Auswahl der Frage:
+ \__exsheets_select_question:V \g__exsheets_questions_current_id_tl
+ \prop_map_inline:Nn \l__exsheets_class_prop
+ { \use:c { __exsheets_questions_use_##1: } }
+ \exsheets_check_question_tags:VF \g__exsheets_questions_current_id_tl
+ { \bool_gset_false:N \g__exsheets_questions_use_bool }
+ \bool_if:nT
+ {
+ \g__exsheets_questions_use_bool &&
+ !\l__exsheets_questions_deactivate_bool
+ }
+ {
+ \exsheets_if_current_question_is_used:T
+ { \refstepcounter {question} }
+ \__exsheets_get_sectioning_numbers:
+ \bool_if:nT
+ {
+ (
+ \l__exsheets_points_questions_default_bool &&
+ \l__exsheets_parse_points_bool
+ ) ||
+ (
+ \l__exsheets_parse_points_bool% &&
+ % \l__exsheets_questions_print_bool
+ )
+ }
+ {
+ \exsheets_if_current_question_is_used:T
+ {
+ \exsheets_add_points:V \l__exsheets_question_points_fp
+ \exsheets_add_bonus:V \l__exsheets_question_bonus_fp
+ }
+ }
+ \tl_if_blank:VTF \l__exsheets_questions_id_tl
+ {
+ \tl_set:Nx \l__exsheets_tmpa_tl
+ { \int_use:N \g__exsheets_questions_id_int }
+ }
+ {
+ \tl_set_eq:NN
+ \l__exsheets_tmpa_tl
+ \l__exsheets_questions_id_tl
+ }
+ \tl_set_eq:NN \CurrentQuestionID \l__exsheets_tmpa_tl
+ \bool_if:NT \l__exsheets_questions_print_bool
+ {
+ \bool_if:NTF \l__exsheets_exam_bool
+ {
+ \tl_set_eq:NN
+ \l__exsheets_questions_title_tl
+ \l__exsheets_questions_name_tl
+ }
+ {
+ \tl_set_eq:NN
+ \l__exsheets_questions_title_tl
+ \l__exsheets_exercise_name_tl
+ }
+ \bool_if:nTF
+ { \l__exsheets_parse_points_bool && !\l__exsheets_only_print_points_bool }
+ {
+ #1
+ \exsheets_use_heading:VVVVnV
+ \l__exsheets_question_heading_instance_tl
+ \l__exsheets_questions_title_tl
+ \l__exsheets_qu_counter_interpretation_tl
+ \l__exsheets_question_points_fp
+ { \l__exsheets_question_bonus_fp }
+ \l__exsheets_tmpa_tl
+ }
+ {
+ \bool_if:NT \l__exsheets_only_print_points_bool
+ { \bool_set_false:N \l__exsheets_parse_points_bool }
+ % might be dangerous to expand here...
+ \tl_if_blank:xTF { \l__exsheets_questions_points_tl }
+ {
+ #1
+ \exsheets_use_heading:VVVnnV
+ \l__exsheets_question_heading_instance_tl
+ \l__exsheets_questions_title_tl
+ \l__exsheets_qu_counter_interpretation_tl
+ {0}
+ {0}
+ \l__exsheets_tmpa_tl
+ }
+ {
+ #1
+ \exsheets_use_heading:VVVVnV
+ \l__exsheets_question_heading_instance_tl
+ \l__exsheets_questions_title_tl
+ \l__exsheets_qu_counter_interpretation_tl
+ \l__exsheets_questions_points_tl
+ {0}
+ \l__exsheets_tmpa_tl
+ }
+ }
+ }
+ }
+ }
+\cs_generate_variant:Nn \__exsheets_start_question_if_used:n {V}
+
+\newenvironment { __exsheets_question: } [2]
+ {
+ \__exsheets_question_start:n {#1}
+ \__exsheets_question_points:n {#2}
+ \exp_args:NVV \__exsheets_questions_internal:
+ \l__exsheets_questions_pre_hook_tl
+ \l__exsheets_questions_post_hook_tl
+ }
+ {
+ \end__exsheets_questions_internal:
+ }
+
+% current question number:
+\cs_new_protected:Npn \exsheets@save@number #1#2
+ { \expandafter\global\expandafter\edef\csname exsheets@question@#1\endcsname{#2} }
+
+\cs_new_protected:Npn \__exsheets_save_number_in_aux_x:Nnn #1#2#3
+ {
+ \prop_gput:Nfx #1 {#2} {#3}
+ \exsheets_write_to_aux_x:n { \exsheets@save@number {#2} {#3} }
+ }
+
+\cs_new_protected:Npn \__exsheets_save_number_in:N #1
+ {
+ \bool_if:NTF \l__exsheets_print_number_bool
+ {
+ \cs_if_exist:NTF \thechapter
+ {
+ \__exsheets_save_number_in_aux_x:Nnn #1
+ { \int_use:N \g__exsheets_questions_id_int }
+ { \arabic{chapter}-\arabic{section}-\arabic{question} }
+ }
+ {
+ \__exsheets_save_number_in_aux_x:Nnn #1
+ { \int_use:N \g__exsheets_questions_id_int }
+ { -\arabic{section}-\arabic{question} }
+ }
+ }
+ {
+ \cs_if_exist:NTF \thechapter
+ {
+ \__exsheets_save_number_in_aux_x:Nnn #1
+ { \int_use:N \g__exsheets_questions_id_int }
+ { @@@\arabic{chapter}-\arabic{section}-\arabic{question} }
+ }
+ {
+ \__exsheets_save_number_in_aux_x:Nnn #1
+ { \int_use:N \g__exsheets_questions_id_int }
+ { @@@-\arabic{section}-\arabic{question} }
+ }
+ }
+ }
+
+% #1: prop
+% #2: id
+% #3: code
+\cs_new_protected:Npn \__exsheets_restore_number_from_and_do:Nnn #1#2#3
+ {
+ \prop_get:NnNT #1 {#2} \l__exsheets_tmpc_tl
+ {
+ \exp_after:wN
+ \__exsheets_read_number:w \l__exsheets_tmpc_tl \q_stop
+ #3
+ }
+ % use \exsheets_read_counter_settings:V \l__exsheets_qu_counter_format_tl
+ % afterwards to print the number
+ }
+\cs_generate_variant:Nn \__exsheets_restore_number_from_and_do:Nnn { NV }
+
+\DeclareExpandableDocumentCommand \QuestionNumber {m}
+ { \exsheets_question_number:n {#1} }
+
+\cs_new:Npn \exsheets_question_number:n #1
+ { \exsheets_get_question_property:nn {counter} {#1} }
+
+% \cs_new_protected:Npn \__exsheets_question_number:N #1
+% {
+% \cs_if_exist:NTF #1
+% {
+% \exp_after:wN \__exsheets_get_question_number:w #1 \q_stop
+% \ReadCounterPatternFrom [exsheets] \l__exsheets_qu_counter_pattern_tl
+% }
+% { \textbf {??} }
+% }
+% \cs_generate_variant:Nn \__exsheets_question_number:N { c }
+
+% \cs_new_protected:Npn \__exsheets_get_question_number:w #1-#2-#3 \q_stop
+% {
+% \cs_if_exist:NT \thechapter
+% { \int_set:Nn \l__exsheets_counter_ch_int {#1} }
+% \int_set:Nn \l__exsheets_counter_sec_int {#2}
+% \int_set:Nn \l_exsheets_counter_qu_int {#3}
+% }
+
+% map ID's to number of used questions
+\cs_new_protected:Npn \exsheets@used@id #1#2
+ { \prop_gput:Nnn \g__exsheets_questions_used_prop {#1} {#2} }
+
+\cs_new_protected:Npn \__exsheets_mark_as_used:n #1
+ {
+ \int_gincr:N \g__exsheets_questions_used_int
+ \prop_gput_if_new:Nxx \g__exsheets_questions_used_prop
+ {#1}
+ { \int_use:N \g__exsheets_questions_used_int }
+ \exsheets_write_to_aux_x:n
+ { \exsheets@used@id {#1} { \int_use:N \g__exsheets_questions_used_int } }
+ }
+
+% ----------------------------------------------------------------------------
+% title of a question:
+\cs_if_exist:NF \exsheets_headings_files_loaded:
+ {
+ \file_input:n {exsheets_headings.def}
+ \file_input:n {exsheets_headings.cfg}
+ }
+
+% #1: instance
+% #2: title
+% #3: number
+% #4: points
+% #5: bonus
+% #6: id
+\cs_new_protected:Npn \exsheets_use_heading:nnnnnn #1#2#3#4#5#6
+ {
+ \IfInstanceExistTF {exsheets-heading} {#1}
+ { \UseInstance {exsheets-heading} {#1} }
+ {
+ \msg_warning:nnx {exsheets} {headings} {#1}
+ \UseInstance {exsheets-heading} {block}
+ }
+ {#2} {#3} {#4} {#5} {#6}
+ }
+\cs_generate_variant:Nn \exsheets_use_heading:nnnnnn { V , VVVnnV , VVVVnV }
+
+\NewDocumentCommand \ExSheetsHeading { mmmmmm }
+ { \exsheets_use_heading:nnnnnn {#1} {#2} {#3} {#4} {#5} {#6} }
+
+% options for the questions:
+\keys_define:nn { exsheets / question }
+ {
+ type .choice: ,
+ type / exam .code:n =
+ \bool_set_true:N \l__exsheets_exam_bool ,
+ type / exercise .code:n =
+ \bool_set_false:N \l__exsheets_exam_bool ,
+ name .code:n =
+ \tl_set:Nn \l__exsheets_exercise_name_tl {#1}
+ \tl_set:Nn \l__exsheets_questions_name_tl {#1} ,
+ headings .tl_set:N = \l__exsheets_question_heading_instance_tl ,
+ subtitle .tl_set:N = \l__exsheets_questions_subtitle_tl ,
+ print .bool_set:N = \l__exsheets_questions_print_bool ,
+ print .default:n = true ,
+ ID .tl_set:N = \l__exsheets_questions_id_tl ,
+ label .tl_set:N = \l__exsheets_questions_label_tl ,
+ use .choice: ,
+ use / true .code:n =
+ \bool_gset_true:N \g__exsheets_questions_use_bool
+ \bool_set_true:N \l__exsheets_questions_use_bool ,
+ use / false .code:n =
+ \bool_gset_false:N \g__exsheets_questions_use_bool
+ \bool_set_false:N \l__exsheets_questions_use_bool ,
+ use .default:n = true ,
+ skip-below .dim_set:N = \l__exsheets_questions_skip_below_dim ,
+ no-skip-below .bool_set:N = \l__exsheets_no_skip_after_bool ,
+ pre-hook .tl_set:N = \l__exsheets_questions_pre_hook_tl ,
+ post-hook .tl_set:N = \l__exsheets_questions_post_hook_tl ,
+ pre-body-hook .tl_set:N = \l__exsheets_questions_pre_body_hook_tl ,
+ post-body-hook .tl_set:N = \l__exsheets_questions_post_body_hook_tl ,
+ save-to-aux .bool_set:N = \l__exsheets_save_question_body_to_aux_bool
+ }
+
+% ----------------------------------------------------------------------------
+% using ``metadata'':
+\cs_new_protected:Npn \exsheets_declare_question_property:n #1
+ {
+ \prop_new:c { g__exsheets_question_property_#1_prop }
+ \keys_define:nn { question / meta }
+ { #1 .code:n = \__exsheets_question_set_property:nn {#1} {##1} }
+ }
+
+\NewDocumentCommand \DeclareQuestionProperty { m }
+ { \exsheets_declare_question_property:n {#1} }
+\@onlypreamble \DeclareQuestionProperty
+
+\cs_new_protected:Npn \exsheets_set_question_properties:n #1
+ {
+ \@bsphack
+ \bool_if:NTF \l__exsheets_inside_question_bool
+ { \keys_set:nn { question / meta } {#1} }
+ { \msg_error:nnn {exsheets} {only-inside-question} {\SetQuestionProperties} }
+ \@esphack
+ }
+\cs_generate_variant:Nn \exsheets_set_question_properties:n { x }
+
+% #1: property
+% #2: ID
+\prg_new_conditional:Npnn \exsheets_if_question_property:nn #1#2 {T,F,TF}
+ {
+ \prop_if_in:cnTF { g__exsheets_question_property_#1_prop } {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\DeclareExpandableDocumentCommand \IfQuestionPropertyTF { }
+ { \exsheets_if_question_property:nnTF }
+\DeclareExpandableDocumentCommand \IfQuestionPropertyT { }
+ { \exsheets_if_question_property:nnT }
+\DeclareExpandableDocumentCommand \IfQuestionPropertyF { }
+ { \exsheets_if_question_property:nnF }
+
+\NewDocumentCommand \SetQuestionProperties { +m }
+ { \exsheets_set_question_properties:n {#1} }
+
+% #1: ID
+% #2: property
+% #3: value
+\cs_new_protected:Npn \exsheets@question@property #1#2#3
+ {
+ \prop_gput:cnn { g__exsheets_question_property_#2_prop }
+ {#1} {#3}
+ }
+
+% #1: property
+% #2: value
+\cs_new_protected:Npn \__exsheets_question_set_property:nn #1#2
+ {
+ \prop_gput:cVn { g__exsheets_question_property_#1_prop }
+ \CurrentQuestionID {#2}
+ % watch if this has negativ effects:
+ \exsheets_write_to_aux_x:n
+ {
+ \exp_not:N \exsheets@question@property
+ { \CurrentQuestionID }
+ { \exp_not:n {#1} }
+ { \exp_not:n {#2} }
+ }
+ }
+
+% #1: property
+% #2: ID
+\DeclareExpandableDocumentCommand \GetQuestionProperty { mm }
+ { \exsheets_get_question_property:no {#1} {#2} }
+
+\cs_new:Npn \exsheets_get_question_property:nn #1#2
+ {
+ \prop_if_in:cnTF { g__exsheets_question_property_#1_prop } {#2}
+ { \prop_item:cn { g__exsheets_question_property_#1_prop } {#2} }
+ { ?? }
+ }
+\cs_generate_variant:Nn \exsheets_get_question_property:nn { no , nV }
+
+\cs_new_protected:Npn \exsheets_for_each_question_do:n #1
+ {
+ \int_gzero:N \g__exsheets_tmpa_int
+ \prop_map_inline:Nn \g__exsheets_questions_used_prop
+ { \int_gincr:N \g__exsheets_tmpa_int #1 }
+ }
+
+\NewDocumentCommand \ForEachQuestion {m}
+ { \exsheets_for_each_question_do:n {#1} }
+
+\cs_new:Npn \iflastquestion
+ {
+ \int_compare:nTF
+ { \numberofquestions = \g__exsheets_tmpa_int }
+ }
+
+\cs_if_exist:NF \numberofquestions
+ {
+ \cs_new:Npn \numberofquestions
+ { \int_to_arabic:V \g__exsheets_questions_used_int }
+ }
+
+% ----------------------------------------------------------------------------
+% debug-Info:
+\RequirePackage {xcolor}
+\colorlet {exsheetsdebugcolor} {yellow}
+
+\keys_define:nn {exsheets}
+ {
+ debug .bool_set:N = \l__exsheets_questions_debug_bool
+ }
+
+\cs_new_protected:Npn \exsheets_debug_box:nn #1#2
+ {
+ \par
+ \noindent
+ \group_begin:
+ \normalfont\normalsize\normalcolor
+ \colorbox {exsheetsdebugcolor}
+ { \parbox { \dim_eval:n { #1 - 2 \fboxsep } } {#2} }
+ \group_end:
+ \par
+ }
+
+\cs_new:Npn \__exsheets_list_comma: {}
+
+\cs_new_protected:Npn \exsheets_questions_debug:n #1
+ {
+ \bool_if:nT
+ { \l__exsheets_questions_debug_bool && \l__exsheets_inside_question_bool }
+ {
+ \exsheets_debug_box:nn { \linewidth }
+ {
+ \textbf {ID} :~ \textit {#1}
+ \prop_map_inline:Nn \l__exsheets_class_prop
+ {
+ \bool_if:cT { l__exsheets_questions_##2_bool }
+ {
+ ;~ \textbf {##2} :~
+ \textit { \tl_use:c { l__exsheets_questions_##2_tl } }
+ }
+ }
+ \prop_get:NnN \g__exsheets_tags_prop
+ {#1}
+ \l__exsheets_tmpa_tl
+ \quark_if_no_value:VTF \l__exsheets_tmpa_tl
+ { ;~ \textbf {not~tagged} }
+ {
+ ;~ \textbf {tags} : ~
+ \seq_set_split:NnV \l__exsheets_tmpa_seq
+ {,}
+ \l__exsheets_tmpa_tl
+ \textit { \seq_use:Nn \l__exsheets_tmpa_seq {,~} }
+ }
+ }
+ }
+ }
+
+\exsheets_deprecate_cs:Npnn \DebugExSheets #1
+ {the~ option~ debug}
+ { \keys_set:nn {exsheets} { debug = #1 } }
+
+% ----------------------------------------------------------------------------
+% include random/selected questions from a file:
+\cs_new_protected:Npn \exsheets_file_input_if_exist:n #1
+ { \file_if_exist:nT {#1} { \file_input:n {#1} } }
+\cs_new_protected:Npn \exsheets_file_input_if_exist:nF #1#2
+ { \file_if_exist:nTF {#1} { \file_input:n {#1} } {#2} }
+
+\cs_new_protected:Npn \exsheets_prop_count:N #1
+ {
+ \__exsheets_prop_count:NN #1 \l__exsheets_tmpa_int
+ \int_use:N \l__exsheets_tmpa_int
+ }
+
+\cs_new_protected:Npn \__exsheets_prop_count:NN #1#2
+ {
+ \int_zero:N #2
+ \prop_map_inline:Nn #1
+ { \int_incr:N #2 }
+ }
+
+\NewDocumentCommand \includequestions { om }
+ {
+ \group_begin:
+ \IfNoValueF {#1}
+ { \keys_set:nn { exsheets / include } {#1} }
+ \exsheets_include_questions:n {#2}
+ \group_end:
+ }
+
+\cs_new_protected:Npn \exsheets_include_questions:n #1
+ {
+ \bool_set_true:N \l__exsheets_select_questions_bool
+ \clist_gclear:N \questionsincludedlast
+ \seq_set_split:Nnn \l__exsheets_tmpa_seq { , } {#1}
+ \seq_map_inline:Nn \l__exsheets_tmpa_seq
+ {
+ \bool_set_true:N \l__exsheets_questions_deactivate_bool
+ \int_set_eq:NN
+ \l__exsheets_questions_set_int
+ \g__exsheets_questions_used_int
+ \int_set_eq:NN
+ \l__exsheets_tmpc_int
+ \g__exsheets_questions_id_int
+ \int_gzero:N \g__exsheets_select_random_int
+ \exsheets_file_input_if_exist:nF {##1}
+ { \msg_error:nnn {exsheets} {file-not-found} {##1} }
+ \__exsheets_prop_count:NN
+ \g__exsheets_included_questions_prop
+ \l__exsheets_tmpa_int
+ \bool_if:NT \l__exsheets_questions_debug_bool
+ {
+ \exsheets_debug_box:nn
+ { \linewidth }
+ {
+ The~file~ ` \texttt { \tl_to_str:n {##1} } ' ~contains~
+ \exsheets_prop_count:N \g__exsheets_included_questions_prop
+ \c_space_tl questions~with~the~following~IDs:\par
+ \cs_set_protected:Npn \__exsheets_list_comma:
+ { \cs_set:Npn \__exsheets_list_comma: { ,~ } }
+ \prop_map_inline:Nn \g__exsheets_included_questions_prop
+ { \__exsheets_list_comma: ####2 }
+ }
+ }
+ \bool_set_false:N \l__exsheets_questions_deactivate_bool
+ \int_set_eq:NN \l__exsheets_tmpd_int \g__exsheets_questions_id_int
+ \int_gset_eq:NN \g__exsheets_questions_id_int \l__exsheets_tmpc_int
+ \bool_if:NT \l__exsheets_include_questions_no_duplicates_bool
+ {
+ \seq_map_inline:Nn \g_exsheets_included_questions_seq
+ { \clist_put_right:Nn \l__exsheets_exclude_id_clist {####1} }
+ }
+ \__exsheets_select_question_random:n {##1}
+ \exsheets_file_input_if_exist:n {##1}
+ \int_gset_eq:NN \g__exsheets_questions_id_int \l__exsheets_tmpd_int
+ \prop_gclear:N \g__exsheets_included_questions_prop
+ \clist_clear:N \l__exsheets_include_id_clist
+ \clist_clear:N \l__exsheets_exclude_id_clist
+ \int_gzero:N \g__exsheets_selection_number_int
+ % \seq_show:N \g_exsheets_included_questions_seq
+ }
+ \bool_set_false:N \l__exsheets_select_questions_bool
+ }
+
+% options:
+% - IDs=<list of IDs>
+% - all=true|false % default when no option is given
+% - random=<num>
+% - exclude=<list of IDs>
+\keys_define:nn { exsheets / include }
+ {
+ all .bool_set:N = \l__exsheets_include_all_bool ,
+ IDs .code:n =
+ \bool_set_false:N \l__exsheets_include_all_bool
+ \bool_set_false:N \l__exsheets_include_random_bool
+ \bool_set_true:N \l__exsheets_include_by_id_bool
+ \clist_set:Nn \l__exsheets_include_id_clist {#1} ,
+ % the `exclude' option does _not_ set \l__exsheets_include_random_bool ,
+ % \l__exsheets_include_by_id_bool or \l__exsheets_include_all_bool so
+ % it can be combined with the other options:
+ exclude .clist_set:N = \l__exsheets_exclude_id_clist ,
+ random .code:n =
+ \bool_set_false:N \l__exsheets_include_all_bool
+ \bool_set_true:N \l__exsheets_include_random_bool
+ \bool_set_false:N \l__exsheets_include_by_id_bool
+ \int_set:Nn \l__exsheets_include_random_int {#1} ,
+ no-duplicates .bool_set:N = \l__exsheets_include_questions_no_duplicates_bool
+ }
+
+\cs_new_protected:Npn \__exsheets_select_question:n #1
+ {
+ \bool_if:NTF \l__exsheets_select_questions_bool
+ {
+ \bool_if:NTF \l__exsheets_questions_deactivate_bool
+ {
+ \bool_if:NT \l__exsheets_questions_use_bool
+ {
+ \int_gincr:N \g__exsheets_selection_number_int
+ \bool_if:NTF \l__exsheets_include_random_bool
+ {
+ \prop_gput:Nxn \g__exsheets_included_questions_prop
+ { \int_use:N \g__exsheets_selection_number_int } {#1}
+ }
+ {
+ \prop_gput:Nxn \g__exsheets_included_questions_prop
+ { \int_use:N \g__exsheets_questions_id_int } {#1}
+ }
+ }
+ }
+ {
+ \int_gincr:N \g__exsheets_questions_id_int
+ \bool_if:NTF \l__exsheets_include_random_bool
+ {
+ \int_gincr:N \g__exsheets_select_random_int
+ \int_set_eq:NN \l__exsheets_tmpa_int \g__exsheets_select_random_int
+% ID: \int_use:N \g__exsheets_questions_id_int ,~
+% set: \int_use:N \l__exsheets_questions_set_int ,~
+% selection: \int_use:N \g__exsheets_selection_number_int ,~
+% tmpa: \int_use:N \l__exsheets_tmpa_int \par
+ }
+ {
+ \int_set_eq:NN
+ \l__exsheets_tmpa_int
+ \g__exsheets_questions_id_int
+ }
+ \prop_get:NxN \g__exsheets_included_questions_prop
+ { \int_use:N \l__exsheets_tmpa_int }
+ \l__exsheets_tmpa_tl
+ \__exsheets_select_question_by_id:V \l__exsheets_tmpa_tl
+ }
+ }
+ {
+ \__exsheets_use_question:n {#1}
+ }
+ }
+\cs_generate_variant:Nn \__exsheets_select_question:n { V }
+
+\cs_new_protected:Npn \__exsheets_select_question_by_id:n #1
+ {
+ \bool_if:NTF \l__exsheets_include_all_bool
+ {% parsing list of excluded IDs
+ \clist_if_in:NnTF
+ \l__exsheets_exclude_id_clist
+ {#1}
+ { \bool_gset_false:N \g__exsheets_questions_use_bool }
+ {
+ \bool_gset_true:N \g__exsheets_questions_use_bool
+ \clist_gput_right:Nn \questionsincludedlast {#1}
+ \seq_gput_right:Nn \g_exsheets_included_questions_seq {#1}
+ \__exsheets_use_question:n {#1}
+ }
+ }
+ {% parsing list of included IDs
+ \clist_if_in:NnTF
+ \l__exsheets_include_id_clist
+ {#1}
+ {
+ \clist_if_in:NnTF
+ \l__exsheets_exclude_id_clist
+ {#1}
+ { \bool_gset_false:N \g__exsheets_questions_use_bool }
+ {
+ \bool_gset_true:N \g__exsheets_questions_use_bool
+ \clist_gput_right:Nn \questionsincludedlast {#1}
+ \seq_gput_right:Nn \g_exsheets_included_questions_seq {#1}
+ \__exsheets_use_question:n {#1}
+ % \exsheets_if_current_question_is_used:T
+ % { \__exsheets_mark_as_used:n {#1} }
+ % \prop_gput:NnV \g__exsheets_questions_id_prop
+ % {#1}
+ % \g__exsheets_questions_id_int
+ }
+ }
+ { \bool_gset_false:N \g__exsheets_questions_use_bool }
+ }
+ }
+\cs_generate_variant:Nn \__exsheets_select_question_by_id:n { V }
+
+\cs_new_protected:Npn \__exsheets_use_question:n #1
+ {
+ \exsheets_if_current_question_is_used:T
+ { \__exsheets_mark_as_used:n {#1} }
+ \prop_gput:NnV \g__exsheets_questions_id_prop
+ {#1}
+ \g__exsheets_questions_id_int
+ }
+
+% TODO: poor efficiency -- there should be no need to map through
+% \l__exsheets_class_prop *two* times
+\cs_new_protected:Npn \__exsheets_select_question_random:n #1
+ {
+ \bool_if:NT \l__exsheets_include_random_bool
+ {
+ % number of question in file:
+ \__exsheets_prop_count:NN
+ \g__exsheets_included_questions_prop
+ \l__exsheets_tmpa_int
+ % number of selectable questions in file:
+ \int_zero:N \l__exsheets_tmpb_int
+ \prop_map_inline:Nn \g__exsheets_included_questions_prop
+ {
+ \prop_map_inline:Nn \l__exsheets_class_prop
+ {
+ \bool_if:cT { g__exsheets_use_####1_bool }
+ {
+ \bool_set_true:N \l__exsheets_use_selection_bool
+ \prop_get:cnNT { g__exsheets_questions_####2_prop } {##1}
+ \l__exsheets_tmpa_tl
+ {
+ \prop_if_in:cVT { g__exsheets_####1_active_prop }
+ \l__exsheets_tmpa_tl
+ { \int_incr:N \l__exsheets_tmpb_int }
+ }
+ }
+ }
+ }
+ \int_compare:nTF { \l__exsheets_include_random_int >= \l__exsheets_tmpa_int }
+ {
+ % not enough questions available:
+ \msg_warning:nnxxx {exsheets} {random-file}
+ { \int_use:N \l__exsheets_include_random_int }
+ {#1}
+ { \int_use:N \l__exsheets_tmpa_int }
+ \bool_set_true:N \l__exsheets_include_all_bool
+ }
+ {
+ \bool_if:nTF
+ {
+ \int_compare_p:n
+ { \l__exsheets_include_random_int >= \l__exsheets_tmpb_int }
+ &&
+ \l__exsheets_use_selection_bool
+ }
+ {
+ % not enough questions selectable:
+ \msg_warning:nnxxxx {exsheets} {random-selectable}
+ { \int_use:N \l__exsheets_include_random_int }
+ {#1}
+ { \int_use:N \l__exsheets_tmpa_int }
+ { \int_use:N \l__exsheets_tmpb_int }
+ \bool_set_true:N \l__exsheets_include_all_bool
+ }
+ {
+ \int_zero:N \l__exsheets_tmpb_int
+ \int_do_while:nn
+ { \l__exsheets_tmpb_int < \l__exsheets_include_random_int }
+ {
+ \pgfmathparse { random(\int_use:N \l__exsheets_tmpa_int) }
+ \tl_set_eq:NN \l__exsheets_tmpa_tl \pgfmathresult
+ \prop_get:NVN \g__exsheets_included_questions_prop
+ \l__exsheets_tmpa_tl
+ \l__exsheets_tmpb_tl
+ \clist_if_in:NVF \l__exsheets_include_id_clist \l__exsheets_tmpb_tl
+ {
+ \tl_clear:N \l__exsheets_include_id_tl
+ \prop_map_inline:Nn \l__exsheets_class_prop
+ {
+ \prop_get:cVNT { g__exsheets_questions_##2_prop }
+ \l__exsheets_tmpa_tl \l__exsheets_tmpc_tl
+ {
+ \bool_if:cT { g__exsheets_use_##1_bool }
+ {
+ \prop_if_in:cVTF { g__exsheets_##1_active_prop }
+ \l__exsheets_tmpc_tl
+ { \tl_put_right:Nn \l__exsheets_include_id_tl {y} }
+ { \tl_put_right:Nn \l__exsheets_include_id_tl {n} }
+ }
+ }
+ }
+ \bool_set_true:N \l__exsheets_tmpa_bool
+ \clist_if_in:NVT
+ \l__exsheets_exclude_id_clist
+ \l__exsheets_tmpb_tl
+ { \bool_set_false:N \l__exsheets_tmpa_bool }
+ \seq_if_in:NnT
+ \g_exsheets_included_questions_seq
+ \l__exsheets_tmpb_tl
+ { \bool_set_false:N \l__exsheets_tmpa_bool }
+ \tl_if_in:NnT \l__exsheets_include_id_tl {n}
+ { \bool_set_false:N \l__exsheets_tmpa_bool }
+ \bool_if:NT \l__exsheets_tmpa_bool
+ % \tl_if_in:NnF \l__exsheets_include_id_tl { n }
+ % {
+ % \clist_if_in:NVF
+ % \l__exsheets_exclude_id_clist
+ % \l__exsheets_tmpb_tl
+ {
+ \clist_put_right:NV
+ \l__exsheets_include_id_clist
+ \l__exsheets_tmpb_tl
+ \int_incr:N \l__exsheets_tmpb_int
+ }
+ % }
+ }
+ }
+ }
+ }
+ }
+ }
+% \cs_generate_variant:Nn \clist_if_in_p:Nn {NV}
+% \cs_generate_variant:Nn \seq_if_in_p:Nn {NV}
+
+\NewDocumentCommand \PrintIfIncludeActiveTF { mm }
+ { \bool_if:NTF \l__exsheets_questions_deactivate_bool {#2} {#1} }
+
+\NewDocumentCommand \PrintIfIncludeActiveT { }
+ { \bool_if:NF \l__exsheets_questions_deactivate_bool }
+
+\NewDocumentCommand \PrintIfIncludeActiveF { }
+ { \bool_if:NT \l__exsheets_questions_deactivate_bool }
+
+% ----------------------------------------------------------------------------
+% die 'solution' Umgebung:
+\cs_new_protected:Npn \__exsheets_save_solution:n #1
+ {
+ % save for later use
+ \bool_if:NTF \l__exsheets_include_all_bool
+ { \int_set:Nn \l__exsheets_tmpe_int { \g__exsheets_questions_id_int -1 } }
+ { \int_set_eq:NN \l__exsheets_tmpe_int \g__exsheets_questions_id_int }
+ \prop_gput:Nxn \g__exsheets_solutions_content_prop
+ { \int_use:N \g__exsheets_questions_id_int }
+ {#1}
+ \prop_gput:NxV \g__exsheets_solutions_questions_id_prop
+ { \int_use:N \g__exsheets_questions_id_int }
+ \g__exsheets_questions_current_id_tl
+ \prop_gput:NxV \g__exsheets_solutions_names_prop
+ { \int_use:N \g__exsheets_questions_id_int }
+ \l__exsheets_solutions_name_tl
+ \prop_gput:NxV \g__exsheets_solutions_counter_prop
+ { \int_use:N \g__exsheets_questions_id_int }
+ \l__exsheets_qu_counter_pattern_tl
+ % print here
+ \exsheets_if_current_question_is_used:T
+ {
+ \bool_if:NT \l__exsheets_solutions_print_bool
+ {
+ \int_set:Nn \l_exsheets_counter_qu_int { \arabic {question} }
+ \__exsheets_get_sectioning_numbers:
+ \__exsheets_print_solution:VVn
+ \g__exsheets_questions_current_id_tl
+ \l__exsheets_solutions_name_tl
+ {#1}
+ }
+ }
+ }
+\cs_generate_variant:Nn \__exsheets_save_solution:n { V }
+
+\NewEnviron { __exsheets_solution_internal: }
+ {
+ \bool_if:nT
+ { \g__exsheets_questions_use_bool && \l__exsheets_solutions_use_bool }
+ { \__exsheets_save_solution:V \BODY }
+ }
+
+\newenvironment {__exsheets_solution:} [1]
+ {
+ \tl_clear:N \l__exsheets_use_solution_tl
+ % \prop_show:N \l__exsheets_class_prop
+ \prop_map_inline:Nn \l__exsheets_class_prop
+ {
+ \use:c {__exsheets_solutions_use_##1:}
+ \bool_if:nTF
+ {
+ \l__exsheets_solutions_use_bool
+ &&
+ (
+ !\bool_if_p:c {g__exsheets_use_##1_bool}
+ ||
+ \bool_if_p:c {l__exsheets_##2_active_bool}
+ )
+ }
+ { \tl_put_right:Nn \l__exsheets_use_solution_tl {y} }
+ { \tl_put_right:Nn \l__exsheets_use_solution_tl {n} }
+ }
+ % verwende, wenn ein Ja dabei war:
+ \tl_if_in:NnT \l__exsheets_use_solution_tl {y}
+ { \bool_set_true:N \l__exsheets_solutions_use_bool }
+ \bool_if:NT \l__exsheets_questions_deactivate_bool
+ { \bool_set_false:N \l__exsheets_solutions_use_bool }
+ \bool_if:NT \l__exsheets_solutions_use_bool
+ {
+ \bool_set_true:N \l__exsheets_inside_solution_bool
+ \IfNoValueF {#1} { \keys_set:nn {exsheets/solution} {#1} }
+ }
+ \tl_if_blank:VT \l__exsheets_solution_heading_instance_tl
+ {
+ \tl_set_eq:NN
+ \l__exsheets_solution_heading_instance_tl
+ \l__exsheets_heading_instance_tl
+ }
+ \__exsheets_solution_internal:
+ }
+ { \end__exsheets_solution_internal: }
+
+\cs_new_protected:Npn \__exsheets_solutions_name:nnn #1#2#3
+ {
+ \tl_if_blank:VT \l__exsheets_solution_heading_instance_tl
+ {
+ \tl_set_eq:NN
+ \l__exsheets_solution_heading_instance_tl
+ \l__exsheets_heading_instance_tl
+ }
+ \exsheets_use_heading:Vnnnnn
+ \l__exsheets_solution_heading_instance_tl
+ {#2} {#1} { 0 } { 0 } {#3}
+ }
+\cs_generate_variant:Nn \__exsheets_solutions_name:nnn { VV , VVV }
+
+\cs_new:Npn \exsheets_solutions_name_style:n #1
+ { \l_exsheets_solutions_name_style_tl #1 }
+
+% ----------------------------------------------------------------------------
+% print solutions:
+% save section / chapter counter:
+\cs_new_protected:Npn \__exsheets_exlabel:n #1
+ {
+ \@bsphack
+ \exsheets_write_to_aux_x:n
+ {
+ \token_to_str:N \newlabel { exse:#1 }
+ { { \arabic {section} } { \thepage } }
+ }
+ \cs_if_exist:NT \thechapter
+ {
+ \exsheets_write_to_aux_x:n
+ {
+ \token_to_str:N \newlabel { exch:#1 }
+ { { \arabic {chapter} } { \thepage } }
+ }
+ }
+ \@esphack
+ }
+
+% user command:
+\cs_new_eq:NN \exlabel \__exsheets_exlabel:n
+
+% adapt \label, maybe do this _after_ BeginDocument:
+\bool_if:NT \l__exsheets_solutions_by_ref_bool
+ {
+ \cs_new_eq:NN \__exsheets_saved_label:n \label
+ \cs_set:Npn \label #1
+ { \__exsheets_saved_label:n {#1} \__exsheets_exlabel:n {#1} }
+ }
+
+% this is like \ref from latex.ltx
+\cs_new:Npn \__exsheets_exref:n #1
+ {
+ \cs_if_exist:cTF { r@#1 }
+ { \__exsheets_exref_aux:n {#1} }
+ {
+ 1\relax
+ \protect\G@refundefinedtrue
+ \@latex@warning{exlabel `#1' on page \thepage \space undefined}%
+ }
+ }
+
+\cs_new:Npn \__exsheets_exref_aux:n #1
+ { \exp_after:wN \exp_after:wN \exp_after:wN \use_i:nn \cs:w r@#1 \cs_end: }
+
+\cs_new_eq:NN \exref \__exsheets_exref:n
+
+% user command:
+\NewDocumentCommand \printsolutions { O{all} }
+ { \exsheets_print_solutions:n {#1} }
+
+% internal command:
+\cs_new_protected:Npn \exsheets_print_solutions:n #1
+ {
+ \group_begin:
+ \bool_set_true:N \l__exsheets_solutions_print_bool
+ \bool_set_true:N \l__exsheets_inside_solution_bool
+ \cs_set:Npn \S ##1 { \exref { exse:##1 } }
+ \cs_set:Npn \C ##1 { \exref { exch:##1 } }
+ \keys_set:nn { exsheets / exsheets_print_solutions } {#1}
+ \group_end:
+ }
+
+\keys_define:nn {exsheets}
+ {
+ exsheets_print_solutions .choice: ,
+ exsheets_print_solutions / section .code:n =
+ { \exsheets_print_solutions_section:n {#1} } ,
+ exsheets_print_solutions / chapter .code:n =
+ { \exsheets_print_solutions_chapter:n {#1} } ,
+ exsheets_print_solutions / all .code:n =
+ { \exsheets_print_solutions_all: } ,
+ exsheets_print_solutions / byID .code:n =
+ { \exsheets_print_solutions_byID:n {#1} }
+ }
+
+\cs_new_protected:Npn \__exsheets_get_sectioning_numbers:
+ {
+ \cs_if_exist:NT \chapter
+ { \int_set:Nn \l__exsheets_counter_ch_int { \arabic {chapter} } }
+ \int_set:Nn \l__exsheets_counter_sec_int { \arabic {section} }
+ \int_set:Nn \l_exsheets_counter_qu_int { \arabic {question} }
+ }
+
+% #1: numeric ID
+% #2: condition
+\cs_new_protected:Npn \__exsheets_print_solution_if:nn #1#2
+ {
+ \bool_if:nT
+ { #2 && \prop_if_in_p:Nn \g__exsheets_solutions_questions_id_prop {#1} }
+ {
+ \prop_get:NnN \g__exsheets_solutions_names_prop
+ {#1} \l__exsheets_tmpa_tl
+ \prop_get:NnN \g__exsheets_solutions_content_prop
+ {#1} \l__exsheets_tmpb_tl
+ \prop_get:NnN \g__exsheets_solutions_questions_id_prop
+ {#1} \l__exsheets_tmpc_tl
+ \prop_get:NnN \g__exsheets_solutions_counter_prop
+ {#1} \l__exsheets_tmpd_tl
+ \group_begin:
+ \tl_set_eq:NN \CurrentQuestionID \l__exsheets_tmpc_tl
+ \__exsheets_sectioning_hook:nV {ch}
+ \l__exsheets_new_chapter_hook_tl
+ \__exsheets_sectioning_hook:nV {sec}
+ \l__exsheets_new_section_hook_tl
+ \group_end:
+ \__exsheets_print_solution:VVV
+ \l__exsheets_tmpc_tl
+ \l__exsheets_tmpa_tl
+ \l__exsheets_tmpb_tl
+ }
+ }
+
+% print by section:
+\cs_new_protected:Npn \exsheets_print_solutions_section:n #1
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \prop_map_inline:Nn \g_exsheets_question_identification_prop
+ {
+ \__exsheets_print_solutions_section:nnn
+ {##1}
+ {##2}
+ { \arabic{section} }
+ }
+ }
+ {
+ \clist_map_inline:nn {#1}
+ { \__exsheets_print_solutions_by_section:w ##1-- \q_stop }
+ }
+ }
+
+\cs_new_protected:Npn \__exsheets_print_solutions_by_section:w #1-#2-#3 \q_stop
+ {
+ % wenn #3=-, dann range-Input
+ \tl_if_eq:nnTF {#3} { - }
+ {
+ \int_zero:N \l__exsheets_tmpa_int
+ \int_set_eq:NN \l__exsheets_tmpb_int \c_ten_thousand
+ \tl_if_blank:nF {#1} { \int_set:Nn \l__exsheets_tmpa_int {#1} }
+ \tl_if_blank:nF {#2} { \int_set:Nn \l__exsheets_tmpb_int {#2} }
+ \int_do_while:nn { \l__exsheets_tmpa_int <= \l__exsheets_tmpb_int }
+ {
+ \prop_map_inline:Nn \g_exsheets_question_identification_prop
+ {
+ \__exsheets_print_solutions_section:nnn
+ {##1} {##2} { \l__exsheets_tmpa_int }
+ }
+ \int_incr:N \l__exsheets_tmpa_int
+ }
+ }
+ {
+ \prop_map_inline:Nn \g_exsheets_question_identification_prop
+ { \__exsheets_print_solutions_section:nnn {##1} {##2} {#1} }
+ }
+ }
+
+\cs_new_protected:Npn \__exsheets_print_solutions_section:nnn #1#2#3
+ {
+ \__exsheets_read_number:w #2 \q_stop
+ \__exsheets_print_solution_if:nn {#1}
+ { \int_compare_p:n { \l__exsheets_counter_sec_int = #3 } }
+ }
+
+% print by chapter:
+\cs_new_protected:Npn \exsheets_print_solutions_chapter:n #1
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \prop_map_inline:Nn \g_exsheets_question_identification_prop
+ {
+ \__exsheets_print_solutions_chapter:nnn {##1} {##2}
+ { \arabic{chapter} }
+ }
+ }
+ {
+ \clist_map_inline:nn {#1}
+ { \__exsheets_print_solutions_by_chapter:w ##1-- \q_stop }
+ }
+ }
+
+\cs_new_protected:Npn \__exsheets_print_solutions_by_chapter:w #1-#2-#3 \q_stop
+ {
+ % wenn #3=-, dann range-Input
+ \tl_if_eq:nnTF {#3} { - }
+ {
+ \int_zero:N \l__exsheets_tmpa_int
+ \int_set_eq:NN \l__exsheets_tmpb_int \c_ten_thousand
+ \tl_if_blank:nF {#1} { \int_set:Nn \l__exsheets_tmpa_int {#1} }
+ \tl_if_blank:nF {#2} { \int_set:Nn \l__exsheets_tmpb_int {#2} }
+ \int_do_while:nn { \l__exsheets_tmpa_int <= \l__exsheets_tmpb_int }
+ {
+ \prop_map_inline:Nn \g_exsheets_question_identification_prop
+ {
+ \__exsheets_print_solutions_chapter:nnn
+ {##1}
+ {##2}
+ { \l__exsheets_tmpa_int }
+ }
+ \int_incr:N \l__exsheets_tmpa_int
+ }
+ }
+ {
+ \prop_map_inline:Nn \g_exsheets_question_identification_prop
+ { \__exsheets_print_solutions_chapter:nnn {##1} {##2} {#1} }
+ }
+ }
+
+\cs_new_protected:Npn \__exsheets_print_solutions_chapter:nnn #1#2#3
+ {
+ \__exsheets_read_number:w #2 \q_stop
+ \__exsheets_print_solution_if:nn {#1}
+ { \int_compare_p:n { \l__exsheets_counter_ch_int = #3 } }
+ }
+
+% print all:
+\cs_new_protected:Npn \exsheets_print_solutions_all:
+ {
+ \prop_map_function:NN \g_exsheets_question_identification_prop
+ \__exsheets_print_solutions_all:nn
+ % \prop_show:N \g_exsheets_question_identification_prop
+ }
+
+\cs_new:Npn \__exsheets_sectioning_hook:nn #1#2
+ {
+ \bool_if:nT {
+ !\int_compare_p:n
+ {
+ \use:c { l__exsheets_current_#1_int }
+ =
+ \use:c { l__exsheets_counter_#1_int }
+ }
+ &&
+ !\int_compare_p:n
+ { \use:c { l__exsheets_counter_#1_int } = 0 }
+ }
+ {#2}
+ }
+\cs_generate_variant:Nn \__exsheets_sectioning_hook:nn { nV }
+
+\cs_new_protected:Npn \__exsheets_print_solutions_all:nn #1#2
+ { \exsheets_print_solutions_if:nnn { \c_true_bool } {#1} {#2} }
+
+% #1: condition
+% #2: numeric question ID
+% #3: question number string (stored in \g_exsheets_question_identification_prop)
+% use function in a wrapper which in turn is fed to
+% \prop_map_function:NN \g_exsheets_question_identification_prop
+\cs_new_protected:Npn \exsheets_print_solutions_if:nnn #1#2#3
+ {
+ \prop_if_in:NnT \g__exsheets_solutions_names_prop {#2}
+ {
+ \int_set_eq:NN
+ \l__exsheets_current_sec_int
+ \l__exsheets_counter_sec_int
+ \int_set_eq:NN
+ \l__exsheets_current_ch_int
+ \l__exsheets_counter_ch_int
+ \__exsheets_read_number:w #3 \q_stop
+ \__exsheets_print_solution_if:nn {#2} {#1}
+ }
+ }
+\cs_generate_variant:Nn \exsheets_print_solutions_if:nnn {nnV}
+
+% print by ID:
+\seq_new:N \l__exsheets_solutions_byID_seq
+\cs_new_protected:Npn \exsheets_print_solutions_byID:n #1
+ {
+ \seq_set_split:Nnn \l__exsheets_solutions_byID_seq { , } {#1}
+ \seq_clear:N \l__exsheets_tmpa_seq
+ \seq_map_inline:Nn \l__exsheets_solutions_byID_seq
+ {
+ \prop_get:NnN \g__exsheets_questions_id_prop
+ {##1} \l__exsheets_tmpa_tl
+ \seq_put_right:NV \l__exsheets_tmpa_seq \l__exsheets_tmpa_tl
+ }
+ \bool_if:NT \l__exsheets_print_byID_sorted_bool
+ {
+ \seq_sort:Nn \l__exsheets_tmpa_seq
+ {
+ \int_compare:nNnTF {##1} > {##2}
+ { \sort_return_swapped: }
+ { \sort_return_same: }
+ }
+ }
+ \seq_map_inline:Nn \l__exsheets_tmpa_seq
+ {
+ \prop_get:NnNT \g_exsheets_question_identification_prop {##1}
+ \l__exsheets_tmpa_tl
+ {
+ \exsheets_print_solutions_if:nnV
+ { \c_true_bool }
+ {##1}
+ \l__exsheets_tmpa_tl
+ }
+ }
+ }
+
+\cs_new_protected:Npn \__exsheets_read_number:w #1-#2-#3 \q_stop
+ {
+ \int_zero:N \l__exsheets_counter_ch_int
+ \int_zero:N \l__exsheets_counter_sec_int
+ \int_zero:N \l_exsheets_counter_qu_int
+ \tl_if_in:nnF {#1} { @@@ }
+ {
+ \tl_if_blank:nF {#1}
+ { \int_set:Nn \l__exsheets_counter_ch_int {#1} }
+ }
+ \int_set:Nn \l__exsheets_counter_sec_int {#2}
+ \int_set:Nn \l_exsheets_counter_qu_int {#3}
+ }
+
+\cs_new_protected:Npn \exsheets_solutions_print_name:nnn #1#2#3
+ {
+ \tl_set_rescan:Nnn \l__exsheets_tmpa_tl
+ { \char_set_catcode_letter:N \@ } {#1}
+ \tl_if_in:nnTF {#1} { @@@ }
+ { \__exsheets_solutions_name:nnn { } {#2} {#3} }
+ { \__exsheets_solutions_name:nnn {#1} {#2} {#3} }
+ \tex_penalty:D \c_ten_thousand
+ }
+\cs_generate_variant:Nn \exsheets_solutions_print_name:nnn { V , VVV }
+
+\cs_new:Npn \__exsheets_surround_with:nnn #1#2#3 { #2#1#3 }
+\cs_generate_variant:Nn \__exsheets_surround_with:nnn { nVV }
+
+% think about the interface with \exsheetsprintsolution a bit more, especially
+% about the placement of the hooks!
+
+% #1: ID
+% #2: name
+% #3: body
+\cs_new_protected:Npn \__exsheets_print_solution:nnn #1#2#3
+ {
+ \group_begin:
+ \tl_set:Nn \CurrentQuestionID {#1}
+ \tl_set:Nx \l__exsheets_tmpa_tl { \exsheets_question_number:n {#1} }
+ \__exsheets_surround_with:nVV
+ {
+ \exp_args:Nnx
+ \exsheetsprintsolution
+ { \exsheets_solutions_print_name:Vnn \l__exsheets_tmpa_tl {#2} {#1} }
+ {
+ \exp_not:V \l__exsheets_solutions_pre_body_hook_tl
+ \exp_not:n {#3}
+ \exp_not:V \l__exsheets_solutions_post_body_hook_tl
+ }
+ }
+ \l__exsheets_solutions_pre_hook_tl
+ \l__exsheets_solutions_post_hook_tl
+ \exsheets_add_space:N \l__exsheets_solutions_skip_below_dim
+ \group_end:
+ }
+\cs_generate_variant:Nn \__exsheets_print_solution:nnn { VV , VVV }
+
+% a user command to be redefined as needed; must have two mandatory arguments!
+% #1: heading
+% #2: body
+\cs_new:Npn \exsheetsprintsolution #1#2 { #1#2 }
+
+\cs_new:Npn \PrintSolutionsTF
+ { \bool_if:NTF \l__exsheets_solutions_print_bool }
+\cs_new:Npn \PrintSolutionsT
+ { \bool_if:NT \l__exsheets_solutions_print_bool }
+\cs_new:Npn \PrintSolutionsF
+ { \bool_if:NF \l__exsheets_solutions_print_bool }
+
+\keys_define:nn { exsheets / solution }
+ {
+ headings .tl_set:N = \l__exsheets_solution_heading_instance_tl ,
+ print .choice: ,
+ print / true .code:n =
+ {
+ \bool_set_true:N \l__exsheets_solutions_print_bool
+ \bool_set_false:N \l__exsheets_solutions_print_section_bool
+ \bool_set_false:N \l__exsheets_solutions_print_chapter_bool
+ \bool_set_false:N \l__exsheets_solutions_print_all_bool
+ } ,
+ print / false .code:n =
+ {
+ \bool_set_false:N \l__exsheets_solutions_print_bool
+ } ,
+ print .default:n = true ,
+ name .tl_set:N = \l__exsheets_solutions_name_tl ,
+ sorted .bool_set:N = \l__exsheets_print_byID_sorted_bool ,
+ skip-below .dim_set:N = \l__exsheets_solutions_skip_below_dim ,
+ no-skip-below .bool_set:N = \l__exsheets_no_skip_after_bool ,
+ pre-body-hook .tl_set:N = \l__exsheets_solutions_pre_body_hook_tl ,
+ post-body-hook .tl_set:N = \l__exsheets_solutions_post_body_hook_tl ,
+ pre-hook .tl_set:N = \l__exsheets_solutions_pre_hook_tl ,
+ post-hook .tl_set:N = \l__exsheets_solutions_post_hook_tl
+ }
+
+% ----------------------------------------------------------------------------
+% create question/solution pairs
+\cs_new_protected:Npn \__exsheets_new_qu_sol_pair:nnnnnn #1#2#3#4#5#6
+ {
+ \NewDocumentEnvironment {#1} { O{}G{} }
+ { \keys_set:nn {exsheets} {#3} \__exsheets_question: {#2,##1} {##2} }
+ { \end__exsheets_question: }
+ \NewDocumentEnvironment {#4} { O{} }
+ { \keys_set:nn {exsheets} {#6} \__exsheets_solution: {#5,##1} }
+ { \end__exsheets_solution: }
+ }
+
+\cs_new_protected:Npn \__exsheets_renew_qu_sol_pair:nnnnnn #1#2#3#4#5#6
+ {
+ \RenewDocumentEnvironment {#1} { O{}G{} }
+ { \keys_set:nn {exsheets} {#3} \__exsheets_question: {#2,##1} {##2} }
+ { \end__exsheets_question: }
+ \RenewDocumentEnvironment {#4} { O{} }
+ { \keys_set:nn {exsheets} {#6} \__exsheets_solution: {#5,##1} }
+ { \end__exsheets_solution: }
+ }
+
+\NewDocumentCommand \NewQuSolPair { mO{}O{}mO{}O{} }
+ { \__exsheets_new_qu_sol_pair:nnnnnn {#1} {#2} {#3} {#4} {#5} {#6} }
+\@onlypreamble \NewQuSolPair
+
+\NewDocumentCommand \RenewQuSolPair { mO{}O{}mO{}O{} }
+ { \__exsheets_renew_qu_sol_pair:nnnnnn {#1} {#2} {#3} {#4} {#5} {#6} }
+\@onlypreamble \RenewQuSolPair
+
+% ----------------------------------------------------------------------------
+% the `tasks' list
+\RequirePackage {tasks} [2014/07/03]
+\AddCounterPattern* [tasks] {question} {qu}
+\ReadCounterFrom [tasks] {question} \l_exsheets_counter_qu_int
+
+% ----------------------------------------------------------------------------
+% the \blank{<words>} command
+\RequirePackage {ulem} \normalem
+
+\cs_new:Npn \exsheets_write_blank:n #1 {#1}
+\cs_set_eq:NN \exsheets_write_blank:n \uline
+
+\keys_define:nn { exsheets / blank }
+ {
+ style .choice: ,
+ style / line .code:n =
+ \cs_set_eq:NN \exsheets_write_blank:n \uline ,
+ style / wave .code:n =
+ \cs_set_eq:NN \exsheets_write_blank:n \uwave ,
+ style / dline .code:n =
+ \cs_set_eq:NN \exsheets_write_blank:n \uuline ,
+ style / dotted .code:n =
+ \cs_set_eq:NN \exsheets_write_blank:n \dotuline ,
+ style / dashed .code:n =
+ \cs_set_eq:NN \exsheets_write_blank:n \dashuline ,
+ scale .tl_set:N = \l__exsheets_blank_scale_tl ,
+ width .code:n =
+ {
+ \bool_set_true:N \l__exsheets_blank_width_bool
+ \dim_set:Nn \l__exsheets_blank_dim {#1}
+ } ,
+ linespread .code:n =
+ \bool_set_true:N \l__exsheets_blank_linespread_bool
+ \tl_set:Nn \l__exsheets_blank_linespread_tl {#1} ,
+ line-increment .dim_set:N =
+ \l__exsheets_blank_line_increment_dim ,
+ line-increment .initial:n = 1pt ,
+ line-minimum-length .dim_set:N =
+ \l__exsheets_blank_line_minimum_length_dim ,
+ line-minimum-length .initial:n = 2em
+ }
+
+\NewDocumentCommand \blank { som }
+ {
+ \group_begin:
+ \IfNoValueF {#2} { \keys_set:nn { exsheets / blank } {#2} }
+ \mode_if_vertical:TF
+ {
+ \IfBooleanF {#1} { \noindent }
+ \exsheets_blank:n {#3}
+ \IfBooleanF {#1}
+ {
+ \bool_if:NT \l__exsheets_blank_linespread_bool
+ { \linespread { \l__exsheets_blank_linespread_tl } \selectfont }
+ \par
+ }
+ }
+ { \exsheets_blank:n {#3} }
+ \group_end:
+ }
+
+\cs_new_protected:Npn \exsheets_blank:n #1
+ {
+ \box_clear:N \l__exsheets_blank_box
+ \mode_if_math:TF
+ { \hbox_set:Nn \l__exsheets_blank_box { $ \m@th \mathpalette{}{#1} $ } }
+ { \hbox_set:Nn \l__exsheets_blank_box {#1} }
+ \bool_if:NTF \l__exsheets_inside_solution_bool
+ { \exsheets_write_blank:n {#1} }
+ {
+ \bool_if:NTF \l__exsheets_blank_width_bool
+ { \__exsheets_blank_skip:N \l__exsheets_blank_dim }
+ {
+ \__exsheets_blank_skip:n
+ { \box_wd:N \l__exsheets_blank_box }
+ }
+ }
+ }
+
+\cs_new_protected:Npn \__exsheets_blank_skip:N #1
+ {
+ \bool_if:NTF \l__exsheets_blank_width_bool
+ { \dim_set:Nn \l__exsheets_tmpa_dim {#1} }
+ {
+ \fp_set:Nn \l__exsheets_tmpa_fp
+ { \dim_to_fp:n {#1} * \l__exsheets_blank_scale_tl }
+ \dim_set:Nn \l__exsheets_tmpa_dim { \fp_to_dim:N \l__exsheets_tmpa_fp }
+ }
+ \dim_compare:nTF
+ { \l__exsheets_tmpa_dim > \l__exsheets_blank_line_minimum_length_dim }
+ {
+ \mode_if_math:TF
+ { \exsheets_write_blank:n { \skip_horizontal:N \l__exsheets_tmpa_dim } }
+ {
+ \dim_do_while:nn { \l__exsheets_tmpa_dim > \c_zero_dim }
+ {
+ \tex_penalty:D \hyphenpenalty
+ \dim_compare:nTF
+ { \l__exsheets_tmpa_dim < \l__exsheets_blank_line_increment_dim }
+ { \exsheets_write_blank:n { \skip_horizontal:N \l__exsheets_tmpa_dim } }
+ {
+ \exsheets_write_blank:n
+ { \skip_horizontal:N \l__exsheets_blank_line_increment_dim }
+ }
+ \dim_sub:Nn \l__exsheets_tmpa_dim { \l__exsheets_blank_line_increment_dim }
+ }
+ }
+ }
+ { \exsheets_write_blank:n { \skip_horizontal:N \l__exsheets_tmpa_dim } }
+ }
+\cs_generate_variant:Nn \__exsheets_blank_skip:N { n }
+
+% the following code from Heiko Oberdieck in d.c.t.t served as inspiration
+% and basis for the \blank command:
+% https://groups.google.com/d/msg/de.comp.text.tex/fZLwraH04jE/o1RSdFXjGuIJ
+%
+% \makeatletter
+% \newcommand*{\luecke}{%
+% \begingroup
+% \setlength{\dimen@}{6cm}%
+% \ifdim\dimen@>2em %
+% \underline{\hspace{1em}}%
+% \advance\dimen@ by -2em\relax
+% \@whiledim\dimen@>0pt\do{%
+% \penalty\hyphenpenalty
+% \ifdim\dimen@<1pt %
+% \underline{\hspace{\dimen@}}%
+% \else
+% \underline{\hspace{1pt}}%
+% \fi
+% \advance\dimen@ by -1pt %
+% }%
+% \underline{\hspace{1em}}%
+% \else
+% \underline{\hspace{\dimen@}}%
+% \fi
+% \endgroup
+% \xspace
+% }
+% \makeatother
+
+% ----------------------------------------------------------------------------
+% \examspace
+% insert space for a student to answer a question
+\cs_new_protected:Npn \__exsheets_examspace:nn #1#2
+ {
+ \par
+ \tex_penalty:D -100 \scan_stop:
+ \dim_set:Nn \l__exsheets_tmpa_dim {#2}
+ \dim_set:Nn \l__exsheets_tmpb_dim { \pagegoal - \pagetotal - \baselineskip }
+ \dim_compare:nTF { \l__exsheets_tmpa_dim > \l__exsheets_tmpb_dim }
+ {
+ \dim_compare:nT { \l__exsheets_tmpb_dim > 0pt } { \vfil }
+ \break
+ \IfBooleanF {#1}
+ {
+ \dim_sub:Nn \l__exsheets_tmpa_dim { \l__exsheets_tmpb_dim }
+ \vspace* { \l__exsheets_tmpa_dim }
+ }
+ }
+ { \skip_vertical:N \l__exsheets_tmpa_dim }
+ }
+\NewDocumentCommand \examspace { sm }
+ { \__exsheets_examspace:nn {#1} {#2} }
+
+% ----------------------------------------------------------------------------
+% SETUP
+\NewDocumentCommand \SetupExSheets { o +m }
+ {
+ \IfNoValueTF {#1}
+ { \keys_set:nn {exsheets} {#2} }
+ { \keys_set:nn { exsheets / #1 } {#2} }
+ }
+
+% ----------------------------------------------------------------------------
+% default definitions:
+% question / solution pair:
+\NewQuSolPair {question} {solution}
+
+% properties:
+% \DeclareQuestionProperty{number}
+\DeclareQuestionProperty {counter}
+\DeclareQuestionProperty {subtitle}
+\DeclareQuestionProperty {question-body}
+\DeclareQuestionProperty {points}
+\DeclareQuestionProperty {bonus-points}
+\bool_if:NT \l__exsheets_auto_label_bool
+ {
+ \DeclareQuestionProperty {ref}
+ \DeclareQuestionProperty {pageref}
+ }
+
+% classes:
+\DeclareQuestionClass {class} {classes}
+\DeclareQuestionClass {topic} {topics}
+
+% ----------------------------------------------------------------------------
+% Sprachanpassungen
+\RequirePackage {translations}
+% translation for the exercises
+\DeclareTranslationFallback {exsheets-exercise-name} {Exercise}
+\DeclareTranslation {English} {exsheets-exercise-name} {Exercise}
+\DeclareTranslation {British} {exsheets-exercise-name} {Exercise}
+\DeclareTranslation {American} {exsheets-exercise-name} {Exercise}
+\DeclareTranslation {French} {exsheets-exercise-name} {Exercice}
+\DeclareTranslation {German} {exsheets-exercise-name} {\"Ubung}
+\DeclareTranslation {Italian} {exsheets-exercise-name} {Esercizio}
+\DeclareTranslation {Spanish} {exsheets-exercise-name} {Ejercicio}
+\DeclareTranslation {Catalan} {exsheets-exercise-name} {Exercici}
+\DeclareTranslation {Turkish} {exsheets-exercise-name} {Egzersiz}
+\DeclareTranslation {Croatian} {exsheets-exercise-name} {Primjer}
+\DeclareTranslation {Hungarian} {exsheets-exercise-name} {Gyakorol}
+\DeclareTranslation {Danish} {exsheets-exercise-name} {Opgave}
+\DeclareTranslation {Norsk} {exsheets-exercise-name} {Oppgave}
+\DeclareTranslation {Portuges} {exsheets-exercise-name} {Exerc\'\i cio}
+% translation for the question
+\DeclareTranslationFallback {exsheets-question-name} {Question}
+\DeclareTranslation {English} {exsheets-question-name} {Question}
+\DeclareTranslation {British} {exsheets-question-name} {Question}
+\DeclareTranslation {American} {exsheets-question-name} {Question}
+\DeclareTranslation {French} {exsheets-question-name} {Question}
+\DeclareTranslation {German} {exsheets-question-name} {Aufgabe}
+\DeclareTranslation {Italian} {exsheets-question-name} {Questione}
+\DeclareTranslation {Spanish} {exsheets-question-name} {Pregunta}
+\DeclareTranslation {Catalan} {exsheets-question-name} {Q\"uesti\'o}
+\DeclareTranslation {Turkish} {exsheets-question-name} {Soru}
+\DeclareTranslation {Croatian} {exsheets-question-name} {Zadatak}
+\DeclareTranslation {Hungarian} {exsheets-question-name} {Feladat}
+\DeclareTranslation {Danish} {exsheets-question-name} {Opgave}
+\DeclareTranslation {Norsk} {exsheets-question-name} {Oppgave}
+\DeclareTranslation {Portuges} {exsheets-question-name} {Quest\~ao}
+% translation for the solutions
+\DeclareTranslationFallback {exsheets-solution-name} {Solution}
+\DeclareTranslation {English} {exsheets-solution-name} {Solution}
+\DeclareTranslation {British} {exsheets-solution-name} {Solution}
+\DeclareTranslation {American} {exsheets-solution-name} {Solution}
+\DeclareTranslation {French} {exsheets-solution-name} {Solution}
+\DeclareTranslation {German} {exsheets-solution-name} {L\"osung}
+\DeclareTranslation {Italian} {exsheets-solution-name} {Soluzione}
+\DeclareTranslation {Spanish} {exsheets-solution-name} {Soluci\'on}
+\DeclareTranslation {Catalan} {exsheets-solution-name} {Soluci\'o}
+\DeclareTranslation {Turkish} {exsheets-solution-name} {\c C\"oz\"um}
+\DeclareTranslation {Croatian} {exsheets-solution-name} {Rje\v{s}enje}
+\DeclareTranslation {Hungarian} {exsheets-solution-name} {Megold\'{a}s}
+\DeclareTranslation {Danish} {exsheets-solution-name} {L\o sning}
+\DeclareTranslation {Norsk} {exsheets-solution-name} {L\o sning}
+\DeclareTranslation {Portuges} {exsheets-solution-name} {Solu\c c\~ao}
+% the actual translating
+\tl_set:Nn \l__exsheets_exercise_name_tl
+ { \GetTranslation {exsheets-exercise-name} }
+\tl_set:Nn \l__exsheets_questions_name_tl
+ { \GetTranslation {exsheets-question-name} }
+\tl_set:Nn \l__exsheets_solutions_name_tl
+ { \GetTranslation {exsheets-solution-name} }
+
+
+% ----------------------------------------------------------------------------
+% save total points in .aux file to make it available for \allpoints anywhere
+\AtEndDocument
+ {
+ \exsheets_write_to_aux_x:n
+ {
+ \exp_not:N \exsheets@sum@of@points
+ { \fp_eval:n { \g__exsheets_points_sum_fp } }^^J
+ \exp_not:N \exsheets@sum@of@bonus
+ { \fp_eval:n { \g__exsheets_bonus_sum_fp } }^^J
+ \exp_not:N \gdef \exp_not:N \numberofquestions
+ { \int_use:N \g__exsheets_questions_used_int }
+ % \exsheets@number@of@questions
+ % { \int_to_arabic:V \g__exsheets_questions_id_int }
+ }
+ }
+
+% ----------------------------------------------------------------------------
+% load custom configuration
+\file_if_exist:nT {exsheets_configurations.cfg}
+ {
+ \AtBeginDocument
+ {
+ \msg_info:nn {exsheets} {loading-configurations}
+ \file_input:n {exsheets_configurations.cfg}
+ }
+ }
+
+\tex_endinput:D
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+HISTORY:
+2011/11/23 v0.1pre - first upload to bitbucket and all changes until
+ considered stable enough/ready to be called
+ 0.1alpha. There'll be no further descriptions until
+ then.
+2012/06/08 v0.1alpha - first hopefully stable version
+2012/06/11 v0.1alpha-a - added headings instances, slightly rewritten
+ `exercises-tasks' object and `tasks' environment
+2012/06/11 v0.1alpha-b - added `multiplechoice' instance and `load-tasks'
+ option
+2012/06/12 v0.1alpha-c - renamed from `exercises' into `ExSheets'
+2012/06/15 v0.1alpha-d - added more flexible solution printing method
+2012/06/15 v0.1beta - filled in some blanks in the documentation, now we
+ need some testing!
+2012/09/07 v0.1beta-a - adjustments to the updated l3kernel
+2012/09/08 v0.1beta-b - sort solutions printed with the `byID' key
+2012/09/16 v0.1beta-c - renamed option `questions-counter-format' into
+ `counter-format'
+2012/09/19 v0.1beta-d - added `topic' key, provide \includequestions with
+ options `all' and `IDs'
+2012/09/24 v0.1beta-e - added question properties and improved random
+ question selection
+2012/09/27 v0.1 - added two headings instances, new option
+ `headings-format'
+ - small changes in the definition of the
+ `exsheets-headings' object
+ - preliminary version of totoc options. Unfortunatly
+ \exsheets@recover@number is not expandable => no
+ hyperref support
+2012/09/30 v0.2beta - version numbering gone crazy! this will now stay
+ 0.2beta until upload to CTAN (v0.2)
+ - integrated packages `translations' and `cntformats':
+ trnslt: provide expandable version of `translator's
+ \translate
+ cntfmts: outsourced previous counter formatting
+ commands; should now be usable in other packages,
+ too, and simplified definitions in `ExSheets'
+ - thanks to `translations' and `cntformats' the `totoc'
+ option now works with `hyperref'
+2012/10/05 v0.2 - removed \sumpoints and moved the functionality to
+ \totalpoints*
+ - changed meaning of \addpoints* and moved former
+ functionality to \points
+ - added bonus point functionality including \addbonus,
+ \bonus, \bonussum, \pointssum, \currentpointssum,
+ \currentbonussum
+ - added grades distribution
+2012/10/05 v0.2a - resolved bug in saving and recovering question number
+ using \exsheets@save@number and \QuestionNumber
+2012/10/08 v0.2b - improved the reference to chapter/solution numbers
+ in \printsolutions
+ - resolved bug in \printsolutions introduced in the
+ last update
+ - upload to CTAN
+
+2012/10/23 v0.3 - bugfix in \exref
+ - new: \NewQuSolPair, \RenewQuSolPair, \examspace
+2012/10/24 v0.3a - fix of headings when followed by a list
+ - changed syntax of {tasks} list to resemble the real
+ lists like enumerate
+2012/10/26 v0.3b - small fix to the {tasks} environment, \NewTasks,
+ \RenewTasks, resolve stupid bug:
+ \ckeckedchoicebox => \checkedchoicebox
+2012/11/08 v0.4 - compatibility with KOMA-Script's `parskip' option:
+ now no unwanted skip and no overfull hbox is produced
+ - env {task} now supports inner environments
+2012/12/02 v0.5 - added \CurrentQuestionID
+2012/12/06 v0.5a - bug fix: solutions had wrong numbers with
+ counter-format=se.qu and [print] option
+2012/12/18 v0.6 - variations, Hungarian translations, corrected
+ Catalanian translations
+2012/12/23 v0.6a - bug fix: labels and items of {tasks} weren't joined
+ at their baselines
+2013/01/06 v0.6b - bug fix: ID counting fixed in \includequestions
+2013/01/19 v0.7 - extracted `tasks' environment into standalone
+ package; this also lead to a slightly new syntax and
+ a few new options for it
+ - changed internals for random selection of questions:
+ uses `pgf' instead of `lcg' and seems to be more
+ reliable than before
+2013/01/21 v0.7a - added option `auto-label' and questions key `label',
+ also added question properties `ref' and `pageref'
+2013/02/17 v0.7b - bug fix: question selection by ID now works again
+2013/03/10 v0.8 - \prop_length => \exsheets_prop_count
+ - define unexpandable internal commands protected
+ - translations basic dictionaries for English, German,
+ French and Spanish
+ - new \includequestions option `exclude'
+ - new way of handling the `class' of questions:
+ instead of hard-coded `classes' and `topics'
+ individual groups like e.g. `difficulties' can be
+ chosen; `classes' and `topics' are still provided for
+ backwards compatibility; this introduces the new
+ command \DeclareQuestionClass
+ - minor changes to the debugging information layout
+ - bug fix in number saving mechanism
+ - \includequestions[random=<num>] now obeys class
+ as done with \SetupExSheets{use-topics={foo,bar}}
+ - new macro \questionsincludedlast
+2013/04/04 v0.8a - added Portuguese translations
+2013/04/07 v0.9 - protected internal commands where appropriate
+ - added possibility to set general options with
+ \NewQuSolPair and \RenewQuSolPair
+2013/04/08 v0.9a - added headings instance `empty'
+2013/04/18 v0.9b - fixed erroneous behaviour of \includequestions when
+ used more than once
+ - added hook \l__exsheets_heading_points_post_hook_tl
+2013/04/21 v0.9c - bug fix: \ForEachQuestion seems to work correctly
+ again
+2013/04/25 v0.9d - bug fix: \includequestions works correctly when used
+ multiple times together with ordinary instances of
+ the {question} environment
+ - bug fix: points/parse=false correctly disables
+ parsing points again
+ - bug fix: \addpoints didn't add to the question
+ property
+ - new option `points/format'
+ - \blank now works in math mode, it doesn't do
+ linebreaks there if `ulem' doesn't allow them (which
+ it doesn't)
+2013/05/01 v0.9e - corrected erroneous behaviour of \examspace
+2013/05/26 v0.9f - fixed incorrectly placed links when the `totoc'
+ option is enabled and questions/solutions are at the
+ top of a new page because there wasn't enough place
+ left at the page before
+2013/05/30 v0.9g - obey \if@filesw
+2013/06/28 v0.9h - cleaner internal use of
+ \exsheets_set_question_properties:n
+2013/07/17 v0.9i - made \g__exsheets_total_bonus_fp and
+ \g__exsheets_total_points_fp public
+ - removed `translations' from the bundle
+2013/10/11 v0.10 - require `translations' like any other package
+ - added `exsheets-listings' package
+ - added Norwegian translations
+ - changed horizontal spaces declared as `1ex' into
+ `.3333em' in the declarations of the headings
+ instances
+ - added subtitles
+2013/11/07 v0.10a - fix bug in loading headings of questions; when
+ included from an external file sometimes the wrong ID
+ has been passed to the headings
+2013/11/20 v0.11 - \GetQuestionClass{}
+ - \PrintQuestionClass(TF)
+2013/12/02 v0.12 - fix issue with \CurrentQuestionID
+ - new options `label-format', `label-cmd', `ref-cmd'
+ and `pageref-cmd' for `auto-label' options that
+ allow specification of labelling command and thus
+ compatibility with packages like `cleveref'
+ - write question properties to aux file so they can be
+ retrieved before the corresponding question is
+ printed
+ - make \GetQuestionProperty expandable
+ - new syntax feature in points argument: a leading
+ bang prevents the points from being added to the sum
+ of points
+ - added possibility for
+ https://bitbucket.org/cgnieder/exsheets/issue/15
+ - added \IfQuestionSubtitle(TF)
+ - added `subtitle' property
+ - dropped `color' option
+2013/12/08 v0.12a - changed details in the printing mechanism of the
+ points which seems to be more consistent
+ - fix bug introduced in the last update: subtitles work
+ again
+2013/12/27 v0.12b - ensure that points are not parsed if a leading bang
+ is inserted
+ - fix bug in parsing the points
+2014/05/11 v0.13 - new options:
+ * chapter-hook
+ * section-hook
+ These options provide hooks to add code in the list
+ of solutions (when printed with \printsolutions[all])
+ when solutions from a new section or chapter are
+ printed
+2014/05/11 v0.13a - bug fix: solutions get the counter-format that's
+ active when the corresponding `solution' environment
+ is placed in the source
+2014/06/27 v0.14 - new command: \ExSheetsHeading
+ - \__exsheets_use_heading:nnnnnn =>
+ \exsheets_use_heading:nnnnnn
+ - new options `question/pre-hook' and
+ `question/post-hook'
+ - new pre-defined property `question-body'
+ - new pre-defined property `bonus-points'
+ - new pre-defined property `counter'
+ - new option `question/save-to-aux'
+ - \ForEachQuestion, \numberofquestions and
+ \iflastquestion are now available before any
+ questions have been typeset
+2014/07/20 v0.15 - remove `tasks' from the bundle and into a package of
+ its own
+ - remove `cntformats' from the bundle and into a package of
+ its own
+ - drop options `load-headings' and `load-tasks'
+ - new command \IfQuestionPropertyTF
+2014/09/14 v0.16 - fix `subtitle-format' option
+ - allow that the format given in `headings-format' and
+ `subtitle-format' can end with a command needing an
+ argument
+ - add options `solution/pre-hook',
+ `solution/post-hook', `solution/pre-body-hook' and
+ `solution/post-body-hook' (this adds a possibility
+ for issue #21)
+ - add options `question/pre-body-hook' and
+ `question/post-body-hook'
+ - add internal interface for the printing of solutions
+ ( \__exsheets_print_solution:nnnn )
+ - fix issue #22
+ - fix issue #23
+ - use only one version number for the whole bundle
+2014/10/14 v0.17 - new option `use-saved-counter-format'
+2015/02/09 v0.18 - added correct Danish translations - thanks to Jonas
+ Nyrup
+ - introduce \exsheetsprintsolution, see
+ http://tex.stackexchange.com/q/227078/ for motivation
+ - change test in \exsheets_h_or_vspace:N to something
+ more reliable and meaningful
+ - new option `no-skip-below'
+2015/05/06 v0.18a - fix bug in points mechanism
+ - singular points name is now only used for exactly 1
+ point
+ - a few cosmetic changes to the points function
+ definitions
+2015/07/04 v0.19 - add http://tex.stackexchange.com/q/222814
+ - allow begin and end of pseudo-environments as hooks
+ to the question an solution environments
+2015/11/18 v0.20 - add tagging feature
+ - new: \DeclareExSheetsHeadingContainer
+2016/01/26 v0.21 - give error message when \includequestions tries to
+ load a file which can't be found (issue)
+ - \exsheets_print_solutions_if:nnn
+ - \l__exsheets_counter_qu_int =>
+ \l_exsheets_counter_qu_int
+ - \g__exsheets_question_number_prop =>
+ \g_exsheets_question_identification_prop
+ - make question properties accessable when question is
+ not printed
+2016/01/26 v0.21a - remove deprecated \prop_get:Nn (=> \prop_item:Nn)
+2016/02/01 v0.21b - fix annoying bug in \exsheets_print_solutions_if:nnn
+2016/03/21 v0.21c - use question property `counter' for retrieving the
+ counter patterns in solution's headings (this
+ resolves http://tex.stackexchange.com/q/299898)
+ - remove option `use-saved-counter-format': solutions
+ should always have the same number pattern as the
+ corresponding questions
+2016/08/14 v0.21d - fix issue #32
+2016/09/07 v0.21e - fix issue #29
+ - fix issue #35
+ - fix issue #36
+2016/09/17 v0.21f - make \exsheets_question_number:n an alias of
+ \exsheets_get_question_property:nn {counter}; this
+ also makes \QuestionNumber an alias of
+ \GetQuestionProperty {counter}
+2016/10/25 v0.21g - smaller steps when creating the blank lines
+2016/11/28 v0.21h - bug in \exsheets@used@id fixed
+2017/02/08 v0.21i - adapt to l3sort integration into l3kernel
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% TODO:
+- solve the problem using verbatim material in questions and solutions
+ (difficult)
+- allow for different kinds of problems/solutions using an independant counter
+ (not trivial)
+- points/decimal-marker, points/frac (?), points/format (?,im interface)
+- points: swedish style
+- \examspace inside {tasks} => possible? (\pagegoal-\pagetotal) gives wrong
+ values here
+- remove doubled points name if total points are unknown
diff --git a/macros/latex/contrib/exsheets/exsheets_configurations.cfg b/macros/latex/contrib/exsheets/exsheets_configurations.cfg
new file mode 100644
index 0000000000..e5f7eb0046
--- /dev/null
+++ b/macros/latex/contrib/exsheets/exsheets_configurations.cfg
@@ -0,0 +1,32 @@
+% ----------------------------------------------------------------------------
+% the EXSHEETS package
+%
+% Yet another package for the creation of exercise sheets
+%
+% ----------------------------------------------------------------------------
+% Clemens Niederberger
+% Web: http://www.mychemistry.eu/forums/forum/exsheets
+% E-Mail: contact@mychemistry.eu
+% ----------------------------------------------------------------------------
+% Copyright 2011-2017 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.
+% ----------------------------------------------------------------------------
+\ProvidesFile{exsheets_configurations.cfg}
+
+% Put your definitions and configurations here.
+
+\endinput
diff --git a/macros/latex/contrib/exsheets/exsheets_en.pdf b/macros/latex/contrib/exsheets/exsheets_en.pdf
new file mode 100644
index 0000000000..56e3247c0d
--- /dev/null
+++ b/macros/latex/contrib/exsheets/exsheets_en.pdf
Binary files differ
diff --git a/macros/latex/contrib/exsheets/exsheets_en.tex b/macros/latex/contrib/exsheets/exsheets_en.tex
new file mode 100644
index 0000000000..d79c5de063
--- /dev/null
+++ b/macros/latex/contrib/exsheets/exsheets_en.tex
@@ -0,0 +1,2650 @@
+% !arara: pdflatex
+% !arara: biber
+% arara: pdflatex
+% arara: pdflatex
+% arara: pdflatex
+% --------------------------------------------------------------------------
+% the EXSHEETS package
+%
+% Yet another package for the creation of exercise sheets
+%
+% --------------------------------------------------------------------------
+% Clemens Niederberger
+% Web: http://www.mychemistry.eu/forums/forum/exsheets/
+% E-Mail: contact@mychemistry.eu
+% --------------------------------------------------------------------------
+% Copyright 2011-2017 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.
+% --------------------------------------------------------------------------
+\documentclass[load-preamble+]{cnltx-doc}
+
+\usepackage{exsheets}
+\usepackage{bookmark}
+
+\setcnltx{
+ package = {exsheets} ,
+ authors = Clemens Niederberger ,
+ email = contact@mychemistry.eu ,
+ url = {http://www.mychemistry.eu/forums/forum/exsheets/} ,
+ title = the \ExSheets\ bundle ,
+ info = {%
+ the packages \ExSheets{} and \ExSheetslistings \\
+ \emph{or}\\
+ Yet another package for the creation of exercise sheets and exams.%
+ } ,
+ module-sep = {\,>>\,} ,
+ index-setup = { othercode=\footnotesize,level=\section} ,
+ abstract = {%
+ \ExSheets\ provides means to create exercises or questions and their
+ corresponding solutions. The questions can be divided into classes and
+ can be printed selectively. Meta-data to questions can be added and
+ recovered.
+ \par
+ The solutions may be printed where they are, can be collected and printed
+ at a later point in the document alltogether or section-wise or
+ selectively by \acs{id}.\par
+ \ExSheets\ provides a comprehensive interface for styling the headings of
+ questions and solutions.%
+ } ,
+ add-cmds = {
+ % exsheets:
+ addpoints,
+ blank,
+ C,
+ checkedchoicebox,choice,choicebox,
+ correct,
+ CurrentQuestionID,
+ DebugExSheets,
+ DeclareExSheetsHeadingContainer,
+ DeclareQuestionClass,DeclareQuestionProperty,
+ examspace,
+ exlabel,
+ ForEachQuestion,
+ GetQuestionClass,
+ GetQuestionProperty,
+ grade,
+ includequestions,iflastquestion,
+ IfQuestionPropertyF,IfQuestionPropertyT,IfQuestionPropertyTF,
+ IfQuestionSubtitleF,IfQuestionSubtitleT,IfQuestionSubtitleTF,
+ lastvariant,
+ NewQuSolPair,NewLstQuSolPair,
+ numberofquestions,
+ points,pointssum,
+ PrintIfIncludeActiveF,PrintIfIncludeActiveT,PrintIfIncludeActiveTF,
+ PrintQuestionClassF,PrintQuestionClassT,PrintQuestionClassTF,
+ printsolutions,
+ PrintSolutionsF,PrintSolutionsTF,PrintSolutionsT,
+ questionsincludedlast,QuestionNumber,RenewQuSolPair,
+ S,
+ SetQuestionProperties,
+ SetupExSheets,
+ SetVariations,
+ startnewitemline,
+ sumpoints,
+ totalpoints,
+ variant,vary,
+ % cntformats:
+ @cntfmts@parsed@pattern,
+ AddCounterPattern,
+ eSaveCounterPattern,
+ NewCounterPattern,
+ ReadCounterFrom,
+ ReadCounterPattern,ReadCounterPatternFrom,
+ SaveCounterPattern,
+ % tasks:
+ NewTasks,
+ settasks,
+ task
+ } ,
+ add-envs = {
+ question,
+ solution,
+ tasks
+ } ,
+ add-silent-cmds = {
+ acs,
+ bigstar,bottomrule,
+ citetitle,cs,color,
+ DeclareInstance,DeclareTemplateInterface,
+ endmdframed,endspacing,
+ keyis,
+ leftthumbsup,
+ mdframed,midrule,
+ rightarrow,rlap,
+ s,sample,setlength,
+ spacing,square,
+ tabcolsep,
+ textcite,
+ textcolor,
+ tmpa,tmpb,
+ toprule
+ }
+}
+\usepackage{exsheets-listings}
+
+\microtypesetup{tracking=scshape}
+
+\defbibheading{bibliography}[\bibname]{\section{#1}}
+
+\usepackage[biblatex]{embrac}[2012/06/29]
+ \ChangeEmph{[}[,.02em]{]}[.055em,-.08em]
+ \ChangeEmph{(}[-.01em,.04em]{)}[.04em,-.05em]
+\usepackage{booktabs,array,ragged2e}
+
+\newpackagename\ExSheets{ExSheets}
+\newpackagename\ExSheetslistings{ExSheets-listings}
+\newpackagename\cntformats{cntformats}
+\newpackagename\Tasks{tasks}
+
+% ----------------------------------------------------------------------------
+% other packages, bibliography, index
+\usepackage{xcoffins,wasysym,enumitem,siunitx}
+
+\usepackage[accsupp]{acro}
+\DeclareAcronym{faq}{
+ short = faq ,
+ long = Frequently Asked Questions ,
+ format = \scshape ,
+ pdfstring = FAQ ,
+ accsupp = FAQ
+}
+\DeclareAcronym{id}{
+ short = id ,
+ long = Identifier ,
+ format = \scshape ,
+ pdfstring = ID ,
+ accsupp = ID
+}
+\DeclareAcronym{ctan}{
+ short = ctan ,
+ long = Comprehensive \TeX\ Archive Network ,
+ format = \scshape ,
+ pdfstring = CTAN ,
+ accsupp = CTAN
+}
+
+\usepackage{filecontents}
+
+\usepackage{csquotes}
+
+\addbibresource{biblatex-examples.bib}
+\addbibresource{\jobname.bib}
+
+\begin{filecontents*}{\jobname.bib}
+@online{tex.sx:131546,
+ title = {Fixing lstlisting inside \ExSheets\ \code{question} and
+ \code{solution} environments} ,
+ author = {Stefano Bragaglia} ,
+ url = {http://tex.stackexchange.com/q/131546/5049} ,
+ date = {2013-09-04} ,
+ urldate = {2013-09-22}
+}
+@online{tex.sx:133907,
+ title = {How do I extract repeated functionality (\ExSheets\ workaround) to
+ make it reusable?} ,
+ author = {Forkrul Assail} ,
+ url = {http://tex.stackexchange.com/q/133907/5049} ,
+ date = {2013-09-18} ,
+ urldate = {2013-09-22}
+}
+\end{filecontents*}
+
+% ----------------------------------------------------------------------------
+% example definitions that have to be done in the preamble:
+\DeclareQuestionClass{difficulty}{difficulties}
+\DeclareQuestionProperty{notes}
+\DeclareQuestionProperty{reference}
+\DeclareQuestionProperty{topic}
+
+\DeclareRelGrades{
+ 1 = 1 ,
+ {1,5} = .9167 ,
+ 2 = .8333 ,
+ {2,5} = .75 ,
+ 3 = .6667 ,
+ {3,5} = .5833 ,
+ 4 = .5
+}
+
+\usepackage{amssymb}
+\let\checkmark\relax
+\usepackage{dingbat}
+
+\DeclareRobustCommand*\questionstar{\texorpdfstring{\bonusquestionsign}{* }}
+\DeclareRobustCommand*\bonusquestionsign{\llap{$\bigstar$\space}}
+
+\NewQuSolPair
+ {question*}[name=\questionstar Bonus Question]
+ {solution*}[name=\questionstar Solution]
+
+\NewTasks[style=multiplechoice]{multiplechoice}[\choice](3)
+\newcommand*\correct{\PrintSolutionsTF{\checkedchoicebox}{\choicebox}}
+
+\usepackage{alphalph}
+\NewPatternFormat{aa}{\alphalph}
+\NewCounterPattern{testa}{ta}
+
+% \AfterPackage!{hyperref}{%
+% \pdfstringdefDisableCommands{\def\questionstar{* }}%
+% }
+
+\begin{document}
+
+\part{Preliminaries}
+\section{Licence and Requirements}
+\license
+
+\ExSheets\ loads and needs the following packages:
+\needpackage{l3kernel}~\cite{bnd:l3kernel}, \pkg{xparse}, \pkg{xtemplate},
+\pkg{l3keys2e}\footnote{all three \CTANurl{l3packages}}~\cite{bnd:l3packages},
+\pkg{l3sort}\footnote{\CTANurl{l3experimental}}~\cite{bnd:l3experimental},
+\needpackage{xcolor}~\cite{pkg:xcolor}, \needpackage{ulem}~\cite{pkg:ulem},
+\needpackage{etoolbox}~\cite{pkg:etoolbox},
+\needpackage{environ}~\cite{pkg:environ}, and
+\pkg{pgfcore}\footnote{\CTANurl[graphics]{pgf}}~\cite{pkg:pgf}. \ExSheets\
+calls \cs*{normalem} (from the \pkg{ulem} package).
+
+\section{Motivation}
+There are already quite a number of packages that allow the creation of
+exercise sheets or written exams. Just to name the most common ones:
+\pkg{eqexam}~\cite{pkg:eqexam}, \pkg{exam}~\cite{cls:exam},
+\pkg{examdesign}~\cite{pkg:examdesign}, \pkg{exercise}~\cite{pkg:exercise},
+\pkg{probsoln}~\cite{pkg:probsoln}, \pkg{answers}~\cite{pkg:answers},
+\pkg{esami}~\cite{pkg:esami}, \pkg{exsol}~\cite{pkg:exsol} (and many
+more \ldots).
+
+One thing I missed in all packages that I've tried out\footnote{Well, probably
+ I didn't try hard enough\ldots} was a high flexibility in choosing which
+questions and solutions should be printed, where which solutions should be
+printed and so on, combined with the possibility to assign questions to
+different classes so one could for example create two versions of an exam out
+of the box. And --~I can't get enough~-- I also want to be able to use/design
+different layouts for questions additional to a standard section-like format.
+All these points are realized in \ExSheets.
+
+Additionally one should be able to assign some sort of meta-data to questions
+that of course should be easily reusable. How this can be done is explained
+in section~\ref{sec:additional_info}.
+
+Then there is --~at least in Germany~-- the habit of having lists of exercises
+aligned in columns but counting from the left to the right instead from up to
+down. That's why the \pkg{tasks} package was developed as part of \ExSheets{}
+and was distributed as part of the bundle\changedversion{0.15}. Now it is a
+package of its own but is loaded by \ExSheets{} automatically with the
+necessary setup to make them work together nicely.
+
+\ExSheets{} has no native support for multiple choice tests but that doesn't
+mean that you can't create them with \ExSheets. It just means that they may
+be a bit more work with \ExSheets{} than with other packages.
+
+I had the idea for this package in 2008. Back then my \TeX{} skills were by
+far not good enough to write it. Actually, even today I wouldn't have been
+able to realize it without all the l3 packages like \pkg{l3kernel} and
+\pkg{l3packages}. I actively began to develop \ExSheets\ in spring~2011 but
+it wasn't until now (September~2012) that I consider it stable enough for
+wider usage. At the time of writing (\today) there still are probably lots of
+rough edges let alone bugs so I am very interested in all kinds of feedback.
+
+\section{Additional Packages}
+\ExSheets\ actually bundles two packages: \ExSheets, \ExSheetslistings.
+\ExSheetslistings\ is an add-on to \ExSheets\ that offers some functionality
+to use \pkg{listings} with \ExSheets. It is presented in
+part~\ref{part:listings}.
+
+\ExSheets\ used to bundle the \pkg{translations} package,
+too\changedversion{0.9i}, but doesn't any more. You can find the
+\pkg{translations} package as a package of it's own on the \ac{ctan}. It also
+used to bundle the packages \pkg{tasks} and
+\pkg{cntformats}\changedversion{0.15}. They're available now as packages of
+their own as well.
+
+% \section{Installation and Documentation}
+% If you install \ExSheets\ manually beware to put the files
+% \begin{itemize}
+% \item[]\verb+exsheets_headings.def+
+% \item[]\verb+exsheets_headings.cfg+
+% \end{itemize}
+% in the same directory as the \code{exsheets.sty} file\footnote{That is, a
+% directory like \code{texmf-local/tex/latex/exsheets}, probably}.
+
+% As with every manual package installation you need to make sure to put the
+% files in a directory where \TeX\ can find them and afterwards update the
+% database.
+
+% \subsection{The \pkg*{tasks} Package}
+% The \pkg{tasks} package~\cite{pkg:tasks} used to be part of the \ExSheets\
+% bundle but is a package of its own now\changedversion{0.15} and released
+% independently. You can find it as every other package on \ctan\ and in a full
+% \TeX~Live or \hologo{MiKTeX} installation.
+
+% \subsection{The \pkg*{cntformats} Package}
+% The \pkg{cntformats} package~\cite{pkg:cntformats} used to be part of the
+% \ExSheets\ bundle but is a package of its own now\changedversion{0.15} and
+% released independently. You can find it as every other package on \ctan\ and
+% in a full \TeX~Live or \hologo{MiKTeX} installation.
+
+% \subsection{The \pkg*{translations} Package}
+% The \pkg{translations} package~\cite{pkg:translations} used to be part of the
+% \ExSheets\ bundle but is a package of its own now\changedversion{0.9i} and
+% released independently. You can find it as every other package on \ctan\ and
+% in a full \TeX~Live or \hologo{MiKTeX} installation.
+
+% \section{News}
+% \begin{description}
+% \item[Version 0.7]
+% With version~0.7 there has been a potentially breaking change: the
+% \code{tasks} environment previously provided by \ExSheets\ has been
+% extracted into a package of its own. This does not change any syntax
+% \emph{per se}. However, if you used custom settings then you'll probably run
+% into some problems. The options for the environment are no longer set with
+% \cs{SetupExSheets} but with \cs{settasks}. Also the object that is used for
+% the list template and its instances has been renamed from
+% \code{exsheets-tasks} into \code{tasks}.
+
+% What's probably even more of a breaking change is a syntax difference of the
+% \code{tasks} environment: the optional argument for the number of columns is
+% \emph{no longer set in braces but parentheses}. This is deliberate as it
+% reflects the optional nature of the argument better and is consistent with
+% the syntax of \cs{NewTasks}, too.
+
+% Additionally the labels of the list got an additional offset of \code{1ex}
+% from the items which will lead to slightly different output. In some cases
+% this might actually lead to the most annoying changes. In this case say
+% \cs{settasks}\Marg{label-offset=0pt} which should cure things again.
+
+% I am very sorry for any inconvenience! I am trying to keep such changes as
+% minimal and rare as possibly. However, it is not always avoidable when a
+% package is new and still a child. It will grow up eventually.
+
+% \ExSheets' other packages -- \href{tasks_en.pdf}{\Tasks} and
+% \href{cntformats_en.pdf}{\cntformats} -- have gotten their own documentation
+% which are essentially extracted from this very document you're reading now.
+% This manual contains links to the respective manuals.
+
+% \item[Version v0.9i]
+% The \pkg{translations} package~\cite{pkg:translations} is no longer part of
+% the \ExSheets\ bundle. From now on (July~17.\@ 2013) it is provided as a
+% package of its own.
+
+% \item[Version 0.10]
+% The \ExSheets\ family has got a new member: \ExSheetslistings. This package
+% proposes a solution for the problem of using verbatim material in \ExSheets'
+% \env{question} and \env{solution} environments. It is presented in
+% part~\ref{part:listings}.
+
+% Question now can get subtitles that are printed if the heading instance
+% supports it, see section~\ref{sec:subtitles-questions}.
+
+% \item[Version 0.11]
+% The commands \cs{GetQuestionClass} and \cs{PrintQuestionClassTF} have been
+% added. They're explained in section~\ref{sec:retr-class-value}.
+
+% \item[Version 0.12]
+% The \option{auto-label} is now more flexible to allow the use together with
+% packages \pkg{cleveref}.
+
+% Question properties can now be retrieved before the question is printed (by
+% writing the properties to the \code{aux} file).
+
+% \item[Version 0.13]
+% New options:
+% \begin{itemize}
+% \item \option{chapter-hook} allows to add code to the list of solutions
+% when the solutions of a new chapter are printed, see
+% section~\ref{sec:solutions-print-all}.
+% \item \option{section-hook} allows to add code to the list of solutions
+% when the solutions of a new section are printed, see
+% section~\ref{sec:solutions-print-all}.
+% \end{itemize}
+
+% \item[Version 0.14]
+% New options:
+% \begin{itemize}
+% \item New option \option{pre-hook} to the \env{question} environment that
+% allows to add code directly before the question body, see
+% section~\ref{sec:opti-ques-envir}.
+% \item New option \option{post-hook} to the \env{question} environment that
+% allows to add code directly after the question body, see
+% section~\ref{sec:opti-ques-envir}.
+% \item New command \cs{ExSheetsHeading}, see
+% section~\ref{sec:using-an-exsheets}.
+% \item New pre-defined question properties \code{question-body},
+% \code{bonus-points} and \code{counter}, see
+% section~\ref{sec:additional_info}.
+% \item New option \option{save-to-aux}, see
+% section~\ref{sec:additional_info}.
+% \end{itemize}
+
+% \item[Version 0.15]
+% \begin{itemize}
+% \item The packages \pkg{tasks} and \pkg{cntformats} have been removed from
+% the bundle and are now distributed as packages of their own.
+% \item The options \option*{load-headings} and \option*{load-tasks} have
+% been dropped. The optional functionality they provided is now provided
+% all the time.
+% \item New command \cs{IfQuestionPropertyTF}, see
+% section~\ref{sec:additional_info}.
+% \end{itemize}
+
+% \item[Version 0.16]
+% New options/changes:
+% \begin{itemize}
+% \item The option \option{pre-hook} to the \env{question} environment now
+% places its contents before the question heading, see
+% section~\ref{sec:opti-ques-envir}.
+% \item New option \option{pre-body-hook} to the \env{question} environment
+% which adds its contents before the question body, see
+% section~\ref{sec:opti-ques-envir}.
+% \item New option \option{post-body-hook} to the \env{question} environment
+% which adds its contents after the question body, see
+% section~\ref{sec:opti-ques-envir}.
+% \item New option \option{pre-hook} to the \env{solution} environment which
+% adds code before a solution, see section~\ref{sec:opti-soli-envir}.
+% \item New option \option{post-hook} to the \env{solution} environment which
+% adds code after a solution, see section~\ref{sec:opti-soli-envir}.
+% \item New option \option{pre-body-hook} to the \env{solution} environment
+% which adds its contents before the solution body, see
+% section~\ref{sec:opti-soli-envir}.
+% \item New option \option{post-body-hook} to the \env{solution} environment
+% which adds its contents after the solution body, see
+% section~\ref{sec:opti-soli-envir}.
+% \end{itemize}
+
+% \item[Version 0.17]
+% New option:
+% \begin{itemize}
+% \item The option \option{use-saved-counter-format} has been introduced. It
+% is described in section~\ref{sec:solutions} on
+% page~\pageref{option:use-saved-counter-format}.
+% \end{itemize}
+
+% \item[Version 0.18]
+% The package now provides the correct Danish translations, thanks to Jonas
+% Nyrup.
+
+% The macro \cs{exsheetsprintsolution} is introduced, see
+% page~\pageref{exsheetsprintsolution} for a little bit of an explanation.
+
+% The option \option{no-skip-below} is introduced which disables the insertion
+% of vertical space after the question and solution environments.
+
+% \item[Version 0.20]
+% New command \cs{DeclareExSheetsHeadingContainer}.
+
+% \item[Version 0.21] Changes:
+% \begin{itemize}
+% \item \cs{includequestions} issues an error if it can't find the file to
+% include.
+% \item question properties are now also accessable when the corresponding
+% question isn't printed.
+% \item The variables \verbcode+\l_exsheets_counter_qu_int+ and \\
+% \verbcode+\g_exsheets_question_identification_prop+ are now public.
+% \end{itemize}
+% \end{description}
+
+\section{Thanks}
+I need to thank the many users who gave me feedback so far! For one thing
+this shows me that \ExSheets\ is useful to people. It also led to many
+improvements like new features and countless bug fixes.
+
+\part{The \ExSheets\ package}\label{part:exsheets}
+\section{Setup}
+The \ExSheets\ package has three different types of options, kind of. The
+first type are the classic package options which are used when you load
+\ExSheets:
+\begin{sourcecode}
+ \usepackage[<options>]{exsheets}
+\end{sourcecode}
+All general options can be used this way and most of them are described in
+section~\ref{sec:options}. All of those options also can be set via the setup
+command:
+\begin{commands}
+ \command{SetupExSheets}[\oarg{module}\marg{options}]
+\end{commands}
+
+The second type are options that belong to a specific environment or command.
+These options are either used directly with the environment/command
+\begin{sourcecode}
+ \begin{env}[<options>]
+ ...
+ \end{env}
+\end{sourcecode}
+or can also be set with the setup command. In the first case they only act
+upon the environment or command where they're used. In the second case they
+are set for all following uses of the corresponding environment or command.
+
+The options of the second type all belong to \module*{modules}. Let's say you
+want to specify some options of the \env{question} environment. You can then
+say the following:
+\begin{sourcecode}
+ \SetupExSheets[question]{option1,option2=value2}
+ % or:
+ \SetupExSheets{question/option1,question/option2=value2}
+\end{sourcecode}
+The \module*{module} an option belongs to is written in the left margin next
+to the when the option is described.
+
+The third type aren't options at all, actually. However, thanks to the great
+\pkg{xtemplate} package you are able to define your own instances of some of
+the objects used by \ExSheets. This is explained in a little more detail in
+part~\ref{part:style} on page~\pageref{part:style}\,ff. This third type,
+however, brings in a possible instability: the \pkg{xtemplate} package is in
+an experimental and developing state. This means that the sytax of the
+package may and possibly will change sometime in the future. I cannot foresee
+what any consequences of that will be for \ExSheets.
+
+\section{General Options}\label{sec:options}
+The package \ExSheets\ has some options, namely the following ones:
+\begin{options}
+ %% counter-format
+ \keyval{counter-format}{counter-format}\Default{qu.}
+ Formatting of the counter of the questions. This option takes a special
+ kind of string that is described in section~\ref{ssec:counter}.
+ \keyval{counter-within}{counter}\Default
+ Resets the \code{question} counter with every step of \meta{counter}.
+ %% auto-label
+ \keybool{auto-label}\Default{false}
+ If set to \code{true} \ExSheets\ will automatically place a
+ \cs*{label}\Marg{qu:\meta{id}} for each question. See
+ section~\ref{sec:auto-label-opti} for ways to customize this. It will
+ also create the question properties \code{ref} and \code{pageref}, see
+ section~\ref{sec:additional_info} for more on this.
+ %% headings
+ \keyval{headings}{instance}\Default{block}
+ Choose the style of the questions' and solutions' headings. There are two
+ predefined styles: \code{block} and \code{runin}.
+ %% headings-format
+ \keyval{headings-format}{code}\Default{\cs*{normalsize}\cs*{bfseries}}
+ This code is placed immediately before the headings of the questions and
+ solutions.
+ \keyval{subtitle-format}{code}\Default{\cs*{normalsize}\cs*{itshape}}
+ This code is placed immediately before the subtitle of the questions and
+ solutions. It only has an effect with a title instance that uses the
+ subtitle coffin, see section~\ref{sec:exsheets-headings}.
+ % skip-below
+ \keyval{skip-below}{dim}\Default{.5\cs*{baselineskip}}
+ \sinceversion{0.18}Sets the vertical space that is inserted after the
+ question and solution environments.
+ % no-skip-below
+ \keybool{no-skip-below}\Default{false}
+ \sinceversion{0.18}Disables the insertion of vertical space after the
+ question and solution environments.
+ %% totoc
+ \keybool{totoc}\Default{false}
+ This option adds the questions and solutions with their names and numbers
+ to the table of contents.
+ %% questions-totoc
+ \keybool{questions-totoc}\Default{false}
+ This option adds the questions with their names and numbers to the table
+ of contents.
+ %% solutions-totoc
+ \keybool{solutions-totoc}\Default{false}
+ This option adds the solutions with their names and numbers to the table
+ of contents.
+ %% toc-level
+ \keyval{toc-level}{toc level}\Default{subsection}
+ This option sets the level in which questions and solutions should appear
+ in the table of contents.
+ %% questions-toc-level
+ \keyval{questions-toc-level}{toc level}\Default{subsection}
+ This option sets the level in which questions should appear in the table
+ of contents.
+ %% solutions-toc-level
+ \keyval{solutions-toc-level}{toc level}\Default{subsection}
+ This option sets the level in which solutions should appear in the table
+ of contents.
+ %% use-ref
+ \keybool{use-ref}\Default{false}
+ enable referencing to sections and chapters in a way that the references
+ can be used with \cs{printsolutions}, see
+ section~\ref{sssec:print_specific_section} for details.
+\end{options}
+The \code{toc} options are demonstrated with section~\ref{sec:solutions:list}
+and the solutions printed there being listed in the table of contents.
+
+
+\section{Create Questions/Exercises and their Solutions}
+Now, let's start with the most important part: the questions and (possibly)
+their respective solutions.
+\subsection{The \env*{question} Environment}\label{ssec:questions}
+Questions are written inside the \env{question} environment:
+\begin{environments}
+ \environment{question}[\oarg{options}\marg{points}]
+ The main environment: creates a new exercise/question. Both arguments are
+ optional!
+\end{environments}
+\begin{example}
+ \begin{question}
+ This is our very first very difficult to solve question!
+ \end{question}
+\end{example}
+As you can see a heading is automatically created and the question is
+numbered. You can of course change both the numbering and the naming, but
+more on that later.
+
+The \env{question} environment takes an optional argument \marg{points} that
+can be used to assign points to the question (as is common in written exams):
+\begin{example}
+ \begin{question}{3}
+ This is our first difficult question that is worth 3 points!
+ \end{question}
+\end{example}
+These points are saved internally (see section~\ref{sec:points} for reasons
+why) and are written to the right margin next to the question heading in the
+default setting.
+
+You can also assign bonus points by inserting \code{\meta{point}+\meta{bonus
+ points}} as argument.
+\begin{example}
+ \begin{question}{1+1}
+ This question is worth 1 point and 1 bonus point.
+ \end{question}
+ \begin{question}{+3}
+ This question is a bonus question. It is worth 3 bonus points.
+ \end{question}
+\end{example}
+
+The points are counted and added to the total sum of points, see
+section~\ref{sec:points} for details on this. \sinceversion{0.12}Should you
+want that the points of a specific question \emph{should not be added} to the
+total sum then precede it with a bang \code{!}:
+\begin{example}
+ \begin{question}{!3}
+ This question's points won't be added to the total sum.
+ \end{question}
+\end{example}
+Beware that this also prevents bonus points. The points simply will be
+written where the heading instance puts them.
+
+\sinceversion{0.3}One additional thing: you might want to define custom
+commands that should behave differently if they're inside or outside of the
+\env{question} environment. In this case you can use these commands:
+\begin{commands}
+ \expandable\command{IfInsideQuestionTF}[\marg{true code}\marg{false code}]
+ Check if inside of a question and either leave \meta{true code} or
+ \meta{false code} in the input stream.
+ \expandable\command{IfInsideQuestionT}[\marg{true code}]
+ Check if inside of a question and either leave \meta{true code} in the
+ input stream if true.
+ \expandable\command{IfInsideQuestionF}[\marg{false code}]
+ Check if inside of a question and either leave \meta{false code} in the
+ input stream if not.
+\end{commands}
+
+\subsection{Options to the \env*{question} Environment}\label{sec:opti-ques-envir}
+The \env{question} environment takes one or more of the following options:
+\begin{options}
+ \keychoice{type}{exam,exercise}\Module{question}\Default{exercise}
+ Determines the type of question and changes the default name of a question
+ from ``Exercise'' to ``Question''. These default names are language
+ dependent.\par
+ If you use \cs*{usepackage}\oarg{ngerman}\marg{babel}, for example, then
+ the names are ``Ãœbung'' and ``Aufgabe''.
+ \keyval{name}{name}\Module{question}\Default
+ Sets a custom name. All predefined names are discarded.
+ \keyval{subtitle}{subtitle}\Module{question}\Default
+ Adds a subtitle \meta{subtitle} for the question that is used by headings
+ instances that make use of the subtitle coffin, see
+ section~\ref{sec:exsheets-headings}.
+ \keyval{skip-below}{dim}\Module{question}\Default{.5\cs*{baselineskip}}
+ \sinceversion{0.18}Sets the vertical space that is inserted after the
+ question environment.
+ \keybool{no-skip-below}\Module{question}\Default{false}
+ \sinceversion{0.18}Disables the insertion of vertical space after the
+ question environment.
+ \keybool{print}\Module{question}\Default{true}
+ Prints or hides the question.
+ \keyval{ID}{id}\Module{question}\Default
+ Assigns a custom \acs{id} to the question. See section~\ref{ssec:ids} for
+ further information.
+ \keyval{label}{label}\Module{question}\Default
+ Places a \cs*{label}\marg{label} for the question. This will overwrite
+ any label that is placed by the \option{auto-label} option.
+ \keyval{class}{class}\Module{question}\Default
+ Assigns a class \meta{class} to the question. See
+ section~\ref{sec:classes} for further information.
+ \keyval{topic}{topic}\Module{question}\Default
+ Assigns a topic \meta{topic} to the question. See
+ section~\ref{sec:topics} for further information.
+ \keybool{use}\Module{question}\Default{true}
+ Discards the question. Or not.
+ \keyval{pre-hook}{code}\Module{question}\Default
+ \changedversion{0.16}Adds \meta{code} directly before the question title.
+ \keyval{post-hook}{code}\Module{question}\Default
+ \changedversion{0.16}Adds \meta{code} directly after the question.
+ \keyval{pre-body-hook}{code}\Module{question}\Default
+ \sinceversion{0.16}Adds \meta{code} directly before the question body.
+ \keyval{post-body-hook}{code}\Module{question}\Default
+ \sinceversion{0.16}Adds \meta{code} directly after the question body.
+\end{options}
+
+\begin{example}
+ \begin{question}[type=exam]
+ This question has the type \keyis{type}{exam}. The default name has changed
+ from ``Exercise'' to ``Question''.
+ \end{question}
+ \begin{question}[name=Fancy name]
+ This question has a custom name.
+ \end{question}
+ \begin{question}[print=false]
+ This question is not printed.
+ \end{question}
+\end{example}
+
+The difference between \option{print} and \option{use} lies behind the scenes:
+with \keyis{print}{false} the question is not printed, but it still gets an
+individual \ac{id}, is numbered, and a possible solution is saved. This is
+for example useful when you want to print a sample solution for an exam. With
+\keyis{use}{false} it is fully discarded which means it is not accessible
+through an \acs{id} and a possible solution will not be saved.
+
+\subsection{Subtitles to Questions}\label{sec:subtitles-questions}
+The \option{subtitle} option mentioned in section~\ref{sec:opti-ques-envir}
+can be used to add a subtitle to a question. However, unless you choose a
+suitable heading (see section~\ref{sec:exsheets-headings}) it won't be
+printed. Currently there is \emph{one} heading instance that uses the
+subtitles but it should be easy to create a custom heading using one of the
+existing ones as a starter example. When creating such a heading you may want
+to distinguish between the cases when a subtitle has been given and when no
+subtitle is present. This can be done with the following commands:
+\begin{commands}
+ \expandable\command{IfQuestionSubtitleTF}[\marg{true code}\marg{false code}]
+ Tests if the current question has a subtitle. Leaves either \meta{true
+ code} or \meta{false code} in the input stream.
+ \expandable\command{IfQuestionSubtitleT}[\marg{true code}]
+ Tests if the current question has a subtitle. Leaves \meta{true code} in
+ the input stream if it has.
+ \expandable\command{IfQuestionSubtitleF}[\marg{false code}]
+ Tests if the current question has a subtitle. Leaves \meta{false code} in
+ the input stream if it hasn't.
+\end{commands}
+
+A subtitle is also a property of a question in the sense of
+section~\ref{sec:additional_info}. That means if a subtitle is given it can
+be retrieved with \cs{GetQuestionProperty}.
+
+As an example you could define your own heading instance that prints the
+\acs{id} of a question and (if given) the subtitle:
+
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{QE}{default}{
+ join = {
+ title[r,B]number[l,B](.333em,0pt) ;
+ title[r,B]subtitle[l,B](1em,0pt)
+ } ,
+ attach = {
+ main[l,vc]title[l,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](\marginparsep,0pt)
+ } ,
+ subtitle-post-code = {ID: \CurrentQuestionID} ,
+ number-post-code = {\IfQuestionSubtitleF{ID: \CurrentQuestionID}}
+ }
+\end{sourcecode}
+
+Please see section~\ref{sec:exsheets-headings} for more details on heading
+instances.
+
+\subsection{The \env*{solution} Environment}
+If you want to save/print (more on the exact usage in
+section~\ref{sec:solutions}) a solution you have to use the \env{solution}
+environment \emph{after} the question it belongs to and \emph{before} the next
+question.
+\begin{environments}
+ \environment{solution}[\oarg{options}]
+ The main environment for adding solutions to exercises/questions.
+\end{environments}
+\begin{example}
+ \begin{question}[ID=first]\label{qu:question_with_solution}
+ This is our first question that gets a solution!
+ \end{question}
+ \begin{solution}
+ This is the solution to exercise~\ref{qu:question_with_solution}!
+ \end{solution}
+\end{example}
+You can see that in the default settings the solution is \emph{not} written to
+the document. It has been saved, though, for possible later usage. We will
+see the solution later!
+
+\subsection{Options to the \env*{solution} Environment}\label{sec:opti-soli-envir}
+The \env{solutions} environment also has options, namely these:
+\begin{options}
+ \keyval{name}{name}\Module{solution}\Default
+ Sets a custom name.
+ \keybool{print}\Module{solution}\Default{false}
+ Prints or hides the solution.
+ \keyval{skip-below}{dim}\Module{solution}\Default{.5\cs*{baselineskip}}
+ \sinceversion{0.18}Sets the vertical space that is inserted after the
+ solution environment.
+ \keybool{no-skip-below}\Module{solution}\Default{false}
+ \sinceversion{0.18}Disables the insertion of vertical space after the
+ solution environment.
+ \keyval{pre-hook}{code}\Module{solution}\Default
+ \sinceversion{0.16}Adds \meta{code} directly before the solution title.
+ \keyval{post-hook}{code}\Module{solution}\Default
+ \sinceversion{0.16}Adds \meta{code} directly after the solution.
+ \keyval{pre-body-hook}{code}\Module{solution}\Default
+ \sinceversion{0.16}Adds \meta{code} directly before the solution body.
+ \keyval{post-body-hook}{code}\Module{solution}\Default
+ \sinceversion{0.16}Adds \meta{code} directly after the solution body.
+\end{options}
+Their meaning is the same as those for the \code{question} environment.
+\begin{example}
+ \begin{question}{5}
+ The solution to this questions gets printed where it is.
+ \end{question}
+ \begin{solution}[print]
+ See? This solution gets printed where you have put it in the code of
+ your document.
+ \end{solution}
+ \begin{question}{2.5}
+ The solution to this questions gets printed where it is \emph{and}
+ has a fancy name. Have you noticed that you can assign partial
+ points?
+ \end{question}
+ \begin{solution}[print,name=Fancy name]
+ See? This solution gets printed where you have put it and has a fancy
+ name!
+ \end{solution}
+\end{example}
+
+\subsection{Setting the Counter}\label{ssec:counter}
+The package option \option{counter-format} allows you to specify how the question
+counter (a counter unsurprisingly name \code{question}) is formatted.
+
+The input is an arbitrary string which means you can have anything as counter
+number. However, the letter combinations \code{ch}, \code{se}, \code{qu} and
+\code{tsk} are replaced with the counters for the chapter, section, question
+or tasks (see the \Tasks\ package), respectively. While the last one is not
+really useful in this case the others allow for a combined numbering. Each of
+these letter combinations can have an optional argument that specifies the
+format of the respective counter. \code{1}: \cs*{arabic}, \code{a}:
+\cs*{alph}, \code{A}: \cs*{Alph}, \code{r}: \cs*{roman} and \code{R}:
+\cs*{Roman}.
+\begin{example}
+ \SetupExSheets{counter-format=Nr~se~(qu[a])}
+ \begin{question}
+ A question with a differently formatted number.
+ \end{question}
+\end{example}
+Since the strings associated with the counters are replaced one has to hide
+them if they are actually wanted in the counter format. The easiest way would
+to hide them in braces.
+\begin{example}
+ \SetupExSheets{counter-format={section}\,se~{question}\,(qu[a])}
+ \begin{question}
+ A question with a yet differently formatted number.
+ \end{question}
+\end{example}
+
+\subsection{Language Settings}
+The names of the questions and solutions are language dependent. If you use
+\pkg{babel} or \pkg{polyglossia} \ExSheets\ will adapt to the document language.
+\ExSheets\ has a number of translations but surely not all! If you miss a
+language please drop me a line in an
+email\footnote{\href{mailto:contact@mychemistry.eu}{contact@mychemistry.eu}}
+containing the \pkg{babel} language name and the correct translations for
+questions (possibly distinguishing between exercises and exam questions) and
+solutions.
+
+Until I implement it you can add something like this to your preamble (example
+for Danish) and try if it works:
+\begin{sourcecode}
+ \DeclareTranslation{Danish}{exsheets-exercise-name}{\O{}velse}
+ \DeclareTranslation{Danish}{exsheets-question-name}{Opgave}
+ \DeclareTranslation{Danish}{exsheets-solution-name}{Opl\o{}sning}
+\end{sourcecode}
+If this isn't working it means that the language you're using is unknown to
+the \pkg{translations} package. In this case please notify me, too. You then
+can still use the \option{name} options.
+
+\section{Counting Points}\label{sec:points}
+\subsection{The Commands}
+You have seen in section~\ref{ssec:questions} that you can assign points to a
+question. If you do so these points are printed into the
+margin\footnote{Well, not necessarily. It depends on the heading style you
+ have chosen.} and are counted internally. But there are additional commands
+to assign points or bonus points and a number of commands to retrieve the sum
+of points and/or bonus points.
+\begin{commands}
+ \command{addpoints}[\sarg\marg{num}]
+ This command can be used to add points assigned to subquestions.
+ \cs{addpoints} will print the points (with ``unit'') \emph{and} add them
+ to the sum of all points, \cs{addpoints}\sarg\ will only add them but print
+ nothing.
+ \command{points}[\sarg\marg{num}]
+ This command will only print the points (with ``unit'') but won't add them
+ to the sum of points.
+ \command{addbonus}[\sarg\marg{num}]
+ This command can be used to add bonus points assigned to subquestions.
+ \cs{addbonus} will print the points (with ``unit'') \emph{and} add them
+ to the sum of all bonus points, \cs{addbonus}\sarg\ will only add them but
+ print nothing.
+ \command{bonus}[\sarg\marg{num}]
+ This command will only print the bonus points (with ``unit'') but won't
+ add them to the sum of bonus points.
+ \command{pointssum}[\sarg]
+ Prints the sum of all points with or without (starred version) ``unit'':
+ \pointssum
+ \command{currentpointssum}[\sarg]
+ Prints the current sum of points with or without (starred version)
+ ``unit'': \currentpointssum
+ \command{bonussum}[\sarg]
+ Prints the sum of all bonus points with or without (starred version)
+ ``unit'': \bonussum
+ \command{currentbonussum}[\sarg]
+ Prints the current sum of bonus points with or without (starred version)
+ ``unit'': \currentbonussum
+ \command{totalpoints}[\sarg]
+ prints the sum of the points \emph{and} the sum of the bonus points with
+ ``unit'': \totalpoints\space The starred version prints the sum of the
+ points without ``unit'': \totalpoints*.
+\end{commands}
+The commands \cs{pointssum}, \cs{bonussum} and \cs{totalpoints} need at
+least \emph{two} \LaTeX\ runs to get the sum right.
+
+Suppose you have an exercise worth \points{4} which consists of four questions
+listed with an \env{enumerate} environment that are all worth \points{1}
+each. You have two possibilities to display and count them:
+\begin{example}
+ % uses package `enumitem'
+ \begin{question}{4}
+ \begin{enumerate}[label=\alph*)]
+ \item blah (\points{1})
+ \item blah (\points{1})
+ \item blah (\points{1})
+ \item blah (\points{1})
+ \end{enumerate}
+ \end{question}
+ \begin{question}
+ \begin{enumerate}[label=\alph*)]
+ \item blah (\addpoints{1})
+ \item blah (\addpoints{1})
+ \item blah (\addpoints{1})
+ \item blah (\addpoints{1})
+ \end{enumerate}
+ \end{question}
+\end{example}
+
+\subsection{Options}
+\begin{options}
+ \keyval{name}{name}\Module{points}\Default{P.}
+ Choose the ``unit'' for the points. If you like to differentiate between
+ a single point and more than one point you can give a plural ending
+ separated with a slash: \keyis{name}{point/s}. This sets also the name of
+ the bonus points.
+ \keyval{name-plural}{plural form of name}\Module{points}\Default
+ Instead of forming the plural form with an ending to the singular form
+ this option allows to set an extra word for it. This sets also the plural
+ form for the bonus points.
+ \keyval{bonus-name}{name}\Module{points}\Default{P.}
+ Choose the ``unit'' for the bonus points. If you like to differentiate
+ between a single point and more than one point you can give a plural
+ ending separated with a slash: \key{bonus-name}{point/s}.
+ \keyval{bonus-plural}{plural form of name}\Module{points}\Default
+ Instead of forming the plural form with an ending to the singular form
+ this option allows to set an extra word for it.
+ \keybool{use-name}\Module{points}\Default{true}
+ Don't display the name at all. Or do.
+ \keyval{format}{code}\Module{points}\Default{\cs*{@firtsofone}}
+ \sinceversion{0.9d}Format number plus name as a whole. Ideally
+ \meta{code} would end with a command that takes an argument. Else
+ number plus name will be braced.
+ \keyval{number-format}{any code}\Module{points}\Default
+ This option allows formatting of the number, \eg, italics:
+ \keyis{number-format}{\cs*{textit}}.
+ \keyval{bonus-format}{any code}\Module{points}\Default
+ This option allows formatting of the number of the bonus points, \eg,
+ italics: \keyis{bonus-format}{\cs*{textit}}.
+ \keybool{parse}\Module{points}\Default{true}
+ If set to \code{false} the points are not counted and the
+ \cs{totalpoints}, \cs{pointssum} and \cs{bonussum} commands won't know
+ their value.
+ \keybool{separate-bonus}\Module{points}\Default{false}
+ This option determines whether points and bonus points each get their own
+ unit when they appear together (in the margin or with \cs{totalpoints}).
+ \keyval{pre-bonus}{tokens}\Module{points}\Default{\cs*{space}(+}
+ Code to be inserted before the bonus points when they follow normal
+ points.
+ \keyval{post-bonus}{tokens}\Module{points}\Default{)}
+ Code to be inserted after the bonus points when they follow normal
+ points.
+\end{options}
+
+\begin{example}[add-sourcecode-options={literate=}]
+ \SetupExSheets[points]{name=point/s,number-format=\color{red}}
+ \begin{question}{1}
+ This one's easy so only 1 point can be earned.
+ \end{question}
+ \begin{question}{7.5}
+ But this one's hard! 7.5 points are in there for you!
+ \end{question}
+\end{example}
+
+\section{Printing Solutions}\label{sec:solutions}
+You have already seen that you can print solutions where they are using the
+\option{print} option. But \ExSheets\ offers you quite more
+possibilities.
+
+In the next subsections the usage of the following command is discussed.
+\begin{commands}
+ \command{printsolutions}[\oarg{setting}]
+ Print solutions of questions/exercises.
+\end{commands}
+
+Before we do that a hint: remember that you can set the option \option{print}
+globally:
+\begin{sourcecode}
+ % in the preamble
+ \SetupExSheets{solution/print=true}
+\end{sourcecode}
+
+Now if you want to typeset some text depending on the option being true or not
+you can use the following commands:
+\begin{commands}
+ \expandable\command{PrintSolutionsTF}[\marg{true code}\marg{false code}]
+ Either leaves \meta{true code} or \meta{false code} in the input stream
+ depending on wether solutions are printed or not, \ie, on the value of the
+ solution's option \option{print}. Inside a \env{solution} environment
+ this always prints \meta{true code}.
+ \expandable\command{PrintSolutionsT}[\marg{true code}]
+ Either leaves \meta{true code} or nothing in the input stream depending on
+ wether solutions are printed or not, \ie, on the value of the solution's
+ option \option{print}. Inside a \env{solution} environment this always
+ prints \meta{true code}.
+ \expandable\command{PrintSolutionsF}[\marg{false code}]
+ Either leaves nothing or \meta{false code} in the input stream depending
+ on wether solutions are printed or not, \ie, on the value of the
+ solution's option \option{print}. Inside a \env{solution}environment this
+ always prints nothing.
+\end{commands}
+They might come in handy if you want two versions of an exercise sheet, one
+with the exercises and one with the solutions, and you want to add different
+titles to these versions, for instance.
+
+% When solutions are saved a lot of information is saved. One of them is the
+% current counter format. The following option determines wether the saved
+% counter format or the currently active one is used when \cs{printsolutions} is
+% called:
+% \begin{options}
+% \keybool{use-saved-counter-format}\Default{true}
+% \changedversion{0.21}When set to true the counter format of solutions
+% printed by \cs{printsolutions}\label{option:use-saved-counter-format} are
+% independent from the setting of \option{counter-format}. The saved format
+% is used instead.
+% \end{options}
+
+\subsection{Print all}\label{sec:solutions-print-all}
+The first and easiest usage of \cs{printsolutions} is the following:
+\begin{sourcecode}
+ \printsolutions
+\end{sourcecode}
+There is nothing more to say, really. It prints all solutions you have
+specified except those belonging to a question with option \keyis{use}{false}.
+Yes, there's one more point: \cs{printsolutions} only knows the solutions
+that have been set \emph{before} its usage! This is also true for every usage
+explained in the next sections.
+
+\begin{example}
+ \printsolutions
+\end{example}
+
+Two options allow to add code to the list of solutions when used with
+\cs{printsolutions}\Oarg{all} (which is the same as using it without option):
+
+\begin{options}
+ \keyval{chapter-hook}{code}
+ \sinceversion{0.13}Adds \meta{code} to the list of solutions every time
+ solutions from a new chapter are printed (before the solutions of the
+ corresponding chapter are printed).
+ \keyval{section-hook}{code}
+ \sinceversion{0.13}Adds \meta{code} to the list of solutions every time
+ solutions from a new section are printed (before the solutions of the
+ corresponding section are printed).
+\end{options}
+
+\subsection{Print per chapter/section}
+\minisec{Current chapter/section}
+If you are not creating an exercise sheet or an exam but are writing a
+textbook you maybe want a section at the end of each chapter showing the
+solution to the exercises presented in that chapter. In this case use the
+command as follows:
+\begin{sourcecode}
+ \printsolutions[section]
+ % or
+ \printsolutions[chapter]
+\end{sourcecode}
+Again, this is pretty much self-explaining. The solutions to the questions of
+the current chapter\footnote{Only if the document class you're using
+ \emph{has} chapters, of course!} or section are printed.
+\begin{example}
+ \begin{question}
+ This is the first and only question in this section.
+ \end{question}
+ \begin{solution}
+ This will be one of a few solutions printed by the following call of
+ \cs{printsolutions}.
+ \end{solution}
+ And now:
+ \printsolutions[section]
+\end{example}
+
+\minisec{Specific chapter/section}\label{sssec:print_specific_section}
+You can also print only the solutions from chapters or sections other than the
+current ones. The syntax is fairly easy:
+\begin{example}
+ \printsolutions[section={1-7,10}]
+ % the same for chapters:
+ % \printsolutions[chapter={1-7,10}]
+\end{example}
+Don't forget that \cs{printsolutions} cannot know the solutions from
+section~10 yet. It is just used to demonstrate the syntax. You can also use
+an open range, \eg, something like
+\begin{sourcecode}
+ \printsolutions[section={-4,10-}]
+\end{sourcecode}
+This would print the solutions from sections~1--4 and from all sections with
+number 10\footnote{Or rather where \cs*{value}\Marg{section} is 10 or greater --
+ the actual counter formatting is irrelevant.} and greater.
+
+There is an obvious disadvantage: you have to know the section numbers! But
+there is a solution: use the package option \keyis{use-ref}{true}. Then you
+can do something like
+\begin{sourcecode}
+ % in the preamble:
+ \usepackage[use-ref]{exsheets}
+ % somewhere in your code after \section{A really cool section title}:
+ \label{sec:ReallyCool}
+ % somewhere later in your code:
+ \printsolutions[section={-\S{sec:ReallyCool}}]
+ % which will print all solutions from questions up to and
+ % including the really cool section
+\end{sourcecode}
+With the package option \keyis{use-ref}{true} each usage of \cs*{label} will
+create additional labels (one preceded with \code{exse:} and another one with
+\code{exch:}) which store the section number and the chapter number,
+respectively. These are used internally by two commands \cs{S} and \cs{C}
+which refer to the section number and the chapter number the label was created
+in. \emph{These commands are only available as arguments of}
+\cs{printsolutions}.
+
+Since some packages like the well known \pkg{hyperref} for example redefine
+\cs*{label} \option{use-ref} won't work in together with it. In this case
+don't use \option{use-ref} and set \cs{exlabel}\marg{label} instead to
+remember the section/the chapter number. Its usage is just like \cs*{label}.
+So the safest way is as follows:
+\begin{sourcecode}
+ % in the preamble:
+ \usepackage{exsheets}
+ % somewhere in your code after \section{A really cool section title}:
+ \exlabel{sec:ReallyCool}
+ % somewhere later in your code:
+ \printsolutions[section={-\S{sec:ReallyCool}}]
+ % which will print all solutions from questions up to and
+ % including the really cool section
+\end{sourcecode}
+Please be aware that the labels must be processed in a previous \LaTeX\ run
+before \cs{S} and \cs{C} can pass them on to \cs{printsolutions}.
+
+\subsection{Print by \acs{id}}\label{ssec:ids}
+Now comes the best part: you can also print selected solutions! Every
+question has an \acs{id}. To see which \acs{id} a question has you can call
+the following command:
+\begin{commands}
+ % \command{DebugExSheets}[\Marg{\choices{true,false}}]
+ % Enable or disable visual \ExSheets' debugging.
+ \expandable\command{CurrentQuestionID}
+ \sinceversion{0.4a}Expands to the current question \acs{id}.
+\end{commands}
+\begin{options}
+ \keybool{debug}
+ Enable or disable visual \ExSheets' debugging.
+\end{options}
+Let's create some more questions and take a look what this command does:
+\begin{example}
+ \SetupExSheets{debug=true}
+ \begin{question}[ID=nice!]
+ A question with a nice \acs{id}!
+ \end{question}
+ \begin{solution}
+ The solution to the question with the nice \acs{id}.
+ \end{solution}
+ \begin{question}{3.75}
+ Yet another question. But this time with quarter points!
+ \end{question}
+ \begin{solution}
+ Yet another solution.
+ \end{solution}
+\end{example}
+
+So now we can call some specific solutions:
+\begin{example}
+ \printsolutions[byID={first,nice!,10,14}]
+\end{example}
+This makes use of the \pkg{l3sort} package which at the time of writing is
+still considered experimental. In case you wonder where solution~14 is:
+question~14 has no solution given.
+
+If you don't want that the solutions are sorted automatically but appear in
+the order given you can use the option
+\begin{options}
+ \keybool{sorted}\Module{solution}\Default{true}
+ Sort solutions given by \acs{id} or don't.
+\end{options}
+
+\section{Conditional Printing of Questions}\label{sec:cond-print-quest}
+\subsection{Using Classes}\label{sec:classes}
+For creating different variants of a written exam or different difficulty
+levels of an exercise sheet it comes in handy if one can assign certain
+classes to questions and then tell \ExSheets\ only to use one ore more
+specific classes.
+\begin{options}
+ \keyval{use-classes}{list of classes}\Default
+ When this option is used only the questions belonging to the specified
+ classes are printed and have their solutions saved.
+\end{options}
+\begin{example}
+ \SetupExSheets{use-classes={A,C}}
+ \begin{question}[class=A]
+ Belonging to class A.
+ \end{question}
+ \begin{question}[class=B]
+ Belonging to class B.
+ \end{question}
+ \begin{question}[class=C]
+ Belonging to class C!
+ \end{question}
+\end{example}
+Questions of classes that are not used are fully discarded. \emph{This also
+ means that questions that don't have a class assigned are discarded.}
+
+\ExplSyntaxOn
+ \bool_set_false:N \g__exsheets_use_classes_bool
+\ExplSyntaxOff
+
+\subsection{Using Topics}\label{sec:topics}
+Similarly to classes one can assign topics to questions. The usage is
+practically identical, the semantic meaning is different.
+\begin{options}
+ \keyval{use-topics}{list of topics}\Default
+ When this option is used only the questions belonging to the specified
+ topics are printed and have their solutions saved.
+\end{options}
+\begin{example}
+ \SetupExSheets{use-topics={trigonometry}}
+ \begin{question}[topic=trigonometry]
+ A trigonometry question.
+ \end{question}
+ \begin{question}[topic=arithmetics]
+ A arithmetics question
+ \end{question}
+\end{example}
+Questions of topics that are not used are fully discarded. \emph{This also
+ means that questions that don't have a topic assigned are discarded.}
+
+If you set both \option{use-classes} and \option{use-topics} then only
+questions will be used that \emph{match both categories}.
+
+Ideally one could assign more than one topic to a question but this is
+\emph{not} supported yet.
+
+\ExplSyntaxOn
+ \bool_set_false:N \g__exsheets_use_topics_bool
+\ExplSyntaxOff
+
+\subsection{Own Dividing Concepts}
+Actually\sinceversion{0.8} both classes and topics are introduced into
+\ExSheets\ internally this way:
+\begin{sourcecode}
+ \DeclareQuestionClass{class}{classes}
+ \DeclareQuestionClass{topic}{topics}
+\end{sourcecode}
+which means you can do the same introducing your own dividing concepts.
+\begin{commands}
+ \command{DeclareQuestionClass}[\marg{singular name}\marg{plural name}]
+ Introduces a new dividing concept and defines both new options for the
+ \env{question} environment and new global options.
+\end{commands}
+
+For example you could decide you want to group your questions according to
+their difficulty. You could place the following line in your preamble:
+\begin{sourcecode}
+ \DeclareQuestionClass{difficulty}{difficulties}
+\end{sourcecode}
+This would define an option \option*{use-difficulties} analogous to
+\option{use-classes} and \option{use-topics}. It would also define an option
+\option{difficulty} for the \env{question} environment. This means you could
+now do something like the following:
+\begin{example}
+ \SetupExSheets{use-difficulties={easy,hard}}
+ \begin{question}[difficulty=easy]
+ An easy question.
+ \end{question}
+ \begin{question}[difficulty=medium]
+ This one's a bit harder.
+ \end{question}
+ \begin{question}[difficulty=hard]
+ Now let's see if you can solve this one.
+ \end{question}
+\end{example}
+
+\subsection{Retrieving the Class Value in a Question}\label{sec:retr-class-value}
+Sometimes it may be desirable to retrieve the value of a class defined by
+\cs{DeclareQuestionClass} that a question has in order to be able to print,
+say. This is possible with the following commands:
+\begin{commands}
+ \expandable\command{GetQuestionClass}[\marg{class}]
+ Prints the value of \meta{class} a question has. The command is
+ expandable. If the class does not exist or the value is empty the command
+ expands to nothing.
+ \command{PrintQuestionClassTF}[\marg{class}\marg{true}\marg{false}]
+ Test if a question has a non-empty value for class \meta{class} and either
+ leaves \meta{true} or \meta{false} in the input stream. In the
+ \meta{true} argument you can refer to the value with \code{\#1} where you
+ want it printed.
+ \command{PrintQuestionClassT}[\marg{class}\marg{true}]
+ Like \cs{PrintQuestionClassTF} but only has the \meta{true} branch.
+ \command{PrintQuestionClassF}[\marg{class}\marg{false}]
+ Like \cs{PrintQuestionClassTF} but only has the \meta{false} branch.
+\end{commands}
+
+\begin{example}
+ \begin{question}[difficulty=hard]
+ This question has the difficulty level
+ ``\PrintQuestionClassTF{difficulty}{#1}{??}''.
+ \end{question}
+\end{example}
+
+\ExplSyntaxOn
+ \bool_set_false:N \g__exsheets_use_difficulties_bool
+\ExplSyntaxOff
+
+\subsection{Tagging Questions}
+There\sinceversion{0.20} is another way of dividing questions: you can assign
+tags to questions:
+\begin{sourcecode}
+ \begin{question}[tags={foo,bar,baz}]
+ ...
+ \end{question}
+\end{sourcecode}
+You can then decide to print only questions with certain tags by using the
+following option:
+\begin{options}
+ \keyval{use-tags}{csv list of tags to include}
+ Select tags. When used only questions being tagged with at least one of
+ the tags in \meta{csv list of tags to include} are printed.
+\end{options}
+
+\section{Adding and Using Additional Information to
+ Questions}\label{sec:additional_info}
+\subsection{Question Properties -- the Basics}
+
+For managing lots of questions and corresponding solutions it can be very
+useful to be able to save and recover additional information to the questions.
+This is possible with the following commands. First the ones for saving:
+\begin{commands}
+ \command{DeclareQuestionProperty}[\marg{name}]
+ This command defines a question property \meta{name}. It can only be
+ used in the document preamble.
+ \command{SetQuestionProperties}[\Marg{\meta{name}=\meta{value},...}]
+ Set the properties for a specific question. this command can only be used
+ inside the \env{question} environment.
+\end{commands}
+Now the commands for recovering the properties:
+\begin{commands}
+ \command{QuestionNumber}[\marg{id}]
+ Recover the number of the question with the \acs{id} \meta{id}. The
+ number is displayed according to the format set with
+ \option{counter-format}.
+ \expandable\command{GetQuestionProperty}[\marg{name}\marg{id}]
+ Recover the property \meta{name} of the question with the \acs{id}
+ \meta{id}. Of course the property must have been declared before. The
+ command is expandable. Since\changedversion{0.12} the properties of a
+ question are written to the \code{aux} file it is possible to retrieve
+ them before the corresponding \env{question} environment has been used.
+ \expandable\command{IfQuestionPropertyTF}[\marg{name}\marg{id}\marg{true}\marg{false}]
+ A command\sinceversion{0.15} that returns \meta{true} if the question with
+ the \acs{id} \meta{id} has the property \meta{name} and \meta{false}
+ otherwise. The variants \cs{IfQuestionPropertyT} and
+ \cs{IfQuestionPropertyF} also exist which only have the \meta{true} or the
+ \meta{false} branch.
+\end{commands}
+
+Let's say we have declared the properties \code{notes}, \code{reference} and
+\code{topic}. By default the property \code{points} is available and gets the
+value of the optional argument of the \code{question} environment.
+
+We can now do the following:
+\begin{example}
+ % uses `biblatex'
+ \begin{question}[ID=center,topic=LaTeX]{3}
+ Explain how you could center text in a \LaTeX\ document.
+ \SetQuestionProperties{
+ topic = \TeX/\LaTeX ,
+ notes = {How to center text.},
+ reference = {\textcite{companion}}}
+ \end{question}
+ \begin{solution}
+ To center a short part of the text body one can use the \env*{center}
+ environment (\points{1}). Inside an environment like \env*{table} one
+ should use \cs*{centering} (\points{1}). For single lines there is also
+ the \cs*{centerline} command (\points{1}).
+ \end{solution}
+ \begin{question}[ID=knuthbooks,topic=LaTeX]{2}
+ Name two books by D.\,E.\,Knuth.
+ \SetQuestionProperties{
+ topic = \TeX/\LaTeX ,
+ notes = {Books by Knuth.},
+ reference = {\textcite{knuth:ct:a,knuth:ct:b,knuth:ct:c,knuth:ct:d,knuth:ct:e}}}
+ \end{question}
+ \begin{solution}
+ For example two volumes from \citetitle{knuth:ct}:
+ \citetitle{knuth:ct:a,knuth:ct:b,knuth:ct:c,knuth:ct:d,knuth:ct:e}. Each
+ valid answer is worth \points{1}
+ \end{solution}
+\end{example}
+
+It is now possible to recover these values later:
+\begin{example}
+ % uses `booktabs'
+ \begin{center}
+ \begin{tabular}{lll}
+ \toprule
+ Question & Property & \\
+ \midrule
+ \QuestionNumber{center}
+ & Points & \GetQuestionProperty{points}{center} \\
+ & Topic & \GetQuestionProperty{topic}{center} \\
+ & References & \GetQuestionProperty{reference}{center} \\
+ & Note & \GetQuestionProperty{notes}{center} \\
+ \midrule
+ \QuestionNumber{knuthbooks}
+ & Points & \GetQuestionProperty{points}{knuthbooks} \\
+ & Topic & \GetQuestionProperty{topic}{knuthbooks} \\
+ & References & \GetQuestionProperty{reference}{knuthbooks} \\
+ & Note & \GetQuestionProperty{notes}{knuthbooks} \\
+ \bottomrule
+ \end{tabular}
+ \end{center}
+\end{example}
+
+Please note that properties \emph{are not the same} as the dividing concepts
+explained in section~\ref{sec:cond-print-quest} although they may seem
+similar in meaning or even have the same name.
+
+When properties are set they are also written to the \code{aux} file which
+means they can be retrieved \emph{before} the corresponding question. Of
+course this means that two compilation runs are necessary.
+
+\subsection{Pre-defined Properties}
+
+A few properties are already defined by \ExSheets:
+\begin{itemize}
+ \item \code{counter}:\sinceversion{0.14} this property holds the actual
+ question number formatted according to the formatting set with option
+ \option{counter-format}.
+ \item \code{subtitle}:\sinceversion{0.12} this property holds the subtitle
+ of the question if given.
+ \item \code{question-body}:\sinceversion{0.14} this property holds the body
+ of the corresponding \env{question} environment. Unlike the other
+ properties it is per default \emph{not} written to the \code{aux} file.
+ \item \code{points}: this property holds the sum of points given to a
+ question.
+ \item \code{bonus-points}:\sinceversion{0.14} this property holds the sum of
+ bonus points given to a question.
+ \item \code{ref}:\sinceversion{0.7f} when the option \option{auto-label} is
+ used this property is defined and expands to the corresponding \cs*{ref}.
+ Also see section~\ref{sec:auto-label-opti}.
+ \item \code{page-ref}:\sinceversion{0.7f} when the option
+ \option{auto-label} is used this property is defined and expands to the
+ corresponding \cs*{pageref}. Also see section~\ref{sec:auto-label-opti}.
+\end{itemize}
+
+There is one option affecting the property \code{question-body}:
+\begin{options}
+ \keybool{save-to-aux}\Module{question}\Default{false}
+ When set to \code{true} the property \code{question-body} is also written
+ to the \code{aux} file.
+\end{options}
+
+\subsection{Advanced Usage}
+
+There are additional commands\sinceversion{0.3} that might prove useful. They
+allow advanced usage of defined properties. Below an example is shown how
+they can be used to generate a grading table.
+\begin{commands}
+ \command{ForEachQuestion}[\marg{code to be executed for each used question}]
+ \changedversion{0.14}Inside the argument one can refer to the \ac{id} of a
+ question with \code{\#1}. You can also refer to the number of the
+ question with \code{\#2}. \emph{Number} means that if you \emph{use}
+ seven questions then those questions have numbers~1 to~7.
+ \expandable\command{numberofquestions}
+ \changedversion{0.14} returns the complete number of used questions.
+ \expandable\command{iflastquestion}[\marg{true code}\marg{false code}]
+ Although this command is available in the whole document it is only useful
+ inside \cs{ForEachQuestion}. It tells you if the end of the loop is
+ reached or not.
+\end{commands}
+
+One could use these commands to create a grading table, for instance:
+\begin{sourcecode}
+ \begin{tabular}{|l|*{\numberofquestions}{c|}c|}\hline
+ Question &
+ \ForEachQuestion{\QuestionNumber{#1}\iflastquestion{}{&}} &
+ Total \\ \hline
+ Points &
+ \ForEachQuestion{\GetQuestionProperty{points}{#1}\iflastquestion{}{&}} &
+ \pointssum* \\ \hline
+ Reached &
+ \ForEachQuestion{\iflastquestion{}{&}} & \\ \hline
+ \end{tabular}
+\end{sourcecode}
+For four questions the table now would look similar to
+figure~\ref{fig:grading-table}.
+
+\begin{figure}[ht]
+ \centering
+ \begin{tabular}{|l|*{4}{c|}c|}\hline
+ Question & 1. & 2. & 3. & 4. & Total \\ \hline
+ Points & 3 & 5 & 10 & 8 & 26 \\ \hline
+ Reached & & & & & \\ \hline
+ \end{tabular}
+ \caption{An example for a grading table. (Actually this is a fake. See the
+ \code{grading-table.tex} file shipped with exsheets for the real use case.)}
+ \label{fig:grading-table}
+\end{figure}
+
+
+\section{Variations of an Exam}
+
+It is a quite common task\sinceversion{0.6} to design an exam in two different
+variants. This is of course possible with \ExSheets' classes (see
+section~\ref{sec:classes}). However, often not the whole question is to be
+different but only small details, the numbers in a maths exam, say. For this
+purpose \ExSheets\ provides the following commands:
+\begin{commands}
+ \command{SetVariations}[\marg{num}]
+ Set the number of different variants. This will determine how many
+ arguments the command \cs{vary} will get. \meta{num} must at least be
+ \code{2} and is initially set to \code{2}.
+ \command{variant}[\marg{num}]
+ Choose the active variant. The argument must be a number between \code{1}
+ and the number set with \cs{SetVariations}. Initially set to \code{1}.
+ \command{vary}[\marg{variant 1}\marg{variant 2}]
+ This command is the one actually used in the document. It has a number of
+ required arguments equal to the number set with \cs{SetVariations}. All
+ of its arguments are discarded except the one specified with
+ \cs{variant}.
+ \command{lastvariant}
+ \sinceversion{0.7b}Each time \cs{vary} is called it stores the value it
+ chose in \cs{lastversion}. This might be convenient to use if one
+ otherwise would have to repeatedly write the same \cs{vary}.
+\end{commands}
+
+\begin{example}
+ \SetVariations{6}%
+ \variant{6}\vary{A}{B}{C}{D}{E}{F}
+ (last variant: \lastvariant)
+ \variant{1}\vary{A}{B}{C}{D}{E}{F}
+ (last variant: \lastvariant)
+ \variant{5}\vary{A}{B}{C}{D}{E}{F}
+ (last variant: \lastvariant)
+ \variant{2}\vary{A}{B}{C}{D}{E}{F}
+ (last variant: \lastvariant)
+ \variant{4}\vary{A}{B}{C}{D}{E}{F}
+ (last variant: \lastvariant)
+ \variant{3}\vary{A}{B}{C}{D}{E}{F}
+ (last variant: \lastvariant)
+\end{example}
+
+\section{A Grade Distribution}
+Probably this is a rather esoteric feature but it could proof useful in some
+cases. Suppose you are a German math teacher and want to grade exactly
+corresponding to the number of points relative to the sum of total points,
+regardless of how big that might be. You could do something like this to
+present your grading decisions for the exam:
+\begin{example}
+ % preamble:
+ % \DeclareRelGrades{
+ % 1 = 1 ,
+ % {1,5} = .9167 ,
+ % 2 = .8333 ,
+ % {2,5} = .75 ,
+ % 3 = .6667 ,
+ % {3,5} = .5833 ,
+ % 4 = .5
+ % }
+ \small\setlength\tabcolsep{2pt}
+ \begin{tabular}{r|*8c}
+ Punkte
+ & $\grade*{1}$ & $\le\grade*{1}$ & $\le\grade*{1,5}$ & $\le\grade*{2}$
+ & $\le\grade*{2,5}$ & $\le\grade*{3}$ & $\le\grade*{3,5}$ & $<\grade*{4}$ \\
+ Note
+ & 1 & 1--2 & 2 & 2--3 & 3 & 3--4 & 4 & 5
+ \end{tabular}
+\end{example}
+
+These are the available commands and options:
+\begin{commands}
+ \command{DeclareRelGrades}[\Marg{\meta{grade}=\meta{num},...}]
+ This command is used to define grades and assign the percentage of total
+ points to them.
+ \command{grade}[\sarg\marg{grade}]
+ Gives the number of points corresponding to a grade depending on the value
+ of \cs{pointssum} with or without (starred version) ``unit''.
+\end{commands}
+\begin{options}
+ \keyval{round}{num}\Module{grades}\Default{0}
+ The number of decimals the points of a grade are rounded to. This doesn't
+ apply to the maximum number of points if the rounded number would be
+ bigger than the actual sum.
+ \keybool{half}\Module{grades}\Default{false}
+ If set to \code{true} points are rounded either to full or to half
+ points.
+\end{options}
+
+\section{Selectively Include Questions from External Files}\label{sec:include}
+\subsection{Caveat}
+I need to say some words of caution: the \cs{includequestions} that will be
+presented shortly is probably \ExSheets' most experimental one at the time of
+writing (\today). Thanks to feedback of users it is constantly improved and
+bugs are fixed. It is not a very efficient way to insert question regarding
+performance and you shouldn't wonder if compilation slows down when you use
+it. It probably needs to be re-written all over but on the one hand that
+would introduce new bugs and on the other hand for the time being I don't have
+the capacities, anyway, so you'll have to live it, I'm afraid.
+
+\subsection{How it works}
+Suppose you have one or more files with questions prepared to use them as a
+kind of database. One for class A, say, one for class B, one for class C and
+so one, something like this:
+\begin{sourcecode}
+ % this is file classA.tex
+ \begin{question}[class=A,ID=A1,topic=X]
+ First question of class A, topic X.
+ \end{question}
+ \begin{solution}
+ First solution of class A.
+ \end{solution}
+ \begin{question}[class=A,ID=A2,topic=Y]
+ Second question of class A, topic Y.
+ \end{question}
+ \begin{solution}
+ Second solution of class A.
+ \end{solution}
+ ...
+ % end of file classA.tex
+ \endinput
+\end{sourcecode}
+You can of course just \cs*{input} or \cs*{include} it but that would of
+course include the whole file into your document. But would't it be nice to
+just include selected questions? Or maybe a five random questions from the
+file? That is possible with the following command:
+\begin{commands}
+ \command{includequestions}[\oarg{options}\marg{list of filenames}]
+ Include questions from external files.
+\end{commands}
+If you use it without options it will have the same effect as \cs*{input}.
+There are however the following options:
+\begin{options}
+ \keybool{all}\Module{include}
+ \keyval{IDs}{list of IDs}\Module{include}\Default
+ Includes only the specified questions.
+ \keyval{random}{num}\Module{include}\Default
+ Includes \meta{num} randomly selected questions. This option uses the
+ \pkg{pgfcore} package to create the pseudo-random numbers.
+ \keyval{exclude}{list of IDs}\Module{include}\Default
+ Questions who's \acp{id} are specified here are \emph{not} included. This
+ option can be combined with the \option{random} option.
+\end{options}
+
+The usage should be self-explainable:
+\begin{sourcecode}
+ % include questions A1, A3 and A4:
+ \includequestions[IDs={A1,A3,A4}]{classA.tex}
+ % or include 3 random questions:
+ \includequestions[random=3]{classA}
+\end{sourcecode}
+In order to be able to select the questions \ExSheets\ needs to \cs*{input}
+the file twice. The first time the available questions are determined, the
+second time the selected questions are used. This unfortunately means that
+anything that is \emph{not} part of a question or solution is also input
+twice. Either don't put anything else into the file or use one of the
+following commands for control:
+\begin{commands}
+ \command{PrintIfIncludeActiveTF}[\marg{true code}\marg{false code}]
+ Checks if the questions are actively included or not and puts \meta{true
+ code} or \meta{false code} in the input stream depending on the answer.
+ \command{PrintIfIncludeActiveT}[\marg{true code}]
+ Checks if the questions are actively included or not and puts \meta{true
+ code} in the input stream if the answer is yes.
+ \command{PrintIfIncludeActiveF}[\marg{false code}]
+ Checks if the questions are actively included or not and puts \meta{false
+ code} in the input stream if the answer is no.
+\end{commands}
+
+The selection can be refined further by selecting questions belonging to a
+specific class of questions (see section~\ref{sec:cond-print-quest}) before
+using \cs{includequestions}.
+
+\sinceversion{0.8}After you've used \cs{includequestions} the \acp{id} of the
+included questions is available as an unordered comma separated list in the
+following macro:
+\begin{commands}
+ \command{questionsincludedlast}
+ Unordered comma separated list of question \acp{id} included with the last
+ usage of \cs{includequestions}.
+\end{commands}
+
+\section{The \option*{auto-label} Option}\label{sec:auto-label-opti}
+The\sinceversion{0.12} package option \option{auto-label} sets a
+\cs*{label}\Marg{qu:\meta{id}} every time the question environment is used.
+Both the used command and the automated label can be customized using the
+following options:
+
+\begin{options}
+ \keyval{label-format}{code}\Default{qu:\#1}
+ The pattern for generating the automatic label. \code{\#1} gets replaced
+ by the \ac{id} of the corresponding question.
+ \keyval{label-cmd}{macro}\Default{\cs*{label}}
+ The command used for generating the label. A command that should take one
+ mandatory argument.
+ \keyval{ref-cmd}{macro}\Default{\cs*{ref}}
+ The command used in the \code{ref} property created by the
+ \option{auto-label} option, also see section \ref{sec:additional_info}.
+ The command should take one mandatory argument.
+ \keyval{pageref-cmd}{macro}\Default{\cs*{pageref}}
+ The command used in the \code{pageref} property created by the
+ \option{auto-label} option, also see section \ref{sec:additional_info}.
+ The command should take one mandatory argument.
+\end{options}
+
+\section{Own Question/Solution Pairs}
+\ExSheets\changedversion{0.9} provides the possibility to create new
+environments that behave like the \env{question} and \env{solution}
+environments. This would allow, for example, to define a
+\env*{question*}/\env*{solution*} environment pair for bonus questions. The
+following commands may be used in the document preamble:
+\begin{commands}
+ \command{NewQuSolPair}[\marg{question}\oarg{question options}\oarg{general
+ options}\marg{solution}\oarg{solution options}\oarg{general options}]
+ Define a new pair of question and solution environments.
+ \command{RenewQuSolPair}[\marg{question}\oarg{question options}\oarg{general
+ options}\marg{solution}\oarg{solution options}\oarg{general options}]
+ Redefine an existing pair of question and solution environments.
+\end{commands}
+The standard environments are defined as follows:
+\begin{sourcecode}
+ \NewQuSolPair{question}{solution}
+\end{sourcecode}
+
+Let's say we want the possibility to add bonus questions. A simple way would
+be to define starred variants that add a star in the margin left to the title:
+\begin{example}
+ % preamble:
+ % - \texorpdfstring is provided by `hyperref'
+ % - \bigstar is provided by `amssymb'
+ % \DeclareRobustCommand*\questionstar{\texorpdfstring{\bonusquestionsign}{* }}
+ % \DeclareRobustCommand*\bonusquestionsign{\llap{$\bigstar$\space}}
+ %
+ % \NewQuSolPair
+ % {question*}[name=\questionstar Bonus Question]
+ % {solution*}[name=\questionstar Solution]
+ \begin{question*}
+ This is a bonus question.
+ \end{question*}
+ \begin{solution*}[print]
+ This is what the solution looks like.
+ \end{solution*}
+\end{example}
+As you can see the environments take the same options as are described for the
+standard \env{question} and \env{solution} environments.
+
+\section{Filling in the Blanks}
+\subsection{Cloze}
+Both\changedversion{0.4} in exercise sheets and in exams it is sometimes
+desirable to be able to create \blank{blanks} that have to be filled in. Or
+maybe some more lines: \blank[width=5\linewidth]{}
+
+\begin{commands}
+ \command{blank}[\sarg\oarg{options}\marg{text to be filled in}]
+ creates a blank in normal text or in a question but fills the text of its
+ argument if inside a solution. If used at the \emph{begin of a paragraph}
+ \cs{blank} will do two things: it will set the linespread according to an
+ option explained below and will insert \cs*{par} after the lines. If you
+ don't want that use the starred version.
+\end{commands}
+
+The options are these:
+\begin{options}
+ \keychoice{style}{line,wave,dline,dotted,dashed}\Module{blank}\Default{line}
+ The style of the line. This uses the corresponding command from the
+ \pkg{ulem} package and is the whole reason why \ExSheets\ loads it in the
+ first place.
+ \keyval{scale}{num}\Module{blank}\Default{1}
+ Scales the width of the blank by factor \meta{num} unless the width is
+ explicitly set.
+ \keyval{width}{dim}\Module{blank}\Default
+ The width of the line. If it is not used the width of the filled in text
+ is used.
+ \keyval{linespread}{num}\Module{blank}\Default{1}
+ Set the linespread for the blank lines. This only has an effect if
+ \cs{blank} is used at the begin of a paragraph.
+ \keyval{line-increment}{dim}\Module{blank}\Default{1pt}
+ \sinceversion{0.21h}When the blank line ist built it is built in multiples
+ of this value. If the value is too large you may end up with uneven
+ lines. If the value is too small you may end up with a non-ending
+ compilation.
+ \keyval{line-minimum-length}{dim}\Module{blank}\Default{2em}
+ \sinceversion{0.21h}The minimal length a line must have before it is built
+ step by step.
+\end{options}
+\begin{example}
+ \begin{question}
+ Try to fill in \blank[width=4cm]{these} blanks. All of them
+ \blank[style=dotted]{are created} by using the \cs{blank}
+ \blank[style=dashed]{command}.
+ \end{question}
+ \begin{solution}[print]
+ Try to fill in \blank[width=4cm]{these} blanks. All of them
+ \blank[style=dotted]{are created} by using the \cs{blank}
+ \blank[style=dashed]{command}.
+ \end{solution}
+\end{example}
+A number of empty lines are easily created by setting the width option:
+\begin{example}
+ \blank[width=4.8\linewidth,linespread=1.5]{}
+\end{example}
+
+\subsection{Vertical Space for answers}
+When\sinceversion{0.3} you're creating an exam you might want to add some
+vertical space where the students can write down their answers. While you can
+always use \cs*{vspace} this is not always handy when the space left on the
+page is less than you want. In this case it would be nice if a) there would
+be no warning and b) the rest of the space would be added at the top of the
+next page. This is what the following command is for:
+\begin{commands}
+ \command{examspace}[\sarg\marg{dim}]
+ Add space as specified in \meta{dim}. If the space available on the
+ current page is not enough the rest of the space will be added at the top
+ of the next page. The starred version will silently drop any leftover
+ space instead of adding it to the next page.
+\end{commands}
+\begin{example}[side-by-side]
+ \begin{question}
+ What do you think of this feature?
+ \examspace{3cm}
+ \end{question}
+ This line comes after the space.
+\end{example}
+
+\section{Styling your Exercise/Exam Sheets}\label{part:style}
+\subsection{Background}
+The \ExSheets\ package makes extensive use of \LaTeX3's coffins\footnote{See
+ the documentation to the \pkg{xcoffins} package for more information on
+ that.} as well as its templates concept\footnote{Have a look into the
+ documentation to the \pkg{xtemplate} package.}. The latter allows a
+rather easy extension and customization of some of \ExSheets' environments.
+To be more precise: you can define your own instances for the headings used
+for questions and solutions.
+
+What this package doesn't provide is changing the background of questions or
+framing them. But this is easily possible using the \pkg{mdframed} package
+and its \cs*{surroundwithmdframed} command.
+
+\ExSheets{} also provides the options \option{pre-hook}, \option{post-hook},
+\option{pre-body-hook} and \option{post-body-hook} to both the question and
+the solution environment. With them it is rather straightforward to add a
+\pkg{mdframed} frame for instance:
+\begin{sourcecode}
+ \SetupExSheets{
+ solution/pre-hook = \mdframed ,
+ solution/post-hook = \endmdframed
+ }
+\end{sourcecode}
+
+Then\sinceversion{0.18} there is the macro
+\cs{exsheetsprintsolution}\marg{heading}\marg{body}\label{exsheetsprintsolution}
+which may be redefined to suit your needs. The default definition is
+equivalent to
+\begin{sourcecode}
+ \newcommand\exsheetsprintsolution[2]{#1#2}
+\end{sourcecode}
+
+\subsection{The \code{exsheets-headings} Object}\label{sec:exsheets-headings}
+\ExSheets\ defines the object \code{exsheets-headings} and one template for it,
+the `default' template. The package also defines two instances of this
+template, the `block' instance and the `runin' instance.
+
+\begin{example}
+ \SetupExSheets{headings=block}
+ \begin{question}{1}
+ a `block' heading
+ \end{question}
+ \SetupExSheets{headings=runin}
+ \begin{question}{1}
+ a `runin' heading
+ \end{question}
+\end{example}
+
+\subsubsection{Available Options}
+This section only lists the options that can be used when defining an instance
+of the `default' template. The following subsections will give loads of
+examples of their usage. The options are listed in the definition for the
+template interface:
+
+\begin{sourcecode}
+ \DeclareTemplateInterface{exsheets-heading}{default}{3}{
+ % option : type = default
+ 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 =
+ }
+\end{sourcecode}
+
+Each heading is built with at most five coffins available with the names
+`main', `title', `subtitle', `number' and `points'. Those coffins place
+possibly the whole heading, the title, the subtitle, the question number and
+the assigned points. The only coffin that's always typeset is the `main'
+coffin, which is empty per default.
+
+Coffins can be joined (two become one, the first extends its bounding box to
+contain the second) using the following syntax:
+\begin{sourcecode}
+ join = coffin1[handle11,handle12]coffin2[handle21,handle22](x-offset,y-offset)
+\end{sourcecode}
+The syntax for attaching (two become one, the first does \emph{not} extend its
+bounding box around the second) is the same.
+
+More on coffin handles is described in the documentation for the
+\pkg{xcoffins}. Figure~\ref{fig:handles} briefly demonstrates the available
+handle pairs.
+
+\begin{figure}[ht]
+ \centering
+ \parbox{4.5cm}{%
+ \NewCoffin\ExampleCoffin
+ \SetHorizontalCoffin\ExampleCoffin{\color{gray!30}\rule{4cm}{4cm}}%
+ \DisplayCoffinHandles\ExampleCoffin{blue}%
+ }
+ \caption{Available handles for a horizontal coffin.}\label{fig:handles}
+\end{figure}
+
+It is possible\sinceversion{0.20} to add own static coffins:
+\begin{commands}
+ \command{DeclareExSheetsHeadingContainer}[\marg{name}\marg{code}]
+ Defines a new coffin \meta{name} containing \meta{code}. You can refer to
+ the current question's \ac{id} with \cs{CurrentQuestionID}.
+\end{commands}
+
+The following subsections will show all definitions of the instances available
+and how they look. This will hopefully give you enough ideas to create your
+own instance if you want to have another heading style than the ones
+available. Each of the following instances is available through the option
+\key{headings}{instance}.
+
+The following examples use a sample text defined as follows:
+\begin{sourcecode}
+ \def\s{This is some sample text we will use to create a somewhat
+ longer text spanning a few lines.}
+ \def\sample{\s\ \s\par\s}
+\end{sourcecode}
+\def\s{This is some sample text we will use to create a somewhat longer text
+ spanning a few lines.}
+\def\sample{\s\ \s\par\s}
+
+All of the following examples use the same question call:
+\begin{sourcecode}
+ \SetupExSheets{headings=<name>}
+ \begin{question}[subtitle=The subtitle of the question]{1}
+ A `<name>' heading. \sample
+ \end{question}
+\end{sourcecode}
+
+\subsubsection{The `block' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{block}{default}{
+ join = { title[r,B]number[l,B](.333em,0pt) } ,
+ attach =
+ {
+ main[l,vc]title[l,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](\marginparsep,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=block}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `block' heading. \sample
+\end{question}
+
+\subsubsection{The `runin' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{runin}{default}{
+ runin = true ,
+ number-post-code = \space ,
+ 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](.333em,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=runin}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `runin' heading. \sample
+\end{question}
+
+\subsubsection{The `simple' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{simple}{default}{
+ title-format = \normalsize ,
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ attach = { main[l,t]number[l,t](0pt,0pt) } ,
+ join =
+ {
+ number[r,b]title[l,b](.333em,0pt) ;
+ main[l,b]points[l,t](1em,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=simple}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `simple' heading. \sample
+\end{question}
+
+\subsubsection{The `empty' Instance}
+\sinceversion{0.9a}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{empty}{default}{
+ runin = true ,
+ above = \parskip ,
+ below = \parskip ,
+ attach = { main[l,vc]points[l,vc](\linewidth+\marginparsep,0pt) }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=empty}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ An `empty' heading. \sample
+\end{question}
+
+\subsubsection{The `block-rev' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{block-rev}{default}{
+ toc-reversed = true ,
+ join = { number[r,B]title[l,B](.333em,0pt) } ,
+ attach =
+ {
+ main[l,vc]number[l,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](\marginparsep,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=block-rev}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `block-rev' heading. \sample
+\end{question}
+
+\subsubsection{The `block-subtitle' Instance}
+\sinceversion{0.10}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{block-subtitle}{default}{
+ join = {
+ title[r,B]number[l,B](.333em,0pt) ;
+ title[r,B]subtitle[l,B](1em,0pt)
+ } ,
+ attach = {
+ main[l,vc]title[l,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](\marginparsep,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=block-subtitle}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `block-subtitle' heading. \sample
+\end{question}
+\subsubsection{The `block-wp' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{block-wp}{default}{
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join =
+ {
+ title[r,B]number[l,B](.333em,0pt) ;
+ title[r,B]points[l,B](.333em,0pt)
+ } ,
+ attach = { main[l,vc]title[l,vc](0pt,0pt) }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=block-wp}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `block-wp' heading. \sample
+\end{question}
+
+\subsubsection{The `block-wp-rev' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{block-wp-rev}{default}{
+ toc-reversed = true ,
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join =
+ {
+ number[r,B]title[l,B](.333em,0pt) ;
+ number[r,B]points[l,B](.333em,0pt)
+ } ,
+ attach = { main[l,vc]number[l,vc](0pt,0pt) }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=block-wp-rev}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `block-wp-rev' heading. \sample
+\end{question}
+
+\subsubsection{The `block-nr' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{block-nr}{default}{
+ attach =
+ {
+ main[l,vc]number[l,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](\marginparsep,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=block-nr}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `block-nr' heading. \sample
+\end{question}
+
+\subsubsection{The `block-nr-wp' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{block-nr-wp}{default}{
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join = { number[r,vc]points[l,vc](.333em,0pt) } ,
+ attach = { main[l,vc]number[l,vc](0pt,0pt) }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=block-nr-wp}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `block-nr-wp' heading. \sample
+\end{question}
+
+\subsubsection{The `runin-rev' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{runin-rev}{default}{
+ toc-reversed = true ,
+ runin = true ,
+ title-post-code = \space ,
+ attach =
+ { main[l,vc]points[l,vc](\linewidth+\marginparsep,0pt) } ,
+ join =
+ {
+ main[r,vc]number[r,vc](0pt,0pt) ;
+ main[r,vc]title[l,vc](.333em,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=runin-rev}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `runin-rev' heading. \sample
+\end{question}
+
+\subsubsection{The `runin-wp' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{runin-wp}{default}{
+ runin = true ,
+ points-pre-code = ( ,
+ points-post-code = )\space ,
+ join =
+ {
+ main[r,vc]title[r,vc](0pt,0pt) ;
+ main[r,vc]number[l,vc](.333em,0pt) ;
+ main[r,vc]points[l,vc](.333em,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=runin-wp}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `runin-wp' heading. \sample
+\end{question}
+
+\subsubsection{The `runin-wp-rev' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{runin-wp-rev}{default}{
+ toc-reversed = true ,
+ runin = true ,
+ points-pre-code = ( ,
+ points-post-code = )\space ,
+ join =
+ {
+ main[r,vc]number[r,vc](0pt,0pt) ;
+ main[r,vc]title[l,vc](.333em,0pt) ;
+ main[r,vc]points[l,vc](.333em,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=runin-wp-rev}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `runin-wp-rev' heading. \sample
+\end{question}
+
+\subsubsection{The `runin-nr' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{runin-nr}{default}{
+ runin = true ,
+ number-post-code = \space ,
+ attach =
+ { main[l,vc]points[l,vc](\linewidth+\marginparsep,0pt) } ,
+ join = { main[r,vc]number[l,vc](0pt,0pt) }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=runin-nr}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `runin-nr' heading. \sample
+\end{question}
+
+\subsubsection{The `runin-fixed-nr' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{runin-fixed-nr}{default}{
+ runin = true ,
+ number-pre-code = \hbox to 2em \bgroup ,
+ number-post-code = \hfil\egroup ,
+ attach =
+ { main[l,vc]points[l,vc](\linewidth+\marginparsep,0pt) } ,
+ join = { main[r,vc]number[l,vc](0pt,0pt) }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=runin-fixed-nr}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `runin-fixed-nr' heading. \sample
+\end{question}
+
+\subsubsection{The `runin-nr-wp' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{runin-nr-wp}{default}{
+ runin = true ,
+ points-pre-code = ( ,
+ points-post-code = )\space ,
+ join =
+ {
+ main[r,vc]number[l,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](.333em,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=runin-nr-wp}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `runin-nr-wp' heading. \sample
+\end{question}
+
+\subsubsection{The `inline' Instance}
+\sinceversion{0.5}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{inline}{default}{
+ inline = true ,
+ number-pre-code = \space ,
+ number-post-code = \space ,
+ join =
+ {
+ main[r,vc]title[r,vc](0pt,0pt) ;
+ main[r,vc]number[l,vc](0pt,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=inline}
+Text before
+\begin{question}[subtitle=The subtitle of the question]{1}
+ An `inline' heading. \sample
+\end{question}
+ Text after
+
+\subsubsection{The `inline-wp' Instance}
+\sinceversion{0.5}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{inline-wp}{default}{
+ inline = true ,
+ number-pre-code = \space ,
+ number-post-code = \space ,
+ points-pre-code = ( ,
+ points-post-code = )\space ,
+ join =
+ {
+ main[r,vc]title[r,vc](0pt,0pt) ;
+ main[r,vc]number[l,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](0pt,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=inline-wp}
+Text before
+\begin{question}[subtitle=The subtitle of the question]{1}
+ An `inline-wp' heading. \sample
+\end{question}
+ Text after
+
+\subsubsection{The `inline-nr' Instance}
+\sinceversion{0.5}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{inline-nr}{default}{
+ inline = true ,
+ number-post-code = \space ,
+ join = { main[r,vc]number[l,vc](0pt,0pt) }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=inline-nr}
+Text before
+\begin{question}[subtitle=The subtitle of the question]{1}
+ An `inline-nr' heading. \sample
+\end{question}
+ Text after
+
+\subsubsection{The `centered' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{centered}{default}{
+ join = { title[r,B]number[l,B](.333em,0pt) } ,
+ attach =
+ {
+ main[hc,vc]title[hc,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](\marginparsep,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=centered}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `centered' heading. \sample
+\end{question}
+
+\subsubsection{The `centered-wp' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{centered-wp}{default}{
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join =
+ {
+ title[r,B]number[l,B](.333em,0pt) ;
+ title[r,B]points[l,B](.333em,0pt)
+ } ,
+ attach = { main[hc,vc]title[hc,vc](0pt,0pt) }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=centered-wp}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `centered-wp' heading. \sample
+\end{question}
+
+\subsubsection{The `margin' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{margin}{default}{
+ runin = true ,
+ number-post-code = \space ,
+ points-pre-code = ( ,
+ points-post-code = )\space ,
+ join = { title[r,b]number[l,b](.333em,0pt) } ,
+ attach =
+ {
+ main[l,vc]title[r,vc](0pt,0pt) ;
+ main[l,b]points[r,t](0pt,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=margin}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `margin' heading. \sample
+\end{question}
+
+\subsubsection{The `margin-nr' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{margin-nr}{default}{
+ runin = true ,
+ attach =
+ {
+ main[l,vc]number[r,vc](-.333em,0pt) ;
+ main[r,vc]points[l,vc](\linewidth+\marginparsep,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=margin-nr}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `margin-nr' heading. \sample
+\end{question}
+
+\subsubsection{The `raggedleft' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{raggedleft}{default}{
+ join = { title[r,B]number[l,B](.333em,0pt) } ,
+ attach =
+ {
+ main[r,vc]title[r,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](\marginparsep,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=raggedleft}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `raggedleft' heading. \sample
+\end{question}
+
+\subsubsection{The `fancy' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{fancy}{default}{
+ toc-reversed = true ,
+ indent-first = true ,
+ vscale = 2 ,
+ pre-code = \rule{\linewidth}{1pt} ,
+ post-code = \rule{\linewidth}{1pt} ,
+ title-format = \large\scshape\color{rgb:red,0.65;green,0.04;blue,0.07} ,
+ number-format = \large\bfseries\color{rgb:red,0.02;green,0.04;blue,0.48} ,
+ points-format = \itshape ,
+ join = { number[r,B]title[l,B](.333em,0pt) } ,
+ attach =
+ {
+ main[hc,vc]number[hc,vc](0pt,0pt) ;
+ main[l,vc]points[r,vc](-\marginparsep,0pt)
+ }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=fancy}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `fancy' heading. \sample
+\end{question}
+
+\subsubsection{The `fancy-wp' Instance}
+\begin{sourcecode}
+ \DeclareInstance{exsheets-heading}{fancy-wp}{default}{
+ toc-reversed = true ,
+ indent-first = true ,
+ vscale = 2 ,
+ pre-code = \rule{\linewidth}{1pt} ,
+ post-code = \rule{\linewidth}{1pt} ,
+ title-format = \large\scshape\color{rgb:red,0.65;green,0.04;blue,0.07} ,
+ number-format = \large\bfseries\color{rgb:red,0.02;green,0.04;blue,0.48} ,
+ points-format = \itshape ,
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join =
+ {
+ number[r,B]title[l,B](.333em,0pt) ;
+ number[r,B]points[l,B](.333em,0pt)
+ } ,
+ attach = { main[hc,vc]number[hc,vc](0pt,0pt) }
+ }
+\end{sourcecode}
+\SetupExSheets{headings=fancy-wp}
+\begin{question}[subtitle=The subtitle of the question]{1}
+ A `fancy-wp' heading. \sample
+\end{question}
+
+\subsection{Using an \ExSheets{} Heading in Custom Code}\label{sec:using-an-exsheets}
+
+It can be useful to have access to \ExSheets{} headings in custom code. This
+is possible with the following command\sinceversion{0.14}:
+
+\begin{commands}
+ \command{ExSheetsHeading}[\marg{instance}\marg{title}\marg{number}%
+ \marg{points}\marg{bonus}\marg{id}]
+ The meaning of the arguments is as follows:
+ \begin{itemize}
+ \item \meta{instance}: the name of the headings instance to be used.
+ \item \meta{title}: the contents of the \code{title} coffin.
+ \item \meta{number}: the contents of the \code{number} coffin.
+ \item \meta{points}: The number of points given to the question. If
+ non-zero this will cause the points to be printed in the \code{points}
+ coffin.
+ \item \meta{bonus}: the same as \meta{points} but for bonus points.
+ \item \meta{id}: the \acs{id} of the question this heading belongs to.
+ \end{itemize}
+\end{commands}
+
+In combination with \cs{ForEachQuestion} the command can be used to build a
+custom list of questions. An example of its usage can be seen at the German
+Q\&A~site \TeX welt: \url{http://texwelt.de/wissen/fragen/6698#6738}.
+
+\subsection{Load Custom Configurations}
+If you have custom configurations you want to be loaded automatically then save
+them in a file \code{exsheets\_configurations.cfg}. If this file is present it
+will be loaded \cs*{AtBeginDocument}.
+
+\SetupExSheets{headings=block}
+
+\part{The \ExSheetslistings\ Package}\label{part:listings}
+\section{The Problem}
+I knew the day would come when people would ask how to include verbatim
+material in the \env{question} and \env{solution} environments. Since they're
+defined with the \pkg{environ} package they're reading their environment
+bodies like macros read their arguments. This makes it impossible to use
+verbatim material inside them\footnote{See the \TeX\ \acs{faq}
+ \url{http://www.tex.ac.uk/cgi-bin/texfaq2html?label=verbwithin} for reasons
+ why.}. Now the day has come~\cite{tex.sx:131546}. Soon after the first
+question appeared I wrote the first draft for \ExSheetslistings\ for a question
+on \TeX.sx~\cite{tex.sx:133907}.
+
+\section{The Proposed Solution}
+
+The \ExSheetslistings\ package defines \pkg{listings} environments that place
+their contents inside \env{question} and \env{solution} environments. They do
+this by writing the listing to a unique auxiliary file --
+questions to \code{\cs*{jobname}-ex\meta{num}.lst} and solutions to
+\code{\cs*{jobname}-sol\meta{num}.lst} where \meta{num} is an increasing
+integer that ensures that each listing gets a unique file name. Those files
+are then included with \cs{lstinputlisting} if and when the question or
+solution is printed.
+
+\begin{environments}
+ \environment{lstquestion}[\oarg{options}]
+ A \pkg{listings} environment placed in a \env{question}.
+ \environment{lstsolution}[\oarg{options}]
+ A \pkg{listings} environment placed in a \env{solution}.
+\end{environments}
+
+All you have to do to use the package is loading it the usual way:
+\begin{sourcecode}
+ \usepackage{exsheets-listings}
+\end{sourcecode}
+This will also load the packages \ExSheets\ and \pkg{listings} if they're not
+loaded already.
+
+\begin{example}
+ % this uses my listings style used in this documentation for all pieces of
+ % code:
+ \begin{lstquestion}[%
+ pre=Explain what this piece of \TeX\ code does:,
+ listings={style=cnltx}]
+ \begingroup\expandafter\expandafter\expandafter\endgroup
+ \expandafter\ifx\csname foo\endcsname\relax
+ ...
+ \else
+ ...
+ \fi
+ \end{lstquestion}
+\end{example}
+
+The example already shows two options of these environments. Here is the
+complete list:
+\begin{options}
+ \keyval{pre}{text}
+ \meta{text} is placed before the code in the \env{question} or
+ \env{solution} environment.
+ \keyval{post}{text}
+ \meta{text} is placed after the code in the \env{question} or
+ \env{solution} environment.
+ \keyval{options}{options}
+ Options passed to underlying the \env{question} or \env{solution}
+ environment.
+ \keyval{points}{points}
+ The points assigned to the underlying \env{question} environment.
+ \keyval{listings}{options}
+ Options passed to the underlying \pkg{listings} environment.
+\end{options}
+
+There are also two new options for \ExSheets\ that can be set with
+\cs{SetupExSheets}:
+\begin{options}
+ \keyval{listings}{options}\Module{question}
+ Options passed to the underlying \pkg{listings} environment of
+ \env{lstquestion}.
+ \keyval{listings}{options}\Module{solution}
+ Options passed to the underlying \pkg{listings} environment of
+ \env{lstsolution}.
+\end{options}
+
+\section{Own Environments}
+
+\begin{commands}
+ \command{NewLstQuSolPair}[\oarg{options for both environments}\marg{lst question
+ env}\marg{question env}\oarg{options for lst question env}\marg{lst
+ solution env}\marg{solution env}\oarg{options for lst solution env}]
+ Defines two new \pkg{listings} environments that place the listing in a
+ question environment \meta{question env} or a solution environment
+ \meta{solution env}. Those underlying environments should be
+ environments as defined by \cs{NewQuSolPair}. The different options
+ allow to preset options for the newly defined environments.
+\end{commands}
+
+The existing environments have been defined like this:
+\begin{sourcecode}
+ \NewLstQuSolPair{lstquestion}{question}{lstsolution}{solution}
+\end{sourcecode}
+
+\appendix
+\part{Appendix}
+\section{A List of all Solutions used in this Manual}\label{sec:solutions:list}
+\SetupExSheets{headings=block-wp,solutions-totoc}
+\printsolutions
+
+\end{document}
diff --git a/macros/latex/contrib/exsheets/exsheets_headings.cfg b/macros/latex/contrib/exsheets/exsheets_headings.cfg
new file mode 100644
index 0000000000..3badcdbbf4
--- /dev/null
+++ b/macros/latex/contrib/exsheets/exsheets_headings.cfg
@@ -0,0 +1,361 @@
+% --------------------------------------------------------------------------
+% 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-2017 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
+\ProvidesFile{exsheets_headings.cfg}
+ [
+ \c_exsheets_date_tl \c_space_tl
+ v\c_exsheets_version_tl \c_space_tl
+ ExSheets~ headings~ instances
+ ]
+
+\cs_new:Npn \exsheets_headings_files_loaded: {}
+
+% EMPTY:
+\DeclareInstance { exsheets-heading } { empty } { default }
+ {
+ runin = true ,
+ above = \parskip ,
+ below = \parskip ,
+ attach =
+ { main[l,vc] points[l,vc] (\linewidth + \marginparsep,0pt) }
+ }
+
+% SIMPLE:
+\DeclareInstance { exsheets-heading } { simple } { default }
+ {
+ title-format = \normalsize ,
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ attach = { main[l,t] number[l,t] (0pt,0pt) } ,
+ join =
+ {
+ number[r,b] title[l,b] (.333em,0pt) ;
+ main[l,b] points[l,t] (1em,0pt)
+ }
+ }
+
+% BLOCK, REVERSED:
+\DeclareInstance { exsheets-heading } { block-rev } { default }
+ {
+ toc-reversed = true ,
+ join = { number[r,B] title[l,B] (.333em,0pt) } ,
+ attach =
+ {
+ main[l,vc] number[l,vc] (0pt,0pt) ;
+ main[r,vc] points[l,vc] (\marginparsep,0pt)
+ }
+ }
+
+% BLOCK, SUBTITLE:
+\DeclareInstance{exsheets-heading}{block-subtitle}{default}{
+ join = {
+ title[r,B]number[l,B](.333em,0pt) ;
+ title[r,B]subtitle[l,B](1em,0pt)
+ } ,
+ attach = {
+ main[l,vc]title[l,vc](0pt,0pt) ;
+ main[r,vc]points[l,vc](\marginparsep,0pt)
+ }
+}
+
+% BLOCK, POINTS WITH THE TITLE:
+\DeclareInstance { exsheets-heading } { block-wp } { default }
+ {
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join =
+ {
+ title[r,B] number[l,B] (.333em,0pt) ;
+ title[r,B] points[l,B] (.333em,0pt)
+ } ,
+ attach = { main[l,vc] title[l,vc] (0pt,0pt) }
+ }
+
+% BLOCK, POINTS WITH THE TITLE, REVERSED:
+\DeclareInstance { exsheets-heading } { block-wp-rev } { default }
+ {
+ toc-reversed = true ,
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join =
+ {
+ number[r,B] title[l,B] (.333em,0pt) ;
+ number[r,B] points[l,B] (.333em,0pt)
+ } ,
+ attach = { main[l,vc] number[l,vc] (0pt,0pt) }
+ }
+
+% BLOCK WITH NO TITLE:
+\DeclareInstance { exsheets-heading } { block-nr } { default }
+ {
+ attach =
+ {
+ main[l,vc] number[l,vc] (0pt,0pt) ;
+ main[r,vc] points[l,vc] (\marginparsep,0pt)
+ }
+ }
+
+% BLOCK WITH NO TITLE, NUMBER WITH THE TITLE:
+\DeclareInstance { exsheets-heading } { block-nr-wp } { default }
+ {
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join = { number[r,vc] points[l,vc] (.333em,0pt) } ,
+ attach = { main[l,vc] number[l,vc] (0pt,0pt) }
+ }
+
+% RUNIN, REVERSED:
+\DeclareInstance { exsheets-heading } { runin-rev } { default }
+ {
+ toc-reversed = true ,
+ runin = true ,
+ title-post-code = \c_space_tl ,
+ attach =
+ { main[l,vc] points[l,vc] (\linewidth + \marginparsep,0pt) } ,
+ join =
+ {
+ main[r,vc] number[r,vc] (0pt,0pt) ;
+ main[r,vc] title[l,vc] (.333em,0pt)
+ }
+ }
+
+% RUNIN, POINTS WITH THE TITLE:
+\DeclareInstance { exsheets-heading } { runin-wp } { default }
+ {
+ runin = true ,
+ points-pre-code = ( ,
+ points-post-code = ) \c_space_tl ,
+ join =
+ {
+ main[r,vc] title[r,vc] (0pt,0pt) ;
+ main[r,vc] number[l,vc] (.333em,0pt) ;
+ main[r,vc] points[l,vc] (.333em,0pt)
+ }
+ }
+
+% RUNIN, POINTS WITH THE TITLE, REVERSED:
+\DeclareInstance { exsheets-heading } { runin-wp-rev } { default }
+ {
+ toc-reversed = true ,
+ runin = true ,
+ points-pre-code = ( ,
+ points-post-code = ) \c_space_tl ,
+ join =
+ {
+ main[r,vc] number[r,vc] (0pt,0pt) ;
+ main[r,vc] title[l,vc] (.333em,0pt) ;
+ main[r,vc] points[l,vc] (.333em,0pt)
+ }
+ }
+
+% RUNIN WITH NO TITLE:
+\DeclareInstance { exsheets-heading } { runin-nr } { default }
+ {
+ runin = true ,
+ number-post-code = \c_space_tl ,
+ attach =
+ { main[l,vc] points[l,vc] (\linewidth + \marginparsep,0pt) } ,
+ join = { main[r,vc] number[l,vc] (0pt,0pt) }
+ }
+
+% RUNIN WITH NO TITLE, POINTS WITH THE TITLE:
+\DeclareInstance { exsheets-heading } { runin-nr-wp } { default }
+ {
+ runin = true ,
+ points-pre-code = ( ,
+ points-post-code = ) \c_space_tl ,
+ join =
+ {
+ main[r,vc] number[l,vc] (0pt,0pt) ;
+ main[r,vc] points[l,vc] (.333em,0pt)
+ }
+ }
+
+% RUNIN WITH NO TITLE, FIXED WIDTH OF NUMBER
+\DeclareInstance { exsheets-heading } { runin-fixed-nr } { default }
+ {
+ runin = true ,
+ number-pre-code = \hbox to 2em \bgroup ,
+ number-post-code = \hfil\egroup ,
+ attach =
+ { main[l,vc]points[l,vc](\linewidth+\marginparsep,0pt) } ,
+ join = { main[r,vc]number[l,vc](0pt,0pt) }
+ }
+
+% INLINE
+\DeclareInstance { exsheets-heading } { inline } { default }
+ {
+ inline = true ,
+ number-pre-code = \c_space_tl ,
+ number-post-code = \c_space_tl ,
+ join =
+ {
+ main[r,vc] title[r,vc] (0pt,0pt) ;
+ main[r,vc] number[l,vc] (0pt,0pt)
+ }
+ }
+
+% INLINE, POINTS WITH THE TITLE
+\DeclareInstance { exsheets-heading } { inline-wp } { default }
+ {
+ inline = true ,
+ number-pre-code = \c_space_tl ,
+ number-post-code = \c_space_tl ,
+ points-pre-code = ( ,
+ points-post-code = ) \c_space_tl ,
+ join =
+ {
+ main[r,vc] title[r,vc] (0pt,0pt) ;
+ main[r,vc] number[l,vc] (0pt,0pt) ;
+ main[r,vc] points[l,vc] (0pt,0pt)
+ }
+ }
+
+% INLINE WITH NO TITLE:
+\DeclareInstance { exsheets-heading } { inline-nr } { default }
+ {
+ inline = true ,
+ number-post-code = \c_space_tl ,
+ join = { main[r,vc] number[l,vc] (0pt,0pt) }
+ }
+
+% CENTERED:
+\DeclareInstance { exsheets-heading } { centered } { default }
+ {
+ join = { title[r,B] number[l,B] (.333em,0pt) } ,
+ attach =
+ {
+ main[hc,vc] title[hc,vc] (0pt,0pt) ;
+ main[r,vc] points[l,vc] (\marginparsep,0pt)
+ }
+ }
+
+% CENTERED, POINTS WITH THE TITLE:
+\DeclareInstance { exsheets-heading } { centered-wp } { default }
+ {
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join =
+ {
+ title[r,B] number[l,B] (.333em,0pt) ;
+ title[r,B] points[l,B] (.333em,0pt)
+ } ,
+ attach = { main[hc,vc] title[hc,vc] (0pt,0pt) }
+ }
+
+% MARGIN:
+\DeclareInstance { exsheets-heading } { margin } { default }
+ {
+ runin = true ,
+ number-post-code = \c_space_tl ,
+ points-pre-code = ( ,
+ points-post-code = ) \c_space_tl ,
+ join = { title[r,b] number[l,b] (.333em,0pt) } ,
+ attach =
+ {
+ main[l,vc] title[r,vc] (0pt,0pt) ;
+ main[l,b] points[r,t] (0pt,0pt)
+ }
+ }
+
+% MARGIN WITH NO TITLE
+\DeclareInstance { exsheets-heading } { margin-nr } { default }
+ {
+ runin = true ,
+ attach =
+ {
+ main[l,vc]number[r,vc](-.333em,0pt) ;
+ main[r,vc]points[l,vc](\linewidth+\marginparsep,0pt)
+ }
+ }
+
+% RIGHT-ALIGNED:
+\DeclareInstance { exsheets-heading } { raggedleft } { default }
+ {
+ join = { title[r,B] number[l,B] (.333em,0pt) } ,
+ attach =
+ {
+ main[r,vc] title[r,vc] (0pt,0pt) ;
+ main[r,vc] points[l,vc] (\marginparsep,0pt)
+ }
+ }
+
+% MIMICKING KOMA-SECTION:
+\DeclareInstance { exsheets-heading } { koma-section } { default }
+ {
+ vscale = 2 ,
+ title-format = \Large\bfseries\sffamily ,
+ join = { title[r,B] number[l,B] (.333em,0pt) } ,
+ attach =
+ {
+ main[l,vc] title[l,vc] (0pt,0pt) ;
+ main[r,vc] points[l,vc] (\marginparsep,0pt)
+ }
+ }
+
+% FANCY:
+\DeclareInstance { exsheets-heading } { fancy } { default }
+ {
+ toc-reversed = true ,
+ indent-first = true ,
+ vscale = 2 ,
+ pre-code = \rule{\linewidth}{1pt} ,
+ post-code = \rule{\linewidth}{1pt} ,
+ title-format = \large\scshape\color{rgb:red,0.65;green,0.04;blue,0.07} ,
+ number-format = \large\bfseries\color{rgb:red,0.02;green,0.04;blue,0.48} ,
+ points-format = \itshape ,
+ join = { number[r,B] title[l,B] (.333em,0pt) } ,
+ attach =
+ {
+ main[hc,vc] number[hc,vc] (0pt,0pt) ;
+ main[l,vc] points[r,vc] (-\marginparsep,0pt)
+ }
+ }
+
+% FANCY, POINTS WITH THE TITLE:
+\DeclareInstance { exsheets-heading } { fancy-wp } { default }
+ {
+ toc-reversed = true ,
+ indent-first = true ,
+ vscale = 2 ,
+ pre-code = \rule{\linewidth}{1pt} ,
+ post-code = \rule{\linewidth}{1pt} ,
+ title-format = \large\scshape\color{rgb:red,0.65;green,0.04;blue,0.07} ,
+ number-format = \large\bfseries\color{rgb:red,0.02;green,0.04;blue,0.48} ,
+ points-format = \itshape ,
+ points-pre-code = ( ,
+ points-post-code = ) ,
+ join =
+ {
+ number[r,B] title[l,B] (.333em,0pt) ;
+ number[r,B] points[l,B] (.333em,0pt)
+ } ,
+ attach = { main[hc,vc] number[hc,vc] (0pt,0pt) }
+ }
+
+\tex_endinput:D
diff --git a/macros/latex/contrib/exsheets/exsheets_headings.def b/macros/latex/contrib/exsheets/exsheets_headings.def
new file mode 100644
index 0000000000..e7100ce4d6
--- /dev/null
+++ b/macros/latex/contrib/exsheets/exsheets_headings.def
@@ -0,0 +1,474 @@
+% --------------------------------------------------------------------------
+% 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-2017 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)
+ }
+ }
+
+\tex_endinput:D
diff --git a/macros/latex/contrib/exsheets/grading-table.pdf b/macros/latex/contrib/exsheets/grading-table.pdf
new file mode 100644
index 0000000000..a845bcabb0
--- /dev/null
+++ b/macros/latex/contrib/exsheets/grading-table.pdf
Binary files differ
diff --git a/macros/latex/contrib/exsheets/grading-table.tex b/macros/latex/contrib/exsheets/grading-table.tex
new file mode 100644
index 0000000000..ef109bd164
--- /dev/null
+++ b/macros/latex/contrib/exsheets/grading-table.tex
@@ -0,0 +1,48 @@
+% ----------------------------------------------------------------------------
+% the EXSHEETS package
+%
+% Yet another package for the creation of exercise sheets
+%
+% ----------------------------------------------------------------------------
+% Clemens Niederberger
+% Web: http://www.mychemistry.eu/forums/forum/exsheets
+% E-Mail: contact@mychemistry.eu
+% ----------------------------------------------------------------------------
+% Copyright 2011-2017 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.
+% ----------------------------------------------------------------------------
+\documentclass{scrartcl}
+\usepackage{exsheets}
+
+\begin{document}
+
+\begin{question}{3}
+\end{question}
+\begin{question}{5}
+\end{question}
+\begin{question}{10}
+\end{question}
+\begin{question}{8}
+\end{question}
+
+\begin{tabular}{|l|*{\numberofquestions}{c|}c|}\hline
+ Question & \ForEachQuestion{\QuestionNumber{#1}\iflastquestion{}{&}} & Total \\ \hline
+ Points & \ForEachQuestion{\GetQuestionProperty{points}{#1}\iflastquestion{}{&}} & \pointssum* \\ \hline
+ Reached & \ForEachQuestion{\iflastquestion{}{&}} & \\ \hline
+\end{tabular}
+
+\end{document}