% -------------------------------------------------------------------------- % 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-2012 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 package consists of the files % - exsheets.sty, exsheets_headings.def, exsheets_headings.cfg, % exsheets_tasks.def, exsheets_tasks.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. % -------------------------------------------------------------------------- % TASKS: LIST-LIKE ENVIRONMENT \ProvidesFile{exsheets_tasks.def} [\exsheets@date\space v\exsheets@version\space ExSheets tasks object] \RequirePackage { epic } % variables: \seq_new:N \l__exsheets_tasks_seq \int_new:N \l__exsheets_tasks_depth_int \int_new:N \g__exsheets_tasks_int \int_new:N \l__exsheets_tasks_total_items_int \int_new:N \l__exsheets_tasks_columns_int \int_new:N \l__exsheets_tasks_rows_int \bool_new:N \l__exsheets_tasks_enumerate_bool \bool_new:N \l__exsheets_tasks_resume_bool \tl_new:N \l__exsheets_tasks_instance_tl \tl_new:N \l__exsheets_tasks_label_tl \tl_new:N \l__exsheets_tasks_label_pattern_tl \tl_new:N \l__exsheets_tasks_custom_label_format_tl \dim_new:N \l__exsheets_tasks_item_indent_dim \dim_new:N \l__exsheets_tasks_item_width_dim \dim_new:N \l__exsheets_tasks_label_width_dim \dim_new:N \l__exsheets_tasks_default_label_width_dim \skip_new:N \l__exsheets_tasks_after_item_skip \skip_new:N \l__exsheets_tasks_before_list_skip \skip_new:N \l__exsheets_tasks_after_list_skip \NewCounterPattern* [ exsheets ] { task } { tsk } \ReadCounterFrom [ exsheets ] { task } \g__exsheets_tasks_int % scratch coffins: \cs_if_exist:NF \l__exsheets_tmpa_coffin { \coffin_new:N \l__exsheets_tmpa_coffin } \cs_if_exist:NF \l__exsheets_tmpb_coffin { \coffin_new:N \l__exsheets_tmpb_coffin } \cs_if_exist:NF \l__exsheets_tmpc_coffin { \coffin_new:N \l__exsheets_tmpc_coffin } % collect the tasks: \cs_new:Npn \__exsheets_collect_tasks:nw #1#2 \end #3 { \tl_put_right:Nn \l__exsheets_tasks_body_tl { #1 } \end { #3 } \tl_if_eq:nnF { #1 } { #3 } { \__exsheets_collect_tasks:nw { #1 } } } % #1: instance % #2: number of columns % #3: item separator % #4: environment body \cs_new:Npn \__exsheets_tasks:nnnn #1#2#3#4 { \seq_set_split:Nnn \l__exsheets_tasks_seq { #3 } { #4 } % remove the first (empty) item: \seq_pop_left:NN \l__exsheets_tasks_seq \l__exsheets_tmpa_tl \tl_if_blank:VF \l__exsheets_tmpa_tl { \tl_show:N \l__exsheets_tmpa_tl \@noitemerr } \int_set:Nn \l__exsheets_tasks_total_items_int { \seq_length:N \l__exsheets_tasks_seq } \UseInstance { exsheets-tasks } { #1 } { \l__exsheets_tasks_total_items_int } { #2 } { \l__exsheets_tasks_custom_label_format_tl } % just to be sure: \seq_clear:N \l__exsheets_tasks_seq } \cs_generate_variant:Nn \__exsheets_tasks:nnnn { VnnV } \cs_new:Npn \__exsheets_task:nnw #1#2[#3,#4][#5,#6](#7,#8) { \dim_set:Nn \l__exsheets_tasks_item_width_dim { \linewidth / \l__exsheets_tasks_columns_int - \l__exsheets_tasks_depth_int \l__exsheets_tasks_item_indent_dim } \int_incr:N \l__exsheets_tmpa_int \__exsheets_tasks_set_rows_num:NN \l__exsheets_tasks_total_items_int \l__exsheets_tasks_columns_int \int_compare:nT { \l__exsheets_tmpa_int > \l__exsheets_tasks_columns_int } { \int_set:Nn \l__exsheets_tmpa_int { 1 } } % the item: \hcoffin_set:Nn \l__exsheets_tmpa_coffin { \vcoffin_set:Nnn \l__exsheets_tmpc_coffin { \l__exsheets_tasks_item_width_dim } { \__exsheets_tasks_setup: #2 } \coffin_typeset:Nnnnn \l__exsheets_tmpc_coffin { l } { T } { 0pt } { 0pt } } % the label: \hcoffin_set:Nn \l__exsheets_tmpb_coffin { \strut #1 } \coffin_attach:NnnNnnnn \l__exsheets_tmpa_coffin { l } { T } \l__exsheets_tmpb_coffin { l } { T } { -\l__exsheets_tasks_label_width_dim } { 0pt } % typeset label & item: % need this when a new row starts: \int_compare:nT { \l__exsheets_tmpa_int = 1 } { \skip_vertical:N \c_zero_skip } \skip_horizontal:N \l__exsheets_tasks_item_indent_dim \coffin_typeset:Nnnnn \l__exsheets_tmpa_coffin { l } { T } { 0pt } { 0pt } % need this before a new row starts: \int_compare:nT { \l__exsheets_tmpa_int = \l__exsheets_tasks_columns_int } { \skip_vertical:N \l__exsheets_tasks_after_item_skip } \coffin_clear:N \l__exsheets_tmpa_coffin \coffin_clear:N \l__exsheets_tmpb_coffin \coffin_clear:N \l__exsheets_tmpc_coffin } \cs_generate_variant:Nn \__exsheets_task:nnw { VV } \cs_new:Npn \__exsheets_tasks_setup: { \dim_set:Nn \parskip { 0pt } \skip_set:Nn \parfillskip { 0pt plus 1fil } \dim_set_eq:NN \parskip \parsep \dim_set_eq:NN \parindent \listparindent \strut } \cs_new:Npn \__exsheets_tasks_set_rows_num:NN #1#2 { \int_set:Nn \l__exsheets_tasks_rows_int { \int_div_truncate:nn { #1 } { #2 } } \int_compare:nNnT { \int_mod:nn { #1 } { #2 } } > { 0 } { \int_incr:N \l__exsheets_tasks_rows_int } } % the `exsheets-tasks' object: % #1: number of items % #2: number of columns % #3: label-format \DeclareObjectType { exsheets-tasks } { 3 } % the `default' template interface: \DeclareTemplateInterface { exsheets-tasks } { default } { 3 } { enumerate : boolean = true , label : tokenlist , indent : length = 2.5em , label-format : tokenlist = tsk[a]) , label-width : length = 3ex , after-item-skip : skip = 1ex plus 1ex minus 1ex } % the `default' template code: \DeclareTemplateCode { exsheets-tasks } { default } { 3 } { enumerate = \l__exsheets_tasks_enumerate_bool , label = \l__exsheets_tasks_label_tl , indent = \l__exsheets_tasks_item_indent_dim , label-format = \l__exsheets_tasks_label_pattern_tl , label-width = \l__exsheets_tasks_default_label_width_dim , after-item-skip = \l__exsheets_tasks_after_item_skip } { \AssignTemplateKeys \dim_compare:nT { \l__exsheets_tasks_label_width_dim = 0pt } { \dim_set_eq:NN \l__exsheets_tasks_label_width_dim \l__exsheets_tasks_default_label_width_dim } % need this for enumerate list: \bool_if:nT { !\l__exsheets_tasks_resume_bool && \l__exsheets_tasks_enumerate_bool } { \int_gzero:N \g__exsheets_tasks_int } \int_set:Nn \l__exsheets_tasks_columns_int { #2 } % set all the items in their own coffins and join with the ground: \int_zero:N \l__exsheets_tmpa_int \tl_if_blank:VF \l__exsheets_tasks_custom_label_format_tl { \tl_set_eq:NN \l__exsheets_tasks_label_pattern_tl \l__exsheets_tasks_custom_label_format_tl } \seq_map_inline:Nn \l__exsheets_tasks_seq { \__exsheets_read_item:w ##1 \q_stop \bool_if:NTF \l__exsheets_tasks_enumerate_bool { \int_gincr:N \g__exsheets_tasks_int \tl_if_blank:VT \l__exsheets_tasks_label_tl { \tl_set:Nn \l__exsheets_tasks_label_tl { \ReadCounterPatternFrom [ exsheets ] \l__exsheets_tasks_label_pattern_tl } } } { \tl_if_blank:VT \l__exsheets_tasks_label_tl { \tl_set_eq:NN \l__exsheets_tasks_label_tl \labelitemi } } \tl_if_blank:VTF \l__exsheets_tasks_tmp_label_tl { \__exsheets_task:VVw \l__exsheets_tasks_label_tl \l__exsheets_tasks_item_tl [ l , b ] [ l , t ] ( 0pt , 0pt ) } { \__exsheets_task:VVw \l__exsheets_tasks_tmp_label_tl \l__exsheets_tasks_item_tl [ l , b ] [ l , t ] ( 0pt , 0pt ) \tl_clear:N \l__exsheets_tasks_tmp_label_tl } } } \tl_new:N \task \tl_new:N \l__exsheets_tasks_item_tl \tl_new:N \l__exsheets_tasks_tmp_label_tl \cs_new:Npn \__exsheets_read_item:w { \peek_meaning:NTF [ { \__exsheets_read_item_aux:w } { \__exsheets_read_item_aux:w[] } } \cs_new:Npn \__exsheets_read_item_aux:w [#1]#2 \q_stop { \tl_if_blank:nF { #1 } { \tl_set:Nn \l__exsheets_tasks_tmp_label_tl { #1 } } \tl_set:Nn \l__exsheets_tasks_item_tl { \ignorespaces #2 } } % choice box: \bool_new:N \l__exsheets_choice_checked_bool \dim_new:N \l__exsheets_choice_width_dim \dim_set:Nn \l__exsheets_choice_width_dim { 1.25ex } \dim_new:N \l__exsheets_choice_linewidth_dim \dim_set:Nn \l__exsheets_choice_linewidth_dim { .3pt } \dim_new:N \l__exsheets_choice_checkwidth_dim \dim_set:Nn \l__exsheets_choice_checkwidth_dim { .5pt } \dim_new:N \l__exsheets_choice_raise_dim \dim_set:Nn \l__exsheets_choice_raise_dim { .1ex } \cs_new:Npn \exsheets_choice: { \leavevmode \bool_set_false:N \l__exsheets_choice_checked_bool \box_move_up:nn { \l__exsheets_choice_raise_dim } { \hbox:n { \__exsheets_choice: } } } \cs_new:Npn \exsheets_choice_checked: { \leavevmode \bool_set_true:N \l__exsheets_choice_checked_bool \box_move_up:nn { \l__exsheets_choice_raise_dim } { \hbox:n { \__exsheets_choice: } } } \cs_new:Npn \__exsheets_choice: {% \dim_set:Nn \unitlength { .1\l__exsheets_choice_width_dim } \begin{picture}(10,0) \linethickness \l__exsheets_choice_linewidth_dim \drawline(0,0)(0,10)(10,10)(10,0)(0,0) \linethickness \l__exsheets_choice_checkwidth_dim \bool_if:NT \l__exsheets_choice_checked_bool { \drawline(2,2)(8,8) \drawline(2,8)(8,2) } \end{picture}% } \providecommand* \choicebox { \exsheets_choice: } \providecommand* \checkedchoicebox { \exsheets_choice_checked: } % base instance: % ALPHABETIZE: a) b) c) \DeclareInstance { exsheets-tasks } { alphabetize } { default } { } \keys_define:nn { exsheets / tasks } { style .tl_set:N = \l__exsheets_tasks_instance_tl , label .tl_set:N = \l__exsheets_tasks_custom_label_format_tl , label-width .dim_set:N = \l__exsheets_tasks_label_width_dim , before-skip .skip_set:N = \l__exsheets_tasks_before_list_skip , after-skip .skip_set:N = \l__exsheets_tasks_after_list_skip , resume .bool_set:N = \l__exsheets_tasks_resume_bool } % the generic environment: \NewEnviron { __exsheets_tasks_env: } [ 3 ] { \keys_set:nn { exsheets / tasks } { #2 } \tl_if_blank:VT \l__exsheets_tasks_instance_tl { \keys_set:nn { exsheets / tasks } { style = alphabetize } } \skip_vertical:N \l__exsheets_tasks_before_list_skip \skip_vertical:N \c_zero_skip \list {} { \dim_set:Nn \leftmargin { 0pt } \dim_set:Nn \rightmargin { 0pt } } \item \scan_stop: \int_incr:N \l__exsheets_tasks_depth_int \__exsheets_tasks:VnnV \l__exsheets_tasks_instance_tl { #3 } { #1 } \BODY \endlist \skip_vertical:N \l__exsheets_tasks_after_list_skip } % the user environment: \NewDocumentCommand \NewTasks { O{}mO{\task}D(){1} } { \NewDocumentEnvironment { #2 } { O{}G{#4} } { \__exsheets_tasks_env: { #3 } { #1,##1 } { ##2 } } { \end__exsheets_tasks_env: } } \NewDocumentCommand \RenewTasks { O{}mO{\task}D(){1} } { \RenewDocumentEnvironment { #2 } { O{}G{#4} } { \__exsheets_tasks_env: { #3 } { #1,##1 } { ##2 } } { \end__exsheets_tasks_env: } } \NewTasks { tasks } \tex_endinput:D % TODO: option für after-item-skip