diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/sdaps/sdapslayout.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/sdaps/sdapslayout.sty | 669 |
1 files changed, 669 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/sdaps/sdapslayout.sty b/Master/texmf-dist/tex/latex/sdaps/sdapslayout.sty new file mode 100644 index 00000000000..54c755b0481 --- /dev/null +++ b/Master/texmf-dist/tex/latex/sdaps/sdapslayout.sty @@ -0,0 +1,669 @@ +%% +%% This is file `sdapslayout.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% sdapslayout.dtx (with options: `package') +%% +%% This is a generated file. +%% +%% Copyright (C) 2015 by Benjamin Berg <benjamin@sipsolutions.net> +%% +%% 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. +%% +\NeedsTeXFormat{LaTeX2e}[1999/12/01] +\ProvidesPackage{sdapslayout} + [2015/04/10 v0.1 Initial version of SDAPS layout package] +\RequirePackage{expl3}[2011/08/23] +\ExplSyntaxOn +\ExplSyntaxOff + +\RequirePackage{sdapsbase} +\RequirePackage{sdapsarray} +\RequirePackage{xparse} + +\ExplSyntaxOn + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\tl_new:N \l_sdaps_choicearray_qobject_type_tl +\bool_new:N \l_sdaps_choicearray_horizontal_bool +\tl_new:N \l_sdaps_choicearray_var_tl +\tl_new:N \l_sdaps_choicearray_text_tl +\tl_new:N \l_sdaps_choicearray_layouter_tl +\tl_new:N \l_sdaps_choicearray_align_tl +\tl_new:N \l_sdaps_choicearray_extra_tl +\tl_new:N \l_sdaps_choicearray_type_tl +\tl_new:N \l_sdaps_choice_var_tl +\tl_new:N \l_sdaps_choice_val_tl +\tl_new:N \l_sdaps_choice_text_tl +\tl_new:N \l_sdaps_question_var_tl +\tl_new:N \l_sdaps_question_text_tl +\clist_new:N \l_sdaps_question_range_clist +\int_new:N \g_sdaps_choices_box_int +\seq_new:N \g_sdaps_choices_filter_seq +\seq_new:N \g_sdaps_choices_cell_seq +\seq_new:N \g_sdaps_choices_text_seq + +\keys_define:nn { sdaps / choicearray } +{ + horizontal .bool_set:N = \l_sdaps_choicearray_horizontal_bool, + horizontal .default:n = true, + horizontal .initial:n = true, + vertical .bool_set_inverse:N = \l_sdaps_choicearray_horizontal_bool, + vertical .default:n = true, + var .tl_set:N = \l_sdaps_choicearray_var_tl, + text .tl_set:N = \l_sdaps_choicearray_text_tl, + layouter .tl_set:N = \l_sdaps_choicearray_layouter_tl, + layouter .initial:n = default, + align .tl_set:N = \l_sdaps_choicearray_align_tl, + align .initial:n = { }, + + type .choices:nn = { multichoice, singlechoice } { \tl_set:Nx \l_sdaps_choicearray_type_tl { \l_keys_choice_tl } }, + type .initial:n = { multichoice }, + + singlechoice .meta:n = { type=singlechoice }, + multichoice .meta:n = { type=multichoice }, + + noalign .meta:n = { align= }, +} + +\keys_define:nn { sdaps / choicearray / choice } +{ + var .tl_set:N = \l_sdaps_choice_var_tl, + val .tl_set:N = \l_sdaps_choice_val_tl, + text .tl_set:N = \l_sdaps_choice_text_tl, +} + +\keys_define:nn { sdaps / choicearray / question } +{ + var .tl_set:N = \l_sdaps_question_var_tl, + text .tl_set:N = \l_sdaps_question_text_tl, + + range .clist_set:N = \l_sdaps_question_range_clist, + range .initial:n = {...} +} + +\cs_new_protected_nopar:Npn \_sdaps_choicearray_preprocess:nn #1#2 +{ + \keys_set_known:nnN { sdaps / choicearray } { #1 } \l_sdaps_choicearray_extra_tl + + \tl_if_empty:NTF \l_sdaps_choicearray_text_tl { + \sdaps_qobject_begin:nnn { choicearray } { Head } { #2 } + } { + \sdaps_qobject_begin:nnV { choicearray } { Head } \l_sdaps_choicearray_text_tl + } + + \tl_if_empty:NF \l_sdaps_choicearray_var_tl { + \sdaps_qobject_append_var:V \l_sdaps_choicearray_var_tl + } + + \sdaps_checkbox_set_type:V \l_sdaps_choicearray_type_tl + \tl_if_eq:VnTF \l_sdaps_choicearray_type_tl { multichoice } { + \tl_set:Nn \l_sdaps_choicearray_qobject_type_tl { Choice } + } { + \tl_set:Nn \l_sdaps_choicearray_qobject_type_tl { Option } + } +} +\cs_generate_variant:Nn \_sdaps_choicearray_preprocess:nn { Vn } + +\cs_new_protected_nopar:Npn \_sdaps_choicearray_postprocess: +{ + \sdaps_qobject_end:n { choicearray } +} + +\cs_new_protected_nopar:Npn \_sdaps_choicearray_process_choice_insert_tail_after:w { + \bgroup + \group_insert_after:N \_sdaps_choicearray_process_choice_tail: + \sdaps_array_nested_alignenv: + \tex_let:D\next= +} + +\cs_new_protected_nopar:Nn \_sdaps_choicearray_process_choice_tail: { + \ignorespaces +} + +\cs_new_nopar:Nn \_sdaps_choicearray_grab_choice:n { + \seq_gput_right:Nn \g_sdaps_choices_text_seq { #1 } + \group_begin: + \sdaps_array_nested_alignenv: + #1 + \group_end: + \_sdaps_choicearray_process_choice_tail: +} + +\cs_new_nopar:Npn \_sdaps_choicearray_process_choice:nw #1 +{ + % This modifies grouping so it has to be at the start + \sdaps_array_alignment: + \leavevmode + + \tl_clear:N \l_sdaps_choice_var_tl + \tl_clear:N \l_sdaps_choice_val_tl + \tl_clear:N \l_sdaps_choice_text_tl + + \keys_set:nn { sdaps / choicearray / choice } { #1 } + + \int_gincr:N \g_sdaps_choices_box_int + + \tl_if_empty:NT \l_sdaps_choice_var_tl { + % Prefix with _ to force prefixing with generated variable + \tl_set:Nx \l_sdaps_choice_var_tl { \int_use:N \g_sdaps_choices_box_int } + } + \tl_if_empty:NT \l_sdaps_choice_val_tl { + \tl_set:Nx \l_sdaps_choice_val_tl { \int_use:N \g_sdaps_choices_box_int } + } + + \tl_if_eq:VnTF \l_sdaps_choicearray_type_tl { multichoice } { + \seq_gput_right:NV \g_sdaps_choices_filter_seq \l_sdaps_choice_var_tl + } { + \seq_gput_right:NV \g_sdaps_choices_filter_seq \l_sdaps_choice_val_tl + } + + \seq_gput_right:Nx \g_sdaps_choices_cell_seq { \exp_not:n { \sdaps_checkbox:nn } { _ \l_sdaps_choice_var_tl } { \l_sdaps_choice_val_tl } } + + \tl_if_empty:NTF \l_sdaps_choice_text_tl { + % We need to leave a command in the stream that grabs the next parameter + % and outputs it immediately + \cs_set_eq:NN \l_tmpa_token \_sdaps_choicearray_grab_choice:n + } { + % Nothing else to do + \seq_gput_right:NV \g_sdaps_choices_text_seq { \l_sdaps_choice_text_tl } + \cs_set_eq:NN \l_tmpa_token \_sdaps_choicearray_process_choice_insert_tail_after:w + } + \l_tmpa_token +} +\cs_generate_variant:Nn \_sdaps_choicearray_process_choice:nw { Vw } + +\cs_new_protected_nopar:Nn \_sdaps_choicearray_process_question_grab:n { + \tl_set:Nn \l_sdaps_question_text_tl { #1 } + + \_sdaps_choicearray_process_question_head: + + \group_begin: + \sdaps_array_nested_alignenv: + #1 + \group_end: + + \_sdaps_choicearray_process_question_tail: +} + +\cs_new_protected_nopar:Npn \_sdaps_choicearray_process_question_inline:w { + \_sdaps_choicearray_process_question_head: + \bgroup + \group_insert_after:N \_sdaps_choicearray_process_question_tail: + \sdaps_array_nested_alignenv: + \tex_let:D\next= +} + +\cs_new_protected_nopar:Nn \_sdaps_choicearray_process_question_head: { + \sdaps_qobject_begin:nnV { choicearray_question } \l_sdaps_choicearray_qobject_type_tl \l_sdaps_question_text_tl + + \tl_if_empty:NF \l_sdaps_question_var_tl { + \sdaps_qobject_append_var:V \l_sdaps_question_var_tl + } +} + +\cs_new_protected_nopar:Nn \_sdaps_choicearray_process_question_tail: { + \seq_gclear:N \g_tmpa_seq + % l_tmpa_bool is whether we are in a run (i.e. ...) + \bool_set_false:N \l_tmpa_bool + + \clist_gset_eq:NN \g_tmpa_clist \l_sdaps_question_range_clist + \clist_gpop:NN \g_tmpa_clist \l_tmpa_tl + + \seq_map_inline:Nn \g_sdaps_choices_filter_seq { + \tl_if_eq:VnT \l_tmpa_tl { ... } { + \bool_set_true:N \l_tmpa_bool + \clist_gpop:NN \g_tmpa_clist \l_tmpa_tl + } + + \tl_if_eq:VnTF \l_tmpa_tl { ##1 } { + \seq_gput_right:Nn \g_tmpa_seq { \c_true_bool } + \bool_set_false:N \l_tmpa_bool + \clist_gpop:NN \g_tmpa_clist \l_tmpa_tl + } { + % Append if we are handling a run of items and the current item is not + % the last one. + \bool_if:NTF \l_tmpa_bool { + \seq_gput_right:Nn \g_tmpa_seq { \c_true_bool } + } { + % Otherwise, ignore this item + \seq_gput_right:Nn \g_tmpa_seq { \c_false_bool } + } + } + } + + \seq_gset_eq:NN \g_tmpb_seq \g_tmpa_seq + + \seq_map_inline:Nn \g_sdaps_choices_text_seq { + \seq_gpop_left:NN \g_tmpa_seq \l_tmpa_tl + \tl_if_eq:VnT \l_tmpa_tl { \c_true_bool } { + \sdaps_answer:f { ##1 } + } + } + + \seq_map_inline:Nn \g_sdaps_choices_cell_seq { + \sdaps_array_alignment: + + \seq_gpop_left:NN \g_tmpb_seq \l_tmpa_tl + \tl_if_eq:VnT \l_tmpa_tl { \c_true_bool } { + ##1 + } + } + + \sdaps_qobject_end:n { choicearray_question } + \ignorespaces +} + +\cs_new_nopar:Npn \_sdaps_choicearray_process_question:nw #1 +{ + \sdaps_array_newline: + \leavevmode + + \keys_set:nn { sdaps / choicearray / question } { #1 } + + \tl_if_empty:NTF \l_sdaps_question_text_tl { + % We need to leave a command in the stream that grabs the next parameter, + % outputs it again, and finishes the question. + \cs_set_eq:NN \l_tmpa_token \_sdaps_choicearray_process_question_grab:n + } { + % Insert the question around the next argument + \cs_set_eq:NN \l_tmpa_token \_sdaps_choicearray_process_question_inline:w + } + \l_tmpa_token +} +\cs_generate_variant:Nn \_sdaps_choicearray_process_question:nw { Vw } + + +\tl_new:N \l_sdaps_rangearray_var_tl +\tl_new:N \l_sdaps_rangearray_text_tl +\tl_new:N \l_sdaps_rangearray_align_tl +\tl_new:N \l_sdaps_rangearray_extra_tl +\int_new:N \l_sdaps_rangearray_rangecount_int +\bool_new:N \l_sdaps_rangearray_other_bool +\tl_new:N \g_sdaps_question_var_tl +\tl_new:N \g_sdaps_question_text_tl +\tl_new:N \g_sdaps_question_lowertext_tl +\tl_new:N \g_sdaps_question_uppertext_tl +\tl_new:N \g_sdaps_question_othertext_tl + +\keys_define:nn { sdaps / rangearray } +{ + var .tl_set:N = \l_sdaps_rangearray_var_tl, + text .tl_set:N = \l_sdaps_rangearray_text_tl, + count .int_set:N = \l_sdaps_rangearray_rangecount_int, + count .initial:n = 5, + align .tl_set:N = \l_sdaps_rangearray_align_tl, + align .initial:n = { }, + other .bool_set:N = \l_sdaps_rangearray_other_bool, + other .default:n = true, + other .initial:n = false, +} + +\keys_define:nn { sdaps / rangearray / question } +{ + var .tl_gset:N = \g_sdaps_question_var_tl, + text .tl_gset:N = \g_sdaps_question_text_tl, + upper .tl_gset:N = \g_sdaps_question_uppertext_tl, + lower .tl_gset:N = \g_sdaps_question_lowertext_tl, + other .tl_gset:N = \g_sdaps_question_othertext_tl, +} + +\cs_new_protected_nopar:Npn \_sdaps_rangearray_preprocess:nn #1#2 +{ + \keys_set_known:nnN { sdaps / rangearray } { #1 } \l_sdaps_rangearray_extra_tl + + \tl_if_empty:NTF \l_sdaps_rangearray_text_tl { + \sdaps_qobject_begin:nnn { rangearray } { Head } { #2 } + } { + \sdaps_qobject_begin:nnV { rangearray } { Head } \l_sdaps_rangearray_text_tl + } + + \sdaps_checkbox_set_type:n { singlechoice } + + \tl_if_empty:NF \l_sdaps_rangearray_var_tl { + \sdaps_qobject_append_var:V \l_sdaps_rangearray_var_tl + } +} +\cs_generate_variant:Nn \_sdaps_rangearray_preprocess:nn { Vn } + +\cs_new_protected_nopar:Npn \_sdaps_rangearray_postprocess: +{ + \sdaps_qobject_end:n { rangearray } +} + + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_before_question: { + \sdaps_array_newline: + % Note: This needs to be after sdaps_array_newline as the command may be + % discarded otherwise (i.e. it does not make it into the output stream) + % We also need to leave vmode here + \leavevmode + \sdaps_qobject_begin:nnV { rangearray_question } { Range } \g_sdaps_question_text_tl + + \tl_if_empty:NF \g_sdaps_question_var_tl { + \sdaps_qobject_append_var:V \g_sdaps_question_var_tl + } + + \ignorespaces +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_before_lower: { + % right align + \sdaps_array_alignment: + \leavevmode + \sdaps_range:nnV { lower } { 0 } \g_sdaps_question_lowertext_tl + \sdaps_if_rtl:F { + \hfill + } + \ignorespaces +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_before_upper: { + \sdaps_array_alignment: + \leavevmode + \sdaps_range:nnV { upper } { \l_sdaps_rangearray_rangecount_int - 1 } \g_sdaps_question_uppertext_tl + \sdaps_if_rtl:T { + \hfill + } + \ignorespaces +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_before_other: { + % Insert an extra empty column for further spacing + \sdaps_array_alignment: + \sdaps_array_alignment: + \leavevmode + \sdaps_answer:V \g_sdaps_question_othertext_tl + \sdaps_if_rtl:TF { + \hfill + } { + \sdaps_checkbox:nn { } { 0 } {} ~ {} + } + \ignorespaces +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_after_question: { + % Insert an extra empty column for further spacing + \sdaps_array_alignment: + \tl_if_empty:NTF \g_sdaps_question_lowertext_tl { + \cs_set_eq:NN \l_tmpa_token \_sdaps_rangearray_process_question_grab_lower:n + } { + \cs_set_eq:NN \l_tmpa_token \_sdaps_rangearray_process_question_inline_lower:w + } + \l_tmpa_token +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_after_lower: { + % Insert the option checkbox column + \sdaps_if_rtl:T { + \hfill\kern 0pt + } + \sdaps_array_alignment: + \leavevmode + % Seems like right to left writing mode is not started without a paragraph + \sdaps_if_rtl:T { \beginR } + % Assume we have at least one checkbox + \sdaps_checkbox:nn { } { 1 } + \int_step_inline:nnnn { 2 } { 1 } { \l_sdaps_rangearray_rangecount_int } { + \hspace{1em} \sdaps_checkbox:nn { } { ##1 } + } + \sdaps_if_rtl:T { \endR } + + \tl_if_empty:NTF \g_sdaps_question_uppertext_tl { + \cs_set_eq:NN \l_tmpa_token \_sdaps_rangearray_process_question_grab_upper:n + } { + \cs_set_eq:NN \l_tmpa_token \_sdaps_rangearray_process_question_inline_upper:w + } + \l_tmpa_token +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_after_upper: { + \sdaps_if_rtl:F { + \hfill\kern 0pt + } + + \bool_if:NTF \l_sdaps_rangearray_other_bool { + \tl_if_empty:NTF \g_sdaps_question_othertext_tl { + \cs_set_eq:NN \l_tmpa_token \_sdaps_rangearray_process_question_grab_other:n + } { + \cs_set_eq:NN \l_tmpa_token \_sdaps_rangearray_process_question_inline_other:w + } + } { + \cs_set_eq:NN \l_tmpa_token \_sdaps_rangearray_process_question_finish: + } + \l_tmpa_token +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_after_other: { + \sdaps_if_rtl:TF { + {} ~ \sdaps_checkbox:nn { } { 0 } {} + } { + \hfill\kern 0pt + } + \ignorespaces +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_finish: { + \sdaps_qobject_end:n { rangearray_question } + \ignorespaces +} + + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_grab_question:n { + \tl_gset:Nn \g_sdaps_question_text_tl { #1 } + + \_sdaps_rangearray_process_question_before_question: + \group_begin: + \sdaps_array_nested_alignenv: + #1 + \group_end: + \_sdaps_rangearray_process_question_after_question: +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_grab_lower:n { + \tl_gset:Nn \g_sdaps_question_lowertext_tl { #1 } + + \_sdaps_rangearray_process_question_before_lower: + \group_begin: + \sdaps_array_nested_alignenv: + #1 + \group_end: + \_sdaps_rangearray_process_question_after_lower: +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_grab_upper:n { + \tl_gset:Nn \g_sdaps_question_uppertext_tl { #1 } + + \_sdaps_rangearray_process_question_before_upper: + \group_begin: + \sdaps_array_nested_alignenv: + #1 + \group_end: + \_sdaps_rangearray_process_question_after_upper: +} + +\cs_new_protected_nopar:Nn \_sdaps_rangearray_process_question_grab_other:n { + \tl_gset:Nn \g_sdaps_question_othertext_tl { #1 } + + % If the text is empty, assume that this particular question does not have + % an alternative choice. Note that this column might not exist and this + % macro will not even be called in that case. + % If we skip the optional "other" option then we still need to insert the + % alignment to create the column. + \tl_if_empty:NTF \g_sdaps_question_othertext_tl { + \sdaps_array_alignment: + \leavevmode + \ignorespaces + } { + \_sdaps_rangearray_process_question_before_other: + \group_begin: + \sdaps_array_nested_alignenv: + #1 + \group_end: + \_sdaps_rangearray_process_question_after_other: + } + \_sdaps_rangearray_process_question_finish: +} + +\cs_new_protected_nopar:Npn \_sdaps_rangearray_process_question_inline_question:w { + \_sdaps_rangearray_process_question_before_question: + \bgroup + \group_insert_after:N \_sdaps_rangearray_process_question_after_question: + \sdaps_array_nested_alignenv: + \tex_let:D\next= +} + +\cs_new_protected_nopar:Npn \_sdaps_rangearray_process_question_inline_lower:w { + \_sdaps_rangearray_process_question_before_lower: + \bgroup + \group_insert_after:N \_sdaps_rangearray_process_question_after_lower: + \tex_let:D\next= +} + +\cs_new_protected_nopar:Npn \_sdaps_rangearray_process_question_inline_upper:w { + \_sdaps_rangearray_process_question_before_upper: + \bgroup + \group_insert_after:N \_sdaps_rangearray_process_question_after_upper: + \tex_let:D\next= +} + +\cs_new_protected_nopar:Npn \_sdaps_rangearray_process_question_inline_other:w { + \_sdaps_rangearray_process_question_before_other: + % If we reach this macro then a text has been set for the other item. This + % means we never need to ignore the "other" parameter at this point. + \bgroup + \group_insert_after:N \_sdaps_rangearray_process_question_after_other: + \group_insert_after:N \_sdaps_rangearray_process_question_finish: + \tex_let:D\next= +} + +\cs_new_nopar:Npn \_sdaps_rangearray_process_question:nw #1 +{ + % Is there a better way other than clearing these before parsing? + \tl_gclear:N \g_sdaps_question_var_tl + \tl_gclear:N \g_sdaps_question_text_tl + \tl_gclear:N \g_sdaps_question_uppertext_tl + \tl_gclear:N \g_sdaps_question_lowertext_tl + \tl_gclear:N \g_sdaps_question_othertext_tl + + \keys_set:nn { sdaps / rangearray / question } { #1 } + + \tl_if_empty:NTF \g_sdaps_question_text_tl { + % We need to leave a command in the stream that grabs the next parameter, + % outputs it again, and finishes the question. + \cs_set_eq:NN \l_tmpa_token \_sdaps_rangearray_process_question_grab_question:n + } { + % We need to generate the question after the next group stops + \cs_set_eq:NN \l_tmpa_token \_sdaps_rangearray_process_question_inline_question:w + } + \l_tmpa_token +} +\cs_generate_variant:Nn \_sdaps_rangearray_process_question:nw { Vw } + + +\newenvironment { choicearray } [ 2 ] [] +{ + \group_begin: + + \sdaps_context_get:nN { choicearray } \l_tmpa_tl + \tl_if_eq:NNT \l_tmpa_tl \q_no_value { + \tl_set:Nn \l_tmpa_tl {} + } + + \tl_if_empty:nF { #1 } { + \tl_if_empty:NTF \l_tmpa_tl { + \tl_set:Nn \l_tmpa_tl { #1 } + } { + \tl_set:Nf \l_tmpa_tl { \l_tmpa_tl, #1 } + } + } + + \_sdaps_choicearray_preprocess:Vn \l_tmpa_tl { #2 } + % Clear the variables + \seq_gclear:N \g_sdaps_choices_filter_seq + \seq_gclear:N \g_sdaps_choices_cell_seq + \seq_gclear:N \g_sdaps_choices_text_seq + + \int_gzero:N \g_sdaps_choices_box_int + + % Define new commands + \newcommand \choice [ 1 ] [] { + \_sdaps_choicearray_process_choice:nw { ##1 } + } + \newcommand \question [ 1 ] [] { + \_sdaps_choicearray_process_question:nw { ##1 } + } + + \group_begin: + + \tl_set:Nx \l_tmpb_tl {keepenv,layouter=\tl_use:N\l_sdaps_choicearray_layouter_tl,align=\l_sdaps_choicearray_align_tl\bool_if:NF\l_sdaps_choicearray_horizontal_bool{,flip},\l_sdaps_choicearray_extra_tl} + \expandafter\sdapsarray\expandafter[\l_tmpb_tl] +} +{ + \endsdapsarray + \group_end: + % Process keys + \_sdaps_choicearray_postprocess: + + \group_end: +} + +\newenvironment { optionarray } [ 2 ] [] +{ + \choicearray[singlechoice,#1] { #2 } +} +{ + \endchoicearray +} + +\newenvironment { rangearray } [ 2 ] [] +{ + \group_begin: + + \sdaps_context_get:nN { rangearray } \l_tmpa_tl + \tl_if_eq:NNT \l_tmpa_tl \q_no_value { + \tl_set:Nn \l_tmpa_tl {} + } + + \tl_if_empty:nF { #1 } { + \tl_if_empty:NTF \l_tmpa_tl { + \tl_set:Nn \l_tmpa_tl { #1 } + } { + \tl_set:Nf \l_tmpa_tl { \l_tmpa_tl, #1 } + } + } + + \_sdaps_rangearray_preprocess:Vn \l_tmpa_tl { #2 } + + \newcommand \range [ 1 ] [] { + \_sdaps_rangearray_process_question:nw { ##1 } + } + + \group_begin: + + \tl_set:Nx \l_tmpb_tl {keepenv,align=\l_sdaps_rangearray_align_tl,\l_sdaps_rangearray_extra_tl} + \expandafter\sdapsarray\expandafter[\l_tmpb_tl] +} +{ + \endsdapsarray + \group_end: + % Process keys + \_sdaps_rangearray_postprocess: + + \group_end: +} + +\ExplSyntaxOff + +\endinput +%% +%% End of file `sdapslayout.sty'. |